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