Source file misc/cgo/gmp/pi.go

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build ignore
     6  
     7  package main
     8  
     9  import (
    10  	big "."
    11  	"fmt"
    12  	"runtime"
    13  )
    14  
    15  var (
    16  	tmp1  = big.NewInt(0)
    17  	tmp2  = big.NewInt(0)
    18  	numer = big.NewInt(1)
    19  	accum = big.NewInt(0)
    20  	denom = big.NewInt(1)
    21  	ten   = big.NewInt(10)
    22  )
    23  
    24  func extractDigit() int64 {
    25  	if big.CmpInt(numer, accum) > 0 {
    26  		return -1
    27  	}
    28  	tmp1.Lsh(numer, 1).Add(tmp1, numer).Add(tmp1, accum)
    29  	big.DivModInt(tmp1, tmp2, tmp1, denom)
    30  	tmp2.Add(tmp2, numer)
    31  	if big.CmpInt(tmp2, denom) >= 0 {
    32  		return -1
    33  	}
    34  	return tmp1.Int64()
    35  }
    36  
    37  func nextTerm(k int64) {
    38  	y2 := k*2 + 1
    39  	accum.Add(accum, tmp1.Lsh(numer, 1))
    40  	accum.Mul(accum, tmp1.SetInt64(y2))
    41  	numer.Mul(numer, tmp1.SetInt64(k))
    42  	denom.Mul(denom, tmp1.SetInt64(y2))
    43  }
    44  
    45  func eliminateDigit(d int64) {
    46  	accum.Sub(accum, tmp1.Mul(denom, tmp1.SetInt64(d)))
    47  	accum.Mul(accum, ten)
    48  	numer.Mul(numer, ten)
    49  }
    50  
    51  func main() {
    52  	i := 0
    53  	k := int64(0)
    54  	for {
    55  		d := int64(-1)
    56  		for d < 0 {
    57  			k++
    58  			nextTerm(k)
    59  			d = extractDigit()
    60  		}
    61  		eliminateDigit(d)
    62  		fmt.Printf("%c", d+'0')
    63  
    64  		if i++; i%50 == 0 {
    65  			fmt.Printf("\n")
    66  			if i >= 1000 {
    67  				break
    68  			}
    69  		}
    70  	}
    71  
    72  	fmt.Printf("\n%d calls; bit sizes: %d %d %d\n", runtime.NumCgoCall(), numer.Len(), accum.Len(), denom.Len())
    73  }
    74  

View as plain text