# soniakeys/integer

add some 32/64 functions in xmath, rename sieve.Len.

1 parent 5401226 commit 2eb099c0bf70a3035fbbb908bedcfd44d7cd3d20 committed May 8, 2012
Showing with 149 additions and 4 deletions.
1. +1 −1 binomial/binomial.go
2. +1 −1 factorial/double/double.go
3. +1 −1 prime/sprp/sprp_test.go
4. +1 −1 swing/swing.go
5. +65 −0 xmath/xmath.go
6. +80 −0 xmath/xmath_test.go
 @@ -25,7 +25,7 @@ func Binomial(z *big.Int, n, k uint) *big.Int { // sieve p. BinomialS returns nil if p is too small. Otherwise it leaves // the result in z, replacing the existing value of z, and returning z. func BinomialS(z *big.Int, p *sieve.Sieve, n, k uint) *big.Int { - if uint64(n) > p.Len { + if uint64(n) > p.Lim { return nil } if k > n {
 @@ -42,7 +42,7 @@ func DoubleFactorialS(z *big.Int, p *swing.Swing, n uint) *big.Int { nn = n + 1 } - if uint64(nn) > p.Sieve.Len && nn > uint(len(swing.SmallOddFactorial)) { + if uint64(nn) > p.Sieve.Lim && nn > uint(len(swing.SmallOddFactorial)) { return nil }
 @@ -20,7 +20,7 @@ func TestBoundaryCases(t *testing.T) { s := sprp.New() for _, p := range [][]uint64{b12, b23, b32} { - i = 0 + i := 0 s.Iterate(p[0], p[len(p)-1], func(prime uint64) bool { if prime != p[i] { t.Fatal("Incorrect prime. Expected", p[i], "got", prime)
 @@ -36,7 +36,7 @@ func New(n uint) *Swing { // SwingingFactorial member computes n≀ on a Swing object. func (ps *Swing) SwingingFactorial(z *big.Int, n uint) *big.Int { - if uint64(n) > ps.Sieve.Len { + if uint64(n) > ps.Sieve.Lim { return nil } return z.Lsh(ps.OddSwing(z, n), xmath.BitCount32(uint32(n>>1)))
 @@ -94,6 +94,54 @@ func FloorSqrt(n uint) uint { return a } +// FloorSqrt32 is an integer square root function. +func FloorSqrt32(n uint32) uint32 { + b := (n + 1) / 2 + if b >= n { + return n + } + a := b + for { + b = (n/a + a) / 2 + if b >= a { + break + } + a = b + } + return a +} + +// FloorSqrt is an integer square root function. +func FloorSqrt64(n uint64) uint64 { + b := (n + 1) / 2 + if b >= n { + return n + } + a := b + for { + b = (n/a + a) / 2 + if b >= a { + break + } + a = b + } + return a +} + +// TrailingZeros returns the number of trailing 0 bits in v. +// +// If v is 0, it returns 0. +func TrailingZeros(v uint) (c byte) { + // seqential algorithm + if v != 0 { + for v&1 == 0 { + v >>= 1 + c++ + } + } + return +} + // reference: http://graphics.stanford.edu/~seander/bithacks.html const deBruijn32Multiple = 0x077CB531 const deBruijn32Shift = 27 @@ -109,3 +157,20 @@ var deBruijn32Bits = []byte{ func TrailingZeros32(v uint32) byte { return deBruijn32Bits[v&-v*deBruijn32Multiple>>deBruijn32Shift] } + +const deBruijn64Multiple = 0x03f79d71b4ca8b09 +const deBruijn64Shift = 58 + +var deBruijn64Bits = []byte{ + 0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4, + 62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5, + 63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11, + 54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6, +} + +// TrailingZeros64 returns the number of trailing 0 bits in v. +// +// If v is 0, it returns 0. +func TrailingZeros64(v uint64) byte { + return deBruijn64Bits[v&-v*deBruijn64Multiple>>deBruijn64Shift] +}
 @@ -103,6 +103,70 @@ func TestFloorSqrt(t *testing.T) { } } +func TestFloorSqrt32(t *testing.T) { + tcs := []struct { + n, s uint32 + }{ + {0, 0}, + {1, 1}, + {2, 1}, + {3, 1}, + {4, 2}, + {5, 2}, + {7, 2}, + {1<<20 - 1, 1<<10 - 1}, + {1 << 20, 1 << 10}, + {1<<20 + 1, 1 << 10}, + {math.MaxUint32 - 1, math.MaxUint16}, + } + for _, tc := range tcs { + if s := xmath.FloorSqrt32(tc.n); s != tc.s { + t.Errorf("FloorSqrt(%d) expected to be %d. got %d", tc.n, tc.s, s) + } + } +} + +func TestFloorSqrt64(t *testing.T) { + tcs := []struct { + n, s uint64 + }{ + {0, 0}, + {1, 1}, + {2, 1}, + {3, 1}, + {4, 2}, + {5, 2}, + {7, 2}, + {1<<20 - 1, 1<<10 - 1}, + {1 << 20, 1 << 10}, + {1<<20 + 1, 1 << 10}, + {math.MaxUint32 - 1, math.MaxUint16}, + {math.MaxUint64 - 1, math.MaxUint32}, + } + for _, tc := range tcs { + if s := xmath.FloorSqrt64(tc.n); s != tc.s { + t.Errorf("FloorSqrt64(%d) expected to be %d. got %d", tc.n, tc.s, s) + } + } +} + +func TestTrailingZeros(t *testing.T) { + for _, tc := range s { + tcu := uint(tc) + // seqential algorithm + var tz byte + if tcu != 0 { + for nz := tcu; nz&1 == 0; nz >>= 1 { + tz++ + } + } + // test + if cz := xmath.TrailingZeros(tcu); cz != tz { + t.Errorf("TrailingZero(%x) expected %d, got %d", tcu, tz, cz) + } + } +} + func TestTrailingZeros32(t *testing.T) { for _, tc := range s { tc32 := uint32(tc) @@ -119,3 +183,19 @@ func TestTrailingZeros32(t *testing.T) { } } } + +func TestTrailingZeros64(t *testing.T) { + for _, tc := range s { + // seqential algorithm + var tz byte + if tc != 0 { + for nz := tc; nz&1 == 0; nz >>= 1 { + tz++ + } + } + // test + if cz := xmath.TrailingZeros64(tc); cz != tz { + t.Errorf("TrailingZero64(%x) expected %d, got %d", tc, tz, cz) + } + } +}