github.com/dubbogo/gost@v1.14.0/math/big/decimal.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package gxbig 19 20 import ( 21 "encoding/json" 22 "log" 23 "math" 24 "strconv" 25 "strings" 26 ) 27 28 import ( 29 "github.com/pkg/errors" 30 ) 31 32 var ( 33 ErrBadNumber = errors.Errorf("Bad Number") 34 ErrOverflow = errors.Errorf("Data Overflow") 35 ErrTruncated = errors.Errorf("Data Truncated") 36 ErrDivByZero = errors.Errorf("Division by 0") 37 ) 38 39 // RoundMode is the type for round mode. 40 type RoundMode int32 41 42 // constant values. 43 const ( 44 ten0 = 1 45 ten1 = 10 46 ten2 = 100 47 ten3 = 1000 48 ten4 = 10000 49 ten5 = 100000 50 ten6 = 1000000 51 ten7 = 10000000 52 ten8 = 100000000 53 ten9 = 1000000000 54 55 maxWordBufLen = 9 // A Decimal holds 9 words. 56 digitsPerWord = 9 // A word holds 9 digits. 57 wordSize = 4 // A word is 4 bytes int32. 58 digMask = ten8 59 wordBase = ten9 60 wordMax = wordBase - 1 61 notFixedDec = 31 62 63 DivFracIncr = 4 64 65 // ModeHalfEven rounds normally. 66 ModeHalfEven RoundMode = 5 67 // Truncate just truncates the decimal. 68 ModeTruncate RoundMode = 10 69 // Ceiling is not supported now. 70 modeCeiling RoundMode = 0 71 maxDecimalScale = int32(30) 72 pow10off int = 81 73 ) 74 75 var ( 76 wordBufLen = 9 77 mod9 = [128]int8{ 78 0, 1, 2, 3, 4, 5, 6, 7, 8, 79 0, 1, 2, 3, 4, 5, 6, 7, 8, 80 0, 1, 2, 3, 4, 5, 6, 7, 8, 81 0, 1, 2, 3, 4, 5, 6, 7, 8, 82 0, 1, 2, 3, 4, 5, 6, 7, 8, 83 0, 1, 2, 3, 4, 5, 6, 7, 8, 84 0, 1, 2, 3, 4, 5, 6, 7, 8, 85 0, 1, 2, 3, 4, 5, 6, 7, 8, 86 0, 1, 2, 3, 4, 5, 6, 7, 8, 87 0, 1, 2, 3, 4, 5, 6, 7, 8, 88 0, 1, 2, 3, 4, 5, 6, 7, 8, 89 0, 1, 2, 3, 4, 5, 6, 7, 8, 90 0, 1, 2, 3, 4, 5, 6, 7, 8, 91 0, 1, 2, 3, 4, 5, 6, 7, 8, 92 0, 1, 93 } 94 div9 = [128]int{ 95 0, 0, 0, 0, 0, 0, 0, 0, 0, 96 1, 1, 1, 1, 1, 1, 1, 1, 1, 97 2, 2, 2, 2, 2, 2, 2, 2, 2, 98 3, 3, 3, 3, 3, 3, 3, 3, 3, 99 4, 4, 4, 4, 4, 4, 4, 4, 4, 100 5, 5, 5, 5, 5, 5, 5, 5, 5, 101 6, 6, 6, 6, 6, 6, 6, 6, 6, 102 7, 7, 7, 7, 7, 7, 7, 7, 7, 103 8, 8, 8, 8, 8, 8, 8, 8, 8, 104 9, 9, 9, 9, 9, 9, 9, 9, 9, 105 10, 10, 10, 10, 10, 10, 10, 10, 10, 106 11, 11, 11, 11, 11, 11, 11, 11, 11, 107 12, 12, 12, 12, 12, 12, 12, 12, 12, 108 13, 13, 13, 13, 13, 13, 13, 13, 13, 109 14, 14, 110 } 111 powers10 = [10]int32{ten0, ten1, ten2, ten3, ten4, ten5, ten6, ten7, ten8, ten9} 112 dig2bytes = [10]int{0, 1, 1, 2, 2, 3, 3, 4, 4, 4} 113 fracMax = [8]int32{ 114 900000000, 115 990000000, 116 999000000, 117 999900000, 118 999990000, 119 999999000, 120 999999900, 121 999999990, 122 } 123 zeroBigDecimal = Decimal{} 124 pow10off81 = [...]float64{1e-81, 1e-80, 1e-79, 1e-78, 1e-77, 1e-76, 1e-75, 1e-74, 1e-73, 1e-72, 1e-71, 1e-70, 1e-69, 1e-68, 1e-67, 1e-66, 1e-65, 1e-64, 1e-63, 1e-62, 1e-61, 1e-60, 1e-59, 1e-58, 1e-57, 1e-56, 1e-55, 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49, 1e-48, 1e-47, 1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, 1e-40, 1e-39, 1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29, 1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20, 1e-19, 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49, 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59, 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69, 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79, 1e80, 1e81} 125 ) 126 127 // get the zero of Decimal with the specified result fraction digits 128 func zeroMyDecimalWithFrac(frac int8) Decimal { 129 zero := Decimal{} 130 zero.digitsFrac = frac 131 zero.resultFrac = frac 132 return zero 133 } 134 135 // add adds a and b and carry, returns the sum and new carry. 136 func add(a, b, carry int32) (int32, int32) { 137 sum := a + b + carry 138 if sum >= wordBase { 139 carry = 1 140 sum -= wordBase 141 } else { 142 carry = 0 143 } 144 return sum, carry 145 } 146 147 // add2 adds a and b and carry, returns the sum and new carry. 148 // It is only used in DecimalMul. 149 func add2(a, b, carry int32) (int32, int32) { 150 sum := int64(a) + int64(b) + int64(carry) 151 if sum >= wordBase { 152 carry = 1 153 sum -= wordBase 154 } else { 155 carry = 0 156 } 157 158 if sum >= wordBase { 159 sum -= wordBase 160 carry++ 161 } 162 return int32(sum), carry 163 } 164 165 // sub subtracts b and carry from a, returns the diff and new carry. 166 func sub(a, b, carry int32) (int32, int32) { 167 diff := a - b - carry 168 if diff < 0 { 169 carry = 1 170 diff += wordBase 171 } else { 172 carry = 0 173 } 174 return diff, carry 175 } 176 177 // sub2 subtracts b and carry from a, returns the diff and new carry. 178 // the new carry may be 2. 179 func sub2(a, b, carry int32) (int32, int32) { 180 diff := a - b - carry 181 if diff < 0 { 182 carry = 1 183 diff += wordBase 184 } else { 185 carry = 0 186 } 187 if diff < 0 { 188 diff += wordBase 189 carry++ 190 } 191 return diff, carry 192 } 193 194 // fixWordCntError limits word count in wordBufLen, and returns overflow or truncate error. 195 func fixWordCntError(wordsInt, wordsFrac int) (newWordsInt int, newWordsFrac int, err error) { 196 if wordsInt+wordsFrac > wordBufLen { 197 if wordsInt > wordBufLen { 198 return wordBufLen, 0, ErrOverflow 199 } 200 return wordsInt, wordBufLen - wordsInt, ErrTruncated 201 } 202 return wordsInt, wordsFrac, nil 203 } 204 205 /* 206 countLeadingZeroes returns the number of leading zeroes that can be removed from fraction. 207 208 @param i start index 209 @param word value to compare against list of powers of 10 210 */ 211 func countLeadingZeroes(i int, word int32) int { 212 leading := 0 213 for word < powers10[i] { 214 i-- 215 leading++ 216 } 217 return leading 218 } 219 220 /* 221 countTrailingZeros returns the number of trailing zeroes that can be removed from fraction. 222 223 @param i start index 224 @param word value to compare against list of powers of 10 225 */ 226 func countTrailingZeroes(i int, word int32) int { 227 trailing := 0 228 for word%powers10[i] == 0 { 229 i++ 230 trailing++ 231 } 232 return trailing 233 } 234 235 func digitsToWords(digits int) int { 236 if digits+digitsPerWord-1 >= 0 && digits+digitsPerWord-1 < 128 { 237 return div9[digits+digitsPerWord-1] 238 } 239 return (digits + digitsPerWord - 1) / digitsPerWord 240 } 241 242 // BigDecimalStructSize is the struct size of Decimal. 243 const BigDecimalStructSize = 40 244 245 // Decimal represents a decimal value. 246 type Decimal struct { 247 digitsInt int8 // the number of *decimal* digits before the point. 248 249 digitsFrac int8 // the number of decimal digits after the point. 250 251 resultFrac int8 // result fraction digits. 252 253 negative bool 254 255 // wordBuf is an array of int32 words. 256 // A word is an int32 value can hold 9 digits.(0 <= word < wordBase) 257 wordBuf [maxWordBufLen]int32 258 259 // for hessian 260 Value string 261 } 262 263 func (Decimal) JavaClassName() string { 264 return "java.math.BigDecimal" 265 } 266 267 // IsNegative returns whether a decimal is negative. 268 func (d *Decimal) IsNegative() bool { 269 return d.negative 270 } 271 272 // GetDigitsFrac returns the digitsFrac. 273 func (d *Decimal) GetDigitsFrac() int8 { 274 return d.digitsFrac 275 } 276 277 // GetDigitsInt returns the digitsInt. 278 func (d *Decimal) GetDigitsInt() int8 { 279 return d.digitsInt 280 } 281 282 // String returns the decimal string representation rounded to resultFrac. 283 func (d *Decimal) String() string { 284 tmp := *d 285 err := tmp.Round(&tmp, int(tmp.resultFrac), ModeHalfEven) 286 if err != nil { 287 log.Printf("decimal string = error{%v}", err) 288 } 289 return string(tmp.ToString()) 290 } 291 292 func (d *Decimal) stringSize() int { 293 // sign, zero integer and dot. 294 return int(d.digitsInt + d.digitsFrac + 3) 295 } 296 297 func (d *Decimal) removeLeadingZeros() (wordIdx int, digitsInt int) { 298 digitsInt = int(d.digitsInt) 299 i := ((digitsInt - 1) % digitsPerWord) + 1 300 for digitsInt > 0 && d.wordBuf[wordIdx] == 0 { 301 digitsInt -= i 302 i = digitsPerWord 303 wordIdx++ 304 } 305 if digitsInt > 0 { 306 digitsInt -= countLeadingZeroes((digitsInt-1)%digitsPerWord, d.wordBuf[wordIdx]) 307 } else { 308 digitsInt = 0 309 } 310 return 311 } 312 313 func (d *Decimal) removeTrailingZeros() (lastWordIdx int, digitsFrac int) { 314 digitsFrac = int(d.digitsFrac) 315 i := ((digitsFrac - 1) % digitsPerWord) + 1 316 lastWordIdx = digitsToWords(int(d.digitsInt)) + digitsToWords(int(d.digitsFrac)) 317 for digitsFrac > 0 && d.wordBuf[lastWordIdx-1] == 0 { 318 digitsFrac -= i 319 i = digitsPerWord 320 lastWordIdx-- 321 } 322 if digitsFrac > 0 { 323 digitsFrac -= countTrailingZeroes(9-((digitsFrac-1)%digitsPerWord), d.wordBuf[lastWordIdx-1]) 324 } else { 325 digitsFrac = 0 326 } 327 return 328 } 329 330 // ToString converts decimal to its printable string representation without rounding. 331 // 332 // RETURN VALUE 333 // 334 // str - result string 335 // errCode - eDecOK/eDecTruncate/eDecOverflow 336 // 337 func (d *Decimal) ToString() (str []byte) { 338 str = make([]byte, d.stringSize()) 339 digitsFrac := int(d.digitsFrac) 340 wordStartIdx, digitsInt := d.removeLeadingZeros() 341 if digitsInt+digitsFrac == 0 { 342 digitsInt = 1 343 wordStartIdx = 0 344 } 345 346 digitsIntLen := digitsInt 347 if digitsIntLen == 0 { 348 digitsIntLen = 1 349 } 350 digitsFracLen := digitsFrac 351 length := digitsIntLen + digitsFracLen 352 if d.negative { 353 length++ 354 } 355 if digitsFrac > 0 { 356 length++ 357 } 358 str = str[:length] 359 strIdx := 0 360 if d.negative { 361 str[strIdx] = '-' 362 strIdx++ 363 } 364 var fill int 365 if digitsFrac > 0 { 366 fracIdx := strIdx + digitsIntLen 367 fill = digitsFracLen - digitsFrac 368 wordIdx := wordStartIdx + digitsToWords(digitsInt) 369 str[fracIdx] = '.' 370 fracIdx++ 371 for ; digitsFrac > 0; digitsFrac -= digitsPerWord { 372 x := d.wordBuf[wordIdx] 373 wordIdx++ 374 for i := myMin(digitsFrac, digitsPerWord); i > 0; i-- { 375 y := x / digMask 376 str[fracIdx] = byte(y) + '0' 377 fracIdx++ 378 x -= y * digMask 379 x *= 10 380 } 381 } 382 for ; fill > 0; fill-- { 383 str[fracIdx] = '0' 384 fracIdx++ 385 } 386 } 387 fill = digitsIntLen - digitsInt 388 if digitsInt == 0 { 389 fill-- /* symbol 0 before digital point */ 390 } 391 for ; fill > 0; fill-- { 392 str[strIdx] = '0' 393 strIdx++ 394 } 395 if digitsInt > 0 { 396 strIdx += digitsInt 397 wordIdx := wordStartIdx + digitsToWords(digitsInt) 398 for ; digitsInt > 0; digitsInt -= digitsPerWord { 399 wordIdx-- 400 x := d.wordBuf[wordIdx] 401 for i := myMin(digitsInt, digitsPerWord); i > 0; i-- { 402 y := x / 10 403 strIdx-- 404 str[strIdx] = '0' + byte(x-y*10) 405 x = y 406 } 407 } 408 } else { 409 str[strIdx] = '0' 410 } 411 return 412 } 413 414 // FromString parses decimal from string . 415 func (d *Decimal) FromString(str string) error { 416 return d.FromBytes([]byte(str)) 417 } 418 419 // FromString parses decimal from []byte. 420 func (d *Decimal) FromBytes(str []byte) error { 421 for i := 0; i < len(str); i++ { 422 if !isSpace(str[i]) { 423 str = str[i:] 424 break 425 } 426 } 427 if len(str) == 0 { 428 *d = zeroBigDecimal 429 return ErrBadNumber 430 } 431 switch str[0] { 432 case '-': 433 d.negative = true 434 fallthrough 435 case '+': 436 str = str[1:] 437 } 438 var strIdx int 439 for strIdx < len(str) && isDigit(str[strIdx]) { 440 strIdx++ 441 } 442 digitsInt := strIdx 443 var digitsFrac int 444 var endIdx int 445 if strIdx < len(str) && str[strIdx] == '.' { 446 endIdx = strIdx + 1 447 for endIdx < len(str) && isDigit(str[endIdx]) { 448 endIdx++ 449 } 450 digitsFrac = endIdx - strIdx - 1 451 } else { 452 digitsFrac = 0 453 endIdx = strIdx 454 } 455 if digitsInt+digitsFrac == 0 { 456 *d = zeroBigDecimal 457 return ErrBadNumber 458 } 459 wordsInt := digitsToWords(digitsInt) 460 wordsFrac := digitsToWords(digitsFrac) 461 wordsInt, wordsFrac, err := fixWordCntError(wordsInt, wordsFrac) 462 if err != nil { 463 digitsFrac = wordsFrac * digitsPerWord 464 if err == ErrOverflow { 465 digitsInt = wordsInt * digitsPerWord 466 } 467 } 468 d.digitsInt = int8(digitsInt) 469 d.digitsFrac = int8(digitsFrac) 470 wordIdx := wordsInt 471 strIdxTmp := strIdx 472 var word int32 473 var innerIdx int 474 for digitsInt > 0 { 475 digitsInt-- 476 strIdx-- 477 word += int32(str[strIdx]-'0') * powers10[innerIdx] 478 innerIdx++ 479 if innerIdx == digitsPerWord { 480 wordIdx-- 481 d.wordBuf[wordIdx] = word 482 word = 0 483 innerIdx = 0 484 } 485 } 486 if innerIdx != 0 { 487 wordIdx-- 488 d.wordBuf[wordIdx] = word 489 } 490 491 wordIdx = wordsInt 492 strIdx = strIdxTmp 493 word = 0 494 innerIdx = 0 495 for digitsFrac > 0 { 496 digitsFrac-- 497 strIdx++ 498 word = int32(str[strIdx]-'0') + word*10 499 innerIdx++ 500 if innerIdx == digitsPerWord { 501 d.wordBuf[wordIdx] = word 502 wordIdx++ 503 word = 0 504 innerIdx = 0 505 } 506 } 507 if innerIdx != 0 { 508 d.wordBuf[wordIdx] = word * powers10[digitsPerWord-innerIdx] 509 } 510 if endIdx+1 <= len(str) { 511 if str[endIdx] == 'e' || str[endIdx] == 'E' { 512 exponent, err1 := strToInt(string(str[endIdx+1:])) 513 if err1 != nil { 514 err = errors.Cause(err1) 515 if err != ErrTruncated { 516 *d = zeroBigDecimal 517 } 518 } 519 if exponent > math.MaxInt32/2 { 520 negative := d.negative 521 maxDecimal(wordBufLen*digitsPerWord, 0, d) 522 d.negative = negative 523 err = ErrOverflow 524 } 525 if exponent < math.MinInt32/2 && err != ErrOverflow { 526 *d = zeroBigDecimal 527 err = ErrTruncated 528 } 529 if err != ErrOverflow { 530 shiftErr := d.Shift(int(exponent)) 531 if shiftErr != nil { 532 if shiftErr == ErrOverflow { 533 negative := d.negative 534 maxDecimal(wordBufLen*digitsPerWord, 0, d) 535 d.negative = negative 536 } 537 err = shiftErr 538 } 539 } 540 } else { 541 trimstr := strings.TrimSpace(string(str[endIdx:])) 542 if len(trimstr) != 0 { 543 err = ErrTruncated 544 } 545 } 546 } 547 allZero := true 548 for i := 0; i < wordBufLen; i++ { 549 if d.wordBuf[i] != 0 { 550 allZero = false 551 break 552 } 553 } 554 if allZero { 555 d.negative = false 556 } 557 d.resultFrac = d.digitsFrac 558 return err 559 } 560 561 // Shift shifts decimal digits in given number (with rounding if it need), shift > 0 means shift to left shift, 562 // shift < 0 means right shift. In fact it is multiplying on 10^shift. 563 // 564 // RETURN 565 // eDecOK OK 566 // eDecOverflow operation lead to overflow, number is untoched 567 // eDecTruncated number was rounded to fit into buffer 568 // 569 func (d *Decimal) Shift(shift int) error { 570 var err error 571 if shift == 0 { 572 return nil 573 } 574 var ( 575 // digitBegin is index of first non zero digit (all indexes from 0). 576 digitBegin int 577 // digitEnd is index of position after last decimal digit. 578 digitEnd int 579 // point is index of digit position just after point. 580 point = digitsToWords(int(d.digitsInt)) * digitsPerWord 581 // new point position. 582 newPoint = point + shift 583 // number of digits in result. 584 digitsInt, digitsFrac int 585 newFront int 586 ) 587 digitBegin, digitEnd = d.digitBounds() 588 if digitBegin == digitEnd { 589 *d = zeroBigDecimal 590 return nil 591 } 592 593 digitsInt = newPoint - digitBegin 594 if digitsInt < 0 { 595 digitsInt = 0 596 } 597 digitsFrac = digitEnd - newPoint 598 if digitsFrac < 0 { 599 digitsFrac = 0 600 } 601 wordsInt := digitsToWords(digitsInt) 602 wordsFrac := digitsToWords(digitsFrac) 603 newLen := wordsInt + wordsFrac 604 if newLen > wordBufLen { 605 lack := newLen - wordBufLen 606 if wordsFrac < lack { 607 return ErrOverflow 608 } 609 /* cut off fraction part to allow new number to fit in our buffer */ 610 err = ErrTruncated 611 wordsFrac -= lack 612 diff := digitsFrac - wordsFrac*digitsPerWord 613 err1 := d.Round(d, digitEnd-point-diff, ModeHalfEven) 614 if err1 != nil { 615 return errors.Cause(err1) 616 } 617 digitEnd -= diff 618 digitsFrac = wordsFrac * digitsPerWord 619 if digitEnd <= digitBegin { 620 /* 621 We lost all digits (they will be shifted out of buffer), so we can 622 just return 0. 623 */ 624 *d = zeroBigDecimal 625 return ErrTruncated 626 } 627 } 628 629 if shift%digitsPerWord != 0 { 630 var lMiniShift, rMiniShift, miniShift int 631 var doLeft bool 632 /* 633 Calculate left/right shift to align decimal digits inside our bug 634 digits correctly. 635 */ 636 if shift > 0 { 637 lMiniShift = shift % digitsPerWord 638 rMiniShift = digitsPerWord - lMiniShift 639 doLeft = lMiniShift <= digitBegin 640 } else { 641 rMiniShift = (-shift) % digitsPerWord 642 lMiniShift = digitsPerWord - rMiniShift 643 doLeft = (digitsPerWord*wordBufLen - digitEnd) < rMiniShift 644 } 645 if doLeft { 646 d.doMiniLeftShift(lMiniShift, digitBegin, digitEnd) 647 miniShift = -lMiniShift 648 } else { 649 d.doMiniRightShift(rMiniShift, digitBegin, digitEnd) 650 miniShift = rMiniShift 651 } 652 newPoint += miniShift 653 /* 654 If number is shifted and correctly aligned in buffer we can finish. 655 */ 656 if shift+miniShift == 0 && (newPoint-digitsInt) < digitsPerWord { 657 d.digitsInt = int8(digitsInt) 658 d.digitsFrac = int8(digitsFrac) 659 return err /* already shifted as it should be */ 660 } 661 digitBegin += miniShift 662 digitEnd += miniShift 663 } 664 665 /* if new 'decimal front' is in first digit, we do not need move digits */ 666 newFront = newPoint - digitsInt 667 if newFront >= digitsPerWord || newFront < 0 { 668 /* need to move digits */ 669 var wordShift int 670 if newFront > 0 { 671 /* move left */ 672 wordShift = newFront / digitsPerWord 673 to := digitBegin/digitsPerWord - wordShift 674 barier := (digitEnd-1)/digitsPerWord - wordShift 675 for ; to <= barier; to++ { 676 d.wordBuf[to] = d.wordBuf[to+wordShift] 677 } 678 for barier += wordShift; to <= barier; to++ { 679 d.wordBuf[to] = 0 680 } 681 wordShift = -wordShift 682 } else { 683 /* move right */ 684 wordShift = (1 - newFront) / digitsPerWord 685 to := (digitEnd-1)/digitsPerWord + wordShift 686 barier := digitBegin/digitsPerWord + wordShift 687 for ; to >= barier; to-- { 688 d.wordBuf[to] = d.wordBuf[to-wordShift] 689 } 690 for barier -= wordShift; to >= barier; to-- { 691 d.wordBuf[to] = 0 692 } 693 } 694 digitShift := wordShift * digitsPerWord 695 digitBegin += digitShift 696 digitEnd += digitShift 697 newPoint += digitShift 698 } 699 /* 700 If there are gaps then fill them with 0. 701 702 Only one of following 'for' loops will work because wordIdxBegin <= wordIdxEnd. 703 */ 704 wordIdxBegin := digitBegin / digitsPerWord 705 wordIdxEnd := (digitEnd - 1) / digitsPerWord 706 wordIdxNewPoint := 0 707 708 /* We don't want negative new_point below */ 709 if newPoint != 0 { 710 wordIdxNewPoint = (newPoint - 1) / digitsPerWord 711 } 712 if wordIdxNewPoint > wordIdxEnd { 713 for wordIdxNewPoint > wordIdxEnd { 714 d.wordBuf[wordIdxNewPoint] = 0 715 wordIdxNewPoint-- 716 } 717 } else { 718 for ; wordIdxNewPoint < wordIdxBegin; wordIdxNewPoint++ { 719 d.wordBuf[wordIdxNewPoint] = 0 720 } 721 } 722 d.digitsInt = int8(digitsInt) 723 d.digitsFrac = int8(digitsFrac) 724 return err 725 } 726 727 /* 728 digitBounds returns bounds of decimal digits in the number. 729 730 start - index (from 0 ) of first decimal digits. 731 end - index of position just after last decimal digit. 732 */ 733 func (d *Decimal) digitBounds() (start, end int) { 734 var i int 735 bufBeg := 0 736 bufLen := digitsToWords(int(d.digitsInt)) + digitsToWords(int(d.digitsFrac)) 737 bufEnd := bufLen - 1 738 739 /* find non-zero digit from number beginning */ 740 for bufBeg < bufLen && d.wordBuf[bufBeg] == 0 { 741 bufBeg++ 742 } 743 if bufBeg >= bufLen { 744 return 0, 0 745 } 746 747 /* find non-zero decimal digit from number beginning */ 748 if bufBeg == 0 && d.digitsInt > 0 { 749 i = (int(d.digitsInt) - 1) % digitsPerWord 750 start = digitsPerWord - i - 1 751 } else { 752 i = digitsPerWord - 1 753 start = bufBeg * digitsPerWord 754 } 755 if bufBeg < bufLen { 756 start += countLeadingZeroes(i, d.wordBuf[bufBeg]) 757 } 758 759 /* find non-zero digit at the end */ 760 for bufEnd > bufBeg && d.wordBuf[bufEnd] == 0 { 761 bufEnd-- 762 } 763 /* find non-zero decimal digit from the end */ 764 if bufEnd == bufLen-1 && d.digitsFrac > 0 { 765 i = (int(d.digitsFrac)-1)%digitsPerWord + 1 766 end = bufEnd*digitsPerWord + i 767 i = digitsPerWord - i + 1 768 } else { 769 end = (bufEnd + 1) * digitsPerWord 770 i = 1 771 } 772 end -= countTrailingZeroes(i, d.wordBuf[bufEnd]) 773 return start, end 774 } 775 776 /* 777 doMiniLeftShift does left shift for alignment of data in buffer. 778 779 shift number of decimal digits on which it should be shifted 780 beg/end bounds of decimal digits (see digitsBounds()) 781 782 NOTE 783 Result fitting in the buffer should be garanted. 784 'shift' have to be from 1 to digitsPerWord-1 (inclusive) 785 */ 786 func (d *Decimal) doMiniLeftShift(shift, beg, end int) { 787 bufFrom := beg / digitsPerWord 788 bufEnd := (end - 1) / digitsPerWord 789 cShift := digitsPerWord - shift 790 if beg%digitsPerWord < shift { 791 d.wordBuf[bufFrom-1] = d.wordBuf[bufFrom] / powers10[cShift] 792 } 793 for bufFrom < bufEnd { 794 d.wordBuf[bufFrom] = (d.wordBuf[bufFrom]%powers10[cShift])*powers10[shift] + d.wordBuf[bufFrom+1]/powers10[cShift] 795 bufFrom++ 796 } 797 d.wordBuf[bufFrom] = (d.wordBuf[bufFrom] % powers10[cShift]) * powers10[shift] 798 } 799 800 /* 801 doMiniRightShift does right shift for alignment of data in buffer. 802 803 shift number of decimal digits on which it should be shifted 804 beg/end bounds of decimal digits (see digitsBounds()) 805 806 NOTE 807 Result fitting in the buffer should be garanted. 808 'shift' have to be from 1 to digitsPerWord-1 (inclusive) 809 */ 810 func (d *Decimal) doMiniRightShift(shift, beg, end int) { 811 bufFrom := (end - 1) / digitsPerWord 812 bufEnd := beg / digitsPerWord 813 cShift := digitsPerWord - shift 814 if digitsPerWord-((end-1)%digitsPerWord+1) < shift { 815 d.wordBuf[bufFrom+1] = (d.wordBuf[bufFrom] % powers10[shift]) * powers10[cShift] 816 } 817 for bufFrom > bufEnd { 818 d.wordBuf[bufFrom] = d.wordBuf[bufFrom]/powers10[shift] + (d.wordBuf[bufFrom-1]%powers10[shift])*powers10[cShift] 819 bufFrom-- 820 } 821 d.wordBuf[bufFrom] = d.wordBuf[bufFrom] / powers10[shift] 822 } 823 824 // Round rounds the decimal to "frac" digits. 825 // 826 // to - result buffer. d == to is allowed 827 // frac - to what position after fraction point to round. can be negative! 828 // roundMode - round to the nearest even or truncate 829 // ModeHalfEven rounds normally. 830 // Truncate just truncates the decimal. 831 // 832 // NOTES 833 // scale can be negative ! 834 // one TRUNCATED error (line XXX below) isn't treated very logical :( 835 // 836 // RETURN VALUE 837 // eDecOK/eDecTruncated 838 func (d *Decimal) Round(to *Decimal, frac int, roundMode RoundMode) (err error) { 839 // wordsFracTo is the number of fraction words in buffer. 840 wordsFracTo := (frac + 1) / digitsPerWord 841 if frac > 0 { 842 wordsFracTo = digitsToWords(frac) 843 } 844 wordsFrac := digitsToWords(int(d.digitsFrac)) 845 wordsInt := digitsToWords(int(d.digitsInt)) 846 847 roundDigit := int32(roundMode) 848 /* TODO - fix this code as it won't work for CEILING mode */ 849 850 if wordsInt+wordsFracTo > wordBufLen { 851 wordsFracTo = wordBufLen - wordsInt 852 frac = wordsFracTo * digitsPerWord 853 err = ErrTruncated 854 } 855 if int(d.digitsInt)+frac < 0 { 856 *to = zeroBigDecimal 857 return nil 858 } 859 if to != d { 860 copy(to.wordBuf[:], d.wordBuf[:]) 861 to.negative = d.negative 862 to.digitsInt = int8(myMin(wordsInt, wordBufLen) * digitsPerWord) 863 } 864 if wordsFracTo > wordsFrac { 865 idx := wordsInt + wordsFrac 866 for wordsFracTo > wordsFrac { 867 wordsFracTo-- 868 to.wordBuf[idx] = 0 869 idx++ 870 } 871 to.digitsFrac = int8(frac) 872 to.resultFrac = to.digitsFrac 873 return 874 } 875 if frac >= int(d.digitsFrac) { 876 to.digitsFrac = int8(frac) 877 to.resultFrac = to.digitsFrac 878 return 879 } 880 881 // Do increment. 882 toIdx := wordsInt + wordsFracTo - 1 883 if frac == wordsFracTo*digitsPerWord { 884 doInc := false 885 switch roundMode { 886 // Notice: No support for ceiling mode now. 887 case modeCeiling: 888 // If any word after scale is not zero, do increment. 889 // e.g ceiling 3.0001 to scale 1, gets 3.1 890 idx := toIdx + (wordsFrac - wordsFracTo) 891 for idx > toIdx { 892 if d.wordBuf[idx] != 0 { 893 doInc = true 894 break 895 } 896 idx-- 897 } 898 case ModeHalfEven: 899 digAfterScale := d.wordBuf[toIdx+1] / digMask // the first digit after scale. 900 // If first digit after scale is 5 and round even, do increment if digit at scale is odd. 901 doInc = (digAfterScale > 5) || (digAfterScale == 5) 902 case ModeTruncate: 903 // Never round, just truncate. 904 doInc = false 905 } 906 if doInc { 907 if toIdx >= 0 { 908 to.wordBuf[toIdx]++ 909 } else { 910 toIdx++ 911 to.wordBuf[toIdx] = wordBase 912 } 913 } else if wordsInt+wordsFracTo == 0 { 914 *to = zeroBigDecimal 915 return nil 916 } 917 } else { 918 /* TODO - fix this code as it won't work for CEILING mode */ 919 pos := wordsFracTo*digitsPerWord - frac - 1 920 shiftedNumber := to.wordBuf[toIdx] / powers10[pos] 921 digAfterScale := shiftedNumber % 10 922 if digAfterScale > roundDigit || (roundDigit == 5 && digAfterScale == 5) { 923 shiftedNumber += 10 924 } 925 to.wordBuf[toIdx] = powers10[pos] * (shiftedNumber - digAfterScale) 926 } 927 /* 928 In case we're rounding e.g. 1.5e9 to 2.0e9, the decimal words inside 929 the buffer are as follows. 930 931 Before <1, 5e8> 932 After <2, 5e8> 933 934 Hence we need to set the 2nd field to 0. 935 The same holds if we round 1.5e-9 to 2e-9. 936 */ 937 if wordsFracTo < wordsFrac { 938 idx := wordsInt + wordsFracTo 939 if frac == 0 && wordsInt == 0 { 940 idx = 1 941 } 942 for idx < wordBufLen { 943 to.wordBuf[idx] = 0 944 idx++ 945 } 946 } 947 948 // Handle carry. 949 var carry int32 950 if to.wordBuf[toIdx] >= wordBase { 951 carry = 1 952 to.wordBuf[toIdx] -= wordBase 953 for carry == 1 && toIdx > 0 { 954 toIdx-- 955 to.wordBuf[toIdx], carry = add(to.wordBuf[toIdx], 0, carry) 956 } 957 if carry > 0 { 958 if wordsInt+wordsFracTo >= wordBufLen { 959 wordsFracTo-- 960 frac = wordsFracTo * digitsPerWord 961 err = ErrTruncated 962 } 963 for toIdx = wordsInt + myMax(wordsFracTo, 0); toIdx > 0; toIdx-- { 964 if toIdx < wordBufLen { 965 to.wordBuf[toIdx] = to.wordBuf[toIdx-1] 966 } else { 967 err = ErrOverflow 968 } 969 } 970 to.wordBuf[toIdx] = 1 971 /* We cannot have more than 9 * 9 = 81 digits. */ 972 if int(to.digitsInt) < digitsPerWord*wordBufLen { 973 to.digitsInt++ 974 } else { 975 err = ErrOverflow 976 } 977 } 978 } else { 979 for { 980 if to.wordBuf[toIdx] != 0 { 981 break 982 } 983 if toIdx == 0 { 984 /* making 'zero' with the proper scale */ 985 idx := wordsFracTo + 1 986 to.digitsInt = 1 987 to.digitsFrac = int8(myMax(frac, 0)) 988 to.negative = false 989 for toIdx < idx { 990 to.wordBuf[toIdx] = 0 991 toIdx++ 992 } 993 to.resultFrac = to.digitsFrac 994 return nil 995 } 996 toIdx-- 997 } 998 } 999 /* Here we check 999.9 -> 1000 case when we need to increase intDigCnt */ 1000 firstDig := mod9[to.digitsInt] 1001 if firstDig > 0 && to.wordBuf[toIdx] >= powers10[firstDig] { 1002 to.digitsInt++ 1003 } 1004 if frac < 0 { 1005 frac = 0 1006 } 1007 to.digitsFrac = int8(frac) 1008 to.resultFrac = to.digitsFrac 1009 return 1010 } 1011 1012 // FromInt sets the decimal value from int64. 1013 func (d *Decimal) FromInt(val int64) *Decimal { 1014 var uVal uint64 1015 if val < 0 { 1016 d.negative = true 1017 uVal = uint64(-val) 1018 } else { 1019 uVal = uint64(val) 1020 } 1021 return d.FromUint(uVal) 1022 } 1023 1024 // FromUint sets the decimal value from uint64. 1025 func (d *Decimal) FromUint(val uint64) *Decimal { 1026 x := val 1027 wordIdx := 1 1028 for x >= wordBase { 1029 wordIdx++ 1030 x /= wordBase 1031 } 1032 d.digitsFrac = 0 1033 d.digitsInt = int8(wordIdx * digitsPerWord) 1034 x = val 1035 for wordIdx > 0 { 1036 wordIdx-- 1037 y := x / wordBase 1038 d.wordBuf[wordIdx] = int32(x - y*wordBase) 1039 x = y 1040 } 1041 return d 1042 } 1043 1044 // ToInt returns int part of the decimal, returns the result and errcode. 1045 func (d *Decimal) ToInt() (int64, error) { 1046 var x int64 1047 wordIdx := 0 1048 for i := d.digitsInt; i > 0; i -= digitsPerWord { 1049 y := x 1050 /* 1051 Attention: trick! 1052 we're calculating -|from| instead of |from| here 1053 because |LONGLONG_MIN| > LONGLONG_MAX 1054 so we can convert -9223372036854775808 correctly 1055 */ 1056 x = x*wordBase - int64(d.wordBuf[wordIdx]) 1057 wordIdx++ 1058 if y < math.MinInt64/wordBase || x > y { 1059 /* 1060 the decimal is bigger than any possible integer 1061 return border integer depending on the sign 1062 */ 1063 if d.negative { 1064 return math.MinInt64, ErrOverflow 1065 } 1066 return math.MaxInt64, ErrOverflow 1067 } 1068 } 1069 /* boundary case: 9223372036854775808 */ 1070 if !d.negative && x == math.MinInt64 { 1071 return math.MaxInt64, ErrOverflow 1072 } 1073 if !d.negative { 1074 x = -x 1075 } 1076 for i := d.digitsFrac; i > 0; i -= digitsPerWord { 1077 if d.wordBuf[wordIdx] != 0 { 1078 return x, ErrTruncated 1079 } 1080 wordIdx++ 1081 } 1082 return x, nil 1083 } 1084 1085 // ToUint returns int part of the decimal, returns the result and errcode. 1086 func (d *Decimal) ToUint() (uint64, error) { 1087 if d.negative { 1088 return 0, ErrOverflow 1089 } 1090 var x uint64 1091 wordIdx := 0 1092 for i := d.digitsInt; i > 0; i -= digitsPerWord { 1093 y := x 1094 x = x*wordBase + uint64(d.wordBuf[wordIdx]) 1095 wordIdx++ 1096 if y > math.MaxUint64/wordBase || x < y { 1097 return math.MaxUint64, ErrOverflow 1098 } 1099 } 1100 for i := d.digitsFrac; i > 0; i -= digitsPerWord { 1101 if d.wordBuf[wordIdx] != 0 { 1102 return x, ErrTruncated 1103 } 1104 wordIdx++ 1105 } 1106 return x, nil 1107 } 1108 1109 // FromFloat64 creates a decimal from float64 value. 1110 func (d *Decimal) FromFloat64(f float64) error { 1111 s := strconv.FormatFloat(f, 'g', -1, 64) 1112 return d.FromString(s) 1113 } 1114 1115 // ToFloat64 converts decimal to float64 value. 1116 func (d *Decimal) ToFloat64() (f float64, err error) { 1117 digitsInt := int(d.digitsInt) 1118 digitsFrac := int(d.digitsFrac) 1119 // https://en.wikipedia.org/wiki/Double-precision_floating-point_format#IEEE_754_double-precision_binary_floating-point_format:_binary64 1120 // "The 53-bit significand precision gives from 15 to 17 significant decimal digits precision (2−53 ≈ 1.11 × 10−16). 1121 // If a decimal string with at most 15 significant digits is converted to IEEE 754 double-precision representation, 1122 // and then converted back to a decimal string with the same number of digits, the final result should match the original string." 1123 // The new method is about 10.5X faster than the old one according to the benchmark in types/mydecimal_benchmark_test.go. 1124 // The initial threshold here is 15, we adjusted it to 12 for compatibility with previous. 1125 // We did a full test of 12 significant digits to make sure it's correct and behaves as before. 1126 if digitsInt+digitsFrac > 12 { 1127 f, err = strconv.ParseFloat(d.String(), 64) 1128 if err != nil { 1129 err = ErrOverflow 1130 } 1131 return 1132 } 1133 wordsInt := (digitsInt-1)/digitsPerWord + 1 1134 wordIdx := 0 1135 for i := 0; i < digitsInt; i += digitsPerWord { 1136 x := d.wordBuf[wordIdx] 1137 wordIdx++ 1138 // Equivalent to f += float64(x) * math.Pow10((wordsInt-wordIdx)*digitsPerWord) 1139 f += float64(x) * pow10off81[(wordsInt-wordIdx)*digitsPerWord+pow10off] 1140 } 1141 fracStart := wordIdx 1142 for i := 0; i < digitsFrac; i += digitsPerWord { 1143 x := d.wordBuf[wordIdx] 1144 wordIdx++ 1145 // Equivalent to f += float64(x) * math.Pow10(-digitsPerWord*(wordIdx-fracStart)) 1146 f += float64(x) * pow10off81[-digitsPerWord*(wordIdx-fracStart)+pow10off] 1147 } 1148 // Equivalent to unit := math.Pow10(int(d.resultFrac)) 1149 unit := pow10off81[int(d.resultFrac)+pow10off] 1150 f = math.Round(f*unit) / unit 1151 if d.negative { 1152 f = -f 1153 } 1154 return 1155 } 1156 1157 /* 1158 ToBin converts decimal to its binary fixed-length representation 1159 two representations of the same length can be compared with memcmp 1160 with the correct -1/0/+1 result 1161 1162 PARAMS 1163 precision/frac - if precision is 0, internal value of the decimal will be used, 1164 then the encoded value is not memory comparable. 1165 1166 NOTE 1167 the buffer is assumed to be of the size DecimalBinSize(precision, frac) 1168 1169 RETURN VALUE 1170 bin - binary value 1171 errCode - eDecOK/eDecTruncate/eDecOverflow 1172 1173 DESCRIPTION 1174 for storage decimal numbers are converted to the "binary" format. 1175 1176 This format has the following properties: 1177 1. length of the binary representation depends on the {precision, frac} 1178 as provided by the caller and NOT on the digitsInt/digitsFrac of the decimal to 1179 convert. 1180 2. binary representations of the same {precision, frac} can be compared 1181 with memcmp - with the same result as DecimalCompare() of the original 1182 decimals (not taking into account possible precision loss during 1183 conversion). 1184 1185 This binary format is as follows: 1186 1. First the number is converted to have a requested precision and frac. 1187 2. Every full digitsPerWord digits of digitsInt part are stored in 4 bytes 1188 as is 1189 3. The first digitsInt % digitesPerWord digits are stored in the reduced 1190 number of bytes (enough bytes to store this number of digits - 1191 see dig2bytes) 1192 4. same for frac - full word are stored as is, 1193 the last frac % digitsPerWord digits - in the reduced number of bytes. 1194 5. If the number is negative - every byte is inversed. 1195 5. The very first bit of the resulting byte array is inverted (because 1196 memcmp compares unsigned bytes, see property 2 above) 1197 1198 Example: 1199 1200 1234567890.1234 1201 1202 internally is represented as 3 words 1203 1204 1 234567890 123400000 1205 1206 (assuming we want a binary representation with precision=14, frac=4) 1207 in hex it's 1208 1209 00-00-00-01 0D-FB-38-D2 07-5A-EF-40 1210 1211 now, middle word is full - it stores 9 decimal digits. It goes 1212 into binary representation as is: 1213 1214 1215 ........... 0D-FB-38-D2 ............ 1216 1217 First word has only one decimal digit. We can store one digit in 1218 one byte, no need to waste four: 1219 1220 01 0D-FB-38-D2 ............ 1221 1222 now, last word. It's 123400000. We can store 1234 in two bytes: 1223 1224 01 0D-FB-38-D2 04-D2 1225 1226 So, we've packed 12 bytes number in 7 bytes. 1227 And now we invert the highest bit to get the final result: 1228 1229 81 0D FB 38 D2 04 D2 1230 1231 And for -1234567890.1234 it would be 1232 1233 7E F2 04 C7 2D FB 2D 1234 */ 1235 func (d *Decimal) ToBin(precision, frac int) ([]byte, error) { 1236 return d.WriteBin(precision, frac, []byte{}) 1237 } 1238 1239 // WriteBin encode and write the binary encoded to target buffer 1240 func (d *Decimal) WriteBin(precision, frac int, buf []byte) ([]byte, error) { 1241 if precision > digitsPerWord*maxWordBufLen || precision < 0 || frac > int(maxDecimalScale) || frac < 0 { 1242 return buf, ErrBadNumber 1243 } 1244 var err error 1245 var mask int32 1246 if d.negative { 1247 mask = -1 1248 } 1249 digitsInt := precision - frac 1250 wordsInt := digitsInt / digitsPerWord 1251 leadingDigits := digitsInt - wordsInt*digitsPerWord 1252 wordsFrac := frac / digitsPerWord 1253 trailingDigits := frac - wordsFrac*digitsPerWord 1254 1255 wordsFracFrom := int(d.digitsFrac) / digitsPerWord 1256 trailingDigitsFrom := int(d.digitsFrac) - wordsFracFrom*digitsPerWord 1257 intSize := wordsInt*wordSize + dig2bytes[leadingDigits] 1258 fracSize := wordsFrac*wordSize + dig2bytes[trailingDigits] 1259 fracSizeFrom := wordsFracFrom*wordSize + dig2bytes[trailingDigitsFrom] 1260 originIntSize := intSize 1261 originFracSize := fracSize 1262 bufLen := len(buf) 1263 if bufLen+intSize+fracSize <= cap(buf) { 1264 buf = buf[:bufLen+intSize+fracSize] 1265 } else { 1266 buf = append(buf, make([]byte, intSize+fracSize)...) 1267 } 1268 bin := buf[bufLen:] 1269 binIdx := 0 1270 wordIdxFrom, digitsIntFrom := d.removeLeadingZeros() 1271 if digitsIntFrom+fracSizeFrom == 0 { 1272 mask = 0 1273 digitsInt = 1 1274 } 1275 1276 wordsIntFrom := digitsIntFrom / digitsPerWord 1277 leadingDigitsFrom := digitsIntFrom - wordsIntFrom*digitsPerWord 1278 iSizeFrom := wordsIntFrom*wordSize + dig2bytes[leadingDigitsFrom] 1279 1280 if digitsInt < digitsIntFrom { 1281 wordIdxFrom += wordsIntFrom - wordsInt 1282 if leadingDigitsFrom > 0 { 1283 wordIdxFrom++ 1284 } 1285 if leadingDigits > 0 { 1286 wordIdxFrom-- 1287 } 1288 wordsIntFrom = wordsInt 1289 leadingDigitsFrom = leadingDigits 1290 err = ErrOverflow 1291 } else if intSize > iSizeFrom { 1292 for intSize > iSizeFrom { 1293 intSize-- 1294 bin[binIdx] = byte(mask) 1295 binIdx++ 1296 } 1297 } 1298 1299 if fracSize < fracSizeFrom || 1300 (fracSize == fracSizeFrom && (trailingDigits <= trailingDigitsFrom || wordsFrac <= wordsFracFrom)) { 1301 if fracSize < fracSizeFrom || (fracSize == fracSizeFrom && trailingDigits < trailingDigitsFrom) || (fracSize == fracSizeFrom && wordsFrac < wordsFracFrom) { 1302 err = ErrTruncated 1303 } 1304 wordsFracFrom = wordsFrac 1305 trailingDigitsFrom = trailingDigits 1306 } else if fracSize > fracSizeFrom && trailingDigitsFrom > 0 { 1307 if wordsFrac == wordsFracFrom { 1308 trailingDigitsFrom = trailingDigits 1309 fracSize = fracSizeFrom 1310 } else { 1311 wordsFracFrom++ 1312 trailingDigitsFrom = 0 1313 } 1314 } 1315 // xIntFrom part 1316 if leadingDigitsFrom > 0 { 1317 i := dig2bytes[leadingDigitsFrom] 1318 x := (d.wordBuf[wordIdxFrom] % powers10[leadingDigitsFrom]) ^ mask 1319 wordIdxFrom++ 1320 writeWord(bin[binIdx:], x, i) 1321 binIdx += i 1322 } 1323 1324 // wordsInt + wordsFrac part. 1325 for stop := wordIdxFrom + wordsIntFrom + wordsFracFrom; wordIdxFrom < stop; binIdx += wordSize { 1326 x := d.wordBuf[wordIdxFrom] ^ mask 1327 wordIdxFrom++ 1328 writeWord(bin[binIdx:], x, 4) 1329 } 1330 1331 // xFracFrom part 1332 if trailingDigitsFrom > 0 { 1333 var x int32 1334 i := dig2bytes[trailingDigitsFrom] 1335 lim := trailingDigits 1336 if wordsFracFrom < wordsFrac { 1337 lim = digitsPerWord 1338 } 1339 1340 for trailingDigitsFrom < lim && dig2bytes[trailingDigitsFrom] == i { 1341 trailingDigitsFrom++ 1342 } 1343 x = (d.wordBuf[wordIdxFrom] / powers10[digitsPerWord-trailingDigitsFrom]) ^ mask 1344 writeWord(bin[binIdx:], x, i) 1345 binIdx += i 1346 } 1347 if fracSize > fracSizeFrom { 1348 binIdxEnd := originIntSize + originFracSize 1349 for fracSize > fracSizeFrom && binIdx < binIdxEnd { 1350 fracSize-- 1351 bin[binIdx] = byte(mask) 1352 binIdx++ 1353 } 1354 } 1355 bin[0] ^= 0x80 1356 return buf, err 1357 } 1358 1359 // ToHashKey removes the leading and trailing zeros and generates a hash key. 1360 // Two Decimals dec0 and dec1 with different fraction will generate the same hash keys if dec0.Compare(dec1) == 0. 1361 func (d *Decimal) ToHashKey() ([]byte, error) { 1362 _, digitsInt := d.removeLeadingZeros() 1363 _, digitsFrac := d.removeTrailingZeros() 1364 prec := digitsInt + digitsFrac 1365 if prec == 0 { // zeroDecimal 1366 prec = 1 1367 } 1368 buf, err := d.ToBin(prec, digitsFrac) 1369 if err == ErrTruncated { 1370 // This err is caused by shorter digitsFrac; 1371 // After removing the trailing zeros from a Decimal, 1372 // so digitsFrac may be less than the real digitsFrac of the Decimal, 1373 // thus ErrTruncated may be raised, we can ignore it here. 1374 err = nil 1375 } 1376 buf = append(buf, byte(digitsFrac)) 1377 return buf, err 1378 } 1379 1380 // PrecisionAndFrac returns the internal precision and frac number. 1381 func (d *Decimal) PrecisionAndFrac() (precision, frac int) { 1382 frac = int(d.digitsFrac) 1383 _, digitsInt := d.removeLeadingZeros() 1384 precision = digitsInt + frac 1385 if precision == 0 { 1386 precision = 1 1387 } 1388 return 1389 } 1390 1391 // IsZero checks whether it's a zero decimal. 1392 func (d *Decimal) IsZero() bool { 1393 isZero := true 1394 for _, val := range d.wordBuf { 1395 if val != 0 { 1396 isZero = false 1397 break 1398 } 1399 } 1400 return isZero 1401 } 1402 1403 // FromBin Restores decimal from its binary fixed-length representation. 1404 func (d *Decimal) FromBin(bin []byte, precision, frac int) (binSize int, err error) { 1405 if len(bin) == 0 { 1406 *d = zeroBigDecimal 1407 return 0, ErrBadNumber 1408 } 1409 digitsInt := precision - frac 1410 wordsInt := digitsInt / digitsPerWord 1411 leadingDigits := digitsInt - wordsInt*digitsPerWord 1412 wordsFrac := frac / digitsPerWord 1413 trailingDigits := frac - wordsFrac*digitsPerWord 1414 wordsIntTo := wordsInt 1415 if leadingDigits > 0 { 1416 wordsIntTo++ 1417 } 1418 wordsFracTo := wordsFrac 1419 if trailingDigits > 0 { 1420 wordsFracTo++ 1421 } 1422 1423 binIdx := 0 1424 mask := int32(-1) 1425 if bin[binIdx]&0x80 > 0 { 1426 mask = 0 1427 } 1428 binSize, err = DecimalBinSize(precision, frac) 1429 if err != nil { 1430 return 0, err 1431 } 1432 if binSize < 0 || binSize > 40 { 1433 return 0, ErrBadNumber 1434 } 1435 dCopy := make([]byte, 40) 1436 dCopy = dCopy[:binSize] 1437 copy(dCopy, bin) 1438 dCopy[0] ^= 0x80 1439 bin = dCopy 1440 oldWordsIntTo := wordsIntTo 1441 wordsIntTo, wordsFracTo, err = fixWordCntError(wordsIntTo, wordsFracTo) 1442 if err != nil { 1443 if wordsIntTo < oldWordsIntTo { 1444 binIdx += dig2bytes[leadingDigits] + (wordsInt-wordsIntTo)*wordSize 1445 } else { 1446 trailingDigits = 0 1447 wordsFrac = wordsFracTo 1448 } 1449 } 1450 d.negative = mask != 0 1451 d.digitsInt = int8(wordsInt*digitsPerWord + leadingDigits) 1452 d.digitsFrac = int8(wordsFrac*digitsPerWord + trailingDigits) 1453 1454 wordIdx := 0 1455 if leadingDigits > 0 { 1456 i := dig2bytes[leadingDigits] 1457 x := readWord(bin[binIdx:], i) 1458 binIdx += i 1459 d.wordBuf[wordIdx] = x ^ mask 1460 if uint64(d.wordBuf[wordIdx]) >= uint64(powers10[leadingDigits+1]) { 1461 *d = zeroBigDecimal 1462 return binSize, ErrBadNumber 1463 } 1464 if wordIdx > 0 || d.wordBuf[wordIdx] != 0 { 1465 wordIdx++ 1466 } else { 1467 d.digitsInt -= int8(leadingDigits) 1468 } 1469 } 1470 for stop := binIdx + wordsInt*wordSize; binIdx < stop; binIdx += wordSize { 1471 d.wordBuf[wordIdx] = readWord(bin[binIdx:], 4) ^ mask 1472 if uint32(d.wordBuf[wordIdx]) > wordMax { 1473 *d = zeroBigDecimal 1474 return binSize, ErrBadNumber 1475 } 1476 if wordIdx > 0 || d.wordBuf[wordIdx] != 0 { 1477 wordIdx++ 1478 } else { 1479 d.digitsInt -= digitsPerWord 1480 } 1481 } 1482 1483 for stop := binIdx + wordsFrac*wordSize; binIdx < stop; binIdx += wordSize { 1484 d.wordBuf[wordIdx] = readWord(bin[binIdx:], 4) ^ mask 1485 if uint32(d.wordBuf[wordIdx]) > wordMax { 1486 *d = zeroBigDecimal 1487 return binSize, ErrBadNumber 1488 } 1489 wordIdx++ 1490 } 1491 1492 if trailingDigits > 0 { 1493 i := dig2bytes[trailingDigits] 1494 x := readWord(bin[binIdx:], i) 1495 d.wordBuf[wordIdx] = (x ^ mask) * powers10[digitsPerWord-trailingDigits] 1496 if uint32(d.wordBuf[wordIdx]) > wordMax { 1497 *d = zeroBigDecimal 1498 return binSize, ErrBadNumber 1499 } 1500 } 1501 1502 if d.digitsInt == 0 && d.digitsFrac == 0 { 1503 *d = zeroBigDecimal 1504 } 1505 d.resultFrac = int8(frac) 1506 return binSize, err 1507 } 1508 1509 // DecimalBinSize returns the size of array to hold a binary representation of a decimal. 1510 func DecimalBinSize(precision, frac int) (int, error) { 1511 digitsInt := precision - frac 1512 wordsInt := digitsInt / digitsPerWord 1513 wordsFrac := frac / digitsPerWord 1514 xInt := digitsInt - wordsInt*digitsPerWord 1515 xFrac := frac - wordsFrac*digitsPerWord 1516 if xInt < 0 || xInt >= len(dig2bytes) || xFrac < 0 || xFrac >= len(dig2bytes) { 1517 return 0, ErrBadNumber 1518 } 1519 return wordsInt*wordSize + dig2bytes[xInt] + wordsFrac*wordSize + dig2bytes[xFrac], nil 1520 } 1521 1522 func readWord(b []byte, size int) int32 { 1523 var x int32 1524 switch size { 1525 case 1: 1526 x = int32(int8(b[0])) 1527 case 2: 1528 x = int32(int8(b[0]))<<8 + int32(b[1]) 1529 case 3: 1530 if b[0]&128 > 0 { 1531 x = int32(uint32(255)<<24 | uint32(b[0])<<16 | uint32(b[1])<<8 | uint32(b[2])) 1532 } else { 1533 x = int32(uint32(b[0])<<16 | uint32(b[1])<<8 | uint32(b[2])) 1534 } 1535 case 4: 1536 x = int32(b[3]) + int32(b[2])<<8 + int32(b[1])<<16 + int32(int8(b[0]))<<24 1537 } 1538 return x 1539 } 1540 1541 func writeWord(b []byte, word int32, size int) { 1542 v := uint32(word) 1543 switch size { 1544 case 1: 1545 b[0] = byte(word) 1546 case 2: 1547 b[0] = byte(v >> 8) 1548 b[1] = byte(v) 1549 case 3: 1550 b[0] = byte(v >> 16) 1551 b[1] = byte(v >> 8) 1552 b[2] = byte(v) 1553 case 4: 1554 b[0] = byte(v >> 24) 1555 b[1] = byte(v >> 16) 1556 b[2] = byte(v >> 8) 1557 b[3] = byte(v) 1558 } 1559 } 1560 1561 // Compare compares one decimal to another, returns -1/0/1. 1562 func (d *Decimal) Compare(to *Decimal) int { 1563 if d.negative == to.negative { 1564 cmp, err := doSub(d, to, nil) 1565 if err != nil { 1566 log.Printf("decimal compare = error{%v}", err) 1567 } 1568 return cmp 1569 } 1570 if d.negative { 1571 return -1 1572 } 1573 return 1 1574 } 1575 1576 // None of ToBin, ToFloat64, or ToString can encode MyDecimal without loss. 1577 // So we still need a MarshalJSON/UnmarshalJSON function. 1578 type jsonDecimal struct { 1579 DigitsInt int8 1580 DigitsFrac int8 1581 ResultFrac int8 1582 Negative bool 1583 WordBuf [maxWordBufLen]int32 1584 } 1585 1586 // MarshalJSON implements Marshaler.MarshalJSON interface. 1587 func (d *Decimal) MarshalJSON() ([]byte, error) { 1588 var r jsonDecimal 1589 r.DigitsInt = d.digitsInt 1590 r.DigitsFrac = d.digitsFrac 1591 r.ResultFrac = d.resultFrac 1592 r.Negative = d.negative 1593 r.WordBuf = d.wordBuf 1594 return json.Marshal(r) 1595 } 1596 1597 // UnmarshalJSON implements Unmarshaler.UnmarshalJSON interface. 1598 func (d *Decimal) UnmarshalJSON(data []byte) error { 1599 var r jsonDecimal 1600 err := json.Unmarshal(data, &r) 1601 if err == nil { 1602 d.digitsInt = r.DigitsInt 1603 d.digitsFrac = r.DigitsFrac 1604 d.resultFrac = r.ResultFrac 1605 d.negative = r.Negative 1606 d.wordBuf = r.WordBuf 1607 } 1608 return err 1609 } 1610 1611 // DecimalNeg reverses decimal's sign. 1612 func DecimalNeg(from *Decimal) *Decimal { 1613 to := *from 1614 if from.IsZero() { 1615 return &to 1616 } 1617 to.negative = !from.negative 1618 return &to 1619 } 1620 1621 // DecimalAdd adds two decimals, sets the result to 'to'. 1622 // Note: DO NOT use `from1` or `from2` as `to` since the metadata 1623 // of `to` may be changed during evaluating. 1624 func DecimalAdd(from1, from2, to *Decimal) error { 1625 from1, from2, to = validateArgs(from1, from2, to) 1626 to.resultFrac = myMaxInt8(from1.resultFrac, from2.resultFrac) 1627 if from1.negative == from2.negative { 1628 return doAdd(from1, from2, to) 1629 } 1630 _, err := doSub(from1, from2, to) 1631 return err 1632 } 1633 1634 // DecimalSub subs one decimal from another, sets the result to 'to'. 1635 func DecimalSub(from1, from2, to *Decimal) error { 1636 from1, from2, to = validateArgs(from1, from2, to) 1637 to.resultFrac = myMaxInt8(from1.resultFrac, from2.resultFrac) 1638 if from1.negative == from2.negative { 1639 _, err := doSub(from1, from2, to) 1640 return err 1641 } 1642 return doAdd(from1, from2, to) 1643 } 1644 1645 func validateArgs(f1, f2, to *Decimal) (*Decimal, *Decimal, *Decimal) { 1646 if to == nil { 1647 return f1, f2, to 1648 } 1649 if f1 == to { 1650 tmp := *f1 1651 f1 = &tmp 1652 } 1653 if f2 == to { 1654 tmp := *f2 1655 f2 = &tmp 1656 } 1657 to.digitsFrac = 0 1658 to.digitsInt = 0 1659 to.resultFrac = 0 1660 to.negative = false 1661 for i := range to.wordBuf { 1662 to.wordBuf[i] = 0 1663 } 1664 return f1, f2, to 1665 } 1666 1667 func doSub(from1, from2, to *Decimal) (cmp int, err error) { 1668 var ( 1669 wordsInt1 = digitsToWords(int(from1.digitsInt)) 1670 wordsFrac1 = digitsToWords(int(from1.digitsFrac)) 1671 wordsInt2 = digitsToWords(int(from2.digitsInt)) 1672 wordsFrac2 = digitsToWords(int(from2.digitsFrac)) 1673 wordsFracTo = myMax(wordsFrac1, wordsFrac2) 1674 1675 start1 = 0 1676 stop1 = wordsInt1 1677 idx1 = 0 1678 start2 = 0 1679 stop2 = wordsInt2 1680 idx2 = 0 1681 ) 1682 if from1.wordBuf[idx1] == 0 { 1683 for idx1 < stop1 && from1.wordBuf[idx1] == 0 { 1684 idx1++ 1685 } 1686 start1 = idx1 1687 wordsInt1 = stop1 - idx1 1688 } 1689 if from2.wordBuf[idx2] == 0 { 1690 for idx2 < stop2 && from2.wordBuf[idx2] == 0 { 1691 idx2++ 1692 } 1693 start2 = idx2 1694 wordsInt2 = stop2 - idx2 1695 } 1696 1697 var carry int32 1698 if wordsInt2 > wordsInt1 { 1699 carry = 1 1700 } else if wordsInt2 == wordsInt1 { 1701 end1 := stop1 + wordsFrac1 - 1 1702 end2 := stop2 + wordsFrac2 - 1 1703 for idx1 <= end1 && from1.wordBuf[end1] == 0 { 1704 end1-- 1705 } 1706 for idx2 <= end2 && from2.wordBuf[end2] == 0 { 1707 end2-- 1708 } 1709 wordsFrac1 = end1 - stop1 + 1 1710 wordsFrac2 = end2 - stop2 + 1 1711 for idx1 <= end1 && idx2 <= end2 && from1.wordBuf[idx1] == from2.wordBuf[idx2] { 1712 idx1++ 1713 idx2++ 1714 } 1715 if idx1 <= end1 { 1716 if idx2 <= end2 && from2.wordBuf[idx2] > from1.wordBuf[idx1] { 1717 carry = 1 1718 } else { 1719 carry = 0 1720 } 1721 } else { 1722 if idx2 <= end2 { 1723 carry = 1 1724 } else { 1725 if to == nil { 1726 return 0, nil 1727 } 1728 *to = zeroMyDecimalWithFrac(to.resultFrac) 1729 return 0, nil 1730 } 1731 } 1732 } 1733 1734 if to == nil { 1735 if carry > 0 == from1.negative { // from2 is negative too. 1736 return 1, nil 1737 } 1738 return -1, nil 1739 } 1740 1741 to.negative = from1.negative 1742 1743 /* ensure that always idx1 > idx2 (and wordsInt1 >= wordsInt2) */ 1744 if carry > 0 { 1745 from1, from2 = from2, from1 1746 start1, start2 = start2, start1 1747 wordsInt1, wordsInt2 = wordsInt2, wordsInt1 1748 wordsFrac1, wordsFrac2 = wordsFrac2, wordsFrac1 1749 to.negative = !to.negative 1750 } 1751 1752 wordsInt1, wordsFracTo, err = fixWordCntError(wordsInt1, wordsFracTo) 1753 idxTo := wordsInt1 + wordsFracTo 1754 to.digitsFrac = from1.digitsFrac 1755 if to.digitsFrac < from2.digitsFrac { 1756 to.digitsFrac = from2.digitsFrac 1757 } 1758 to.digitsInt = int8(wordsInt1 * digitsPerWord) 1759 if err != nil { 1760 if to.digitsFrac > int8(wordsFracTo*digitsPerWord) { 1761 to.digitsFrac = int8(wordsFracTo * digitsPerWord) 1762 } 1763 if wordsFrac1 > wordsFracTo { 1764 wordsFrac1 = wordsFracTo 1765 } 1766 if wordsFrac2 > wordsFracTo { 1767 wordsFrac2 = wordsFracTo 1768 } 1769 if wordsInt2 > wordsInt1 { 1770 wordsInt2 = wordsInt1 1771 } 1772 } 1773 carry = 0 1774 1775 /* part 1 - max(frac) ... min (frac) */ 1776 if wordsFrac1 > wordsFrac2 { 1777 idx1 = start1 + wordsInt1 + wordsFrac1 1778 stop1 = start1 + wordsInt1 + wordsFrac2 1779 idx2 = start2 + wordsInt2 + wordsFrac2 1780 for wordsFracTo > wordsFrac1 { 1781 wordsFracTo-- 1782 idxTo-- 1783 to.wordBuf[idxTo] = 0 1784 } 1785 for idx1 > stop1 { 1786 idxTo-- 1787 idx1-- 1788 to.wordBuf[idxTo] = from1.wordBuf[idx1] 1789 } 1790 } else { 1791 idx1 = start1 + wordsInt1 + wordsFrac1 1792 idx2 = start2 + wordsInt2 + wordsFrac2 1793 stop2 = start2 + wordsInt2 + wordsFrac1 1794 for wordsFracTo > wordsFrac2 { 1795 wordsFracTo-- 1796 idxTo-- 1797 to.wordBuf[idxTo] = 0 1798 } 1799 for idx2 > stop2 { 1800 idxTo-- 1801 idx2-- 1802 to.wordBuf[idxTo], carry = sub(0, from2.wordBuf[idx2], carry) 1803 } 1804 } 1805 1806 /* part 2 - min(frac) ... wordsInt2 */ 1807 for idx2 > start2 { 1808 idxTo-- 1809 idx1-- 1810 idx2-- 1811 to.wordBuf[idxTo], carry = sub(from1.wordBuf[idx1], from2.wordBuf[idx2], carry) 1812 } 1813 1814 /* part 3 - wordsInt2 ... wordsInt1 */ 1815 for carry > 0 && idx1 > start1 { 1816 idxTo-- 1817 idx1-- 1818 to.wordBuf[idxTo], carry = sub(from1.wordBuf[idx1], 0, carry) 1819 } 1820 for idx1 > start1 { 1821 idxTo-- 1822 idx1-- 1823 to.wordBuf[idxTo] = from1.wordBuf[idx1] 1824 } 1825 for idxTo > 0 { 1826 idxTo-- 1827 to.wordBuf[idxTo] = 0 1828 } 1829 return 0, err 1830 } 1831 1832 func doAdd(from1, from2, to *Decimal) error { 1833 var ( 1834 err error 1835 wordsInt1 = digitsToWords(int(from1.digitsInt)) 1836 wordsFrac1 = digitsToWords(int(from1.digitsFrac)) 1837 wordsInt2 = digitsToWords(int(from2.digitsInt)) 1838 wordsFrac2 = digitsToWords(int(from2.digitsFrac)) 1839 wordsIntTo = myMax(wordsInt1, wordsInt2) 1840 wordsFracTo = myMax(wordsFrac1, wordsFrac2) 1841 ) 1842 1843 var x int32 1844 if wordsInt1 > wordsInt2 { 1845 x = from1.wordBuf[0] 1846 } else if wordsInt2 > wordsInt1 { 1847 x = from2.wordBuf[0] 1848 } else { 1849 x = from1.wordBuf[0] + from2.wordBuf[0] 1850 } 1851 if x > wordMax-1 { /* yes, there is */ 1852 wordsIntTo++ 1853 to.wordBuf[0] = 0 /* safety */ 1854 } 1855 1856 wordsIntTo, wordsFracTo, err = fixWordCntError(wordsIntTo, wordsFracTo) 1857 if err == ErrOverflow { 1858 maxDecimal(wordBufLen*digitsPerWord, 0, to) 1859 return err 1860 } 1861 idxTo := wordsIntTo + wordsFracTo 1862 to.negative = from1.negative 1863 to.digitsInt = int8(wordsIntTo * digitsPerWord) 1864 to.digitsFrac = myMaxInt8(from1.digitsFrac, from2.digitsFrac) 1865 1866 if err != nil { 1867 if to.digitsFrac > int8(wordsFracTo*digitsPerWord) { 1868 to.digitsFrac = int8(wordsFracTo * digitsPerWord) 1869 } 1870 if wordsFrac1 > wordsFracTo { 1871 wordsFrac1 = wordsFracTo 1872 } 1873 if wordsFrac2 > wordsFracTo { 1874 wordsFrac2 = wordsFracTo 1875 } 1876 if wordsInt1 > wordsIntTo { 1877 wordsInt1 = wordsIntTo 1878 } 1879 if wordsInt2 > wordsIntTo { 1880 wordsInt2 = wordsIntTo 1881 } 1882 } 1883 dec1, dec2 := from1, from2 1884 var idx1, idx2, stop, stop2 int 1885 /* part 1 - max(frac) ... min (frac) */ 1886 if wordsFrac1 > wordsFrac2 { 1887 idx1 = wordsInt1 + wordsFrac1 1888 stop = wordsInt1 + wordsFrac2 1889 idx2 = wordsInt2 + wordsFrac2 1890 if wordsInt1 > wordsInt2 { 1891 stop2 = wordsInt1 - wordsInt2 1892 } 1893 } else { 1894 idx1 = wordsInt2 + wordsFrac2 1895 stop = wordsInt2 + wordsFrac1 1896 idx2 = wordsInt1 + wordsFrac1 1897 if wordsInt2 > wordsInt1 { 1898 stop2 = wordsInt2 - wordsInt1 1899 } 1900 dec1, dec2 = from2, from1 1901 } 1902 for idx1 > stop { 1903 idxTo-- 1904 idx1-- 1905 to.wordBuf[idxTo] = dec1.wordBuf[idx1] 1906 } 1907 1908 /* part 2 - min(frac) ... min(digitsInt) */ 1909 carry := int32(0) 1910 for idx1 > stop2 { 1911 idx1-- 1912 idx2-- 1913 idxTo-- 1914 to.wordBuf[idxTo], carry = add(dec1.wordBuf[idx1], dec2.wordBuf[idx2], carry) 1915 } 1916 1917 /* part 3 - min(digitsInt) ... max(digitsInt) */ 1918 stop = 0 1919 if wordsInt1 > wordsInt2 { 1920 idx1 = wordsInt1 - wordsInt2 1921 dec1 = from1 1922 } else { 1923 idx1 = wordsInt2 - wordsInt1 1924 dec1 = from2 1925 } 1926 for idx1 > stop { 1927 idxTo-- 1928 idx1-- 1929 to.wordBuf[idxTo], carry = add(dec1.wordBuf[idx1], 0, carry) 1930 } 1931 if carry > 0 { 1932 idxTo-- 1933 to.wordBuf[idxTo] = 1 1934 } 1935 return err 1936 } 1937 1938 func maxDecimal(precision, frac int, to *Decimal) { 1939 digitsInt := precision - frac 1940 to.negative = false 1941 to.digitsInt = int8(digitsInt) 1942 idx := 0 1943 if digitsInt > 0 { 1944 firstWordDigits := digitsInt % digitsPerWord 1945 if firstWordDigits > 0 { 1946 to.wordBuf[idx] = powers10[firstWordDigits] - 1 /* get 9 99 999 ... */ 1947 idx++ 1948 } 1949 for digitsInt /= digitsPerWord; digitsInt > 0; digitsInt-- { 1950 to.wordBuf[idx] = wordMax 1951 idx++ 1952 } 1953 } 1954 to.digitsFrac = int8(frac) 1955 if frac > 0 { 1956 lastDigits := frac % digitsPerWord 1957 for frac /= digitsPerWord; frac > 0; frac-- { 1958 to.wordBuf[idx] = wordMax 1959 idx++ 1960 } 1961 if lastDigits > 0 { 1962 to.wordBuf[idx] = fracMax[lastDigits-1] 1963 } 1964 } 1965 } 1966 1967 /* 1968 DecimalMul multiplies two decimals. 1969 1970 from1, from2 - factors 1971 to - product 1972 1973 RETURN VALUE 1974 E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW; 1975 1976 NOTES 1977 in this implementation, with wordSize=4 we have digitsPerWord=9, 1978 and 63-digit number will take only 7 words (basically a 7-digit 1979 "base 999999999" number). Thus there's no need in fast multiplication 1980 algorithms, 7-digit numbers can be multiplied with a naive O(n*n) 1981 method. 1982 1983 XXX if this library is to be used with huge numbers of thousands of 1984 digits, fast multiplication must be implemented. 1985 */ 1986 func DecimalMul(from1, from2, to *Decimal) error { 1987 from1, from2, to = validateArgs(from1, from2, to) 1988 var ( 1989 err error 1990 wordsInt1 = digitsToWords(int(from1.digitsInt)) 1991 wordsFrac1 = digitsToWords(int(from1.digitsFrac)) 1992 wordsInt2 = digitsToWords(int(from2.digitsInt)) 1993 wordsFrac2 = digitsToWords(int(from2.digitsFrac)) 1994 wordsIntTo = digitsToWords(int(from1.digitsInt) + int(from2.digitsInt)) 1995 wordsFracTo = wordsFrac1 + wordsFrac2 1996 idx1 = wordsInt1 1997 idx2 = wordsInt2 1998 idxTo int 1999 tmp1 = wordsIntTo 2000 tmp2 = wordsFracTo 2001 ) 2002 // to.resultFrac = myMinInt8(from1.resultFrac+from2.resultFrac, maxDecimalScale) 2003 to.resultFrac = myMinInt8(from1.resultFrac+from2.resultFrac, int8(30)) 2004 wordsIntTo, wordsFracTo, err = fixWordCntError(wordsIntTo, wordsFracTo) 2005 to.negative = from1.negative != from2.negative 2006 to.digitsFrac = from1.digitsFrac + from2.digitsFrac 2007 if to.digitsFrac > notFixedDec { 2008 to.digitsFrac = notFixedDec 2009 } 2010 to.digitsInt = int8(wordsIntTo * digitsPerWord) 2011 if err == ErrOverflow { 2012 return err 2013 } 2014 if err != nil { 2015 if to.digitsFrac > int8(wordsFracTo*digitsPerWord) { 2016 to.digitsFrac = int8(wordsFracTo * digitsPerWord) 2017 } 2018 if to.digitsInt > int8(wordsIntTo*digitsPerWord) { 2019 to.digitsInt = int8(wordsIntTo * digitsPerWord) 2020 } 2021 if tmp1 > wordsIntTo { 2022 tmp1 -= wordsIntTo 2023 tmp2 = tmp1 >> 1 2024 wordsInt2 -= tmp1 - tmp2 2025 wordsFrac1 = 0 2026 wordsFrac2 = 0 2027 } else { 2028 tmp2 -= wordsFracTo 2029 tmp1 = tmp2 >> 1 2030 if wordsFrac1 <= wordsFrac2 { 2031 wordsFrac1 -= tmp1 2032 wordsFrac2 -= tmp2 - tmp1 2033 } else { 2034 wordsFrac2 -= tmp1 2035 wordsFrac1 -= tmp2 - tmp1 2036 } 2037 } 2038 } 2039 startTo := wordsIntTo + wordsFracTo - 1 2040 start2 := idx2 + wordsFrac2 - 1 2041 stop1 := idx1 - wordsInt1 2042 stop2 := idx2 - wordsInt2 2043 to.wordBuf = zeroBigDecimal.wordBuf 2044 2045 for idx1 += wordsFrac1 - 1; idx1 >= stop1; idx1-- { 2046 carry := int32(0) 2047 idxTo = startTo 2048 idx2 = start2 2049 for idx2 >= stop2 { 2050 var hi, lo int32 2051 p := int64(from1.wordBuf[idx1]) * int64(from2.wordBuf[idx2]) 2052 hi = int32(p / wordBase) 2053 lo = int32(p - int64(hi)*wordBase) 2054 to.wordBuf[idxTo], carry = add2(to.wordBuf[idxTo], lo, carry) 2055 carry += hi 2056 idx2-- 2057 idxTo-- 2058 } 2059 if carry > 0 { 2060 if idxTo < 0 { 2061 return ErrOverflow 2062 } 2063 to.wordBuf[idxTo], carry = add2(to.wordBuf[idxTo], 0, carry) 2064 } 2065 for idxTo--; carry > 0; idxTo-- { 2066 if idxTo < 0 { 2067 return ErrOverflow 2068 } 2069 to.wordBuf[idxTo], carry = add(to.wordBuf[idxTo], 0, carry) 2070 } 2071 startTo-- 2072 } 2073 2074 /* Now we have to check for -0.000 case */ 2075 if to.negative { 2076 idx := 0 2077 end := wordsIntTo + wordsFracTo 2078 for { 2079 if to.wordBuf[idx] != 0 { 2080 break 2081 } 2082 idx++ 2083 /* We got decimal zero */ 2084 if idx == end { 2085 *to = zeroMyDecimalWithFrac(to.resultFrac) 2086 break 2087 } 2088 } 2089 } 2090 2091 idxTo = 0 2092 dToMove := wordsIntTo + digitsToWords(int(to.digitsFrac)) 2093 for to.wordBuf[idxTo] == 0 && to.digitsInt > digitsPerWord { 2094 idxTo++ 2095 to.digitsInt -= digitsPerWord 2096 dToMove-- 2097 } 2098 if idxTo > 0 { 2099 curIdx := 0 2100 for dToMove > 0 { 2101 to.wordBuf[curIdx] = to.wordBuf[idxTo] 2102 curIdx++ 2103 idxTo++ 2104 dToMove-- 2105 } 2106 } 2107 return err 2108 } 2109 2110 // DecimalDiv does division of two decimals. 2111 // 2112 // from1 - dividend 2113 // from2 - divisor 2114 // to - quotient 2115 // fracIncr - increment of fraction 2116 func DecimalDiv(from1, from2, to *Decimal, fracIncr int) error { 2117 from1, from2, to = validateArgs(from1, from2, to) 2118 // to.resultFrac = myMinInt8(from1.resultFrac+int8(fracIncr), int8(maxDecimalScale)) 2119 to.resultFrac = myMinInt8(from1.resultFrac+int8(fracIncr), int8(30)) 2120 return doDivMod(from1, from2, to, nil, fracIncr) 2121 } 2122 2123 /* 2124 DecimalMod does modulus of two decimals. 2125 2126 from1 - dividend 2127 from2 - divisor 2128 to - modulus 2129 2130 RETURN VALUE 2131 E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO; 2132 2133 NOTES 2134 see do_div_mod() 2135 2136 DESCRIPTION 2137 the modulus R in R = M mod N 2138 2139 is defined as 2140 2141 0 <= |R| < |M| 2142 sign R == sign M 2143 R = M - k*N, where k is integer 2144 2145 thus, there's no requirement for M or N to be integers 2146 */ 2147 func DecimalMod(from1, from2, to *Decimal) error { 2148 from1, from2, to = validateArgs(from1, from2, to) 2149 to.resultFrac = myMaxInt8(from1.resultFrac, from2.resultFrac) 2150 return doDivMod(from1, from2, nil, to, 0) 2151 } 2152 2153 func doDivMod(from1, from2, to, mod *Decimal, fracIncr int) error { 2154 var ( 2155 frac1 = digitsToWords(int(from1.digitsFrac)) * digitsPerWord 2156 prec1 = int(from1.digitsInt) + frac1 2157 frac2 = digitsToWords(int(from2.digitsFrac)) * digitsPerWord 2158 prec2 = int(from2.digitsInt) + frac2 2159 ) 2160 if mod != nil { 2161 to = mod 2162 } 2163 2164 /* removing all the leading zeros */ 2165 i := ((prec2 - 1) % digitsPerWord) + 1 2166 idx2 := 0 2167 for prec2 > 0 && from2.wordBuf[idx2] == 0 { 2168 prec2 -= i 2169 i = digitsPerWord 2170 idx2++ 2171 } 2172 if prec2 <= 0 { 2173 /* short-circuit everything: from2 == 0 */ 2174 return ErrDivByZero 2175 } 2176 2177 prec2 -= countLeadingZeroes((prec2-1)%digitsPerWord, from2.wordBuf[idx2]) 2178 i = ((prec1 - 1) % digitsPerWord) + 1 2179 idx1 := 0 2180 for prec1 > 0 && from1.wordBuf[idx1] == 0 { 2181 prec1 -= i 2182 i = digitsPerWord 2183 idx1++ 2184 } 2185 if prec1 <= 0 { 2186 /* short-circuit everything: from1 == 0 */ 2187 *to = zeroMyDecimalWithFrac(to.resultFrac) 2188 return nil 2189 } 2190 prec1 -= countLeadingZeroes((prec1-1)%digitsPerWord, from1.wordBuf[idx1]) 2191 2192 /* let's fix fracIncr, taking into account frac1,frac2 increase */ 2193 fracIncr -= frac1 - int(from1.digitsFrac) + frac2 - int(from2.digitsFrac) 2194 if fracIncr < 0 { 2195 fracIncr = 0 2196 } 2197 2198 digitsIntTo := (prec1 - frac1) - (prec2 - frac2) 2199 if from1.wordBuf[idx1] >= from2.wordBuf[idx2] { 2200 digitsIntTo++ 2201 } 2202 var wordsIntTo int 2203 if digitsIntTo < 0 { 2204 digitsIntTo /= digitsPerWord 2205 wordsIntTo = 0 2206 } else { 2207 wordsIntTo = digitsToWords(digitsIntTo) 2208 } 2209 var wordsFracTo int 2210 var err error 2211 if mod != nil { 2212 // we're calculating N1 % N2. 2213 // The result will have 2214 // digitsFrac=max(frac1, frac2), as for subtraction 2215 // digitsInt=from2.digitsInt 2216 to.negative = from1.negative 2217 to.digitsFrac = myMaxInt8(from1.digitsFrac, from2.digitsFrac) 2218 } else { 2219 wordsFracTo = digitsToWords(frac1 + frac2 + fracIncr) 2220 wordsIntTo, wordsFracTo, err = fixWordCntError(wordsIntTo, wordsFracTo) 2221 to.negative = from1.negative != from2.negative 2222 to.digitsInt = int8(wordsIntTo * digitsPerWord) 2223 to.digitsFrac = int8(wordsFracTo * digitsPerWord) 2224 } 2225 idxTo := 0 2226 stopTo := wordsIntTo + wordsFracTo 2227 if mod == nil { 2228 for digitsIntTo < 0 && idxTo < wordBufLen { 2229 to.wordBuf[idxTo] = 0 2230 idxTo++ 2231 digitsIntTo++ 2232 } 2233 } 2234 i = digitsToWords(prec1) 2235 len1 := i + digitsToWords(2*frac2+fracIncr+1) + 1 2236 if len1 < 3 { 2237 len1 = 3 2238 } 2239 2240 tmp1 := make([]int32, len1) 2241 copy(tmp1, from1.wordBuf[idx1:idx1+i]) 2242 2243 start1 := 0 2244 var stop1 int 2245 start2 := idx2 2246 stop2 := idx2 + digitsToWords(prec2) - 1 2247 2248 /* removing end zeroes */ 2249 for from2.wordBuf[stop2] == 0 && stop2 >= start2 { 2250 stop2-- 2251 } 2252 len2 := stop2 - start2 2253 stop2++ 2254 2255 /* 2256 calculating norm2 (normalized from2.wordBuf[start2]) - we need from2.wordBuf[start2] to be large 2257 (at least > DIG_BASE/2), but unlike Knuth's Alg. D we don't want to 2258 normalize input numbers (as we don't make a copy of the divisor). 2259 Thus we normalize first dec1 of buf2 only, and we'll normalize tmp1[start1] 2260 on the fly for the purpose of guesstimation only. 2261 It's also faster, as we're saving on normalization of from2. 2262 */ 2263 normFactor := wordBase / int64(from2.wordBuf[start2]+1) 2264 norm2 := int32(normFactor * int64(from2.wordBuf[start2])) 2265 if len2 > 0 { 2266 norm2 += int32(normFactor * int64(from2.wordBuf[start2+1]) / wordBase) 2267 } 2268 dcarry := int32(0) 2269 if tmp1[start1] < from2.wordBuf[start2] { 2270 dcarry = tmp1[start1] 2271 start1++ 2272 } 2273 2274 // main loop 2275 var guess int64 2276 for ; idxTo < stopTo; idxTo++ { 2277 /* short-circuit, if possible */ 2278 if dcarry == 0 && tmp1[start1] < from2.wordBuf[start2] { 2279 guess = 0 2280 } else { 2281 /* D3: make a guess */ 2282 x := int64(tmp1[start1]) + int64(dcarry)*wordBase 2283 y := int64(tmp1[start1+1]) 2284 guess = (normFactor*x + normFactor*y/wordBase) / int64(norm2) 2285 if guess >= wordBase { 2286 guess = wordBase - 1 2287 } 2288 2289 if len2 > 0 { 2290 /* remove normalization */ 2291 if int64(from2.wordBuf[start2+1])*guess > (x-guess*int64(from2.wordBuf[start2]))*wordBase+y { 2292 guess-- 2293 } 2294 if int64(from2.wordBuf[start2+1])*guess > (x-guess*int64(from2.wordBuf[start2]))*wordBase+y { 2295 guess-- 2296 } 2297 } 2298 2299 /* D4: multiply and subtract */ 2300 idx2 = stop2 2301 idx1 = start1 + len2 2302 var carry int32 2303 for carry = 0; idx2 > start2; idx1-- { 2304 var hi, lo int32 2305 idx2-- 2306 x = guess * int64(from2.wordBuf[idx2]) 2307 hi = int32(x / wordBase) 2308 lo = int32(x - int64(hi)*wordBase) 2309 tmp1[idx1], carry = sub2(tmp1[idx1], lo, carry) 2310 carry += hi 2311 } 2312 if dcarry < carry { 2313 carry = 1 2314 } else { 2315 carry = 0 2316 } 2317 2318 /* D5: check the remainder */ 2319 if carry > 0 { 2320 /* D6: correct the guess */ 2321 guess-- 2322 idx2 = stop2 2323 idx1 = start1 + len2 2324 for carry = 0; idx2 > start2; idx1-- { 2325 idx2-- 2326 tmp1[idx1], carry = add(tmp1[idx1], from2.wordBuf[idx2], carry) 2327 } 2328 } 2329 } 2330 if mod == nil { 2331 to.wordBuf[idxTo] = int32(guess) 2332 } 2333 dcarry = tmp1[start1] 2334 start1++ 2335 } 2336 if mod != nil { 2337 /* 2338 now the result is in tmp1, it has 2339 digitsInt=prec1-frac1 2340 digitsFrac=max(frac1, frac2) 2341 */ 2342 if dcarry != 0 { 2343 start1-- 2344 tmp1[start1] = dcarry 2345 } 2346 idxTo = 0 2347 2348 digitsIntTo = prec1 - frac1 - start1*digitsPerWord 2349 if digitsIntTo < 0 { 2350 /* If leading zeroes in the fractional part were earlier stripped */ 2351 wordsIntTo = digitsIntTo / digitsPerWord 2352 } else { 2353 wordsIntTo = digitsToWords(digitsIntTo) 2354 } 2355 2356 wordsFracTo = digitsToWords(int(to.digitsFrac)) 2357 err = nil 2358 if wordsIntTo == 0 && wordsFracTo == 0 { 2359 *to = zeroBigDecimal 2360 return err 2361 } 2362 if wordsIntTo <= 0 { 2363 if -wordsIntTo >= wordBufLen { 2364 *to = zeroBigDecimal 2365 return ErrTruncated 2366 } 2367 stop1 = start1 + wordsIntTo + wordsFracTo 2368 wordsFracTo += wordsIntTo 2369 to.digitsInt = 0 2370 for wordsIntTo < 0 { 2371 to.wordBuf[idxTo] = 0 2372 idxTo++ 2373 wordsIntTo++ 2374 } 2375 } else { 2376 if wordsIntTo > wordBufLen { 2377 to.digitsInt = int8(digitsPerWord * wordBufLen) 2378 to.digitsFrac = 0 2379 return ErrOverflow 2380 } 2381 stop1 = start1 + wordsIntTo + wordsFracTo 2382 to.digitsInt = int8(myMin(wordsIntTo*digitsPerWord, int(from2.digitsInt))) 2383 } 2384 if wordsIntTo+wordsFracTo > wordBufLen { 2385 stop1 -= wordsIntTo + wordsFracTo - wordBufLen 2386 wordsFracTo = wordBufLen - wordsIntTo 2387 to.digitsFrac = int8(wordsFracTo * digitsPerWord) 2388 err = ErrTruncated 2389 } 2390 for start1 < stop1 { 2391 to.wordBuf[idxTo] = tmp1[start1] 2392 idxTo++ 2393 start1++ 2394 } 2395 } 2396 idxTo, digitsIntTo = to.removeLeadingZeros() 2397 to.digitsInt = int8(digitsIntTo) 2398 if idxTo != 0 { 2399 copy(to.wordBuf[:], to.wordBuf[idxTo:]) 2400 } 2401 2402 if to.IsZero() { 2403 to.negative = false 2404 } 2405 return err 2406 } 2407 2408 // DecimalPeak returns the length of the encoded decimal. 2409 func DecimalPeak(b []byte) (int, error) { 2410 if len(b) < 3 { 2411 return 0, ErrBadNumber 2412 } 2413 precision := int(b[0]) 2414 frac := int(b[1]) 2415 binSize, err := DecimalBinSize(precision, frac) 2416 if err != nil { 2417 return 0, err 2418 } 2419 return binSize + 2, nil 2420 } 2421 2422 // NewDecFromInt creates a Decimal from int. 2423 func NewDecFromInt(i int64) *Decimal { 2424 return new(Decimal).FromInt(i) 2425 } 2426 2427 // NewDecFromUint creates a Decimal from uint. 2428 func NewDecFromUint(i uint64) *Decimal { 2429 return new(Decimal).FromUint(i) 2430 } 2431 2432 // NewDecFromFloat creates a Decimal from float. 2433 func NewDecFromFloat(f float64) (*Decimal, error) { 2434 dec := new(Decimal) 2435 err := dec.FromFloat64(f) 2436 return dec, err 2437 } 2438 2439 // NewDecFromString creates a Decimal from string 2440 func NewDecFromString(s string) (*Decimal, error) { 2441 dec := new(Decimal) 2442 err := dec.FromString(s) 2443 return dec, err 2444 } 2445 2446 // NewMaxOrMinDec returns the max or min value decimal for given precision and fraction. 2447 func NewMaxOrMinDec(negative bool, prec, frac int) *Decimal { 2448 str := make([]byte, prec+2) 2449 for i := 0; i < len(str); i++ { 2450 str[i] = '9' 2451 } 2452 if negative { 2453 str[0] = '-' 2454 } else { 2455 str[0] = '+' 2456 } 2457 str[1+prec-frac] = '.' 2458 dec := new(Decimal) 2459 err := dec.FromBytes(str) 2460 if err != nil { 2461 log.Printf("newMaxOrMinDec client = error{%v}", err) 2462 } 2463 return dec 2464 }