Permalink
Browse files

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

  • Loading branch information...
1 parent 5401226 commit 2eb099c0bf70a3035fbbb908bedcfd44d7cd3d20 @soniakeys 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
View
@@ -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
}
View
@@ -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)
View
@@ -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)))
View
@@ -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]
+}
View
@@ -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)
+ }
+ }
+}

0 comments on commit 2eb099c

Please sign in to comment.