mirror of
				https://github.com/1Password/onepassword-operator.git
				synced 2025-10-26 09:20:45 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			616 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			616 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Package inf (type inf.Dec) implements "infinite-precision" decimal
 | |
| // arithmetic.
 | |
| // "Infinite precision" describes two characteristics: practically unlimited
 | |
| // precision for decimal number representation and no support for calculating
 | |
| // with any specific fixed precision.
 | |
| // (Although there is no practical limit on precision, inf.Dec can only
 | |
| // represent finite decimals.)
 | |
| //
 | |
| // This package is currently in experimental stage and the API may change.
 | |
| //
 | |
| // This package does NOT support:
 | |
| //  - rounding to specific precisions (as opposed to specific decimal positions)
 | |
| //  - the notion of context (each rounding must be explicit)
 | |
| //  - NaN and Inf values, and distinguishing between positive and negative zero
 | |
| //  - conversions to and from float32/64 types
 | |
| //
 | |
| // Features considered for possible addition:
 | |
| //  + formatting options
 | |
| //  + Exp method
 | |
| //  + combined operations such as AddRound/MulAdd etc
 | |
| //  + exchanging data in decimal32/64/128 formats
 | |
| //
 | |
| package inf // import "gopkg.in/inf.v0"
 | |
| 
 | |
| // TODO:
 | |
| //  - avoid excessive deep copying (quo and rounders)
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"math/big"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| // A Dec represents a signed arbitrary-precision decimal.
 | |
| // It is a combination of a sign, an arbitrary-precision integer coefficient
 | |
| // value, and a signed fixed-precision exponent value.
 | |
| // The sign and the coefficient value are handled together as a signed value
 | |
| // and referred to as the unscaled value.
 | |
| // (Positive and negative zero values are not distinguished.)
 | |
| // Since the exponent is most commonly non-positive, it is handled in negated
 | |
| // form and referred to as scale.
 | |
| //
 | |
| // The mathematical value of a Dec equals:
 | |
| //
 | |
| //  unscaled * 10**(-scale)
 | |
| //
 | |
| // Note that different Dec representations may have equal mathematical values.
 | |
| //
 | |
| //  unscaled  scale  String()
 | |
| //  -------------------------
 | |
| //         0      0    "0"
 | |
| //         0      2    "0.00"
 | |
| //         0     -2    "0"
 | |
| //         1      0    "1"
 | |
| //       100      2    "1.00"
 | |
| //        10      0   "10"
 | |
| //         1     -1   "10"
 | |
| //
 | |
| // The zero value for a Dec represents the value 0 with scale 0.
 | |
| //
 | |
| // Operations are typically performed through the *Dec type.
 | |
| // The semantics of the assignment operation "=" for "bare" Dec values is
 | |
| // undefined and should not be relied on.
 | |
| //
 | |
| // Methods are typically of the form:
 | |
| //
 | |
| //	func (z *Dec) Op(x, y *Dec) *Dec
 | |
| //
 | |
| // and implement operations z = x Op y with the result as receiver; if it
 | |
| // is one of the operands it may be overwritten (and its memory reused).
 | |
| // To enable chaining of operations, the result is also returned. Methods
 | |
| // returning a result other than *Dec take one of the operands as the receiver.
 | |
| //
 | |
| // A "bare" Quo method (quotient / division operation) is not provided, as the
 | |
| // result is not always a finite decimal and thus in general cannot be
 | |
| // represented as a Dec.
 | |
| // Instead, in the common case when rounding is (potentially) necessary,
 | |
| // QuoRound should be used with a Scale and a Rounder.
 | |
| // QuoExact or QuoRound with RoundExact can be used in the special cases when it
 | |
| // is known that the result is always a finite decimal.
 | |
| //
 | |
| type Dec struct {
 | |
| 	unscaled big.Int
 | |
| 	scale    Scale
 | |
| }
 | |
| 
 | |
| // Scale represents the type used for the scale of a Dec.
 | |
| type Scale int32
 | |
| 
 | |
| const scaleSize = 4 // bytes in a Scale value
 | |
| 
 | |
| // Scaler represents a method for obtaining the scale to use for the result of
 | |
| // an operation on x and y.
 | |
| type scaler interface {
 | |
| 	Scale(x *Dec, y *Dec) Scale
 | |
| }
 | |
| 
 | |
| var bigInt = [...]*big.Int{
 | |
| 	big.NewInt(0), big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(4),
 | |
| 	big.NewInt(5), big.NewInt(6), big.NewInt(7), big.NewInt(8), big.NewInt(9),
 | |
| 	big.NewInt(10),
 | |
| }
 | |
| 
 | |
| var exp10cache [64]big.Int = func() [64]big.Int {
 | |
| 	e10, e10i := [64]big.Int{}, bigInt[1]
 | |
| 	for i := range e10 {
 | |
| 		e10[i].Set(e10i)
 | |
| 		e10i = new(big.Int).Mul(e10i, bigInt[10])
 | |
| 	}
 | |
| 	return e10
 | |
| }()
 | |
| 
 | |
| // NewDec allocates and returns a new Dec set to the given int64 unscaled value
 | |
| // and scale.
 | |
| func NewDec(unscaled int64, scale Scale) *Dec {
 | |
| 	return new(Dec).SetUnscaled(unscaled).SetScale(scale)
 | |
| }
 | |
| 
 | |
| // NewDecBig allocates and returns a new Dec set to the given *big.Int unscaled
 | |
| // value and scale.
 | |
| func NewDecBig(unscaled *big.Int, scale Scale) *Dec {
 | |
| 	return new(Dec).SetUnscaledBig(unscaled).SetScale(scale)
 | |
| }
 | |
| 
 | |
| // Scale returns the scale of x.
 | |
| func (x *Dec) Scale() Scale {
 | |
| 	return x.scale
 | |
| }
 | |
| 
 | |
| // Unscaled returns the unscaled value of x for u and true for ok when the
 | |
| // unscaled value can be represented as int64; otherwise it returns an undefined
 | |
| // int64 value for u and false for ok. Use x.UnscaledBig().Int64() to avoid
 | |
| // checking the validity of the value when the check is known to be redundant.
 | |
| func (x *Dec) Unscaled() (u int64, ok bool) {
 | |
| 	u = x.unscaled.Int64()
 | |
| 	var i big.Int
 | |
| 	ok = i.SetInt64(u).Cmp(&x.unscaled) == 0
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // UnscaledBig returns the unscaled value of x as *big.Int.
 | |
| func (x *Dec) UnscaledBig() *big.Int {
 | |
| 	return &x.unscaled
 | |
| }
 | |
| 
 | |
| // SetScale sets the scale of z, with the unscaled value unchanged, and returns
 | |
| // z.
 | |
| // The mathematical value of the Dec changes as if it was multiplied by
 | |
| // 10**(oldscale-scale).
 | |
| func (z *Dec) SetScale(scale Scale) *Dec {
 | |
| 	z.scale = scale
 | |
| 	return z
 | |
| }
 | |
| 
 | |
| // SetUnscaled sets the unscaled value of z, with the scale unchanged, and
 | |
| // returns z.
 | |
| func (z *Dec) SetUnscaled(unscaled int64) *Dec {
 | |
| 	z.unscaled.SetInt64(unscaled)
 | |
| 	return z
 | |
| }
 | |
| 
 | |
| // SetUnscaledBig sets the unscaled value of z, with the scale unchanged, and
 | |
| // returns z.
 | |
| func (z *Dec) SetUnscaledBig(unscaled *big.Int) *Dec {
 | |
| 	z.unscaled.Set(unscaled)
 | |
| 	return z
 | |
| }
 | |
| 
 | |
| // Set sets z to the value of x and returns z.
 | |
| // It does nothing if z == x.
 | |
| func (z *Dec) Set(x *Dec) *Dec {
 | |
| 	if z != x {
 | |
| 		z.SetUnscaledBig(x.UnscaledBig())
 | |
| 		z.SetScale(x.Scale())
 | |
| 	}
 | |
| 	return z
 | |
| }
 | |
| 
 | |
| // Sign returns:
 | |
| //
 | |
| //	-1 if x <  0
 | |
| //	 0 if x == 0
 | |
| //	+1 if x >  0
 | |
| //
 | |
| func (x *Dec) Sign() int {
 | |
| 	return x.UnscaledBig().Sign()
 | |
| }
 | |
| 
 | |
| // Neg sets z to -x and returns z.
 | |
| func (z *Dec) Neg(x *Dec) *Dec {
 | |
| 	z.SetScale(x.Scale())
 | |
| 	z.UnscaledBig().Neg(x.UnscaledBig())
 | |
| 	return z
 | |
| }
 | |
| 
 | |
| // Cmp compares x and y and returns:
 | |
| //
 | |
| //   -1 if x <  y
 | |
| //    0 if x == y
 | |
| //   +1 if x >  y
 | |
| //
 | |
| func (x *Dec) Cmp(y *Dec) int {
 | |
| 	xx, yy := upscale(x, y)
 | |
| 	return xx.UnscaledBig().Cmp(yy.UnscaledBig())
 | |
| }
 | |
| 
 | |
| // Abs sets z to |x| (the absolute value of x) and returns z.
 | |
| func (z *Dec) Abs(x *Dec) *Dec {
 | |
| 	z.SetScale(x.Scale())
 | |
| 	z.UnscaledBig().Abs(x.UnscaledBig())
 | |
| 	return z
 | |
| }
 | |
| 
 | |
| // Add sets z to the sum x+y and returns z.
 | |
| // The scale of z is the greater of the scales of x and y.
 | |
| func (z *Dec) Add(x, y *Dec) *Dec {
 | |
| 	xx, yy := upscale(x, y)
 | |
| 	z.SetScale(xx.Scale())
 | |
| 	z.UnscaledBig().Add(xx.UnscaledBig(), yy.UnscaledBig())
 | |
| 	return z
 | |
| }
 | |
| 
 | |
| // Sub sets z to the difference x-y and returns z.
 | |
| // The scale of z is the greater of the scales of x and y.
 | |
| func (z *Dec) Sub(x, y *Dec) *Dec {
 | |
| 	xx, yy := upscale(x, y)
 | |
| 	z.SetScale(xx.Scale())
 | |
| 	z.UnscaledBig().Sub(xx.UnscaledBig(), yy.UnscaledBig())
 | |
| 	return z
 | |
| }
 | |
| 
 | |
| // Mul sets z to the product x*y and returns z.
 | |
| // The scale of z is the sum of the scales of x and y.
 | |
| func (z *Dec) Mul(x, y *Dec) *Dec {
 | |
| 	z.SetScale(x.Scale() + y.Scale())
 | |
| 	z.UnscaledBig().Mul(x.UnscaledBig(), y.UnscaledBig())
 | |
| 	return z
 | |
| }
 | |
| 
 | |
| // Round sets z to the value of x rounded to Scale s using Rounder r, and
 | |
| // returns z.
 | |
| func (z *Dec) Round(x *Dec, s Scale, r Rounder) *Dec {
 | |
| 	return z.QuoRound(x, NewDec(1, 0), s, r)
 | |
| }
 | |
| 
 | |
| // QuoRound sets z to the quotient x/y, rounded using the given Rounder to the
 | |
| // specified scale.
 | |
| //
 | |
| // If the rounder is RoundExact but the result can not be expressed exactly at
 | |
| // the specified scale, QuoRound returns nil, and the value of z is undefined.
 | |
| //
 | |
| // There is no corresponding Div method; the equivalent can be achieved through
 | |
| // the choice of Rounder used.
 | |
| //
 | |
| func (z *Dec) QuoRound(x, y *Dec, s Scale, r Rounder) *Dec {
 | |
| 	return z.quo(x, y, sclr{s}, r)
 | |
| }
 | |
| 
 | |
| func (z *Dec) quo(x, y *Dec, s scaler, r Rounder) *Dec {
 | |
| 	scl := s.Scale(x, y)
 | |
| 	var zzz *Dec
 | |
| 	if r.UseRemainder() {
 | |
| 		zz, rA, rB := new(Dec).quoRem(x, y, scl, true, new(big.Int), new(big.Int))
 | |
| 		zzz = r.Round(new(Dec), zz, rA, rB)
 | |
| 	} else {
 | |
| 		zz, _, _ := new(Dec).quoRem(x, y, scl, false, nil, nil)
 | |
| 		zzz = r.Round(new(Dec), zz, nil, nil)
 | |
| 	}
 | |
| 	if zzz == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	return z.Set(zzz)
 | |
| }
 | |
| 
 | |
| // QuoExact sets z to the quotient x/y and returns z when x/y is a finite
 | |
| // decimal. Otherwise it returns nil and the value of z is undefined.
 | |
| //
 | |
| // The scale of a non-nil result is "x.Scale() - y.Scale()" or greater; it is
 | |
| // calculated so that the remainder will be zero whenever x/y is a finite
 | |
| // decimal.
 | |
| func (z *Dec) QuoExact(x, y *Dec) *Dec {
 | |
| 	return z.quo(x, y, scaleQuoExact{}, RoundExact)
 | |
| }
 | |
| 
 | |
| // quoRem sets z to the quotient x/y with the scale s, and if useRem is true,
 | |
| // it sets remNum and remDen to the numerator and denominator of the remainder.
 | |
| // It returns z, remNum and remDen.
 | |
| //
 | |
| // The remainder is normalized to the range -1 < r < 1 to simplify rounding;
 | |
| // that is, the results satisfy the following equation:
 | |
| //
 | |
| //  x / y = z + (remNum/remDen) * 10**(-z.Scale())
 | |
| //
 | |
| // See Rounder for more details about rounding.
 | |
| //
 | |
| func (z *Dec) quoRem(x, y *Dec, s Scale, useRem bool,
 | |
| 	remNum, remDen *big.Int) (*Dec, *big.Int, *big.Int) {
 | |
| 	// difference (required adjustment) compared to "canonical" result scale
 | |
| 	shift := s - (x.Scale() - y.Scale())
 | |
| 	// pointers to adjusted unscaled dividend and divisor
 | |
| 	var ix, iy *big.Int
 | |
| 	switch {
 | |
| 	case shift > 0:
 | |
| 		// increased scale: decimal-shift dividend left
 | |
| 		ix = new(big.Int).Mul(x.UnscaledBig(), exp10(shift))
 | |
| 		iy = y.UnscaledBig()
 | |
| 	case shift < 0:
 | |
| 		// decreased scale: decimal-shift divisor left
 | |
| 		ix = x.UnscaledBig()
 | |
| 		iy = new(big.Int).Mul(y.UnscaledBig(), exp10(-shift))
 | |
| 	default:
 | |
| 		ix = x.UnscaledBig()
 | |
| 		iy = y.UnscaledBig()
 | |
| 	}
 | |
| 	// save a copy of iy in case it to be overwritten with the result
 | |
| 	iy2 := iy
 | |
| 	if iy == z.UnscaledBig() {
 | |
| 		iy2 = new(big.Int).Set(iy)
 | |
| 	}
 | |
| 	// set scale
 | |
| 	z.SetScale(s)
 | |
| 	// set unscaled
 | |
| 	if useRem {
 | |
| 		// Int division
 | |
| 		_, intr := z.UnscaledBig().QuoRem(ix, iy, new(big.Int))
 | |
| 		// set remainder
 | |
| 		remNum.Set(intr)
 | |
| 		remDen.Set(iy2)
 | |
| 	} else {
 | |
| 		z.UnscaledBig().Quo(ix, iy)
 | |
| 	}
 | |
| 	return z, remNum, remDen
 | |
| }
 | |
| 
 | |
| type sclr struct{ s Scale }
 | |
| 
 | |
| func (s sclr) Scale(x, y *Dec) Scale {
 | |
| 	return s.s
 | |
| }
 | |
| 
 | |
| type scaleQuoExact struct{}
 | |
| 
 | |
| func (sqe scaleQuoExact) Scale(x, y *Dec) Scale {
 | |
| 	rem := new(big.Rat).SetFrac(x.UnscaledBig(), y.UnscaledBig())
 | |
| 	f2, f5 := factor2(rem.Denom()), factor(rem.Denom(), bigInt[5])
 | |
| 	var f10 Scale
 | |
| 	if f2 > f5 {
 | |
| 		f10 = Scale(f2)
 | |
| 	} else {
 | |
| 		f10 = Scale(f5)
 | |
| 	}
 | |
| 	return x.Scale() - y.Scale() + f10
 | |
| }
 | |
| 
 | |
| func factor(n *big.Int, p *big.Int) int {
 | |
| 	// could be improved for large factors
 | |
| 	d, f := n, 0
 | |
| 	for {
 | |
| 		dd, dm := new(big.Int).DivMod(d, p, new(big.Int))
 | |
| 		if dm.Sign() == 0 {
 | |
| 			f++
 | |
| 			d = dd
 | |
| 		} else {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 	return f
 | |
| }
 | |
| 
 | |
| func factor2(n *big.Int) int {
 | |
| 	// could be improved for large factors
 | |
| 	f := 0
 | |
| 	for ; n.Bit(f) == 0; f++ {
 | |
| 	}
 | |
| 	return f
 | |
| }
 | |
| 
 | |
| func upscale(a, b *Dec) (*Dec, *Dec) {
 | |
| 	if a.Scale() == b.Scale() {
 | |
| 		return a, b
 | |
| 	}
 | |
| 	if a.Scale() > b.Scale() {
 | |
| 		bb := b.rescale(a.Scale())
 | |
| 		return a, bb
 | |
| 	}
 | |
| 	aa := a.rescale(b.Scale())
 | |
| 	return aa, b
 | |
| }
 | |
| 
 | |
| func exp10(x Scale) *big.Int {
 | |
| 	if int(x) < len(exp10cache) {
 | |
| 		return &exp10cache[int(x)]
 | |
| 	}
 | |
| 	return new(big.Int).Exp(bigInt[10], big.NewInt(int64(x)), nil)
 | |
| }
 | |
| 
 | |
| func (x *Dec) rescale(newScale Scale) *Dec {
 | |
| 	shift := newScale - x.Scale()
 | |
| 	switch {
 | |
| 	case shift < 0:
 | |
| 		e := exp10(-shift)
 | |
| 		return NewDecBig(new(big.Int).Quo(x.UnscaledBig(), e), newScale)
 | |
| 	case shift > 0:
 | |
| 		e := exp10(shift)
 | |
| 		return NewDecBig(new(big.Int).Mul(x.UnscaledBig(), e), newScale)
 | |
| 	}
 | |
| 	return x
 | |
| }
 | |
| 
 | |
| var zeros = []byte("00000000000000000000000000000000" +
 | |
| 	"00000000000000000000000000000000")
 | |
| var lzeros = Scale(len(zeros))
 | |
| 
 | |
| func appendZeros(s []byte, n Scale) []byte {
 | |
| 	for i := Scale(0); i < n; i += lzeros {
 | |
| 		if n > i+lzeros {
 | |
| 			s = append(s, zeros...)
 | |
| 		} else {
 | |
| 			s = append(s, zeros[0:n-i]...)
 | |
| 		}
 | |
| 	}
 | |
| 	return s
 | |
| }
 | |
| 
 | |
| func (x *Dec) String() string {
 | |
| 	if x == nil {
 | |
| 		return "<nil>"
 | |
| 	}
 | |
| 	scale := x.Scale()
 | |
| 	s := []byte(x.UnscaledBig().String())
 | |
| 	if scale <= 0 {
 | |
| 		if scale != 0 && x.unscaled.Sign() != 0 {
 | |
| 			s = appendZeros(s, -scale)
 | |
| 		}
 | |
| 		return string(s)
 | |
| 	}
 | |
| 	negbit := Scale(-((x.Sign() - 1) / 2))
 | |
| 	// scale > 0
 | |
| 	lens := Scale(len(s))
 | |
| 	if lens-negbit <= scale {
 | |
| 		ss := make([]byte, 0, scale+2)
 | |
| 		if negbit == 1 {
 | |
| 			ss = append(ss, '-')
 | |
| 		}
 | |
| 		ss = append(ss, '0', '.')
 | |
| 		ss = appendZeros(ss, scale-lens+negbit)
 | |
| 		ss = append(ss, s[negbit:]...)
 | |
| 		return string(ss)
 | |
| 	}
 | |
| 	// lens > scale
 | |
| 	ss := make([]byte, 0, lens+1)
 | |
| 	ss = append(ss, s[:lens-scale]...)
 | |
| 	ss = append(ss, '.')
 | |
| 	ss = append(ss, s[lens-scale:]...)
 | |
| 	return string(ss)
 | |
| }
 | |
| 
 | |
| // Format is a support routine for fmt.Formatter. It accepts the decimal
 | |
| // formats 'd' and 'f', and handles both equivalently.
 | |
| // Width, precision, flags and bases 2, 8, 16 are not supported.
 | |
| func (x *Dec) Format(s fmt.State, ch rune) {
 | |
| 	if ch != 'd' && ch != 'f' && ch != 'v' && ch != 's' {
 | |
| 		fmt.Fprintf(s, "%%!%c(dec.Dec=%s)", ch, x.String())
 | |
| 		return
 | |
| 	}
 | |
| 	fmt.Fprintf(s, x.String())
 | |
| }
 | |
| 
 | |
| func (z *Dec) scan(r io.RuneScanner) (*Dec, error) {
 | |
| 	unscaled := make([]byte, 0, 256) // collects chars of unscaled as bytes
 | |
| 	dp, dg := -1, -1                 // indexes of decimal point, first digit
 | |
| loop:
 | |
| 	for {
 | |
| 		ch, _, err := r.ReadRune()
 | |
| 		if err == io.EOF {
 | |
| 			break loop
 | |
| 		}
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		switch {
 | |
| 		case ch == '+' || ch == '-':
 | |
| 			if len(unscaled) > 0 || dp >= 0 { // must be first character
 | |
| 				r.UnreadRune()
 | |
| 				break loop
 | |
| 			}
 | |
| 		case ch == '.':
 | |
| 			if dp >= 0 {
 | |
| 				r.UnreadRune()
 | |
| 				break loop
 | |
| 			}
 | |
| 			dp = len(unscaled)
 | |
| 			continue // don't add to unscaled
 | |
| 		case ch >= '0' && ch <= '9':
 | |
| 			if dg == -1 {
 | |
| 				dg = len(unscaled)
 | |
| 			}
 | |
| 		default:
 | |
| 			r.UnreadRune()
 | |
| 			break loop
 | |
| 		}
 | |
| 		unscaled = append(unscaled, byte(ch))
 | |
| 	}
 | |
| 	if dg == -1 {
 | |
| 		return nil, fmt.Errorf("no digits read")
 | |
| 	}
 | |
| 	if dp >= 0 {
 | |
| 		z.SetScale(Scale(len(unscaled) - dp))
 | |
| 	} else {
 | |
| 		z.SetScale(0)
 | |
| 	}
 | |
| 	_, ok := z.UnscaledBig().SetString(string(unscaled), 10)
 | |
| 	if !ok {
 | |
| 		return nil, fmt.Errorf("invalid decimal: %s", string(unscaled))
 | |
| 	}
 | |
| 	return z, nil
 | |
| }
 | |
| 
 | |
| // SetString sets z to the value of s, interpreted as a decimal (base 10),
 | |
| // and returns z and a boolean indicating success. The scale of z is the
 | |
| // number of digits after the decimal point (including any trailing 0s),
 | |
| // or 0 if there is no decimal point. If SetString fails, the value of z
 | |
| // is undefined but the returned value is nil.
 | |
| func (z *Dec) SetString(s string) (*Dec, bool) {
 | |
| 	r := strings.NewReader(s)
 | |
| 	_, err := z.scan(r)
 | |
| 	if err != nil {
 | |
| 		return nil, false
 | |
| 	}
 | |
| 	_, _, err = r.ReadRune()
 | |
| 	if err != io.EOF {
 | |
| 		return nil, false
 | |
| 	}
 | |
| 	// err == io.EOF => scan consumed all of s
 | |
| 	return z, true
 | |
| }
 | |
| 
 | |
| // Scan is a support routine for fmt.Scanner; it sets z to the value of
 | |
| // the scanned number. It accepts the decimal formats 'd' and 'f', and
 | |
| // handles both equivalently. Bases 2, 8, 16 are not supported.
 | |
| // The scale of z is the number of digits after the decimal point
 | |
| // (including any trailing 0s), or 0 if there is no decimal point.
 | |
| func (z *Dec) Scan(s fmt.ScanState, ch rune) error {
 | |
| 	if ch != 'd' && ch != 'f' && ch != 's' && ch != 'v' {
 | |
| 		return fmt.Errorf("Dec.Scan: invalid verb '%c'", ch)
 | |
| 	}
 | |
| 	s.SkipSpace()
 | |
| 	_, err := z.scan(s)
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| // Gob encoding version
 | |
| const decGobVersion byte = 1
 | |
| 
 | |
| func scaleBytes(s Scale) []byte {
 | |
| 	buf := make([]byte, scaleSize)
 | |
| 	i := scaleSize
 | |
| 	for j := 0; j < scaleSize; j++ {
 | |
| 		i--
 | |
| 		buf[i] = byte(s)
 | |
| 		s >>= 8
 | |
| 	}
 | |
| 	return buf
 | |
| }
 | |
| 
 | |
| func scale(b []byte) (s Scale) {
 | |
| 	for j := 0; j < scaleSize; j++ {
 | |
| 		s <<= 8
 | |
| 		s |= Scale(b[j])
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // GobEncode implements the gob.GobEncoder interface.
 | |
| func (x *Dec) GobEncode() ([]byte, error) {
 | |
| 	buf, err := x.UnscaledBig().GobEncode()
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	buf = append(append(buf, scaleBytes(x.Scale())...), decGobVersion)
 | |
| 	return buf, nil
 | |
| }
 | |
| 
 | |
| // GobDecode implements the gob.GobDecoder interface.
 | |
| func (z *Dec) GobDecode(buf []byte) error {
 | |
| 	if len(buf) == 0 {
 | |
| 		return fmt.Errorf("Dec.GobDecode: no data")
 | |
| 	}
 | |
| 	b := buf[len(buf)-1]
 | |
| 	if b != decGobVersion {
 | |
| 		return fmt.Errorf("Dec.GobDecode: encoding version %d not supported", b)
 | |
| 	}
 | |
| 	l := len(buf) - scaleSize - 1
 | |
| 	err := z.UnscaledBig().GobDecode(buf[:l])
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	z.SetScale(scale(buf[l : l+scaleSize]))
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // MarshalText implements the encoding.TextMarshaler interface.
 | |
| func (x *Dec) MarshalText() ([]byte, error) {
 | |
| 	return []byte(x.String()), nil
 | |
| }
 | |
| 
 | |
| // UnmarshalText implements the encoding.TextUnmarshaler interface.
 | |
| func (z *Dec) UnmarshalText(data []byte) error {
 | |
| 	_, ok := z.SetString(string(data))
 | |
| 	if !ok {
 | |
| 		return fmt.Errorf("invalid inf.Dec")
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | 
