| 585 | */ |
| 586 | |
| 587 | int decimal_shift(decimal_t *dec, int shift) |
| 588 | { |
| 589 | /* index of first non zero digit (all indexes from 0) */ |
| 590 | int beg; |
| 591 | /* index of position after last decimal digit */ |
| 592 | int end; |
| 593 | /* index of digit position just after point */ |
| 594 | int point= ROUND_UP(dec->intg) * DIG_PER_DEC1; |
| 595 | /* new point position */ |
| 596 | int new_point= point + shift; |
| 597 | /* number of digits in result */ |
| 598 | int digits_int, digits_frac; |
| 599 | /* length of result and new fraction in big digits*/ |
| 600 | int new_len, new_frac_len; |
| 601 | /* return code */ |
| 602 | int err= E_DEC_OK; |
| 603 | int new_front; |
| 604 | |
| 605 | if (shift == 0) |
| 606 | return E_DEC_OK; |
| 607 | |
| 608 | digits_bounds(dec, &beg, &end); |
| 609 | |
| 610 | if (beg == end) |
| 611 | { |
| 612 | decimal_make_zero(dec); |
| 613 | return E_DEC_OK; |
| 614 | } |
| 615 | |
| 616 | digits_int= new_point - beg; |
| 617 | set_if_bigger(digits_int, 0); |
| 618 | digits_frac= end - new_point; |
| 619 | set_if_bigger(digits_frac, 0); |
| 620 | |
| 621 | if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) > |
| 622 | dec->len) |
| 623 | { |
| 624 | int lack= new_len - dec->len; |
| 625 | int diff; |
| 626 | |
| 627 | if (new_frac_len < lack) |
| 628 | return E_DEC_OVERFLOW; /* lack more then we have in fraction */ |
| 629 | |
| 630 | /* cat off fraction part to allow new number to fit in our buffer */ |
| 631 | err= E_DEC_TRUNCATED; |
| 632 | new_frac_len-= lack; |
| 633 | diff= digits_frac - (new_frac_len * DIG_PER_DEC1); |
| 634 | /* Make rounding method as parameter? */ |
| 635 | decimal_round(dec, dec, end - point - diff, HALF_UP); |
| 636 | end-= diff; |
| 637 | digits_frac= new_frac_len * DIG_PER_DEC1; |
| 638 | |
| 639 | if (end <= beg) |
| 640 | { |
| 641 | /* |
| 642 | we lost all digits (they will be shifted out of buffer), so we can |
| 643 | just return 0 |
| 644 | */ |
no test coverage detected