public static long get_BID64()

in java/dfp/src/main/java/com/epam/deltix/dfp/JavaImplParse.java [878:1078]


    public static long get_BID64(long sgn, int expon, long coeff, int rmode, FloatingPointStatusFlag fpsc) {
        long Stemp_w0, Stemp_w1, Q_low_w0, Q_low_w1;
        long QH, r, mask, _C64, remainder_h, carry;
        int extra_digits, amount, amount2;
        int status;

        if ((UnsignedLong.isGreater(coeff, 9999999999999999L))) {
            expon++;
            coeff = 1000000000000000L;
        }
        // check for possible underflow/overflow
        if ((/*UnsignedInteger.compare*/(expon) + Integer.MIN_VALUE >= (3 * 256) + Integer.MIN_VALUE)) {
            if (expon < 0) {
                // underflow
                if (expon + MAX_FORMAT_DIGITS < 0) {
                    __set_status_flags(fpsc, BID_UNDERFLOW_EXCEPTION | BID_INEXACT_EXCEPTION);
                    if (rmode == BID_ROUNDING_DOWN && sgn != 0)
                        return 0x8000000000000001L;
                    if (rmode == BID_ROUNDING_UP && sgn == 0)
                        return 1L;
                    // result is 0
                    return sgn;
                }
                if (sgn != 0 && (rmode == BID_ROUNDING_DOWN || rmode == BID_ROUNDING_UP) /*(uint)(rmode - 1) < 2*/)
                    rmode = 3 - rmode;
                // get digits to be shifted out
                extra_digits = -expon;
                coeff += bid_round_const_table[rmode][extra_digits];

                // get coeff*(2^M[extra_digits])/10^extra_digits
                //__mul_64x128_full(out QH, out Q_low, coeff, bid_reciprocals10_128_flat[extra_digits << 1], bid_reciprocals10_128_flat[(extra_digits << 1) + 1]);
                //public static void __mul_64x128_full(/*out*/ long Ph, /*out*/ final BID_UINT128 Ql, final long A, final long B_w0, final long B_w1)
                {

                    final long _B_w0 = bid_reciprocals10_128_BID_UINT128[extra_digits << 1];
                    final long _B_w1 = bid_reciprocals10_128_BID_UINT128[(extra_digits << 1) + 1];

                    long _ALBL_w0, _ALBL_w1, _ALBH_w0, _ALBH_w1, _QM2_w0, _QM2_w1;

                    //__mul_64x64_to_128(out ALBH, A, B.w1);
                    _ALBH_w1 = Mul64Impl.unsignedMultiplyHigh(coeff, _B_w1);
                    _ALBH_w0 = coeff * _B_w1;
                    //__mul_64x64_to_128(out ALBL, A, B.w0);
                    _ALBL_w1 = Mul64Impl.unsignedMultiplyHigh(coeff, _B_w0);
                    _ALBL_w0 = coeff * _B_w0;

                    Q_low_w0 = _ALBL_w0;
                    //__add_128_64(out QM2, ALBH, ALBL.w1);
                    {
                        long R64H;
                        R64H = _ALBH_w1;
                        _QM2_w0 = (_ALBL_w1) + _ALBH_w0;
                        if ((UnsignedLong.isLess(_QM2_w0, _ALBL_w1)))
                            R64H++;
                        _QM2_w1 = R64H;
                    }
                    Q_low_w1 = _QM2_w0;
                    QH = _QM2_w1;
                }

                // now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128
                amount = bid_recip_scale[extra_digits];

                _C64 = QH >>> amount;

                if (rmode == 0) //BID_ROUNDING_TO_NEAREST
                    if ((_C64 & 1) != 0) {
                        // check whether fractional part of initial_P/10^extra_digits is exactly .5

                        // get remainder
                        amount2 = 64 - amount;
                        remainder_h = 0;
                        remainder_h--;
                        remainder_h >>>= amount2;
                        remainder_h = remainder_h & QH;

                        if (remainder_h == 0
                            && ((UnsignedLong.isLess(Q_low_w1, bid_reciprocals10_128_BID_UINT128[(extra_digits << 1) + 1]))
                            || (Q_low_w1 == bid_reciprocals10_128_BID_UINT128[(extra_digits << 1) + 1]
                            && (UnsignedLong.isLess(Q_low_w0, bid_reciprocals10_128_BID_UINT128[(extra_digits << 1) /*+ 0*/]))))) {
                            _C64--;
                        }
                    }


                if (is_inexact(fpsc))
                    __set_status_flags(fpsc, BID_UNDERFLOW_EXCEPTION);
                else {
                    status = BID_INEXACT_EXCEPTION;
                    // get remainder
                    remainder_h = QH << (64 - amount);

                    switch (rmode) {
                        case BID_ROUNDING_TO_NEAREST:
                        case BID_ROUNDING_TIES_AWAY:
                            // test whether fractional part is 0
                            if (remainder_h == 0x8000000000000000L
                                && ((UnsignedLong.isLess(Q_low_w1, bid_reciprocals10_128_BID_UINT128[(extra_digits << 1) + 1]))
                                || (Q_low_w1 == bid_reciprocals10_128_BID_UINT128[(extra_digits << 1) + 1]
                                && (UnsignedLong.isLess(Q_low_w0, bid_reciprocals10_128_BID_UINT128[(extra_digits << 1) /*+ 0*/])))))
                                status = BID_EXACT_STATUS;
                            break;
                        case BID_ROUNDING_DOWN:
                        case BID_ROUNDING_TO_ZERO:
                            if (remainder_h == 0
                                && ((UnsignedLong.isLess(Q_low_w1, bid_reciprocals10_128_BID_UINT128[(extra_digits << 1) + 1])))
                                || (Q_low_w1 == bid_reciprocals10_128_BID_UINT128[(extra_digits << 1) + 1]
                                && (UnsignedLong.isLess(Q_low_w0, bid_reciprocals10_128_BID_UINT128[(extra_digits << 1) /*+ 0*/]))))
                                status = BID_EXACT_STATUS;
                            break;
                        default:
                            // round up
                            long CY;
                            //__add_carry_out(out Stemp_w0, out CY, Q_low_w0, bid_reciprocals10_128_flat[(extra_digits << 1) + 0]);
                        {
                            final long __Y = bid_reciprocals10_128_BID_UINT128[(extra_digits << 1) /*+ 0*/];

                            Stemp_w0 = Q_low_w0 + __Y;
                            CY = (UnsignedLong.isLess(Stemp_w0, Q_low_w0)) ? 1L : 0;
                        }
                        //__add_carry_in_out(out Stemp_w1, out carry, Q_low_w1, bid_reciprocals10_128_flat[(extra_digits << 1) + 1], CY);
                        {
                            final long __Y = bid_reciprocals10_128_BID_UINT128[(extra_digits << 1) + 1];

                            final long __X1;
                            __X1 = Q_low_w1 + CY;
                            Stemp_w1 = __X1 + __Y;
                            carry = ((UnsignedLong.isLess(Stemp_w1, __X1)) || (UnsignedLong.isLess(__X1, CY))) ? 1L : 0;
                        }

                        if ((UnsignedLong.isGreaterOrEqual((remainder_h >>> (64 - amount)) + carry, 1L << amount)))
                            status = BID_EXACT_STATUS;
                        break;
                    }

                    if (status != BID_EXACT_STATUS)
                        __set_status_flags(fpsc, BID_UNDERFLOW_EXCEPTION | status);
                }


                return sgn | _C64;
            }
            if (coeff == 0) {
                if (expon > DECIMAL_MAX_EXPON_64) expon = DECIMAL_MAX_EXPON_64;
            }
            while ((UnsignedLong.isLess(coeff, 1000000000000000L)) && expon >= 3 * 256) {
                expon--;
                coeff = (coeff << 3) + (coeff << 1);
            }
            if (expon > DECIMAL_MAX_EXPON_64) {
                __set_status_flags(fpsc, BID_OVERFLOW_EXCEPTION | BID_INEXACT_EXCEPTION);
                // overflow
                r = sgn | INFINITY_MASK64;
                switch (rmode) {
                    case BID_ROUNDING_DOWN:
                        if (sgn == 0)
                            r = LARGEST_BID64;
                        break;
                    case BID_ROUNDING_TO_ZERO:
                        r = sgn | LARGEST_BID64;
                        break;
                    case BID_ROUNDING_UP:
                        // round up
                        if (sgn != 0)
                            r = SMALLEST_BID64;
                        break;
                }
                return r;
            }
        }

        mask = 1;
        mask <<= EXPONENT_SHIFT_SMALL64;

        // check whether coefficient fits in 10*5+3 bits
        if ((UnsignedLong.isLess(coeff, mask))) {
            r = LONG_LOW_PART & expon;
            r <<= EXPONENT_SHIFT_SMALL64;
            r |= (coeff | sgn);
            return r;
        }
        // special format

        // eliminate the case coeff==10^16 after rounding
        if (coeff == 10000000000000000L) {
            r = LONG_LOW_PART & (expon + 1);
            r <<= EXPONENT_SHIFT_SMALL64;
            r |= (1000000000000000L | sgn);
            return r;
        }

        r = LONG_LOW_PART & expon;
        r <<= EXPONENT_SHIFT_LARGE64;
        r |= (sgn | SPECIAL_ENCODING_MASK64);
        // add coeff, without leading bits
        mask = (mask >>> 2) - 1;
        coeff &= mask;
        r |= coeff;

        return r;
    }