API reference

apn_mojo.rational

Rational keeps fractions exact, in lowest terms with positive denominators. See the Rational tutorial for examples and Batch for collections of fractions.

Exact fractions and their functions, one declaration per name.

Every result is in lowest terms with a positive denominator. Apply a function to batches with vmap, as in vmap[apn_mojo.rational.add]()(xs, ys).

Summary

Name Kind Summary
abs function The absolute value.
add function The exact sum; the same as left + right.
ceil function Round a Rational toward positive infinity, to an Integer (numpy's ceil).
clip function value limited to [a_min, a_max]: minimum(maximum(value, a_min), a_max) (numpy's clip), so a_max when a_min > a_max.
divide function The exact quotient; the same as left / right.
floor function Round a Rational toward negative infinity, to an Integer (numpy's floor).
gcd function The greatest common divisor of two fractions.
lcm function The least common multiple of two fractions.
maximum function The larger of two Rationals, the first when they are equal (numpy's maximum).
minimum function The smaller of two Rationals, the first when they are equal (numpy's minimum).
multiply function The exact product; the same as left * right.
pow_rational function An exact power for a signed integral exponent.
reciprocal function 1 / value, exactly (numpy's reciprocal).
root_exact function The exact n-th root of a fraction, when it has one.
round function Round a Rational to the nearest Integer, a half to the even neighbour, to an Integer (numpy's round).
stable_hash function A 64-bit hash of the value, stable across processes and releases.
subtract function The exact difference; the same as left - right.
trunc function Round a Rational toward zero, to an Integer (numpy's trunc).
Rational struct An exact fraction, always in lowest terms with a positive denominator.

Functions

abs

Source: apn_mojo/rational/math.mojo

def abs(value: Rational) raises -> Rational

The absolute value.

Arguments

  • value (Rational): The fraction.

Returns

Rational: The nonnegative magnitude.

Raises

Error: Only on a checked size error.

add

Source: apn_mojo/rational/math.mojo

def add(left: Rational, right: Rational) raises -> Rational

The exact sum; the same as left + right.

Arguments

  • left (Rational): The first operand.
  • right (Rational): The second operand.

Returns

Rational: left + right in lowest terms.

Raises

Error: Only on a checked size error.

ceil

Source: apn_mojo/rational/math.mojo

def ceil(value: Rational) raises -> Integer

Round a Rational toward positive infinity, to an Integer (numpy's ceil).

Arguments

  • value (Rational): The operand.

Returns

Integer: The smallest Integer not below the value.

Raises

Error: Only on a checked size error.

clip

Source: apn_mojo/rational/math.mojo

def clip(value: Rational, a_min: Rational, a_max: Rational) raises -> Rational

value limited to [a_min, a_max]: minimum(maximum(value, a_min), a_max) (numpy's clip), so a_max when a_min > a_max.

Arguments

  • value (Rational): The operand.
  • a_min (Rational): The lower limit.
  • a_max (Rational): The upper limit.

Returns

Rational: The limited value.

Raises

Error: Only on a checked size error.

divide

Source: apn_mojo/rational/math.mojo

def divide(left: Rational, right: Rational) raises -> Rational

The exact quotient; the same as left / right.

Arguments

  • left (Rational): The dividend.
  • right (Rational): The divisor.

Returns

Rational: left / right in lowest terms.

Raises

Error: When right is zero.

floor

Source: apn_mojo/rational/math.mojo

def floor(value: Rational) raises -> Integer

Round a Rational toward negative infinity, to an Integer (numpy's floor).

Arguments

  • value (Rational): The operand.

Returns

Integer: The largest Integer not above the value.

Raises

Error: Only on a checked size error.

gcd

Source: apn_mojo/rational/math.mojo

def gcd(a: Rational, b: Rational) raises -> Rational

The greatest common divisor of two fractions.

It is the largest fraction of which both are integer multiples: gcd(1/2, 1/3) is 1/6 and gcd(4/9, 2/5) is 2/45. In lowest terms it is gcd(numerators) / lcm(denominators), already reduced.

Arguments

  • a (Rational): The first fraction.
  • b (Rational): The second fraction.

Returns

Rational: The nonnegative gcd; gcd(0, 0) is zero.

Raises

Error: Only on a checked size error.

lcm

Source: apn_mojo/rational/math.mojo

def lcm(a: Rational, b: Rational) raises -> Rational

The least common multiple of two fractions.

It is the smallest nonnegative fraction that is an integer multiple of both: lcm(1/2, 1/3) is 1. In lowest terms it is lcm(numerators) / gcd(denominators), already reduced.

Arguments

  • a (Rational): The first fraction.
  • b (Rational): The second fraction.

Returns

Rational: The nonnegative lcm; zero when either input is zero.

Raises

Error: Only on a checked size error.

maximum

Source: apn_mojo/rational/math.mojo

def maximum(left: Rational, right: Rational) raises -> Rational

The larger of two Rationals, the first when they are equal (numpy's maximum).

Arguments

  • left (Rational): The first operand.
  • right (Rational): The second operand.

Returns

Rational: left if left >= right, else right.

Raises

Error: Only on a checked size error.

minimum

Source: apn_mojo/rational/math.mojo

def minimum(left: Rational, right: Rational) raises -> Rational

The smaller of two Rationals, the first when they are equal (numpy's minimum).

Arguments

  • left (Rational): The first operand.
  • right (Rational): The second operand.

Returns

Rational: left if left <= right, else right.

Raises

Error: Only on a checked size error.

multiply

Source: apn_mojo/rational/math.mojo

def multiply(left: Rational, right: Rational) raises -> Rational

The exact product; the same as left * right.

Arguments

  • left (Rational): The first operand.
  • right (Rational): The second operand.

Returns

Rational: left * right in lowest terms.

Raises

Error: Only on a checked size error.

pow_rational

Source: apn_mojo/rational/value.mojo

def pow_rational(base: Rational, exponent: Integer) raises -> Rational

An exact power for a signed integral exponent.

A negative exponent takes the exact reciprocal; every zero exponent, including 0 ** 0, gives one. Integer and native bases widen exactly.

Arguments

  • base (Rational): The base.
  • exponent (Integer): The exponent, of any size.

Returns

Rational: base ** exponent as a Rational, even when integral.

Raises

Error: When base is zero and exponent negative.

reciprocal

Source: apn_mojo/rational/math.mojo

def reciprocal(value: Rational) raises -> Rational

1 / value, exactly (numpy's reciprocal).

Arguments

  • value (Rational): A nonzero Rational.

Returns

Rational: The exact reciprocal.

Raises

Error: When value is zero.

root_exact

Source: apn_mojo/rational/math.mojo

def root_exact(value: Rational, n: Integer) raises -> Optional[Rational]

The exact n-th root of a fraction, when it has one.

root_exact(9/4, 2) is 3/2 and root_exact(-27/8, 3) is -3/2; root_exact(2, 2) is None. A fraction in lowest terms is a perfect power exactly when its numerator and denominator are. Through vmap it gives the roots, 0 where there is none, and a Mask of where there is one.

Arguments

  • value (Rational): The radicand; a negative one has a root only for odd n.
  • n (Integer): The degree, positive.

Returns

Optional[Rational]: The fraction r with r**n == value, or None when there is none.

Raises

Error: When n is not positive.

round

Source: apn_mojo/rational/math.mojo

def round(value: Rational) raises -> Integer

Round a Rational to the nearest Integer, a half to the even neighbour, to an Integer (numpy's round).

Arguments

  • value (Rational): The operand.

Returns

Integer: The nearest Integer: 2.5 gives 2, 3.5 gives 4 and -2.5 gives -2.

Raises

Error: Only on a checked size error.

stable_hash

Source: apn_mojo/rational/math.mojo

def stable_hash(x: Rational) -> UInt64

A 64-bit hash of the value, stable across processes and releases.

The algorithm is APNH-64: tag 2, then the numerator and the denominator in lowest terms, each encoded as an Integer. Unlike Mojo's Hasher, its output never changes, so stored hashes stay valid. Equal fractions hash equal.

Arguments

  • x (Rational): The fraction.

Returns

UInt64: The hash.

subtract

Source: apn_mojo/rational/math.mojo

def subtract(left: Rational, right: Rational) raises -> Rational

The exact difference; the same as left - right.

Arguments

  • left (Rational): The first operand.
  • right (Rational): The second operand.

Returns

Rational: left - right in lowest terms.

Raises

Error: Only on a checked size error.

trunc

Source: apn_mojo/rational/math.mojo

def trunc(value: Rational) raises -> Integer

Round a Rational toward zero, to an Integer (numpy's trunc).

Arguments

  • value (Rational): The operand.

Returns

Integer: The integer part.

Raises

Error: Only on a checked size error.

Structs

Rational

Source: apn_mojo/rational/value.mojo

struct Rational(
    Absable,
    Boolable,
    Equatable,
    Hashable,
    ImplicitlyCopyable,
    IntableRaising,
    Writable,
    _BatchElement,
)

An exact fraction, always in lowest terms with a positive denominator.

Zero is 0/1, and every result is canonical, so there is nothing to normalize. Rational(8, -12) is -2/3, and Rational("1.25e-3") is exactly 1/800: text never passes through floating point.

Operation Contract
x + y, x - y, x * y, x / y Exact; division by zero raises
x ** n Signed integral exponent; a negative power takes the reciprocal
-x, abs(x) Exact
==, !=, <, <=, >, >= Exact comparison returning Bool
Bool(x) False only for zero

Integer, native integral and literal operands mix exactly in either order; Float operands give Float. +=, -=, *=, /= and **= leave the destination unchanged when they raise. Equal values hash equally, and an integral Rational hashes like the corresponding Integer.

Limitations

A native integer cannot be the left operand of a comparison; write value > native or Rational(native) < value. Ordered comparisons can raise checked size errors, so Rational is not Comparable.

Implements

Absable, Boolable, Copyable, Equatable, Hashable, ImplicitlyCopyable, IntableRaising, Writable, _BatchElement, _MapArgument

Rational.__init__ { #Rational.init .api-name }

def __init__(out self, value: Int = 0)

A Rational from a native Int; Rational() is zero.

Arguments

  • value (Int): The value.
def __init__(
    out self,
    text: String,
    *,
    allow_whitespace: Bool = False,
    allow_underscores: Bool = False,
    limits: Optional[ConversionLimits] = None,
) raises

Parse an exact fraction or decimal.

Accepts integers, fractions such as -12/+30, and decimals such as .125, 1. or 1.25e-3. Decimal points and exponents cannot be combined with /.

Arguments

  • text (String): The number.
  • allow_whitespace (Bool): Accept surrounding ASCII whitespace.
  • allow_underscores (Bool): Accept single underscores between digits.
  • limits (Optional[ConversionLimits]): Optional per-call conversion limits; see ConversionLimits.

Raises

Error: When the text is not a valid number, naming the byte offset; when a denominator is zero; or when it exceeds limits.

def __init__(out self, var numerator: Integer, var denominator: Integer) raises

The fraction numerator / denominator, reduced.

Arguments

  • numerator (var Integer): The numerator.
  • denominator (var Integer): The denominator, nonzero.

Raises

Error: When the denominator is zero.

def __init__(out self, value: Float) raises

The exact value of a finite Float; see Float.to_rational_exact.

Arguments

  • value (Float): A finite Float; both zeros give 0.

Raises

Error: For infinity and NaN.

3 more overloads

A Rational equal to an Integer.

def __init__(out self, value: Integer)

A Rational from an integer literal of any width.

def __init__(out self, value: IntLiteral)

A Rational from a native integral scalar of at most 64 bits.

def __init__[dtype: DType](out self, value: SIMD[dtype, 1])

Rational.ceil

def ceil(self) raises -> Integer

Round toward positive infinity.

Returns

Integer: The smallest Integer not below the value.

Raises

Error: Only on a checked size error.

Rational.denominator

def denominator(self) -> Integer

The denominator in lowest terms.

Returns

Integer: An independent positive Integer.

Rational.floor

def floor(self) raises -> Integer

Round toward negative infinity.

Returns

Integer: The largest Integer not above the value; Rational(-7, 3).floor() is -3.

Raises

Error: Only on a checked size error.

Rational.from_json

def from_json(
    text: String,
    *,
    limits: Optional[ConversionLimits] = None,
) raises -> Self

Read a Rational from its version-1 JSON record.

The components must already be canonical: coprime, a positive denominator, and zero as 0/1.

Arguments

  • text (String): The JSON record.
  • limits (Optional[ConversionLimits]): Optional per-call conversion limits; see ConversionLimits.

Returns

Self: The Rational the record holds.

Raises

Error: When the text is not exactly that schema, naming the byte offset.

Rational.is_integer

def is_integer(self) -> Bool

Whether the value is an integer (Python's Fraction.is_integer).

Returns

Bool: True when the denominator is 1.

Rational.numerator

def numerator(self) -> Integer

The numerator in lowest terms.

Returns

Integer: An independent Integer carrying the sign.

Rational.parse

def parse(
    text: String,
    *,
    allow_whitespace: Bool = False,
    allow_underscores: Bool = False,
    limits: Optional[ConversionLimits] = None,
) raises -> Self

Parse an exact fraction or decimal; the same contract as the text constructor.

Arguments

  • text (String): The number.
  • allow_whitespace (Bool): Accept surrounding ASCII whitespace.
  • allow_underscores (Bool): Accept single underscores between digits.
  • limits (Optional[ConversionLimits]): Optional per-call conversion limits; see ConversionLimits.

Returns

Self: The parsed Rational.

Raises

Error: When the text is not a valid number, or exceeds limits.

Rational.round

def round(self) raises -> Integer

Round to the nearest Integer, and a half to the even neighbour.

Returns

Integer: The nearest Integer; Rational(5, 2) and Rational(3, 2) both give 2, and Rational(-5, 2) gives -2.

Raises

Error: Only on a checked size error.

Rational.sign

def sign(self) -> Int

The sign: -1, 0 or 1.

Returns

Int: The sign of the numerator.

Rational.to_integer_exact

def to_integer_exact(self) raises -> Integer

Convert an integral value to Integer.

Returns

Integer: The Integer equal to this value.

Raises

Error: When the value has a fractional part; choose floor, ceil or trunc.

Rational.to_json

def to_json(self, *, limits: Optional[ConversionLimits] = None) raises -> String

Write the version-1 JSON record of this Rational.

Arguments

  • limits (Optional[ConversionLimits]): Optional per-call conversion limits; see ConversionLimits.

Returns

String: {"version":1,"family":"rational","numerator":"-7","denominator":"3"} style compact JSON.

Raises

Error: When the output exceeds limits.

Rational.to_native_exact

def to_native_exact[dtype: DType](self) raises -> SIMD[dtype, 1]

Convert an integral value to a native integer type, exactly.

Parameters

  • dtype (DType): The target: DType.int or a signed or unsigned 8- to 64-bit integer.

Returns

SIMD[dtype, 1]: The same value in the native type.

Raises

Error: When the value has a fractional part or does not fit the type.

Rational.to_string

def to_string(
    self,
    *,
    limits: Optional[ConversionLimits] = None,
) raises -> String

The canonical text numerator/denominator, omitting /1.

Arguments

  • limits (Optional[ConversionLimits]): Optional per-call conversion limits; see ConversionLimits.

Returns

String: Exact text, not a rounded decimal.

Raises

Error: When the output exceeds limits.

Rational.trunc

def trunc(self) raises -> Integer

Round toward zero.

Returns

Integer: The integer part.

Raises

Error: Only on a checked size error.

Rational.write_to

def write_to(self, mut writer: Some[Writer])

Write the canonical text, as print does.

Arguments

  • writer (mut Some[Writer]): The destination.

Exact text

Supply text to parse a fraction exactly: "1.25e-3" becomes 1/800, and "0.1" becomes 1/10.

integer  := [+-]? digits
fraction := integer "/" integer
decimal  := [+-]? (digits ("." digits?)? | "." digits)
            ([eE] [+-]? digits)?

Digits must be ASCII. Leading zeros and signed zero are accepted and reduced to canonical values. A fraction needs two integers and a nonzero denominator; its components cannot contain decimal points or exponents. Prefixes such as 0x, infinities, NaNs, and trailing characters are rejected.

Zero can be parsed without expanding a huge decimal exponent. A nonzero value whose expansion exceeds storage limits raises a checked error.

JSON and limits

JSON records must already be reduced. The denominator is positive, the two components are coprime, and zero has numerator "0" and denominator "1". Canonical decimal fields permit a minus sign on a negative numerator, but no plus sign, padding zeros, or negative zero. Use the text constructor when input such as "2/4" needs normalization.

One rational counts as one logical value under ConversionLimits. Input digits include written significand and exponent digits; zeros implied by an exponent do not count. Text output omits a denominator of one, while JSON writes both components. The allocation budget covers numeric conversion, normalization, and output storage. See conversion limits.

Mixing families

Integer and rational operands produce exact fractions in either arithmetic order. A Float or typed native float gives a Float result, rounded from the exact fraction and the other operand's stored value. Library comparisons use exact values; typed native numbers should appear on the right.

Int(x) requires an integral value that fits a native Int. to_integer_exact() requires an integral value but returns an arbitrary- precision integer. Use floor, ceil, or trunc for directed rounding. pow_rational accepts signed integer exponents.

The family also provides gcd, lcm, and root_exact. If an exact root is absent, the fraction is not the requested rational power; the generated declarations give the domain rules. Use the family names explicitly, since the root package exports the integer versions of gcd and lcm.