package decimal import ( "bytes" "encoding" "encoding/json" "fmt" "io" "math" "math/big" "regexp" "runtime" "strconv" "strings" "github.com/ericlagergren/decimal/internal/arith" "github.com/ericlagergren/decimal/internal/c" ) const ( // Radix is the base in which decimal arithmetic is // performed. Radix = 10 // IsCanonical is true since Big decimals are always // normalized. IsCanonical = true ) // Big is a floating-point, arbitrary-precision // // It is represented as a number and a scale. A scale greater // than zero indicates the number of decimal digits after the // radix. Otherwise, the number is multiplied by 10 to the power // of the negation of the scale. More formally, // // Big = number × 10**-scale // // with MinScale <= scale <= MaxScale. A Big may also be ±0, // ±Infinity, or ±NaN (either quiet or signaling). Non-NaN Big // values are ordered, defined as the result of x.Cmp(y). // // Additionally, each Big value has a contextual object which // governs arithmetic operations. type Big struct { // Context is the decimal's unique contextual object. Context Context // unscaled is only used if the decimal is too large to fit // in compact. unscaled big.Int // compact is use if the value fits into an uint64. The scale // does not affect whether this field is used. If a decimal // has 20 or fewer digits, this field will be used. compact uint64 // exp is the negated scale, meaning // // number × 10**exp = number × 10**-scale // exp int // precision is the current precision. precision int // form indicates whether a decimal is a finite number, an // infinity, or a NaN value and whether it's signed or not. form form } var ( _ fmt.Formatter = (*Big)(nil) _ fmt.Scanner = (*Big)(nil) _ fmt.Stringer = (*Big)(nil) _ json.Unmarshaler = (*Big)(nil) _ encoding.TextUnmarshaler = (*Big)(nil) _ decomposer = (*Big)(nil) ) // form indicates whether a decimal is a finite number, an // infinity, or a nan value and whether it's signed or not. type form uint8 const ( // Particular bits: // // 0: sign bit // 1: infinity // 2: signaling nan // 3: quiet nan // 4-7: unused finite form = 0 // default, all zeros; do not re-order this constant. signbit form = 1 << 0 // do not assign this; used to check for signedness. pinf form = 1 << 1 // may compare with ==, &, etc. ninf form = pinf | signbit // may compare with ==, &, etc. inf form = pinf // do not assign this; used to check for either infinity. snan form = 1 << 2 // compare with bitwise & only due to ssnan qnan form = 1 << 3 // compare with bitwise & only due to sqnan ssnan form = snan | signbit // primarily for printing, signbit sqnan form = qnan | signbit // primarily for printing, signbit nan form = snan | qnan // do not assign this; used to check for either NaN. special = inf | nan // do not assign this; used to check for a special value. ) func (f form) String() string { // GDA versions. Go needs to be handled manually. switch f { case finite: return "finite" case finite | signbit: return "-finite" case snan: return "sNaN" case snan | signbit: return "-sNaN" case qnan: return "NaN" case qnan | signbit: return "-NaN" case pinf: return "Infinity" case ninf: return "-Infinity" default: return fmt.Sprintf("unknown form: %0.8b", f) } } // Payload is a NaN value's payload. type Payload uint64 //go:generate stringer -type Payload -linecomment const ( absvalue Payload = iota + 1 // absolute value of NaN acos // acos with NaN as an operand addinfinf // addition of infinities with opposing signs addition // addition with NaN as an operand asin // asin with NaN as an operand atan // atan with NaN as an operand atan2 // atan2 with NaN as an operand comparison // comparison with NaN as an operand cos // cos with NaN as an operand division // division with NaN as an operand exp // exp with NaN as an operand invctxomode // operation with an invalid OperatingMode invctxpgtu // operation with a precision greater than MaxPrecision invctxpltz // operation with a precision less than zero invctxrmode // operation with an invalid RoundingMode invctxsgtu // operation with a scale greater than MaxScale invctxsltu // operation with a scale lesser than MinScale log // log with NaN as an operand log10 // log10 with NaN as an operand mul0inf // multiplication of zero with infinity multiplication // multiplication with NaN as an operand negation // negation with NaN as an operand nextminus // next-minus with NaN as an operand nextplus // next-plus with NaN as an operand quantinf // quantization of an infinity quantization // quantization with NaN as an operand quantminmax // quantization exceeds minimum or maximum scale quantprec // quantization exceeds working precision quo00 // division of zero by zero quoinfinf // division of infinity by infinity quointprec // result of integer division was larger than the desired precision quorem_ // integer division or remainder has too many digits quotermexp // division with unlimited precision has a non-terminating decimal expansion reduction // reduction with NaN as an operand reminfy // remainder of infinity remprec // result of remainder operation was larger than the desired precision remx0 // remainder by zero sin // sin with NaN as an operand subinfinf // subtraction of infinities with opposing signs subtraction // subtraction with NaN as an operand ) // An ErrNaN is used when a decimal operation would lead to a NaN under IEEE-754 // rules. An ErrNaN implements the error interface. type ErrNaN struct { Msg string } func (e ErrNaN) Error() string { return e.Msg } var _ error = ErrNaN{} // Canonical sets z to the canonical form of z. // // Since Big values are always canonical, it's identical to Copy. func (z *Big) Canonical(x *Big) *Big { return z.Copy(x) } // CheckNaNs checks if either x or y is NaN. // // If so, it follows the rules of NaN handling set forth in the // GDA specification. The argument y may be nil. It reports // whether either condition is a NaN. func (z *Big) CheckNaNs(x, y *Big) bool { return z.invalidContext(z.Context) || z.checkNaNs(x, y, 0) } func (z *Big) checkNaNs(x, y *Big, op Payload) bool { var yform form if y != nil { yform = y.form } f := (x.form | yform) & nan if f == 0 { return false } form := qnan var cond Condition if f&snan != 0 { cond = InvalidOperation if x.form&snan != 0 { form |= (x.form & signbit) } else { form |= (y.form & signbit) } } else if x.form&nan != 0 { form |= (x.form & signbit) } else { form |= (y.form & signbit) } z.setNaN(cond, form, op) return true } func (z *Big) xflow(exp int, over, neg bool) *Big { // over == overflow // neg == intermediate result < 0 if over { // TODO(eric): actually choose the largest finite number in the current // precision. This is legacy now. // // NOTE(eric): in some situations, the decimal library tells us to set // z to "the largest finite number that can be represented in the // current precision..." Use signed Infinity instead. // // Because of the logic above, every rounding mode works out to the // following. if neg { z.form = ninf } else { z.form = pinf } z.Context.Conditions |= Overflow | Inexact | Rounded return z } var sign form if neg { sign = signbit } z.setZero(sign, exp) z.Context.Conditions |= Underflow | Inexact | Rounded | Subnormal return z } // These methods are here to prevent typos. func (x *Big) isCompact() bool { return x.compact != c.Inflated } func (x *Big) isInflated() bool { return !x.isCompact() } func (x *Big) isSpecial() bool { return x.form&special != 0 } // isZero reports whether x is zero. // // Only use after checking for specials. func (x *Big) isZero() bool { if debug { if x.isSpecial() { panic("isZero called on a special value") } } return x.compact == 0 } // adjusted returns the adjusted exponent. // // The adjusted exponent is the exponent of x when expressed in // scientific notation with one digit before the radix. func (x *Big) adjusted() int { return (x.exp + x.Precision()) - 1 } // etiny returns the minimum exponent of a subnormal result. func (c Context) etiny() int { return c.emin() - (c.precision() - 1) } // etop returns the maximum exponent of an overflow result. func (c Context) etop() int { return c.emax() - (c.precision() - 1) } // Abs sets z to the absolute value of x and returns z. func (z *Big) Abs(x *Big) *Big { return z.Context.Abs(z, x) } // Add sets z to x + y and returns z. func (z *Big) Add(x, y *Big) *Big { return z.Context.Add(z, x, y) } // Class returns the "class" of x, which is one of the following: // // sNaN // NaN // -Infinity // -Normal // -Subnormal // -Zero // +Zero // +Subnormal // +Normal // +Infinity // func (x *Big) Class() string { if x.IsNaN(0) { if x.IsNaN(+1) { return "NaN" } return "sNaN" } if x.Signbit() { if x.IsInf(0) { return "-Infinity" } if x.isZero() { return "-Zero" } if x.IsSubnormal() { return "-Subnormal" } return "-Normal" } if x.IsInf(0) { return "+Infinity" } if x.isZero() { return "+Zero" } if x.IsSubnormal() { return "+Subnormal" } return "+Normal" } // Cmp compares x and y and returns: // // -1 if x < y // 0 if x == y // +1 if x > y // // It does not modify x or y. The result is undefined if either // x or y are NaN. // // For an abstract comparison with NaN values, see CmpTotal. func (x *Big) Cmp(y *Big) int { if debug { x.validate() y.validate() } return cmp(x, y, false) } // CmpAbs compares |x| and |y| and returns: // // -1 if |x| < |y| // 0 if |x| == |y| // +1 if |x| > |y| // // It does not modify x or y. The result is undefined if either // x or y are NaN. // // For an abstract comparison with NaN values, see // CmpTotalAbs. func (x *Big) CmpAbs(y *Big) int { if debug { x.validate() y.validate() } return cmp(x, y, true) } func cmpInt(x *Big, y int64) int { switch { case x.Signbit() && y >= 0: return -1 case !x.Signbit() && y < 0: return +1 default: return cmpAbsInt(x, y) } } func cmpAbsInt(x *Big, y int64) int { u := uint64(y) // Same scales, so compare straight across. if x.exp == 0 { // If the scales are the same and x x is not compact, // then by definition it's larger than y. if !x.isCompact() { return +1 } return arith.Cmp(x.compact, u) } // Signs are the same and the scales differ. Compare the // lengths of their integral parts; if they differ in length // one number is larger. // E.g.: 1234.01 // 1230011 xl := x.adjusted() yl := arith.Length(u) - 1 if xl != yl { if xl < yl { return -1 } return +1 } // The length of the integral parts match. Rescale x, then // compare straight across. t, ok := scalex(x.compact, x.exp) if !ok { if x.exp > 0 { // Overflow. return +1 } // Underflow. return -1 } return arith.Cmp(t, u) } // cmp is the implementation for both Cmp and CmpAbs. func cmp(x, y *Big, abs bool) int { if x == y { return 0 } // NaN cmp x // z cmp NaN // NaN cmp NaN if (x.form|y.form)&nan != 0 { return 0 } // Fast path: Catches non-finite forms like zero and ±Inf, // possibly signed. xs := x.ord(abs) ys := y.ord(abs) if xs != ys { if xs > ys { return +1 } return -1 } switch xs { case 0, +2, -2: return 0 default: r := cmpabs(x, y) if xs < 0 && !abs { r = -r } return r } } // ord returns similar to Sign except -Inf is -2 and +Inf is +2. func (x *Big) ord(abs bool) int { if x.form&inf != 0 { if x.form == pinf || abs { return +2 } return -2 } r := x.Sign() if abs && r < 0 { r = -r } return r } func cmpabs(x, y *Big) int { // Same scales means we can compare straight across. if x.exp == y.exp { if x.isCompact() { if y.isCompact() { return arith.Cmp(x.compact, y.compact) } return -1 // y.isInflateed } if y.isCompact() { return +1 // !x.isCompact } return x.unscaled.CmpAbs(&y.unscaled) } // Signs are the same and the scales differ. Compare the // lengths of their integral parts; if they differ in length // one number is larger. // E.g.: 1234.01 // 123.011 xl := x.adjusted() yl := y.adjusted() if xl != yl { if xl < yl { return -1 } return +1 } diff := int64(x.exp) - int64(y.exp) shift := uint64(arith.Abs(diff)) if arith.Safe(shift) && x.isCompact() && y.isCompact() { p, _ := arith.Pow10(shift) if diff < 0 { return arith.CmpShift(x.compact, y.compact, p) } return -arith.CmpShift(y.compact, x.compact, p) } xw, yw := x.unscaled.Bits(), y.unscaled.Bits() if x.isCompact() { xw = arith.Words(x.compact) } if y.isCompact() { yw = arith.Words(y.compact) } var tmp big.Int if diff < 0 { yw = arith.MulBigPow10(&tmp, tmp.SetBits(copybits(yw)), shift).Bits() } else { xw = arith.MulBigPow10(&tmp, tmp.SetBits(copybits(xw)), shift).Bits() } return arith.CmpBits(xw, yw) } // CmpTotal compares x and y in a manner similar to the Big.Cmp, // but allows ordering of all abstract representations. // // In particular, this means NaN values have a defined ordering. // From lowest to highest the ordering is: // // -NaN // -sNaN // -Infinity // -127 // -1.00 // -1 // -0.000 // -0 // +0 // +1.2300 // +1.23 // +1E+9 // +Infinity // +sNaN // +NaN // func (x *Big) CmpTotal(y *Big) int { if debug { x.validate() y.validate() } xs := x.ordTotal(false) ys := y.ordTotal(false) if xs != ys { if xs > ys { return +1 } return -1 } if xs != 0 { return 0 } return x.Cmp(y) } // CmpTotalAbs is like CmpTotal but instead compares the absolute // values of x and y. func (x *Big) CmpTotalAbs(y *Big) int { if debug { x.validate() y.validate() } xs := x.ordTotal(true) ys := y.ordTotal(true) if xs != ys { if xs > ys { return +1 } return -1 } if xs != 0 { return 0 } return x.CmpAbs(y) } func (x *Big) ordTotal(abs bool) (r int) { // -2 == -qnan // -1 == -snan // 0 == not nan // +1 == snan // +2 == qnan if x.IsNaN(0) { if x.IsNaN(+1) { // qnan r = +2 } else { r = +1 } if !abs && x.Signbit() { r = -r } } return r } // Copy sets z to a copy of x and returns z. func (z *Big) Copy(x *Big) *Big { if debug { x.validate() } if z != x { sign := x.form & signbit z.copyAbs(x) z.form |= sign } return z } // copyAbs sets z to a copy of |x| and returns z. func (z *Big) copyAbs(x *Big) *Big { if z != x { z.precision = x.Precision() z.exp = x.exp z.compact = x.compact if x.IsFinite() && x.isInflated() { z.unscaled.Set(&x.unscaled) } } z.form = x.form & ^signbit return z } // CopyAbs is like Abs, but no flags are changed and the result // is not rounded. func (z *Big) CopyAbs(x *Big) *Big { if debug { x.validate() } return z.copyAbs(x) } // CopyNeg is like Neg, but no flags are changed and the result // is not rounded. func (z *Big) CopyNeg(x *Big) *Big { if debug { x.validate() } xform := x.form // in case z == x z.copyAbs(x) z.form = xform ^ signbit return z } // CopySign sets z to x with the sign of y and returns z. // // It accepts NaN values. func (z *Big) CopySign(x, y *Big) *Big { if debug { x.validate() y.validate() } // Pre-emptively capture signbit in case z == y. sign := y.form & signbit z.copyAbs(x) z.form |= sign return z } // Float64 returns x as a float64 and a bool indicating whether // x can fit into a float64 without truncation, overflow, or // underflow. // // Special values are considered exact; however, special values // that occur because the magnitude of x is too large to be // represented as a float64 are not. func (x *Big) Float64() (f float64, ok bool) { if debug { x.validate() } if !x.IsFinite() { switch x.form { case pinf, ninf: return math.Inf(int(x.form & signbit)), true case snan, qnan: return math.NaN(), true case ssnan, sqnan: return math.Copysign(math.NaN(), -1), true } } const ( maxMantissa = 1<<53 + 1 // largest exact mantissa ) parse := false switch xc := x.compact; { case !x.isCompact(): parse = true case x.isZero(): f = 0 ok = true case x.exp == 0: f = float64(xc) ok = xc < maxMantissa || (xc&(xc-1)) == 0 case x.exp > 0: f = float64(x.compact) * math.Pow10(x.exp) ok = x.compact < maxMantissa && !math.IsInf(f, 0) && !math.IsNaN(f) case x.exp < 0: f = float64(x.compact) / math.Pow10(-x.exp) ok = x.compact < maxMantissa && !math.IsInf(f, 0) && !math.IsNaN(f) default: parse = true } if parse { f, _ = strconv.ParseFloat(x.String(), 64) ok = !math.IsInf(f, 0) && !math.IsNaN(f) } if x.form&signbit != 0 { f = math.Copysign(f, -1) } return f, ok } // Float sets z, which may be nil, to x and returns z. // // The result is undefined if z is a NaN value. func (x *Big) Float(z *big.Float) *big.Float { if debug { x.validate() } if z == nil { z = new(big.Float) } switch x.form { case finite, finite | signbit: if x.isZero() { z.SetUint64(0) } else { z.SetRat(x.Rat(nil)) } case pinf, ninf: z.SetInf(x.form == pinf) default: // snan, qnan, ssnan, sqnan: z.SetUint64(0) } return z } // Format implements the fmt.Formatter interface. // // The following verbs are supported: // // %s: -dddd.dd or -d.dddd±edd, depending on x // %d: same as %s // %v: same as %s // %e: -d.dddd±edd // %E: -d.dddd±Edd // %f: -dddd.dd // %g: same as %f // // While width is honored in the same manner as the fmt package (the minimum // width of the formatted number), precision is the number of significant digits // in the decimal number. Given %f, however, precision is the number of digits // following the radix. // // Format honors all flags (such as '+' and ' ') in the same manner as the fmt // package, except for '#'. Unless used in conjunction with %v, %q, or %p, the // '#' flag will be ignored; decimals have no defined hexadeximal or octal // representation. // // %+v, %#v, %T, %#p, and %p all honor the formats specified in the fmt // package's documentation. func (x *Big) Format(s fmt.State, c rune) { if debug { x.validate() } prec, hasPrec := s.Precision() if !hasPrec { prec = x.Precision() } width, hasWidth := s.Width() if !hasWidth { width = noWidth } var ( hash = s.Flag('#') dash = s.Flag('-') lpZero = s.Flag('0') lpSpace = width != noWidth && !dash && !lpZero plus = s.Flag('+') space = s.Flag(' ') f = formatter{prec: prec, width: width} e = sciE[x.Context.OperatingMode] ) // If we need to left pad then we need to first write our // string into an // empty buffer. tmpbuf := lpZero || lpSpace if tmpbuf { b := new(strings.Builder) b.Grow(x.Precision()) f.w = b } else { f.w = stateWrapper{s} } if plus { f.sign = '+' } else if space { f.sign = ' ' } // noE is a placeholder for formats that do not use scientific notation // and don't require 'e' or 'E' const noE = 0 switch c { case 's', 'd': f.format(x, normal, e) case 'q': // The fmt package's docs specify that the '+' flag // "guarantee[s] ASCII-only output for %q (%+q)" f.sign = 0 // Since no other escaping is needed we can do it ourselves and save // whatever overhead running it through fmt.Fprintf would incur. quote := byte('"') if hash { quote = '`' } f.WriteByte(quote) f.format(x, normal, e) f.WriteByte(quote) case 'e', 'E': f.format(x, sci, byte(c)) case 'f', 'F': if !hasPrec { prec = 0 } else { // %f's precision means "number of digits after the radix" if x.exp > 0 { f.prec += (x.exp + x.Precision()) } else { if adj := x.exp + x.Precision(); adj > -f.prec { f.prec += adj } else { f.prec = -f.prec } } } f.format(x, plain, noE) case 'g', 'G': // %g's precision means "number of significant digits" f.format(x, plain, noE) // Make sure we return from the following two cases. case 'v': // %v == %s if !hash && !plus { f.format(x, normal, e) break } // This is the easiest way of doing it. Note we can't use type Big Big, // even though it's declared inside a function. Go thinks it's recursive. // At least the fields are checked at compile time. type Big struct { Context Context unscaled big.Int compact uint64 exp int precision int form form } specs := "" if dash { specs += "-" } else if lpZero { specs += "0" } if hash { specs += "#" } else if plus { specs += "+" } else if space { specs += " " } fmt.Fprintf(s, "%"+specs+"v", (*Big)(x)) return default: fmt.Fprintf(s, "%%!%c(*Big=%s)", c, x.String()) return } // Need padding out to width. if f.n < int64(width) { switch pad := int64(width) - f.n; { case dash: io.CopyN(s, spaceReader{}, pad) case lpZero: io.CopyN(s, zeroReader{}, pad) case lpSpace: io.CopyN(s, spaceReader{}, pad) } } if tmpbuf { // fmt's internal state type implements stringWriter I think. io.WriteString(s, f.w.(*strings.Builder).String()) } } // FMA sets z to (x * y) + u without any intermediate rounding. func (z *Big) FMA(x, y, u *Big) *Big { return z.Context.FMA(z, x, y, u) } // Int sets z, which may be nil, to x, truncating the fractional // portion (if any) and returns z. // // If x is an infinity or a NaN value the result is undefined. func (x *Big) Int(z *big.Int) *big.Int { if debug { x.validate() } if z == nil { z = new(big.Int) } if !x.IsFinite() { return z } if x.isCompact() { z.SetUint64(x.compact) } else { z.Set(&x.unscaled) } if x.Signbit() { z.Neg(z) } if x.exp == 0 { return z } return bigScalex(z, z, x.exp) } // Int64 returns x as an int64, truncating towards zero. // // The bool result indicates whether the conversion to an int64 // was successful. func (x *Big) Int64() (int64, bool) { if debug { x.validate() } if !x.IsFinite() { return 0, false } // x might be too large to fit into an int64 *now*, but // rescaling x might shrink it enough. See issue #20. if !x.isCompact() { xb := x.Int(nil) return xb.Int64(), xb.IsInt64() } u := x.compact if x.exp != 0 { var ok bool if u, ok = scalex(u, x.exp); !ok { return 0, false } } su := int64(u) if su >= 0 || x.Signbit() && su == -su { if x.Signbit() { su = -su } return su, true } return 0, false } // Uint64 returns x as a uint64, truncating towards zero. // // The bool result indicates whether the conversion to a uint64 // was successful. func (x *Big) Uint64() (uint64, bool) { if debug { x.validate() } if !x.IsFinite() || x.Signbit() { return 0, false } // x might be too large to fit into an uint64 *now*, but // rescaling x might shrink it enough. See issue #20. if !x.isCompact() { xb := x.Int(nil) return xb.Uint64(), xb.IsUint64() } b := x.compact if x.exp == 0 { return b, true } return scalex(b, x.exp) } // IsFinite reports whether x is finite. func (x *Big) IsFinite() bool { return x.form & ^signbit == 0 } // IsNormal reports whether x is normal. func (x *Big) IsNormal() bool { return x.IsFinite() && x.adjusted() >= x.Context.emin() } // IsSubnormal reports whether x is subnormal. func (x *Big) IsSubnormal() bool { return x.IsFinite() && x.adjusted() < x.Context.emin() } // IsInf reports whether x is an infinity according to sign. // If sign > 0, IsInf reports whether x is positive infinity. // If sign < 0, IsInf reports whether x is negative infinity. // If sign == 0, IsInf reports whether x is either infinity. func (x *Big) IsInf(sign int) bool { return sign >= 0 && x.form == pinf || sign <= 0 && x.form == ninf } // IsNaN reports whether x is NaN. // If sign > 0, IsNaN reports whether x is quiet NaN. // If sign < 0, IsNaN reports whether x is signaling NaN. // If sign == 0, IsNaN reports whether x is either NaN. func (x *Big) IsNaN(quiet int) bool { return quiet >= 0 && x.form&qnan == qnan || quiet <= 0 && x.form&snan == snan } // IsInt reports whether x is an integer. // // Infinity and NaN values are not integers. func (x *Big) IsInt() bool { if debug { x.validate() } if !x.IsFinite() { return false } // 0, 5000, 40 if x.isZero() || x.exp >= 0 { return true } xp := x.Precision() exp := x.exp // 0.001 // 0.5 if -exp >= xp { return false } // 44.00 // 1.000 if x.isCompact() { for v := x.compact; v%10 == 0; v /= 10 { exp++ } // Avoid the overhead of copying x.unscaled if we know // for a fact it's not an integer. } else if x.unscaled.Bit(0) == 0 { v := new(big.Int).Set(&x.unscaled) r := new(big.Int) for { v.QuoRem(v, c.TenInt, r) if r.Sign() != 0 { break } exp++ } } return exp >= 0 } // Mantissa returns the mantissa of x and reports whether the // mantissa fits into a uint64 and x is finite. // // This may be used to convert a decimal representing a monetary // value to its most basic unit (e.g., $123.45 to 12345 cents). func (x *Big) Mantissa() (uint64, bool) { return x.compact, x.IsFinite() && x.compact != c.Inflated } // MarshalText implements encoding.TextMarshaler. func (x *Big) MarshalText() ([]byte, error) { if debug { x.validate() } if x == nil { return []byte(""), nil } var ( b = new(bytes.Buffer) f = formatter{w: b, prec: x.Precision(), width: noWidth} e = sciE[x.Context.OperatingMode] ) b.Grow(x.Precision()) f.format(x, normal, e) return b.Bytes(), nil } // Max returns the greater of the provided values. // // The result is undefined if no values are are provided. func Max(a, b *Big) *Big { v := a.Cmp(b) if v >= 0 { return a } return b } // MaxAbs returns the greater of the absolute value of the provided values. // // The result is undefined if no values are provided. func MaxAbs(x ...*Big) *Big { m := x[0] for _, v := range x[1:] { if v.CmpAbs(m) > 0 { m = v } } return m } // Min returns the lesser of the provided values. // // The result is undefined if no values are are provided. func Min(x ...*Big) *Big { m := x[0] for _, v := range x[1:] { if v.Cmp(m) < 0 { m = v } } return m } // MinAbs returns the lesser of the absolute value of the // provided values. // // The result is undefined if no values are provided. func MinAbs(x ...*Big) *Big { m := x[0] for _, v := range x[1:] { if v.CmpAbs(m) < 0 { m = v } } return m } // maxfor sets z to 999...n with the provided sign. func maxfor(z *big.Int, n, sign int) { arith.Sub(z, arith.BigPow10(uint64(n)), 1) if sign < 0 { z.Neg(z) } } // Mul sets z to x * y and returns z. func (z *Big) Mul(x, y *Big) *Big { return z.Context.Mul(z, x, y) } // Neg sets z to -x and returns z. // // If x is positive infinity, z will be set to negative infinity // and vice versa. If x == 0, z will be set to zero. It is an // error if x is a NaN value func (z *Big) Neg(x *Big) *Big { return z.Context.Neg(z, x) } // New creates a new Big decimal with the given value and scale. // // For example: // // New(1234, 3) // 1.234 // New(42, 0) // 42 // New(4321, 5) // 0.04321 // New(-1, 0) // -1 // New(3, -10) // 30 000 000 000 // func New(value int64, scale int) *Big { return new(Big).SetMantScale(value, scale) } // Payload returns the payload of x, provided x is a NaN value. // // If x is not a NaN value, the result is undefined. func (x *Big) Payload() Payload { if !x.IsNaN(0) { return 0 } return Payload(x.compact) } // Precision returns the number of digits in the unscaled form of // x. // // x == 0 has a precision of 1. The result is undefined if x is // not finite. func (x *Big) Precision() int { // Cannot call validate since validate calls this method. if !x.IsFinite() { return 0 } if x.precision == 0 { return 1 } return x.precision } // Quantize sets z to the number equal in value and sign to z // with the scale, n. // // z is rounded according to z.Context.RoundingMode. To perform // truncation, set z.Context.RoundingMode to ToZero. func (z *Big) Quantize(n int) *Big { return z.Context.Quantize(z, n) } // Quo sets z to x / y and returns z. func (z *Big) Quo(x, y *Big) *Big { return z.Context.Quo(z, x, y) } // QuoInt sets z to x / y with the remainder truncated. See QuoRem for more // details. func (z *Big) QuoInt(x, y *Big) *Big { return z.Context.QuoInt(z, x, y) } // QuoRem sets z to the quotient x / y and r to the remainder x % y, such that // x = z * y + r, and returns the pair (z, r). func (z *Big) QuoRem(x, y, r *Big) (*Big, *Big) { return z.Context.QuoRem(z, x, y, r) } // Rat sets z, which may be nil, to x and returns z. // // The result is undefined if x is an infinity or NaN value. func (x *Big) Rat(z *big.Rat) *big.Rat { if debug { x.validate() } if z == nil { z = new(big.Rat) } if !x.IsFinite() { return z.SetInt64(0) } // Fast path for decimals <= math.MaxInt64. if x.IsInt() { if u, ok := x.Int64(); ok { // If profiled we can call scalex ourselves and save // the overhead of calling Int64. But I doubt it'll // matter much. return z.SetInt64(u) } } num := new(big.Int) if x.isCompact() { num.SetUint64(x.compact) } else { num.Set(&x.unscaled) } if x.exp > 0 { arith.MulBigPow10(num, num, uint64(x.exp)) } if x.Signbit() { num.Neg(num) } denom := c.OneInt if x.exp < 0 { denom = new(big.Int) if shift, ok := arith.Pow10(uint64(-x.exp)); ok { denom.SetUint64(shift) } else { denom.Set(arith.BigPow10(uint64(-x.exp))) } } return z.SetFrac(num, denom) } // Raw directly returns x's raw compact and unscaled values. // // Caveat emptor: neither are guaranteed to be valid. Raw is // intended to support missing functionality outside this package // and should generally be avoided. Additionally, Raw is the only // part of this package's API that is not guaranteed to remain // stable. This means the function could change or disappear at // any time, even across minor version numbers. func Raw(x *Big) (*uint64, *big.Int) { return &x.compact, &x.unscaled } // Reduce reduces a finite z to its most simplest form. func (z *Big) Reduce() *Big { return z.Context.Reduce(z) } // Rem sets z to the remainder x % y. See QuoRem for more details. func (z *Big) Rem(x, y *Big) *Big { return z.Context.Rem(z, x, y) } // Round rounds z down to n digits of precision and returns z. // // The result is undefined if z is not finite. No rounding will // occur if n <= 0. The result of Round will always be in the // interval [⌊10**p⌋, z] where p = the precision of z. func (z *Big) Round(n int) *Big { ctx := z.Context ctx.Precision = n return ctx.Round(z) } // RoundToInt rounds z down to an integral value. func (z *Big) RoundToInt() *Big { return z.Context.RoundToInt(z) } // SameQuantum reports whether x and y have the same exponent // (scale). func (x *Big) SameQuantum(y *Big) bool { return x.Scale() == y.Scale() } // SetSignbit sets z to -z if sign is true, otherwise to +z. func (z *Big) SetSignbit(sign bool) *Big { if sign { z.form |= signbit } else { z.form &^= signbit } return z } // Scale returns x's scale. func (x *Big) Scale() int { return -x.exp } // Scan implements fmt.Scanner. func (z *Big) Scan(state fmt.ScanState, verb rune) error { return z.scan(byteReader{state}) } // Set sets z to x and returns z. // // The result might be rounded depending on z.Context, even if // z == x. func (z *Big) Set(x *Big) *Big { return z.Context.Set(z, x) } // setShared sets z to x, but does not copy. // // z may possibly alias x. func (z *Big) setShared(x *Big) *Big { if debug { x.validate() } if z != x { z.precision = x.Precision() z.compact = x.compact z.form = x.form z.exp = x.exp z.unscaled = x.unscaled } return z } // SetBigMantScale sets z to the given value and scale. func (z *Big) SetBigMantScale(value *big.Int, scale int) *Big { // Do this first in case value == z.unscaled. Don't want to // clobber the sign. z.form = finite if value.Sign() < 0 { z.form |= signbit } z.unscaled.Abs(value) z.compact = c.Inflated z.precision = arith.BigLength(value) if z.unscaled.IsUint64() { if v := z.unscaled.Uint64(); v != c.Inflated { z.compact = v } } z.exp = -scale return z } // SetFloat sets z to exactly x and returns z. func (z *Big) SetFloat(x *big.Float) *Big { if x.IsInf() { if x.Signbit() { z.form = ninf } else { z.form = pinf } return z } neg := x.Signbit() if x.Sign() == 0 { if neg { z.form |= signbit } z.compact = 0 z.precision = 1 return z } z.exp = 0 x0 := new(big.Float).Copy(x).SetPrec(big.MaxPrec) x0.Abs(x0) if !x.IsInt() { for !x0.IsInt() { x0.Mul(x0, c.TenFloat) z.exp-- } } if mant, acc := x0.Uint64(); acc == big.Exact { z.compact = mant z.precision = arith.Length(mant) } else { z.compact = c.Inflated x0.Int(&z.unscaled) z.precision = arith.BigLength(&z.unscaled) } z.form = finite if neg { z.form |= signbit } return z } // SetFloat64 sets z to exactly x. func (z *Big) SetFloat64(x float64) *Big { if x == 0 { var sign form if math.Signbit(x) { sign = signbit } return z.setZero(sign, 0) } if math.IsNaN(x) { var sign form if math.Signbit(x) { sign = signbit } return z.setNaN(0, qnan|sign, 0) } if math.IsInf(x, 0) { if math.IsInf(x, 1) { z.form = pinf } else { z.form = ninf } return z } // The gist of the following is lifted from math/big/rat.go, // but adapted for base-10 decimals. const expMask = 1<<11 - 1 bits := math.Float64bits(x) mantissa := bits & (1<<52 - 1) exp := int((bits >> 52) & expMask) if exp == 0 { // denormal exp -= 1022 } else { // normal mantissa |= 1 << 52 exp -= 1023 } if mantissa == 0 { return z.SetUint64(0) } shift := 52 - exp for mantissa&1 == 0 && shift > 0 { mantissa >>= 1 shift-- } z.exp = 0 z.form = finite | form(bits>>63) if shift > 0 { z.unscaled.SetUint64(uint64(shift)) z.unscaled.Exp(c.FiveInt, &z.unscaled, nil) arith.Mul(&z.unscaled, &z.unscaled, mantissa) z.exp = -shift } else { // TODO(eric): figure out why this doesn't work for // _some_ numbers. See // https://github.com/ericlagergren/decimal/issues/89 // // z.compact = mantissa << uint(-shift) // z.precision = arith.Length(z.compact) z.compact = c.Inflated z.unscaled.SetUint64(mantissa) z.unscaled.Lsh(&z.unscaled, uint(-shift)) } return z.norm() } // SetInf sets z to -Inf if signbit is set or +Inf is signbit is // not set, and returns z. func (z *Big) SetInf(signbit bool) *Big { if signbit { z.form = ninf } else { z.form = pinf } return z } // SetMantScale sets z to the given value and scale. func (z *Big) SetMantScale(value int64, scale int) *Big { z.SetUint64(arith.Abs(value)) z.exp = -scale if value < 0 { z.form |= signbit } return z } // setNaN is an internal NaN-setting method that panics when the // OperatingMode is Go. func (z *Big) setNaN(c Condition, f form, p Payload) *Big { z.form = f z.compact = uint64(p) z.Context.Conditions |= c if z.Context.OperatingMode == Go { panic(ErrNaN{Msg: z.Context.Conditions.String()}) } return z } // SetNaN sets z to a signaling NaN if signal is true or quiet // NaN otherwise and returns z. // // No conditions are raised. func (z *Big) SetNaN(signal bool) *Big { if signal { z.form = snan } else { z.form = qnan } z.compact = 0 // payload return z } // SetRat sets z to to the possibly rounded value of x and // returns z. func (z *Big) SetRat(x *big.Rat) *Big { return z.Context.SetRat(z, x) } // SetScale sets z's scale to scale and returns z. func (z *Big) SetScale(scale int) *Big { z.exp = -scale return z } // Regexp matches any valid string representing a decimal that // can be passed to SetString. var Regexp = regexp.MustCompile(`(?i)(([+-]?(\d+\.\d*|\.?\d+)([eE][+-]?\d+)?)|(inf(infinity)?))|([+-]?([sq]?nan\d*))`) // SetString sets z to the value of s and returns z. // // s must have one of the following formats: // // 1.234 // 1234 // 1.234e+5 // 1.234E-5 // 0.000001234 // Inf // NaN // qNaN // sNaN // // Each format may be preceded by an optional sign, either "-" or // "+". By default, "Inf" and "NaN" map to "+Inf" and "qNaN", // respectively. NaN values may have optional diagnostic // information, represented as trailing digits; for example, // "NaN123". // // If s does not match one of the allowed formats, the // ConversionSyntax condition is set. // // SetString will only return (nil, false) if a library error // occurs. In general, it safe to ignore the bool result. func (z *Big) SetString(s string) (*Big, bool) { if err := z.scan(strings.NewReader(s)); err != nil { return nil, false } return z, true } func (z *Big) setTriple(compact uint64, sign form, exp int) *Big { z.compact = compact z.precision = arith.Length(compact) z.exp = exp z.form = finite | sign return z } func (z *Big) setZero(sign form, exp int) *Big { z.compact = 0 z.precision = 1 z.exp = exp z.form = finite | sign return z } // SetUint64 is shorthand for SetMantScale(x, 0) for an unsigned // integer. func (z *Big) SetUint64(x uint64) *Big { z.compact = x if x == c.Inflated { z.unscaled.SetUint64(x) } z.precision = arith.Length(x) z.exp = 0 z.form = finite return z } // Sign returns: // // -1 if x < 0 // 0 if x == 0 // +1 if x > 0 // // No distinction is made between +0 and -0. The result is // undefined if x is a NaN value. func (x *Big) Sign() int { if debug { x.validate() } if (x.IsFinite() && x.isZero()) || x.IsNaN(0) { return 0 } if x.form&signbit != 0 { return -1 } return 1 } // Signbit reports whether x is negative, negative zero, negative // infinity, or negative NaN. func (x *Big) Signbit() bool { if debug { x.validate() } return x.form&signbit != 0 } // String returns the string representation of x. // // It's equivalent to the %s verb discussed in the Format // method's documentation. // // Special cases depend on the OperatingMode. func (x *Big) String() string { if x == nil { return "" } var ( b = new(strings.Builder) f = formatter{w: b, prec: x.Precision(), width: noWidth} e = sciE[x.Context.OperatingMode] ) b.Grow(x.Precision()) f.format(x, normal, e) return b.String() } // Sub sets z to x - y and returns z. func (z *Big) Sub(x, y *Big) *Big { return z.Context.Sub(z, x, y) } // UnmarshalJSON implements json.Unmarshaler. func (z *Big) UnmarshalJSON(data []byte) error { if len(data) >= 2 && data[0] == '"' && data[len(data)-1] == '"' { data = data[1 : len(data)-1] } return z.UnmarshalText(data) } // UnmarshalText implements encoding.TextUnmarshaler. func (z *Big) UnmarshalText(data []byte) error { return z.scan(bytes.NewReader(data)) } // validate ensures x's internal state is correct. There's no need for it to // have good performance since it's for debug == true only. func (x *Big) validate() { defer func() { if err := recover(); err != nil { pc, _, _, ok := runtime.Caller(4) if caller := runtime.FuncForPC(pc); ok && caller != nil { fmt.Println("called by:", caller.Name()) } type Big struct { Context Context unscaled big.Int compact uint64 exp int precision int form form } fmt.Printf("%#v\n", (*Big)(x)) panic(err) } }() switch x.form { case finite, finite | signbit: if x.isInflated() { if x.unscaled.IsUint64() && x.unscaled.Uint64() != c.Inflated { panic(fmt.Sprintf("inflated but unscaled == %d", x.unscaled.Uint64())) } if x.unscaled.Sign() < 0 { panic("x.unscaled.Sign() < 0") } if bl, xp := arith.BigLength(&x.unscaled), x.precision; bl != xp { panic(fmt.Sprintf("BigLength (%d) != x.Precision (%d)", bl, xp)) } } if x.isCompact() { if bl, xp := arith.Length(x.compact), x.Precision(); bl != xp { panic(fmt.Sprintf("BigLength (%d) != x.Precision() (%d)", bl, xp)) } } case snan, ssnan, qnan, sqnan, pinf, ninf: // OK case nan: panic(x.form.String()) default: panic(fmt.Sprintf("invalid form %s", x.form)) } }