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>
This commit is contained in:
Ilya Tocar 2018-05-15 13:29:18 -05:00 committed by Robert Griesemer
parent 9b49edef50
commit 323c85862a
1 changed files with 11 additions and 30 deletions

View File

@ -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,