public static long round()

in java/dfp/src/main/java/com/epam/deltix/dfp/JavaImpl.java [2230:2349]


    public static long round(final long value, final int n, final RoundingMode roundType) {
        if (isNonFinite(value))
            return value;
        if (n > JavaImpl.MAX_EXPONENT)
            return value;
        if (n < JavaImpl.MIN_EXPONENT)
            return JavaImpl.ZERO;

//        final Decimal64Parts parts = tlsDecimal64Parts.get();
//        JavaImpl.toParts(value, parts);
        long partsCoefficient;
        long partsSignMask;
        int partsExponent;
        { // Copy-paste the toParts method for speedup
            partsSignMask = value & MASK_SIGN;

            if (isSpecial(value)) {
//                if (isNonFinite(value)) {
//                    partsExponent = 0;
//
//                    partsCoefficient = value & 0xFE03_FFFF_FFFF_FFFFL;
//                    if ((value & 0x0003_FFFF_FFFF_FFFFL) > MAX_COEFFICIENT)
//                        partsCoefficient = value & ~MASK_COEFFICIENT;
//                    if (isInfinity(value))
//                        partsCoefficient = value & MASK_SIGN_INFINITY_NAN; // TODO: Why this was done??
//                } else
                {
                    // Check for non-canonical values.
                    final long coefficient = (value & LARGE_COEFFICIENT_MASK) | LARGE_COEFFICIENT_HIGH_BIT;
                    partsCoefficient = coefficient > MAX_COEFFICIENT ? 0 : coefficient;

                    // Extract exponent.
                    final long tmp = value >> EXPONENT_SHIFT_LARGE;
                    partsExponent = (int) (tmp & EXPONENT_MASK);
                }
            } else {

                // Extract exponent. Maximum biased value for "small exponent" is 0x2FF(*2=0x5FE), signed: []
                // upper 1/4 of the mask range is "special", as checked in the code above
                final long tmp = value >> EXPONENT_SHIFT_SMALL;
                partsExponent = (int) (tmp & EXPONENT_MASK);

                // Extract coefficient.
                partsCoefficient = (value & SMALL_COEFFICIENT_MASK);
            }
        }

        if (partsCoefficient == 0)
            return Decimal64Utils.ZERO;

        final int exponent = partsExponent - JavaImpl.EXPONENT_BIAS + n;

        if (exponent >= 0) // value is already rounded
            return value;
        // All next - negative exponent case

        final long divFactor;
        int addExponent = 0;
        { // Truncate all digits except last one
            int absPower = -exponent;
            if (absPower >= MAX_FORMAT_DIGITS) {
                divFactor = MAX_COEFFICIENT + 1;
                final int expShift = MAX_FORMAT_DIGITS;
                addExponent = absPower - expShift;

            } else {
                divFactor = POWERS_OF_TEN[absPower];
            }
        }

        // Process last digit
        switch (roundType) {
            case UP:
                partsCoefficient = addExponent == 0 ? ((partsCoefficient + divFactor - 1) / divFactor) * divFactor : divFactor;
                break;

            case DOWN:
                partsCoefficient = addExponent == 0 ? (partsCoefficient / divFactor) * divFactor : 0;
                break;

            case CEILING:
                if (partsSignMask >= 0/*!parts.isNegative()*/)
                    partsCoefficient = addExponent == 0 ? ((partsCoefficient + divFactor - 1) / divFactor) * divFactor : divFactor;
                else
                    partsCoefficient = addExponent == 0 ? (partsCoefficient / divFactor) * divFactor : 0;
                break;

            case FLOOR:
                if (partsSignMask >= 0/*!parts.isNegative()*/)
                    partsCoefficient = addExponent == 0 ? (partsCoefficient / divFactor) * divFactor : 0;
                else
                    partsCoefficient = addExponent == 0 ? ((partsCoefficient + divFactor - 1) / divFactor) * divFactor : divFactor;
                break;

            case HALF_UP:
                partsCoefficient = addExponent == 0 ? ((partsCoefficient + divFactor / 2) / divFactor) * divFactor : 0;
                break;

            case HALF_DOWN:
                partsCoefficient = addExponent == 0 ? ((partsCoefficient + divFactor / 2 - 1) / divFactor) * divFactor : 0;
                break;

            case HALF_EVEN:
                partsCoefficient = addExponent == 0 ? ((partsCoefficient + divFactor / 2 - 1 + ((partsCoefficient / divFactor) & 1L)) / divFactor) * divFactor : 0;
                break;

            case UNNECESSARY:
                if (!isRoundedImpl(addExponent, partsCoefficient, divFactor))
                    throw new ArithmeticException("Rounding necessary");
                return value;

            default:
                throw new IllegalArgumentException("Unsupported roundType(=" + roundType + ") value.");
        }
        partsExponent += addExponent;
        if (partsCoefficient == 0)
            return JavaImpl.ZERO;

        return pack(partsSignMask, partsExponent, partsCoefficient, BID_ROUNDING_TO_NEAREST); // JavaImpl.fromParts(parts)
    }