mirror of
https://github.com/golang/go
synced 2024-09-30 09:28:33 -06:00
math/big: replace local versions of bitLen, nlz with math/bits versions
Verified that BenchmarkBitLen time went down from 2.25 ns/op to 0.65 ns/op an a 2.3 GHz Intel Core i7, before removing that benchmark (now covered by math/bits benchmarks). Change-Id: I3890bb7d1889e95b9a94bd68f0bdf06f1885adeb Reviewed-on: https://go-review.googlesource.com/38464 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
536a2257fb
commit
70ea0ec30f
@ -76,42 +76,10 @@ func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
|
||||
return
|
||||
}
|
||||
|
||||
// Length of x in bits.
|
||||
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.
|
||||
// Wraps bits.LeadingZeros call for convenience.
|
||||
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
|
||||
if w == 0 {
|
||||
return 32 + nlz(Word(x))
|
||||
}
|
||||
return nlz(Word(w))
|
||||
case 64:
|
||||
return nlz(Word(x))
|
||||
}
|
||||
panic("unreachable")
|
||||
return uint(bits.LeadingZeros(uint(x)))
|
||||
}
|
||||
|
||||
// q = (u1<<_W + u0 - r)/y
|
||||
|
@ -269,14 +269,3 @@ E7: SUBL $1, BX // i--
|
||||
|
||||
MOVL DX, r+32(FP)
|
||||
RET
|
||||
|
||||
// func bitLen(x Word) (n int)
|
||||
TEXT ·bitLen(SB),NOSPLIT,$0
|
||||
BSRL x+0(FP), AX
|
||||
JZ Z1
|
||||
INCL AX
|
||||
MOVL AX, n+4(FP)
|
||||
RET
|
||||
|
||||
Z1: MOVL $0, n+4(FP)
|
||||
RET
|
||||
|
@ -450,14 +450,3 @@ E7: SUBQ $1, BX // i--
|
||||
|
||||
MOVQ DX, r+64(FP)
|
||||
RET
|
||||
|
||||
// func bitLen(x Word) (n int)
|
||||
TEXT ·bitLen(SB),NOSPLIT,$0
|
||||
BSRQ x+0(FP), AX
|
||||
JZ Z1
|
||||
ADDQ $1, AX
|
||||
MOVQ AX, n+8(FP)
|
||||
RET
|
||||
|
||||
Z1: MOVQ $0, n+8(FP)
|
||||
RET
|
||||
|
@ -38,6 +38,3 @@ TEXT ·addMulVVW(SB),NOSPLIT,$0
|
||||
|
||||
TEXT ·divWVW(SB),NOSPLIT,$0
|
||||
JMP ·divWVW_g(SB)
|
||||
|
||||
TEXT ·bitLen(SB),NOSPLIT,$0
|
||||
JMP ·bitLen_g(SB)
|
||||
|
@ -292,11 +292,3 @@ TEXT ·mulWW(SB),NOSPLIT,$0
|
||||
MOVW R4, z1+8(FP)
|
||||
MOVW R3, z0+12(FP)
|
||||
RET
|
||||
|
||||
// func bitLen(x Word) (n int)
|
||||
TEXT ·bitLen(SB),NOSPLIT,$0
|
||||
MOVW x+0(FP), R0
|
||||
CLZ R0, R0
|
||||
RSB $32, R0
|
||||
MOVW R0, n+4(FP)
|
||||
RET
|
||||
|
@ -165,13 +165,3 @@ TEXT ·addMulVVW(SB),NOSPLIT,$0
|
||||
// func divWVW(z []Word, xn Word, x []Word, y Word) (r Word)
|
||||
TEXT ·divWVW(SB),NOSPLIT,$0
|
||||
B ·divWVW_g(SB)
|
||||
|
||||
|
||||
// func bitLen(x Word) (n int)
|
||||
TEXT ·bitLen(SB),NOSPLIT,$0
|
||||
MOVD x+0(FP), R0
|
||||
CLZ R0, R0
|
||||
MOVD $64, R1
|
||||
SUB R0, R1, R0
|
||||
MOVD R0, n+8(FP)
|
||||
RET
|
||||
|
@ -18,4 +18,3 @@ func shrVU(z, x []Word, s uint) (c Word)
|
||||
func mulAddVWW(z, x []Word, y, r Word) (c Word)
|
||||
func addMulVVW(z, x []Word, y Word) (c Word)
|
||||
func divWVW(z []Word, xn Word, x []Word, y Word) (r Word)
|
||||
func bitLen(x Word) (n int)
|
||||
|
@ -49,7 +49,3 @@ func addMulVVW(z, x []Word, y Word) (c Word) {
|
||||
func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) {
|
||||
return divWVW_g(z, xn, x, y)
|
||||
}
|
||||
|
||||
func bitLen(x Word) (n int) {
|
||||
return bitLen_g(x)
|
||||
}
|
||||
|
@ -41,6 +41,3 @@ TEXT ·addMulVVW(SB),NOSPLIT,$0
|
||||
|
||||
TEXT ·divWVW(SB),NOSPLIT,$0
|
||||
JMP ·divWVW_g(SB)
|
||||
|
||||
TEXT ·bitLen(SB),NOSPLIT,$0
|
||||
JMP ·bitLen_g(SB)
|
||||
|
@ -41,6 +41,3 @@ TEXT ·addMulVVW(SB),NOSPLIT,$0
|
||||
|
||||
TEXT ·divWVW(SB),NOSPLIT,$0
|
||||
JMP ·divWVW_g(SB)
|
||||
|
||||
TEXT ·bitLen(SB),NOSPLIT,$0
|
||||
JMP ·bitLen_g(SB)
|
||||
|
@ -175,12 +175,3 @@ end:
|
||||
|
||||
TEXT ·divWVW(SB), NOSPLIT, $0
|
||||
BR ·divWVW_g(SB)
|
||||
|
||||
// func bitLen(x Word) int
|
||||
TEXT ·bitLen(SB), NOSPLIT, $0
|
||||
MOVD x+0(FP), R4
|
||||
CNTLZD R4, R4
|
||||
MOVD $64, R5
|
||||
SUB R4, R5
|
||||
MOVD R5, n+8(FP)
|
||||
RET
|
||||
|
@ -1237,13 +1237,3 @@ E7: SUB $1, R7 // i--
|
||||
|
||||
MOVD R10, r+64(FP)
|
||||
RET
|
||||
|
||||
// func bitLen(x Word) (n int)
|
||||
TEXT ·bitLen(SB),NOSPLIT,$0
|
||||
MOVD x+0(FP), R2
|
||||
FLOGR R2, R2 // clobbers R3
|
||||
MOVD $64, R3
|
||||
SUB R2, R3
|
||||
MOVD R3, n+8(FP)
|
||||
RET
|
||||
|
||||
|
@ -395,32 +395,3 @@ func BenchmarkAddMulVVW(b *testing.B) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testWordBitLen(t *testing.T, fname string, f func(Word) int) {
|
||||
for i := 0; i <= _W; i++ {
|
||||
x := Word(1) << uint(i-1) // i == 0 => x == 0
|
||||
n := f(x)
|
||||
if n != i {
|
||||
t.Errorf("got %d; want %d for %s(%#x)", n, i, fname, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWordBitLen(t *testing.T) {
|
||||
testWordBitLen(t, "bitLen", bitLen)
|
||||
testWordBitLen(t, "bitLen_g", bitLen_g)
|
||||
}
|
||||
|
||||
// runs b.N iterations of bitLen called on a Word containing (1 << nbits)-1.
|
||||
func BenchmarkBitLen(b *testing.B) {
|
||||
// Individual bitLen tests. Numbers chosen to examine both sides
|
||||
// of powers-of-two boundaries.
|
||||
for _, nbits := range []uint{0, 1, 2, 3, 4, 5, 8, 9, 16, 17, 31} {
|
||||
testword := Word((uint64(1) << nbits) - 1)
|
||||
b.Run(fmt.Sprint(nbits), func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
bitLen(testword)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ package big
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
const debugFloat = false // enable for debugging
|
||||
@ -498,8 +499,8 @@ func (z *Float) setBits64(neg bool, x uint64) *Float {
|
||||
}
|
||||
// x != 0
|
||||
z.form = finite
|
||||
s := nlz64(x)
|
||||
z.mant = z.mant.setUint64(x << s)
|
||||
s := bits.LeadingZeros64(x)
|
||||
z.mant = z.mant.setUint64(x << uint(s))
|
||||
z.exp = int32(64 - s) // always fits
|
||||
if z.prec < 64 {
|
||||
z.round(0)
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/bits"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
@ -328,9 +329,9 @@ func TestFloat64Text(t *testing.T) {
|
||||
|
||||
// actualPrec returns the number of actually used mantissa bits.
|
||||
func actualPrec(x float64) uint {
|
||||
if bits := math.Float64bits(x); x != 0 && bits&(0x7ff<<52) == 0 {
|
||||
if mant := math.Float64bits(x); x != 0 && mant&(0x7ff<<52) == 0 {
|
||||
// x is denormalized
|
||||
return 64 - nlz64(bits&(1<<52-1))
|
||||
return 64 - uint(bits.LeadingZeros64(mant&(1<<52-1)))
|
||||
}
|
||||
return 53
|
||||
}
|
||||
|
@ -644,7 +644,7 @@ 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
|
||||
}
|
||||
|
@ -8,10 +8,18 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/bits"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
return bits.Len(uint(x)) - 1
|
||||
}
|
||||
|
||||
func itoa(x nat, base int) []byte {
|
||||
// special cases
|
||||
switch {
|
||||
|
Loading…
Reference in New Issue
Block a user