From: Robert Griesemer Date: Wed, 4 Feb 2015 23:07:04 +0000 (-0800) Subject: strconv: simplified logic resulting in faster float formatting X-Git-Tag: go1.5beta1~2050 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=81a3f291f0721fee5dee6cd012cfdc7e4ee41a04;p=gostls13.git strconv: simplified logic resulting in faster float formatting benchmark old ns/op new ns/op delta BenchmarkFormatFloatDecimal 300 283 -5.67% BenchmarkFormatFloat 383 381 -0.52% BenchmarkFormatFloatExp 359 357 -0.56% BenchmarkFormatFloatNegExp 357 358 +0.28% BenchmarkFormatFloatBig 468 430 -8.12% BenchmarkAppendFloatDecimal 104 92.5 -11.06% BenchmarkAppendFloat 199 190 -4.52% BenchmarkAppendFloatExp 172 167 -2.91% BenchmarkAppendFloatNegExp 172 169 -1.74% BenchmarkAppendFloatBig 280 235 -16.07% BenchmarkAppendFloat32Integer 104 92.4 -11.15% BenchmarkAppendFloat32ExactFraction 168 171 +1.79% BenchmarkAppendFloat32Point 206 199 -3.40% BenchmarkAppendFloat32Exp 167 167 +0.00% BenchmarkAppendFloat32NegExp 167 166 -0.60% BenchmarkAppendFloat64Fixed1 134 129 -3.73% BenchmarkAppendFloat64Fixed2 144 136 -5.56% BenchmarkAppendFloat64Fixed3 138 134 -2.90% BenchmarkAppendFloat64Fixed4 145 138 -4.83% Change-Id: Ia143840cb34cbd1cebd6b691dd0a45b7264b406c Reviewed-on: https://go-review.googlesource.com/3920 Reviewed-by: Alan Donovan --- diff --git a/src/strconv/ftoa.go b/src/strconv/ftoa.go index 1a9c41b85a..f885d96e9c 100644 --- a/src/strconv/ftoa.go +++ b/src/strconv/ftoa.go @@ -119,7 +119,7 @@ func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte { // Precision for shortest representation mode. switch fmt { case 'e', 'E': - prec = digs.nd - 1 + prec = max(digs.nd-1, 0) case 'f': prec = max(digs.nd-digs.dp, 0) case 'g', 'G': @@ -348,14 +348,13 @@ func fmtE(dst []byte, neg bool, d decimalSlice, prec int, fmt byte) []byte { if prec > 0 { dst = append(dst, '.') i := 1 - m := d.nd + prec + 1 - max(d.nd, prec+1) - for i < m { - dst = append(dst, d.d[i]) - i++ + m := min(d.nd, prec+1) + if i < m { + dst = append(dst, d.d[i:m]...) + i = m } - for i <= prec { + for ; i <= prec; i++ { dst = append(dst, '0') - i++ } } @@ -373,27 +372,16 @@ func fmtE(dst []byte, neg bool, d decimalSlice, prec int, fmt byte) []byte { } dst = append(dst, ch) - // dddd - var buf [3]byte - i := len(buf) - for exp >= 10 { - i-- - buf[i] = byte(exp%10 + '0') - exp /= 10 + // dd or ddd + switch { + case exp < 10: + dst = append(dst, '0', byte(exp)+'0') + case exp < 100: + dst = append(dst, byte(exp/10)+'0', byte(exp%10)+'0') + default: + dst = append(dst, byte(exp/100)+'0', byte(exp/10)%10+'0', byte(exp%10)+'0') } - // exp < 10 - i-- - buf[i] = byte(exp + '0') - switch i { - case 0: - dst = append(dst, buf[0], buf[1], buf[2]) - case 1: - dst = append(dst, buf[1], buf[2]) - case 2: - // leading zeroes - dst = append(dst, '0', buf[2]) - } return dst } @@ -406,11 +394,9 @@ func fmtF(dst []byte, neg bool, d decimalSlice, prec int) []byte { // integer, padded with zeros as needed. if d.dp > 0 { - var i int - for i = 0; i < d.dp && i < d.nd; i++ { - dst = append(dst, d.d[i]) - } - for ; i < d.dp; i++ { + m := min(d.nd, d.dp) + dst = append(dst, d.d[:m]...) + for ; m < d.dp; m++ { dst = append(dst, '0') } } else { @@ -467,6 +453,13 @@ func fmtB(dst []byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte { return append(dst, buf[w:]...) } +func min(a, b int) int { + if a < b { + return a + } + return b +} + func max(a, b int) int { if a > b { return a