------------------------------------------------------------------ */ decTrim -- trim trailing zeros or normalize */ / dn is the number to trim or normalize */ set is the context to use to check for clamp */ all is 1 to remove all trailing zeros, 0 for just fraction ones */ noclamp is 1 to unconditional (unclamped) trim
| 6587 | /* so special values are unchanged and no error is possible. */ |
| 6588 | /* ------------------------------------------------------------------ */ |
| 6589 | static decNumber * decTrim(decNumber *dn, decContext *set, Flag all, |
| 6590 | Flag noclamp, Int *dropped) { |
| 6591 | Int d, exp; // work |
| 6592 | uInt cut; // .. |
| 6593 | Unit *up; // -> current Unit |
| 6594 | |
| 6595 | #if DECCHECK |
| 6596 | if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn; |
| 6597 | #endif |
| 6598 | |
| 6599 | *dropped=0; // assume no zeros dropped |
| 6600 | if ((dn->bits & DECSPECIAL) // fast exit if special .. |
| 6601 | || (*dn->lsu & 0x01)) return dn; // .. or odd |
| 6602 | if (ISZERO(dn)) { // .. or 0 |
| 6603 | dn->exponent=0; // (sign is preserved) |
| 6604 | return dn; |
| 6605 | } |
| 6606 | |
| 6607 | // have a finite number which is even |
| 6608 | exp=dn->exponent; |
| 6609 | cut=1; // digit (1-DECDPUN) in Unit |
| 6610 | up=dn->lsu; // -> current Unit |
| 6611 | for (d=0; d<dn->digits-1; d++) { // [don't strip the final digit] |
| 6612 | // slice by powers |
| 6613 | #if DECDPUN<=4 |
| 6614 | uInt quot=QUOT10(*up, cut); |
| 6615 | if ((*up-quot*powers[cut])!=0) break; // found non-0 digit |
| 6616 | #else |
| 6617 | if (*up%powers[cut]!=0) break; // found non-0 digit |
| 6618 | #endif |
| 6619 | // have a trailing 0 |
| 6620 | if (!all) { // trimming |
| 6621 | // [if exp>0 then all trailing 0s are significant for trim] |
| 6622 | if (exp<=0) { // if digit might be significant |
| 6623 | if (exp==0) break; // then quit |
| 6624 | exp++; // next digit might be significant |
| 6625 | } |
| 6626 | } |
| 6627 | cut++; // next power |
| 6628 | if (cut>DECDPUN) { // need new Unit |
| 6629 | up++; |
| 6630 | cut=1; |
| 6631 | } |
| 6632 | } // d |
| 6633 | if (d==0) return dn; // none to drop |
| 6634 | |
| 6635 | // may need to limit drop if clamping |
| 6636 | if (set->clamp && !noclamp) { |
| 6637 | Int maxd=set->emax-set->digits+1-dn->exponent; |
| 6638 | if (maxd<=0) return dn; // nothing possible |
| 6639 | if (d>maxd) d=maxd; |
| 6640 | } |
| 6641 | |
| 6642 | // effect the drop |
| 6643 | decShiftToLeast(dn->lsu, D2U(dn->digits), d); |
| 6644 | dn->exponent+=d; // maintain numerical value |
| 6645 | dn->digits-=d; // new length |
| 6646 | *dropped=d; // report the count |
no test coverage detected