diff options
Diffstat (limited to 'libgo/go/math/big/nat.go')
-rw-r--r-- | libgo/go/math/big/nat.go | 63 |
1 files changed, 8 insertions, 55 deletions
diff --git a/libgo/go/math/big/nat.go b/libgo/go/math/big/nat.go index 9b1a626..889eacb 100644 --- a/libgo/go/math/big/nat.go +++ b/libgo/go/math/big/nat.go @@ -9,6 +9,7 @@ package big import ( + "math/bits" "math/rand" "sync" ) @@ -67,24 +68,14 @@ func (z nat) setWord(x Word) nat { } func (z nat) setUint64(x uint64) nat { - // single-digit values + // single-word value if w := Word(x); uint64(w) == x { return z.setWord(w) } - - // compute number of words n required to represent x - n := 0 - for t := x; t > 0; t >>= _W { - n++ - } - - // split x into n words - z = z.make(n) - for i := range z { - z[i] = Word(x & _M) - x >>= _W - } - + // 2-word value + z = z.make(2) + z[1] = Word(x >> 32) + z[0] = Word(x) return z } @@ -653,49 +644,11 @@ func (z nat) divLarge(u, uIn, v nat) (q, r nat) { // Length of x in bits. x must be normalized. func (x nat) bitLen() int { if i := len(x) - 1; i >= 0 { - return i*_W + bitLen(x[i]) + return i*_W + bits.Len(uint(x[i])) } 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 { @@ -707,7 +660,7 @@ 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 |