package big
+import "math/bits"
+
// A Word represents a single digit of a multi-precision unsigned integer.
type Word uint
const (
- // Compute the size _S of a Word in bytes.
- _m = ^Word(0)
- _logS = _m>>8&1 + _m>>16&1 + _m>>32&1
- _S = 1 << _logS
+ _S = _W / 8 // word size in bytes
- _W = _S << 3 // word size in bits
- _B = 1 << _W // digit base
- _M = _B - 1 // digit mask
+ _W = bits.UintSize // word size in bits
+ _B = 1 << _W // digit base
+ _M = _B - 1 // digit mask
_W2 = _W / 2 // half word size in bits
_B2 = 1 << _W2 // half digit base
}
// Length of x in bits.
-func bitLen_g(x Word) (n int) {
- for ; x >= 0x8000; x >>= 16 {
- n += 16
- }
- if x >= 0x80 {
- x >>= 8
- n += 8
- }
- if x >= 0x8 {
- x >>= 4
- n += 4
- }
- if x >= 0x2 {
- x >>= 2
- n += 2
- }
- if x >= 0x1 {
- n++
- }
- return
+func bitLen_g(x Word) int {
+ return bits.Len(uint(x))
}
// log2 computes the integer binary logarithm of x.
// The result is the integer n for which 2^n <= x < 2^(n+1).
// If x == 0, the result is -1.
func log2(x Word) int {
+ // TODO(gri) Replace with call to bits.Len once we have a fast
+ // implementation for the same platforms currently supporting math/big.
return bitLen(x) - 1
}
// nlz returns the number of leading zeros in x.
func nlz(x Word) uint {
+ // TODO(gri) Replace with call to bits.LeadingZeros once we have a fast
+ // implementation for the same platforms currently supporting math/big.
return uint(_W - bitLen(x))
}
// nlz64 returns the number of leading zeros in x.
func nlz64(x uint64) uint {
+ // TODO(gri) Replace with call to bits.LeadingZeros64 once we have a fast
+ // implementation for the same platforms currently supporting math/big.
switch _W {
case 32:
w := x >> 32
package big
import (
+ "math/bits"
"math/rand"
"sync"
)
return 0
}
-const deBruijn32 = 0x077CB531
-
-var deBruijn32Lookup = [...]byte{
- 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
- 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9,
-}
-
-const deBruijn64 = 0x03f79d71b4ca8b09
-
-var deBruijn64Lookup = [...]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,
-}
-
-// trailingZeroBits returns the number of consecutive least significant zero
-// bits of x.
-func trailingZeroBits(x Word) uint {
- // x & -x leaves only the right-most bit set in the word. Let k be the
- // index of that bit. Since only a single bit is set, the value is two
- // to the power of k. Multiplying by a power of two is equivalent to
- // left shifting, in this case by k bits. The de Bruijn constant is
- // such that all six bit, consecutive substrings are distinct.
- // Therefore, if we have a left shifted version of this constant we can
- // find by how many bits it was shifted by looking at which six bit
- // substring ended up at the top of the word.
- // (Knuth, volume 4, section 7.3.1)
- switch _W {
- case 32:
- return uint(deBruijn32Lookup[((x&-x)*deBruijn32)>>27])
- case 64:
- return uint(deBruijn64Lookup[((x&-x)*(deBruijn64&_M))>>58])
- default:
- panic("unknown word size")
- }
-}
-
// trailingZeroBits returns the number of consecutive least significant zero
// bits of x.
func (x nat) trailingZeroBits() uint {
i++
}
// x[i] != 0
- return i*_W + trailingZeroBits(x[i])
+ return i*_W + uint(bits.TrailingZeros(uint(x[i])))
}
// z = x << s
}
}
-func TestTrailingZeroBits(t *testing.T) {
- // test 0 case explicitly
- if n := trailingZeroBits(0); n != 0 {
- t.Errorf("got trailingZeroBits(0) = %d; want 0", n)
- }
-
- x := Word(1)
- for i := uint(0); i < _W; i++ {
- n := trailingZeroBits(x)
- if n != i {
- t.Errorf("got trailingZeroBits(%#x) = %d; want %d", x, n, i%_W)
- }
- x <<= 1
- }
-
- // test 0 case explicitly
- if n := nat(nil).trailingZeroBits(); n != 0 {
- t.Errorf("got nat(nil).trailingZeroBits() = %d; want 0", n)
- }
-
- y := nat(nil).set(natOne)
- for i := uint(0); i <= 3*_W; i++ {
- n := y.trailingZeroBits()
- if n != i {
- t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.utoa(16), n, i)
- }
- y = y.shl(y, 1)
- }
-}
-
var montgomeryTests = []struct {
x, y, m string
k0 uint64