Class: Bignum

Inherits:
Integer show all
Defined in:
bignum.c

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

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

#[email protected], #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

#between?

Instance Method Details

#%(other) ⇒ Numeric #modulo(other) ⇒ Numeric

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

Overloads:


2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
# File 'bignum.c', line 2928

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.

Returns:


3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
# File 'bignum.c', line 3255

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

#*(other) ⇒ Numeric

Multiplies big and other, returning the result.

Returns:


2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
# File 'bignum.c', line 2636

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

Returns:


3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
# File 'bignum.c', line 3151

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

#+(other) ⇒ Numeric

Adds big and other, returning the result.

Returns:


2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
# File 'bignum.c', line 2007

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.

Returns:


2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
# File 'bignum.c', line 2044

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)

Returns:


1730
1731
1732
1733
1734
1735
1736
1737
1738
# File 'bignum.c', line 1730

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.

Returns:


2900
2901
2902
2903
2904
# File 'bignum.c', line 2900

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.

Returns:

  • (Boolean)

1651
1652
1653
1654
1655
# File 'bignum.c', line 1651

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).

Returns:


3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
# File 'bignum.c', line 3520

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

#<=(real) ⇒ Boolean

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

Returns:

  • (Boolean)

1665
1666
1667
1668
1669
# File 'bignum.c', line 1665

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.

Returns:

  • (-1, 0, +1, nil)

1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
# File 'bignum.c', line 1529

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

#==(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

Returns:

  • (Boolean)

1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
# File 'bignum.c', line 1682

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;
}

#==(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

Returns:

  • (Boolean)

1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
# File 'bignum.c', line 1682

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;
}

#>(real) ⇒ Boolean

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

Returns:

  • (Boolean)

1623
1624
1625
1626
1627
# File 'bignum.c', line 1623

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.

Returns:

  • (Boolean)

1637
1638
1639
1640
1641
# File 'bignum.c', line 1637

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).

Returns:


3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
# File 'bignum.c', line 3584

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

#[](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

Returns:

  • (0, 1)

3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
# File 'bignum.c', line 3681

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

#^(numeric) ⇒ Integer

Performs bitwise exclusive or between big and numeric.

Returns:


3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
# File 'bignum.c', line 3446

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

#absBignum

Returns the absolute value of big.

-1234567890987654321.abs   #=> 1234567890987654321

Returns:


3765
3766
3767
3768
3769
3770
3771
3772
3773
# File 'bignum.c', line 3765

static VALUE
rb_big_abs(VALUE x)
{
    if (!RBIGNUM_SIGN(x)) {
	x = rb_big_clone(x);
	RBIGNUM_SET_SIGN(x, 1);
    }
    return x;
}

#coerceObject

MISSING: documentation


3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
# File 'bignum.c', line 3743

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

Performs integer division: returns integer value.

Returns:


2913
2914
2915
2916
2917
# File 'bignum.c', line 2913

VALUE
rb_big_idiv(VALUE x, VALUE y)
{
    return rb_big_divide(x, y, rb_intern("div"));
}

#divmod(numeric) ⇒ Array

See Numeric#divmod.

Returns:


2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
# File 'bignum.c', line 2986

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

Returns:

  • (Boolean)

Returns:

  • (Boolean)

1713
1714
1715
1716
1717
1718
1719
1720
1721
# File 'bignum.c', line 1713

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?Boolean

Returns true if big is an even number.

Returns:

  • (Boolean)

Returns:

  • (Boolean)

3816
3817
3818
3819
3820
3821
3822
3823
# File 'bignum.c', line 3816

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

Returns:


3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
# File 'bignum.c', line 3099

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

#hashFixnum

Compute a hash based on the value of big.

Returns:


3730
3731
3732
3733
3734
3735
3736
3737
# File 'bignum.c', line 3730

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

#absBignum

Returns the absolute value of big.

-1234567890987654321.abs   #=> 1234567890987654321

Returns:


3765
3766
3767
3768
3769
3770
3771
3772
3773
# File 'bignum.c', line 3765

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.

Overloads:


2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
# File 'bignum.c', line 2928

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.

Returns:

  • (Boolean)

Returns:

  • (Boolean)

3800
3801
3802
3803
3804
3805
3806
3807
# File 'bignum.c', line 3800

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

Returns:


2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
# File 'bignum.c', line 2958

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

#sizeInteger

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

Returns:


3787
3788
3789
3790
3791
# File 'bignum.c', line 3787

static VALUE
rb_big_size(VALUE big)
{
    return LONG2FIX(RBIGNUM_LEN(big)*SIZEOF_BDIGITS);
}

#to_fFloat

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

Returns:


1431
1432
1433
1434
1435
# File 'bignum.c', line 1431

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"

Returns:


1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
# File 'bignum.c', line 1174

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.

Returns:


3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
# File 'bignum.c', line 3351

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

#~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"

Returns:


1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
# File 'bignum.c', line 1752

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