public static long get_BID64()

in java/dfp/src/main/java/com/epam/deltix/dfp/JavaImplMul.java [664:788]


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

        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) {
                    // result is 0
                    return sgn;
                }
                // get digits to be shifted out
                extra_digits = -expon;
                coeff += bid_round_const_table_nearest[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 _A = coeff;
                    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(_A, _B_w1);
                    _ALBH_w0 = _A * _B_w1;
                    //__mul_64x64_to_128(out ALBL, A, B.w0);
                    _ALBL_w1 = Mul64Impl.unsignedMultiplyHigh(_A, _B_w0);
                    _ALBL_w0 = _A * _B_w0;

                    Q_low_w0 = _ALBL_w0;
                    //__add_128_64(out QM2, ALBH, ALBL.w1);
                    {
                        final long __A128_w0 = _ALBH_w0;
                        final long __A128_w1 = _ALBH_w1;
                        final long __B64 = _ALBL_w1;
                        long R64H;
                        R64H = __A128_w1;
                        _QM2_w0 = (__B64) + __A128_w0;
                        if ((UnsignedLong.isLess(_QM2_w0, __B64)))
                            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 (BID_ROUNDING_TO_NEAREST == 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--;
                    }
                }

                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) {
                // overflow
                return sgn | INFINITY_MASK64;
            }
        }

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