Skip to content

Instantly share code, notes, and snippets.

@zyxar
Created April 6, 2012 05:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zyxar/2317067 to your computer and use it in GitHub Desktop.
Save zyxar/2317067 to your computer and use it in GitHub Desktop.
π's nth hexadecimal digit generator
/*
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