]> Cypherpunks repositories - gostls13.git/commitdiff
math/big: replace local versions of bitLen, nlz with math/bits versions
authorRobert Griesemer <gri@golang.org>
Thu, 23 Mar 2017 17:54:08 +0000 (10:54 -0700)
committerRobert Griesemer <gri@golang.org>
Thu, 23 Mar 2017 19:43:09 +0000 (19:43 +0000)
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>
17 files changed:
src/math/big/arith.go
src/math/big/arith_386.s
src/math/big/arith_amd64.s
src/math/big/arith_amd64p32.s
src/math/big/arith_arm.s
src/math/big/arith_arm64.s
src/math/big/arith_decl.go
src/math/big/arith_decl_pure.go
src/math/big/arith_mips64x.s
src/math/big/arith_mipsx.s
src/math/big/arith_ppc64x.s
src/math/big/arith_s390x.s
src/math/big/arith_test.go
src/math/big/float.go
src/math/big/floatconv_test.go
src/math/big/nat.go
src/math/big/natconv_test.go

index 8cc0fb6497d13bdb5e43220cb2432561689b0cb6..ad352403a7c5e7223ff1f6fb081d877542da6f95 100644 (file)
@@ -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
index 7c8ab8feb752b91c5d97665c982d6d600742e790..6c080f074a3c0671c81f90d599a65f7812e75319 100644 (file)
@@ -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
index a7eba676b00cc386befed52d306f2b2f0654fea1..7e502246c89e58005c6261fe4004cc2d9349f9cb 100644 (file)
@@ -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
index 6006646647b82d7b9ba34020efe236e1146fac12..0a672386ccd753ab1ede00ed66c18840b727915b 100644 (file)
@@ -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)
index 69590ff39e1a4b584c6e1fb6c2c6d6fb6e08e4aa..ba65fd2b1fa5e1754914adc315d168efcce16d7b 100644 (file)
@@ -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
index 24a717cbb0ea2422ec9092ee057858f8e9d18711..397b4630a84639449bce18e0f10c03f5763203b5 100644 (file)
@@ -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
index 5433b6d61d41357ac3d6fc266aa87f028736e46a..41e592334c376ecc532bd5bf870c7fe89f3c12ab 100644 (file)
@@ -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)
index 21775ddf3e364db01666abbc6c5a604e8538bc85..4ae49c123d9f71bb6c64d87bb726a46398b89f5b 100644 (file)
@@ -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)
-}
index f9288fc26e9d0d81733cd471ef0d061ee019eb1c..983510ee3d42d1e9f8d7b44334fc650b1f22afdd 100644 (file)
@@ -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)
index ac2311465ff52dbd9e548990498b90de4205bf71..54cafbd9c0c80cc6108bd2dde5596ab1ff9e359e 100644 (file)
@@ -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)
index 89d1cbfecd063daec266f582a4a16d824708614d..3606dae068ee792dc5ff2a24bb45ddc30d311052 100644 (file)
@@ -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
index bddfd9e83e8303a6db22f480e415efb193b1411d..4520d161d779d112330c7c21f894e01b3ad67e05 100644 (file)
@@ -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
-
index f2b308300093f42d33dbdabe32e06a97b79c3ec4..13b0436ab4e39b2a18f34cd6f4c5de02009afc99 100644 (file)
@@ -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)
-                       }
-               })
-       }
-}
index 6517e2063ce1a783727bfa388c7f5795346155ab..ac5464b1279eb5da5e9b8f906ad7d81cd936e5d7 100644 (file)
@@ -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)
index 9911280abc26c1dab0fe230fe05697584ea994c7..6d0f17dbe035d2cb0ceb9dabfc5dbfbebfd8b2cf 100644 (file)
@@ -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
 }
index 67176553b0ac53283c020aab8030715ac713dcf0..889eacb90f03c12911187d22d0f705beb12c81e5 100644 (file)
@@ -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
 }
index bdb60e68e0a711ed242555607ff5743f5c87e092..898a39fc2c2445bd219bbc007e2a48ea62136e6f 100644 (file)
@@ -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 {