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;
}