internal/number: clean up RoundingContext
- remove Scale and Precision fields
- pass RoundingContext as value (safer)
- fixes a bug as a side-effect
Change-Id: I248eccae2ad7fa5fe411b0893eaf784e8b10aca7
Reviewed-on: https://go-review.googlesource.com/58570
Run-TryBot: Marcel van Lohuizen <mpvl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/internal/number/decimal.go b/internal/number/decimal.go
index 7c28dc1..443c69e 100644
--- a/internal/number/decimal.go
+++ b/internal/number/decimal.go
@@ -292,7 +292,7 @@
// A Converter converts a number into decimals according to the given rounding
// criteria.
type Converter interface {
- Convert(d *Decimal, r *RoundingContext)
+ Convert(d *Decimal, r RoundingContext)
}
const (
@@ -302,7 +302,7 @@
// Convert converts the given number to the decimal representation using the
// supplied RoundingContext.
-func (d *Decimal) Convert(r *RoundingContext, number interface{}) {
+func (d *Decimal) Convert(r RoundingContext, number interface{}) {
switch f := number.(type) {
case Converter:
d.clear()
@@ -344,7 +344,7 @@
}
// ConvertInt converts an integer to decimals.
-func (d *Decimal) ConvertInt(r *RoundingContext, signed bool, x uint64) {
+func (d *Decimal) ConvertInt(r RoundingContext, signed bool, x uint64) {
if r.Increment > 0 {
// TODO: if uint64 is too large, fall back to float64
if signed {
@@ -364,7 +364,7 @@
}
// ConvertFloat converts a floating point number to decimals.
-func (d *Decimal) ConvertFloat(r *RoundingContext, x float64, size int) {
+func (d *Decimal) ConvertFloat(r RoundingContext, x float64, size int) {
d.clear()
if math.IsNaN(x) {
d.NaN = true
@@ -380,11 +380,13 @@
return
}
// Simple case: decimal notation
- if r.Scale > 0 || r.Increment > 0 || r.Precision == 0 {
- if int(r.Scale) > len(scales) {
- x *= math.Pow(10, float64(r.Scale))
+ scale := r.scale()
+ prec := r.precision()
+ if scale > 0 || r.Increment > 0 || prec == 0 {
+ if scale > len(scales) {
+ x *= math.Pow(10, float64(scale))
} else {
- x *= scales[r.Scale]
+ x *= scales[scale]
}
if r.Increment > 0 {
inc := float64(r.Increment)
@@ -395,7 +397,7 @@
x = r.Mode.roundFloat(x)
}
d.fillIntDigits(uint64(math.Abs(x)))
- d.Exp = int32(len(d.Digits)) - r.Scale
+ d.Exp = int32(len(d.Digits) - scale)
return
}
@@ -407,7 +409,6 @@
// AppendDigits(dst []byte, x float64, base, size, prec int) (digits []byte, exp, accuracy int)
// TODO: This only supports the nearest even rounding mode.
- prec := int(r.Precision)
if prec > 0 {
prec--
}
diff --git a/internal/number/decimal_test.go b/internal/number/decimal_test.go
index 11d7644..7860459 100644
--- a/internal/number/decimal_test.go
+++ b/internal/number/decimal_test.go
@@ -23,13 +23,13 @@
// value NaN, Inf, or -Inf.
func mkdec(num string) (d Decimal) {
var r RoundingContext
- d.Convert(&r, dec(num))
+ d.Convert(r, dec(num))
return
}
type dec string
-func (s dec) Convert(d *Decimal, _ *RoundingContext) {
+func (s dec) Convert(d *Decimal, _ RoundingContext) {
num := string(s)
if num[0] == '-' {
d.Neg = true
@@ -241,14 +241,18 @@
}
func TestConvert(t *testing.T) {
- scale2 := &RoundingContext{Scale: 2}
- scale2away := &RoundingContext{Scale: 2, Mode: AwayFromZero}
- inc0_05 := &RoundingContext{Increment: 5, Scale: 2}
- inc50 := &RoundingContext{Increment: 50}
- prec3 := &RoundingContext{Precision: 3}
+ scale2 := RoundingContext{}
+ scale2.SetScale(2)
+ scale2away := RoundingContext{Mode: AwayFromZero}
+ scale2away.SetScale(2)
+ inc0_05 := RoundingContext{Increment: 5}
+ inc0_05.SetScale(2)
+ inc50 := RoundingContext{Increment: 50}
+ prec3 := RoundingContext{}
+ prec3.SetPrecision(3)
testCases := []struct {
x interface{}
- rc *RoundingContext
+ rc RoundingContext
out string
}{
{int8(-34), scale2, "-34"},
@@ -294,7 +298,7 @@
type converter int
-func (c converter) Convert(d *Decimal, r *RoundingContext) {
+func (c converter) Convert(d *Decimal, r RoundingContext) {
d.Digits = append(d.Digits, 1, 0, 0)
d.Exp = 3
}
diff --git a/internal/number/format.go b/internal/number/format.go
index 9c764dc..744120a 100755
--- a/internal/number/format.go
+++ b/internal/number/format.go
@@ -81,12 +81,12 @@
func (f *Formatter) Append(dst []byte, x interface{}) []byte {
var d Decimal
- r := &f.RoundingContext
+ r := f.RoundingContext
d.Convert(r, x)
return f.Render(dst, FormatDigits(&d, r))
}
-func FormatDigits(d *Decimal, r *RoundingContext) Digits {
+func FormatDigits(d *Decimal, r RoundingContext) Digits {
if r.isScientific() {
return scientificVisibleDigits(r, d)
}
@@ -94,7 +94,7 @@
}
func (f *Formatter) Format(dst []byte, d *Decimal) []byte {
- return f.Render(dst, FormatDigits(d, &f.RoundingContext))
+ return f.Render(dst, FormatDigits(d, f.RoundingContext))
}
func (f *Formatter) Render(dst []byte, d Digits) []byte {
@@ -142,7 +142,7 @@
return result
}
-func decimalVisibleDigits(r *RoundingContext, d *Decimal) Digits {
+func decimalVisibleDigits(r RoundingContext, d *Decimal) Digits {
if d.NaN || d.Inf {
return Digits{digits: digits{Neg: d.Neg, NaN: d.NaN, Inf: d.Inf}}
}
@@ -282,7 +282,7 @@
return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
}
-func scientificVisibleDigits(r *RoundingContext, d *Decimal) Digits {
+func scientificVisibleDigits(r RoundingContext, d *Decimal) Digits {
if d.NaN || d.Inf {
return Digits{digits: digits{Neg: d.Neg, NaN: d.NaN, Inf: d.Inf}}
}
diff --git a/internal/number/format_test.go b/internal/number/format_test.go
index c56cbc1..fc7c36d 100755
--- a/internal/number/format_test.go
+++ b/internal/number/format_test.go
@@ -453,7 +453,7 @@
buf := make([]byte, 100)
t.Run(tc.pattern+"/"+num, func(t *testing.T) {
var d Decimal
- d.Convert(&f.RoundingContext, dec(num))
+ d.Convert(f.RoundingContext, dec(num))
buf = f.Format(buf[:0], &d)
if got := string(buf); got != want {
t.Errorf("\n got %[1]q (%[1]s)\nwant %[2]q (%[2]s)", got, want)
@@ -480,7 +480,7 @@
var f Formatter
f.InitDecimal(tc.tag)
var d Decimal
- d.Convert(&f.RoundingContext, dec(tc.num))
+ d.Convert(f.RoundingContext, dec(tc.num))
b := f.Format(nil, &d)
if got := string(b); got != tc.want {
t.Errorf("got %[1]q (%[1]s); want %[2]q (%[2]s)", got, tc.want)
@@ -508,7 +508,7 @@
tc.init(language.English)
f.SetScale(2)
var d Decimal
- d.Convert(&f.RoundingContext, dec(tc.num))
+ d.Convert(f.RoundingContext, dec(tc.num))
b := f.Format(nil, &d)
if got := string(b); got != tc.want {
t.Errorf("got %[1]q (%[1]s); want %[2]q (%[2]s)", got, tc.want)
diff --git a/internal/number/pattern.go b/internal/number/pattern.go
index 881308e..89c2a1c 100644
--- a/internal/number/pattern.go
+++ b/internal/number/pattern.go
@@ -39,19 +39,14 @@
//
// This type is only intended for internal use.
type Pattern struct {
- // TODO: this struct can be packed a lot better than it is now. Should be
- // possible to make it 32 bytes.
-
- Affix string // includes prefix and suffix. First byte is prefix length.
- Offset uint16 // Offset into Affix for prefix and suffix
- NegOffset uint16 // Offset into Affix for negative prefix and suffix or 0.
-
- FormatWidth uint16
-
- PadRune rune
-
RoundingContext
+ Affix string // includes prefix and suffix. First byte is prefix length.
+ Offset uint16 // Offset into Affix for prefix and suffix
+ NegOffset uint16 // Offset into Affix for negative prefix and suffix or 0.
+ PadRune rune
+ FormatWidth uint16
+
GroupingSize [2]uint8
Flags PatternFlag
}
@@ -60,45 +55,44 @@
// It contains all information needed to determine the "visible digits" as
// required by the pluralization rules.
type RoundingContext struct {
- Precision int32 // maximum number of significant digits.
- Scale int32 // maximum number of decimals after the dot.
-
- // if > 0, round to Increment * 10^-Scale
- Increment uint32 // Use Min*Digits to determine scale
+ Increment uint32 // if > 0, round to Increment * 10^-scale()
+ // TODO: unify these two fields so that there is a more unambiguous meaning
+ // of how precision is handled.
+ MaxSignificantDigits int16 // -1 is infinite precision
+ MaxFractionDigits uint16
Mode RoundingMode
DigitShift uint8 // Number of decimals to shift. Used for % and ‰.
// Number of digits.
- // TODO: consider using uint32
- MinIntegerDigits uint8
+ MinIntegerDigits uint8
+
MaxIntegerDigits uint8
MinFractionDigits uint8
- MaxFractionDigits uint8
MinSignificantDigits uint8
- MaxSignificantDigits uint8
MinExponentDigits uint8
}
-func (r *RoundingContext) update() {
- if r.Scale > 0 {
- r.SetScale(int(r.Scale))
+func (r *RoundingContext) scale() int {
+ // scale is 0 when precision is set.
+ if r.MaxSignificantDigits != 0 {
+ return 0
}
- if r.Precision > 0 {
- r.SetPrecision(int(r.Precision))
- }
+ return int(r.MaxFractionDigits)
}
+func (r *RoundingContext) precision() int { return int(r.MaxSignificantDigits) }
+
// SetScale fixes the RoundingContext to a fixed number of fraction digits.
func (r *RoundingContext) SetScale(scale int) {
r.MinFractionDigits = uint8(scale)
- r.MaxFractionDigits = uint8(scale)
+ r.MaxFractionDigits = uint16(scale)
}
func (r *RoundingContext) SetPrecision(prec int) {
- r.MaxSignificantDigits = uint8(prec)
+ r.MaxSignificantDigits = int16(prec)
}
func (r *RoundingContext) isScientific() bool {
@@ -420,7 +414,7 @@
func (p *parser) normalizeSigDigitsWithExponent() state {
p.MinIntegerDigits, p.MaxIntegerDigits = 1, 1
p.MinFractionDigits = p.MinSignificantDigits - 1
- p.MaxFractionDigits = p.MaxSignificantDigits - 1
+ p.MaxFractionDigits = uint16(p.MaxSignificantDigits) - 1
p.MinSignificantDigits, p.MaxSignificantDigits = 0, 0
return p.exponent
}
diff --git a/internal/number/tables.go b/internal/number/tables.go
index b140234..2cf16f5 100644
--- a/internal/number/tables.go
+++ b/internal/number/tables.go
@@ -846,323 +846,291 @@
0x04, 0x04,
} // Size: 778 bytes
-var formats = []Pattern{Pattern{Affix: "",
+var formats = []Pattern{Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x0,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "",
Offset: 0x0,
NegOffset: 0x0,
- FormatWidth: 0x0,
PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
+ FormatWidth: 0x0,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x3,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x9,
+ GroupingSize: [2]uint8{0x3,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x0,
+ MaxIntegerDigits: 0x1,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x1},
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x3,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x00\x03\u00a0%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x7,
+ GroupingSize: [2]uint8{0x3,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x00\x01%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x6,
+ GroupingSize: [2]uint8{0x3,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x3,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0xc,
+ GroupingSize: [2]uint8{0x3,
+ 0x2},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x00\x01%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x9,
+ GroupingSize: [2]uint8{0x3,
+ 0x2},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x00\x03\u00a0%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0xa,
+ GroupingSize: [2]uint8{0x3,
+ 0x2},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x6,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x9,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x6,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x6,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x3},
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0xd,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x4},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x00\x01%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x3,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x03%\u00a0\x00",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x7,
+ GroupingSize: [2]uint8{0x3,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x03%\u00a0\x00\x04%\u00a0-\x00",
+ Offset: 0x0,
+ NegOffset: 0x5,
+ PadRune: 0,
+ FormatWidth: 0x7,
+ GroupingSize: [2]uint8{0x3,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x0,
+ MaxIntegerDigits: 0x1,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x1},
+ Affix: "\x01[\x01]",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x5,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x0,
+ Mode: 0x0,
DigitShift: 0x0,
MinIntegerDigits: 0x0,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0},
- GroupingSize: [2]uint8{0x0,
- 0x0},
- Flags: 0x0},
- Pattern{Affix: "",
+ Affix: "",
Offset: 0x0,
NegOffset: 0x0,
- FormatWidth: 0x9,
PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x0,
- MinIntegerDigits: 0x1,
- MaxIntegerDigits: 0x0,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x3,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x0},
- GroupingSize: [2]uint8{0x3,
- 0x0},
- Flags: 0x0},
- Pattern{Affix: "",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x3,
- PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x0,
- MinIntegerDigits: 0x0,
- MaxIntegerDigits: 0x1,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x1},
- GroupingSize: [2]uint8{0x0,
- 0x0},
- Flags: 0x0},
- Pattern{Affix: "\x00\x03\u00a0%",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x7,
- PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x2,
- MinIntegerDigits: 0x1,
- MaxIntegerDigits: 0x0,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x0},
- GroupingSize: [2]uint8{0x3,
- 0x0},
- Flags: 0x0},
- Pattern{Affix: "\x00\x01%",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x6,
- PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x2,
- MinIntegerDigits: 0x1,
- MaxIntegerDigits: 0x0,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x0},
- GroupingSize: [2]uint8{0x3,
- 0x0},
- Flags: 0x0},
- Pattern{Affix: "",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0xc,
- PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x0,
- MinIntegerDigits: 0x1,
- MaxIntegerDigits: 0x0,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x3,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x0},
- GroupingSize: [2]uint8{0x3,
- 0x2},
- Flags: 0x0},
- Pattern{Affix: "\x00\x01%",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x9,
- PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x2,
- MinIntegerDigits: 0x1,
- MaxIntegerDigits: 0x0,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x0},
- GroupingSize: [2]uint8{0x3,
- 0x2},
- Flags: 0x0},
- Pattern{Affix: "\x00\x03\u00a0%",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0xa,
- PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x2,
- MinIntegerDigits: 0x1,
- MaxIntegerDigits: 0x0,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x0},
- GroupingSize: [2]uint8{0x3,
- 0x2},
- Flags: 0x0},
- Pattern{Affix: "",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x9,
- PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x0,
- MinIntegerDigits: 0x1,
- MaxIntegerDigits: 0x0,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x6,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x0},
- GroupingSize: [2]uint8{0x0,
- 0x0},
- Flags: 0x0},
- Pattern{Affix: "",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0xd,
- PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x0,
- MinIntegerDigits: 0x1,
- MaxIntegerDigits: 0x0,
- MinFractionDigits: 0x6,
- MaxFractionDigits: 0x6,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x3},
- GroupingSize: [2]uint8{0x0,
- 0x0},
- Flags: 0x4},
- Pattern{Affix: "\x00\x01%",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x3,
- PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x2,
- MinIntegerDigits: 0x1,
- MaxIntegerDigits: 0x0,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x0},
- GroupingSize: [2]uint8{0x0,
- 0x0},
- Flags: 0x0},
- Pattern{Affix: "\x03%\u00a0\x00",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x7,
- PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x2,
- MinIntegerDigits: 0x1,
- MaxIntegerDigits: 0x0,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x0},
- GroupingSize: [2]uint8{0x3,
- 0x0},
- Flags: 0x0},
- Pattern{Affix: "\x03%\u00a0\x00\x04%\u00a0-\x00",
- Offset: 0x0,
- NegOffset: 0x5,
- FormatWidth: 0x7,
- PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x2,
- MinIntegerDigits: 0x1,
- MaxIntegerDigits: 0x0,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x0},
- GroupingSize: [2]uint8{0x3,
- 0x0},
- Flags: 0x0},
- Pattern{Affix: "\x01[\x01]",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x5,
- PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x0,
- MinIntegerDigits: 0x0,
- MaxIntegerDigits: 0x1,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x1},
- GroupingSize: [2]uint8{0x0,
- 0x0},
- Flags: 0x0},
- Pattern{Affix: "",
- Offset: 0x0,
- NegOffset: 0x0,
FormatWidth: 0x1,
- PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x0,
- MinIntegerDigits: 0x0,
- MaxIntegerDigits: 0x0,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x0},
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x0},
- Pattern{Affix: "\x01%\x00",
+ Pattern{RoundingContext: RoundingContext{Increment: 0x0,
+ MaxSignificantDigits: 0,
+ MaxFractionDigits: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x01%\x00",
Offset: 0x0,
NegOffset: 0x0,
- FormatWidth: 0x6,
PadRune: 0,
- RoundingContext: RoundingContext{Mode: 0x0,
- Precision: 0,
- Scale: 0,
- Increment: 0x0,
- DigitShift: 0x2,
- MinIntegerDigits: 0x1,
- MaxIntegerDigits: 0x0,
- MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
- MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x0},
+ FormatWidth: 0x6,
GroupingSize: [2]uint8{0x3,
0x0},
Flags: 0x0}}
diff --git a/message/fmt_test.go b/message/fmt_test.go
index 0dbedcb..b22420d 100755
--- a/message/fmt_test.go
+++ b/message/fmt_test.go
@@ -565,8 +565,8 @@
// old test/fmt_test.go
{"%e", 1.0, "1.000000\u202f×\u202f10⁰⁰"},
- {"%e", 1234.5678e3, "1.234570\u202f×\u202f10⁰⁶"},
- {"%e", 1234.5678e-8, "1.234570\u202f×\u202f10⁻⁰⁵"},
+ {"%e", 1234.5678e3, "1.234568\u202f×\u202f10⁰⁶"},
+ {"%e", 1234.5678e-8, "1.234568\u202f×\u202f10⁻⁰⁵"},
{"%e", -7.0, "-7.000000\u202f×\u202f10⁰⁰"},
{"%e", -1e-9, "-1.000000\u202f×\u202f10⁻⁰⁹"},
{"%f", 1234.5678e3, "1,234,567.800000"},
@@ -580,8 +580,8 @@
{"%g", -1e-9, "-1\u202f×\u202f10⁻⁰⁹"},
{"%g", float32(-1e-9), "-1\u202f×\u202f10⁻⁰⁹"},
{"%E", 1.0, "1.000000\u202f×\u202f10⁰⁰"},
- {"%E", 1234.5678e3, "1.234570\u202f×\u202f10⁰⁶"},
- {"%E", 1234.5678e-8, "1.234570\u202f×\u202f10⁻⁰⁵"},
+ {"%E", 1234.5678e3, "1.234568\u202f×\u202f10⁰⁶"},
+ {"%E", 1234.5678e-8, "1.234568\u202f×\u202f10⁻⁰⁵"},
{"%E", -7.0, "-7.000000\u202f×\u202f10⁰⁰"},
{"%E", -1e-9, "-1.000000\u202f×\u202f10⁻⁰⁹"},
{"%G", 1234.5678e3, "1.2345678\u202f×\u202f10⁰⁶"},
diff --git a/message/print.go b/message/print.go
index 8c8a23f..c0bef3f 100644
--- a/message/print.go
+++ b/message/print.go
@@ -237,7 +237,7 @@
if p.fmt.sharp || p.fmt.sharpV {
p.fmt.fmt_float(v, size, verb, -1)
} else {
- p.fmtVariableFloat(v, size, -1)
+ p.fmtVariableFloat(v, size)
}
case 'e', 'E':
if p.fmt.sharp || p.fmt.sharpV {
@@ -284,7 +284,7 @@
f.MinIntegerDigits = 1
f.MaxIntegerDigits = 0
f.MinFractionDigits = uint8(minFrac)
- f.MaxFractionDigits = uint8(maxFrac)
+ f.MaxFractionDigits = uint16(maxFrac)
p.setFlags(f)
f.PadRune = 0
if p.fmt.widPresent {
@@ -308,8 +308,13 @@
func (p *printer) initScientific(minFrac, maxFrac int) {
f := &p.toScientific
- f.MinFractionDigits = uint8(minFrac)
- f.MaxFractionDigits = uint8(maxFrac)
+ if maxFrac < 0 {
+ f.SetPrecision(maxFrac)
+ } else {
+ f.SetPrecision(maxFrac + 1)
+ f.MinFractionDigits = uint8(minFrac)
+ f.MaxFractionDigits = uint16(maxFrac)
+ }
f.MinExponentDigits = 2
p.setFlags(f)
f.PadRune = 0
@@ -328,8 +333,6 @@
func (p *printer) fmtDecimalInt(v uint64, isSigned bool) {
var d number.Decimal
- p.toDecimal.RoundingContext.Scale = 0
- d.ConvertInt(&p.toDecimal.RoundingContext, isSigned, v)
f := &p.toDecimal
if p.fmt.precPresent {
@@ -344,6 +347,7 @@
} else {
p.initDecimal(0, 0)
}
+ d.ConvertInt(p.toDecimal.RoundingContext, isSigned, v)
out := p.toDecimal.Format([]byte(nil), &d)
p.Buffer.Write(out)
@@ -354,22 +358,21 @@
if p.fmt.precPresent {
prec = p.fmt.prec
}
- p.toDecimal.RoundingContext.Scale = int32(prec)
- d.ConvertFloat(&p.toDecimal.RoundingContext, v, size)
-
p.initDecimal(prec, prec)
+ d.ConvertFloat(p.toDecimal.RoundingContext, v, size)
out := p.toDecimal.Format([]byte(nil), &d)
p.Buffer.Write(out)
}
-func (p *printer) fmtVariableFloat(v float64, size, prec int) {
+func (p *printer) fmtVariableFloat(v float64, size int) {
+ prec := -1
if p.fmt.precPresent {
prec = p.fmt.prec
}
var d number.Decimal
- p.toScientific.RoundingContext.Precision = int32(prec)
- d.ConvertFloat(&p.toScientific.RoundingContext, v, size)
+ p.initScientific(0, prec)
+ d.ConvertFloat(p.toScientific.RoundingContext, v, size)
// Copy logic of 'g' formatting from strconv. It is simplified a bit as
// we don't have to mind having prec > len(d.Digits).
@@ -407,10 +410,9 @@
if p.fmt.precPresent {
prec = p.fmt.prec
}
- p.toScientific.RoundingContext.Precision = int32(prec)
- d.ConvertFloat(&p.toScientific.RoundingContext, v, size)
-
p.initScientific(prec, prec)
+ rc := p.toScientific.RoundingContext
+ d.ConvertFloat(rc, v, size)
out := p.toScientific.Format([]byte(nil), &d)
p.Buffer.Write(out)