In Files

  • numeric.c

Fixnum

A Fixnum holds Integer values that can be represented in a native machine word (minus 1 bit). If any operation on a Fixnum exceeds this range, the value is automatically converted to a Bignum.

Fixnum objects have immediate value. This means that when they are assigned or passed as parameters, the actual object is passed, rather than a reference to that object. Assignment does not alias Fixnum objects. There is effectively only one Fixnum object instance for any given integer value, so, for example, you cannot add a singleton method to a Fixnum.

Public Instance Methods

fix % other => Numeric click to toggle source

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

 
               static VALUE
fix_mod(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        long mod;

        fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
        return LONG2NUM(mod);
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        x = rb_int2big(FIX2LONG(x));
        return rb_big_modulo(x, y);
      case T_FLOAT:
        {
            double mod;

            flodivmod((double)FIX2LONG(x), RFLOAT_VALUE(y), 0, &mod);
            return DBL2NUM(mod);
        }
      default:
        return rb_num_coerce_bin(x, y, '%');
    }
}
            
fix & other => integer click to toggle source

Bitwise AND.

 
               static VALUE
fix_and(VALUE x, VALUE y)
{
    long val;

    if (!FIXNUM_P(y = bit_coerce(y))) {
        return rb_big_and(y, x);
    }
    val = FIX2LONG(x) & FIX2LONG(y);
    return LONG2NUM(val);
}
            
fix * numeric => numeric_result click to toggle source

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

 
               static VALUE
fix_mul(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
#ifdef __HP_cc
/* avoids an optimization bug of HP aC++/ANSI C B3910B A.06.05 [Jul 25 2005] */
        volatile
#endif
        long a, b;
#if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
        LONG_LONG d;
#else
        long c;
        VALUE r;
#endif

        a = FIX2LONG(x);
        b = FIX2LONG(y);

#if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
        d = (LONG_LONG)a * b;
        if (FIXABLE(d)) return LONG2FIX(d);
        return rb_ll2inum(d);
#else
        if (FIT_SQRT_LONG(a) && FIT_SQRT_LONG(b))
            return LONG2FIX(a*b);
        c = a * b;
        r = LONG2FIX(c);

        if (a == 0) return x;
        if (FIX2LONG(r) != c || c/a != b) {
            r = rb_big_mul(rb_int2big(a), rb_int2big(b));
        }
        return r;
#endif
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return rb_big_mul(y, x);
      case T_FLOAT:
        return DBL2NUM((double)FIX2LONG(x) * RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '*');
    }
}
            
fix ** other => Numeric click to toggle source

Raises fix to the other power, which may be negative or fractional.

2 ** 3      #=> 8
2 ** -1     #=> 0.5
2 ** 0.5    #=> 1.4142135623731
 
               static VALUE
fix_pow(VALUE x, VALUE y)
{
    static const double zero = 0.0;
    long a = FIX2LONG(x);

    if (FIXNUM_P(y)) {
        long b = FIX2LONG(y);

        if (b < 0)
            return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);

        if (b == 0) return INT2FIX(1);
        if (b == 1) return x;
        if (a == 0) {
            if (b > 0) return INT2FIX(0);
            return DBL2NUM(1.0 / zero);
        }
        if (a == 1) return INT2FIX(1);
        if (a == -1) {
            if (b % 2 == 0)
                return INT2FIX(1);
            else 
                return INT2FIX(-1);
        }
        return int_pow(a, b);
    }
    switch (TYPE(y)) {
      case T_BIGNUM:

        if (rb_funcall(y, '<', 1, INT2FIX(0)))
            return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);

        if (a == 0) return INT2FIX(0);
        if (a == 1) return INT2FIX(1);
        if (a == -1) {
            if (int_even_p(y)) return INT2FIX(1);
            else return INT2FIX(-1);
        }
        x = rb_int2big(FIX2LONG(x));
        return rb_big_pow(x, y);
      case T_FLOAT:
        if (RFLOAT_VALUE(y) == 0.0) return DBL2NUM(1.0);
        if (a == 0) {
            return DBL2NUM(RFLOAT_VALUE(y) < 0 ? (1.0 / zero) : 0.0);
        }
        if (a == 1) return DBL2NUM(1.0);
        return DBL2NUM(pow((double)a, RFLOAT_VALUE(y)));
      default:
        return rb_num_coerce_bin(x, y, rb_intern("**"));
    }
}
            
fix + numeric => numeric_result click to toggle source

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

 
               static VALUE
fix_plus(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        long a, b, c;
        VALUE r;

        a = FIX2LONG(x);
        b = FIX2LONG(y);
        c = a + b;
        r = LONG2NUM(c);

        return r;
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return rb_big_plus(y, x);
      case T_FLOAT:
        return DBL2NUM((double)FIX2LONG(x) + RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '+');
    }
}
            
fix - numeric => numeric_result click to toggle source

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

 
               static VALUE
fix_minus(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        long a, b, c;
        VALUE r;

        a = FIX2LONG(x);
        b = FIX2LONG(y);
        c = a - b;
        r = LONG2NUM(c);

        return r;
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        x = rb_int2big(FIX2LONG(x));
        return rb_big_minus(x, y);
      case T_FLOAT:
        return DBL2NUM((double)FIX2LONG(x) - RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, '-');
    }
}
            
-fix => integer click to toggle source

Negates fix (which might return a Bignum).

 
               static VALUE
fix_uminus(VALUE num)
{
    return LONG2NUM(-FIX2LONG(num));
}
            
fix / numeric => numeric_result 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.

 
               static VALUE
fix_div(VALUE x, VALUE y)
{
    return fix_divide(x, y, '/');
}
            
fix < other => true or false click to toggle source

Returns true if the value of fix is less than that of other.

 
               static VALUE
fix_lt(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        if (FIX2LONG(x) < FIX2LONG(y)) return Qtrue;
        return Qfalse;
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) < 0 ? Qtrue : Qfalse;
      case T_FLOAT:
        return (double)FIX2LONG(x) < RFLOAT_VALUE(y) ? Qtrue : Qfalse;
      default:
        return rb_num_coerce_relop(x, y, '<');
    }
}
            
fix << count => integer click to toggle source

Shifts fix left count positions (right if count is negative).

 
               static VALUE
rb_fix_lshift(VALUE x, VALUE y)
{
    long val, width;

    val = NUM2LONG(x);
    if (!FIXNUM_P(y))
        return rb_big_lshift(rb_int2big(val), y);
    width = FIX2LONG(y);
    if (width < 0)
        return fix_rshift(val, (unsigned long)-width);
    return fix_lshift(val, width);
}
            
fix <= other => true or false click to toggle source

Returns true if the value of fix is less than or equal to that of other.

 
               static VALUE
fix_le(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        if (FIX2LONG(x) <= FIX2LONG(y)) return Qtrue;
        return Qfalse;
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) <= 0 ? Qtrue : Qfalse;
      case T_FLOAT:
        return (double)FIX2LONG(x) <= RFLOAT_VALUE(y) ? Qtrue : Qfalse;
      default:
        return rb_num_coerce_relop(x, y, rb_intern("<="));
    }
}
            
fix <=> numeric => -1, 0, +1 click to toggle source

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

 
               static VALUE
fix_cmp(VALUE x, VALUE y)
{
    if (x == y) return INT2FIX(0);
    if (FIXNUM_P(y)) {
        if (FIX2LONG(x) > FIX2LONG(y)) return INT2FIX(1);
        return INT2FIX(-1);
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return rb_big_cmp(rb_int2big(FIX2LONG(x)), y);
      case T_FLOAT:
        return rb_dbl_cmp((double)FIX2LONG(x), RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
    }
}
            
fix == other click to toggle source

Return true if fix equals other numerically.

1 == 2      #=> false
1 == 1.0    #=> true
 
               static VALUE
fix_equal(VALUE x, VALUE y)
{
    if (x == y) return Qtrue;
    if (FIXNUM_P(y)) return Qfalse;
    switch (TYPE(y)) {
      case T_BIGNUM:
        return rb_big_eq(y, x);
      case T_FLOAT:
        return (double)FIX2LONG(x) == RFLOAT_VALUE(y) ? Qtrue : Qfalse;
      default:
        return num_equal(x, y);
    }
}
            
fix == other click to toggle source

Return true if fix equals other numerically.

1 == 2      #=> false
1 == 1.0    #=> true
 
               static VALUE
fix_equal(VALUE x, VALUE y)
{
    if (x == y) return Qtrue;
    if (FIXNUM_P(y)) return Qfalse;
    switch (TYPE(y)) {
      case T_BIGNUM:
        return rb_big_eq(y, x);
      case T_FLOAT:
        return (double)FIX2LONG(x) == RFLOAT_VALUE(y) ? Qtrue : Qfalse;
      default:
        return num_equal(x, y);
    }
}
            
fix > other => true or false click to toggle source

Returns true if the value of fix is greater than that of other.

 
               static VALUE
fix_gt(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        if (FIX2LONG(x) > FIX2LONG(y)) return Qtrue;
        return Qfalse;
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) > 0 ? Qtrue : Qfalse;
      case T_FLOAT:
        return (double)FIX2LONG(x) > RFLOAT_VALUE(y) ? Qtrue : Qfalse;
      default:
        return rb_num_coerce_relop(x, y, '>');
    }
}
            
fix >= other => true or false click to toggle source

Returns true if the value of fix is greater than or equal to that of other.

 
               static VALUE
fix_ge(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        if (FIX2LONG(x) >= FIX2LONG(y)) return Qtrue;
        return Qfalse;
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) >= 0 ? Qtrue : Qfalse;
      case T_FLOAT:
        return (double)FIX2LONG(x) >= RFLOAT_VALUE(y) ? Qtrue : Qfalse;
      default:
        return rb_num_coerce_relop(x, y, rb_intern(">="));
    }
}
            
fix >> count => integer click to toggle source

Shifts fix right count positions (left if count is negative).

 
               static VALUE
rb_fix_rshift(VALUE x, VALUE y)
{
    long i, val;

    val = FIX2LONG(x);
    if (!FIXNUM_P(y))
        return rb_big_rshift(rb_int2big(val), y);
    i = FIX2LONG(y);
    if (i == 0) return x;
    if (i < 0)
        return fix_lshift(val, (unsigned long)-i);
    return fix_rshift(val, i);
}
            
fix[n] => 0, 1 click to toggle source

Bit Reference—Returns the nth bit in the binary representation of fix, where fix is the least significant bit.

a = 0b11001100101010
30.downto(0) do |n| print a[n] end

produces:

0000000000000000011001100101010
 
               static VALUE
fix_aref(VALUE fix, VALUE idx)
{
    long val = FIX2LONG(fix);
    long i;

    idx = rb_to_int(idx);
    if (!FIXNUM_P(idx)) {
        idx = rb_big_norm(idx);
        if (!FIXNUM_P(idx)) {
            if (!RBIGNUM_SIGN(idx) || val >= 0)
                return INT2FIX(0);
            return INT2FIX(1);
        }
    }
    i = FIX2LONG(idx);

    if (i < 0) return INT2FIX(0);
    if (SIZEOF_LONG*CHAR_BIT-1 < i) {
        if (val < 0) return INT2FIX(1);
        return INT2FIX(0);
    }
    if (val & (1L<<i))
        return INT2FIX(1);
    return INT2FIX(0);
}
            
fix ^ other => integer click to toggle source

Bitwise EXCLUSIVE OR.

 
               static VALUE
fix_xor(VALUE x, VALUE y)
{
    long val;

    if (!FIXNUM_P(y = bit_coerce(y))) {
        return rb_big_xor(y, x);
    }
    val = FIX2LONG(x) ^ FIX2LONG(y);
    return LONG2NUM(val);
}
            
abs → aFixnum click to toggle source

Returns the absolute value of fix.

-12345.abs   #=> 12345
12345.abs    #=> 12345
 
               static VALUE
fix_abs(VALUE fix)
{
    long i = FIX2LONG(fix);

    if (i < 0) i = -i;

    return LONG2NUM(i);
}
            
div(numeric) => numeric_result click to toggle source

Performs integer division: returns integer value.

 
               static VALUE
fix_idiv(VALUE x, VALUE y)
{
    return fix_divide(x, y, rb_intern("div"));
}
            
divmod(numeric) => array click to toggle source

See Numeric#divmod.

 
               static VALUE
fix_divmod(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        long div, mod;

        fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, &mod);

        return rb_assoc_new(LONG2NUM(div), LONG2NUM(mod));
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        x = rb_int2big(FIX2LONG(x));
        return rb_big_divmod(x, y);
      case T_FLOAT:
        {
            double div, mod;
            volatile VALUE a, b;

            flodivmod((double)FIX2LONG(x), RFLOAT_VALUE(y), &div, &mod);
            a = dbl2ival(div);
            b = DBL2NUM(mod);
            return rb_assoc_new(a, b);
        }
      default:
        return rb_num_coerce_bin(x, y, rb_intern("divmod"));
    }
}
            
even? → true or false click to toggle source

Returns true if fix is an even number.

 
               static VALUE
fix_even_p(VALUE num)
{
    if (num & 2) {
        return Qfalse;
    }
    return Qtrue;
}
            
fdiv(numeric) => float click to toggle source

Returns the floating point result of dividing fix by numeric.

654321.fdiv(13731)      #=> 47.6528293642124
654321.fdiv(13731.24)   #=> 47.6519964693647
 
               static VALUE
fix_fdiv(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        return DBL2NUM((double)FIX2LONG(x) / (double)FIX2LONG(y));
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        return DBL2NUM((double)FIX2LONG(x) / rb_big2dbl(y));
      case T_FLOAT:
        return DBL2NUM((double)FIX2LONG(x) / RFLOAT_VALUE(y));
      default:
        return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
    }
}
            
abs → aFixnum click to toggle source

Returns the absolute value of fix.

-12345.abs   #=> 12345
12345.abs    #=> 12345
 
               static VALUE
fix_abs(VALUE fix)
{
    long i = FIX2LONG(fix);

    if (i < 0) i = -i;

    return LONG2NUM(i);
}
            
modulo(other) => Numeric click to toggle source

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

 
               static VALUE
fix_mod(VALUE x, VALUE y)
{
    if (FIXNUM_P(y)) {
        long mod;

        fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
        return LONG2NUM(mod);
    }
    switch (TYPE(y)) {
      case T_BIGNUM:
        x = rb_int2big(FIX2LONG(x));
        return rb_big_modulo(x, y);
      case T_FLOAT:
        {
            double mod;

            flodivmod((double)FIX2LONG(x), RFLOAT_VALUE(y), 0, &mod);
            return DBL2NUM(mod);
        }
      default:
        return rb_num_coerce_bin(x, y, '%');
    }
}
            
odd? → true or false click to toggle source

Returns true if fix is an odd number.

 
               static VALUE
fix_odd_p(VALUE num)
{
    if (num & 2) {
        return Qtrue;
    }
    return Qfalse;
}
            
size → fixnum click to toggle source

Returns the number of bytes in the machine representation of a Fixnum.

1.size            #=> 4
-1.size           #=> 4
2147483647.size   #=> 4
 
               static VALUE
fix_size(VALUE fix)
{
    return INT2FIX(sizeof(long));
}
            
next => integer click to toggle source
succ => integer

Returns the Integer equal to int + 1.

1.next      #=> 2
(-1).next   #=> 0
 
               static VALUE
fix_succ(VALUE num)
{
    long i = FIX2LONG(num) + 1;
    return LONG2NUM(i);
}
            
to_f → float click to toggle source

Converts fix to a Float.

 
               static VALUE
fix_to_f(VALUE num)
{
    double val;

    val = (double)FIX2LONG(num);

    return DBL2NUM(val);
}
            
to_s( base=10 ) → aString click to toggle source

Returns a string containing the representation of fix radix base (between 2 and 36).

12345.to_s       #=> "12345"
12345.to_s(2)    #=> "11000000111001"
12345.to_s(8)    #=> "30071"
12345.to_s(10)   #=> "12345"
12345.to_s(16)   #=> "3039"
12345.to_s(36)   #=> "9ix"
 
               static VALUE
fix_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_fix2str(x, base);
}
            
zero? => true or false click to toggle source

Returns true if fix is zero.

 
               static VALUE
fix_zero_p(VALUE num)
{
    if (FIX2LONG(num) == 0) {
        return Qtrue;
    }
    return Qfalse;
}
            
fix | other => integer click to toggle source

Bitwise OR.

 
               static VALUE
fix_or(VALUE x, VALUE y)
{
    long val;

    if (!FIXNUM_P(y = bit_coerce(y))) {
        return rb_big_or(y, x);
    }
    val = FIX2LONG(x) | FIX2LONG(y);
    return LONG2NUM(val);
}
            
~fix => integer click to toggle source

One's complement: returns a number where each bit is flipped.

 
               static VALUE
fix_rev(VALUE num)
{
    long val = FIX2LONG(num);

    val = ~val;
    return LONG2NUM(val);
}