Example #1
0
static VALUE 
bigmul_low_digits(VALUE x, VALUE y, int digits)
{
    int xn = RBIGNUM_LEN(x);
    if (FIXNUM_P(y)) y = INTVALUE2BIG(y);
    int yn = RBIGNUM_LEN(y);

    if (digits > xn + yn) 
    {
        digits = xn + yn;
    }
    VALUE z = rb_big_new(digits, 1);

    BDIGIT* xds = RBIGNUM_DIGITS(x);
    BDIGIT* yds = RBIGNUM_DIGITS(y);
    BDIGIT* zds = RBIGNUM_DIGITS(z);

    BDIGIT c0,c1,c2; // carry
    int i, j, k, beg, end;
    for (k = c0 = c1 = c2 = 0; k < digits; k++)
    {
        beg = k >= yn - 1 ? k - yn + 1 : 0; 
        end = k >= xn     ? xn - 1     : k;
        for (i = beg, j = k - beg; i <= end; ++i, --j)
            MULADD(xds[i], yds[j]);
        zds[k] = c0;
        c0 = c1;
        c1 = c2;
        c2 = 0;
    }
    return rb_big_norm(z);
}
Example #2
0
VALUE rb_big_barrett_reduce(VALUE x, VALUE m, VALUE mu, int inplace)
{
    if (!NEGATIVE_P(x) && MORE(m, x))
    {
        return x;
    }
    unsigned long len = RBIGNUM_LEN(m); /* >= 1 */
    if (FIXNUM_P(x))
    {
        return FIX2LONG(x) >= 0 ? x : rb_big_plus(m, x);
    }

    VALUE   q = bigmul_high_digits(x, mu, len - 1, len - 1);
    /* q is not normed */
    q = rshift_digits_inplace(q, len + 1);
    /* [x/m] - 3 <= q <= [x/m] */
    q = bigmul_low_digits(q, m, len + 1);
    /* q is normed */

    VALUE a = inplace ? x : rb_big_clone(x);
    if (RBIGNUM_LEN(a) > (long)len + 1)
    {
        RBIGNUM_SET_LEN(a, len + 1);
    }

    a = rb_big_minus(a, q);
    if (NEGATIVE_P(a))
        a = ADD(a, power_of_two((len + 1) * BITSPERDIG));
    /* a = (x - q * m) mod (base ** (len + 1)) */

    while (!MORE(m, a)) /* that is, m <= a */
        a = SUB(a, m);
    return rb_big_norm(a);
}
Example #3
0
static VALUE
gcd_gmp(VALUE x, VALUE y)
{
    return rb_big_norm(rb_gcd_gmp(big(x), big(y)));
}
Example #4
0
static VALUE
gcd_normal(VALUE x, VALUE y)
{
    return rb_big_norm(rb_gcd_normal(rb_to_int(x), rb_to_int(y)));
}