Maintenance of Ruby 2.0.0 ended on February 24, 2016. Read more

In Files

  • bignum.c

Bignum

Bignum objects hold integers outside the range of Fixnum. Bignum objects are created automatically when integer calculations would otherwise overflow a Fixnum. When a calculation involving Bignum objects returns a result that will fit in a Fixnum, the result is automatically converted.

For the purposes of the bitwise operations and [], a Bignum is treated as if it were an infinite-length bitstring with 2's complement representation.

While Fixnum values are immediate, Bignum objects are not—assignment and parameter passing work with references to objects, not the objects themselves.

Public Instance Methods

big % other → Numeric click to toggle source

Returns big modulo other. See Numeric#divmod for more information.

 
               VALUE
rb_big_modulo(VALUE x, VALUE y)
{
    VALUE z;

    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;

      case T_BIGNUM:
        break;

      default:
        return rb_num_coerce_bin(x, y, '%');
    }
    bigdivmod(x, y, 0, &z);

    return bignorm(z);
}
            
big & numeric → integer click to toggle source

Performs bitwise and between big and numeric.

 
               VALUE
rb_big_and(VALUE xx, VALUE yy)
{
    volatile VALUE x, y, z;
    BDIGIT *ds1, *ds2, *zds;
    long i, l1, l2;
    char sign;

    if (!FIXNUM_P(yy) && !RB_TYPE_P(yy, T_BIGNUM)) {
        return rb_num_coerce_bit(xx, yy, '&');
    }

    x = xx;
    y = yy;

    if (!RBIGNUM_SIGN(x)) {
        x = rb_big_clone(x);
        get2comp(x);
    }
    if (FIXNUM_P(y)) {
        return bigand_int(x, FIX2LONG(y));
    }
    if (!RBIGNUM_SIGN(y)) {
        y = rb_big_clone(y);
        get2comp(y);
    }
    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
        l1 = RBIGNUM_LEN(y);
        l2 = RBIGNUM_LEN(x);
        ds1 = BDIGITS(y);
        ds2 = BDIGITS(x);
        sign = RBIGNUM_SIGN(y);
    }
    else {
        l1 = RBIGNUM_LEN(x);
        l2 = RBIGNUM_LEN(y);
        ds1 = BDIGITS(x);
        ds2 = BDIGITS(y);
        sign = RBIGNUM_SIGN(x);
    }
    z = bignew(l2, RBIGNUM_SIGN(x) || RBIGNUM_SIGN(y));
    zds = BDIGITS(z);

    for (i=0; i<l1; i++) {
        zds[i] = ds1[i] & ds2[i];
    }
    for (; i<l2; i++) {
        zds[i] = sign?0:ds2[i];
    }
    if (!RBIGNUM_SIGN(z)) get2comp(z);
    return bignorm(z);
}
            
big * other → Numeric click to toggle source

Multiplies big and other, returning the result.

 
               VALUE
rb_big_mul(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;

      case T_BIGNUM:
        break;

      case T_FLOAT:
        return DBL2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));

      default:
        return rb_num_coerce_bin(x, y, '*');
    }

    return bignorm(bigmul0(x, y));
}
            
big ** exponent → numeric click to toggle source

Raises big to the exponent power (which may be an integer, float, or anything that will coerce to a number). The result may be a Fixnum, Bignum, or Float

123456789 ** 2      #=> 15241578750190521
123456789 ** 1.2    #=> 5126464716.09932
123456789 ** -2     #=> 6.5610001194102e-17
 
               VALUE
rb_big_pow(VALUE x, VALUE y)
{
    double d;
    SIGNED_VALUE yy;

    if (y == INT2FIX(0)) return INT2FIX(1);
    switch (TYPE(y)) {
      case T_FLOAT:
        d = RFLOAT_VALUE(y);
        if ((!RBIGNUM_SIGN(x) && !BIGZEROP(x)) && d != round(d))
            return rb_funcall(rb_complex_raw1(x), rb_intern("**"), 1, y);
        break;

      case T_BIGNUM:
        rb_warn("in a**b, b may be too big");
        d = rb_big2dbl(y);
        break;

      case T_FIXNUM:
        yy = FIX2LONG(y);

        if (yy < 0)
            return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
        else {
            VALUE z = 0;
            SIGNED_VALUE mask;
            const long xlen = RBIGNUM_LEN(x) - 1;
            const long xbits = ffs(RBIGNUM_DIGITS(x)[xlen]) + SIZEOF_BDIGITS*BITSPERDIG*xlen;
            const long BIGLEN_LIMIT = BITSPERDIG*1024*1024;

            if ((xbits > BIGLEN_LIMIT) || (xbits * yy > BIGLEN_LIMIT)) {
                rb_warn("in a**b, b may be too big");
                d = (double)yy;
                break;
            }
            for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
                if (z) z = bigsqr(z);
                if (yy & mask) {
                    z = z ? bigtrunc(bigmul0(z, x)) : x;
                }
            }
            return bignorm(z);
        }
        /* NOTREACHED */
        break;

      default:
        return rb_num_coerce_bin(x, y, rb_intern("**"));
    }
    return DBL2NUM(pow(rb_big2dbl(x), d));
}
            
big + other → Numeric click to toggle source

Adds big and other, returning the result.

 
               VALUE
rb_big_plus(VALUE x, VALUE y)
{
    long n;

    switch (TYPE(y)) {
      case T_FIXNUM:
        n = FIX2LONG(y);
        if ((n > 0) != RBIGNUM_SIGN(x)) {
            if (n < 0) {
                n = -n;
            }
            return bigsub_int(x, n);
        }
        if (n < 0) {
            n = -n;
        }
        return bigadd_int(x, n);

      case T_BIGNUM:
        return bignorm(bigadd(x, y, 1));

      case T_FLOAT:
        return DBL2NUM(rb_big2dbl(x) + RFLOAT_VALUE(y));

      default:
        return rb_num_coerce_bin(x, y, '+');
    }
}
            
big - other → Numeric click to toggle source

Subtracts other from big, returning the result.

 
               VALUE
rb_big_minus(VALUE x, VALUE y)
{
    long n;

    switch (TYPE(y)) {
      case T_FIXNUM:
        n = FIX2LONG(y);
        if ((n > 0) != RBIGNUM_SIGN(x)) {
            if (n < 0) {
                n = -n;
            }
            return bigadd_int(x, n);
        }
        if (n < 0) {
            n = -n;
        }
        return bigsub_int(x, n);

      case T_BIGNUM:
        return bignorm(bigadd(x, y, 0));

      case T_FLOAT:
        return DBL2NUM(rb_big2dbl(x) - RFLOAT_VALUE(y));

      default:
        return rb_num_coerce_bin(x, y, '-');
    }
}
            
-big → integer click to toggle source

Unary minus (returns an integer whose value is 0-big)

 
               VALUE
rb_big_uminus(VALUE x)
{
    VALUE z = rb_big_clone(x);

    RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(x));

    return bignorm(z);
}
            
big / other → Numeric click to toggle source

Performs division: the class of the resulting object depends on the class of numeric and on the magnitude of the result.

 
               VALUE
rb_big_div(VALUE x, VALUE y)
{
    return rb_big_divide(x, y, '/');
}
            
big < real → true or false click to toggle source

Returns true if the value of big is less than that of real.

 
               static VALUE
big_lt(VALUE x, VALUE y)
{
    return big_op(x, y, big_op_lt);
}
            
big << numeric → integer click to toggle source

Shifts big left numeric positions (right if numeric is negative).

 
               VALUE
rb_big_lshift(VALUE x, VALUE y)
{
    long shift;
    int neg = 0;

    for (;;) {
        if (FIXNUM_P(y)) {
            shift = FIX2LONG(y);
            if (shift < 0) {
                neg = 1;
                shift = -shift;
            }
            break;
        }
        else if (RB_TYPE_P(y, T_BIGNUM)) {
            if (!RBIGNUM_SIGN(y)) {
                VALUE t = check_shiftdown(y, x);
                if (!NIL_P(t)) return t;
                neg = 1;
            }
            shift = big2ulong(y, "long", TRUE);
            break;
        }
        y = rb_to_int(y);
    }

    x = neg ? big_rshift(x, shift) : big_lshift(x, shift);
    return bignorm(x);
}
            
big <= real → true or false click to toggle source

Returns true if the value of big is less than or equal to that of real.

 
               static VALUE
big_le(VALUE x, VALUE y)
{
    return big_op(x, y, big_op_le);
}
            
big <=> numeric → -1, 0, +1 or nil click to toggle source

Comparison—Returns -1, 0, or +1 depending on whether big is less than, equal to, or greater than numeric. This is the basis for the tests in Comparable.

nil is returned if the two values are incomparable.

 
               VALUE
rb_big_cmp(VALUE x, VALUE y)
{
    long xlen = RBIGNUM_LEN(x);
    BDIGIT *xds, *yds;

    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;

      case T_BIGNUM:
        break;

      case T_FLOAT:
        return rb_integer_float_cmp(x, y);

      default:
        return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
    }

    if (RBIGNUM_SIGN(x) > RBIGNUM_SIGN(y)) return INT2FIX(1);
    if (RBIGNUM_SIGN(x) < RBIGNUM_SIGN(y)) return INT2FIX(-1);
    if (xlen < RBIGNUM_LEN(y))
        return (RBIGNUM_SIGN(x)) ? INT2FIX(-1) : INT2FIX(1);
    if (xlen > RBIGNUM_LEN(y))
        return (RBIGNUM_SIGN(x)) ? INT2FIX(1) : INT2FIX(-1);

    xds = BDIGITS(x);
    yds = BDIGITS(y);

    while (xlen-- && (xds[xlen]==yds[xlen]));
    if (-1 == xlen) return INT2FIX(0);
    return (xds[xlen] > yds[xlen]) ?
        (RBIGNUM_SIGN(x) ? INT2FIX(1) : INT2FIX(-1)) :
            (RBIGNUM_SIGN(x) ? INT2FIX(-1) : INT2FIX(1));
}
            
big == obj → true or false click to toggle source

Returns true only if obj has the same value as big. Contrast this with Bignum#eql?, which requires obj to be a Bignum.

68719476736 == 68719476736.0   #=> true
 
               VALUE
rb_big_eq(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;
      case T_BIGNUM:
        break;
      case T_FLOAT:
        return rb_integer_float_eq(x, y);
      default:
        return rb_equal(y, x);
    }
    if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
    if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
    return Qtrue;
}
            
big == obj → true or false click to toggle source

Returns true only if obj has the same value as big. Contrast this with Bignum#eql?, which requires obj to be a Bignum.

68719476736 == 68719476736.0   #=> true
 
               VALUE
rb_big_eq(VALUE x, VALUE y)
{
    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;
      case T_BIGNUM:
        break;
      case T_FLOAT:
        return rb_integer_float_eq(x, y);
      default:
        return rb_equal(y, x);
    }
    if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
    if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
    return Qtrue;
}
            
big > real → true or false click to toggle source

Returns true if the value of big is greater than that of real.

 
               static VALUE
big_gt(VALUE x, VALUE y)
{
    return big_op(x, y, big_op_gt);
}
            
big >= real → true or false click to toggle source

Returns true if the value of big is greater than or equal to that of real.

 
               static VALUE
big_ge(VALUE x, VALUE y)
{
    return big_op(x, y, big_op_ge);
}
            
big >> numeric → integer click to toggle source

Shifts big right numeric positions (left if numeric is negative).

 
               VALUE
rb_big_rshift(VALUE x, VALUE y)
{
    long shift;
    int neg = 0;

    for (;;) {
        if (FIXNUM_P(y)) {
            shift = FIX2LONG(y);
            if (shift < 0) {
                neg = 1;
                shift = -shift;
            }
            break;
        }
        else if (RB_TYPE_P(y, T_BIGNUM)) {
            if (RBIGNUM_SIGN(y)) {
                VALUE t = check_shiftdown(y, x);
                if (!NIL_P(t)) return t;
            }
            else {
                neg = 1;
            }
            shift = big2ulong(y, "long", TRUE);
            break;
        }
        y = rb_to_int(y);
    }

    x = neg ? big_lshift(x, shift) : big_rshift(x, shift);
    return bignorm(x);
}
            
big[n] → 0, 1 click to toggle source

Bit Reference—Returns the nth bit in the (assumed) binary representation of big, where big is the least significant bit.

a = 9**15
50.downto(0) do |n|
  print a[n]
end

produces:

000101110110100000111000011110010100111100010111001
 
               static VALUE
rb_big_aref(VALUE x, VALUE y)
{
    BDIGIT *xds;
    BDIGIT_DBL num;
    VALUE shift;
    long i, s1, s2;

    if (RB_TYPE_P(y, T_BIGNUM)) {
        if (!RBIGNUM_SIGN(y))
            return INT2FIX(0);
        bigtrunc(y);
        if (RBIGNUM_LEN(y) > DIGSPERLONG) {
          out_of_range:
            return RBIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
        }
        shift = big2ulong(y, "long", FALSE);
    }
    else {
        i = NUM2LONG(y);
        if (i < 0) return INT2FIX(0);
        shift = (VALUE)i;
    }
    s1 = shift/BITSPERDIG;
    s2 = shift%BITSPERDIG;

    if (s1 >= RBIGNUM_LEN(x)) goto out_of_range;
    if (!RBIGNUM_SIGN(x)) {
        xds = BDIGITS(x);
        i = 0; num = 1;
        while (num += ~xds[i], ++i <= s1) {
            num = BIGDN(num);
        }
    }
    else {
        num = BDIGITS(x)[s1];
    }
    if (num & ((BDIGIT_DBL)1<<s2))
        return INT2FIX(1);
    return INT2FIX(0);
}
            
big ^ numeric → integer click to toggle source

Performs bitwise +exclusive or+ between big and numeric.

 
               VALUE
rb_big_xor(VALUE xx, VALUE yy)
{
    volatile VALUE x, y;
    VALUE z;
    BDIGIT *ds1, *ds2, *zds;
    long i, l1, l2;
    char sign;

    if (!FIXNUM_P(yy) && !RB_TYPE_P(yy, T_BIGNUM)) {
        return rb_num_coerce_bit(xx, yy, '^');
    }

    x = xx;
    y = yy;

    if (!RBIGNUM_SIGN(x)) {
        x = rb_big_clone(x);
        get2comp(x);
    }
    if (FIXNUM_P(y)) {
        return bigxor_int(x, FIX2LONG(y));
    }
    if (!RBIGNUM_SIGN(y)) {
        y = rb_big_clone(y);
        get2comp(y);
    }
    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
        l1 = RBIGNUM_LEN(y);
        l2 = RBIGNUM_LEN(x);
        ds1 = BDIGITS(y);
        ds2 = BDIGITS(x);
        sign = RBIGNUM_SIGN(y);
    }
    else {
        l1 = RBIGNUM_LEN(x);
        l2 = RBIGNUM_LEN(y);
        ds1 = BDIGITS(x);
        ds2 = BDIGITS(y);
        sign = RBIGNUM_SIGN(x);
    }
    RBIGNUM_SET_SIGN(x, RBIGNUM_SIGN(x)?1:0);
    RBIGNUM_SET_SIGN(y, RBIGNUM_SIGN(y)?1:0);
    z = bignew(l2, !(RBIGNUM_SIGN(x) ^ RBIGNUM_SIGN(y)));
    zds = BDIGITS(z);

    for (i=0; i<l1; i++) {
        zds[i] = ds1[i] ^ ds2[i];
    }
    for (; i<l2; i++) {
        zds[i] = sign?ds2[i]:~ds2[i];
    }
    if (!RBIGNUM_SIGN(z)) get2comp(z);

    return bignorm(z);
}
            
abs → aBignum click to toggle source

Returns the absolute value of big.

-1234567890987654321.abs   #=> 1234567890987654321
 
               static VALUE
rb_big_abs(VALUE x)
{
    if (!RBIGNUM_SIGN(x)) {
        x = rb_big_clone(x);
        RBIGNUM_SET_SIGN(x, 1);
    }
    return x;
}
            
coerce(p1) click to toggle source

MISSING: documentation

 
               static VALUE
rb_big_coerce(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        y = rb_int2big(FIX2LONG(y));
    }
    else if (!RB_TYPE_P(y, T_BIGNUM)) {
        rb_raise(rb_eTypeError, "can't coerce %s to Bignum",
                 rb_obj_classname(y));
    }
    return rb_assoc_new(y, x);
}
            
div(other) → integer click to toggle source

Performs integer division: returns integer value.

 
               VALUE
rb_big_idiv(VALUE x, VALUE y)
{
    return rb_big_divide(x, y, rb_intern("div"));
}
            
divmod(numeric) → array click to toggle source

See Numeric#divmod.

 
               VALUE
rb_big_divmod(VALUE x, VALUE y)
{
    VALUE div, mod;

    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;

      case T_BIGNUM:
        break;

      default:
        return rb_num_coerce_bin(x, y, rb_intern("divmod"));
    }
    bigdivmod(x, y, &div, &mod);

    return rb_assoc_new(bignorm(div), bignorm(mod));
}
            
eql?(obj) → true or false click to toggle source

Returns true only if obj is a Bignum with the same value as big. Contrast this with Bignum#==, which performs type conversions.

68719476736.eql?(68719476736.0)   #=> false
 
               VALUE
rb_big_eql(VALUE x, VALUE y)
{
    if (!RB_TYPE_P(y, T_BIGNUM)) return Qfalse;
    if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
    if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
    if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
    return Qtrue;
}
            
even? → true or false click to toggle source

Returns true if big is an even number.

 
               static VALUE
rb_big_even_p(VALUE num)
{
    if (BDIGITS(num)[0] & 1) {
        return Qfalse;
    }
    return Qtrue;
}
            
fdiv(numeric) → float click to toggle source

Returns the floating point result of dividing big by numeric.

-1234567890987654321.fdiv(13731)      #=> -89910996357705.5
-1234567890987654321.fdiv(13731.24)   #=> -89909424858035.7
 
               VALUE
rb_big_fdiv(VALUE x, VALUE y)
{
    double dx, dy;

    dx = big2dbl(x);
    switch (TYPE(y)) {
      case T_FIXNUM:
        dy = (double)FIX2LONG(y);
        if (isinf(dx))
            return big_fdiv(x, y);
        break;

      case T_BIGNUM:
        dy = rb_big2dbl(y);
        if (isinf(dx) || isinf(dy))
            return big_fdiv(x, y);
        break;

      case T_FLOAT:
        dy = RFLOAT_VALUE(y);
        if (isnan(dy))
            return y;
        if (isinf(dx))
            return big_fdiv(x, y);
        break;

      default:
        return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
    }
    return DBL2NUM(dx / dy);
}
            
hash → fixnum click to toggle source

Compute a hash based on the value of big.

 
               static VALUE
rb_big_hash(VALUE x)
{
    st_index_t hash;

    hash = rb_memhash(BDIGITS(x), sizeof(BDIGIT)*RBIGNUM_LEN(x)) ^ RBIGNUM_SIGN(x);
    return INT2FIX(hash);
}
            
inspect(p1 = v1) click to toggle source
Alias for: to_s
abs → aBignum click to toggle source

Returns the absolute value of big.

-1234567890987654321.abs   #=> 1234567890987654321
 
               static VALUE
rb_big_abs(VALUE x)
{
    if (!RBIGNUM_SIGN(x)) {
        x = rb_big_clone(x);
        RBIGNUM_SET_SIGN(x, 1);
    }
    return x;
}
            
modulo(other) → Numeric click to toggle source

Returns big modulo other. See Numeric#divmod for more information.

 
               VALUE
rb_big_modulo(VALUE x, VALUE y)
{
    VALUE z;

    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;

      case T_BIGNUM:
        break;

      default:
        return rb_num_coerce_bin(x, y, '%');
    }
    bigdivmod(x, y, 0, &z);

    return bignorm(z);
}
            
odd? → true or false click to toggle source

Returns true if big is an odd number.

 
               static VALUE
rb_big_odd_p(VALUE num)
{
    if (BDIGITS(num)[0] & 1) {
        return Qtrue;
    }
    return Qfalse;
}
            
remainder(numeric) → number click to toggle source

Returns the remainder after dividing big by numeric.

-1234567890987654321.remainder(13731)      #=> -6966
-1234567890987654321.remainder(13731.24)   #=> -9906.22531493148
 
               static VALUE
rb_big_remainder(VALUE x, VALUE y)
{
    VALUE z;

    switch (TYPE(y)) {
      case T_FIXNUM:
        y = rb_int2big(FIX2LONG(y));
        break;

      case T_BIGNUM:
        break;

      default:
        return rb_num_coerce_bin(x, y, rb_intern("remainder"));
    }
    bigdivrem(x, y, 0, &z);

    return bignorm(z);
}
            
size → integer click to toggle source

Returns the number of bytes in the machine representation of big.

(256**10 - 1).size   #=> 12
(256**20 - 1).size   #=> 20
(256**40 - 1).size   #=> 40
 
               static VALUE
rb_big_size(VALUE big)
{
    return LONG2FIX(RBIGNUM_LEN(big)*SIZEOF_BDIGITS);
}
            
to_f → float click to toggle source

Converts big to a Float. If big doesn't fit in a Float, the result is infinity.

 
               static VALUE
rb_big_to_f(VALUE x)
{
    return DBL2NUM(rb_big2dbl(x));
}
            
to_s(base=10) → string click to toggle source

Returns a string containing the representation of big radix base (2 through 36).

12345654321.to_s         #=> "12345654321"
12345654321.to_s(2)      #=> "1011011111110110111011110000110001"
12345654321.to_s(8)      #=> "133766736061"
12345654321.to_s(16)     #=> "2dfdbbc31"
78546939656932.to_s(36)  #=> "rubyrules"
 
               static VALUE
rb_big_to_s(int argc, VALUE *argv, VALUE x)
{
    int base;

    if (argc == 0) base = 10;
    else {
        VALUE b;

        rb_scan_args(argc, argv, "01", &b);
        base = NUM2INT(b);
    }
    return rb_big2str(x, base);
}
            
Also aliased as: inspect
big | numeric → integer click to toggle source

Performs bitwise or between big and numeric.

 
               VALUE
rb_big_or(VALUE xx, VALUE yy)
{
    volatile VALUE x, y, z;
    BDIGIT *ds1, *ds2, *zds;
    long i, l1, l2;
    char sign;

    if (!FIXNUM_P(yy) && !RB_TYPE_P(yy, T_BIGNUM)) {
        return rb_num_coerce_bit(xx, yy, '|');
    }

    x = xx;
    y = yy;

    if (!RBIGNUM_SIGN(x)) {
        x = rb_big_clone(x);
        get2comp(x);
    }
    if (FIXNUM_P(y)) {
        return bigor_int(x, FIX2LONG(y));
    }
    if (!RBIGNUM_SIGN(y)) {
        y = rb_big_clone(y);
        get2comp(y);
    }
    if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
        l1 = RBIGNUM_LEN(y);
        l2 = RBIGNUM_LEN(x);
        ds1 = BDIGITS(y);
        ds2 = BDIGITS(x);
        sign = RBIGNUM_SIGN(y);
    }
    else {
        l1 = RBIGNUM_LEN(x);
        l2 = RBIGNUM_LEN(y);
        ds1 = BDIGITS(x);
        ds2 = BDIGITS(y);
        sign = RBIGNUM_SIGN(x);
    }
    z = bignew(l2, RBIGNUM_SIGN(x) && RBIGNUM_SIGN(y));
    zds = BDIGITS(z);

    for (i=0; i<l1; i++) {
        zds[i] = ds1[i] | ds2[i];
    }
    for (; i<l2; i++) {
        zds[i] = sign?ds2[i]:(BDIGIT)(BIGRAD-1);
    }
    if (!RBIGNUM_SIGN(z)) get2comp(z);
    return bignorm(z);
}
            
~big → integer click to toggle source

Inverts the bits in big. As Bignums are conceptually infinite length, the result acts as if it had an infinite number of one bits to the left. In hex representations, this is displayed as two periods to the left of the digits.

sprintf("%X", ~0x1122334455)    #=> "..FEEDDCCBBAA"
 
               static VALUE
rb_big_neg(VALUE x)
{
    VALUE z = rb_big_clone(x);
    BDIGIT *ds;
    long i;

    if (!RBIGNUM_SIGN(x)) get2comp(z);
    ds = BDIGITS(z);
    i = RBIGNUM_LEN(x);
    if (!i) return INT2FIX(~(SIGNED_VALUE)0);
    while (i--) {
        ds[i] = ~ds[i];
    }
    RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(z));
    if (RBIGNUM_SIGN(x)) get2comp(z);

    return bignorm(z);
}