Skip to content

Commit 59a6ba5

Browse files
committed
math/big: factored out an internal accessor method (cleanup), added benchmark
Current result of DecimalConversion benchmark (for future reference): BenchmarkDecimalConversion-8 10000 204770 ns/op Measured on Mac Mini (late 2012) running OS X 10.10.5, 2.3 GHz Intel Core i7, 8 GB 1333 MHz DDR3. Also: Removed comment suggesting to implement decimal by representing digits as numbers 0..9 rather than ASCII chars '0'..'9' to avoid repeated +/-'0' operations. Tried and it appears (per above benchmark) that the +/-'0' operations are neglibile but the addition conversion passes around it are not and that it makes things significantly slower. Change-Id: I6ee033b1172043248093cc5d02abff5fc54c2e7a Reviewed-on: https://go-review.googlesource.com/14857 Reviewed-by: Brad Fitzpatrick <[email protected]> Run-TryBot: Robert Griesemer <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Alan Donovan <[email protected]>
1 parent 53c92f9 commit 59a6ba5

3 files changed

Lines changed: 21 additions & 19 deletions

File tree

src/math/big/decimal.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ type decimal struct {
2929
exp int // exponent
3030
}
3131

32+
// at returns the i'th mantissa digit, starting with the most significant digit at 0.
33+
func (d *decimal) at(i int) byte {
34+
if 0 <= i && i < len(d.mant) {
35+
return d.mant[i]
36+
}
37+
return '0'
38+
}
39+
3240
// Maximum shift amount that can be done in one pass without overflow.
3341
// A Word has _W bits and (1<<maxShift - 1)*10 + 9 must fit into Word.
3442
const maxShift = _W - 4
@@ -92,12 +100,6 @@ func (x *decimal) init(m nat, shift int) {
92100
}
93101
}
94102

95-
// Possibly optimization: The current implementation of nat.string takes
96-
// a charset argument. When a right shift is needed, we could provide
97-
// "\x00\x01...\x09" instead of "012..9" (as in nat.decimalString) and
98-
// avoid the repeated +'0' and -'0' operations in decimal.shr (and do a
99-
// single +'0' pass at the end).
100-
101103
// shr implements x >> s, for s <= maxShift.
102104
func shr(x *decimal, s uint) {
103105
// Division by 1<<s using shift-and-subtract algorithm.

src/math/big/decimal_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,13 @@ func TestDecimalRounding(t *testing.T) {
104104
}
105105
}
106106
}
107+
108+
func BenchmarkDecimalConversion(b *testing.B) {
109+
for i := 0; i < b.N; i++ {
110+
for shift := -100; shift <= +100; shift++ {
111+
var d decimal
112+
d.init(natOne, shift)
113+
d.String()
114+
}
115+
}
116+
}

src/math/big/ftoa.go

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -201,14 +201,8 @@ func roundShortest(d *decimal, x *Float) {
201201
// Now we can figure out the minimum number of digits required.
202202
// Walk along until d has distinguished itself from upper and lower.
203203
for i, m := range d.mant {
204-
l := byte('0') // lower digit
205-
if i < len(lower.mant) {
206-
l = lower.mant[i]
207-
}
208-
u := byte('0') // upper digit
209-
if i < len(upper.mant) {
210-
u = upper.mant[i]
211-
}
204+
l := lower.at(i)
205+
u := upper.at(i)
212206

213207
// Okay to round down (truncate) if lower has a different digit
214208
// or if lower is inclusive and is exactly the result of rounding
@@ -296,11 +290,7 @@ func fmtF(buf []byte, prec int, d decimal) []byte {
296290
if prec > 0 {
297291
buf = append(buf, '.')
298292
for i := 0; i < prec; i++ {
299-
ch := byte('0')
300-
if j := d.exp + i; 0 <= j && j < len(d.mant) {
301-
ch = d.mant[j]
302-
}
303-
buf = append(buf, ch)
293+
buf = append(buf, d.at(d.exp+i))
304294
}
305295
}
306296

0 commit comments

Comments
 (0)