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 }