Created
April 6, 2012 05:01
-
-
Save zyxar/2317067 to your computer and use it in GitHub Desktop.
π's nth hexadecimal digit generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This program implements the BBP algorithm to generate a few hexadecimal | |
digits beginning immediately after a given position id, or in other words | |
beginning at position id + 1. The original C version was implemented by | |
David H. Bailey. | |
*/ | |
/* | |
Marcus Zy 06-04-2012 "Good Friday" | |
This is my first ever 'go' program. | |
*/ | |
package main | |
import ( | |
"fmt" | |
"math" | |
"strconv" | |
"flag" | |
"runtime" | |
) | |
const ( | |
ntp = 25 | |
eps = 1e-17 | |
) | |
type keyvalue struct { | |
key int | |
value byte | |
} | |
func expm(p, ak float64) float64 { | |
var i, j int | |
var p1, pt, r float64 | |
var tp [ntp]float64 | |
tp1 := 0 | |
if tp1 == 0 { | |
tp1 = 1 | |
tp[0] = 1. | |
for i := 1; i < ntp; i++ { | |
tp[i] = 2. * tp[i-1] | |
} | |
} | |
if ak == 1. { | |
return 0. | |
} | |
for i = 0; i < ntp; i++ { | |
if tp[i] > p { | |
break | |
} | |
} | |
pt = tp[i-1] | |
p1 = p | |
r = 1. | |
for j = 1; j <= i; j++ { | |
if p1 >= pt { | |
r = 16. * r | |
r = math.Mod(r, ak) | |
p1 = p1 - pt | |
} | |
pt = 0.5 * pt | |
if pt >= 1. { | |
r = r * r | |
r = math.Mod(r, ak) | |
} | |
} | |
return r | |
//return math.Mod(math.Pow(16.,p), ak) | |
} | |
func series(m,id int) float64 { | |
var k int | |
var ak, p, s, t float64 | |
s = 0. | |
for k = 0; k < id; k++ { | |
ak = float64(8 * k + m) | |
p = float64(id - k) | |
t = expm(p, ak) | |
s = s + t/ak | |
s = math.Mod(s, 1) | |
} | |
for k = id; k < id + 100; k++ { | |
ak = float64(8 * k + m) | |
t = math.Pow(16., float64(id-k))/ak | |
if t < eps { | |
break | |
} | |
s = s + t | |
s = math.Mod(s, 1) | |
} | |
return s | |
} | |
func get_byte(id int) byte { | |
s1, s2, s3, s4 := series(1, id), series(4, id), series(5, id), series(6, id) | |
pid := 4. * s1 - 2 * s2 - s3 - s4 | |
pid = math.Mod(pid, 1) + 1 | |
y := math.Abs(pid) | |
y = 16. * (y - math.Floor(y)) | |
var first, second byte | |
first = byte(y) | |
y = 16. * (y - math.Floor(y)) | |
second = byte(y) | |
return (first << 4) | second | |
} | |
func calc(id, i int, c chan keyvalue) { | |
c <- keyvalue{i, get_byte(id)} | |
} | |
func main() { | |
flag.Parse() | |
if flag.NArg() < 2 { | |
return | |
} | |
var index, num int | |
index,_ = strconv.Atoi(flag.Arg(0)) | |
num,_ = strconv.Atoi(flag.Arg(1)) | |
nrt := runtime.NumCPU() | |
if nrt > 16 { nrt = 16 } | |
runtime.GOMAXPROCS(nrt) | |
c := make(chan keyvalue, num) | |
for i := 0; i < num; i++ { | |
go calc(index + i*2, i, c) | |
} | |
var buf keyvalue | |
buffer := make([]byte, num) | |
for i := 0; i < num; i++ { | |
//fmt.Printf("%02X", <-c) | |
buf = <- c | |
buffer[buf.key] = buf.value | |
} | |
fmt.Printf("%02X\n", buffer) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment