blob: e59312177f4144705af7034c3c538aee134b397c [file] [log] [blame]
Robert Griesemer081bc692009-08-06 18:16:51 -07001/*
2Redistribution and use in source and binary forms, with or without
3modification, are permitted provided that the following conditions are met:
4
5 * Redistributions of source code must retain the above copyright
6 notice, this list of conditions and the following disclaimer.
7
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11
12 * Neither the name of "The Computer Language Benchmarks Game" nor the
13 name of "The Computer Language Shootout Benchmarks" nor the names of
14 its contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27POSSIBILITY OF SUCH DAMAGE.
28*/
29
30/* The Computer Language Benchmarks Game
31 * http://shootout.alioth.debian.org/
32 *
33 * contributed by The Go Authors.
34 * based on pidigits.c (by Paolo Bonzini & Sean Bartlett,
35 * modified by Michael Mellor)
36 */
37
38package main
39
40import (
Evan Shaw76cbbc82010-04-20 20:39:36 -070041 "big"
Robert Griesemer45ca9f72009-12-15 15:41:46 -080042 "flag"
43 "fmt"
Robert Griesemer081bc692009-08-06 18:16:51 -070044)
45
Russ Cox19dae072009-11-20 13:11:42 -080046var n = flag.Int("n", 27, "number of digits")
47var silent = flag.Bool("s", false, "don't print result")
Robert Griesemer081bc692009-08-06 18:16:51 -070048
49var (
Evan Shaw76cbbc82010-04-20 20:39:36 -070050 tmp1 = big.NewInt(0)
51 tmp2 = big.NewInt(0)
Evan Shaw5bf420f2010-10-30 20:16:44 -070052 tmp3 = big.NewInt(0)
Evan Shaw76cbbc82010-04-20 20:39:36 -070053 y2 = big.NewInt(0)
54 bigk = big.NewInt(0)
55 numer = big.NewInt(1)
56 accum = big.NewInt(0)
57 denom = big.NewInt(1)
58 ten = big.NewInt(10)
Robert Griesemer081bc692009-08-06 18:16:51 -070059)
60
61func extract_digit() int64 {
62 if numer.Cmp(accum) > 0 {
Russ Cox19dae072009-11-20 13:11:42 -080063 return -1
Robert Griesemer081bc692009-08-06 18:16:51 -070064 }
65
Robert Griesemer0dbd8972009-08-10 17:44:46 -070066 // Compute (numer * 3 + accum) / denom
Robert Griesemer58e77992010-04-30 21:25:48 -070067 tmp1.Lsh(numer, 1)
Evan Shaw76cbbc82010-04-20 20:39:36 -070068 tmp1.Add(tmp1, numer)
69 tmp1.Add(tmp1, accum)
70 tmp1.DivMod(tmp1, denom, tmp2)
Robert Griesemer081bc692009-08-06 18:16:51 -070071
Robert Griesemer0dbd8972009-08-10 17:44:46 -070072 // Now, if (numer * 4 + accum) % denom...
Evan Shaw76cbbc82010-04-20 20:39:36 -070073 tmp2.Add(tmp2, numer)
Robert Griesemer081bc692009-08-06 18:16:51 -070074
Robert Griesemer0dbd8972009-08-10 17:44:46 -070075 // ... is normalized, then the two divisions have the same result.
Robert Griesemer081bc692009-08-06 18:16:51 -070076 if tmp2.Cmp(denom) >= 0 {
Russ Cox19dae072009-11-20 13:11:42 -080077 return -1
Robert Griesemer081bc692009-08-06 18:16:51 -070078 }
79
Evan Shaw76cbbc82010-04-20 20:39:36 -070080 return tmp1.Int64()
Robert Griesemer081bc692009-08-06 18:16:51 -070081}
82
83func next_term(k int64) {
Robert Griesemerb9caa4a2010-05-03 18:48:05 -070084 y2.SetInt64(k*2 + 1)
85 bigk.SetInt64(k)
Robert Griesemer081bc692009-08-06 18:16:51 -070086
Robert Griesemer58e77992010-04-30 21:25:48 -070087 tmp1.Lsh(numer, 1)
Evan Shaw76cbbc82010-04-20 20:39:36 -070088 accum.Add(accum, tmp1)
89 accum.Mul(accum, y2)
90 numer.Mul(numer, bigk)
91 denom.Mul(denom, y2)
Robert Griesemer081bc692009-08-06 18:16:51 -070092}
93
94func eliminate_digit(d int64) {
Evan Shaw5bf420f2010-10-30 20:16:44 -070095 tmp3.SetInt64(d)
96 accum.Sub(accum, tmp3.Mul(denom, tmp3))
Evan Shaw76cbbc82010-04-20 20:39:36 -070097 accum.Mul(accum, ten)
98 numer.Mul(numer, ten)
Robert Griesemer081bc692009-08-06 18:16:51 -070099}
100
Rob Piked2fc5d62010-02-02 10:53:37 +1100101func printf(s string, arg ...interface{}) {
Robert Griesemer081bc692009-08-06 18:16:51 -0700102 if !*silent {
Russ Cox2ee420f2010-09-24 11:55:48 -0400103 fmt.Printf(s, arg...)
Robert Griesemer081bc692009-08-06 18:16:51 -0700104 }
105}
106
107func main() {
Robert Griesemer45ca9f72009-12-15 15:41:46 -0800108 flag.Parse()
Robert Griesemer081bc692009-08-06 18:16:51 -0700109
Robert Griesemer45ca9f72009-12-15 15:41:46 -0800110 var m int // 0 <= m < 10
Robert Griesemer081bc692009-08-06 18:16:51 -0700111 for i, k := 0, int64(0); ; {
Robert Griesemer45ca9f72009-12-15 15:41:46 -0800112 d := int64(-1)
Robert Griesemer081bc692009-08-06 18:16:51 -0700113 for d < 0 {
Robert Griesemer45ca9f72009-12-15 15:41:46 -0800114 k++
115 next_term(k)
116 d = extract_digit()
Robert Griesemer081bc692009-08-06 18:16:51 -0700117 }
118
Robert Griesemer45ca9f72009-12-15 15:41:46 -0800119 printf("%c", d+'0')
Robert Griesemer081bc692009-08-06 18:16:51 -0700120
Robert Griesemer45ca9f72009-12-15 15:41:46 -0800121 i++
122 m = i % 10
Robert Griesemer081bc692009-08-06 18:16:51 -0700123 if m == 0 {
Russ Cox19dae072009-11-20 13:11:42 -0800124 printf("\t:%d\n", i)
Robert Griesemer081bc692009-08-06 18:16:51 -0700125 }
126 if i >= *n {
Russ Cox19dae072009-11-20 13:11:42 -0800127 break
Robert Griesemer081bc692009-08-06 18:16:51 -0700128 }
Robert Griesemer45ca9f72009-12-15 15:41:46 -0800129 eliminate_digit(d)
Robert Griesemer081bc692009-08-06 18:16:51 -0700130 }
131
132 if m > 0 {
Russ Cox19dae072009-11-20 13:11:42 -0800133 printf("%s\t:%d\n", " "[m:10], *n)
Robert Griesemer081bc692009-08-06 18:16:51 -0700134 }
135}