Skip to content

Commit

Permalink
add some 32/64 functions in xmath, rename sieve.Len.
Browse files Browse the repository at this point in the history
  • Loading branch information
soniakeys committed May 8, 2012
1 parent 5401226 commit 2eb099c
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 4 deletions.
2 changes: 1 addition & 1 deletion binomial/binomial.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion factorial/double/double.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
2 changes: 1 addition & 1 deletion prime/sprp/sprp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion swing/swing.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down
65 changes: 65 additions & 0 deletions xmath/xmath.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]
}
80 changes: 80 additions & 0 deletions xmath/xmath_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.