Functional Weave
Code in Rust

math.rational@2.0.0

impl/python/rational.py

1,611 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from typing import Tuple

from .math_gcd_lcm import gcd_wide  ← from math.gcd-lcm ^1.0.0 · built alongside by fune
from .math_rational_types import Rational

_MAX_SAFE = 9007199254740991


def rational_from_wide(numerator: int, denominator: int) -> Rational:
    """Reduce a wide fraction and bring it back into the exact number range.

    The arithmetic works on products that may be past 2^53, and only the
    reduced result has to fit.
    """
    if denominator == 0:
        raise ValueError("denominator must not be zero")
    g = gcd_wide(numerator, denominator)
    n = numerator // g
    d = denominator // g
    if d < 0:
        n, d = -n, -d
    # Python ints never overflow, but TypeScript numbers stop being exact here,
    # and the three languages must agree.
    if n > _MAX_SAFE or n < -_MAX_SAFE or d > _MAX_SAFE:
        raise ValueError("rational overflow: the reduced result exceeds 2^53 - 1")
    return Rational(numerator=n, denominator=d)


def rational(numerator: int, denominator: int) -> Rational:
    """Build a reduced fraction with a positive denominator."""
    for v in (numerator, denominator):
        if isinstance(v, bool) or not isinstance(v, int):
            raise TypeError("numerator and denominator must be integers")
        if v > _MAX_SAFE or v < -_MAX_SAFE:
            raise ValueError("rational overflow: numerator and denominator must be within 2^53 - 1")
    return rational_from_wide(numerator, denominator)


def rational_parts(r: Rational) -> Tuple[int, int]:
    """A checked, reduced operand as (numerator, denominator)."""
    n = rational(r.numerator, r.denominator)
    return n.numerator, n.denominator