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 oddn.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; seeConversionLimits.
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; seeConversionLimits.
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; seeConversionLimits.
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; seeConversionLimits.
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.intor 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; seeConversionLimits.
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.