static void mpb_shr_round()

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