pi.go 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  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. //go:build ignore
  5. // +build ignore
  6. package main
  7. import (
  8. big "."
  9. "fmt"
  10. "runtime"
  11. )
  12. var (
  13. tmp1 = big.NewInt(0)
  14. tmp2 = big.NewInt(0)
  15. numer = big.NewInt(1)
  16. accum = big.NewInt(0)
  17. denom = big.NewInt(1)
  18. ten = big.NewInt(10)
  19. )
  20. func extractDigit() int64 {
  21. if big.CmpInt(numer, accum) > 0 {
  22. return -1
  23. }
  24. tmp1.Lsh(numer, 1).Add(tmp1, numer).Add(tmp1, accum)
  25. big.DivModInt(tmp1, tmp2, tmp1, denom)
  26. tmp2.Add(tmp2, numer)
  27. if big.CmpInt(tmp2, denom) >= 0 {
  28. return -1
  29. }
  30. return tmp1.Int64()
  31. }
  32. func nextTerm(k int64) {
  33. y2 := k*2 + 1
  34. accum.Add(accum, tmp1.Lsh(numer, 1))
  35. accum.Mul(accum, tmp1.SetInt64(y2))
  36. numer.Mul(numer, tmp1.SetInt64(k))
  37. denom.Mul(denom, tmp1.SetInt64(y2))
  38. }
  39. func eliminateDigit(d int64) {
  40. accum.Sub(accum, tmp1.Mul(denom, tmp1.SetInt64(d)))
  41. accum.Mul(accum, ten)
  42. numer.Mul(numer, ten)
  43. }
  44. func main() {
  45. i := 0
  46. k := int64(0)
  47. for {
  48. d := int64(-1)
  49. for d < 0 {
  50. k++
  51. nextTerm(k)
  52. d = extractDigit()
  53. }
  54. eliminateDigit(d)
  55. fmt.Printf("%c", d+'0')
  56. if i++; i%50 == 0 {
  57. fmt.Printf("\n")
  58. if i >= 1000 {
  59. break
  60. }
  61. }
  62. }
  63. fmt.Printf("\n%d calls; bit sizes: %d %d %d\n", runtime.NumCgoCall(), numer.Len(), accum.Len(), denom.Len())
  64. }