protected int round()

in commons-math-legacy-core/src/main/java/org/apache/commons/math4/legacy/core/dfp/DfpDec.java [163:287]


    protected int round(int in) {

        int msb = mant[mant.length - 1];
        if (msb == 0) {
            // special case -- this == zero
            return 0;
        }

        int cmaxdigits = mant.length * 4;
        int lsbthreshold = 1000;
        while (lsbthreshold > msb) {
            lsbthreshold /= 10;
            cmaxdigits--;
        }


        final int digits = getDecimalDigits();
        final int lsbshift = cmaxdigits - digits;
        final int lsd = lsbshift / 4;

        lsbthreshold = 1;
        for (int i = 0; i < lsbshift % 4; i++) {
            lsbthreshold *= 10;
        }

        final int lsb = mant[lsd];

        if (lsbthreshold <= 1 && digits == 4 * mant.length - 3) {
            return super.round(in);
        }

        int discarded = in;  // not looking at this after this point
        final int n;
        if (lsbthreshold == 1) {
            // look to the next digit for rounding
            n = (mant[lsd - 1] / 1000) % 10;
            mant[lsd - 1] %= 1000;
            discarded |= mant[lsd - 1];
        } else {
            n = (lsb * 10 / lsbthreshold) % 10;
            discarded |= lsb % (lsbthreshold / 10);
        }

        for (int i = 0; i < lsd; i++) {
            discarded |= mant[i];    // need to know if there are any discarded bits
            mant[i] = 0;
        }

        mant[lsd] = lsb / lsbthreshold * lsbthreshold;

        final boolean inc;
        switch (getField().getRoundingMode()) {
        case ROUND_DOWN:
            inc = false;
            break;

        case ROUND_UP:
            inc = (n != 0) || (discarded != 0); // round up if n!=0
            break;

        case ROUND_HALF_UP:
            inc = n >= 5;  // round half up
            break;

        case ROUND_HALF_DOWN:
            inc = n > 5;  // round half down
            break;

        case ROUND_HALF_EVEN:
            inc = (n > 5) ||
                  (n == 5 && discarded != 0) ||
                  (n == 5 && discarded == 0 && ((lsb / lsbthreshold) & 1) == 1);  // round half-even
            break;

        case ROUND_HALF_ODD:
            inc = (n > 5) ||
                  (n == 5 && discarded != 0) ||
                  (n == 5 && discarded == 0 && ((lsb / lsbthreshold) & 1) == 0);  // round half-odd
            break;

        case ROUND_CEIL:
            inc = (sign == 1) && (n != 0 || discarded != 0);  // round ceil
            break;

        case ROUND_FLOOR:
        default:
            inc = (sign == -1) && (n != 0 || discarded != 0);  // round floor
            break;
        }

        if (inc) {
            // increment if necessary
            int rh = lsbthreshold;
            for (int i = lsd; i < mant.length; i++) {
                final int r = mant[i] + rh;
                rh = r / RADIX;
                mant[i] = r % RADIX;
            }

            if (rh != 0) {
                shiftRight();
                mant[mant.length - 1] = rh;
            }
        }

        // Check for exceptional cases and raise signals if necessary
        if (exp < MIN_EXP) {
            // Gradual Underflow
            getField().setIEEEFlagsBits(DfpField.FLAG_UNDERFLOW);
            return DfpField.FLAG_UNDERFLOW;
        }

        if (exp > MAX_EXP) {
            // Overflow
            getField().setIEEEFlagsBits(DfpField.FLAG_OVERFLOW);
            return DfpField.FLAG_OVERFLOW;
        }

        if (n != 0 || discarded != 0) {
            // Inexact
            getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT);
            return DfpField.FLAG_INEXACT;
        }
        return 0;
    }