P.S. (For posterity ;-) The reason the else-clause is not coded normally at the end of fib_half() is because of present Go compiler limitations. When this limit is removed the code should change.)
package main
import (
"fmt"
"math/big"
)
// recursive splitting Fibonacci evaluation
func fib_half(n int) (*big.Int, *big.Int) {
if n <= 0 {
zero := big.NewInt(0)
return zero, zero
}
if n == 1 {
return big.NewInt(0), big.NewInt(1)
}
h := n / 2 // compute F(n) from F(n/2) for O(log2 n) complexity
f1, f2 := fib_half(h) // f1 = F(h-1), f2 = F(h)
f3 := big.NewInt(0).Add(f1, f2) // f3 = F(h+1)
t := big.NewInt(0).Add(f1, f3)
t = t.Mul(t, f2)
s2 := big.NewInt(0).Mul(f2, f2) // F(h)**2
if n&1 == 1 { // handle odd n
s3 := big.NewInt(0).Mul(f3, f3) // F(h+1)**2
return t, s2.Add(s2, s3) // (f1 + f3)*f2, f2*f2 + f3*f3
} // else // handle even n
s1 := big.NewInt(0).Mul(f1, f1) // F(h-1)**2
return s1.Add(s1, s2), t // f1*f1 + f2*f2, (f1 + f3)*f2
}
func fib(n int) *big.Int {
_, f := fib_half(n)
return f
}
func trim(n *big.Int) string {
s := fmt.Sprintf("%d", n)
width := 91
length := len(s)
if length > width {
s = s[0:(width-3)/2] + "..." + s[length-(width-3)/2:]
}
s = fmt.Sprintf("%*s [%7d digits]", width, s, length)
return s
}
var fibTests = []struct {
n int
f string
}{
{0, "0"},
{1, "1"},
{2, "1"},
{3, "2"},
{4, "3"},
{480, "9216845717656874712980450562726202415567360565980794777111390850331644813674856981646960226192287360"},
{485, "102216385354134324778078911974689347564945335253989394162085272183728832930964492342791374522266860485"},
{490, "1133597084613134447271848482284309025629966048359864130560049384871348807054284272752352079971127752695"},
{495, "12571784316098613244768412217102088629494571867212494830322628505768565710528091492618664254204672140130"},
{500, "139423224561697880139724382870407283950070256587697307264108962948325571622863290691557658876222521294125"},
}
func testFib() int {
failures := 0
for i, test := range fibTests {
s := fmt.Sprintf("%d", fib(test.n))
if s != test.f {
fmt.Printf("error: #%d got %v want %v\n", i, s, test.f)
failures++
}
}
if failures == 0 {
fmt.Printf("passed\n")
} else {
fmt.Printf("failed: %d failures\n", failures)
}
return failures
}
func main() {
fmt.Printf("testing... ")
testFib()
fmt.Printf("\n")
fmt.Printf("first\n")
for n := 0; n <= 16; n++ {
fmt.Printf(" F(%2d) = %d\n", n, fib(n))
}
fmt.Printf("\n")
fmt.Printf("F(2**n)\n")
for n := 1; n <= 1<<20; n <<= 1 {
fmt.Printf(" F(%7d) = %s\n", n, trim(fib(n)))
}
fmt.Printf("\n")
fmt.Printf("F(10**n)\n")
for n := 1; n <= 1000000; n *= 10 {
fmt.Printf(" F(%7d) = %s\n", n, trim(fib(n)))
}
fmt.Printf("\n")
fmt.Printf("probable prime Fibonacci numbers (sequence A001605 in OEIS)\n")
for n := 0; n <= 600; n++ {
f := fib(n)
if f.ProbablyPrime(64) {
fmt.Printf(" F(%7d) = %s\n", n, trim(f))
}
}
fmt.Printf("\n")
}
OUTPUT:
mtj$ go run fib.go
testing... passed
first
F( 0) = 0
F( 1) = 1
F( 2) = 1
F( 3) = 2
F( 4) = 3
F( 5) = 5
F( 6) = 8
F( 7) = 13
F( 8) = 21
F( 9) = 34
F(10) = 55
F(11) = 89
F(12) = 144
F(13) = 233
F(14) = 377
F(15) = 610
F(16) = 987
F(2**n)
F( 1) = 1 [ 1 digits]
F( 2) = 1 [ 1 digits]
F( 4) = 3 [ 1 digits]
F( 8) = 21 [ 2 digits]
F( 16) = 987 [ 3 digits]
F( 32) = 2178309 [ 7 digits]
F( 64) = 10610209857723 [ 14 digits]
F( 128) = 251728825683549488150424261 [ 27 digits]
F( 256) = 141693817714056513234709965875411919657707794958199867 [ 54 digits]
F( 512) = 44893845313309942978077298160660626646181883...66661322268805744081870933775586567858979269 [ 107 digits]
F( 1024) = 45066996336778198131043832357288860493678605...68899711089246778413354004103631553925405243 [ 214 digits]
F( 2048) = 45415304437437894250455714462906892027009082...10145547104337536614028338983073680262684101 [ 428 digits]
F( 4096) = 46120017322804312474564457085636141271732249...85050077521931600327064840520442470066917947 [ 856 digits]
F( 8192) = 47562418031541483249676431926694568862149480...34121942551466950077266295376251851089202629 [ 1712 digits]
F( 16384) = 50583963273256865512698275499738614264772589...16487934517684664695772372793939867475669563 [ 3424 digits]
F( 32768) = 57215106297689468939590948384261448582742164...43607205126221971914921497265149891505753541 [ 6848 digits]
F( 65536) = 73199214460290552832639915812598454538952425...17531793911596579203414697270190955307463227 [ 13696 digits]
F( 131072) = 11981131726582568764552857855321239080658488...44491510870363731782250304265906436130344389 [ 27393 digits]
F( 262144) = 32098200701891878424611639413278177386990176...46534756609059187480173020581102949038682683 [ 54785 digits]
F( 524288) = 23038085126797742368512278649433257358762739...35892895641064341683333020246122520212016581 [ 109570 digits]
F(1048576) = 11868006063550661146017510449861600696082418...24222218017383101627183453200033680691163707 [ 219140 digits]
F(10**n)
F( 1) = 1 [ 1 digits]
F( 10) = 55 [ 2 digits]
F( 100) = 354224848179261915075 [ 21 digits]
F( 1000) = 43466557686937456435688527675040625802564660...38298969649928516003704476137795166849228875 [ 209 digits]
F( 10000) = 33644764876431783266621612005107543310302148...62430701794976171121233066073310059947366875 [ 2090 digits]
F( 100000) = 25974069347221724166155034021275915414880485...09970015699780289236362349895374653428746875 [ 20899 digits]
F(1000000) = 19532821287077577316320149475962563324435429...19033684684301719893411568996526838242546875 [ 208988 digits]
probable prime Fibonacci numbers (sequence A001605 in OEIS)
F( 3) = 2 [ 1 digits]
F( 4) = 3 [ 1 digits]
F( 5) = 5 [ 1 digits]
F( 7) = 13 [ 2 digits]
F( 11) = 89 [ 2 digits]
F( 13) = 233 [ 3 digits]
F( 17) = 1597 [ 4 digits]
F( 23) = 28657 [ 5 digits]
F( 29) = 514229 [ 6 digits]
F( 43) = 433494437 [ 9 digits]
F( 47) = 2971215073 [ 10 digits]
F( 83) = 99194853094755497 [ 17 digits]
F( 131) = 1066340417491710595814572169 [ 28 digits]
F( 137) = 19134702400093278081449423917 [ 29 digits]
F( 359) = 475420437734698220747368027166749382927701417016557193662268716376935476241 [ 75 digits]
F( 431) = 529892711006095621792039556787784670197112759029534506620905162834769955134424689676262369 [ 90 digits]
F( 433) = 1387277127804783827114186103186246392258450358171783690079918032136025225954602593712568353 [ 91 digits]
F( 449) = 30617199924845450305543138480837172081112854...38497131674799321571238149015933442805665949 [ 94 digits]
F( 509) = 10597999265301490732599643671505003412515860...80142974347195483140293254396195769876129909 [ 107 digits]
F( 569) = 36684474316080978061473613646275630451100586...93560857904335017879540515228143777781065869 [ 119 digits]
F( 571) = 96041200618922553823942883360924865026104917...08478864192589084185254331637646183008074629 [ 119 digits]