static int mul_pow()

in src/couch_quickjs/quickjs/dtoa.c [893:956]


static int mul_pow(mpb_t *a, int radix1, int radix_shift, int f, BOOL is_int, int e)
{
    int e_offset, d, n, n0;

    e_offset = -f * radix_shift;
    if (radix1 != 1) {
        d = digits_per_limb_table[radix1 - 2];
        if (f >= 0) {
            limb_t h, b;
            
            b = 0;
            n0 = 0;
            while (f != 0) {
                n = min_int(f, d);
                if (n != n0) {
                    b = pow_ui(radix1, n);
                    n0 = n;
                }
                h = mp_mul1(a->tab, a->tab, a->len, b, 0);
                if (h != 0) {
                    a->tab[a->len++] = h;
                }
                f -= n;
            }
        } else {
            int extra_bits, l, shift;
            limb_t r, rem, b, b_inv;
            
            f = -f;
            l = (f + d - 1) / d; /* high bound for the number of limbs (XXX: make it better) */
            e_offset += l * LIMB_BITS;
            if (!is_int) {
                /* at least 'e' bits are needed in the final result for rounding */
                extra_bits = max_int(e - mpb_floor_log2(a), 0);
            } else {
                /* at least two extra bits are needed in the final result
                   for rounding */
                extra_bits = max_int(2 + e - e_offset, 0);
            }
            e_offset += extra_bits;
            mpb_shr_round(a, -(l * LIMB_BITS + extra_bits), JS_RNDZ);
            
            b = 0;
            b_inv = 0;
            shift = 0;
            n0 = 0;
            rem = 0;
            while (f != 0) {
                n = min_int(f, d);
                if (n != n0) {
                    b = pow_ui_inv(&b_inv, &shift, radix1, n);
                    n0 = n;
                }
                r = mp_div1norm(a->tab, a->tab, a->len, b, 0, b_inv, shift);
                rem |= r;
                mpb_renorm(a);
                f -= n;
            }
            /* if the remainder is non zero, use it for rounding */
            a->tab[0] |= (rem != 0);
        }
    }
    return e_offset;
}