/*
* 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);
}