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
7package main
8
9import (
10	big "."
11	"fmt"
12	"runtime"
13)
14
15var (
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
24func 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
37func 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
45func 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
51func 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