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