diff options
author | Ilya Tocar <ilya.tocar@intel.com> | 2018-05-15 13:29:18 -0500 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2018-05-30 19:28:20 +0000 |
commit | 323c85862a7afbde66a3bba0776bf4ba6cd7c030 (patch) | |
tree | 9a0272405c9d90c2ad4c57eb1299d50377d0a107 /src/strconv | |
parent | 9b49edef50a86ac06d956774bc03a2410f73920f (diff) | |
download | go-323c85862a7afbde66a3bba0776bf4ba6cd7c030.tar.gz go-323c85862a7afbde66a3bba0776bf4ba6cd7c030.zip |
strconv: simplify (*extFloat).Normalize
Use math/bits.LeadingZeros64 instead of local implementation.
This simplifies code, makes Normalize inlinable and fixes performance regression.
Idea was suggested by Giovanni Bajo in #25298
Performance results below:
Atof64Decimal-6 46.7ns ± 0% 46.7ns ± 0% ~ (all equal)
Atof64Float-6 57.9ns ± 1% 56.9ns ± 0% -1.72% (p=0.000 n=10+9)
Atof64FloatExp-6 163ns ± 0% 123ns ± 0% -24.54% (p=0.002 n=8+10)
Atof64Big-6 222ns ± 1% 185ns ± 1% -16.65% (p=0.000 n=9+10)
Atof64RandomBits-6 155ns ± 2% 154ns ± 3% ~ (p=0.225 n=10+10)
Atof64RandomFloats-6 156ns ± 2% 154ns ± 2% ~ (p=0.124 n=10+9)
Atof32Decimal-6 47.3ns ± 0% 46.7ns ± 0% -1.26% (p=0.000 n=7+9)
Atof32Float-6 51.5ns ± 1% 51.6ns ± 1% ~ (p=0.455 n=10+9)
Atof32FloatExp-6 163ns ± 1% 124ns ± 1% -24.36% (p=0.000 n=10+10)
Atof32Random-6 199ns ± 1% 163ns ± 0% -17.93% (p=0.000 n=10+10)
FormatFloat/Decimal-6 209ns ± 2% 211ns ± 2% ~ (p=0.402 n=10+10)
FormatFloat/Float-6 393ns ± 2% 379ns ± 1% -3.57% (p=0.000 n=10+10)
FormatFloat/Exp-6 333ns ± 2% 321ns ± 1% -3.56% (p=0.000 n=10+9)
FormatFloat/NegExp-6 338ns ± 3% 317ns ± 1% -6.27% (p=0.000 n=10+9)
FormatFloat/Big-6 457ns ± 1% 443ns ± 2% -2.99% (p=0.000 n=9+10)
FormatFloat/BinaryExp-6 230ns ± 2% 232ns ± 2% ~ (p=0.070 n=10+10)
FormatFloat/32Integer-6 209ns ± 2% 211ns ± 1% ~ (p=0.203 n=10+8)
FormatFloat/32ExactFraction-6 330ns ± 2% 319ns ± 1% -3.42% (p=0.000 n=10+10)
FormatFloat/32Point-6 393ns ± 2% 377ns ± 1% -4.15% (p=0.000 n=10+10)
FormatFloat/32Exp-6 331ns ± 2% 318ns ± 2% -4.02% (p=0.000 n=10+10)
FormatFloat/32NegExp-6 327ns ± 2% 315ns ± 2% -3.70% (p=0.000 n=10+10)
FormatFloat/64Fixed1-6 265ns ± 2% 253ns ± 2% -4.38% (p=0.000 n=10+10)
FormatFloat/64Fixed2-6 278ns ± 2% 262ns ± 3% -5.71% (p=0.000 n=10+10)
FormatFloat/64Fixed3-6 271ns ± 2% 260ns ± 2% -4.03% (p=0.000 n=10+10)
FormatFloat/64Fixed4-6 277ns ± 3% 267ns ± 1% -3.55% (p=0.000 n=10+9)
FormatFloat/Slowpath64-6 71.0µs ± 0% 71.0µs ± 0% ~ (p=0.744 n=10+8)
AppendFloat/Decimal-6 100ns ± 1% 100ns ± 0% ~ (p=0.294 n=10+8)
AppendFloat/Float-6 273ns ± 0% 260ns ± 1% -4.87% (p=0.000 n=7+10)
AppendFloat/Exp-6 213ns ± 0% 200ns ± 0% -6.29% (p=0.000 n=8+10)
AppendFloat/NegExp-6 211ns ± 0% 198ns ± 0% -6.16% (p=0.000 n=8+8)
AppendFloat/Big-6 319ns ± 0% 305ns ± 0% -4.31% (p=0.000 n=8+7)
AppendFloat/BinaryExp-6 98.4ns ± 0% 92.9ns ± 0% -5.63% (p=0.000 n=9+8)
AppendFloat/32Integer-6 101ns ± 1% 102ns ± 1% +0.89% (p=0.004 n=10+10)
AppendFloat/32ExactFraction-6 222ns ± 1% 210ns ± 0% -5.28% (p=0.000 n=10+9)
AppendFloat/32Point-6 273ns ± 1% 261ns ± 1% -4.62% (p=0.000 n=10+9)
AppendFloat/32Exp-6 209ns ± 1% 197ns ± 0% -5.56% (p=0.000 n=10+9)
AppendFloat/32NegExp-6 207ns ± 1% 194ns ± 1% -6.18% (p=0.000 n=10+10)
AppendFloat/64Fixed1-6 145ns ± 0% 131ns ± 1% -9.93% (p=0.000 n=9+10)
AppendFloat/64Fixed2-6 160ns ± 0% 146ns ± 0% -8.58% (p=0.000 n=10+8)
AppendFloat/64Fixed3-6 147ns ± 1% 132ns ± 1% -10.25% (p=0.000 n=10+10)
AppendFloat/64Fixed4-6 161ns ± 1% 149ns ± 0% -7.93% (p=0.000 n=10+10)
AppendFloat/Slowpath64-6 70.6µs ± 1% 70.9µs ± 0% +0.37% (p=0.000 n=10+8)
Change-Id: I63bbc40905abd795fbd24743604c790023d11a43
Reviewed-on: https://go-review.googlesource.com/113256
Run-TryBot: Ilya Tocar <ilya.tocar@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'src/strconv')
-rw-r--r-- | src/strconv/extfloat.go | 41 |
1 files changed, 11 insertions, 30 deletions
diff --git a/src/strconv/extfloat.go b/src/strconv/extfloat.go index 7f17bc6a0d..558daa1dbe 100644 --- a/src/strconv/extfloat.go +++ b/src/strconv/extfloat.go @@ -4,6 +4,10 @@ package strconv +import ( + "math/bits" +) + // An extFloat represents an extended floating-point number, with more // precision than a float64. It does not try to save bits: the // number represented by the structure is mant*(2^exp), with a negative @@ -196,38 +200,15 @@ func (f *extFloat) AssignComputeBounds(mant uint64, exp int, neg bool, flt *floa // Normalize normalizes f so that the highest bit of the mantissa is // set, and returns the number by which the mantissa was left-shifted. -func (f *extFloat) Normalize() (shift uint) { - mant, exp := f.mant, f.exp - if mant == 0 { +func (f *extFloat) Normalize() uint { + // bits.LeadingZeros64 would return 64 + if f.mant == 0 { return 0 } - if mant>>(64-32) == 0 { - mant <<= 32 - exp -= 32 - } - if mant>>(64-16) == 0 { - mant <<= 16 - exp -= 16 - } - if mant>>(64-8) == 0 { - mant <<= 8 - exp -= 8 - } - if mant>>(64-4) == 0 { - mant <<= 4 - exp -= 4 - } - if mant>>(64-2) == 0 { - mant <<= 2 - exp -= 2 - } - if mant>>(64-1) == 0 { - mant <<= 1 - exp -= 1 - } - shift = uint(f.exp - exp) - f.mant, f.exp = mant, exp - return + shift := bits.LeadingZeros64(f.mant) + f.mant <<= uint(shift) + f.exp -= shift + return uint(shift) } // Multiply sets f to the product f*g: the result is correctly rounded, |