/*
 * call-seq:
 *     big >> numeric   =>  integer
 *
 * Shifts big right _numeric_ positions (left if _numeric_ is negative).
 */

static VALUE
rb_big_rshift(x, y)
    VALUE x, y;
{
    BDIGIT *xds, *zds;
    int shift = NUM2INT(y);
    long s1 = shift/BITSPERDIG;
    long s2 = shift%BITSPERDIG;
    VALUE z;
    BDIGIT_DBL num = 0;
    long i, j;
    volatile VALUE save_x;

    if (shift < 0) return rb_big_lshift(x, INT2FIX(-shift));

    if (s1 > RBIGNUM(x)->len) {
        if (RBIGNUM(x)->sign)
            return INT2FIX(0);
        else
            return INT2FIX(-1);
    }
    if (!RBIGNUM(x)->sign) {
        save_x = x = rb_big_clone(x);
        get2comp(x);
    }
    xds = BDIGITS(x);
    i = RBIGNUM(x)->len; j = i - s1;
    z = bignew(j, RBIGNUM(x)->sign);
    if (!RBIGNUM(x)->sign) {
        num = ((BDIGIT_DBL)~0) << BITSPERDIG;
    }
    zds = BDIGITS(z);
    while (i--, j--) {
        num = (num | xds[i]) >> s2;
        zds[j] = BIGLO(num);
        num = BIGUP(xds[i]);
    }
    if (!RBIGNUM(x)->sign) {
        get2comp(z);
    }
    return bignorm(z);
}