Class: Bignum
Overview
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.
Instance Method Summary collapse
-
#% ⇒ Object
Returns big modulo other.
-
#&(numeric) ⇒ Integer
Performs bitwise
and
between big and numeric. -
#*(other) ⇒ Numeric
Multiplies big and other, returning the result.
-
#**(exponent) ⇒ Numeric
Raises big to the exponent power (which may be an integer, float, or anything that will coerce to a number).
-
#+(other) ⇒ Numeric
Adds big and other, returning the result.
-
#-(other) ⇒ Numeric
Subtracts other from big, returning the result.
-
#- ⇒ Integer
Unary minus (returns an integer whose value is 0-big).
-
#/(other) ⇒ Numeric
Performs division: the class of the resulting object depends on the class of
numeric
and on the magnitude of the result. -
#<(real) ⇒ Boolean
Returns
true
if the value ofbig
is less than that ofreal
. -
#<<(numeric) ⇒ Integer
Shifts big left numeric positions (right if numeric is negative).
-
#<=(real) ⇒ Boolean
Returns
true
if the value ofbig
is less than or equal to that ofreal
. -
#<=>(numeric) ⇒ -1, ...
Comparison---Returns -1, 0, or +1 depending on whether big is less than, equal to, or greater than numeric.
-
#==(obj) ⇒ Boolean
Returns
true
only if obj has the same value as big. -
#==(obj) ⇒ Boolean
Returns
true
only if obj has the same value as big. -
#>(real) ⇒ Boolean
Returns
true
if the value ofbig
is greater than that ofreal
. -
#>=(real) ⇒ Boolean
Returns
true
if the value ofbig
is greater than or equal to that ofreal
. -
#>>(numeric) ⇒ Integer
Shifts big right numeric positions (left if numeric is negative).
-
#[](n) ⇒ 0, 1
Bit Reference---Returns the nth bit in the (assumed) binary representation of big, where big[0] is the least significant bit.
-
#^(numeric) ⇒ Integer
Performs bitwise exclusive or between big and numeric.
-
#abs ⇒ Bignum
Returns the absolute value of big.
-
#coerce ⇒ Object
MISSING: documentation.
-
#div(other) ⇒ Integer
Performs integer division: returns integer value.
-
#divmod(numeric) ⇒ Array
See
Numeric#divmod
. -
#eql?(obj) ⇒ Boolean
Returns
true
only if obj is aBignum
with the same value as big. -
#even? ⇒ Boolean
Returns
true
if big is an even number. -
#fdiv(numeric) ⇒ Float
Returns the floating point result of dividing big by numeric.
-
#hash ⇒ Fixnum
Compute a hash based on the value of big.
-
#abs ⇒ Bignum
Returns the absolute value of big.
-
#modulo ⇒ Object
Returns big modulo other.
-
#odd? ⇒ Boolean
Returns
true
if big is an odd number. -
#remainder(numeric) ⇒ Numeric
Returns the remainder after dividing big by numeric.
-
#size ⇒ Integer
Returns the number of bytes in the machine representation of big.
-
#to_f ⇒ Float
Converts big to a
Float
. -
#to_s(base = 10) ⇒ String
Returns a string containing the representation of big radix base (2 through 36).
-
#|(numeric) ⇒ Integer
Performs bitwise
or
between big and numeric. -
#~ ⇒ Integer
Inverts the bits in big.
Methods inherited from Integer
#ceil, #chr, #denominator, #downto, #floor, #gcd, #gcdlcm, #integer?, #lcm, #next, #numerator, #ord, #pred, #rationalize, #round, #succ, #times, #to_i, #to_int, #to_r, #truncate, #upto
Methods inherited from Numeric
#+@, #abs2, #angle, #arg, #ceil, #conj, #conjugate, #denominator, #floor, #i, #imag, #imaginary, #initialize_copy, #integer?, #nonzero?, #numerator, #phase, #polar, #quo, #real, #real?, #rect, #rectangular, #round, #singleton_method_added, #step, #to_c, #to_int, #truncate, #zero?
Methods included from Comparable
Instance Method Details
#%(other) ⇒ Numeric #modulo(other) ⇒ Numeric
Returns big modulo other. See Numeric.divmod for more information.
|
# File 'bignum.c'
/*
* call-seq:
* big % other -> Numeric
* big.modulo(other) -> Numeric
*
* 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);
}
|
#&(numeric) ⇒ Integer
Performs bitwise and
between big and numeric.
|
# File 'bignum.c'
/*
* call-seq:
* big & numeric -> integer
*
* 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;
x = xx;
y = bit_coerce(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);
}
|
#*(other) ⇒ Numeric
Multiplies big and other, returning the result.
|
# File 'bignum.c'
/*
* call-seq:
* big * other -> Numeric
*
* 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));
}
|
#**(exponent) ⇒ Numeric
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
|
# File 'bignum.c'
/*
* call-seq:
* big ** exponent -> numeric
*
* 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 BIGLEN_LIMIT = 1024*1024 / SIZEOF_BDIGITS;
if ((RBIGNUM_LEN(x) > BIGLEN_LIMIT) ||
(RBIGNUM_LEN(x) > BIGLEN_LIMIT / yy)) {
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));
}
|
#+(other) ⇒ Numeric
Adds big and other, returning the result.
|
# File 'bignum.c'
/*
* call-seq:
* big + other -> Numeric
*
* 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, '+');
}
}
|
#-(other) ⇒ Numeric
Subtracts other from big, returning the result.
|
# File 'bignum.c'
/*
* call-seq:
* big - other -> Numeric
*
* 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, '-');
}
}
|
#- ⇒ Integer
Unary minus (returns an integer whose value is 0-big)
|
# File 'bignum.c'
/*
* call-seq:
* -big -> integer
*
* Unary minus (returns an integer whose value is 0-big)
*/
static VALUE
rb_big_uminus(VALUE x)
{
VALUE z = rb_big_clone(x);
RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(x));
return bignorm(z);
}
|
#/(other) ⇒ Numeric
Performs division: the class of the resulting object depends on the class of numeric
and on the magnitude of the result.
|
# File 'bignum.c'
/*
* call-seq:
* big / other -> Numeric
*
* Performs division: the class of the resulting object depends on
* the class of <code>numeric</code> and on the magnitude of the
* result.
*/
VALUE
rb_big_div(VALUE x, VALUE y)
{
return rb_big_divide(x, y, '/');
}
|
#<(real) ⇒ Boolean
Returns true
if the value of big
is less than that of real
.
|
# File 'bignum.c'
/*
* call-seq:
* big < real -> true or false
*
* Returns <code>true</code> if the value of <code>big</code> is
* less than that of <code>real</code>.
*/
static VALUE
big_lt(VALUE x, VALUE y)
{
return big_op(x, y, 2);
}
|
#<<(numeric) ⇒ Integer
Shifts big left numeric positions (right if numeric is negative).
|
# File 'bignum.c'
/*
* call-seq:
* big << numeric -> integer
*
* 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 (TYPE(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);
}
|
#<=(real) ⇒ Boolean
Returns true
if the value of big
is less than or equal to that of real
.
|
# File 'bignum.c'
/*
* call-seq:
* big <= real -> true or false
*
* Returns <code>true</code> if the value of <code>big</code> is
* less than or equal to that of <code>real</code>.
*/
static VALUE
big_le(VALUE x, VALUE y)
{
return big_op(x, y, 3);
}
|
#<=>(numeric) ⇒ -1, ...
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
.
|
# File 'bignum.c'
/*
* call-seq:
* big <=> numeric -> -1, 0, +1 or nil
*
* Comparison---Returns -1, 0, or +1 depending on whether <i>big</i> is
* less than, equal to, or greater than <i>numeric</i>. This is the
* basis for the tests in <code>Comparable</code>.
*
*/
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:
{
double a = RFLOAT_VALUE(y);
if (isinf(a)) {
if (a > 0.0) return INT2FIX(-1);
else return INT2FIX(1);
}
return rb_dbl_cmp(rb_big2dbl(x), a);
}
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));
}
|
#==(obj) ⇒ Boolean
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
|
# File 'bignum.c'
/*
* call-seq:
* big == obj -> true or false
*
* Returns <code>true</code> only if <i>obj</i> has the same value
* as <i>big</i>. Contrast this with <code>Bignum#eql?</code>, which
* requires <i>obj</i> to be a <code>Bignum</code>.
*
* 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:
{
volatile double a, b;
a = RFLOAT_VALUE(y);
if (isnan(a)) return Qfalse;
b = rb_big2dbl(x);
return (a == b)?Qtrue:Qfalse;
}
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;
}
|
#==(obj) ⇒ Boolean
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
|
# File 'bignum.c'
/*
* call-seq:
* big == obj -> true or false
*
* Returns <code>true</code> only if <i>obj</i> has the same value
* as <i>big</i>. Contrast this with <code>Bignum#eql?</code>, which
* requires <i>obj</i> to be a <code>Bignum</code>.
*
* 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:
{
volatile double a, b;
a = RFLOAT_VALUE(y);
if (isnan(a)) return Qfalse;
b = rb_big2dbl(x);
return (a == b)?Qtrue:Qfalse;
}
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;
}
|
#>(real) ⇒ Boolean
Returns true
if the value of big
is greater than that of real
.
|
# File 'bignum.c'
/*
* call-seq:
* big > real -> true or false
*
* Returns <code>true</code> if the value of <code>big</code> is
* greater than that of <code>real</code>.
*/
static VALUE
big_gt(VALUE x, VALUE y)
{
return big_op(x, y, 0);
}
|
#>=(real) ⇒ Boolean
Returns true
if the value of big
is greater than or equal to that of real
.
|
# File 'bignum.c'
/*
* call-seq:
* big >= real -> true or false
*
* Returns <code>true</code> if the value of <code>big</code> is
* greater than or equal to that of <code>real</code>.
*/
static VALUE
big_ge(VALUE x, VALUE y)
{
return big_op(x, y, 1);
}
|
#>>(numeric) ⇒ Integer
Shifts big right numeric positions (left if numeric is negative).
|
# File 'bignum.c'
/*
* call-seq:
* big >> numeric -> integer
*
* 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 (TYPE(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);
}
|
#[](n) ⇒ 0, 1
Bit Reference---Returns the nth bit in the (assumed) binary representation of big, where big[0] is the least significant bit.
a = 9**15
50.downto(0) do |n|
print a[n]
end
produces:
000101110110100000111000011110010100111100010111001
|
# File 'bignum.c'
/*
* call-seq:
* big[n] -> 0, 1
*
* Bit Reference---Returns the <em>n</em>th bit in the (assumed) binary
* representation of <i>big</i>, where <i>big</i>[0] is the least
* significant bit.
*
* a = 9**15
* 50.downto(0) do |n|
* print a[n]
* end
*
* <em>produces:</em>
*
* 000101110110100000111000011110010100111100010111001
*
*/
static VALUE
rb_big_aref(VALUE x, VALUE y)
{
BDIGIT *xds;
BDIGIT_DBL num;
VALUE shift;
long i, s1, s2;
if (TYPE(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);
}
|
#^(numeric) ⇒ Integer
Performs bitwise exclusive or between big and numeric.
|
# File 'bignum.c'
/*
* call-seq:
* big ^ numeric -> integer
*
* 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;
x = xx;
y = bit_coerce(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 ⇒ Bignum
Returns the absolute value of big.
-1234567890987654321.abs #=> 1234567890987654321
|
# File 'bignum.c'
/*
* call-seq:
* big.abs -> aBignum
*
* Returns the absolute value of <i>big</i>.
*
* -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 ⇒ Object
MISSING: documentation
|
# File 'bignum.c'
/*
* MISSING: documentation
*/
static VALUE
rb_big_coerce(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
return rb_assoc_new(rb_int2big(FIX2LONG(y)), x);
}
else if (TYPE(y) == T_BIGNUM) {
return rb_assoc_new(y, x);
}
else {
rb_raise(rb_eTypeError, "can't coerce %s to Bignum",
rb_obj_classname(y));
}
/* not reached */
return Qnil;
}
|
#div(other) ⇒ Integer
Performs integer division: returns integer value.
|
# File 'bignum.c'
/*
* call-seq:
* big.div(other) -> integer
*
* 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
See Numeric#divmod
.
|
# File 'bignum.c'
/*
* call-seq:
* big.divmod(numeric) -> array
*
* See <code>Numeric#divmod</code>.
*
*/
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) ⇒ Boolean
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
|
# File 'bignum.c'
/*
* call-seq:
* big.eql?(obj) -> true or false
*
* Returns <code>true</code> only if <i>obj</i> is a
* <code>Bignum</code> with the same value as <i>big</i>. Contrast this
* with <code>Bignum#==</code>, which performs type conversions.
*
* 68719476736.eql?(68719476736.0) #=> false
*/
static VALUE
rb_big_eql(VALUE x, VALUE y)
{
if (TYPE(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? ⇒ Boolean
Returns true
if big is an even number.
|
# File 'bignum.c'
/*
* call-seq:
* big.even? -> true or false
*
* Returns <code>true</code> if <i>big</i> is an even number.
*/
static VALUE
rb_big_even_p(VALUE num)
{
if (BDIGITS(num)[0] & 1) {
return Qfalse;
}
return Qtrue;
}
|
#fdiv(numeric) ⇒ Float
Returns the floating point result of dividing big by numeric.
-1234567890987654321.fdiv(13731) #=> -89910996357705.5
-1234567890987654321.fdiv(13731.24) #=> -89909424858035.7
|
# File 'bignum.c'
/*
* call-seq:
* big.fdiv(numeric) -> float
*
* Returns the floating point result of dividing <i>big</i> by
* <i>numeric</i>.
*
* -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
Compute a hash based on the value of big.
|
# File 'bignum.c'
/*
* call-seq:
* big.hash -> fixnum
*
* 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);
}
|
#abs ⇒ Bignum
Returns the absolute value of big.
-1234567890987654321.abs #=> 1234567890987654321
|
# File 'bignum.c'
/*
* call-seq:
* big.abs -> aBignum
*
* Returns the absolute value of <i>big</i>.
*
* -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;
}
|
#%(other) ⇒ Numeric #modulo(other) ⇒ Numeric
Returns big modulo other. See Numeric.divmod for more information.
|
# File 'bignum.c'
/*
* call-seq:
* big % other -> Numeric
* big.modulo(other) -> Numeric
*
* 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? ⇒ Boolean
Returns true
if big is an odd number.
|
# File 'bignum.c'
/*
* call-seq:
* big.odd? -> true or false
*
* Returns <code>true</code> if <i>big</i> is an odd number.
*/
static VALUE
rb_big_odd_p(VALUE num)
{
if (BDIGITS(num)[0] & 1) {
return Qtrue;
}
return Qfalse;
}
|
#remainder(numeric) ⇒ Numeric
Returns the remainder after dividing big by numeric.
-1234567890987654321.remainder(13731) #=> -6966
-1234567890987654321.remainder(13731.24) #=> -9906.22531493148
|
# File 'bignum.c'
/*
* call-seq:
* big.remainder(numeric) -> number
*
* Returns the remainder after dividing <i>big</i> by <i>numeric</i>.
*
* -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
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
|
# File 'bignum.c'
/*
* call-seq:
* big.size -> integer
*
* Returns the number of bytes in the machine representation of
* <i>big</i>.
*
* (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
Converts big to a Float
. If big doesn't fit in a Float
, the result is infinity.
|
# File 'bignum.c'
/*
* call-seq:
* big.to_f -> float
*
* Converts <i>big</i> to a <code>Float</code>. If <i>big</i> doesn't
* fit in a <code>Float</code>, the result is infinity.
*
*/
static VALUE
rb_big_to_f(VALUE x)
{
return DBL2NUM(rb_big2dbl(x));
}
|
#to_s(base = 10) ⇒ String
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"
|
# File 'bignum.c'
/*
* call-seq:
* big.to_s(base=10) -> string
*
* Returns a string containing the representation of <i>big</i> radix
* <i>base</i> (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);
}
|
#|(numeric) ⇒ Integer
Performs bitwise or
between big and numeric.
|
# File 'bignum.c'
/*
* call-seq:
* big | numeric -> integer
*
* 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;
x = xx;
y = bit_coerce(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);
}
|
#~ ⇒ Integer
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"
|
# File 'bignum.c'
/*
* call-seq:
* ~big -> integer
*
* 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);
}
|