diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 8ee3cbd..6e949e6 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -56,9 +56,15 @@ jobs: - name: Run fuzzing for string parsing run: go test -fuzztime 20s -fuzz ^FuzzParse$ + - name: Run fuzzing from BSON unmarshaling + run: go test -fuzztime 20s -fuzz ^FuzzBSON$ + - name: Run fuzzing for string conversion run: go test -fuzztime 20s -fuzz ^FuzzDecimal_String_Parse$ + - name: Run fuzzing for IEEE 754-2008 conversion + run: go test -fuzztime 20s -fuzz ^FuzzDecimal_IEEE_ParseIEEE$ + - name: Run fuzzing for binary-text interoperability run: go test -fuzztime 20s -fuzz ^FuzzDecimal_Binary_Text$ diff --git a/CHANGELOG.md b/CHANGELOG.md index b1b9127..45c9341 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [0.1.35] - 2025-01-12 + +### Added + +- Implemented `Decimal.UnmarshalJSON`, `Decimal.MarshalJSON`, `Decimal.UnmarshalBSONValue`, `Decimal.MarshalBSONValue`. + ## [0.1.34] - 2024-12-27 ### Added diff --git a/decimal.go b/decimal.go index eb0c833..e5c5aa8 100644 --- a/decimal.go +++ b/decimal.go @@ -122,14 +122,18 @@ func overflowError(gotPrec, gotScale, wantScale int) error { } } -func unknownOverflowError(wantScale int) error { - maxDigits := MaxPrec - wantScale - switch wantScale { - case 0: - return fmt.Errorf("%w: the integer part of a %T can have at most %v digits, but it has significantly more digits", errDecimalOverflow, Decimal{}, maxDigits) - default: - return fmt.Errorf("%w: with %v significant digits after the decimal point, the integer part of a %T can have at most %v digits, but it has significantly more digits", errDecimalOverflow, wantScale, Decimal{}, maxDigits) +func unknownOverflowError() error { + return fmt.Errorf("%w: the integer part of a %T can have at most %v digits, but it has significantly more digits", errDecimalOverflow, Decimal{}, MaxPrec) +} + +// MustNew is like [New] but panics if the decimal cannot be constructed. +// It simplifies safe initialization of global variables holding decimals. +func MustNew(value int64, scale int) Decimal { + d, err := New(value, scale) + if err != nil { + panic(fmt.Sprintf("New(%v, %v) failed: %v", value, scale, err)) } + return d } // New returns a decimal equal to value / 10^scale. @@ -153,16 +157,6 @@ func New(value int64, scale int) (Decimal, error) { return newSafe(neg, coef, scale) } -// MustNew is like [New] but panics if the decimal cannot be constructed. -// It simplifies safe initialization of global variables holding decimals. -func MustNew(value int64, scale int) Decimal { - d, err := New(value, scale) - if err != nil { - panic(fmt.Sprintf("New(%v, %v) failed: %v", value, scale, err)) - } - return d -} - // NewFromInt64 converts a pair of integers, representing the whole and // fractional parts, to a (possibly rounded) decimal equal to whole + frac / 10^scale. // NewFromInt64 removes all trailing zeros from the fractional part. @@ -179,7 +173,7 @@ func NewFromInt64(whole, frac int64, scale int) (Decimal, error) { // Whole d, err := New(whole, 0) if err != nil { - return Decimal{}, fmt.Errorf("converting integers: %w", err) + return Decimal{}, fmt.Errorf("converting integers: %w", err) // should never happen } // Fraction f, err := New(frac, scale) @@ -196,12 +190,62 @@ func NewFromInt64(whole, frac int64, scale int) (Decimal, error) { f = f.Trim(0) d, err = d.Add(f) if err != nil { - return Decimal{}, fmt.Errorf("converting integers: %w", err) + return Decimal{}, fmt.Errorf("converting integers: %w", err) // should never happen } } return d, nil } +// Int64 returns a pair of integers representing the whole and +// (possibly rounded) fractional parts of the decimal. +// If given scale is greater than the scale of the decimal, then the fractional part +// is zero-padded to the right. +// If given scale is smaller than the scale of the decimal, then the fractional part +// is rounded using [rounding half to even] (banker's rounding). +// The relationship between the decimal and the returned values can be expressed +// as d = whole + frac / 10^scale. +// This method is useful for converting amounts to [protobuf] format. +// See also constructor [NewFromInt64]. +// +// If the result cannot be represented as a pair of int64 values, +// then false is returned. +// +// [rounding half to even]: https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_even +// [protobuf]: https://github.com/googleapis/googleapis/blob/master/google/type/money.proto +func (d Decimal) Int64(scale int) (whole, frac int64, ok bool) { + if scale < MinScale || scale > MaxScale { + return 0, 0, false + } + x := d.coef + y := pow10[d.Scale()] + if scale < d.Scale() { + x = x.rshHalfEven(d.Scale() - scale) + y = pow10[scale] + } + q, r, ok := x.quoRem(y) + if !ok { + return 0, 0, false // Should never happen + } + if scale > d.Scale() { + r, ok = r.lsh(scale - d.Scale()) + if !ok { + return 0, 0, false // Should never happen + } + } + if d.IsNeg() { + if q > -math.MinInt64 || r > -math.MinInt64 { + return 0, 0, false + } + //nolint:gosec + return -int64(q), -int64(r), true + } + if q > math.MaxInt64 || r > math.MaxInt64 { + return 0, 0, false + } + //nolint:gosec + return int64(q), int64(r), true +} + // NewFromFloat64 converts a float to a (possibly rounded) decimal. // See also method [Decimal.Float64]. // @@ -222,24 +266,31 @@ func NewFromFloat64(f float64) (Decimal, error) { return d, nil } -// Zero returns a decimal with a value of 0, having the same scale as decimal d. -// See also methods [Decimal.One], [Decimal.ULP]. -func (d Decimal) Zero() Decimal { - return newUnsafe(false, 0, d.Scale()) -} - -// One returns a decimal with a value of 1, having the same scale as decimal d. -// See also methods [Decimal.Zero], [Decimal.ULP]. -func (d Decimal) One() Decimal { - return newUnsafe(false, pow10[d.Scale()], d.Scale()) +// Float64 returns the nearest binary floating-point number rounded +// using [rounding half to even] (banker's rounding). +// See also constructor [NewFromFloat64]. +// +// This conversion may lose data, as float64 has a smaller precision +// than the decimal type. +// +// [rounding half to even]: https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_even +func (d Decimal) Float64() (f float64, ok bool) { + s := d.String() + f, err := strconv.ParseFloat(s, 64) + if err != nil { + return 0, false + } + return f, true } -// ULP (Unit in the Last Place) returns the smallest representable positive -// difference between two decimals with the same scale as decimal d. -// It can be useful for implementing rounding and comparison algorithms. -// See also methods [Decimal.Zero], [Decimal.One]. -func (d Decimal) ULP() Decimal { - return newUnsafe(false, 1, d.Scale()) +// MustParse is like [Parse] but panics if the string cannot be parsed. +// It simplifies safe initialization of global variables holding decimals. +func MustParse(s string) Decimal { + d, err := Parse(s) + if err != nil { + panic(fmt.Sprintf("Parse(%q) failed: %v", s, err)) + } + return d } // Parse converts a string to a (possibly rounded) decimal. @@ -375,11 +426,12 @@ func parseBint(s string, minScale int) (Decimal, error) { // Coefficient bcoef := getBint() defer putBint(bcoef) - bcoef.setFint(0) var fcoef fint var shift, scale int var hasCoef, ok bool + bcoef.setFint(0) + // Algorithm: // 1. Add as many digits as possible to the uint64 coefficient (fast). // 2. Once the uint64 coefficient has reached its maximum value, @@ -469,16 +521,6 @@ func parseBint(s string, minScale int) (Decimal, error) { return newFromBint(neg, bcoef, scale, minScale) } -// MustParse is like [Parse] but panics if the string cannot be parsed. -// It simplifies safe initialization of global variables holding decimals. -func MustParse(s string) Decimal { - d, err := Parse(s) - if err != nil { - panic(fmt.Sprintf("Parse(%q) failed: %v", s, err)) - } - return d -} - // String implements the [fmt.Stringer] interface and returns // a string representation of the decimal. // The returned string does not use scientific or engineering notation and is @@ -530,74 +572,42 @@ func (d Decimal) String() string { return string(buf[pos+1:]) } -// Float64 returns the nearest binary floating-point number rounded -// using [rounding half to even] (banker's rounding). -// See also constructor [NewFromFloat64]. -// -// This conversion may lose data, as float64 has a smaller precision -// than the decimal type. +// UnmarshalJSON implements the [json.Unmarshaler] interface. +// UnmarshalJSON supports the following JSON types: number and numeric string. +// See also constructor [Parse]. // -// [rounding half to even]: https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_even -func (d Decimal) Float64() (f float64, ok bool) { - s := d.String() - f, err := strconv.ParseFloat(s, 64) +// [json.Unmarshaler]: https://pkg.go.dev/encoding/json#Unmarshaler +func (d *Decimal) UnmarshalJSON(data []byte) error { + if string(data) == "null" { + return nil + } + if len(data) >= 2 && data[0] == '"' && data[len(data)-1] == '"' { + data = data[1 : len(data)-1] + } + var err error + *d, err = Parse(string(data)) if err != nil { - return 0, false + return fmt.Errorf("unmarshaling %T: %w", Decimal{}, err) } - return f, true + return nil } -// Int64 returns a pair of integers representing the whole and -// (possibly rounded) fractional parts of the decimal. -// If given scale is greater than the scale of the decimal, then the fractional part -// is zero-padded to the right. -// If given scale is smaller than the scale of the decimal, then the fractional part -// is rounded using [rounding half to even] (banker's rounding). -// The relationship between the decimal and the returned values can be expressed -// as d = whole + frac / 10^scale. -// This method is useful for converting amounts to [protobuf] format. -// See also constructor [NewFromInt64]. -// -// If the result cannot be represented as a pair of int64 values, -// then false is returned. +// MarshalJSON implements the [json.Marshaler] interface. +// MarshalJSON always returns a numeric string. +// See also method [Decimal.String]. // -// [rounding half to even]: https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_even -// [protobuf]: https://github.com/googleapis/googleapis/blob/master/google/type/money.proto -func (d Decimal) Int64(scale int) (whole, frac int64, ok bool) { - if scale < MinScale || scale > MaxScale { - return 0, 0, false - } - x := d.coef - y := pow10[d.Scale()] - if scale < d.Scale() { - x = x.rshHalfEven(d.Scale() - scale) - y = pow10[scale] - } - q, r, ok := x.quoRem(y) - if !ok { - return 0, 0, false // Should never happen - } - if scale > d.Scale() { - r, ok = r.lsh(scale - d.Scale()) - if !ok { - return 0, 0, false // Should never happen - } - } - if d.IsNeg() { - if q > -math.MinInt64 || r > -math.MinInt64 { - return 0, 0, false - } - //nolint:gosec - return -int64(q), -int64(r), true - } - if q > math.MaxInt64 || r > math.MaxInt64 { - return 0, 0, false - } - //nolint:gosec - return int64(q), int64(r), true +// [json.Marshaler]: https://pkg.go.dev/encoding/json#Marshaler +func (d Decimal) MarshalJSON() ([]byte, error) { + s := d.String() + b := make([]byte, 0, len(s)+2) + b = append(b, '"') + b = append(b, s...) + b = append(b, '"') + return b, nil } // UnmarshalText implements the [encoding.TextUnmarshaler] interface. +// UnmarshalBinary supports only numeric strings. // See also constructor [Parse]. // // [encoding.TextUnmarshaler]: https://pkg.go.dev/encoding#TextUnmarshaler @@ -605,12 +615,13 @@ func (d *Decimal) UnmarshalText(text []byte) error { var err error *d, err = Parse(string(text)) if err != nil { - return fmt.Errorf("unmarshaling %T: %w", d, err) + return fmt.Errorf("unmarshaling %T: %w", Decimal{}, err) } return nil } // MarshalText implements the [encoding.TextMarshaler] interface. +// MarshalText always returns a numeric string. // See also method [Decimal.String]. // // [encoding.TextMarshaler]: https://pkg.go.dev/encoding#TextMarshaler @@ -619,6 +630,7 @@ func (d Decimal) MarshalText() ([]byte, error) { } // UnmarshalBinary implements the [encoding.BinaryUnmarshaler] interface. +// UnmarshalBinary supports only numeric strings. // See also constructor [Parse]. // // [encoding.BinaryUnmarshaler]: https://pkg.go.dev/encoding#BinaryUnmarshaler @@ -626,12 +638,13 @@ func (d *Decimal) UnmarshalBinary(data []byte) error { var err error *d, err = Parse(string(data)) if err != nil { - return fmt.Errorf("unmarshaling %T: %w", d, err) + return fmt.Errorf("unmarshaling %T: %w", Decimal{}, err) } return nil } // MarshalBinary implements the [encoding.BinaryMarshaler] interface. +// MarshalBinary always returns a numeric string. // See also method [Decimal.String]. // // [encoding.BinaryMarshaler]: https://pkg.go.dev/encoding#BinaryMarshaler @@ -639,8 +652,196 @@ func (d Decimal) MarshalBinary() ([]byte, error) { return []byte(d.String()), nil } +// UnmarshalBSONValue implements the v2 [bson.ValueUnmarshaler] interface. +// UnmarshalBSONValue supports the following [BSON types]: double, string, int32, int64, and decimal128. +// +// [bson.ValueUnmarshaler]: https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/bson#ValueUnmarshaler +// [BSON types]: https://bsonspec.org/spec.html +func (d *Decimal) UnmarshalBSONValue(typ byte, data []byte) error { + // constants are from https://bsonspec.org/spec.html + var err error + switch typ { + case 1: + *d, err = parseBSONFloat64(data) + case 2: + *d, err = parseBSONString(data) + case 10: + // null, do nothing + case 16: + *d, err = parseBSONInt32(data) + case 18: + *d, err = parseBSONInt64(data) + case 19: + *d, err = parseIEEEDecimal128(data) + default: + err = fmt.Errorf("BSON type %d is not supported", typ) + } + if err != nil { + err = fmt.Errorf("converting from BSON type %d to %T: %w", typ, Decimal{}, err) + } + return err +} + +// MarshalBSONValue implements the v2 [bson.ValueMarshaler] interface. +// MarshalBSONValue always returns [decimal128]. +// +// [bson.ValueMarshaler]: https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/bson#ValueMarshaler +// [decimal128]: https://bsonspec.org/spec.html +func (d Decimal) MarshalBSONValue() (typ byte, data []byte, err error) { + return 19, d.ieeeDecimal128(), nil +} + +// parseBSONInt32 parses a BSON int32 to a decimal. +func parseBSONInt32(data []byte) (Decimal, error) { + if len(data) != 4 { + return Decimal{}, fmt.Errorf("%w: invalid data length %v", errInvalidDecimal, len(data)) + } + u := uint32(data[0]) + u |= uint32(data[1]) << 8 + u |= uint32(data[2]) << 16 + u |= uint32(data[3]) << 24 + i := int64(int32(u)) //nolint:gosec + return New(i, 0) +} + +// parseBSONInt64 parses a BSON int64 to a decimal. +// The byte order of the input data must be little-endian. +func parseBSONInt64(data []byte) (Decimal, error) { + if len(data) != 8 { + return Decimal{}, fmt.Errorf("%w: invalid data length %v", errInvalidDecimal, len(data)) + } + u := uint64(data[0]) + u |= uint64(data[1]) << 8 + u |= uint64(data[2]) << 16 + u |= uint64(data[3]) << 24 + u |= uint64(data[4]) << 32 + u |= uint64(data[5]) << 40 + u |= uint64(data[6]) << 48 + u |= uint64(data[7]) << 56 + i := int64(u) //nolint:gosec + return New(i, 0) +} + +// parseBSONFloat64 parses a BSON float64 to a (possibly rounded) decimal. +// The byte order of the input data must be little-endian. +func parseBSONFloat64(data []byte) (Decimal, error) { + if len(data) != 8 { + return Decimal{}, fmt.Errorf("%w: invalid data length %v", errInvalidDecimal, len(data)) + } + u := uint64(data[0]) + u |= uint64(data[1]) << 8 + u |= uint64(data[2]) << 16 + u |= uint64(data[3]) << 24 + u |= uint64(data[4]) << 32 + u |= uint64(data[5]) << 40 + u |= uint64(data[6]) << 48 + u |= uint64(data[7]) << 56 + f := math.Float64frombits(u) + return NewFromFloat64(f) +} + +// parseBSONString parses a BSON string to a (possibly rounded) decimal. +// The byte order of the input data must be little-endian. +func parseBSONString(data []byte) (Decimal, error) { + if len(data) < 4 { + return Decimal{}, fmt.Errorf("%w: invalid data length %v", errInvalidDecimal, len(data)) + } + u := uint32(data[0]) + u |= uint32(data[1]) << 8 + u |= uint32(data[2]) << 16 + u |= uint32(data[3]) << 24 + l := int(int32(u)) //nolint:gosec + if l < 1 || l > 330 || len(data) < l+4 { + return Decimal{}, fmt.Errorf("%w: invalid string length %v", errInvalidDecimal, l) + } + if data[l+4-1] != 0 { + return Decimal{}, fmt.Errorf("%w: invalid null terminator %v", errInvalidDecimal, data[l+4-1]) + } + s := string(data[4 : l+4-1]) + return Parse(s) +} + +// parseIEEEDecimal128 converts a 128-bit IEEE 754-2008 decimal +// floating point with binary integer decimal encoding to +// a (possibly rounded) decimal. +// The byte order of the input data must be little-endian. +// +// parseIEEEDecimal128 returns an error if: +// - the data length is not equal to 16 bytes; +// - the decimal a special value (NaN or Inf); +// - the integer part of the result has more than [MaxPrec] digits. +func parseIEEEDecimal128(data []byte) (Decimal, error) { + if len(data) != 16 { + return Decimal{}, fmt.Errorf("%w: invalid data length %v", errInvalidDecimal, len(data)) + } + if data[15]&0b0111_1100 == 0b0111_1100 { + return Decimal{}, fmt.Errorf("%w: special value NaN", errInvalidDecimal) + } + if data[15]&0b0111_1100 == 0b0111_1000 { + return Decimal{}, fmt.Errorf("%w: special value Inf", errInvalidDecimal) + } + if data[15]&0b0110_0000 == 0b0110_0000 { + return Decimal{}, fmt.Errorf("%w: unsupported encoding", errInvalidDecimal) + } + + // Sign + neg := data[15]&0b1000_0000 == 0b1000_0000 + + // Scale + var scale int + scale |= int(data[14]) >> 1 + scale |= int(data[15]&0b0111_1111) << 7 + scale = 6176 - scale + + // TODO fint optimization + + // Coefficient + coef := getBint() + defer putBint(coef) + + buf := make([]byte, 15) + for i := range 15 { + buf[i] = data[14-i] + } + buf[0] &= 0b0000_0001 + coef.setBytes(buf) + + // Scale normalization + if coef.sign() == 0 { + scale = max(scale, MinScale) + } + + return newFromBint(neg, coef, scale, 0) +} + +// ieeeDecimal128 returns a 128-bit IEEE 754-2008 decimal +// floating point with binary integer decimal encoding. +// The byte order of the result is little-endian. +func (d Decimal) ieeeDecimal128() []byte { + var buf [16]byte + scale := d.Scale() + coef := d.Coef() + + // Sign + if d.IsNeg() { + buf[15] = 0b1000_0000 + } + + // Scale + scale = 6176 - scale + buf[15] |= byte((scale >> 7) & 0b0111_1111) + buf[14] |= byte((scale << 1) & 0b1111_1110) + + // Coefficient + for i := range 8 { + buf[i] = byte(coef & 0b1111_1111) + coef >>= 8 + } + + return buf[:] +} + // Scan implements the [sql.Scanner] interface. -// See also constructor [Parse]. // // [sql.Scanner]: https://pkg.go.dev/database/sql#Scanner func (d *Decimal) Scan(value any) error { @@ -648,22 +849,31 @@ func (d *Decimal) Scan(value any) error { switch value := value.(type) { case string: *d, err = Parse(value) - case []byte: - *d, err = Parse(string(value)) case int64: *d, err = New(value, 0) case float64: *d, err = NewFromFloat64(value) + case []byte: + // Special case: MySQL driver sends DECIMAL as []byte + *d, err = Parse(string(value)) + case float32: + // Special case: MySQL driver sends FLOAT as float32 + *d, err = NewFromFloat64(float64(value)) + case uint64: + // Special case: ClickHouse driver sends 0 as uint64 + *d, err = newSafe(false, fint(value), 0) case nil: - err = fmt.Errorf("converting to %T: nil is not supported", d) + err = fmt.Errorf("%T does not support null values, use %T or *%T", Decimal{}, NullDecimal{}, Decimal{}) default: - err = fmt.Errorf("converting from %T to %T: type %T is not supported", value, d, value) + err = fmt.Errorf("type %T is not supported", value) + } + if err != nil { + err = fmt.Errorf("converting from %T to %T: %w", value, Decimal{}, err) } return err } // Value implements the [driver.Valuer] interface. -// See also method [Decimal.String]. // // [driver.Valuer]: https://pkg.go.dev/database/sql/driver#Valuer func (d Decimal) Value() (driver.Value, error) { @@ -863,6 +1073,26 @@ func (d Decimal) Format(state fmt.State, verb rune) { } } +// Zero returns a decimal with a value of 0, having the same scale as decimal d. +// See also methods [Decimal.One], [Decimal.ULP]. +func (d Decimal) Zero() Decimal { + return newUnsafe(false, 0, d.Scale()) +} + +// One returns a decimal with a value of 1, having the same scale as decimal d. +// See also methods [Decimal.Zero], [Decimal.ULP]. +func (d Decimal) One() Decimal { + return newUnsafe(false, pow10[d.Scale()], d.Scale()) +} + +// ULP (Unit in the Last Place) returns the smallest representable positive +// difference between two decimals with the same scale as decimal d. +// It can be useful for implementing rounding and comparison algorithms. +// See also methods [Decimal.Zero], [Decimal.One]. +func (d Decimal) ULP() Decimal { + return newUnsafe(false, 1, d.Scale()) +} + // Prec returns the number of digits in the coefficient. // See also method [Decimal.Coef]. func (d Decimal) Prec() int { @@ -896,7 +1126,7 @@ func (d Decimal) MinScale() int { // IsInt returns true if there are no significant digits after the decimal point. func (d Decimal) IsInt() bool { - return d.coef%pow10[d.Scale()] == 0 + return d.Scale() == 0 || d.coef%pow10[d.Scale()] == 0 } // IsOne returns: @@ -1164,13 +1394,14 @@ func prodFint(d ...Decimal) (Decimal, error) { func prodBint(d ...Decimal) (Decimal, error) { ecoef := getBint() defer putBint(ecoef) - ecoef.setFint(One.coef) - escale := One.Scale() - eneg := One.IsNeg() fcoef := getBint() defer putBint(fcoef) + ecoef.setFint(One.coef) + escale := One.Scale() + eneg := One.IsNeg() + for _, f := range d { fcoef.setFint(f.coef) @@ -1181,10 +1412,14 @@ func prodBint(d ...Decimal) (Decimal, error) { // Intermediate truncation if escale > bscale { - shift := escale - bscale - ecoef.rshDown(ecoef, shift) + ecoef.rshDown(ecoef, escale-bscale) escale = bscale } + + // Check if e >= 10^59 + if ecoef.hasPrec(len(bpow10)) { + return Decimal{}, unknownOverflowError() + } } return newFromBint(eneg, ecoef, escale, 0) @@ -1289,15 +1524,16 @@ func meanFint(d ...Decimal) (Decimal, error) { func meanBint(d ...Decimal) (Decimal, error) { ecoef := getBint() defer putBint(ecoef) - ecoef.setFint(Zero.coef) - escale := Zero.Scale() - eneg := Zero.IsNeg() fcoef := getBint() defer putBint(fcoef) ncoef := getBint() defer putBint(ncoef) + + ecoef.setFint(Zero.coef) + escale := Zero.Scale() + eneg := Zero.IsNeg() ncoef.setInt64(int64(len(d))) for _, f := range d { @@ -1385,12 +1621,13 @@ func (d Decimal) mulFint(e Decimal, minScale int) (Decimal, error) { func (d Decimal) mulBint(e Decimal, minScale int) (Decimal, error) { dcoef := getBint() defer putBint(dcoef) - dcoef.setFint(d.coef) - dscale := d.Scale() - dneg := d.IsNeg() ecoef := getBint() defer putBint(ecoef) + + dcoef.setFint(d.coef) + dscale := d.Scale() + dneg := d.IsNeg() ecoef.setFint(e.coef) // Compute d = d * e @@ -1404,7 +1641,7 @@ func (d Decimal) mulBint(e Decimal, minScale int) (Decimal, error) { // Pow returns the (possibly rounded) decimal raised to the given decimal power. // If zero is raised to zero power then the result is one. // -// PowInt returns an error if: +// Pow returns an error if: // - the integer part of the result has more than [MaxPrec] digits; // - zero is raised to a negative power; // - negative is raised to a fractional power. @@ -1416,7 +1653,7 @@ func (d Decimal) Pow(e Decimal) (Decimal, error) { // Special case: integer power if e.IsInt() { - power := e.Trim(0).Coef() + power := e.Trunc(0).Coef() f, err := d.powIntFint(power, e.IsNeg()) if err != nil { f, err = d.powIntBint(power, e.IsNeg()) @@ -1487,7 +1724,7 @@ func (d Decimal) powBint(e Decimal) (Decimal, error) { // Check if f <= -100 or f >= 100 if fcoef.hasPrec(3 + bscale) { if !inv { - return Decimal{}, unknownOverflowError(0) + return Decimal{}, unknownOverflowError() } return newSafe(false, 0, MaxScale) } @@ -1596,12 +1833,14 @@ func (d Decimal) powIntFint(pow uint64, inv bool) (Decimal, error) { func (d Decimal) powIntBint(pow uint64, inv bool) (Decimal, error) { dcoef := getBint() defer putBint(dcoef) + + ecoef := getBint() + defer putBint(ecoef) + dcoef.setFint(d.coef) dneg := d.IsNeg() dscale := d.Scale() - ecoef := getBint() - defer putBint(ecoef) ecoef.setFint(One.coef) eneg := One.IsNeg() escale := One.Scale() @@ -1618,15 +1857,14 @@ func (d Decimal) powIntBint(pow uint64, inv bool) (Decimal, error) { // Intermediate truncation if escale > bscale { - shift := escale - bscale - ecoef.rshDown(ecoef, shift) + ecoef.rshDown(ecoef, escale-bscale) escale = bscale } - // Check if e <= -10^60 or e >= 10^60 + // Check if e <= -10^59 or e >= 10^59 if ecoef.hasPrec(len(bpow10)) { if !inv { - return Decimal{}, unknownOverflowError(0) + return Decimal{}, unknownOverflowError() } return newSafe(false, 0, MaxScale) } @@ -1641,15 +1879,14 @@ func (d Decimal) powIntBint(pow uint64, inv bool) (Decimal, error) { // Intermediate truncation if dscale > bscale { - shift := dscale - bscale - dcoef.rshDown(dcoef, shift) + dcoef.rshDown(dcoef, dscale-bscale) dscale = bscale } - // Check if d <= -10^60 or d >= 10^60 + // Check if d <= -10^59 or d >= 10^59 if dcoef.hasPrec(len(bpow10)) { if !inv { - return Decimal{}, unknownOverflowError(0) + return Decimal{}, unknownOverflowError() } return newSafe(false, 0, MaxScale) } @@ -1658,7 +1895,7 @@ func (d Decimal) powIntBint(pow uint64, inv bool) (Decimal, error) { if inv { if ecoef.sign() == 0 { - return Decimal{}, unknownOverflowError(0) + return Decimal{}, unknownOverflowError() } // Compute e = ⌊1 / eāŒ‹ @@ -1669,7 +1906,7 @@ func (d Decimal) powIntBint(pow uint64, inv bool) (Decimal, error) { return newFromBint(eneg, ecoef, escale, 0) } -// Sqrt computes the square root of a decimal. +// Sqrt computes the (possibly rounded) square root of a decimal. // d.Sqrt() is significantly faster than d.Pow(0.5). // // Sqrt returns an error if the decimal is negative. @@ -1754,9 +1991,9 @@ func (d Decimal) Log2() (Decimal, error) { // Preferred scale if e.IsInt() { - // This is workaround, according to the GDA - // we should only trim if d is an integer power of 2. - e = e.Trim(0) + // According to the GDA, only integer powers of 2 should be trimmed to zero scale. + // However, such validation is slow, so we will trim all integers. + e = e.Trunc(0) } return e, nil @@ -1814,9 +2051,9 @@ func (d Decimal) Log10() (Decimal, error) { // Preferred scale if e.IsInt() { - // This is workaround, according to the GDA - // we should only trim if d is an integer power of 10. - e = e.Trim(0) + // According to the GDA, only integer powers of 10 should be trimmed to zero scale. + // However, such validation is slow, so we will trim all integers. + e = e.Trunc(0) } return e, nil @@ -1866,11 +2103,6 @@ func (d Decimal) Log() (Decimal, error) { return newSafe(false, 0, 0) } - // Special case: Euler's number - if d == E { - return newSafe(false, 1000000000000000000, 18) - } - // General case e, err := d.logBint() if err != nil { @@ -1963,7 +2195,7 @@ func (d Decimal) Exp() (Decimal, error) { // Special case: overflow if d.CmpAbs(Hundred) >= 0 { if !d.IsNeg() { - return Decimal{}, unknownOverflowError(0) + return Decimal{}, unknownOverflowError() } return newSafe(false, 0, MaxScale) } @@ -1995,7 +2227,7 @@ func (d Decimal) expBint() (Decimal, error) { if d.IsNeg() { if ecoef.sign() == 0 { - return Decimal{}, unknownOverflowError(0) + return Decimal{}, unknownOverflowError() } // Compute e = ⌊1 / eāŒ‹ ecoef.quo(bpow10[2*bscale], ecoef) @@ -2127,13 +2359,14 @@ func sumFint(d ...Decimal) (Decimal, error) { func sumBint(d ...Decimal) (Decimal, error) { ecoef := getBint() defer putBint(ecoef) - ecoef.setFint(Zero.coef) - escale := Zero.Scale() - eneg := Zero.IsNeg() fcoef := getBint() defer putBint(fcoef) + ecoef.setFint(Zero.coef) + escale := Zero.Scale() + eneg := Zero.IsNeg() + for _, f := range d { fcoef.setFint(f.coef) @@ -2260,13 +2493,14 @@ func (d Decimal) addFint(e Decimal, minScale int) (Decimal, error) { func (d Decimal) addBint(e Decimal, minScale int) (Decimal, error) { dcoef := getBint() defer putBint(dcoef) - dcoef.setFint(d.coef) - dscale := d.Scale() - dneg := d.IsNeg() ecoef := getBint() defer putBint(ecoef) + + dcoef.setFint(d.coef) + dscale := d.Scale() ecoef.setFint(e.coef) + dneg := d.IsNeg() // Alignment switch { @@ -2401,18 +2635,19 @@ func (d Decimal) addMulFint(e, f Decimal, minScale int) (Decimal, error) { func (d Decimal) addMulBint(e, f Decimal, minScale int) (Decimal, error) { dcoef := getBint() defer putBint(dcoef) - dcoef.setFint(d.coef) - dscale := d.Scale() - dneg := d.IsNeg() ecoef := getBint() defer putBint(ecoef) - ecoef.setFint(e.coef) - escale := e.Scale() - eneg := e.IsNeg() fcoef := getBint() defer putBint(fcoef) + + dcoef.setFint(d.coef) + dscale := d.Scale() + dneg := d.IsNeg() + ecoef.setFint(e.coef) + escale := e.Scale() + eneg := e.IsNeg() fcoef.setFint(f.coef) // Compute e = e * f @@ -2585,16 +2820,17 @@ func (d Decimal) addQuoFint(e, f Decimal, minScale int) (Decimal, error) { func (d Decimal) addQuoBint(e, f Decimal, minScale int) (Decimal, error) { dcoef := getBint() defer putBint(dcoef) - dcoef.setFint(d.coef) - dneg := d.IsNeg() ecoef := getBint() defer putBint(ecoef) - ecoef.setFint(e.coef) - eneg := e.IsNeg() fcoef := getBint() defer putBint(fcoef) + + dcoef.setFint(d.coef) + dneg := d.IsNeg() + ecoef.setFint(e.coef) + eneg := e.IsNeg() fcoef.setFint(f.coef) // Alignment @@ -2716,11 +2952,12 @@ func (d Decimal) quoFint(e Decimal, minScale int) (Decimal, error) { func (d Decimal) quoBint(e Decimal, minScale int) (Decimal, error) { dcoef := getBint() defer putBint(dcoef) - dcoef.setFint(d.coef) - dneg := d.IsNeg() ecoef := getBint() defer putBint(ecoef) + + dcoef.setFint(d.coef) + dneg := d.IsNeg() ecoef.setFint(e.coef) // Alignment @@ -2803,17 +3040,18 @@ func (d Decimal) quoRemFint(e Decimal) (q, r Decimal, err error) { func (d Decimal) quoRemBint(e Decimal) (q, r Decimal, err error) { dcoef := getBint() defer putBint(dcoef) - dcoef.setFint(d.coef) ecoef := getBint() defer putBint(ecoef) - ecoef.setFint(e.coef) qcoef := getBint() defer putBint(qcoef) rcoef := getBint() defer putBint(rcoef) + + dcoef.setFint(d.coef) + ecoef.setFint(e.coef) rscale := d.Scale() // Alignment @@ -3003,10 +3241,11 @@ func (d Decimal) cmpFint(e Decimal) (int, error) { func (d Decimal) cmpBint(e Decimal) int { dcoef := getBint() defer putBint(dcoef) - dcoef.setFint(d.coef) ecoef := getBint() defer putBint(ecoef) + + dcoef.setFint(d.coef) ecoef.setFint(e.coef) // Alignment @@ -3036,7 +3275,7 @@ type NullDecimal struct { } // Scan implements the [sql.Scanner] interface. -// See also constructor [Parse]. +// See also method [Decimal.Scan]. // // [sql.Scanner]: https://pkg.go.dev/database/sql#Scanner func (n *NullDecimal) Scan(value any) error { @@ -3050,7 +3289,7 @@ func (n *NullDecimal) Scan(value any) error { } // Value implements the [driver.Valuer] interface. -// See also method [Decimal.String]. +// See also method [Decimal.Value]. // // [driver.Valuer]: https://pkg.go.dev/database/sql/driver#Valuer func (n NullDecimal) Value() (driver.Value, error) { @@ -3059,3 +3298,59 @@ func (n NullDecimal) Value() (driver.Value, error) { } return n.Decimal.Value() } + +// UnmarshalJSON implements the [json.Unmarshaler] interface. +// See also method [Decimal.UnmarshalJSON]. +// +// [json.Unmarshaler]: https://pkg.go.dev/encoding/json#Unmarshaler +func (n *NullDecimal) UnmarshalJSON(data []byte) error { + if string(data) == "null" { + n.Decimal = Decimal{} + n.Valid = false + return nil + } + n.Valid = true + return n.Decimal.UnmarshalJSON(data) +} + +// MarshalJSON implements the [json.Marshaler] interface. +// See also method [Decimal.MarshalJSON]. +// +// [json.Marshaler]: https://pkg.go.dev/encoding/json#Marshaler +func (n NullDecimal) MarshalJSON() ([]byte, error) { + if !n.Valid { + return []byte("null"), nil + } + return n.Decimal.MarshalJSON() +} + +// UnmarshalBSONValue implements the v2 [bson.ValueUnmarshaler] interface. +// UnmarshalBSONValue supports the following [BSON types]: double, string, null, int32, int64, and decimal128. +// See also method [Decimal.UnmarshalBSONValue]. +// +// [bson.ValueUnmarshaler]: https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/bson#ValueUnmarshaler +// [BSON types]: https://bsonspec.org/spec.html +func (n *NullDecimal) UnmarshalBSONValue(typ byte, data []byte) error { + // constants are from https://bsonspec.org/spec.html + if typ == 10 { + n.Decimal = Decimal{} + n.Valid = false + return nil + } + n.Valid = true + return n.Decimal.UnmarshalBSONValue(typ, data) +} + +// MarshalBSONValue implements the v2 [bson.ValueMarshaler] interface. +// MarshalBSONValue always returns the following [BSON types]: decimal128 or null. +// See also method [Decimal.MarshalBSONValue]. +// +// [bson.ValueMarshaler]: https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/bson#ValueMarshaler +// [BSON types]: https://bsonspec.org/spec.html +func (n NullDecimal) MarshalBSONValue() (typ byte, data []byte, err error) { + // constants are from https://bsonspec.org/spec.html + if !n.Valid { + return 10, nil, nil + } + return n.Decimal.MarshalBSONValue() +} diff --git a/decimal_test.go b/decimal_test.go index e77cda5..f8f4376 100644 --- a/decimal_test.go +++ b/decimal_test.go @@ -1,9 +1,11 @@ package decimal import ( + "bytes" "database/sql" "database/sql/driver" "encoding" + "encoding/json" "errors" "fmt" "math" @@ -41,6 +43,10 @@ func TestDecimal_Interfaces(t *testing.T) { if !ok { t.Errorf("%T does not implement fmt.Formatter", d) } + _, ok = d.(json.Marshaler) + if !ok { + t.Errorf("%T does not implement json.Marshaler", d) + } _, ok = d.(encoding.TextMarshaler) if !ok { t.Errorf("%T does not implement encoding.TextMarshaler", d) @@ -55,6 +61,10 @@ func TestDecimal_Interfaces(t *testing.T) { } d = &Decimal{} + _, ok = d.(json.Unmarshaler) + if !ok { + t.Errorf("%T does not implement json.Unmarshaler", d) + } _, ok = d.(encoding.TextUnmarshaler) if !ok { t.Errorf("%T does not implement encoding.TextUnmarshaler", d) @@ -347,11 +357,11 @@ func TestParse(t *testing.T) { {"0.9999999999999999999", false, 9999999999999999999, 19}, // Rounding + {"-999999999999999999.99", true, 1000000000000000000, 0}, {"0.00000000000000000000000000000000000000", false, 0, 19}, {"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", false, 0, 19}, {"-0.00000000000000000000000000000000000001", false, 0, 19}, {"0.00000000000000000000000000000000000001", false, 0, 19}, - {"-999999999999999999.99", true, 1000000000000000000, 0}, {"0.123456789012345678901234567890", false, 1234567890123456789, 19}, {"0.12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678", false, 1234567890123456789, 19}, @@ -503,6 +513,737 @@ func TestMustParse(t *testing.T) { }) } +func TestDecimalUnmarshalText(t *testing.T) { + t.Run("error", func(t *testing.T) { + d := Decimal{} + err := d.UnmarshalText([]byte("1.1.1")) + if err == nil { + t.Errorf("UnmarshalText(\"1.1.1\") did not fail") + } + }) +} + +func TestDecimalUnmarshalBinary(t *testing.T) { + t.Run("error", func(t *testing.T) { + d := Decimal{} + err := d.UnmarshalBinary([]byte("1.1.1")) + if err == nil { + t.Errorf("UnmarshalBinary(\"1.1.1\") did not fail") + } + }) +} + +func TestDecimalUnmarshalJSON(t *testing.T) { + t.Run("success", func(t *testing.T) { + tests := []struct { + s string + want string + }{ + {"null", "0"}, + {"\"-9999999999999999999.0\"", "-9999999999999999999"}, + {"\"-9999999999999999999\"", "-9999999999999999999"}, + {"\"-999999999999999999.9\"", "-999999999999999999.9"}, + {"\"-99999999999999999.99\"", "-99999999999999999.99"}, + {"\"-1000000000000000000.0\"", "-1000000000000000000"}, + {"\"-0.9999999999999999999\"", "-0.9999999999999999999"}, + } + for _, tt := range tests { + var got Decimal + err := got.UnmarshalJSON([]byte(tt.s)) + if err != nil { + t.Errorf("UnmarshalJSON(%q) failed: %v", tt.s, err) + continue + } + want := MustParse(tt.want) + if got != want { + t.Errorf("UnmarshalJSON(%q) = %q, want %q", tt.s, got, want) + } + } + }) + + t.Run("error", func(t *testing.T) { + d := Decimal{} + err := d.UnmarshalJSON([]byte("\"-1.1.1\"")) + if err == nil { + t.Errorf("UnmarshalJSON(\"-1.1.1\") did not fail") + } + }) +} + +func TestDecimalUnmarshalBSONValue(t *testing.T) { + t.Run("success", func(t *testing.T) { + tests := []struct { + typ byte + data []byte + want string + }{ + {1, []byte{0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0xf0, 0x3f}, "1.0001220703125"}, + {2, []byte{0x15, 0x0, 0x0, 0x0, 0x2d, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x0}, "-9999999999999999999"}, + {10, nil, "0"}, + {16, []byte{0xff, 0xff, 0xff, 0x7f}, "2147483647"}, + {18, []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, "9223372036854775807"}, + {19, []byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "1.265"}, + } + for _, tt := range tests { + got := Decimal{} + err := got.UnmarshalBSONValue(tt.typ, tt.data) + if err != nil { + t.Errorf("UnmarshalBSONValue(%v, % x) failed: %v", tt.typ, tt.data, err) + continue + } + want := MustParse(tt.want) + if got != want { + t.Errorf("UnmarshalBSONValue(%v, % x) = %q, want %q", tt.typ, tt.data, got, want) + } + } + }) + + t.Run("error", func(t *testing.T) { + d := Decimal{} + err := d.UnmarshalBSONValue(12, nil) + if err == nil { + t.Errorf("UnmarshalBSONValue(12, nil) did not fail") + } + }) +} + +func TestParseBSONFloat64(t *testing.T) { + t.Run("success", func(t *testing.T) { + tests := []struct { + b []byte + want string + }{ + // Zero + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0"}, + + // Negative zero + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0"}, + + // Integers + {[]byte{0x2a, 0x1b, 0xf5, 0xf4, 0x10, 0x22, 0xb1, 0xc3}, "-1234567892123200000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xbf}, "-1"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x3f}, "1"}, + {[]byte{0x2a, 0x1b, 0xf5, 0xf4, 0x10, 0x22, 0xb1, 0x43}, "1234567892123200000"}, + + // Floats + {[]byte{0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0xf0, 0xbf}, "-1.0001220703125"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0xf0, 0x3f}, "1.0001220703125"}, + } + + for _, tt := range tests { + got, err := parseBSONFloat64(tt.b) + if err != nil { + t.Errorf("parseBSONFloat64(%v) failed: %v", tt.b, err) + continue + } + want := MustParse(tt.want) + if got != want { + t.Errorf("parseBSONFloat64(%v) = %q, want %q", tt.b, got, want) + } + + } + }) + + t.Run("error", func(t *testing.T) { + tests := map[string][]byte{ + "length 1": {}, + "length 2": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + "length 3": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + "nan 1": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x7f}, + "nan 2": {0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x7f}, + "inf 1": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x7f}, + "inf 2": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xff}, + } + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + _, err := parseBSONFloat64(tt) + if err == nil { + t.Errorf("parseBSONFloat64(%v) did not fail", tt) + } + }) + } + }) +} + +func TestParseBSONString(t *testing.T) { + t.Run("success", func(t *testing.T) { + tests := []struct { + b []byte + want string + }{ + {[]byte{0x15, 0x0, 0x0, 0x0, 0x2d, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x0}, "-9999999999999999999"}, + {[]byte{0x17, 0x0, 0x0, 0x0, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x0}, "-0.0000000000000000001"}, + {[]byte{0x16, 0x0, 0x0, 0x0, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0}, "0.0000000000000000000"}, + {[]byte{0x2, 0x0, 0x0, 0x0, 0x30, 0x0}, "0"}, + {[]byte{0x16, 0x0, 0x0, 0x0, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x0}, "0.0000000000000000001"}, + {[]byte{0x2, 0x0, 0x0, 0x0, 0x31, 0x0}, "1"}, + {[]byte{0x3, 0x0, 0x0, 0x0, 0x30, 0x31, 0x0}, "1"}, + {[]byte{0x15, 0x0, 0x0, 0x0, 0x33, 0x2e, 0x31, 0x34, 0x31, 0x35, 0x39, 0x32, 0x36, 0x35, 0x33, 0x35, 0x38, 0x39, 0x37, 0x39, 0x33, 0x32, 0x33, 0x38, 0x0}, "3.141592653589793238"}, + {[]byte{0x3, 0x0, 0x0, 0x0, 0x31, 0x30, 0x0}, "10"}, + {[]byte{0x14, 0x0, 0x0, 0x0, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x0}, "9999999999999999999"}, + } + for _, tt := range tests { + got, err := parseBSONString(tt.b) + if err != nil { + t.Errorf("parseBSONString(%v) failed: %v", tt.b, err) + continue + } + want := MustParse(tt.want) + if got != want { + t.Errorf("parseBSONString(%v) = %q, want %q", tt.b, got, want) + } + + } + }) + + t.Run("error", func(t *testing.T) { + tests := map[string][]byte{ + "length 1": {}, + "length 2": {0x0, 0x0, 0x0, 0x0}, + "length 3": {0x2, 0x0, 0x0, 0x0, 0x30}, + "terminator 1": {0x2, 0x0, 0x0, 0x0, 0x30, 0x30}, + } + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + _, err := parseBSONString(tt) + if err == nil { + t.Errorf("parseBSONString(%v) did not fail", tt) + } + }) + } + }) +} + +func TestParseBSONInt32(t *testing.T) { + t.Run("success", func(t *testing.T) { + tests := []struct { + b []byte + want string + }{ + {[]byte{0x0, 0x0, 0x0, 0x80}, "-2147483648"}, + {[]byte{0xff, 0xff, 0xff, 0xff}, "-1"}, + {[]byte{0x0, 0x0, 0x0, 0x0}, "0"}, + {[]byte{0x1, 0x0, 0x0, 0x0}, "1"}, + {[]byte{0xff, 0xff, 0xff, 0x7f}, "2147483647"}, + } + for _, tt := range tests { + got, err := parseBSONInt32(tt.b) + if err != nil { + t.Errorf("parseBSONInt32(%v) failed: %v", tt.b, err) + continue + } + want := MustParse(tt.want) + if got != want { + t.Errorf("parseBSONInt32(%v) = %q, want %q", tt.b, got, want) + } + + } + }) + + t.Run("error", func(t *testing.T) { + tests := map[string][]byte{ + "length 1": {}, + "length 2": {0x0, 0x0, 0x0}, + "length 3": {0x0, 0x0, 0x0, 0x0, 0x0}, + } + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + _, err := parseBSONInt32(tt) + if err == nil { + t.Errorf("parseBSONInt32(%v) did not fail", tt) + } + }) + } + }) +} + +func TestParseBSONInt64(t *testing.T) { + t.Run("success", func(t *testing.T) { + tests := []struct { + b []byte + want string + }{ + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "-9223372036854775808"}, + {[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, "-1"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0"}, + {[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "1"}, + {[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, "9223372036854775807"}, + } + for _, tt := range tests { + got, err := parseBSONInt64(tt.b) + if err != nil { + t.Errorf("parseBSONInt64(%v) failed: %v", tt.b, err) + continue + } + want := MustParse(tt.want) + if got != want { + t.Errorf("parseBSONInt64(%v) = %q, want %q", tt.b, got, want) + } + + } + }) + + t.Run("error", func(t *testing.T) { + tests := map[string][]byte{ + "length 1": {}, + "length 2": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + "length 3": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + } + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + _, err := parseBSONInt64(tt) + if err == nil { + t.Errorf("parseBSONInt64(%v) did not fail", tt) + } + }) + } + }) +} + +func TestParseIEEEDecimal128(t *testing.T) { + t.Run("success", func(t *testing.T) { + tests := []struct { + b []byte + want string + }{ + // Zeros + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7a, 0x2b}, "0.0000000000000000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x30}, "0.00000000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0x30}, "0.0000000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2e, 0x30}, "0.000000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x30}, "0.00000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0x30}, "0.0000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "0.000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0x30}, "0.00000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x30}, "0.0000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "0.000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "0.00"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}, "0.0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x30}, "0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x30}, "0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x30}, "0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48, 0x30}, "0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4a, 0x30}, "0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4c, 0x30}, "0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e, 0x30}, "0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x30}, "0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "0"}, + + // Negative zeroes + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2e, 0xb0}, "0.000000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0xb0}, "0.00000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0xb0}, "0.0000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0xb0}, "0.000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0xb0}, "0.00000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xb0}, "0.0000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0xb0}, "0.000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0xb0}, "0.00"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xb0}, "0.0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0xb0}, "0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0xb0}, "0"}, + + // Overflows with 0 coefficient + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x5f}, "0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, "0"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0xdf}, "0"}, + + // Underflows + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0a, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0x0, 0x0}, "0.0000000000000000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x0a, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0x0, 0x80}, "0.0000000000000000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x81, 0xef, 0xac, 0x85, 0x5b, 0x41, 0x6d, 0x2d, 0xee, 0x04, 0x0, 0x0}, "0.0000000000000000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x81, 0xef, 0xac, 0x85, 0x5b, 0x41, 0x6d, 0x2d, 0xee, 0x04, 0x0, 0x0}, "0.0000000000000000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x81, 0xef, 0xac, 0x85, 0x5b, 0x41, 0x6d, 0x2d, 0xee, 0x04, 0x0, 0x80}, "0.0000000000000000000"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x81, 0xef, 0xac, 0x85, 0x5b, 0x41, 0x6d, 0x2d, 0xee, 0x04, 0x0, 0x80}, "0.0000000000000000000"}, + {[]byte{0x0, 0x0, 0x20, 0x3b, 0x9d, 0xb5, 0x05, 0x6f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24}, "0.0000000000000000000"}, + {[]byte{0x0, 0x0, 0xfe, 0xd8, 0x3f, 0x4e, 0x7c, 0x9f, 0xe4, 0xe2, 0x69, 0xe3, 0x8a, 0x5b, 0xcd, 0x17}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x02, 0x0}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x02, 0x0}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x02, 0x80}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x02, 0x80}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x0}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x80}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x72, 0x28}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0a, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0x0, 0x0}, "0.0000000000000000000"}, + {[]byte{0x01, 0x0, 0x0, 0x0, 0x0a, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0x0, 0x80}, "0.0000000000000000000"}, + {[]byte{0x0a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"}, + {[]byte{0x0a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, "0.0000000000000000000"}, + {[]byte{0x0a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"}, + {[]byte{0x0a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80}, "0.0000000000000000000"}, + {[]byte{0x3c, 0x17, 0x25, 0x84, 0x19, 0xd7, 0x10, 0xc4, 0x2f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24}, "0.0000000000000000000"}, + {[]byte{0xff, 0xff, 0xff, 0xff, 0x09, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0x0, 0x0}, "0.0000000000000000000"}, + {[]byte{0xff, 0xff, 0xff, 0xff, 0x09, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0x0, 0x80}, "0.0000000000000000000"}, + {[]byte{0xff, 0xff, 0xff, 0xff, 0x63, 0x8e, 0x8d, 0x37, 0xc0, 0x87, 0xad, 0xbe, 0x09, 0xed, 0x01, 0x0}, "0.0000000000000000000"}, + + // Powers of 10 + {[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-1"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xb0}, "-1.0"}, + {[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xb0}, "-0.1"}, + {[]byte{0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0xb0}, "-0.0000000100"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0x30}, "0.0000000000010"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0x30}, "0.000000000010"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x30}, "0.00000000010"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0x30}, "0.0000000010"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2e, 0x30}, "0.000000010"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x30}, "0.00000010"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0x30}, "0.0000010"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "0.000010"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0x30}, "0.00010"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x30}, "0.0010"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "0.010"}, + {[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}, "0.1"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "0.10"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0xa, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0xfc, 0x2f}, "0.1000000000000000000"}, + {[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "1"}, + {[]byte{0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "1.00"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}, "1.0"}, + {[]byte{0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}, "10.0"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "10"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x30}, "100"}, + {[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x30}, "1000"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x30}, "1000"}, + {[]byte{0xe8, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "1000"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x30}, "10000"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48, 0x30}, "100000"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4a, 0x30}, "1000000"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4c, 0x30}, "10000000"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e, 0x30}, "100000000"}, + {[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "1000000000"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x30}, "1000000000"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "10000000000"}, + {[]byte{0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "100000000000"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0x30}, "100000000000"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x56, 0x30}, "1000000000000"}, + {[]byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x58, 0x30}, "10000000000000"}, + + // Integers + {[]byte{0xee, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-750"}, + {[]byte{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-123"}, + {[]byte{0x4c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-76"}, + {[]byte{0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-12"}, + {[]byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-1"}, + {[]byte{0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "2"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "7"}, + {[]byte{0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "9"}, + {[]byte{0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "12"}, + {[]byte{0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "17"}, + {[]byte{0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "19"}, + {[]byte{0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "20"}, + {[]byte{0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "29"}, + {[]byte{0x1e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "30"}, + {[]byte{0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "39"}, + {[]byte{0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "40"}, + {[]byte{0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "44"}, + {[]byte{0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "49"}, + {[]byte{0x32, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "50"}, + {[]byte{0x3b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "59"}, + {[]byte{0x3c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "60"}, + {[]byte{0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "69"}, + {[]byte{0x46, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "70"}, + {[]byte{0x47, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "71"}, + {[]byte{0x48, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "72"}, + {[]byte{0x49, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "73"}, + {[]byte{0x4a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "74"}, + {[]byte{0x4b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "75"}, + {[]byte{0x4c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "76"}, + {[]byte{0x4d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "77"}, + {[]byte{0x4e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "78"}, + {[]byte{0x4f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "79"}, + {[]byte{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "123"}, + {[]byte{0x8, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "520"}, + {[]byte{0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "521"}, + {[]byte{0x9, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "777"}, + {[]byte{0xa, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "778"}, + {[]byte{0x13, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "787"}, + {[]byte{0x1f, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "799"}, + {[]byte{0x6d, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "877"}, + {[]byte{0x78, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "888"}, + {[]byte{0x79, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "889"}, + {[]byte{0x82, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "898"}, + {[]byte{0x83, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "899"}, + {[]byte{0xd3, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "979"}, + {[]byte{0xdc, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "988"}, + {[]byte{0xdd, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "989"}, + {[]byte{0xe2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "994"}, + {[]byte{0xe3, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "995"}, + {[]byte{0xe5, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "997"}, + {[]byte{0xe6, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "998"}, + {[]byte{0xe7, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "999"}, + {[]byte{0x30, 0x75, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "30000"}, + {[]byte{0x90, 0x94, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "890000"}, + + {[]byte{0xfe, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "4294967294"}, + {[]byte{0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "4294967295"}, + {[]byte{0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "4294967296"}, + {[]byte{0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "4294967297"}, + + {[]byte{0x1, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-2147483649"}, + {[]byte{0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-2147483648"}, + {[]byte{0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-2147483647"}, + {[]byte{0xfe, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-2147483646"}, + {[]byte{0xfe, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "2147483646"}, + {[]byte{0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "2147483647"}, + {[]byte{0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "2147483648"}, + {[]byte{0x1, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "2147483649"}, + + // 1265 multiplied by powers of 10 + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x30}, "0.0000000000000000000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x30}, "0.0000000000000000000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x30}, "0.0000000000000000001"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0x30}, "0.0000000000000000013"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x30}, "0.0000000000000000126"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0x30}, "0.000000001265"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x30}, "0.00000001265"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0x30}, "0.0000001265"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2e, 0x30}, "0.000001265"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x30}, "0.00001265"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0x30}, "0.0001265"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "0.001265"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0x30}, "0.01265"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x30}, "0.1265"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "1.265"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "12.65"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}, "126.5"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "1265"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x30}, "12650"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x30}, "126500"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x30}, "1265000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48, 0x30}, "12650000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4a, 0x30}, "126500000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4c, 0x30}, "1265000000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e, 0x30}, "12650000000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x30}, "126500000000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "1265000000000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0x30}, "12650000000000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x56, 0x30}, "126500000000000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x58, 0x30}, "1265000000000000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, 0x30}, "12650000000000000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5c, 0x30}, "126500000000000000"}, + {[]byte{0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5e, 0x30}, "1265000000000000000"}, + + // 7 multiplied by powers of 10 + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0x30}, "0.0000000000007"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0x30}, "0.000000000007"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x30}, "0.00000000007"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0x30}, "0.0000000007"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2e, 0x30}, "0.000000007"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x30}, "0.00000007"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0x30}, "0.0000007"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "0.000007"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0x30}, "0.00007"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x30}, "0.0007"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "0.007"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "0.07"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}, "0.7"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "7"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x30}, "70"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x30}, "700"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x30}, "7000"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48, 0x30}, "70000"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4a, 0x30}, "700000"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4c, 0x30}, "7000000"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e, 0x30}, "70000000"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x30}, "700000000"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "7000000000"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x30}, "7000000000"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0x30}, "70000000000"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x56, 0x30}, "700000000000"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x58, 0x30}, "7000000000000"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, 0x30}, "70000000000000"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5c, 0x30}, "700000000000000"}, + {[]byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5e, 0x30}, "7000000000000000"}, + + // Sequences of digits + {[]byte{0x18, 0x5c, 0xa, 0xce, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xb0}, "-345678.5432"}, + {[]byte{0x39, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-12345"}, + {[]byte{0xd2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}, "-1234"}, + {[]byte{0x39, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0xb0}, "-123.45"}, + {[]byte{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0xb0}, "-1.23"}, + {[]byte{0x15, 0xcd, 0x5b, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x30}, "0.0000000123456789"}, + {[]byte{0x15, 0xcd, 0x5b, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x30}, "0.000000123456789"}, + {[]byte{0xf2, 0xaf, 0x96, 0x7e, 0xd0, 0x5c, 0x82, 0xde, 0x32, 0x97, 0xff, 0x6f, 0xde, 0x3c, 0xf0, 0x2f}, "0.0000001234567890123"}, + {[]byte{0x15, 0xcd, 0x5b, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x30}, "0.00000123456789"}, + {[]byte{0x15, 0xcd, 0x5b, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0x30}, "0.0000123456789"}, + {[]byte{0x40, 0xef, 0x5a, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x30}, "0.00123400000"}, + {[]byte{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "0.123"}, + {[]byte{0x78, 0xdf, 0xd, 0x86, 0x48, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x30}, "0.123456789012344"}, + {[]byte{0x79, 0xdf, 0xd, 0x86, 0x48, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x30}, "0.123456789012345"}, + {[]byte{0xf2, 0xaf, 0x96, 0x7e, 0xd0, 0x5c, 0x82, 0xde, 0x32, 0x97, 0xff, 0x6f, 0xde, 0x3c, 0xfc, 0x2f}, "0.1234567890123456789"}, + {[]byte{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "1.23"}, + {[]byte{0xd2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}, "1.234"}, + {[]byte{0x39, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}, "123.45"}, + {[]byte{0xd2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "1234"}, + {[]byte{0x39, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "12345"}, + {[]byte{0x18, 0x5c, 0xa, 0xce, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x30}, "345678.5432"}, + {[]byte{0x6a, 0xf9, 0xb, 0x7c, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "345678.543210"}, + {[]byte{0xf1, 0x98, 0x67, 0xc, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0x30}, "345678.54321"}, + {[]byte{0x6a, 0x19, 0x56, 0x25, 0x22, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "2345678.543210"}, + {[]byte{0x6a, 0xb9, 0xc8, 0x73, 0x3a, 0xb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "12345678.543210"}, + {[]byte{0x40, 0xaf, 0xd, 0x86, 0x48, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "123456789.000000"}, + {[]byte{0x80, 0x91, 0xf, 0x86, 0x48, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x30}, "123456789.123456"}, + {[]byte{0x80, 0x91, 0xf, 0x86, 0x48, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}, "123456789123456"}, + } + + for _, tt := range tests { + got, err := parseIEEEDecimal128(tt.b) + if err != nil { + t.Errorf("parseIEEEDecimal128([% x]) failed: %v", tt.b, err) + continue + } + want := MustParse(tt.want) + if got != want { + t.Errorf("parseIEEEDecimal128([% x]) = %q, want %q", tt.b, got, want) + } + } + }) + + t.Run("error", func(t *testing.T) { + tests := map[string][]byte{ + "length 1": {}, + "length 2": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + "length 3": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + "inf 1": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x78}, + "inf 2": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8}, + "nan 1": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7c}, + "nan 2": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc}, + "nan 3": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7e}, + "nan 4": {0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7e}, + "nan 5": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe}, + "overflow 1": {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x41, 0x30}, + "overflow 2": {0x0, 0x0, 0x0, 0x0, 0xa, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0xcc, 0x37}, + "overflow 3": {0x0, 0x0, 0x0, 0x0, 0xa, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0xfe, 0x5f}, + "overflow 4": {0x0, 0x0, 0x0, 0x0, 0xa, 0x5b, 0xc1, 0x38, 0x93, 0x8d, 0x44, 0xc6, 0x4d, 0x31, 0xfe, 0xdf}, + "overflow 5": {0x0, 0x0, 0x0, 0x0, 0x81, 0xef, 0xac, 0x85, 0x5b, 0x41, 0x6d, 0x2d, 0xee, 0x4, 0xfe, 0x5f}, + "overflow 6": {0x0, 0x0, 0x0, 0x10, 0x61, 0x2, 0x25, 0x3e, 0x5e, 0xce, 0x4f, 0x20, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 7": {0x0, 0x0, 0x0, 0x40, 0xea, 0xed, 0x74, 0x46, 0xd0, 0x9c, 0x2c, 0x9f, 0xc, 0x0, 0xfe, 0x5f}, + "overflow 8": {0x0, 0x0, 0x0, 0x4a, 0x48, 0x1, 0x14, 0x16, 0x95, 0x45, 0x8, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 9": {0x0, 0x0, 0x0, 0x80, 0x26, 0x4b, 0x91, 0xc0, 0x22, 0x20, 0xbe, 0x37, 0x7e, 0x0, 0xfe, 0x5f}, + "overflow 10": {0x0, 0x0, 0x0, 0x80, 0x7f, 0x1b, 0xcf, 0x85, 0xb2, 0x70, 0x59, 0xc8, 0xa4, 0x3c, 0xfe, 0x5f}, + "overflow 11": {0x0, 0x0, 0x0, 0x80, 0x7f, 0x1b, 0xcf, 0x85, 0xb2, 0x70, 0x59, 0xc8, 0xa4, 0x3c, 0xfe, 0xdf}, + "overflow 12": {0x0, 0x0, 0x0, 0xa0, 0xca, 0x17, 0x72, 0x6d, 0xae, 0xf, 0x1e, 0x43, 0x1, 0x0, 0xfe, 0x5f}, + "overflow 13": {0x0, 0x0, 0x0, 0xa1, 0xed, 0xcc, 0xce, 0x1b, 0xc2, 0xd3, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 14": {0x0, 0x0, 0x0, 0xe4, 0xd2, 0xc, 0xc8, 0xdc, 0xd2, 0xb7, 0x52, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 15": {0x0, 0x0, 0x0, 0xe8, 0x3c, 0x80, 0xd0, 0x9f, 0x3c, 0x2e, 0x3b, 0x3, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 16": {0x0, 0x0, 0x10, 0x63, 0x2d, 0x5e, 0xc7, 0x6b, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 17": {0x0, 0x0, 0x40, 0xb2, 0xba, 0xc9, 0xe0, 0x19, 0x1e, 0x2, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 18": {0x0, 0x0, 0x64, 0xa7, 0xb3, 0xb6, 0xe0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 19": {0x0, 0x0, 0x80, 0xf6, 0x4a, 0xe1, 0xc7, 0x2, 0x2d, 0x15, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 20": {0x0, 0x0, 0x8a, 0x5d, 0x78, 0x45, 0x63, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 21": {0x0, 0x0, 0xa0, 0xde, 0xc5, 0xad, 0xc9, 0x35, 0x36, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 22": {0x0, 0x0, 0xc1, 0x6f, 0xf2, 0x86, 0x23, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 23": {0x0, 0x0, 0xe8, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 24": {0x0, 0x10, 0xa5, 0xd4, 0xe8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 25": {0x0, 0x40, 0x7a, 0x10, 0xf3, 0x5a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 26": {0x0, 0x80, 0xc6, 0xa4, 0x7e, 0x8d, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 27": {0x0, 0xa0, 0x72, 0x4e, 0x18, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 28": {0x0, 0xca, 0x9a, 0x3b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 29": {0x0, 0xe1, 0xf5, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 30": {0x0, 0xe4, 0xb, 0x54, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 31": {0x0, 0xe8, 0x76, 0x48, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 32": {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf4, 0x30}, + "overflow 33": {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x5f}, + "overflow 34": {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 35": {0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x31}, + "overflow 36": {0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0x38}, + "overflow 37": {0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x5f}, + "overflow 38": {0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf4, 0x30}, + "overflow 39": {0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 40": {0x10, 0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 41": {0x40, 0x42, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 42": {0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf4, 0x30}, + "overflow 43": {0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 44": {0x79, 0xd9, 0xe0, 0xf9, 0x76, 0x3a, 0xda, 0x42, 0x9d, 0x2, 0x0, 0x0, 0x0, 0x0, 0x58, 0x30}, + "overflow 45": {0x80, 0x96, 0x98, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 46": {0xa0, 0x86, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 47": {0xc7, 0x71, 0x1c, 0xc7, 0xb5, 0x48, 0xf3, 0x77, 0xdc, 0x80, 0xa1, 0x31, 0xc8, 0x36, 0x40, 0x30}, + "overflow 48": {0xe8, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x5f}, + "overflow 49": {0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x30}, + "overflow 50": {0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x62, 0x30}, + "overflow 51": {0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, 0x30}, + "overflow 52": {0xf1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0x30}, + "overflow 53": {0xf2, 0xaf, 0x96, 0x7e, 0xd0, 0x5c, 0x82, 0xde, 0x32, 0x97, 0xff, 0x6f, 0xde, 0x3c, 0x40, 0x30}, + "overflow 54": {0xf2, 0xaf, 0x96, 0x7e, 0xd0, 0x5c, 0x82, 0xde, 0x32, 0x97, 0xff, 0x6f, 0xde, 0x3c, 0x40, 0xb0}, + "overflow 55": {0xf2, 0xaf, 0x96, 0x7e, 0xd0, 0x5c, 0x82, 0xde, 0x32, 0x97, 0xff, 0x6f, 0xde, 0x3c, 0xfe, 0x5f}, + "overflow 56": {0xf2, 0xaf, 0x96, 0x7e, 0xd0, 0x5c, 0x82, 0xde, 0x32, 0x97, 0xff, 0x6f, 0xde, 0x3c, 0xfe, 0xdf}, + "overflow 57": {0xff, 0xff, 0xff, 0xff, 0x63, 0x8e, 0x8d, 0x37, 0xc0, 0x87, 0xad, 0xbe, 0x9, 0xed, 0x41, 0x30}, + "overflow 58": {0xff, 0xff, 0xff, 0xff, 0x63, 0x8e, 0x8d, 0x37, 0xc0, 0x87, 0xad, 0xbe, 0x9, 0xed, 0xff, 0x5f}, + "overflow 59": {0xff, 0xff, 0xff, 0xff, 0x63, 0x8e, 0x8d, 0x37, 0xc0, 0x87, 0xad, 0xbe, 0x9, 0xed, 0xff, 0xdf}, + "overflow 60": {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x30}, + } + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + _, err := parseIEEEDecimal128(tt) + if err == nil { + t.Errorf("parseIEEEDecimal128([% x]) did not fail", tt) + } + }) + } + }) +} + +func TestDecimal_IEEEDecimal128(t *testing.T) { + t.Run("success", func(t *testing.T) { + tests := []struct { + d string + want []byte + }{ + {"-9999999999999999999", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}}, + {"-999999999999999999.9", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xb0}}, + {"-99999999999999999.99", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0xb0}}, + {"-9999999999999999.999", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0xb0}}, + {"-0.9999999999999999999", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xb0}}, + {"-1", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}}, + {"-0.1", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xb0}}, + {"-0.01", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0xb0}}, + {"-0.0000000000000000001", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xb0}}, + {"0", []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}}, + {"0.0", []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}}, + {"0.00", []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}}, + {"0.0000000000000000000", []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0x30}}, + {"0.0000000000000000001", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0x30}}, + {"0.01", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}}, + {"0.1", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}}, + {"1", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}}, + {"0.9999999999999999999", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0x30}}, + {"9999999999999999.999", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x30}}, + {"99999999999999999.99", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x30}}, + {"999999999999999999.9", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, 0x30}}, + {"9999999999999999999", []byte{0xff, 0xff, 0xe7, 0x89, 0x4, 0x23, 0xc7, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}}, + + // Exported constants + {NegOne.String(), []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xb0}}, + {Zero.String(), []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}}, + {One.String(), []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}}, + {Two.String(), []byte{0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}}, + {Ten.String(), []byte{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}}, + {Hundred.String(), []byte{0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}}, + {Thousand.String(), []byte{0xe8, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x30}}, + {E.String(), []byte{0x73, 0x61, 0xb3, 0xc0, 0xeb, 0x46, 0xb9, 0x25, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x30}}, + {Pi.String(), []byte{0xd6, 0x49, 0x32, 0xa2, 0xdf, 0x2d, 0x99, 0x2b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x30}}, + } + for _, tt := range tests { + d := MustParse(tt.d) + got := d.ieeeDecimal128() + if !bytes.Equal(got, tt.want) { + t.Errorf("%q.ieeeDecimal128() = [% x], want [% x]", d, got, tt.want) + } + + } + }) +} + func TestDecimal_String(t *testing.T) { t.Run("success", func(t *testing.T) { tests := []struct { @@ -524,15 +1265,15 @@ func TestDecimal_String(t *testing.T) { {false, 0, 1, "0.0"}, {false, 0, 2, "0.00"}, {false, 0, 19, "0.0000000000000000000"}, - {false, 1, 0, "1"}, - {false, 1, 1, "0.1"}, - {false, 1, 2, "0.01"}, {false, 1, 19, "0.0000000000000000001"}, - {false, maxCoef, 0, "9999999999999999999"}, - {false, maxCoef, 1, "999999999999999999.9"}, - {false, maxCoef, 2, "99999999999999999.99"}, - {false, maxCoef, 3, "9999999999999999.999"}, + {false, 1, 2, "0.01"}, + {false, 1, 1, "0.1"}, + {false, 1, 0, "1"}, {false, maxCoef, 19, "0.9999999999999999999"}, + {false, maxCoef, 3, "9999999999999999.999"}, + {false, maxCoef, 2, "99999999999999999.99"}, + {false, maxCoef, 1, "999999999999999999.9"}, + {false, maxCoef, 0, "9999999999999999999"}, // Exported constants {NegOne.neg, NegOne.coef, NegOne.Scale(), "-1"}, @@ -565,17 +1306,16 @@ func TestDecimal_Float64(t *testing.T) { wantFloat float64 wantOk bool }{ - {"9999999999999999999", 9999999999999999999, true}, - {"1000000000000000000", 1000000000000000000, true}, - {"1", 1, true}, - {"0.9999999999999999999", 0.9999999999999999999, true}, - {"0.0000000000000000001", 0.0000000000000000001, true}, - {"-9999999999999999999", -9999999999999999999, true}, {"-1000000000000000000", -1000000000000000000, true}, {"-1", -1, true}, {"-0.9999999999999999999", -0.9999999999999999999, true}, {"-0.0000000000000000001", -0.0000000000000000001, true}, + {"0.0000000000000000001", 0.0000000000000000001, true}, + {"0.9999999999999999999", 0.9999999999999999999, true}, + {"1", 1, true}, + {"1000000000000000000", 1000000000000000000, true}, + {"9999999999999999999", 9999999999999999999, true}, } for _, tt := range tests { d := MustParse(tt.d) @@ -611,21 +1351,20 @@ func TestDecimal_Int64(t *testing.T) { // Powers of ten {"0.0001", 4, 0, 1, true}, - {"0.001", 4, 0, 10, true}, - {"0.01", 4, 0, 100, true}, - {"0.1", 4, 0, 1000, true}, - {"1", 4, 1, 0, true}, - {"10", 4, 10, 0, true}, - {"100", 4, 100, 0, true}, - {"1000", 4, 1000, 0, true}, - {"0.0001", 4, 0, 1, true}, + {"0.001", 4, 0, 10, true}, {"0.001", 3, 0, 1, true}, + {"0.01", 4, 0, 100, true}, {"0.01", 2, 0, 1, true}, + {"0.1", 4, 0, 1000, true}, {"0.1", 1, 0, 1, true}, + {"1", 4, 1, 0, true}, {"1", 0, 1, 0, true}, + {"10", 4, 10, 0, true}, {"10", 0, 10, 0, true}, + {"100", 4, 100, 0, true}, {"100", 0, 100, 0, true}, + {"1000", 4, 1000, 0, true}, {"1000", 0, 1000, 0, true}, // Signs @@ -674,26 +1413,26 @@ func TestDecimal_Int64(t *testing.T) { {"0.9999999999999999999", 3, 1, 0, true}, // Edge cases - {"9223372036854775807", 0, 9223372036854775807, 0, true}, {"-9223372036854775808", 0, -9223372036854775808, 0, true}, - {"922337203685477580.8", 1, 922337203685477580, 8, true}, {"-922337203685477580.9", 1, -922337203685477580, -9, true}, - {"9.223372036854775808", 18, 9, 223372036854775808, true}, {"-9.223372036854775809", 18, -9, -223372036854775809, true}, - {"0.9223372036854775807", 19, 0, 9223372036854775807, true}, {"-0.9223372036854775808", 19, 0, -9223372036854775808, true}, + {"0.9223372036854775807", 19, 0, 9223372036854775807, true}, + {"9.223372036854775808", 18, 9, 223372036854775808, true}, + {"922337203685477580.8", 1, 922337203685477580, 8, true}, + {"9223372036854775807", 0, 9223372036854775807, 0, true}, // Failures - {"9223372036854775808", 0, 0, 0, false}, - {"-9223372036854775809", 0, 0, 0, false}, - {"0.9223372036854775808", 19, 0, 0, false}, - {"-0.9223372036854775809", 19, 0, 0, false}, - {"9999999999999999999", 0, 0, 0, false}, {"-9999999999999999999", 0, 0, 0, false}, - {"0.9999999999999999999", 19, 0, 0, false}, + {"-9223372036854775809", 0, 0, 0, false}, {"-0.9999999999999999999", 19, 0, 0, false}, + {"-0.9223372036854775809", 19, 0, 0, false}, {"0.1", -1, 0, 0, false}, {"0.1", 20, 0, 0, false}, + {"0.9223372036854775808", 19, 0, 0, false}, + {"0.9999999999999999999", 19, 0, 0, false}, + {"9223372036854775808", 0, 0, 0, false}, + {"9999999999999999999", 0, 0, 0, false}, } for _, tt := range tests { d := MustParse(tt.d) @@ -710,6 +1449,7 @@ func TestDecimal_Scan(t *testing.T) { f float64 want string }{ + {math.SmallestNonzeroFloat64, "0.0000000000000000000"}, {1e-20, "0.0000000000000000000"}, {1e-19, "0.0000000000000000001"}, {1e-5, "0.00001"}, @@ -729,7 +1469,42 @@ func TestDecimal_Scan(t *testing.T) { got := Decimal{} err := got.Scan(tt.f) if err != nil { - t.Errorf("Scan(1.23456) failed: %v", err) + t.Errorf("Scan(%v) failed: %v", tt.f, err) + continue + } + want := MustParse(tt.want) + if got != want { + t.Errorf("Scan(%v) = %v, want %v", tt.f, got, want) + } + } + }) + + t.Run("float32", func(t *testing.T) { + tests := []struct { + f float32 + want string + }{ + {math.SmallestNonzeroFloat32, "0.0000000000000000000"}, + {1e-20, "0.0000000000000000000"}, + {1e-19, "0.0000000000000000001"}, + {1e-5, "0.0000099999997473788"}, + {1e-4, "0.0000999999974737875"}, + {1e-3, "0.0010000000474974513"}, + {1e-2, "0.009999999776482582"}, + {1e-1, "0.10000000149011612"}, + {1e0, "1"}, + {1e1, "10"}, + {1e2, "100"}, + {1e3, "1000"}, + {1e4, "10000"}, + {1e5, "100000"}, + {1e18, "999999984306749400"}, + } + for _, tt := range tests { + got := Decimal{} + err := got.Scan(tt.f) + if err != nil { + t.Errorf("Scan(%v) failed: %v", tt.f, err) continue } want := MustParse(tt.want) @@ -762,6 +1537,28 @@ func TestDecimal_Scan(t *testing.T) { } }) + t.Run("uint64", func(t *testing.T) { + tests := []struct { + i uint64 + want string + }{ + {0, "0"}, + {9999999999999999999, "9999999999999999999"}, + } + for _, tt := range tests { + got := Decimal{} + err := got.Scan(tt.i) + if err != nil { + t.Errorf("Scan(%v) failed: %v", tt.i, err) + continue + } + want := MustParse(tt.want) + if got != want { + t.Errorf("Scan(%v) = %v, want %v", tt.i, got, want) + } + } + }) + t.Run("[]byte", func(t *testing.T) { tests := []struct { b []byte @@ -795,8 +1592,6 @@ func TestDecimal_Scan(t *testing.T) { uint16(123), uint32(123), uint(123), - uint64(123), - float32(123), nil, } for _, tt := range tests { @@ -1964,6 +2759,12 @@ func TestProd(t *testing.T) { "overflow 1": {"10000000000", "1000000000"}, "overflow 2": {"1000000000000000000", "10"}, "overflow 3": {"4999999999999999995", "-2.000000000000000002"}, + "overflow 4": { + "9999999999999999999", "9999999999999999999", + "9999999999999999999", "9999999999999999999", + "9999999999999999999", "9999999999999999999", + "9999999999999999999", "9999999999999999999", + }, } for name, ss := range tests { t.Run(name, func(t *testing.T) { @@ -1986,6 +2787,7 @@ func TestMean(t *testing.T) { d []string want string }{ + {[]string{"1"}, "1"}, {[]string{"1", "1"}, "1"}, {[]string{"2", "3"}, "2.5"}, {[]string{"5.75", "3.3"}, "4.525"}, @@ -2048,6 +2850,7 @@ func TestMean(t *testing.T) { // Captured during fuzzing {[]string{"9223372036854775807", "9223372036854775807", "922337203685477580.7"}, "6456360425798343065"}, {[]string{"922.3372036854775807", "2", "-3000000000"}, "-999999691.8875987715"}, + {[]string{"0.5", "0.3", "0.2"}, "0.3333333333333333333"}, } for _, tt := range tests { d := make([]Decimal, len(tt.d)) @@ -2863,6 +3666,9 @@ func TestDecimal_Pow(t *testing.T) { {"0.85", "-267", "7000786514887173012"}, {"0.066", "-16", "7714309010612096020"}, {"-0.9223372036854775808", "-128", "31197.15320234751783"}, + {"999999999.999999999", "-9223372036854775808", "0"}, + {"-0.9223372036854775807", "-541", "-9877744411719625497"}, + {"0.9223372036854775702", "-540", "9110611159425388150"}, } for _, tt := range tests { d := MustParse(tt.d) @@ -3128,10 +3934,12 @@ func TestDecimal_PowInt(t *testing.T) { {"1.00001", 600000, "403.4166908911542153"}, // no error // Captured during fuzzing + {"-0.9223372036854775807", -541, "-9877744411719625497"}, + {"999999999.999999999", math.MinInt, "0"}, + {"-0.9223372036854775808", -128, "31197.15320234751783"}, {"0.85", -267, "7000786514887173012"}, {"0.066", -16, "7714309010612096020"}, - {"-0.9223372036854775808", -128, "31197.15320234751783"}, - {"999999999.999999999", math.MinInt, "0"}, + {"0.9223372036854775702", -540, "9110611159425388150"}, } for _, tt := range tests { d := MustParse(tt.d) @@ -3685,7 +4493,7 @@ func TestDecimal_Log(t *testing.T) { {"0.1353352832366126919", "-2.000000000000000000"}, {"0.3678794411714423216", "-1.000000000000000000"}, {"1", "0"}, - {E.String(), "1.000000000000000000"}, + {E.String(), "0.9999999999999999999"}, {"7.389056098930650227", "2.000000000000000000"}, {"20.08553692318766774", "3.000000000000000000"}, {"54.59815003314423908", "4.000000000000000000"}, @@ -3748,7 +4556,7 @@ func TestDecimal_Log(t *testing.T) { {"2.7182818284590452", "0.9999999999999999870"}, {"2.71828182845904523", "0.9999999999999999980"}, {"2.718281828459045234", "0.9999999999999999995"}, - {E.String(), "1.000000000000000000"}, + {E.String(), "0.9999999999999999999"}, {"2.718281828459045236", "1.000000000000000000"}, {"2.71828182845904524", "1.000000000000000002"}, {"2.7182818284590453", "1.000000000000000024"}, @@ -4663,15 +5471,46 @@ func TestDecimal_QuoRem(t *testing.T) { {"2", "8", "0", "2"}, {"2", "9", "0", "2"}, - // Other tests - {"12345", "4.999", "2469", "2.469"}, - {"12345", "4.99", "2473", "4.73"}, + // Closer and closer to five {"12345", "4.9", "2519", "1.9"}, + {"12345", "4.99", "2473", "4.73"}, + {"12345", "4.999", "2469", "2.469"}, + {"12345", "4.9999", "2469", "0.2469"}, + {"12345", "4.99999", "2469", "0.02469"}, + {"12345", "4.999999", "2469", "0.002469"}, + {"12345", "4.9999999", "2469", "0.0002469"}, + {"12345", "4.99999999", "2469", "0.00002469"}, + {"12345", "4.999999999", "2469", "0.000002469"}, + {"12345", "4.9999999999", "2469", "0.0000002469"}, + {"12345", "4.99999999999", "2469", "0.00000002469"}, + {"12345", "4.999999999999", "2469", "0.000000002469"}, + {"12345", "4.9999999999999", "2469", "0.0000000002469"}, + {"12345", "4.99999999999999", "2469", "0.00000000002469"}, + {"12345", "4.999999999999999", "2469", "0.000000000002469"}, + {"12345", "4.9999999999999999", "2469", "0.0000000000002469"}, + {"12345", "4.99999999999999999", "2469", "0.00000000000002469"}, + {"12345", "4.999999999999999999", "2469", "0.000000000000002469"}, {"12345", "5", "2469", "0"}, - {"12345", "5.1", "2420", "3.0"}, - {"12345", "5.01", "2464", "0.36"}, + {"12345", "5.000000000000000001", "2468", "4.999999999999997532"}, + {"12345", "5.00000000000000001", "2468", "4.99999999999997532"}, + {"12345", "5.0000000000000001", "2468", "4.9999999999997532"}, + {"12345", "5.000000000000001", "2468", "4.999999999997532"}, + {"12345", "5.00000000000001", "2468", "4.99999999997532"}, + {"12345", "5.0000000000001", "2468", "4.9999999997532"}, + {"12345", "5.000000000001", "2468", "4.999999997532"}, + {"12345", "5.00000000001", "2468", "4.99999997532"}, + {"12345", "5.0000000001", "2468", "4.9999997532"}, + {"12345", "5.000000001", "2468", "4.999997532"}, + {"12345", "5.00000001", "2468", "4.99997532"}, + {"12345", "5.0000001", "2468", "4.9997532"}, + {"12345", "5.000001", "2468", "4.997532"}, + {"12345", "5.00001", "2468", "4.97532"}, + {"12345", "5.0001", "2468", "4.7532"}, {"12345", "5.001", "2468", "2.532"}, + {"12345", "5.01", "2464", "0.36"}, + {"12345", "5.1", "2420", "3.0"}, + // Other tests {"41", "21", "1", "20"}, {"4.2", "3.1000003", "1", "1.0999997"}, {"1.000000000000000000", "0.000000000000000003", "333333333333333333", "0.000000000000000001"}, @@ -5014,6 +5853,19 @@ func FuzzParse(f *testing.F) { ) } +func FuzzBSON(f *testing.F) { + for _, c := range corpus { + d := newUnsafe(c.neg, fint(c.coef), c.scale) + f.Add(byte(19), d.ieeeDecimal128()) + } + f.Fuzz( + func(_ *testing.T, typ byte, data []byte) { + var d Decimal + _ = d.UnmarshalBSONValue(typ, data) + }, + ) +} + func FuzzDecimal_String_Parse(f *testing.F) { for _, d := range corpus { f.Add(d.neg, d.scale, d.coef) @@ -5042,6 +5894,34 @@ func FuzzDecimal_String_Parse(f *testing.F) { ) } +func FuzzDecimal_IEEE_ParseIEEE(f *testing.F) { + for _, d := range corpus { + f.Add(d.neg, d.scale, d.coef) + } + + f.Fuzz( + func(t *testing.T, neg bool, scale int, coef uint64) { + want, err := newSafe(neg, fint(coef), scale) + if err != nil { + t.Skip() + return + } + + data := want.ieeeDecimal128() + got, err := parseIEEEDecimal128(data) + if err != nil { + t.Errorf("parseIEEEDecimal128(% x) failed: %v", data, err) + return + } + + if got.CmpTotal(want) != 0 { + t.Errorf("parseIEEEDecimal128(% x) = %v, want %v", data, got, want) + return + } + }, + ) +} + func FuzzDecimal_Binary_Text(f *testing.F) { for _, d := range corpus { f.Add(d.neg, d.scale, d.coef) diff --git a/doc.go b/doc.go index f345806..c8f3bb7 100644 --- a/doc.go +++ b/doc.go @@ -152,7 +152,7 @@ Errors are returned in the following cases: [Sum], [Mean] and [Prod] return an error if no arguments are provided. [Decimal.PowInt] returns an error if 0 is raised to a negative power. [Decimal.Sqrt] returns an error if the square root of a negative decimal is requested. - [Decimal.Log], [Decimal.Log2], [Decimal.Log10] return an error when calculating the natural logarithm of a non-positive decimal. + [Decimal.Log], [Decimal.Log2], [Decimal.Log10] return an error when calculating a logarithm of a non-positive decimal. [Decimal.Pow] returns an error if 0 is raised to a negative powere or a negative decimal is raised to a fractional power. - Overflow: @@ -170,7 +170,7 @@ Errors are not returned in the following cases: A. JSON -The package integrates seamlessly with standard [encoding/json] through +The package integrates with standard [encoding/json] through the implementation of [encoding.TextMarshaller] and [encoding.TextUnmarshaler] interfaces. Below is an example structure: @@ -189,7 +189,14 @@ Below is an example OpenAPI schema: format: decimal pattern: '^(\-|\+)?((\d+(\.\d*)?)|(\.\d+))$' -B. XML +B. BSON + +The package integrates with [mongo-driver/v2/bson] via the implementation of +[bson.ValueMarshaler] and [bson.ValueUnmarshaler] interfaces. +This package marshals decimals as Decimal128, ensuring the preservation of +the exact numerical value. + +C. XML The package integrates with standard [encoding/xml] via the implementation of [encoding.TextMarshaller] and [encoding.TextUnmarshaler] interfaces. @@ -210,7 +217,7 @@ using the following type: -C. Protocol Buffers +D. Protocol Buffers Protocol Buffers provide two formats to represent decimals. The first format represents decimals as [numerical strings]. @@ -235,7 +242,7 @@ Below is an example of a proto definition: int32 nanos = 2; } -D. SQL +E. SQL The package integrates with the standard [database/sql] via the implementation of [sql.Scanner] and [driver.Valuer] interfaces. @@ -278,5 +285,8 @@ Below are the reasons for these preferences: [context]: https://speleotrove.com/decimal/damodel.html [numerical strings]: https://github.com/googleapis/googleapis/blob/master/google/type/decimal.proto [a pair of integers]: https://github.com/googleapis/googleapis/blob/master/google/type/money.proto +[mongo-driver/v2/bson]: https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/bson +[bson.ValueMarshaler]: https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/bson#ValueMarshaler +[bson.ValueUnmarshaler]: https://pkg.go.dev/go.mongodb.org/mongo-driver/v2/bson#ValueUnmarshaler */ package decimal diff --git a/doc_test.go b/doc_test.go index ae68027..3b789f9 100644 --- a/doc_test.go +++ b/doc_test.go @@ -266,9 +266,9 @@ func ExampleDecimal_String() { // Output: 1234567890.123456789 } -func unmarshalGOB(b []byte) (decimal.Decimal, error) { +func unmarshalGOB(data []byte) (decimal.Decimal, error) { var d decimal.Decimal - dec := gob.NewDecoder(bytes.NewReader(b)) + dec := gob.NewDecoder(bytes.NewReader(data)) err := dec.Decode(&d) if err != nil { return decimal.Decimal{}, err @@ -281,13 +281,13 @@ func marshalGOB(s string) ([]byte, error) { if err != nil { return nil, err } - var buf bytes.Buffer - enc := gob.NewEncoder(&buf) + var data bytes.Buffer + enc := gob.NewEncoder(&data) err = enc.Encode(d) if err != nil { return nil, err } - return buf.Bytes(), nil + return data.Bytes(), nil } func ExampleDecimal_UnmarshalBinary_gob() { @@ -306,10 +306,10 @@ func ExampleDecimal_UnmarshalBinary_gob() { } func ExampleDecimal_MarshalBinary_gob() { - bcd, err := marshalGOB("5.67") - fmt.Printf("% x %v\n", bcd, err) + data, err := marshalGOB("5.67") + fmt.Printf("[% x] %v\n", data, err) // Output: - // 12 7f 06 01 01 07 44 65 63 69 6d 61 6c 01 ff 80 00 00 00 08 ff 80 00 04 35 2e 36 37 + // [12 7f 06 01 01 07 44 65 63 69 6d 61 6c 01 ff 80 00 00 00 08 ff 80 00 04 35 2e 36 37] } func ExampleDecimal_Float64() { @@ -340,6 +340,29 @@ func ExampleDecimal_Int64() { // 5 6700 true } +func ExampleDecimal_UnmarshalBSONValue_bson() { + data := []byte{ + 0x37, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x30, + } + + var d decimal.Decimal + err := d.UnmarshalBSONValue(19, data) + fmt.Println(d, err) + // Output: + // 5.67 +} + +func ExampleDecimal_MarshalBSONValue_bson() { + d := decimal.MustParse("5.67") + t, data, err := d.MarshalBSONValue() + fmt.Printf("%v [% x] %v\n", t, data, err) + // Output: + // 19 [37 02 00 00 00 00 00 00 00 00 00 00 00 00 3c 30] +} + type Object struct { Number decimal.Decimal `json:"number"` } @@ -358,19 +381,18 @@ func marshalJSON(s string) (string, error) { if err != nil { return "", err } - v := Object{Number: d} - b, err := json.Marshal(v) + data, err := json.Marshal(Object{Number: d}) if err != nil { return "", err } - return string(b), nil + return string(data), nil } -func ExampleDecimal_UnmarshalText_json() { +func ExampleDecimal_UnmarshalJSON_json() { fmt.Println(unmarshalJSON(`{"number":"5.67"}`)) fmt.Println(unmarshalJSON(`{"number":"-5.67"}`)) - fmt.Println(unmarshalJSON(`{"number":"5.67e-5"}`)) - fmt.Println(unmarshalJSON(`{"number":"5.67e5"}`)) + fmt.Println(unmarshalJSON(`{"number":5.67e-5}`)) + fmt.Println(unmarshalJSON(`{"number":5.67e5}`)) // Output: // {5.67} // {-5.67} @@ -378,16 +400,12 @@ func ExampleDecimal_UnmarshalText_json() { // {567000} } -func ExampleDecimal_MarshalText_json() { +func ExampleDecimal_MarshalJSON_json() { fmt.Println(marshalJSON("5.67")) fmt.Println(marshalJSON("-5.67")) - fmt.Println(marshalJSON("5.67e-5")) - fmt.Println(marshalJSON("5.67e5")) // Output: // {"number":"5.67"} // {"number":"-5.67"} - // {"number":"0.0000567"} - // {"number":"567000"} } type Entity struct { @@ -405,12 +423,11 @@ func marshalXML(s string) (string, error) { if err != nil { return "", err } - v := Entity{Number: d} - b, err := xml.Marshal(v) + data, err := xml.Marshal(Entity{Number: d}) if err != nil { return "", err } - return string(b), nil + return string(data), nil } func ExampleDecimal_UnmarshalText_xml() { @@ -1316,28 +1333,98 @@ func ExampleDecimal_WithinOne_slices() { } func ExampleNullDecimal_Scan() { - var n, m decimal.NullDecimal - _ = n.Scan("5.67") - _ = m.Scan(nil) + var n decimal.NullDecimal + _ = n.Scan(nil) fmt.Println(n) + + var m decimal.NullDecimal + _ = m.Scan("5.67") fmt.Println(m) // Output: - // {5.67 true} // {0 false} + // {5.67 true} } func ExampleNullDecimal_Value() { n := decimal.NullDecimal{ - Decimal: decimal.MustParse("5.67"), - Valid: true, + Valid: false, } + fmt.Println(n.Value()) + m := decimal.NullDecimal{ - Decimal: decimal.MustParse("0"), - Valid: false, + Decimal: decimal.MustParse("5.67"), + Valid: true, } - fmt.Println(n.Value()) fmt.Println(m.Value()) // Output: - // 5.67 // + // 5.67 +} + +func ExampleNullDecimal_UnmarshalJSON_json() { + var n decimal.NullDecimal + _ = json.Unmarshal([]byte(`null`), &n) + fmt.Println(n) + + var m decimal.NullDecimal + _ = json.Unmarshal([]byte(`"5.67"`), &m) + fmt.Println(m) + // Output: + // {0 false} + // {5.67 true} +} + +func ExampleNullDecimal_MarshalJSON_json() { + n := decimal.NullDecimal{ + Valid: false, + } + data, _ := json.Marshal(n) + fmt.Println(string(data)) + + m := decimal.NullDecimal{ + Decimal: decimal.MustParse("5.67"), + Valid: true, + } + data, _ = json.Marshal(m) + fmt.Println(string(data)) + // Output: + // null + // "5.67" +} + +func ExampleNullDecimal_UnmarshalBSONValue_bson() { + var n decimal.NullDecimal + _ = n.UnmarshalBSONValue(10, nil) + fmt.Println(n) + + data := []byte{ + 0x37, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x30, + } + var m decimal.NullDecimal + _ = m.UnmarshalBSONValue(19, data) + fmt.Println(m) + // Output: + // {0 false} + // {5.67 true} +} + +func ExampleNullDecimal_MarshalBSONValue_bson() { + n := decimal.NullDecimal{ + Valid: false, + } + t, data, _ := n.MarshalBSONValue() + fmt.Printf("%v [% x]\n", t, data) + + m := decimal.NullDecimal{ + Decimal: decimal.MustParse("5.67"), + Valid: true, + } + t, data, _ = m.MarshalBSONValue() + fmt.Printf("%v [% x]\n", t, data) + // Output: + // 10 [] + // 19 [37 02 00 00 00 00 00 00 00 00 00 00 00 00 3c 30] } diff --git a/integer.go b/integer.go index ce9a8fa..e151bd2 100644 --- a/integer.go +++ b/integer.go @@ -440,318 +440,318 @@ var bfact = [...]*bint{ } // bscale is a scale of precomputed values in bexp, blog and bnlog10. -const bscale = 40 +const bscale = 41 -// bexp is a cache of powers of e, where bexp[x] = round(exp(x) * 10^40). +// bexp is a cache of powers of e, where bexp[x] = round(exp(x) * 10^41). var bexp = [...]*bint{ - mustParseBint("10000000000000000000000000000000000000000"), - mustParseBint("27182818284590452353602874713526624977572"), - mustParseBint("73890560989306502272304274605750078131803"), - mustParseBint("200855369231876677409285296545817178969879"), - mustParseBint("545981500331442390781102612028608784027907"), - mustParseBint("1484131591025766034211155800405522796234877"), - mustParseBint("4034287934927351226083871805433882796058999"), - mustParseBint("10966331584284585992637202382881214324422191"), - mustParseBint("29809579870417282747435920994528886737559679"), - mustParseBint("81030839275753840077099966894327599650114761"), - mustParseBint("220264657948067165169579006452842443663535126"), - mustParseBint("598741417151978184553264857922577816142610797"), - mustParseBint("1627547914190039208080052048984867831702092845"), - mustParseBint("4424133920089205033261027759490882817843913061"), - mustParseBint("12026042841647767777492367707678594494124865434"), - mustParseBint("32690173724721106393018550460917213155057385438"), - mustParseBint("88861105205078726367630237407814503508027198219"), - mustParseBint("241549527535752982147754351803858238798675673527"), - mustParseBint("656599691373305111387865032590600335692163557862"), - mustParseBint("1784823009631872608449100337887227038836197331652"), - mustParseBint("4851651954097902779691068305415405586846389889448"), - mustParseBint("13188157344832146972099988837453027850914444373805"), - mustParseBint("35849128461315915616811599459784206892226930650373"), - mustParseBint("97448034462489026000346326848229752776493877640360"), - mustParseBint("264891221298434722941391621528118823408701986192485"), - mustParseBint("720048993373858725241613514661261579152235338133953"), - mustParseBint("1957296094288387642697763978760953427920361009506976"), - mustParseBint("5320482406017986166837473043411774416592558042836888"), - mustParseBint("14462570642914751736770474229969288569020623295099229"), - mustParseBint("39313342971440420743886205808435276857969423334439022"), - mustParseBint("106864745815244621469904686507414016500244950054730550"), - mustParseBint("290488496652474252310856821116798256667646950902969802"), - mustParseBint("789629601826806951609780226351082242199561951153523307"), - mustParseBint("2146435797859160646242977615312608803692259060547978973"), - mustParseBint("5834617425274548814029027346103910190036592389411081058"), - mustParseBint("15860134523134307281296446257746601251762039501345261543"), - mustParseBint("43112315471151952271134222928569253907888636167803477308"), - mustParseBint("117191423728026113087729397911901945216753636944618223835"), - mustParseBint("318559317571137562203286717012986459995422099051810077532"), - mustParseBint("865934004239937469536069327192649342497018547001959865915"), - mustParseBint("2353852668370199854078999107490348045088716172545554672367"), - mustParseBint("6398434935300549492226634035155708188793366213968552794550"), - mustParseBint("17392749415205010473946813036112352261479840577250084010371"), - mustParseBint("47278394682293465614744575627442803708197519623809381709672"), - mustParseBint("128516001143593082758092996321430992578011432207588258719200"), - mustParseBint("349342710574850953480347972334060995334116564975181542601261"), - mustParseBint("949611942060244887451336491171183231018171589210799878504382"), - mustParseBint("2581312886190067396232858002152733804316370829930440608106140"), - mustParseBint("7016735912097631738654715998861174054559379987253219837545489"), - mustParseBint("19073465724950996905250998409538484473881897305437834024752347"), - mustParseBint("51847055285870724640874533229334853848274691005838464019040569"), - mustParseBint("140934908242693879644921433123701687886847607900637140170526193"), - mustParseBint("383100800071657684930356954878619938987055974551165775908346028"), - mustParseBint("1041375943302908779718347293349379643980467133154913248052087720"), - mustParseBint("2830753303274693900442063548014074540850325893535906840720731339"), - mustParseBint("7694785265142017138182745590129393992070767572650840919231681173"), - mustParseBint("20916594960129961539070711572146737781529668474992672656676676057"), - mustParseBint("56857199993359322226403488206332533033721583344882177434891220735"), - mustParseBint("154553893559010393035307669111746200683637170969308302467116768062"), - mustParseBint("420121040379051425495659343071916176841111197329909678646425729420"), - mustParseBint("1142007389815684283662957183144765630198045959556395839565027991758"), - mustParseBint("3104297935701919908707342141107100372062950176763708815107564010774"), - mustParseBint("8438356668741454489073329480373117960080692679667410404618178186988"), - mustParseBint("22937831594696098790993528402686136004632793409030482301381199511167"), - mustParseBint("62351490808116168829092387089284697448313918462357999143885916990140"), - mustParseBint("169488924441033371414178361143719749489262362255165049131572696453162"), - mustParseBint("460718663433129154267731844280600868933490030370960407306440545574167"), - mustParseBint("1252363170842213780513521960744365767534885274044974816408022857210242"), - mustParseBint("3404276049931740521376907187004350595373876139945651636051545736600125"), - mustParseBint("9253781725587787600242397916687345873476599207208413119353845239598413"), - mustParseBint("25154386709191670062657811742521129614074129733831405138218401569861105"), - mustParseBint("68376712297627438667558928266777109559458359312890877256686727658114853"), - mustParseBint("185867174528412798034037018125454119469463966962328032683933850866499093"), - mustParseBint("505239363027610419455703833218576464853672449756171770789213166551930106"), - mustParseBint("1373382979540176187784188529808538931579983079249937463822561704858035705"), - mustParseBint("3733241996799001640254908317264700143427783686916000023393828672448903946"), - mustParseBint("10148003881138887278324617841317169757766648151681178808763635653226535478"), - mustParseBint("27585134545231702062864698199026619433415201752487088590995883625110505109"), - mustParseBint("74984169969901204346756305912240604547046589777861588130171222791280558952"), - mustParseBint("203828106651266876683231375371726323746973648615242102353428236178115964699"), - mustParseBint("554062238439351005257117339583166129248567288326853228703001882820457004497"), - mustParseBint("1506097314585030548352594130167674981899396492128265421629867495043027091398"), - mustParseBint("4093996962127454696660914229327829043200537921938527777647428991700125373374"), - mustParseBint("11128637547917594120870714781839408057340769207204930341930032294439923480142"), - mustParseBint("30250773222011423382665663964434287424690322223040881602116084211601897768842"), - mustParseBint("82230127146229135103043280164077746954862861884762740395239338497441610348757"), - mustParseBint("223524660373471504744306573233271473987753925132099739429441837680417972801971"), - mustParseBint("607603022505687214952232893813027607526137532596212101484085761453808043968143"), - mustParseBint("1651636254994001855528329796264858767069628842000044813888811507530815559084855"), - mustParseBint("4489612819174345246284245579645316277765980586371851526049317217652687150894562"), - mustParseBint("12204032943178408020027100351363697539707464210997675462443438298243127273585772"), - mustParseBint("33174000983357426257555161078525919096030145811823308270488072600691470127989678"), - mustParseBint("90176284050342989314009959821709052591287461132007268331792149066465537579218609"), - mustParseBint("245124554292008578555277294311091534234875641496469060954583388360415063258824081"), - mustParseBint("666317621641089583424481405024087326268738875420965655939985025716548852338674439"), - mustParseBint("1811239082889023282193798758098815925047897174544128618703060579473814364244597447"), - mustParseBint("4923458286012058399754862059113304494837799571252660279409509621865019936779306778"), - mustParseBint("13383347192042695004617364087061150290767174572136446001205548731904473876766495093"), - mustParseBint("36379709476088045792877438267601857298931012558640829628754924149828121778270335566"), - mustParseBint("98890303193469467705600309671380371014050826071993351734019971537110944470074060060"), + mustParseBint("100000000000000000000000000000000000000000"), + mustParseBint("271828182845904523536028747135266249775725"), + mustParseBint("738905609893065022723042746057500781318032"), + mustParseBint("2008553692318766774092852965458171789698791"), + mustParseBint("5459815003314423907811026120286087840279074"), + mustParseBint("14841315910257660342111558004055227962348767"), + mustParseBint("40342879349273512260838718054338827960589990"), + mustParseBint("109663315842845859926372023828812143244221913"), + mustParseBint("298095798704172827474359209945288867375596794"), + mustParseBint("810308392757538400770999668943275996501147609"), + mustParseBint("2202646579480671651695790064528424436635351262"), + mustParseBint("5987414171519781845532648579225778161426107970"), + mustParseBint("16275479141900392080800520489848678317020928448"), + mustParseBint("44241339200892050332610277594908828178439130606"), + mustParseBint("120260428416477677774923677076785944941248654338"), + mustParseBint("326901737247211063930185504609172131550573854382"), + mustParseBint("888611052050787263676302374078145035080271982186"), + mustParseBint("2415495275357529821477543518038582387986756735272"), + mustParseBint("6565996913733051113878650325906003356921635578619"), + mustParseBint("17848230096318726084491003378872270388361973316517"), + mustParseBint("48516519540979027796910683054154055868463898894485"), + mustParseBint("131881573448321469720999888374530278509144443738048"), + mustParseBint("358491284613159156168115994597842068922269306503727"), + mustParseBint("974480344624890260003463268482297527764938776403601"), + mustParseBint("2648912212984347229413916215281188234087019861924853"), + mustParseBint("7200489933738587252416135146612615791522353381339528"), + mustParseBint("19572960942883876426977639787609534279203610095069759"), + mustParseBint("53204824060179861668374730434117744165925580428368881"), + mustParseBint("144625706429147517367704742299692885690206232950992288"), + mustParseBint("393133429714404207438862058084352768579694233344390219"), + mustParseBint("1068647458152446214699046865074140165002449500547305499"), + mustParseBint("2904884966524742523108568211167982566676469509029698025"), + mustParseBint("7896296018268069516097802263510822421995619511535233066"), + mustParseBint("21464357978591606462429776153126088036922590605479789726"), + mustParseBint("58346174252745488140290273461039101900365923894110810578"), + mustParseBint("158601345231343072812964462577466012517620395013452615427"), + mustParseBint("431123154711519522711342229285692539078886361678034773077"), + mustParseBint("1171914237280261130877293979119019452167536369446182238348"), + mustParseBint("3185593175711375622032867170129864599954220990518100775324"), + mustParseBint("8659340042399374695360693271926493424970185470019598659152"), + mustParseBint("23538526683701998540789991074903480450887161725455546723665"), + mustParseBint("63984349353005494922266340351557081887933662139685527945496"), + mustParseBint("173927494152050104739468130361123522614798405772500840103706"), + mustParseBint("472783946822934656147445756274428037081975196238093817096720"), + mustParseBint("1285160011435930827580929963214309925780114322075882587192003"), + mustParseBint("3493427105748509534803479723340609953341165649751815426012609"), + mustParseBint("9496119420602448874513364911711832310181715892107998785043817"), + mustParseBint("25813128861900673962328580021527338043163708299304406081061397"), + mustParseBint("70167359120976317386547159988611740545593799872532198375454888"), + mustParseBint("190734657249509969052509984095384844738818973054378340247523471"), + mustParseBint("518470552858707246408745332293348538482746910058384640190405693"), + mustParseBint("1409349082426938796449214331237016878868476079006371401705261930"), + mustParseBint("3831008000716576849303569548786199389870559745511657759083460282"), + mustParseBint("10413759433029087797183472933493796439804671331549132480520877196"), + mustParseBint("28307533032746939004420635480140745408503258935359068407207313389"), + mustParseBint("76947852651420171381827455901293939920707675726508409192316811729"), + mustParseBint("209165949601299615390707115721467377815296684749926726566766760571"), + mustParseBint("568571999933593222264034882063325330337215833448821774348912207348"), + mustParseBint("1545538935590103930353076691117462006836371709693083024671167680619"), + mustParseBint("4201210403790514254956593430719161768411111973299096786464257294200"), + mustParseBint("11420073898156842836629571831447656301980459595563958395650279917582"), + mustParseBint("31042979357019199087073421411071003720629501767637088151075640107741"), + mustParseBint("84383566687414544890733294803731179600806926796674104046181781869882"), + mustParseBint("229378315946960987909935284026861360046327934090304823013811995111671"), + mustParseBint("623514908081161688290923870892846974483139184623579991438859169901398"), + mustParseBint("1694889244410333714141783611437197494892623622551650491315726964531624"), + mustParseBint("4607186634331291542677318442806008689334900303709604073064405455741671"), + mustParseBint("12523631708422137805135219607443657675348852740449748164080228572102416"), + mustParseBint("34042760499317405213769071870043505953738761399456516360515457366001246"), + mustParseBint("92537817255877876002423979166873458734765992072084131193538452395984132"), + mustParseBint("251543867091916700626578117425211296140741297338314051382184015698611046"), + mustParseBint("683767122976274386675589282667771095594583593128908772566867276581148527"), + mustParseBint("1858671745284127980340370181254541194694639669623280326839338508664990931"), + mustParseBint("5052393630276104194557038332185764648536724497561717707892131665519301059"), + mustParseBint("13733829795401761877841885298085389315799830792499374638225617048580357052"), + mustParseBint("37332419967990016402549083172647001434277836869160000233938286724489039463"), + mustParseBint("101480038811388872783246178413171697577666481516811788087636356532265354778"), + mustParseBint("275851345452317020628646981990266194334152017524870885909958836251105051085"), + mustParseBint("749841699699012043467563059122406045470465897778615881301712227912805589523"), + mustParseBint("2038281066512668766832313753717263237469736486152421023534282361781159646993"), + mustParseBint("5540622384393510052571173395831661292485672883268532287030018828204570044975"), + mustParseBint("15060973145850305483525941301676749818993964921282654216298674950430270913981"), + mustParseBint("40939969621274546966609142293278290432005379219385277776474289917001253733742"), + mustParseBint("111286375479175941208707147818394080573407692072049303419300322944399234801420"), + mustParseBint("302507732220114233826656639644342874246903222230408816021160842116018977688417"), + mustParseBint("822301271462291351030432801640777469548628618847627403952393384974416103487573"), + mustParseBint("2235246603734715047443065732332714739877539251320997394294418376804179728019707"), + mustParseBint("6076030225056872149522328938130276075261375325962121014840857614538080439681426"), + mustParseBint("16516362549940018555283297962648587670696288420000448138888115075308155590848548"), + mustParseBint("44896128191743452462842455796453162777659805863718515260493172176526871508945617"), + mustParseBint("122040329431784080200271003513636975397074642109976754624434382982431272735857720"), + mustParseBint("331740009833574262575551610785259190960301458118233082704880726006914701279896785"), + mustParseBint("901762840503429893140099598217090525912874611320072683317921490664655375792186090"), + mustParseBint("2451245542920085785552772943110915342348756414964690609545833883604150632588240812"), + mustParseBint("6663176216410895834244814050240873262687388754209656559399850257165488523386744387"), + mustParseBint("18112390828890232821937987580988159250478971745441286187030605794738143642445974469"), + mustParseBint("49234582860120583997548620591133044948377995712526602794095096218650199367793067780"), + mustParseBint("133833471920426950046173640870611502907671745721364460012055487319044738767664950934"), + mustParseBint("363797094760880457928774382676018572989310125586408296287549241498281217782703355658"), + mustParseBint("988903031934694677056003096713803710140508260719933517340199715371109444700740600601"), } -// blog is a cache of natural logarithms, where blog[x] = round(ln(x) * 10^40). +// blog is a cache of natural logarithms, where blog[x] = round(ln(x) * 10^41). var blog = [...]*bint{ nil, mustParseBint("0"), - mustParseBint("6931471805599453094172321214581765680755"), - mustParseBint("10986122886681096913952452369225257046475"), - mustParseBint("13862943611198906188344642429163531361510"), - mustParseBint("16094379124341003746007593332261876395256"), - mustParseBint("17917594692280550008124773583807022727230"), - mustParseBint("19459101490553133051053527434431797296371"), - mustParseBint("20794415416798359282516963643745297042265"), - mustParseBint("21972245773362193827904904738450514092950"), - mustParseBint("23025850929940456840179914546843642076011"), - mustParseBint("23978952727983705440619435779651292998217"), - mustParseBint("24849066497880003102297094798388788407985"), - mustParseBint("25649493574615367360534874415653186048053"), - mustParseBint("26390573296152586145225848649013562977126"), - mustParseBint("27080502011022100659960045701487133441731"), - mustParseBint("27725887222397812376689284858327062723020"), - mustParseBint("28332133440562160802495346178731265355882"), - mustParseBint("28903717578961646922077225953032279773705"), - mustParseBint("29444389791664404600090274318878535372374"), - mustParseBint("29957322735539909934352235761425407756766"), - mustParseBint("30445224377234229965005979803657054342846"), - mustParseBint("30910424533583158534791756994233058678972"), - mustParseBint("31354942159291496908067528318101961184424"), - mustParseBint("31780538303479456196469416012970554088740"), - mustParseBint("32188758248682007492015186664523752790512"), - mustParseBint("32580965380214820454707195630234951728808"), - mustParseBint("32958368660043290741857357107675771139425"), - mustParseBint("33322045101752039239398169863595328657881"), - mustParseBint("33672958299864740271832720323619116054945"), - mustParseBint("34011973816621553754132366916068899122486"), - mustParseBint("34339872044851462459291643245423572104499"), - mustParseBint("34657359027997265470861606072908828403775"), - mustParseBint("34965075614664802354571888148876550044692"), - mustParseBint("35263605246161613896667667393313031036637"), - mustParseBint("35553480614894136797061120766693673691627"), - mustParseBint("35835189384561100016249547167614045454460"), - mustParseBint("36109179126442244443680956710314471639001"), - mustParseBint("36375861597263857694262595533460301053129"), - mustParseBint("36635616461296464274487326784878443094528"), - mustParseBint("36888794541139363028524556976007173437521"), - mustParseBint("37135720667043078038667633730374075883764"), - mustParseBint("37376696182833683059178301018238820023601"), - mustParseBint("37612001156935624234728425133458470355591"), - mustParseBint("37841896339182611628964078208814824359727"), - mustParseBint("38066624897703197573912498070712390488206"), - mustParseBint("38286413964890950002239849532683726865179"), - mustParseBint("38501476017100585868209506697721737088961"), - mustParseBint("38712010109078909290641737227552319769495"), - mustParseBint("38918202981106266102107054868863594592742"), - mustParseBint("39120230054281460586187507879105518471267"), - mustParseBint("39318256327243257716447798547956522402357"), - mustParseBint("39512437185814273548879516844816717409563"), - mustParseBint("39702919135521218341444691390290577703600"), - mustParseBint("39889840465642743836029678322257536820180"), - mustParseBint("40073331852324709186627029111913169393473"), - mustParseBint("40253516907351492333570491078177094338636"), - mustParseBint("40430512678345501514042726688103792418849"), - mustParseBint("40604430105464193366005041538200881735700"), - mustParseBint("40775374439057194506160503737196976240633"), - mustParseBint("40943445622221006848304688130650664803241"), - mustParseBint("41108738641733112487513891034256147463157"), - mustParseBint("41271343850450915553463964460005337785254"), - mustParseBint("41431347263915326878958432172882311389321"), - mustParseBint("41588830833596718565033927287490594084530"), - mustParseBint("41743872698956371106542467747915062443309"), - mustParseBint("41896547420264255448744209363458315725447"), - mustParseBint("42046926193909660596700719963637227505669"), - mustParseBint("42195077051761066990839988607894796717392"), - mustParseBint("42341065045972593822019980687327218230899"), - mustParseBint("42484952420493589891233441981275439372382"), - mustParseBint("42626798770413154213294545325130340967596"), - mustParseBint("42766661190160553110421868382195811135215"), - mustParseBint("42904594411483911290921088574385425709048"), - mustParseBint("43040650932041697537853277924896237319756"), - mustParseBint("43174881135363104405967639033749009836987"), - mustParseBint("43307333402863310788434916748042066733884"), - mustParseBint("43438054218536838491672963214083090294588"), - mustParseBint("43567088266895917368659647999460208775283"), - mustParseBint("43694478524670214941729455414814109221735"), - mustParseBint("43820266346738816122696878190588939118276"), - mustParseBint("43944491546724387655809809476901028185900"), - mustParseBint("44067192472642531132839954944955841564519"), - mustParseBint("44188406077965979234754722232913704530293"), - mustParseBint("44308167988433136153350622232820585704356"), - mustParseBint("44426512564903164548502939510993141751138"), - mustParseBint("44543472962535077328900746348040236036346"), - mustParseBint("44659081186545837185785172692844373101420"), - mustParseBint("44773368144782064723136399423396590040482"), - mustParseBint("44886363697321398383178155406698492194047"), - mustParseBint("44998096703302650668084819285294156168961"), - mustParseBint("45108595065168500411588401850084983344424"), - mustParseBint("45217885770490403096412170747265492545934"), - mustParseBint("45325994931532559373244095614648829150974"), - mustParseBint("45432947822700038962381827912303502769716"), - mustParseBint("45538768916005408346097867651140411767630"), - mustParseBint("45643481914678362384814058442134085450250"), - mustParseBint("45747109785033828221167216217039617138089"), - mustParseBint("45849674786705719196279376083445360273497"), - mustParseBint("45951198501345899268524340518101807091167"), + mustParseBint("69314718055994530941723212145817656807550"), + mustParseBint("109861228866810969139524523692252570464749"), + mustParseBint("138629436111989061883446424291635313615100"), + mustParseBint("160943791243410037460075933322618763952560"), + mustParseBint("179175946922805500081247735838070227272299"), + mustParseBint("194591014905531330510535274344317972963708"), + mustParseBint("207944154167983592825169636437452970422650"), + mustParseBint("219722457733621938279049047384505140929498"), + mustParseBint("230258509299404568401799145468436420760110"), + mustParseBint("239789527279837054406194357796512929982171"), + mustParseBint("248490664978800031022970947983887884079849"), + mustParseBint("256494935746153673605348744156531860480527"), + mustParseBint("263905732961525861452258486490135629771258"), + mustParseBint("270805020110221006599600457014871334417309"), + mustParseBint("277258872223978123766892848583270627230200"), + mustParseBint("283321334405621608024953461787312653558820"), + mustParseBint("289037175789616469220772259530322797737048"), + mustParseBint("294443897916644046000902743188785353723738"), + mustParseBint("299573227355399099343522357614254077567660"), + mustParseBint("304452243772342299650059798036570543428458"), + mustParseBint("309104245335831585347917569942330586789721"), + mustParseBint("313549421592914969080675283181019611844238"), + mustParseBint("317805383034794561964694160129705540887399"), + mustParseBint("321887582486820074920151866645237527905120"), + mustParseBint("325809653802148204547071956302349517288077"), + mustParseBint("329583686600432907418573571076757711394247"), + mustParseBint("333220451017520392393981698635953286578808"), + mustParseBint("336729582998647402718327203236191160549451"), + mustParseBint("340119738166215537541323669160688991224859"), + mustParseBint("343398720448514624592916432454235721044994"), + mustParseBint("346573590279972654708616060729088284037750"), + mustParseBint("349650756146648023545718881488765500446920"), + mustParseBint("352636052461616138966676673933130310366370"), + mustParseBint("355534806148941367970611207666936736916269"), + mustParseBint("358351893845611000162495471676140454544598"), + mustParseBint("361091791264422444436809567103144716390008"), + mustParseBint("363758615972638576942625955334603010531288"), + mustParseBint("366356164612964642744873267848784430945276"), + mustParseBint("368887945411393630285245569760071734375210"), + mustParseBint("371357206670430780386676337303740758837641"), + mustParseBint("373766961828336830591783010182388200236008"), + mustParseBint("376120011569356242347284251334584703555914"), + mustParseBint("378418963391826116289640782088148243597271"), + mustParseBint("380666248977031975739124980707123904882058"), + mustParseBint("382864139648909500022398495326837268651788"), + mustParseBint("385014760171005858682095066977217370889605"), + mustParseBint("387120101090789092906417372275523197694949"), + mustParseBint("389182029811062661021070548688635945927417"), + mustParseBint("391202300542814605861875078791055184712670"), + mustParseBint("393182563272432577164477985479565224023569"), + mustParseBint("395124371858142735488795168448167174095627"), + mustParseBint("397029191355212183414446913902905777035998"), + mustParseBint("398898404656427438360296783222575368201797"), + mustParseBint("400733318523247091866270291119131693934731"), + mustParseBint("402535169073514923335704910781770943386359"), + mustParseBint("404305126783455015140427266881037924188487"), + mustParseBint("406044301054641933660050415382008817357001"), + mustParseBint("407753744390571945061605037371969762406335"), + mustParseBint("409434456222210068483046881306506648032409"), + mustParseBint("411087386417331124875138910342561474631568"), + mustParseBint("412713438504509155534639644600053377852544"), + mustParseBint("414313472639153268789584321728823113893207"), + mustParseBint("415888308335967185650339272874905940845300"), + mustParseBint("417438726989563711065424677479150624433087"), + mustParseBint("418965474202642554487442093634583157254470"), + mustParseBint("420469261939096605967007199636372275056693"), + mustParseBint("421950770517610669908399886078947967173920"), + mustParseBint("423410650459725938220199806873272182308987"), + mustParseBint("424849524204935898912334419812754393723819"), + mustParseBint("426267987704131542132945453251303409675958"), + mustParseBint("427666611901605531104218683821958111352148"), + mustParseBint("429045944114839112909210885743854257090475"), + mustParseBint("430406509320416975378532779248962373197558"), + mustParseBint("431748811353631044059676390337490098369869"), + mustParseBint("433073334028633107884349167480420667338838"), + mustParseBint("434380542185368384916729632140830902945879"), + mustParseBint("435670882668959173686596479994602087752826"), + mustParseBint("436944785246702149417294554148141092217354"), + mustParseBint("438202663467388161226968781905889391182760"), + mustParseBint("439444915467243876558098094769010281858996"), + mustParseBint("440671924726425311328399549449558415645191"), + mustParseBint("441884060779659792347547222329137045302931"), + mustParseBint("443081679884331361533506222328205857043558"), + mustParseBint("444265125649031645485029395109931417511380"), + mustParseBint("445434729625350773289007463480402360363464"), + mustParseBint("446590811865458371857851726928443731014200"), + mustParseBint("447733681447820647231363994233965900404821"), + mustParseBint("448863636973213983831781554066984921940466"), + mustParseBint("449980967033026506680848192852941561689608"), + mustParseBint("451085950651685004115884018500849833444235"), + mustParseBint("452178857704904030964121707472654925459338"), + mustParseBint("453259949315325593732440956146488291509743"), + mustParseBint("454329478227000389623818279123035027697155"), + mustParseBint("455387689160054083460978676511404117676298"), + mustParseBint("456434819146783623848140584421340854502499"), + mustParseBint("457471097850338282211672162170396171380891"), + mustParseBint("458496747867057191962793760834453602734967"), + mustParseBint("459511985013458992685243405181018070911669"), } -// bnlog10 is a cache of multiples of the natural logarithm of 10, where bnlog10[x] = round(x * ln(10) * 10^40). +// bnlog10 is a cache of multiples of the natural logarithm of 10, where bnlog10[x] = round(x * ln(10) * 10^41). var bnlog10 = [...]*bint{ mustParseBint("0"), - mustParseBint("23025850929940456840179914546843642076011"), - mustParseBint("46051701859880913680359829093687284152022"), - mustParseBint("69077552789821370520539743640530926228033"), - mustParseBint("92103403719761827360719658187374568304044"), - mustParseBint("115129254649702284200899572734218210380055"), - mustParseBint("138155105579642741041079487281061852456066"), - mustParseBint("161180956509583197881259401827905494532077"), - mustParseBint("184206807439523654721439316374749136608088"), - mustParseBint("207232658369464111561619230921592778684099"), mustParseBint("230258509299404568401799145468436420760110"), - mustParseBint("253284360229345025241979060015280062836121"), - mustParseBint("276310211159285482082158974562123704912132"), - mustParseBint("299336062089225938922338889108967346988143"), - mustParseBint("322361913019166395762518803655810989064154"), - mustParseBint("345387763949106852602698718202654631140165"), - mustParseBint("368413614879047309442878632749498273216176"), - mustParseBint("391439465808987766283058547296341915292187"), - mustParseBint("414465316738928223123238461843185557368198"), - mustParseBint("437491167668868679963418376390029199444209"), mustParseBint("460517018598809136803598290936872841520220"), - mustParseBint("483542869528749593643778205483716483596231"), - mustParseBint("506568720458690050483958120030560125672242"), - mustParseBint("529594571388630507324138034577403767748253"), - mustParseBint("552620422318570964164317949124247409824264"), - mustParseBint("575646273248511421004497863671091051900275"), - mustParseBint("598672124178451877844677778217934693976286"), - mustParseBint("621697975108392334684857692764778336052297"), - mustParseBint("644723826038332791525037607311621978128308"), - mustParseBint("667749676968273248365217521858465620204319"), mustParseBint("690775527898213705205397436405309262280330"), - mustParseBint("713801378828154162045577350952152904356341"), - mustParseBint("736827229758094618885757265498996546432352"), - mustParseBint("759853080688035075725937180045840188508363"), - mustParseBint("782878931617975532566117094592683830584375"), - mustParseBint("805904782547915989406297009139527472660386"), - mustParseBint("828930633477856446246476923686371114736397"), - mustParseBint("851956484407796903086656838233214756812408"), - mustParseBint("874982335337737359926836752780058398888419"), - mustParseBint("898008186267677816767016667326902040964430"), mustParseBint("921034037197618273607196581873745683040441"), - mustParseBint("944059888127558730447376496420589325116452"), - mustParseBint("967085739057499187287556410967432967192463"), - mustParseBint("990111589987439644127736325514276609268474"), - mustParseBint("1013137440917380100967916240061120251344485"), - mustParseBint("1036163291847320557808096154607963893420496"), - mustParseBint("1059189142777261014648276069154807535496507"), - mustParseBint("1082214993707201471488455983701651177572518"), - mustParseBint("1105240844637141928328635898248494819648529"), - mustParseBint("1128266695567082385168815812795338461724540"), mustParseBint("1151292546497022842008995727342182103800551"), - mustParseBint("1174318397426963298849175641889025745876562"), - mustParseBint("1197344248356903755689355556435869387952573"), - mustParseBint("1220370099286844212529535470982713030028584"), - mustParseBint("1243395950216784669369715385529556672104595"), - mustParseBint("1266421801146725126209895300076400314180606"), - mustParseBint("1289447652076665583050075214623243956256617"), - mustParseBint("1312473503006606039890255129170087598332628"), - mustParseBint("1335499353936546496730435043716931240408639"), - mustParseBint("1358525204866486953570614958263774882484650"), mustParseBint("1381551055796427410410794872810618524560661"), - mustParseBint("1404576906726367867250974787357462166636672"), - mustParseBint("1427602757656308324091154701904305808712683"), - mustParseBint("1450628608586248780931334616451149450788694"), - mustParseBint("1473654459516189237771514530997993092864705"), - mustParseBint("1496680310446129694611694445544836734940716"), - mustParseBint("1519706161376070151451874360091680377016727"), - mustParseBint("1542732012306010608292054274638524019092738"), - mustParseBint("1565757863235951065132234189185367661168749"), - mustParseBint("1588783714165891521972414103732211303244760"), mustParseBint("1611809565095831978812594018279054945320771"), - mustParseBint("1634835416025772435652773932825898587396782"), - mustParseBint("1657861266955712892492953847372742229472793"), - mustParseBint("1680887117885653349333133761919585871548804"), - mustParseBint("1703912968815593806173313676466429513624815"), - mustParseBint("1726938819745534263013493591013273155700826"), - mustParseBint("1749964670675474719853673505560116797776837"), - mustParseBint("1772990521605415176693853420106960439852848"), - mustParseBint("1796016372535355633534033334653804081928859"), - mustParseBint("1819042223465296090374213249200647724004870"), mustParseBint("1842068074395236547214393163747491366080881"), - mustParseBint("1865093925325177004054573078294335008156892"), - mustParseBint("1888119776255117460894752992841178650232903"), - mustParseBint("1911145627185057917734932907388022292308914"), - mustParseBint("1934171478114998374575112821934865934384925"), - mustParseBint("1957197329044938831415292736481709576460936"), - mustParseBint("1980223179974879288255472651028553218536947"), - mustParseBint("2003249030904819745095652565575396860612958"), - mustParseBint("2026274881834760201935832480122240502688969"), - mustParseBint("2049300732764700658776012394669084144764980"), mustParseBint("2072326583694641115616192309215927786840991"), - mustParseBint("2095352434624581572456372223762771428917002"), - mustParseBint("2118378285554522029296552138309615070993013"), - mustParseBint("2141404136484462486136732052856458713069024"), - mustParseBint("2164429987414402942976911967403302355145035"), - mustParseBint("2187455838344343399817091881950145997221046"), - mustParseBint("2210481689274283856657271796496989639297057"), - mustParseBint("2233507540204224313497451711043833281373068"), - mustParseBint("2256533391134164770337631625590676923449079"), - mustParseBint("2279559242064105227177811540137520565525090"), + mustParseBint("2302585092994045684017991454684364207601101"), + mustParseBint("2532843602293450252419790600152800628361212"), + mustParseBint("2763102111592854820821589745621237049121322"), + mustParseBint("2993360620892259389223388891089673469881432"), + mustParseBint("3223619130191663957625188036558109890641542"), + mustParseBint("3453877639491068526026987182026546311401652"), + mustParseBint("3684136148790473094428786327494982732161762"), + mustParseBint("3914394658089877662830585472963419152921873"), + mustParseBint("4144653167389282231232384618431855573681983"), + mustParseBint("4374911676688686799634183763900291994442093"), + mustParseBint("4605170185988091368035982909368728415202203"), + mustParseBint("4835428695287495936437782054837164835962313"), + mustParseBint("5065687204586900504839581200305601256722423"), + mustParseBint("5295945713886305073241380345774037677482533"), + mustParseBint("5526204223185709641643179491242474098242644"), + mustParseBint("5756462732485114210044978636710910519002754"), + mustParseBint("5986721241784518778446777782179346939762864"), + mustParseBint("6216979751083923346848576927647783360522974"), + mustParseBint("6447238260383327915250376073116219781283084"), + mustParseBint("6677496769682732483652175218584656202043194"), + mustParseBint("6907755278982137052053974364053092622803304"), + mustParseBint("7138013788281541620455773509521529043563415"), + mustParseBint("7368272297580946188857572654989965464323525"), + mustParseBint("7598530806880350757259371800458401885083635"), + mustParseBint("7828789316179755325661170945926838305843745"), + mustParseBint("8059047825479159894062970091395274726603855"), + mustParseBint("8289306334778564462464769236863711147363965"), + mustParseBint("8519564844077969030866568382332147568124076"), + mustParseBint("8749823353377373599268367527800583988884186"), + mustParseBint("8980081862676778167670166673269020409644296"), + mustParseBint("9210340371976182736071965818737456830404406"), + mustParseBint("9440598881275587304473764964205893251164516"), + mustParseBint("9670857390574991872875564109674329671924626"), + mustParseBint("9901115899874396441277363255142766092684736"), + mustParseBint("10131374409173801009679162400611202513444847"), + mustParseBint("10361632918473205578080961546079638934204957"), + mustParseBint("10591891427772610146482760691548075354965067"), + mustParseBint("10822149937072014714884559837016511775725177"), + mustParseBint("11052408446371419283286358982484948196485287"), + mustParseBint("11282666955670823851688158127953384617245397"), + mustParseBint("11512925464970228420089957273421821038005507"), + mustParseBint("11743183974269632988491756418890257458765618"), + mustParseBint("11973442483569037556893555564358693879525728"), + mustParseBint("12203700992868442125295354709827130300285838"), + mustParseBint("12433959502167846693697153855295566721045948"), + mustParseBint("12664218011467251262098953000764003141806058"), + mustParseBint("12894476520766655830500752146232439562566168"), + mustParseBint("13124735030066060398902551291700875983326278"), + mustParseBint("13354993539365464967304350437169312404086389"), + mustParseBint("13585252048664869535706149582637748824846499"), + mustParseBint("13815510557964274104107948728106185245606609"), + mustParseBint("14045769067263678672509747873574621666366719"), + mustParseBint("14276027576563083240911547019043058087126829"), + mustParseBint("14506286085862487809313346164511494507886939"), + mustParseBint("14736544595161892377715145309979930928647050"), + mustParseBint("14966803104461296946116944455448367349407160"), + mustParseBint("15197061613760701514518743600916803770167270"), + mustParseBint("15427320123060106082920542746385240190927380"), + mustParseBint("15657578632359510651322341891853676611687490"), + mustParseBint("15887837141658915219724141037322113032447600"), + mustParseBint("16118095650958319788125940182790549453207710"), + mustParseBint("16348354160257724356527739328258985873967821"), + mustParseBint("16578612669557128924929538473727422294727931"), + mustParseBint("16808871178856533493331337619195858715488041"), + mustParseBint("17039129688155938061733136764664295136248151"), + mustParseBint("17269388197455342630134935910132731557008261"), + mustParseBint("17499646706754747198536735055601167977768371"), + mustParseBint("17729905216054151766938534201069604398528481"), + mustParseBint("17960163725353556335340333346538040819288592"), + mustParseBint("18190422234652960903742132492006477240048702"), + mustParseBint("18420680743952365472143931637474913660808812"), + mustParseBint("18650939253251770040545730782943350081568922"), + mustParseBint("18881197762551174608947529928411786502329032"), + mustParseBint("19111456271850579177349329073880222923089142"), + mustParseBint("19341714781149983745751128219348659343849253"), + mustParseBint("19571973290449388314152927364817095764609363"), + mustParseBint("19802231799748792882554726510285532185369473"), + mustParseBint("20032490309048197450956525655753968606129583"), + mustParseBint("20262748818347602019358324801222405026889693"), + mustParseBint("20493007327647006587760123946690841447649803"), + mustParseBint("20723265836946411156161923092159277868409913"), + mustParseBint("20953524346245815724563722237627714289170024"), + mustParseBint("21183782855545220292965521383096150709930134"), + mustParseBint("21414041364844624861367320528564587130690244"), + mustParseBint("21644299874144029429769119674033023551450354"), + mustParseBint("21874558383443433998170918819501459972210464"), + mustParseBint("22104816892742838566572717964969896392970574"), + mustParseBint("22335075402042243134974517110438332813730684"), + mustParseBint("22565333911341647703376316255906769234490795"), + mustParseBint("22795592420641052271778115401375205655250905"), } // mustParseBint converts a string to *big.Int, panicking on error. @@ -787,6 +787,10 @@ func (z *bint) setInt64(x int64) { (*big.Int)(z).SetInt64(x) } +func (z *bint) setBytes(buf []byte) { + (*big.Int)(z).SetBytes(buf) +} + func (z *bint) setFint(x fint) { (*big.Int)(z).SetUint64(uint64(x)) }