DfpDec extends Dfp { @Override protected int round(int in) { int msb = mant[mant.length-1]; if (msb == 0) { 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; final int n; if (lsbthreshold == 1) { 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]; 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); break; case ROUND_HALF_UP: inc = n >= 5; break; case ROUND_HALF_DOWN: inc = n > 5; break; case ROUND_HALF_EVEN: inc = (n > 5) || (n == 5 && discarded != 0) || (n == 5 && discarded == 0 && ((lsb / lsbthreshold) & 1) == 1); break; case ROUND_HALF_ODD: inc = (n > 5) || (n == 5 && discarded != 0) || (n == 5 && discarded == 0 && ((lsb / lsbthreshold) & 1) == 0); break; case ROUND_CEIL: inc = (sign == 1) && (n != 0 || discarded != 0); break; case ROUND_FLOOR: default: inc = (sign == -1) && (n != 0 || discarded != 0); break; } if (inc) { 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; } } if (exp < MIN_EXP) { getField().setIEEEFlagsBits(DfpField.FLAG_UNDERFLOW); return DfpField.FLAG_UNDERFLOW; } if (exp > MAX_EXP) { getField().setIEEEFlagsBits(DfpField.FLAG_OVERFLOW); return DfpField.FLAG_OVERFLOW; } if (n != 0 || discarded != 0) { getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT); return DfpField.FLAG_INEXACT; } return 0; } protected  DfpDec(final DfpField factory); protected  DfpDec(final DfpField factory, byte x); protected  DfpDec(final DfpField factory, int x); protected  DfpDec(final DfpField factory, long x); protected  DfpDec(final DfpField factory, double x);  DfpDec(final Dfp d); protected  DfpDec(final DfpField factory, final String s); protected  DfpDec(final DfpField factory, final byte sign, final byte nans); @Override Dfp newInstance(); @Override Dfp newInstance(final byte x); @Override Dfp newInstance(final int x); @Override Dfp newInstance(final long x); @Override Dfp newInstance(final double x); @Override Dfp newInstance(final Dfp d); @Override Dfp newInstance(final String s); @Override Dfp newInstance(final byte sign, final byte nans); @Override Dfp nextAfter(Dfp x);  }
@Test public void testRound() { field.setRoundingMode(DfpField.RoundingMode.ROUND_HALF_EVEN); test(new DfpDec(field, "12345678901234567890"), new DfpDec(field, "12345678901234568000"), DfpField.FLAG_INEXACT, "Round #1"); test(new DfpDec(field, "0.12345678901234567890"), new DfpDec(field, "0.12345678901234568"), DfpField.FLAG_INEXACT, "Round #2"); test(new DfpDec(field, "0.12345678901234567500"), new DfpDec(field, "0.12345678901234568"), DfpField.FLAG_INEXACT, "Round #3"); test(new DfpDec(field, "0.12345678901234568500"), new DfpDec(field, "0.12345678901234568"), DfpField.FLAG_INEXACT, "Round #4"); test(new DfpDec(field, "0.12345678901234568501"), new DfpDec(field, "0.12345678901234569"), DfpField.FLAG_INEXACT, "Round #5"); test(new DfpDec(field, "0.12345678901234568499"), new DfpDec(field, "0.12345678901234568"), DfpField.FLAG_INEXACT, "Round #6"); test(new DfpDec(field, "1.2345678901234567890"), new DfpDec(field, "1.2345678901234568"), DfpField.FLAG_INEXACT, "Round #7"); test(new DfpDec(field, "1.2345678901234567500"), new DfpDec(field, "1.2345678901234568"), DfpField.FLAG_INEXACT, "Round #8"); test(new DfpDec(field, "1.2345678901234568500"), new DfpDec(field, "1.2345678901234568"), DfpField.FLAG_INEXACT, "Round #9"); test(new DfpDec(field, "1.2345678901234568000").add(new DfpDec(field, ".0000000000000000501")), new DfpDec(field, "1.2345678901234569"), DfpField.FLAG_INEXACT, "Round #10"); test(new DfpDec(field, "1.2345678901234568499"), new DfpDec(field, "1.2345678901234568"), DfpField.FLAG_INEXACT, "Round #11"); test(new DfpDec(field, "12.345678901234567890"), new DfpDec(field, "12.345678901234568"), DfpField.FLAG_INEXACT, "Round #12"); test(new DfpDec(field, "12.345678901234567500"), new DfpDec(field, "12.345678901234568"), DfpField.FLAG_INEXACT, "Round #13"); test(new DfpDec(field, "12.345678901234568500"), new DfpDec(field, "12.345678901234568"), DfpField.FLAG_INEXACT, "Round #14"); test(new DfpDec(field, "12.345678901234568").add(new DfpDec(field, ".000000000000000501")), new DfpDec(field, "12.345678901234569"), DfpField.FLAG_INEXACT, "Round #15"); test(new DfpDec(field, "12.345678901234568499"), new DfpDec(field, "12.345678901234568"), DfpField.FLAG_INEXACT, "Round #16"); test(new DfpDec(field, "123.45678901234567890"), new DfpDec(field, "123.45678901234568"), DfpField.FLAG_INEXACT, "Round #17"); test(new DfpDec(field, "123.45678901234567500"), new DfpDec(field, "123.45678901234568"), DfpField.FLAG_INEXACT, "Round #18"); test(new DfpDec(field, "123.45678901234568500"), new DfpDec(field, "123.45678901234568"), DfpField.FLAG_INEXACT, "Round #19"); test(new DfpDec(field, "123.456789012345685").add(new DfpDec(field, ".00000000000000501")), new DfpDec(field, "123.45678901234569"), DfpField.FLAG_INEXACT, "Round #20"); test(new DfpDec(field, "123.45678901234568499"), new DfpDec(field, "123.45678901234568"), DfpField.FLAG_INEXACT, "Round #21"); field.setRoundingMode(DfpField.RoundingMode.ROUND_DOWN); test(new DfpDec(field, "12345678901234567").add(new DfpDec(field, "0.9")), new DfpDec(field, "12345678901234567"), DfpField.FLAG_INEXACT, "Round #22"); test(new DfpDec(field, "12345678901234567").add(new DfpDec(field, "0.99999999")), new DfpDec(field, "12345678901234567"), DfpField.FLAG_INEXACT, "Round #23"); test(new DfpDec(field, "-12345678901234567").add(new DfpDec(field, "-0.99999999")), new DfpDec(field, "-12345678901234567"), DfpField.FLAG_INEXACT, "Round #24"); field.setRoundingMode(DfpField.RoundingMode.ROUND_UP); test(new DfpDec(field, "12345678901234567").add(new DfpDec(field, "0.1")), new DfpDec(field, "12345678901234568"), DfpField.FLAG_INEXACT, "Round #25"); test(new DfpDec(field, "12345678901234567").add(new DfpDec(field, "0.0001")), new DfpDec(field, "12345678901234568"), DfpField.FLAG_INEXACT, "Round #26"); test(new DfpDec(field, "-12345678901234567").add(new DfpDec(field, "-0.1")), new DfpDec(field, "-12345678901234568"), DfpField.FLAG_INEXACT, "Round #27"); test(new DfpDec(field, "-12345678901234567").add(new DfpDec(field, "-0.0001")), new DfpDec(field, "-12345678901234568"), DfpField.FLAG_INEXACT, "Round #28"); test(new DfpDec(field, "-12345678901234567").add(new DfpDec(field, "0")), new DfpDec(field, "-12345678901234567"), 0, "Round #28.5"); field.setRoundingMode(DfpField.RoundingMode.ROUND_HALF_UP); test(new DfpDec(field, "12345678901234567").add(new DfpDec(field, "0.499999999999")), new DfpDec(field, "12345678901234567"), DfpField.FLAG_INEXACT, "Round #29"); test(new DfpDec(field, "12345678901234567").add(new DfpDec(field, "0.50000001")), new DfpDec(field, "12345678901234568"), DfpField.FLAG_INEXACT, "Round #30"); test(new DfpDec(field, "12345678901234567").add(new DfpDec(field, "0.5")), new DfpDec(field, "12345678901234568"), DfpField.FLAG_INEXACT, "Round #30.5"); test(new DfpDec(field, "-12345678901234567").add(new DfpDec(field, "-0.499999999999")), new DfpDec(field, "-12345678901234567"), DfpField.FLAG_INEXACT, "Round #31"); test(new DfpDec(field, "-12345678901234567").add(new DfpDec(field, "-0.50000001")), new DfpDec(field, "-12345678901234568"), DfpField.FLAG_INEXACT, "Round #32"); field.setRoundingMode(DfpField.RoundingMode.ROUND_HALF_DOWN); test(new DfpDec(field, "12345678901234567").add(new DfpDec(field, "0.5001")), new DfpDec(field, "12345678901234568"), DfpField.FLAG_INEXACT, "Round #33"); test(new DfpDec(field, "12345678901234567").add(new DfpDec(field, "0.5000")), new DfpDec(field, "12345678901234567"), DfpField.FLAG_INEXACT, "Round #34"); test(new DfpDec(field, "-12345678901234567").add(new DfpDec(field, "-0.5001")), new DfpDec(field, "-12345678901234568"), DfpField.FLAG_INEXACT, "Round #35"); test(new DfpDec(field, "-12345678901234567").add(new DfpDec(field, "-0.6")), new DfpDec(field, "-12345678901234568"), DfpField.FLAG_INEXACT, "Round #35.5"); test(new DfpDec(field, "-12345678901234567").add(new DfpDec(field, "-0.5000")), new DfpDec(field, "-12345678901234567"), DfpField.FLAG_INEXACT, "Round #36"); field.setRoundingMode(DfpField.RoundingMode.ROUND_HALF_ODD); test(new DfpDec(field, "12345678901234568").add(new DfpDec(field, "0.5000")), new DfpDec(field, "12345678901234569"), DfpField.FLAG_INEXACT, "Round #37"); test(new DfpDec(field, "12345678901234567").add(new DfpDec(field, "0.5000")), new DfpDec(field, "12345678901234567"), DfpField.FLAG_INEXACT, "Round #38"); test(new DfpDec(field, "-12345678901234568").add(new DfpDec(field, "-0.5000")), new DfpDec(field, "-12345678901234569"), DfpField.FLAG_INEXACT, "Round #39"); test(new DfpDec(field, "-12345678901234567").add(new DfpDec(field, "-0.5000")), new DfpDec(field, "-12345678901234567"), DfpField.FLAG_INEXACT, "Round #40"); field.setRoundingMode(DfpField.RoundingMode.ROUND_CEIL); test(new DfpDec(field, "12345678901234567").add(new DfpDec(field, "0.0001")), new DfpDec(field, "12345678901234568"), DfpField.FLAG_INEXACT, "Round #41"); test(new DfpDec(field, "-12345678901234567").add(new DfpDec(field, "-0.9999")), new DfpDec(field, "-12345678901234567"), DfpField.FLAG_INEXACT, "Round #42"); field.setRoundingMode(DfpField.RoundingMode.ROUND_FLOOR); test(new DfpDec(field, "12345678901234567").add(new DfpDec(field, "0.9999")), new DfpDec(field, "12345678901234567"), DfpField.FLAG_INEXACT, "Round #43"); test(new DfpDec(field, "-12345678901234567").add(new DfpDec(field, "-0.0001")), new DfpDec(field, "-12345678901234568"), DfpField.FLAG_INEXACT, "Round #44"); field.setRoundingMode(DfpField.RoundingMode.ROUND_HALF_EVEN); }