iyi

Standard library, 0.18.0

std/big

Arbitrary precision numbers: BigInt, BigDecimal, BigRational and BigFloat.

import std/big to use it. Source: src/std/big.iyi at v0.18.0.

Everything here is iyi all the way down: no GMP, no libc, no lib (SPEC.md III.9, III.10). The module refuses what it cannot answer with a sentence and exits 1: division and modulo by zero, a negative exponent, a base outside 2..36, a digit the base does not have, a value that does not fit the integer asked for.

BigInt is sign-magnitude:

@sign : Int32          -1 negative, 0 zero, 1 positive
@limbs : Array(UInt64) little-endian 32-bit digits, no leading zeros

Each limb holds 32 bits in a 64-bit word so that a 32x32 product plus two carries still fits the word; the canonical form (zero is sign 0 with no limbs) makes equality a limb-by-limb comparison.

Algorithms: schoolbook add/sub; schoolbook multiply below 64 limbs and Karatsuba above; single-limb short division, one pass for a quotient of one limb, or Knuth's Algorithm D (TAOCP 4.3.1); binary square-and-multiply for **; Montgomery multiplication on 64-bit words with a sliding window for pow_mod modulo an odd number, a fixed window that reads its whole table for pow_mod_secret, square-and-multiply modulo an even one; two's complement over infinite sign extension for & | ^ ~ << >>. // truncates toward zero and % takes the dividend's sign, the prelude's Int32 rule. hash mixes every limb with wrapping arithmetic, so any size hashes.

BigDecimal is value * 10^-scale with an exact BigInt value. + - * are exact. / is the one operation that can be inexact: div(other, precision) answers the quotient rounded half away from zero to precision fractional digits, and an exact quotient is answered with the fewest digits that write it (1/4 is 0.25, 6/3 is 2); a / b is a.div(b, DIVISION_PRECISION) with 20 fractional digits. == and hash agree: 1.10 == 1.1 and both hash alike. Zero prints as 0 whatever its scale.

BigRational is a reduced numerator/denominator pair with a positive denominator; every operation reduces, so == and hash are structural.

BigFloat is a binary float of any precision, ±mantissa · 2^exponent with the mantissa exactly precision bits, each result rounded once to the nearest, ties to even, from its exact value (see BigFloat).

BigDecimalstruct

std/bigiyi doc src/std/big.iyi
pub struct BigDecimal
  def !=(other : BigDecimal) : Bool
  def %(other : BigDecimal) : BigDecimal
  def *(other : BigDecimal) : BigDecimal
  def *(other : Int32 | Int64) : BigDecimal
  def +(other : BigDecimal) : BigDecimal
  def +(other : Int32 | Int64) : BigDecimal
  def + : BigDecimal
  def -(other : BigDecimal) : BigDecimal
  def -(other : Int32 | Int64) : BigDecimal
  def - : BigDecimal
  def /(other : BigDecimal) : BigDecimal
  def /(other : Int32 | Int64) : BigDecimal
  def //(other : BigDecimal) : BigDecimal
  def abs : BigDecimal
  protected def self.align(a : BigDecimal, b : BigDecimal) : Tuple(BigInt, BigInt, Int32)
  # `self / other` rounded to `precision` fractional digits, half away from
  # zero. A quotient that is exact within `precision` digits is answered with
  # the fewest digits that write it: `1/4` is `0.25`, `6/3` is `2`. One that
  # is not keeps all `precision` digits, so the reader sees where it was cut.
  def div(other : BigDecimal, precision : Int32) : BigDecimal
  # The same value at another scale is the same key: `1.10`, `1.1` and
  # `11e-1` hash alike because `==` says they are equal. The digits without
  # their trailing zeros and the exponent that goes with them name the value;
  # multiplying a negative scale out made `1e1000000.hash` take 2.6 s.
  def hash : Int32
  def initialize(value : BigInt, scale : Int32 = 0)
  def initialize(num : Int32 = 0, scale : Int32 = 0)
  def initialize(num : Int64, scale : Int32 = 0)
  # Parses `[+-]digits[.digits][e[+-]digits]`; anything else is refused.
  def initialize(str : String)
  def inspect : String
  # Bounds on the place of the leading digit, from the limb count alone:
  # 10^(lo - 1) <= |self| < 10^hi. 30102 and 30103 in 100,000 bracket
  # log10(2) for each 32-bit limb.
  protected def magnitude_bounds : Tuple(Int64, Int64)
  def negate : BigDecimal
  def negative? : Bool
  # The same value with the smallest non-negative scale: trailing zeros of
  # the fraction are dropped and a negative scale is multiplied out.
  def normalized : BigDecimal
  def positive? : Bool
  def scale : Int32
  # The value without its trailing zeros, at most `limit` of them, and how
  # many went. Counted once in the digits and divided out once: one divmod
  # by ten per zero was quadratic, and the hash of `1.` and 40,000 zeros, or
  # `3.div(3, 40000)`, took 725 ms. A value that does not end in zero is
  # answered by one division by ten, without printing it.
  protected def strip_zeros(limit : Int32) : Tuple(BigInt, Int32)
  def to_big_d : BigDecimal
  def to_big_i : BigInt
  def to_f : Float64
  def to_f64 : Float64
  def to_i32 : Int32
  def to_i64 : Int64
  # Zero is `0` whatever its scale; every other value prints every digit of
  # its scale, so `1.10` stays `1.10`.
  def to_s : String
  def value : BigInt
  def zero? : Bool
end

BigFloatstruct

A binary floating-point number of any precision: ±mantissa · 2^exponent, the mantissa exactly precision bits long (128 unless asked), every result rounded once, to the nearest value of that many bits, ties to even

  • the rounding IEEE 754 gives a double, at any width. The other library's

BigFloat is GMP's mpf, which truncates and keeps more bits than it was asked for; this one answers what MPFR does.

  a = BigFloat.new(2, 256)
  a.sqrt.to_s
  # => "1.4142135623730950488016887242096980785696718753769480731766797379907324784621"
  BigFloat.new("0.1", 24).to_f64   # => 0.10000000149011612

An operation between two answers at the larger precision; with an integer, at the BigFloat's. to_s writes the fewest decimal digits that read back to the same value at its precision, positional from 1e-4 to below 1e15 and with an exponent outside, as Float64#to_s writes. There is no NaN or infinity: dividing by zero, the square root of a negative number, a NaN or an infinite double, a precision under 1 and a string that is no number are refused.

std/bigiyi doc src/std/big.iyi
pub struct BigFloat
  def *(other : BigFloat) : BigFloat
  def *(other : Int32 | Int64 | BigInt) : BigFloat
  # The power, its exact value rounded once; a negative exponent is the
  # reciprocal of the power, rounded once.
  def **(exponent : Int32) : BigFloat
  def +(other : BigFloat) : BigFloat
  def +(other : Int32 | Int64 | BigInt) : BigFloat
  def + : BigFloat
  def -(other : BigFloat) : BigFloat
  def -(other : Int32 | Int64 | BigInt) : BigFloat
  def - : BigFloat
  def /(other : BigFloat) : BigFloat
  def /(other : Int32 | Int64 | BigInt) : BigFloat
  def ==(other : BigFloat) : Bool
  def abs : BigFloat
  def ceil : BigFloat
  protected def self.check(precision : Int32) : Nil
  # An integer at exactly the bits it has.
  protected def self.exactly(value : Int32 | Int64 | BigInt) : BigFloat
  protected def exponent : Int64
  def floor : BigFloat
  # Equal values hash alike whatever their precision: the mantissa without
  # its trailing zero bits.
  def hash : Int32
  def initialize(negative : Bool, mantissa : BigInt, exponent : Int64, precision : Int32)
  def inspect : String
  # The largest integer whose square is at most *value*, by Newton's
  # method from above.
  protected def self.isqrt(value : BigInt) : BigInt
  protected def mantissa : BigInt
  def negative? : Bool
  def self.new(value : Int32, precision : Int32 = DEFAULT_PRECISION) : BigFloat
  def self.new(value : Int64, precision : Int32 = DEFAULT_PRECISION) : BigFloat
  def self.new(value : BigInt, precision : Int32 = DEFAULT_PRECISION) : BigFloat
  # The double's exact value, rounded to *precision* bits.
  def self.new(value : Float64, precision : Int32 = DEFAULT_PRECISION) : BigFloat
  def self.new(value : BigRational, precision : Int32 = DEFAULT_PRECISION) : BigFloat
  def self.new(value : BigDecimal, precision : Int32 = DEFAULT_PRECISION) : BigFloat
  # A decimal - `-12.5`, `1e-30`, `6.02214076E23` - rounded to *precision*
  # bits; anything else is refused.
  def self.new(text : String, precision : Int32 = DEFAULT_PRECISION) : BigFloat
  # As `new`, nil for a string that is no number.
  def self.parse?(text : String, precision : Int32 = DEFAULT_PRECISION) : BigFloat | ::Nil
  # *digits* with its first digit at 10^*point*, as `Float64#to_s` puts
  # a point: positional from 10^-4 to 10^14, an exponent outside.
  protected def self.place(digits : String, point : Int64) : String
  def positive? : Bool
  def precision : Int32
  # Under one half is zero; from there the fraction is at most
  # *precision* bits, compared with one half exactly.
  def round : BigFloat
  # *num*/*den* · 2^*shift* (both non-negative, *den* not zero), rounded to
  # *precision* bits, ties to even: every value here is made by this, from
  # an exact one.
  protected def self.rounded(negative : Bool, num : BigInt, den : BigInt, shift : Int64, precision : Int32) : BigFloat
  # The square root, rounded once. The mantissa is widened to at least
  # 2·precision + 4 bits over an even power of two, so the integer root
  # has two bits past the ones kept, and a root that is not exact carries a
  # half below its last bit into the rounding, which no tie can be.
  def sqrt : BigFloat
  # The exact sum, rounded once. An addend more than *precision* + 2 bits
  # below the other cannot move it - it is under a quarter of the larger's
  # last place, even where that place halves below a power of two - and
  # is not shifted out to a size it would only be rounded away from.
  protected def sum(other : BigFloat, precision : Int32) : BigFloat
  # Toward zero, floor, ceiling, and to the nearest integer, ties to even.
  def to_big_i : BigInt
  # The exact value as a fraction.
  def to_big_r : BigRational
  # The double nearest, ties to even; past the largest double, infinite,
  # and below the smallest, zero.
  def to_f64 : Float64
  # The fewest decimal digits that read back as this value at its
  # precision, the nearest such when there are two; written as
  # `Float64#to_s` writes a double.
  def to_s : String
  # The place above the leading bit: 2^(top - 1) <= |self| < 2^top.
  protected def top : Int64
  def trunc : BigFloat
  protected def trunc_whole : BigInt
  # This value at another precision, rounded if it is fewer bits.
  def with_precision(bits : Int32) : BigFloat
  def zero? : Bool
end

BigIntstruct

std/bigiyi doc src/std/big.iyi
pub struct BigInt
  # Three-way comparison is `<=>`, from `impl Comparable` below.
  def !=(other : BigInt) : Bool
  def !=(other : Int64) : Bool
  def !=(other : Int32) : Bool
  def %(other : BigInt) : BigInt
  def %(other : Int64) : BigInt
  def %(other : Int32) : BigInt
  # Bitwise AND (&) with two's complement semantics
  def &(other : BigInt) : BigInt
  # Multiplication
  def *(other : BigInt) : BigInt
  def *(other : Int64) : BigInt
  def *(other : Int32) : BigInt
  # Exponentiation by squaring: a ** exp
  def **(exp : Int32) : BigInt
  def **(exp : Int64) : BigInt
  def **(exp : BigInt) : BigInt
  # Addition
  def +(other : BigInt) : BigInt
  def +(other : Int64) : BigInt
  def +(other : Int32) : BigInt
  def + : BigInt
  # Subtraction: the sum with the other's sign turned, without copying it.
  def -(other : BigInt) : BigInt
  def -(other : Int64) : BigInt
  def -(other : Int32) : BigInt
  def - : BigInt
  def //(other : BigInt) : BigInt
  def //(other : Int64) : BigInt
  def //(other : Int32) : BigInt
  def <(other : Int64) : Bool
  def <(other : Int32) : Bool
  # Bitwise Left Shift: a << count
  def <<(count : Int32) : BigInt
  def <=(other : Int64) : Bool
  def <=(other : Int32) : Bool
  # Comparison overloads for Int64 and Int32
  def <=>(other : Int64) : Int32
  def <=>(other : Int32) : Int32
  def ==(other : Int64) : Bool
  def ==(other : Int32) : Bool
  def >(other : Int64) : Bool
  def >(other : Int32) : Bool
  def >=(other : Int64) : Bool
  def >=(other : Int32) : Bool
  # Bitwise Right Shift (arithmetic): a >> count
  def >>(count : Int32) : BigInt
  # Bitwise XOR (^) with two's complement semantics
  def ^(other : BigInt) : BigInt
  # Returns the absolute value of self.
  def abs : BigInt
  def abs2 : BigInt
  # The digits of this value's magnitude, least significant first, onto
  # `sink`: exactly `width` of them when `width` is positive, zeros above.
  #
  # A long value is split by `powers[level]`, a power of the chunk about
  # half its size, and each half is written by the level below - the low
  # half to exactly the digits that power stands for, so its leading zeros
  # are kept. Dividing by one chunk at a time is a hardware division per
  # limb per nine digits, n^2 / 9 of them; the split does that only for the
  # short pieces at the bottom and multiplies its way through the rest,
  # dividing by `divmod_recursive`.
  protected def append_digits(radix : UInt64, chunk : UInt64, per : Int32, powers : Array(BigInt), level : Int32, width : Int32, sink : Array(UInt8)) : Nil
  # The bits |value| takes to write.
  protected def self.bit_length(value : BigInt) : Int32
  # `count` bits of this value, not negative, from bit `from` up, in one
  # copy.
  protected def bits(from : Int32, count : Int32) : BigInt
  # The bits one digit of a power-of-two base takes; for any other base,
  # the fewest bits a digit can carry, so that a limb's worth of bits
  # bounds how many digits it makes.
  protected def self.bits_per_digit(base : Int32) : Int32
  # Magnitude comparison: compares |self| and |other|.
  # Returns -1 if |self| < |other|, 0 if |self| == |other|, 1 if |self| > |other|.
  def cmp_abs(other : BigInt) : Int32
  protected def self.digit_byte(value : UInt64) : UInt8
  # A digit byte's value in any base up to 36, or 36 for a byte that is a
  # digit in none.
  protected def self.digit_value(byte : UInt8) : Int32
  # This value's `2n` bits and `low`'s `n` by `b`, `top` and `bottom` its
  # halves of `n` bits each.
  protected def div_three_by_two(low : BigInt, b : BigInt, top : BigInt, bottom : BigInt, n : Int32) : Tuple(BigInt, BigInt)
  # This value, under `divisor * 2^n`, by `divisor`, exactly `n` bits long
  # and `n` even until it is short enough for long division: the top
  # `n + n/2` bits by the divisor, then the remainder and the next `n/2`.
  # Each is a division by the divisor's top half, a product by its bottom
  # half, and at most two corrections, the divisor's top bit being set.
  protected def div_two_by_one(divisor : BigInt, n : Int32) : Tuple(BigInt, BigInt)
  # Division and Modulo. Returns {quotient, remainder}.
  # Division truncates towards zero; remainder follows the sign of the dividend (self).
  #
  # A long divisor and a long quotient go to `divmod_recursive`, the
  # recursive division `to_s` splits its digits with, on the magnitudes,
  # and take their signs after. Long division costs the product of the
  # quotient's length and the divisor's, and every division went to it: a
  # value twice a divisor of 524,288 bits took 282 ms in a release build
  # and one of 2,097,152 bits 4,929 ms, four times over per doubling,
  # where these take 179 and 1,964.
  def divmod(other : BigInt) : Tuple(BigInt, BigInt)
  # Knuth's Algorithm D, with the signs `divmod` gives.
  protected def divmod_long(other : BigInt) : Tuple(BigInt, BigInt)
  # |self| divided by |other|, two limbs or more, for a quotient under
  # 2^32: *shift* is the divisor's bit length less 32, and |self| over
  # 2^shift, A, fits 63 bits. With B the divisor's top 32 bits, the
  # quotient is estimated as A / (B + 1), which is never more than the
  # quotient and short of it by less than A / B^2 + 1, at most three; a - q
  # b is taken in one pass and the divisor taken off what is left while it
  # is not below it.
  protected def divmod_one_limb(other : BigInt, shift : Int32, q_sign : Int32, r_sign : Int32) : Tuple(BigInt, BigInt)
  # The quotient and remainder of this value, not negative, by `divisor`,
  # positive, for the time a few products of half the length take: long
  # division costs the product of the two lengths, and the split print
  # divides by a power half as long as the value, so `to_s` was quadratic -
  # 787 ms for 381,698 digits and 3,107 ms for twice as many. Burnikel and
  # Ziegler's recursive division, in the form Python's `_pylong` writes it,
  # by bits. A value past twice the divisor's length has its top divided
  # first, as long division takes a digit at a time; the rest is shifted so
  # that the divisor's length halves evenly down to where long division is
  # the faster, and the remainder shifted back.
  protected def divmod_recursive(divisor : BigInt) : Tuple(BigInt, BigInt)
  # Returns true if this number is even.
  def even? : Bool
  # The big-endian *bytes* as a non-negative BigInt: a key, a signature, a
  # coordinate as cryptography writes them. Four bytes a limb, the low
  # limb from the last four.
  def self.from_bytes(bytes : Array(UInt8)) : BigInt
  # The value of `digits`, most significant first, in `base`: the inverse
  # of `to_s(base)`, and built the same way. A power-of-two base packs the
  # digits' bits into limbs directly. Any other splits the digits at a
  # power of the chunk (`append_digits`), so that the halves meet in one
  # Karatsuba product each, and runs the short pieces at the bottom through
  # one multiply-add per chunk in place. This had shifted or multiplied a
  # whole new BigInt per digit - per nine digits in decimal - and 80,000
  # hex digits took more than a second.
  protected def self.from_digits(digits : Array(UInt8), base : Int32) : BigInt
  # Parses a hexadecimal string (with or without '0x' prefix).
  def self.from_hex(str : String) : BigInt
  # Greatest Common Divisor (Euclidean algorithm)
  def gcd(other : BigInt) : BigInt
  def gcd(other : Int64) : BigInt
  def gcd(other : Int32) : BigInt
  # FNV-1a over the sign and every limb, folded to 31 bits. Wrapping
  # multiplication (`&*`) is the point: a checked product would overflow on
  # the second limb, and a hash has to answer for any size.
  def hash : Int32
  # Raw constructor from sign and limbs. Trims leading zero limbs to enforce
  # the canonical representation invariant: zero has empty limbs and sign 0.
  def initialize(sign : Int32, limbs : Array(UInt64))
  # Least Common Multiple
  def lcm(other : BigInt) : BigInt
  def lcm(other : Int64) : BigInt
  def lcm(other : Int32) : BigInt
  def limbs : Array(UInt64)
  # Whether the *n* limbs at *r* are at least the *m* at *v*.
  protected def self.limbs_at_least(r : Pointer(UInt64), n : Int32, v : Pointer(UInt64), m : Int32) : Bool
  # Returns the negated value of self (-self).
  def negate : BigInt
  # Returns true if this number is strictly negative (< 0).
  def negative? : Bool
  # Constructs a BigInt from an Int64.
  def self.new(val : Int64) : BigInt
  # Constructs a BigInt from an Int32.
  def self.new(val : Int32) : BigInt
  # Parses a BigInt from a string in the given base (2..36, default 10).
  # Supports leading whitespace, optional sign ('+' or '-'), and base prefixes
  # (0x/0X for hex, 0b/0B for binary, 0o/0O for octal).
  def self.new(str : String, base : Int32 = 10) : BigInt
  # Returns true if this number is odd.
  def odd? : Bool
  # Parses a string with full error checking.
  def self.parse(str : String, base : Int32 = 10) : BigInt
  # Returns true if this number is strictly positive (> 0).
  def positive? : Bool
  # Modular exponentiation: (self ** exp) % mod, in 0...mod whatever the
  # base's sign. An odd modulus, which is every modulus RSA, Diffie-Hellman
  # and DSA work in, goes to `Montgomery` with a sliding window; an even one
  # keeps square-and-multiply with a division per step.
  #
  # Each step here was a product and a long division of twice the
  # modulus' length, and a 2048-bit modulus with a 2048-bit exponent took
  # 19.0 ms in a --release build where Python 3.14's `pow` took 13.3 (3072
  # bits: 63.2 and 42.3, 4096: 168.7 and 100.3). Montgomery's takes 2.5 ms,
  # 8.5 and 20.6 in the run of bench/std_big_exercise.sh that measured
  # Python at 13.7, 45.4 and 102.1, which prints these each run.
  def pow_mod(exp : BigInt, mod : BigInt) : BigInt
  def pow_mod(exp : Int64, mod : Int64) : BigInt
  def pow_mod(exp : Int32, mod : Int32) : BigInt
  # `pow_mod` for an exponent that is a secret, a private key's: a fixed
  # window, every entry of its table read for each window and the one
  # wanted kept by a mask, so neither a branch nor a memory address depends
  # on the exponent's bits, and as many windows as the longer of the
  # exponent and the modulus takes, so the exponent's length does not show
  # either. The modulus has to be odd (a Montgomery modulus): an even one
  # is a misuse, refused.
  #
  # What it does not hide: the base is reduced by `%`, whose time depends
  # on the base and the modulus, so a caller with a secret base (RSA's
  # CRT halves of a message) blinds it first, as std/rsa's signing does.
  def pow_mod_secret(exp : BigInt, mod : BigInt) : BigInt
  def sign : Int32
  # Number of limbs currently allocated.
  def size : Int32
  def to_big : BigInt
  def to_big_d : BigDecimal
  def to_big_i : BigInt
  def to_big_r : BigRational
  # The value big-endian in exactly *size* bytes, zeros in front: the
  # inverse of `from_bytes` at a fixed width, which is how a signature or a
  # coordinate is written. Nil for a negative value or one that does not
  # fit, never a value cut short.
  def to_bytes(size : Int32) : Array(UInt8) | ::Nil
  def to_i : Int32
  # Converts to Int32, raising an overflow error if the value exceeds Int32 range.
  def to_i32 : Int32
  # Converts to Int32 if the value fits, or nil if it overflows.
  def to_i32? : Int32 | ::Nil
  # Converts to Int64, raising an overflow error if the value exceeds Int64 range.
  def to_i64 : Int64
  # Converts to Int64 if the value fits, or nil if it overflows.
  def to_i64? : Int64 | ::Nil
  # Converts this BigInt to a string in the given base (default 10).
  # Bases 2..36 supported. Digits above 9 are lowercase 'a'..'z'.
  #
  # The digits are gathered least significant first and written into the
  # string once. A base that is a power of two reads them straight off the
  # limbs' bits; any other divides a copy of the limbs in place by the
  # largest power of the base a limb holds - 10^9 for decimal - and takes
  # that many digits from each remainder. This had built the text with
  # `res = res + s`, a copy of everything so far per chunk, and divided by
  # a fresh one-limb BigInt per chunk, or per digit outside bases 2, 10
  # and 16: 3 ** 400000 took a second in decimal and in binary, and nine
  # and a half in base 7.
  def to_s(base : Int32) : String
  def to_s : String
  # Helper: bitwise magnitude operation with sign inversion
  protected def twos_mag : BigInt
  # The value of `count` digits from `from`: the high part times the power
  # of the chunk that the low part's digits stand for, plus the low part.
  protected def self.value_of_digits(digits : Array(UInt8), from : Int32, count : Int32, base : UInt64, per : Int32, powers : Array(BigInt)) : BigInt
  # |value| over 2^shift, for one under 2^64: the limbs from bit *shift*.
  protected def self.window(limbs : Array(UInt64), shift : Int32) : UInt64
  # Returns true if this number is zero.
  def zero? : Bool
  # Bitwise OR (|) with two's complement semantics
  def |(other : BigInt) : BigInt
  # Bitwise NOT (~a = -a - 1 in two's complement)
  def ~ : BigInt
end

BigRationalstruct

std/bigiyi doc src/std/big.iyi
pub struct BigRational
  def !=(other : BigRational) : Bool
  def *(other : BigRational) : BigRational
  def *(other : Int32 | Int64 | BigInt) : BigRational
  def **(exp : Int32) : BigRational
  def +(other : BigRational) : BigRational
  def +(other : Int32 | Int64 | BigInt) : BigRational
  def + : BigRational
  def -(other : BigRational) : BigRational
  def -(other : Int32 | Int64 | BigInt) : BigRational
  def - : BigRational
  def /(other : BigRational) : BigRational
  def /(other : Int32 | Int64 | BigInt) : BigRational
  def abs : BigRational
  def denominator : BigInt
  # A rational is stored reduced, so equal values have equal parts.
  def hash : Int32
  def initialize(numerator : BigInt, denominator : BigInt)
  def initialize(num : Int64 = 0_i64, den : Int64 = 1_i64)
  def initialize(num : Int32, den : Int32 = 1)
  def initialize(str : String)
  def inspect : String
  def inv : BigRational
  def negate : BigRational
  def negative? : Bool
  def numerator : BigInt
  def positive? : Bool
  def to_big_d : BigDecimal
  def to_big_i : BigInt
  def to_big_r : BigRational
  # The Float64 nearest this value, ties to even, as python's
  # `float(Fraction)` answers. This had gone through `to_big_d`, twenty
  # fractional digits: every value under 5e-21 was 0.0 and every one under
  # 1e-3 lost significant digits. The quotient is taken to 55 or 56 bits -
  # 55 at the smallest exponent, where the subnormals start - with a sticky
  # low bit for a nonzero remainder, rounded to the bits a Float64 keeps (53,
  # fewer as a subnormal), and scaled by the power of two it was shifted by,
  # which is exact: a value past the largest Float64 is Infinity.
  def to_f64 : Float64
  def to_s : String
  def zero? : Bool
end

Std::Traits::Comparable for BigIntimpl

std/bigiyi doc src/std/big.iyi
impl Std::Traits::Comparable for BigInt
  def <=>(other : self) : Int32
end

Std::Traits::Num for BigIntimpl

std/bigiyi doc src/std/big.iyi
impl Std::Traits::Num for BigInt
  def self.zero : self
  def self.one : self
  def add(other : self) : self
  def mul(other : self) : self
end

Std::Traits::Hashable for BigIntimpl

std/bigiyi doc src/std/big.iyi
impl Std::Traits::Hashable for BigInt
  def hash_key : Int32
end

Std::Traits::Comparable for BigDecimalimpl

std/bigiyi doc src/std/big.iyi
impl Std::Traits::Comparable for BigDecimal
  def <=>(other : self) : Int32
end

Std::Traits::Num for BigDecimalimpl

std/bigiyi doc src/std/big.iyi
impl Std::Traits::Num for BigDecimal
  def self.zero : self
  def self.one : self
  def add(other : self) : self
  def mul(other : self) : self
end

Std::Traits::Hashable for BigDecimalimpl

std/bigiyi doc src/std/big.iyi
impl Std::Traits::Hashable for BigDecimal
  def hash_key : Int32
end

Std::Traits::Comparable for BigRationalimpl

std/bigiyi doc src/std/big.iyi
impl Std::Traits::Comparable for BigRational
  def <=>(other : self) : Int32
end

Std::Traits::Num for BigRationalimpl

std/bigiyi doc src/std/big.iyi
impl Std::Traits::Num for BigRational
  def self.zero : self
  def self.one : self
  def add(other : self) : self
  def mul(other : self) : self
end

Std::Traits::Hashable for BigRationalimpl

std/bigiyi doc src/std/big.iyi
impl Std::Traits::Hashable for BigRational
  def hash_key : Int32
end

Std::Traits::Comparable for BigFloatimpl

std/bigiyi doc src/std/big.iyi
impl Std::Traits::Comparable for BigFloat
  def <=>(other : self) : Int32
end

Std::Traits::Hashable for BigFloatimpl

std/bigiyi doc src/std/big.iyi
impl Std::Traits::Hashable for BigFloat
  def hash_key : Int32
end

Int32struct, reopened

std/bigiyi doc src/std/big.iyi
struct ::Int32
  def *(other : Std::Big::BigInt) : Std::Big::BigInt
  def +(other : Std::Big::BigInt) : Std::Big::BigInt
  def -(other : Std::Big::BigInt) : Std::Big::BigInt
  def <=>(other : Std::Big::BigInt) : Int32
  def ==(other : Std::Big::BigInt) : Bool
  def to_big : Std::Big::BigInt
  def to_big_d : Std::Big::BigDecimal
  def to_big_i : Std::Big::BigInt
  def to_big_r : Std::Big::BigRational
end

Int64struct, reopened

std/bigiyi doc src/std/big.iyi
struct ::Int64
  def *(other : Std::Big::BigInt) : Std::Big::BigInt
  def +(other : Std::Big::BigInt) : Std::Big::BigInt
  def -(other : Std::Big::BigInt) : Std::Big::BigInt
  def <=>(other : Std::Big::BigInt) : Int32
  def ==(other : Std::Big::BigInt) : Bool
  def to_big : Std::Big::BigInt
  def to_big_d : Std::Big::BigDecimal
  def to_big_i : Std::Big::BigInt
  def to_big_r : Std::Big::BigRational
end

Stringclass, reopened

std/bigiyi doc src/std/big.iyi
class ::String
  def to_big_d : Std::Big::BigDecimal
  def to_big_i : Std::Big::BigInt
  def to_big_r : Std::Big::BigRational
end