Open-Source Wikis

/

Ruby

/

Core classes

/

Numerics

ruby/ruby

Numerics

Ruby's numeric tower: NumericIntegerFixnum/Bignum, Float, Rational, Complex. Each has its own C file plus tightly-integrated arithmetic in numeric.c.

Files

File Purpose
numeric.c Numeric, Float, Integer (Fixnum half), shared arithmetic. ~171 KB.
numeric.rb A few Numeric methods in Ruby.
bignum.c The arbitrary-precision integer (Bignum) implementation. ~193 KB.
rational.c Exact-fraction Rational and the GCD machinery. ~70 KB.
complex.c Complex numbers. ~76 KB.
math.c The Math module — sin, cos, log, sqrt.
random.c The Random class and Kernel#rand. ~52 KB.
siphash.c / siphash.h SipHash for non-cryptographic hashing in Hash.

Integer

Integer covers two distinct internal types unified at the language level:

Fixnum

A small integer encoded directly in the VALUE bits:

| 63        ...        2 | 1 | 0 |
| <signed integer>       | x | 1 |

The low bit is set (so it's distinguishable from heap pointers, which are aligned to at least 4 bytes). This gives 63-bit signed integers on 64-bit systems, 31-bit on 32-bit systems. Operations are direct CPU integer operations with overflow checks.

numeric.c::fix_plus, fix_minus, fix_mul etc. are the per-operation handlers. The compiler emits opt_plus/opt_minus/etc. to bypass full method dispatch when both operands are Fixnum.

Bignum

When a Fixnum operation overflows, the result is promoted to a Bignum:

struct RBignum {
    struct RBasic basic;
    long len;
    BDIGIT *digits;             /* sign + magnitude in BDIGIT-sized limbs */
};

bignum.c implements arbitrary-precision arithmetic — addition, subtraction, multiplication (Karatsuba above a threshold), division, modulo, GCD, modular exponentiation. The implementation is hand-tuned C and competes with libraries like GMP for the operations Ruby cares about.

Bignums are silently promoted to Fixnums when they shrink to fit; the VM never exposes the distinction to user code.

Float

Float is IEEE 754 double-precision (64-bit). On most platforms, a Float is a heap object:

struct RFloat {
    struct RBasic basic;
    double float_value;
};

On platforms with the Flonum optimisation (most 64-bit platforms), Floats are encoded directly in the VALUE bits — no heap allocation:

| 63        ...        2 | 1 | 0 |
| <packed double>        | 0 | 1 | 0 |

The Flonum encoding reuses 62 bits of the double's representation, sacrificing a bit of mantissa precision. RB_FLONUM_P(v) tests for it. Most numeric code is Flonum-aware via macros that pack/unpack.

Float arithmetic in Ruby goes through the standard IEEE 754 ops via numeric.c::flo_plus, flo_lt, etc. Special values: Float::INFINITY, Float::NAN, Float::MAX, Float::EPSILON.

Rational

A fraction of two integers (numerator / denominator), kept in lowest terms:

struct RRational {
    struct RBasic basic;
    VALUE num;     /* an Integer */
    VALUE den;     /* a positive Integer */
};

rational.c::r_gcd computes GCD via the Euclidean algorithm. Construction (Rational(a, b)) reduces immediately.

Arithmetic on Rationals stays exact: Rational(1, 3) + Rational(1, 6) == Rational(1, 2). Mixed Rational/Integer arithmetic stays Rational; Rational/Float promotes to Float (at the cost of precision).

The literal syntax 1r produces Rational(1, 1).

Complex

struct RComplex {
    struct RBasic basic;
    VALUE real;
    VALUE imag;
};

Complex(a, b) = a + bi. The fields can be any Numeric — Integer, Float, or even Rational. complex.c defines the arithmetic in the obvious way.

The literal syntax 1+2i is Complex(1, 2).

Math module

math.c defines Math.sin, Math.cos, Math.log, Math.sqrt, Math.atan2, Math.hypot, etc. Each is a thin wrapper over the C standard library's math functions, with NaN/range checks.

Math::PI and Math::E are computed at boot.

For arbitrary-precision math (Bignum exponents, Rational **), the routines in bignum.c and rational.c take over.

Random

random.c implements Random — a Mersenne Twister-based PRNG:

r = Random.new(42)
r.rand     # 0.0..1.0
r.rand(10) # 0..9
r.bytes(8) # 8 random bytes

Per-process and per-Ractor default RNGs are seeded at startup from /dev/urandom (or the OS equivalent). Random::DEFAULT is the per-Ractor default.

SecureRandom (in lib/securerandom.rb) uses OpenSSL or getrandom(2) for cryptographic randomness.

Coercion

When an arithmetic operation receives a non-matching pair of operands, Ruby calls coerce:

1 + Rational(1, 2)
# Integer#+ doesn't know what to do with Rational
# → calls Rational#coerce(1) → returns [Rational(1), Rational(1, 2)]
# → arithmetic proceeds on the coerced pair

numeric.c::num_coerce is the universal Numeric#coerce fallback. User-defined Numeric subclasses override it.

Performance notes

  • Fixnum arithmetic is constant time and inlined by the JIT. Most int-heavy hot paths stay in Fixnum.
  • Bignum arithmetic scales with the number of limbs. Karatsuba kicks in around 100 limbs.
  • Float arithmetic under Flonum is also inlined.
  • Rational/Complex are heap objects and slower; appropriate for cases where exactness matters.

Common pitfalls

  • Integer division truncates: 7 / 2 == 3. Use Rational(7, 2) or Float(7) / 2 for non-truncating.
  • 0.1 + 0.2 != 0.3: standard IEEE 754 behaviour. Use BigDecimal (in bigdecimal gem) for decimal arithmetic.
  • Math.sqrt(-1): returns NaN, not Complex. Math is float-only; use CMath for Complex-aware math.
  • Random per-Ractor: seeded independently per Ractor; reproducible output requires explicit seeding.

Entry points for modification

  • New Numeric method: add to the relevant file (numeric.c/bignum.c/rational.c/complex.c) and register in Init_*.
  • Performance: profile under YJIT; coercion paths are usually the bottleneck for mixed-type arithmetic.
  • New literal syntax: parser change in parse.y and prism/, then ensure the literal lowers to the right Numeric subclass.

See systems/compiler.md for opt_plus/opt_minus opcode specialisation and systems/vm.md for Fixnum/Float fast paths.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Numerics – Ruby wiki | Factory