github.com/Finschia/finschia-sdk@v0.48.1/types/decimal.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"math/big"
     8  	"strconv"
     9  	"strings"
    10  	"testing"
    11  )
    12  
    13  var _ CustomProtobufType = (*Dec)(nil)
    14  
    15  // NOTE: never use new(Dec) or else we will panic unmarshalling into the
    16  // nil embedded big.Int
    17  type Dec struct {
    18  	i *big.Int
    19  }
    20  
    21  const (
    22  	// number of decimal places
    23  	Precision = 18
    24  
    25  	// bits required to represent the above precision
    26  	// Ceiling[Log2[10^Precision - 1]]
    27  	DecimalPrecisionBits = 60
    28  
    29  	// decimalTruncateBits is the minimum number of bits removed
    30  	// by a truncate operation. It is equal to
    31  	// Floor[Log2[10^Precision - 1]].
    32  	decimalTruncateBits = DecimalPrecisionBits - 1
    33  
    34  	maxDecBitLen = maxBitLen + decimalTruncateBits
    35  
    36  	// max number of iterations in ApproxRoot function
    37  	maxApproxRootIterations = 100
    38  )
    39  
    40  var (
    41  	precisionReuse       = new(big.Int).Exp(big.NewInt(10), big.NewInt(Precision), nil)
    42  	fivePrecision        = new(big.Int).Quo(precisionReuse, big.NewInt(2))
    43  	precisionMultipliers []*big.Int
    44  	zeroInt              = big.NewInt(0)
    45  	oneInt               = big.NewInt(1)
    46  	tenInt               = big.NewInt(10)
    47  )
    48  
    49  // Decimal errors
    50  var (
    51  	ErrEmptyDecimalStr      = errors.New("decimal string cannot be empty")
    52  	ErrInvalidDecimalLength = errors.New("invalid decimal length")
    53  	ErrInvalidDecimalStr    = errors.New("invalid decimal string")
    54  )
    55  
    56  // Set precision multipliers
    57  func init() {
    58  	precisionMultipliers = make([]*big.Int, Precision+1)
    59  	for i := 0; i <= Precision; i++ {
    60  		precisionMultipliers[i] = calcPrecisionMultiplier(int64(i))
    61  	}
    62  }
    63  
    64  func precisionInt() *big.Int {
    65  	return new(big.Int).Set(precisionReuse)
    66  }
    67  
    68  func ZeroDec() Dec     { return Dec{new(big.Int).Set(zeroInt)} }
    69  func OneDec() Dec      { return Dec{precisionInt()} }
    70  func SmallestDec() Dec { return Dec{new(big.Int).Set(oneInt)} }
    71  
    72  // calculate the precision multiplier
    73  func calcPrecisionMultiplier(prec int64) *big.Int {
    74  	if prec > Precision {
    75  		panic(fmt.Sprintf("too much precision, maximum %v, provided %v", Precision, prec))
    76  	}
    77  	zerosToAdd := Precision - prec
    78  	multiplier := new(big.Int).Exp(tenInt, big.NewInt(zerosToAdd), nil)
    79  	return multiplier
    80  }
    81  
    82  // get the precision multiplier, do not mutate result
    83  func precisionMultiplier(prec int64) *big.Int {
    84  	if prec > Precision {
    85  		panic(fmt.Sprintf("too much precision, maximum %v, provided %v", Precision, prec))
    86  	}
    87  	return precisionMultipliers[prec]
    88  }
    89  
    90  // create a new Dec from integer assuming whole number
    91  func NewDec(i int64) Dec {
    92  	return NewDecWithPrec(i, 0)
    93  }
    94  
    95  // create a new Dec from integer with decimal place at prec
    96  // CONTRACT: prec <= Precision
    97  func NewDecWithPrec(i, prec int64) Dec {
    98  	return Dec{
    99  		new(big.Int).Mul(big.NewInt(i), precisionMultiplier(prec)),
   100  	}
   101  }
   102  
   103  // create a new Dec from big integer assuming whole numbers
   104  // CONTRACT: prec <= Precision
   105  func NewDecFromBigInt(i *big.Int) Dec {
   106  	return NewDecFromBigIntWithPrec(i, 0)
   107  }
   108  
   109  // create a new Dec from big integer assuming whole numbers
   110  // CONTRACT: prec <= Precision
   111  func NewDecFromBigIntWithPrec(i *big.Int, prec int64) Dec {
   112  	return Dec{
   113  		new(big.Int).Mul(i, precisionMultiplier(prec)),
   114  	}
   115  }
   116  
   117  // create a new Dec from big integer assuming whole numbers
   118  // CONTRACT: prec <= Precision
   119  func NewDecFromInt(i Int) Dec {
   120  	return NewDecFromIntWithPrec(i, 0)
   121  }
   122  
   123  // create a new Dec from big integer with decimal place at prec
   124  // CONTRACT: prec <= Precision
   125  func NewDecFromIntWithPrec(i Int, prec int64) Dec {
   126  	return Dec{
   127  		new(big.Int).Mul(i.BigInt(), precisionMultiplier(prec)),
   128  	}
   129  }
   130  
   131  // create a decimal from an input decimal string.
   132  // valid must come in the form:
   133  //
   134  //	(-) whole integers (.) decimal integers
   135  //
   136  // examples of acceptable input include:
   137  //
   138  //	-123.456
   139  //	456.7890
   140  //	345
   141  //	-456789
   142  //
   143  // NOTE - An error will return if more decimal places
   144  // are provided in the string than the constant Precision.
   145  //
   146  // CONTRACT - This function does not mutate the input str.
   147  func NewDecFromStr(str string) (Dec, error) {
   148  	if len(str) == 0 {
   149  		return Dec{}, fmt.Errorf("%s: %w", str, ErrEmptyDecimalStr)
   150  	}
   151  
   152  	// first extract any negative symbol
   153  	neg := false
   154  	if str[0] == '-' {
   155  		neg = true
   156  		str = str[1:]
   157  	}
   158  
   159  	if len(str) == 0 {
   160  		return Dec{}, fmt.Errorf("%s: %w", str, ErrEmptyDecimalStr)
   161  	}
   162  
   163  	strs := strings.Split(str, ".")
   164  	lenDecs := 0
   165  	combinedStr := strs[0]
   166  
   167  	if len(strs) == 2 { // has a decimal place
   168  		lenDecs = len(strs[1])
   169  		if lenDecs == 0 || len(combinedStr) == 0 {
   170  			return Dec{}, ErrInvalidDecimalLength
   171  		}
   172  		combinedStr += strs[1]
   173  	} else if len(strs) > 2 {
   174  		return Dec{}, ErrInvalidDecimalStr
   175  	}
   176  
   177  	if lenDecs > Precision {
   178  		return Dec{}, fmt.Errorf("value '%s' exceeds max precision by %d decimal places: max precision %d", str, Precision-lenDecs, Precision)
   179  	}
   180  
   181  	// add some extra zero's to correct to the Precision factor
   182  	zerosToAdd := Precision - lenDecs
   183  	zeros := fmt.Sprintf(`%0`+strconv.Itoa(zerosToAdd)+`s`, "")
   184  	combinedStr += zeros
   185  
   186  	combined, ok := new(big.Int).SetString(combinedStr, 10) // base 10
   187  	if !ok {
   188  		return Dec{}, fmt.Errorf("failed to set decimal string with base 10: %s", combinedStr)
   189  	}
   190  	if combined.BitLen() > maxDecBitLen {
   191  		return Dec{}, fmt.Errorf("decimal '%s' out of range; bitLen: got %d, max %d", str, combined.BitLen(), maxDecBitLen)
   192  	}
   193  	if neg {
   194  		combined = new(big.Int).Neg(combined)
   195  	}
   196  
   197  	return Dec{combined}, nil
   198  }
   199  
   200  // Decimal from string, panic on error
   201  func MustNewDecFromStr(s string) Dec {
   202  	dec, err := NewDecFromStr(s)
   203  	if err != nil {
   204  		panic(err)
   205  	}
   206  	return dec
   207  }
   208  
   209  func (d Dec) IsNil() bool       { return d.i == nil }                 // is decimal nil
   210  func (d Dec) IsZero() bool      { return (d.i).Sign() == 0 }          // is equal to zero
   211  func (d Dec) IsNegative() bool  { return (d.i).Sign() == -1 }         // is negative
   212  func (d Dec) IsPositive() bool  { return (d.i).Sign() == 1 }          // is positive
   213  func (d Dec) Equal(d2 Dec) bool { return (d.i).Cmp(d2.i) == 0 }       // equal decimals
   214  func (d Dec) GT(d2 Dec) bool    { return (d.i).Cmp(d2.i) > 0 }        // greater than
   215  func (d Dec) GTE(d2 Dec) bool   { return (d.i).Cmp(d2.i) >= 0 }       // greater than or equal
   216  func (d Dec) LT(d2 Dec) bool    { return (d.i).Cmp(d2.i) < 0 }        // less than
   217  func (d Dec) LTE(d2 Dec) bool   { return (d.i).Cmp(d2.i) <= 0 }       // less than or equal
   218  func (d Dec) Neg() Dec          { return Dec{new(big.Int).Neg(d.i)} } // reverse the decimal sign
   219  func (d Dec) Abs() Dec          { return Dec{new(big.Int).Abs(d.i)} } // absolute value
   220  
   221  // BigInt returns a copy of the underlying big.Int.
   222  func (d Dec) BigInt() *big.Int {
   223  	if d.IsNil() {
   224  		return nil
   225  	}
   226  
   227  	cp := new(big.Int)
   228  	return cp.Set(d.i)
   229  }
   230  
   231  // addition
   232  func (d Dec) Add(d2 Dec) Dec {
   233  	res := new(big.Int).Add(d.i, d2.i)
   234  
   235  	if res.BitLen() > maxDecBitLen {
   236  		panic("Int overflow")
   237  	}
   238  	return Dec{res}
   239  }
   240  
   241  // subtraction
   242  func (d Dec) Sub(d2 Dec) Dec {
   243  	res := new(big.Int).Sub(d.i, d2.i)
   244  
   245  	if res.BitLen() > maxDecBitLen {
   246  		panic("Int overflow")
   247  	}
   248  	return Dec{res}
   249  }
   250  
   251  // multiplication
   252  func (d Dec) Mul(d2 Dec) Dec {
   253  	mul := new(big.Int).Mul(d.i, d2.i)
   254  	chopped := chopPrecisionAndRound(mul)
   255  
   256  	if chopped.BitLen() > maxDecBitLen {
   257  		panic("Int overflow")
   258  	}
   259  	return Dec{chopped}
   260  }
   261  
   262  // multiplication truncate
   263  func (d Dec) MulTruncate(d2 Dec) Dec {
   264  	mul := new(big.Int).Mul(d.i, d2.i)
   265  	chopped := chopPrecisionAndTruncate(mul)
   266  
   267  	if chopped.BitLen() > maxDecBitLen {
   268  		panic("Int overflow")
   269  	}
   270  	return Dec{chopped}
   271  }
   272  
   273  // multiplication
   274  func (d Dec) MulInt(i Int) Dec {
   275  	mul := new(big.Int).Mul(d.i, i.i)
   276  
   277  	if mul.BitLen() > maxDecBitLen {
   278  		panic("Int overflow")
   279  	}
   280  	return Dec{mul}
   281  }
   282  
   283  // MulInt64 - multiplication with int64
   284  func (d Dec) MulInt64(i int64) Dec {
   285  	mul := new(big.Int).Mul(d.i, big.NewInt(i))
   286  
   287  	if mul.BitLen() > maxDecBitLen {
   288  		panic("Int overflow")
   289  	}
   290  	return Dec{mul}
   291  }
   292  
   293  // quotient
   294  func (d Dec) Quo(d2 Dec) Dec {
   295  	// multiply precision twice
   296  	mul := new(big.Int).Mul(d.i, precisionReuse)
   297  	mul.Mul(mul, precisionReuse)
   298  
   299  	quo := new(big.Int).Quo(mul, d2.i)
   300  	chopped := chopPrecisionAndRound(quo)
   301  
   302  	if chopped.BitLen() > maxDecBitLen {
   303  		panic("Int overflow")
   304  	}
   305  	return Dec{chopped}
   306  }
   307  
   308  // quotient truncate
   309  func (d Dec) QuoTruncate(d2 Dec) Dec {
   310  	// multiply precision twice
   311  	mul := new(big.Int).Mul(d.i, precisionReuse)
   312  	mul.Mul(mul, precisionReuse)
   313  
   314  	quo := mul.Quo(mul, d2.i)
   315  	chopped := chopPrecisionAndTruncate(quo)
   316  
   317  	if chopped.BitLen() > maxDecBitLen {
   318  		panic("Int overflow")
   319  	}
   320  	return Dec{chopped}
   321  }
   322  
   323  // quotient, round up
   324  func (d Dec) QuoRoundUp(d2 Dec) Dec {
   325  	// multiply precision twice
   326  	mul := new(big.Int).Mul(d.i, precisionReuse)
   327  	mul.Mul(mul, precisionReuse)
   328  
   329  	quo := new(big.Int).Quo(mul, d2.i)
   330  	chopped := chopPrecisionAndRoundUp(quo)
   331  
   332  	if chopped.BitLen() > maxDecBitLen {
   333  		panic("Int overflow")
   334  	}
   335  	return Dec{chopped}
   336  }
   337  
   338  // quotient
   339  func (d Dec) QuoInt(i Int) Dec {
   340  	mul := new(big.Int).Quo(d.i, i.i)
   341  	return Dec{mul}
   342  }
   343  
   344  // QuoInt64 - quotient with int64
   345  func (d Dec) QuoInt64(i int64) Dec {
   346  	mul := new(big.Int).Quo(d.i, big.NewInt(i))
   347  	return Dec{mul}
   348  }
   349  
   350  // ApproxRoot returns an approximate estimation of a Dec's positive real nth root
   351  // using Newton's method (where n is positive). The algorithm starts with some guess and
   352  // computes the sequence of improved guesses until an answer converges to an
   353  // approximate answer.  It returns `|d|.ApproxRoot() * -1` if input is negative.
   354  // A maximum number of 100 iterations is used a backup boundary condition for
   355  // cases where the answer never converges enough to satisfy the main condition.
   356  func (d Dec) ApproxRoot(root uint64) (guess Dec, err error) {
   357  	defer func() {
   358  		if r := recover(); r != nil {
   359  			var ok bool
   360  			err, ok = r.(error)
   361  			if !ok {
   362  				err = errors.New("out of bounds")
   363  			}
   364  		}
   365  	}()
   366  
   367  	if d.IsNegative() {
   368  		absRoot, err := d.MulInt64(-1).ApproxRoot(root)
   369  		return absRoot.MulInt64(-1), err
   370  	}
   371  
   372  	if root == 1 || d.IsZero() || d.Equal(OneDec()) {
   373  		return d, nil
   374  	}
   375  
   376  	if root == 0 {
   377  		return OneDec(), nil
   378  	}
   379  
   380  	rootInt := NewIntFromUint64(root)
   381  	guess, delta := OneDec(), OneDec()
   382  
   383  	for iter := 0; delta.Abs().GT(SmallestDec()) && iter < maxApproxRootIterations; iter++ {
   384  		prev := guess.Power(root - 1)
   385  		if prev.IsZero() {
   386  			prev = SmallestDec()
   387  		}
   388  		delta = d.Quo(prev)
   389  		delta = delta.Sub(guess)
   390  		delta = delta.QuoInt(rootInt)
   391  
   392  		guess = guess.Add(delta)
   393  	}
   394  
   395  	return guess, nil
   396  }
   397  
   398  // Power returns a the result of raising to a positive integer power
   399  func (d Dec) Power(power uint64) Dec {
   400  	if power == 0 {
   401  		return OneDec()
   402  	}
   403  	tmp := OneDec()
   404  
   405  	for i := power; i > 1; {
   406  		if i%2 != 0 {
   407  			tmp = tmp.Mul(d)
   408  		}
   409  		i /= 2
   410  		d = d.Mul(d)
   411  	}
   412  
   413  	return d.Mul(tmp)
   414  }
   415  
   416  // ApproxSqrt is a wrapper around ApproxRoot for the common special case
   417  // of finding the square root of a number. It returns -(sqrt(abs(d)) if input is negative.
   418  func (d Dec) ApproxSqrt() (Dec, error) {
   419  	return d.ApproxRoot(2)
   420  }
   421  
   422  // is integer, e.g. decimals are zero
   423  func (d Dec) IsInteger() bool {
   424  	return new(big.Int).Rem(d.i, precisionReuse).Sign() == 0
   425  }
   426  
   427  // format decimal state
   428  func (d Dec) Format(s fmt.State, verb rune) {
   429  	_, err := s.Write([]byte(d.String()))
   430  	if err != nil {
   431  		panic(err)
   432  	}
   433  }
   434  
   435  func (d Dec) String() string {
   436  	if d.i == nil {
   437  		return d.i.String()
   438  	}
   439  
   440  	isNeg := d.IsNegative()
   441  
   442  	if isNeg {
   443  		d = d.Neg()
   444  	}
   445  
   446  	bzInt, err := d.i.MarshalText()
   447  	if err != nil {
   448  		return ""
   449  	}
   450  	inputSize := len(bzInt)
   451  
   452  	var bzStr []byte
   453  
   454  	// TODO: Remove trailing zeros
   455  	// case 1, purely decimal
   456  	if inputSize <= Precision {
   457  		bzStr = make([]byte, Precision+2)
   458  
   459  		// 0. prefix
   460  		bzStr[0] = byte('0')
   461  		bzStr[1] = byte('.')
   462  
   463  		// set relevant digits to 0
   464  		for i := 0; i < Precision-inputSize; i++ {
   465  			bzStr[i+2] = byte('0')
   466  		}
   467  
   468  		// set final digits
   469  		copy(bzStr[2+(Precision-inputSize):], bzInt)
   470  	} else {
   471  		// inputSize + 1 to account for the decimal point that is being added
   472  		bzStr = make([]byte, inputSize+1)
   473  		decPointPlace := inputSize - Precision
   474  
   475  		copy(bzStr, bzInt[:decPointPlace])                   // pre-decimal digits
   476  		bzStr[decPointPlace] = byte('.')                     // decimal point
   477  		copy(bzStr[decPointPlace+1:], bzInt[decPointPlace:]) // post-decimal digits
   478  	}
   479  
   480  	if isNeg {
   481  		return "-" + string(bzStr)
   482  	}
   483  
   484  	return string(bzStr)
   485  }
   486  
   487  // Float64 returns the float64 representation of a Dec.
   488  // Will return the error if the conversion failed.
   489  func (d Dec) Float64() (float64, error) {
   490  	return strconv.ParseFloat(d.String(), 64)
   491  }
   492  
   493  // MustFloat64 returns the float64 representation of a Dec.
   494  // Would panic if the conversion failed.
   495  func (d Dec) MustFloat64() float64 {
   496  	if value, err := strconv.ParseFloat(d.String(), 64); err != nil {
   497  		panic(err)
   498  	} else {
   499  		return value
   500  	}
   501  }
   502  
   503  //     ____
   504  //  __|    |__   "chop 'em
   505  //       ` \     round!"
   506  // ___||  ~  _     -bankers
   507  // |         |      __
   508  // |       | |   __|__|__
   509  // |_____:  /   | $$$    |
   510  //              |________|
   511  
   512  // Remove a Precision amount of rightmost digits and perform bankers rounding
   513  // on the remainder (gaussian rounding) on the digits which have been removed.
   514  //
   515  // Mutates the input. Use the non-mutative version if that is undesired
   516  func chopPrecisionAndRound(d *big.Int) *big.Int {
   517  	// remove the negative and add it back when returning
   518  	if d.Sign() == -1 {
   519  		// make d positive, compute chopped value, and then un-mutate d
   520  		d = d.Neg(d)
   521  		d = chopPrecisionAndRound(d)
   522  		d = d.Neg(d)
   523  		return d
   524  	}
   525  
   526  	// get the truncated quotient and remainder
   527  	quo, rem := d, big.NewInt(0)
   528  	quo, rem = quo.QuoRem(d, precisionReuse, rem)
   529  
   530  	if rem.Sign() == 0 { // remainder is zero
   531  		return quo
   532  	}
   533  
   534  	switch rem.Cmp(fivePrecision) {
   535  	case -1:
   536  		return quo
   537  	case 1:
   538  		return quo.Add(quo, oneInt)
   539  	default: // bankers rounding must take place
   540  		// always round to an even number
   541  		if quo.Bit(0) == 0 {
   542  			return quo
   543  		}
   544  		return quo.Add(quo, oneInt)
   545  	}
   546  }
   547  
   548  func chopPrecisionAndRoundUp(d *big.Int) *big.Int {
   549  	// remove the negative and add it back when returning
   550  	if d.Sign() == -1 {
   551  		// make d positive, compute chopped value, and then un-mutate d
   552  		d = d.Neg(d)
   553  		// truncate since d is negative...
   554  		d = chopPrecisionAndTruncate(d)
   555  		d = d.Neg(d)
   556  		return d
   557  	}
   558  
   559  	// get the truncated quotient and remainder
   560  	quo, rem := d, big.NewInt(0)
   561  	quo, rem = quo.QuoRem(d, precisionReuse, rem)
   562  
   563  	if rem.Sign() == 0 { // remainder is zero
   564  		return quo
   565  	}
   566  
   567  	return quo.Add(quo, oneInt)
   568  }
   569  
   570  func chopPrecisionAndRoundNonMutative(d *big.Int) *big.Int {
   571  	tmp := new(big.Int).Set(d)
   572  	return chopPrecisionAndRound(tmp)
   573  }
   574  
   575  // RoundInt64 rounds the decimal using bankers rounding
   576  func (d Dec) RoundInt64() int64 {
   577  	chopped := chopPrecisionAndRoundNonMutative(d.i)
   578  	if !chopped.IsInt64() {
   579  		panic("Int64() out of bound")
   580  	}
   581  	return chopped.Int64()
   582  }
   583  
   584  // RoundInt round the decimal using bankers rounding
   585  func (d Dec) RoundInt() Int {
   586  	return NewIntFromBigInt(chopPrecisionAndRoundNonMutative(d.i))
   587  }
   588  
   589  // chopPrecisionAndTruncate is similar to chopPrecisionAndRound,
   590  // but always rounds down. It does not mutate the input.
   591  func chopPrecisionAndTruncate(d *big.Int) *big.Int {
   592  	return new(big.Int).Quo(d, precisionReuse)
   593  }
   594  
   595  // TruncateInt64 truncates the decimals from the number and returns an int64
   596  func (d Dec) TruncateInt64() int64 {
   597  	chopped := chopPrecisionAndTruncate(d.i)
   598  	if !chopped.IsInt64() {
   599  		panic("Int64() out of bound")
   600  	}
   601  	return chopped.Int64()
   602  }
   603  
   604  // TruncateInt truncates the decimals from the number and returns an Int
   605  func (d Dec) TruncateInt() Int {
   606  	return NewIntFromBigInt(chopPrecisionAndTruncate(d.i))
   607  }
   608  
   609  // TruncateDec truncates the decimals from the number and returns a Dec
   610  func (d Dec) TruncateDec() Dec {
   611  	return NewDecFromBigInt(chopPrecisionAndTruncate(d.i))
   612  }
   613  
   614  // Ceil returns the smallest interger value (as a decimal) that is greater than
   615  // or equal to the given decimal.
   616  func (d Dec) Ceil() Dec {
   617  	tmp := new(big.Int).Set(d.i)
   618  
   619  	quo, rem := tmp, big.NewInt(0)
   620  	quo, rem = quo.QuoRem(tmp, precisionReuse, rem)
   621  
   622  	// no need to round with a zero remainder regardless of sign
   623  	if rem.Cmp(zeroInt) == 0 {
   624  		return NewDecFromBigInt(quo)
   625  	}
   626  
   627  	if rem.Sign() == -1 {
   628  		return NewDecFromBigInt(quo)
   629  	}
   630  
   631  	return NewDecFromBigInt(quo.Add(quo, oneInt))
   632  }
   633  
   634  // MaxSortableDec is the largest Dec that can be passed into SortableDecBytes()
   635  // Its negative form is the least Dec that can be passed in.
   636  var MaxSortableDec = OneDec().Quo(SmallestDec())
   637  
   638  // ValidSortableDec ensures that a Dec is within the sortable bounds,
   639  // a Dec can't have a precision of less than 10^-18.
   640  // Max sortable decimal was set to the reciprocal of SmallestDec.
   641  func ValidSortableDec(dec Dec) bool {
   642  	return dec.Abs().LTE(MaxSortableDec)
   643  }
   644  
   645  // SortableDecBytes returns a byte slice representation of a Dec that can be sorted.
   646  // Left and right pads with 0s so there are 18 digits to left and right of the decimal point.
   647  // For this reason, there is a maximum and minimum value for this, enforced by ValidSortableDec.
   648  func SortableDecBytes(dec Dec) []byte {
   649  	if !ValidSortableDec(dec) {
   650  		panic("dec must be within bounds")
   651  	}
   652  	// Instead of adding an extra byte to all sortable decs in order to handle max sortable, we just
   653  	// makes its bytes be "max" which comes after all numbers in ASCIIbetical order
   654  	if dec.Equal(MaxSortableDec) {
   655  		return []byte("max")
   656  	}
   657  	// For the same reason, we make the bytes of minimum sortable dec be --, which comes before all numbers.
   658  	if dec.Equal(MaxSortableDec.Neg()) {
   659  		return []byte("--")
   660  	}
   661  	// We move the negative sign to the front of all the left padded 0s, to make negative numbers come before positive numbers
   662  	if dec.IsNegative() {
   663  		return append([]byte("-"), []byte(fmt.Sprintf(fmt.Sprintf("%%0%ds", Precision*2+1), dec.Abs().String()))...)
   664  	}
   665  	return []byte(fmt.Sprintf(fmt.Sprintf("%%0%ds", Precision*2+1), dec.String()))
   666  }
   667  
   668  // reuse nil values
   669  var nilJSON []byte
   670  
   671  func init() {
   672  	empty := new(big.Int)
   673  	bz, _ := empty.MarshalText()
   674  	nilJSON, _ = json.Marshal(string(bz))
   675  }
   676  
   677  // MarshalJSON marshals the decimal
   678  func (d Dec) MarshalJSON() ([]byte, error) {
   679  	if d.i == nil {
   680  		return nilJSON, nil
   681  	}
   682  	return json.Marshal(d.String())
   683  }
   684  
   685  // UnmarshalJSON defines custom decoding scheme
   686  func (d *Dec) UnmarshalJSON(bz []byte) error {
   687  	if d.i == nil {
   688  		d.i = new(big.Int)
   689  	}
   690  
   691  	var text string
   692  	err := json.Unmarshal(bz, &text)
   693  	if err != nil {
   694  		return err
   695  	}
   696  
   697  	// TODO: Reuse dec allocation
   698  	newDec, err := NewDecFromStr(text)
   699  	if err != nil {
   700  		return err
   701  	}
   702  
   703  	d.i = newDec.i
   704  	return nil
   705  }
   706  
   707  // MarshalYAML returns the YAML representation.
   708  func (d Dec) MarshalYAML() (interface{}, error) {
   709  	return d.String(), nil
   710  }
   711  
   712  // Marshal implements the gogo proto custom type interface.
   713  func (d Dec) Marshal() ([]byte, error) {
   714  	if d.i == nil {
   715  		d.i = new(big.Int)
   716  	}
   717  	return d.i.MarshalText()
   718  }
   719  
   720  // MarshalTo implements the gogo proto custom type interface.
   721  func (d *Dec) MarshalTo(data []byte) (n int, err error) {
   722  	if d.i == nil {
   723  		d.i = new(big.Int)
   724  	}
   725  
   726  	if d.i.Cmp(zeroInt) == 0 {
   727  		copy(data, []byte{0x30})
   728  		return 1, nil
   729  	}
   730  
   731  	bz, err := d.Marshal()
   732  	if err != nil {
   733  		return 0, err
   734  	}
   735  
   736  	copy(data, bz)
   737  	return len(bz), nil
   738  }
   739  
   740  // Unmarshal implements the gogo proto custom type interface.
   741  func (d *Dec) Unmarshal(data []byte) error {
   742  	if len(data) == 0 {
   743  		d = nil
   744  		return nil
   745  	}
   746  
   747  	if d.i == nil {
   748  		d.i = new(big.Int)
   749  	}
   750  
   751  	if err := d.i.UnmarshalText(data); err != nil {
   752  		return err
   753  	}
   754  
   755  	if d.i.BitLen() > maxDecBitLen {
   756  		return fmt.Errorf("decimal out of range; got: %d, max: %d", d.i.BitLen(), maxDecBitLen)
   757  	}
   758  
   759  	return nil
   760  }
   761  
   762  // Size implements the gogo proto custom type interface.
   763  func (d *Dec) Size() int {
   764  	bz, _ := d.Marshal()
   765  	return len(bz)
   766  }
   767  
   768  // Override Amino binary serialization by proxying to protobuf.
   769  func (d Dec) MarshalAmino() ([]byte, error)   { return d.Marshal() }
   770  func (d *Dec) UnmarshalAmino(bz []byte) error { return d.Unmarshal(bz) }
   771  
   772  func (dp DecProto) String() string {
   773  	return dp.Dec.String()
   774  }
   775  
   776  // helpers
   777  
   778  // test if two decimal arrays are equal
   779  func DecsEqual(d1s, d2s []Dec) bool {
   780  	if len(d1s) != len(d2s) {
   781  		return false
   782  	}
   783  
   784  	for i, d1 := range d1s {
   785  		if !d1.Equal(d2s[i]) {
   786  			return false
   787  		}
   788  	}
   789  	return true
   790  }
   791  
   792  // minimum decimal between two
   793  func MinDec(d1, d2 Dec) Dec {
   794  	if d1.LT(d2) {
   795  		return d1
   796  	}
   797  	return d2
   798  }
   799  
   800  // maximum decimal between two
   801  func MaxDec(d1, d2 Dec) Dec {
   802  	if d1.LT(d2) {
   803  		return d2
   804  	}
   805  	return d1
   806  }
   807  
   808  // intended to be used with require/assert:  require.True(DecEq(...))
   809  func DecEq(t *testing.T, exp, got Dec) (*testing.T, bool, string, string, string) {
   810  	return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp.String(), got.String()
   811  }