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.
Constant Summary collapse
- GMP_VERSION =
rb_sprintf("GMP %s", gmp_version)
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 thannumeric
. -
#==(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 ⇒ Object
Returns the absolute value of big.
-
#bit_length ⇒ Integer
Returns the number of bits of the value of int.
-
#coerce(numeric) ⇒ Array
Returns an array with both a
numeric
and abig
represented as Bignum objects. -
#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.
-
#magnitude ⇒ Object
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
(also: #inspect)
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.
6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 |
# File 'bignum.c', line 6188
VALUE
rb_big_modulo(VALUE x, VALUE y)
{
VALUE z;
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
else if (!RB_BIGNUM_TYPE_P(y)) {
return rb_num_coerce_bin(x, y, '%');
}
bigdivmod(x, y, 0, &z);
return bignorm(z);
}
|
#&(numeric) ⇒ Integer
Performs bitwise and
between big and numeric.
6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 |
# File 'bignum.c', line 6478
VALUE
rb_big_and(VALUE x, VALUE y)
{
VALUE z;
BDIGIT *ds1, *ds2, *zds;
long i, xn, yn, n1, n2;
BDIGIT hibitsx, hibitsy;
BDIGIT hibits1, hibits2;
VALUE tmpv;
BDIGIT tmph;
long tmpn;
if (!FIXNUM_P(y) && !RB_BIGNUM_TYPE_P(y)) {
return rb_num_coerce_bit(x, y, '&');
}
hibitsx = abs2twocomp(&x, &xn);
if (FIXNUM_P(y)) {
return bigand_int(x, xn, hibitsx, FIX2LONG(y));
}
hibitsy = abs2twocomp(&y, &yn);
if (xn > yn) {
tmpv = x; x = y; y = tmpv;
tmpn = xn; xn = yn; yn = tmpn;
tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
}
n1 = xn;
n2 = yn;
ds1 = BDIGITS(x);
ds2 = BDIGITS(y);
hibits1 = hibitsx;
hibits2 = hibitsy;
if (!hibits1)
n2 = n1;
z = bignew(n2, 0);
zds = BDIGITS(z);
for (i=0; i<n1; i++) {
zds[i] = ds1[i] & ds2[i];
}
for (; i<n2; i++) {
zds[i] = hibits1 & ds2[i];
}
twocomp2abs_bang(z, hibits1 && hibits2);
RB_GC_GUARD(x);
RB_GC_GUARD(y);
return bignorm(z);
}
|
#*(other) ⇒ Numeric
Multiplies big and other, returning the result.
5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 |
# File 'bignum.c', line 5996
VALUE
rb_big_mul(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
else if (RB_BIGNUM_TYPE_P(y)) {
}
else if (RB_FLOAT_TYPE_P(y)) {
return DBL2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));
}
else {
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
6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 |
# File 'bignum.c', line 6362
VALUE
rb_big_pow(VALUE x, VALUE y)
{
double d;
SIGNED_VALUE yy;
again:
if (y == INT2FIX(0)) return INT2FIX(1);
if (RB_FLOAT_TYPE_P(y)) {
d = RFLOAT_VALUE(y);
if ((!RBIGNUM_SIGN(x) && !BIGZEROP(x)) && d != round(d))
return rb_funcall(rb_complex_raw1(x), rb_intern("**"), 1, y);
}
else if (RB_BIGNUM_TYPE_P(y)) {
y = bignorm(y);
if (FIXNUM_P(y))
goto again;
rb_warn("in a**b, b may be too big");
d = rb_big2dbl(y);
}
else if (FIXNUM_P(y)) {
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 size_t xbits = rb_absint_numwords(x, 1, NULL);
const size_t BIGLEN_LIMIT = 32*1024*1024;
if (xbits == (size_t)-1 ||
(xbits > BIGLEN_LIMIT) ||
(xbits * yy > BIGLEN_LIMIT)) {
rb_warn("in a**b, b may be too big");
d = (double)yy;
}
else {
for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
if (z) z = bigsq(z);
if (yy & mask) {
z = z ? bigtrunc(bigmul0(z, x)) : x;
}
}
return bignorm(z);
}
}
}
else {
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.
5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 |
# File 'bignum.c', line 5866
VALUE
rb_big_plus(VALUE x, VALUE y)
{
long n;
if (FIXNUM_P(y)) {
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);
}
else if (RB_BIGNUM_TYPE_P(y)) {
return bignorm(bigadd(x, y, 1));
}
else if (RB_FLOAT_TYPE_P(y)) {
return DBL2NUM(rb_big2dbl(x) + RFLOAT_VALUE(y));
}
else {
return rb_num_coerce_bin(x, y, '+');
}
}
|
#-(other) ⇒ Numeric
Subtracts other from big, returning the result.
5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 |
# File 'bignum.c', line 5902
VALUE
rb_big_minus(VALUE x, VALUE y)
{
long n;
if (FIXNUM_P(y)) {
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);
}
else if (RB_BIGNUM_TYPE_P(y)) {
return bignorm(bigadd(x, y, 0));
}
else if (RB_FLOAT_TYPE_P(y)) {
return DBL2NUM(rb_big2dbl(x) - RFLOAT_VALUE(y));
}
else {
return rb_num_coerce_bin(x, y, '-');
}
}
|
#- ⇒ Integer
Unary minus (returns an integer whose value is 0-big)
5577 5578 5579 5580 5581 5582 5583 5584 5585 |
# File 'bignum.c', line 5577
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.
6160 6161 6162 6163 6164 |
# File 'bignum.c', line 6160
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
.
5497 5498 5499 5500 5501 |
# File 'bignum.c', line 5497
static VALUE
big_lt(VALUE x, VALUE y)
{
return big_op(x, y, big_op_lt);
}
|
#<<(numeric) ⇒ Integer
Shifts big left numeric positions (right if numeric is negative).
6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 |
# File 'bignum.c', line 6759
VALUE
rb_big_lshift(VALUE x, VALUE y)
{
int lshift_p;
size_t shift_numdigits;
int shift_numbits;
for (;;) {
if (FIXNUM_P(y)) {
long l = FIX2LONG(y);
unsigned long shift;
if (0 <= l) {
lshift_p = 1;
shift = l;
}
else {
lshift_p = 0;
shift = 1+(unsigned long)(-(l+1));
}
shift_numbits = (int)(shift & (BITSPERDIG-1));
shift_numdigits = shift >> bit_length(BITSPERDIG-1);
return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
}
else if (RB_BIGNUM_TYPE_P(y)) {
return bignorm(big_shift2(x, 1, y));
}
y = rb_to_int(y);
}
}
|
#<=(real) ⇒ Boolean
Returns true
if the value of big
is less than or equal to that of real
.
5511 5512 5513 5514 5515 |
# File 'bignum.c', line 5511
static VALUE
big_le(VALUE x, VALUE y)
{
return big_op(x, y, big_op_le);
}
|
#<=>(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.
nil
is returned if the two values are incomparable.
5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 |
# File 'bignum.c', line 5392
VALUE
rb_big_cmp(VALUE x, VALUE y)
{
int cmp;
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
else if (RB_BIGNUM_TYPE_P(y)) {
}
else if (RB_FLOAT_TYPE_P(y)) {
return rb_integer_float_cmp(x, y);
}
else {
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);
cmp = bary_cmp(BDIGITS(x), RBIGNUM_LEN(x), BDIGITS(y), RBIGNUM_LEN(y));
if (RBIGNUM_SIGN(x))
return INT2FIX(cmp);
else
return INT2FIX(-cmp);
}
|
#==(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
5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 |
# File 'bignum.c', line 5528
VALUE
rb_big_eq(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
if (bignorm(x) == y) return Qtrue;
y = rb_int2big(FIX2LONG(y));
}
else if (RB_BIGNUM_TYPE_P(y)) {
}
else if (RB_FLOAT_TYPE_P(y)) {
return rb_integer_float_eq(x, y);
}
else {
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
5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 |
# File 'bignum.c', line 5528
VALUE
rb_big_eq(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
if (bignorm(x) == y) return Qtrue;
y = rb_int2big(FIX2LONG(y));
}
else if (RB_BIGNUM_TYPE_P(y)) {
}
else if (RB_FLOAT_TYPE_P(y)) {
return rb_integer_float_eq(x, y);
}
else {
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
.
5469 5470 5471 5472 5473 |
# File 'bignum.c', line 5469
static VALUE
big_gt(VALUE x, VALUE y)
{
return big_op(x, y, big_op_gt);
}
|
#>=(real) ⇒ Boolean
Returns true
if the value of big
is greater than or equal to that of real
.
5483 5484 5485 5486 5487 |
# File 'bignum.c', line 5483
static VALUE
big_ge(VALUE x, VALUE y)
{
return big_op(x, y, big_op_ge);
}
|
#>>(numeric) ⇒ Integer
Shifts big right numeric positions (left if numeric is negative).
6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 |
# File 'bignum.c', line 6797
VALUE
rb_big_rshift(VALUE x, VALUE y)
{
int lshift_p;
size_t shift_numdigits;
int shift_numbits;
for (;;) {
if (FIXNUM_P(y)) {
long l = FIX2LONG(y);
unsigned long shift;
if (0 <= l) {
lshift_p = 0;
shift = l;
}
else {
lshift_p = 1;
shift = 1+(unsigned long)(-(l+1));
}
shift_numbits = (int)(shift & (BITSPERDIG-1));
shift_numdigits = shift >> bit_length(BITSPERDIG-1);
return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
}
else if (RB_BIGNUM_TYPE_P(y)) {
return bignorm(big_shift2(x, 0, y));
}
y = rb_to_int(y);
}
}
|
#[](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
6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 |
# File 'bignum.c', line 6846
static VALUE
rb_big_aref(VALUE x, VALUE y)
{
BDIGIT *xds;
unsigned long shift;
long i, s1, s2;
BDIGIT bit;
if (RB_BIGNUM_TYPE_P(y)) {
if (!RBIGNUM_SIGN(y))
return INT2FIX(0);
bigtrunc(y);
if (BIGSIZE(y) > sizeof(long)) {
out_of_range:
return RBIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
}
shift = big2ulong(y, "long");
}
else {
i = NUM2LONG(y);
if (i < 0) return INT2FIX(0);
shift = i;
}
s1 = shift/BITSPERDIG;
s2 = shift%BITSPERDIG;
bit = (BDIGIT)1 << s2;
if (s1 >= RBIGNUM_LEN(x)) goto out_of_range;
xds = BDIGITS(x);
if (RBIGNUM_POSITIVE_P(x))
return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0);
if (xds[s1] & (bit-1))
return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1);
for (i = 0; i < s1; i++)
if (xds[i])
return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1);
return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0);
}
|
#^(numeric) ⇒ Integer
Performs bitwise exclusive or between big and numeric.
6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 |
# File 'bignum.c', line 6704
VALUE
rb_big_xor(VALUE x, VALUE y)
{
VALUE z;
BDIGIT *ds1, *ds2, *zds;
long i, xn, yn, n1, n2;
BDIGIT hibitsx, hibitsy;
BDIGIT hibits1, hibits2;
VALUE tmpv;
BDIGIT tmph;
long tmpn;
if (!FIXNUM_P(y) && !RB_BIGNUM_TYPE_P(y)) {
return rb_num_coerce_bit(x, y, '^');
}
hibitsx = abs2twocomp(&x, &xn);
if (FIXNUM_P(y)) {
return bigxor_int(x, xn, hibitsx, FIX2LONG(y));
}
hibitsy = abs2twocomp(&y, &yn);
if (xn > yn) {
tmpv = x; x = y; y = tmpv;
tmpn = xn; xn = yn; yn = tmpn;
tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
}
n1 = xn;
n2 = yn;
ds1 = BDIGITS(x);
ds2 = BDIGITS(y);
hibits1 = hibitsx;
hibits2 = hibitsy;
z = bignew(n2, 0);
zds = BDIGITS(z);
for (i=0; i<n1; i++) {
zds[i] = ds1[i] ^ ds2[i];
}
for (; i<n2; i++) {
zds[i] = hibitsx ^ ds2[i];
}
twocomp2abs_bang(z, (hibits1 ^ hibits2) != 0);
RB_GC_GUARD(x);
RB_GC_GUARD(y);
return bignorm(z);
}
|
#abs ⇒ Bignum #magnitude ⇒ Bignum
Returns the absolute value of big.
-1234567890987654321.abs #=> 1234567890987654321
6939 6940 6941 6942 6943 6944 6945 6946 6947 |
# File 'bignum.c', line 6939
static VALUE
rb_big_abs(VALUE x)
{
if (!RBIGNUM_SIGN(x)) {
x = rb_big_clone(x);
RBIGNUM_SET_SIGN(x, 1);
}
return x;
}
|
#bit_length ⇒ Integer
Returns the number of bits of the value of int.
“the number of bits” means that the bit position of the highest bit which is different to the sign bit. (The bit position of the bit 2**n is n+1.) If there is no such bit (zero or minus one), zero is returned.
I.e. This method returns ceil(log2(int < 0 ? -int : int+1)).
(-2**10000-1).bit_length #=> 10001
(-2**10000).bit_length #=> 10000
(-2**10000+1).bit_length #=> 10000
(-2**1000-1).bit_length #=> 1001
(-2**1000).bit_length #=> 1000
(-2**1000+1).bit_length #=> 1000
(2**1000-1).bit_length #=> 1000
(2**1000).bit_length #=> 1001
(2**1000+1).bit_length #=> 1001
(2**10000-1).bit_length #=> 10000
(2**10000).bit_length #=> 10001
(2**10000+1).bit_length #=> 10001
6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 |
# File 'bignum.c', line 6998
static VALUE
rb_big_bit_length(VALUE big)
{
int nlz_bits;
size_t numbytes;
static const BDIGIT char_bit[1] = { CHAR_BIT };
BDIGIT numbytes_bary[bdigit_roomof(sizeof(size_t))];
BDIGIT nlz_bary[1];
BDIGIT result_bary[bdigit_roomof(sizeof(size_t)+1)];
numbytes = rb_absint_size(big, &nlz_bits);
if (numbytes == 0)
return LONG2FIX(0);
if (RBIGNUM_NEGATIVE_P(big) && rb_absint_singlebit_p(big)) {
if (nlz_bits != CHAR_BIT-1) {
nlz_bits++;
}
else {
nlz_bits = 0;
numbytes--;
}
}
if (numbytes <= SIZE_MAX / CHAR_BIT) {
return SIZET2NUM(numbytes * CHAR_BIT - nlz_bits);
}
nlz_bary[0] = nlz_bits;
bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1, sizeof(numbytes), 0,
INTEGER_PACK_NATIVE_BYTE_ORDER);
BARY_SHORT_MUL(result_bary, numbytes_bary, char_bit);
BARY_SUB(result_bary, result_bary, nlz_bary);
return rb_integer_unpack(result_bary, numberof(result_bary), sizeof(BDIGIT), 0,
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
}
|
#coerce(numeric) ⇒ Array
Returns an array with both a numeric
and a big
represented as Bignum objects.
This is achieved by converting numeric
to a Bignum.
A TypeError is raised if the numeric
is not a Fixnum or Bignum type.
(0x3FFFFFFFFFFFFFFF+1).coerce(42) #=> [42, 4611686018427387904]
6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 |
# File 'bignum.c', line 6916
static VALUE
rb_big_coerce(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
else if (!RB_BIGNUM_TYPE_P(y)) {
rb_raise(rb_eTypeError, "can't coerce %s to Bignum",
rb_obj_classname(y));
}
return rb_assoc_new(y, x);
}
|
#div(other) ⇒ Integer
Performs integer division: returns integer value.
6173 6174 6175 6176 6177 |
# File 'bignum.c', line 6173
VALUE
rb_big_idiv(VALUE x, VALUE y)
{
return rb_big_divide(x, y, rb_intern("div"));
}
|
#divmod(numeric) ⇒ Array
See Numeric#divmod
.
6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 |
# File 'bignum.c', line 6236
VALUE
rb_big_divmod(VALUE x, VALUE y)
{
VALUE div, mod;
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
else if (!RB_BIGNUM_TYPE_P(y)) {
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
5560 5561 5562 5563 5564 5565 5566 5567 5568 |
# File 'bignum.c', line 5560
VALUE
rb_big_eql(VALUE x, VALUE y)
{
if (!RB_BIGNUM_TYPE_P(y)) 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.
7062 7063 7064 7065 7066 7067 7068 7069 |
# File 'bignum.c', line 7062
static VALUE
rb_big_even_p(VALUE num)
{
if (RBIGNUM_LEN(num) != 0 && 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
6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 |
# File 'bignum.c', line 6320
VALUE
rb_big_fdiv(VALUE x, VALUE y)
{
double dx, dy;
dx = big2dbl(x);
if (FIXNUM_P(y)) {
dy = (double)FIX2LONG(y);
if (isinf(dx))
return big_fdiv_int(x, rb_int2big(FIX2LONG(y)));
}
else if (RB_BIGNUM_TYPE_P(y)) {
dy = rb_big2dbl(y);
if (isinf(dx) || isinf(dy))
return big_fdiv_int(x, y);
}
else if (RB_FLOAT_TYPE_P(y)) {
dy = RFLOAT_VALUE(y);
if (isnan(dy))
return y;
if (isinf(dx))
return big_fdiv_float(x, y);
}
else {
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.
6893 6894 6895 6896 6897 6898 6899 6900 |
# File 'bignum.c', line 6893
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 #magnitude ⇒ Bignum
Returns the absolute value of big.
-1234567890987654321.abs #=> 1234567890987654321
6939 6940 6941 6942 6943 6944 6945 6946 6947 |
# File 'bignum.c', line 6939
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.
6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 |
# File 'bignum.c', line 6188
VALUE
rb_big_modulo(VALUE x, VALUE y)
{
VALUE z;
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
else if (!RB_BIGNUM_TYPE_P(y)) {
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.
7046 7047 7048 7049 7050 7051 7052 7053 |
# File 'bignum.c', line 7046
static VALUE
rb_big_odd_p(VALUE num)
{
if (RBIGNUM_LEN(num) != 0 && 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
6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 |
# File 'bignum.c', line 6213
static VALUE
rb_big_remainder(VALUE x, VALUE y)
{
VALUE z;
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
else if (!RB_BIGNUM_TYPE_P(y)) {
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
6961 6962 6963 6964 6965 |
# File 'bignum.c', line 6961
static VALUE
rb_big_size(VALUE big)
{
return SIZET2NUM(BIGSIZE(big));
}
|
#to_f ⇒ Float
Converts big to a Float
. If big doesn’t fit in a Float
, the result is infinity.
5292 5293 5294 5295 5296 |
# File 'bignum.c', line 5292
static VALUE
rb_big_to_f(VALUE x)
{
return DBL2NUM(rb_big2dbl(x));
}
|
#to_s(base = 10) ⇒ String Also known as: inspect
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"
5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 |
# File 'bignum.c', line 5033
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.
6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 |
# File 'bignum.c', line 6604
VALUE
rb_big_or(VALUE x, VALUE y)
{
VALUE z;
BDIGIT *ds1, *ds2, *zds;
long i, xn, yn, n1, n2;
BDIGIT hibitsx, hibitsy;
BDIGIT hibits1, hibits2;
VALUE tmpv;
BDIGIT tmph;
long tmpn;
if (!FIXNUM_P(y) && !RB_BIGNUM_TYPE_P(y)) {
return rb_num_coerce_bit(x, y, '|');
}
hibitsx = abs2twocomp(&x, &xn);
if (FIXNUM_P(y)) {
return bigor_int(x, xn, hibitsx, FIX2LONG(y));
}
hibitsy = abs2twocomp(&y, &yn);
if (xn > yn) {
tmpv = x; x = y; y = tmpv;
tmpn = xn; xn = yn; yn = tmpn;
tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
}
n1 = xn;
n2 = yn;
ds1 = BDIGITS(x);
ds2 = BDIGITS(y);
hibits1 = hibitsx;
hibits2 = hibitsy;
if (hibits1)
n2 = n1;
z = bignew(n2, 0);
zds = BDIGITS(z);
for (i=0; i<n1; i++) {
zds[i] = ds1[i] | ds2[i];
}
for (; i<n2; i++) {
zds[i] = hibits1 | ds2[i];
}
twocomp2abs_bang(z, hibits1 || hibits2);
RB_GC_GUARD(x);
RB_GC_GUARD(y);
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"
5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 |
# File 'bignum.c', line 5599
static VALUE
rb_big_neg(VALUE x)
{
VALUE z = rb_big_clone(x);
BDIGIT *ds = BDIGITS(z);
long n = RBIGNUM_LEN(z);
if (!n) return INT2FIX(-1);
if (RBIGNUM_POSITIVE_P(z)) {
if (bary_add_one(ds, n)) {
big_extend_carry(z);
}
RBIGNUM_SET_NEGATIVE_SIGN(z);
}
else {
bary_neg(ds, n);
if (bary_add_one(ds, n))
return INT2FIX(-1);
bary_neg(ds, n);
RBIGNUM_SET_POSITIVE_SIGN(z);
}
return bignorm(z);
}
|