// z1<<_W + z0 = x*y + c
func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
- z1, zz0 := mulWW(x, y)
+ z1, zz0 := mulWW_g(x, y)
if z0 = zz0 + c; z0 < zz0 {
z1++
}
return q1*_B2 + q0, (un21*_B2 + un0 - q0*v) >> s
}
+// Keep for performance debugging.
+// Using addWW_g is likely slower.
+const use_addWW_g = false
+
+// The resulting carry c is either 0 or 1.
func addVV_g(z, x, y []Word) (c Word) {
- for i := range z {
- c, z[i] = addWW_g(x[i], y[i], c)
+ if use_addWW_g {
+ for i := range z {
+ c, z[i] = addWW_g(x[i], y[i], c)
+ }
+ return
+ }
+
+ for i, xi := range x[:len(z)] {
+ yi := y[i]
+ zi := xi + yi + c
+ z[i] = zi
+ // see "Hacker's Delight", section 2-12 (overflow detection)
+ c = (xi&yi | (xi|yi)&^zi) >> (_W - 1)
}
return
}
+// The resulting carry c is either 0 or 1.
func subVV_g(z, x, y []Word) (c Word) {
- for i := range z {
- c, z[i] = subWW_g(x[i], y[i], c)
+ if use_addWW_g {
+ for i := range z {
+ c, z[i] = subWW_g(x[i], y[i], c)
+ }
+ return
+ }
+
+ for i, xi := range x[:len(z)] {
+ yi := y[i]
+ zi := xi - yi - c
+ z[i] = zi
+ // see "Hacker's Delight", section 2-12 (overflow detection)
+ c = (yi&^xi | (yi|^xi)&zi) >> (_W - 1)
}
return
}
+// Argument y must be either 0 or 1.
+// The resulting carry c is either 0 or 1.
func addVW_g(z, x []Word, y Word) (c Word) {
+ if use_addWW_g {
+ c = y
+ for i := range z {
+ c, z[i] = addWW_g(x[i], c, 0)
+ }
+ return
+ }
+
c = y
- for i := range z {
- c, z[i] = addWW_g(x[i], c, 0)
+ for i, xi := range x[:len(z)] {
+ zi := xi + c
+ z[i] = zi
+ c = xi &^ zi >> (_W - 1)
}
return
}
func subVW_g(z, x []Word, y Word) (c Word) {
+ if use_addWW_g {
+ c = y
+ for i := range z {
+ c, z[i] = subWW_g(x[i], c, 0)
+ }
+ return
+ }
+
c = y
- for i := range z {
- c, z[i] = subWW_g(x[i], c, 0)
+ for i, xi := range x[:len(z)] {
+ zi := xi - c
+ z[i] = zi
+ c = (zi &^ xi) >> (_W - 1)
}
return
}
return
}
+// TODO(gri) Remove use of addWW_g here and then we can remove addWW_g and subWW_g.
func addMulVVW_g(z, x []Word, y Word) (c Word) {
for i := range z {
z1, z0 := mulAddWWW_g(x[i], y, z[i])
func BenchmarkExp3Power0x40000(b *testing.B) { ExpHelper(b, 3, 0x40000) }
func BenchmarkExp3Power0x100000(b *testing.B) { ExpHelper(b, 3, 0x100000) }
func BenchmarkExp3Power0x400000(b *testing.B) { ExpHelper(b, 3, 0x400000) }
+
+func fibo(n int) nat {
+ switch n {
+ case 0:
+ return nil
+ case 1:
+ return nat{1}
+ }
+ f0 := fibo(0)
+ f1 := fibo(1)
+ var f2 nat
+ for i := 1; i < n; i++ {
+ f2 = f2.add(f0, f1)
+ f0, f1, f2 = f1, f2, f0
+ }
+ return f1
+}
+
+var fiboNums = []string{
+ "0",
+ "55",
+ "6765",
+ "832040",
+ "102334155",
+ "12586269025",
+ "1548008755920",
+ "190392490709135",
+ "23416728348467685",
+ "2880067194370816120",
+ "354224848179261915075",
+}
+
+func TestFibo(t *testing.T) {
+ for i, want := range fiboNums {
+ n := i * 10
+ got := fibo(n).decimalString()
+ if got != want {
+ t.Errorf("fibo(%d) failed: got %s want %s", n, got, want)
+ }
+ }
+}
+
+func BenchmarkFibo(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ fibo(1e0)
+ fibo(1e1)
+ fibo(1e2)
+ fibo(1e3)
+ fibo(1e4)
+ fibo(1e5)
+ }
+}