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