in src/couch_quickjs/quickjs/dtoa.c [313:398]
static void mpb_shr_round(mpb_t *r, int shift, int rnd_mode)
{
int l, i;
if (shift == 0)
return;
if (shift < 0) {
shift = -shift;
l = (unsigned)shift / LIMB_BITS;
shift = shift & (LIMB_BITS - 1);
if (shift != 0) {
r->tab[r->len] = mp_shl(r->tab, r->tab, r->len, shift, 0);
r->len++;
mpb_renorm(r);
}
if (l > 0) {
for(i = r->len - 1; i >= 0; i--)
r->tab[i + l] = r->tab[i];
for(i = 0; i < l; i++)
r->tab[i] = 0;
r->len += l;
}
} else {
limb_t bit1, bit2;
int k, add_one;
switch(rnd_mode) {
default:
case JS_RNDZ:
add_one = 0;
break;
case JS_RNDN:
case JS_RNDNA:
bit1 = mpb_get_bit(r, shift - 1);
if (bit1) {
if (rnd_mode == JS_RNDNA) {
bit2 = 1;
} else {
/* bit2 = oring of all the bits after bit1 */
bit2 = 0;
if (shift >= 2) {
k = shift - 1;
l = (unsigned)k / LIMB_BITS;
k = k & (LIMB_BITS - 1);
for(i = 0; i < min_int(l, r->len); i++)
bit2 |= r->tab[i];
if (l < r->len)
bit2 |= r->tab[l] & (((limb_t)1 << k) - 1);
}
}
if (bit2) {
add_one = 1;
} else {
/* round to even */
add_one = mpb_get_bit(r, shift);
}
} else {
add_one = 0;
}
break;
}
l = (unsigned)shift / LIMB_BITS;
shift = shift & (LIMB_BITS - 1);
if (l >= r->len) {
r->len = 1;
r->tab[0] = add_one;
} else {
if (l > 0) {
r->len -= l;
for(i = 0; i < r->len; i++)
r->tab[i] = r->tab[i + l];
}
if (shift != 0) {
mp_shr(r->tab, r->tab, r->len, shift, 0);
mpb_renorm(r);
}
if (add_one) {
limb_t a;
a = mp_add_ui(r->tab, 1, r->len);
if (a)
r->tab[r->len++] = a;
}
}
}
}