Rand Stats

Wheel

zef:FCO

Actions Status

NAME

Wheel - Lexically scoped arithmetic with infinity and bottom for Raku.

SYNOPSIS

use Wheel;

say 1 / 0;       # Inf
say 0 / 0;       # ⊥
say -1 * Inf;    # Inf
say Inf * -1;    # Inf
say Inf / Inf;   # ⊥
say ⊥ + 42;      # ⊥

DESCRIPTION

Wheel exports arithmetic overloads and the term ⊥ (bottom). It extends ordinary real arithmetic with a single infinity represented by Inf, and a bottom value for indeterminate results.

Operations between Int, Rat and FatRat use exact rational arithmetic, returning Int for integral results and FatRat otherwise. Num and finite Complex arithmetic remain approximate. Both signs of infinity normalize to Inf; NaN (including a complex NaN component) normalizes to bottom. A complex value with an infinite component normalizes to Inf. These rules apply to operands and results.

SUPPORTED TYPES AND VALUES

The same operand types are accepted by wheel, reciprocal, the binary operators +, -, *, /, **, ==, !=, and the unary operators + and -. Operands must be defined values.

Subclasses of supported numeric types are accepted through their ancestry, provided they retain compatible numeric behavior. Native machine values such as int and num are accepted when Raku boxes them into Int or Num at the call boundary. Abstract type objects such as Int, undefined values, plain strings and other Numeric implementations without a supported ancestry or the adapter role are rejected.

Rat and FatRat values with denominator zero are also accepted: a nonzero numerator gives Inf, while a zero numerator gives bottom. The same normalization applies to values returned by adapters. Accepted types can be mixed in either operand position; mixed Num or Complex calculations retain the native floating-point limitations. Nonintegral powers also follow native arithmetic, as described under EXPONENTIATION.

IMPORTS AND LEXICAL SCOPE

Use either use Wheel; or the symbolic alias use ::('⊙');. Both names load the same implementation and export the same operators and bottom term. The symbolic name requires the indirect module-name syntax; use ⊙; is not valid syntax.

Imports apply to the importing lexical scope and its nested scopes. They do not change enclosing or sibling scopes, or functions defined outside that scope. As with other Raku use declarations, imports are resolved at compile time.

{
    use ::('⊙');
    say -1 * Inf;       # Inf
    {
        say Inf * -1;   # Inf (inherited import)
    }
}
say -1 * Inf;           # -Inf (native arithmetic)

ARITHMETIC RULES

For the supported real numeric types, the special cases are:

Bottom absorbs +, -, *, and / in either operand position, including operations with itself. Both +⊥ and -⊥ give ⊥.

⊥ == ⊥ is true, while ⊥ == $number and $number == ⊥ are false for other numeric values. The corresponding != comparisons give the opposite result. Bottom displays as ⊥ and is a defined singleton instance. Explicit Num conversion returns NaN; Int, Rat and FatRat conversions throw an exception.

Normalize an input with wheel($value), or compute its reciprocal with reciprocal($value). Reciprocal maps zero to Inf, Inf to zero, and bottom to itself.

Custom numeric types opt in with the exported WheelConvertible role and implement wheel-value, returning a defined Int, Rat, FatRat, Num or Complex without loss of information. Returning another adapter, a type object or an unsupported value raises an exception. Unsupported Numeric values are rejected rather than silently converted to Num.

The exact rational domain implements the wheel of fractions; floating-point and complex operations retain native rounding limitations. Equality normalizes operands, so external NaN compares as bottom and infinities of either sign compare equal.

EXPONENTIATION

** is a lexical extension in addition to the basic wheel operations. A bottom exponent returns bottom, so 2 ** (0/0) gives ⊥. A zero exponent returns 1 for every supported base, including zero, infinity, bottom and external NaN, following the empty-product convention. Bottom to any other exponent returns bottom.

Integral exponents use exponentiation by squaring through wheel multiplication; negative exponents first take the reciprocal. Rational bases retain exact arithmetic. Thus 3 ** -2 is exactly 1/9, 0 ** -1 gives Inf, and Inf ** -1 gives 0. Complex exponents with zero imaginary part and integral real part use the same path.

Other exponents use native Raku exponentiation after input normalization, then normalize the result. These cases retain native rounding and domain behavior and are not specified by the wheel axioms. Infinities remain unsigned even in the exponent. Power retains native precedence and right associativity and is available through both import names.

MATHEMATICAL MODEL AND VALIDATION

The exact domain is the wheel of fractions over the rational field, with one unsigned infinity and bottom. Binary arithmetic follows the integer-pair model: addition maps (a,b),(c,d) to (ad+bc,bd), multiplication to (ac,bd), and reciprocal swaps the components. All nonzero numerators over zero represent infinity; (0,0) represents bottom. Rat and FatRat inputs with a zero denominator are normalized by the same rules.

Tests cover all eight axioms in Definition 1.1 of Jesper Carlström's Wheels — On Division by Zero, including the commutative monoid laws, reciprocal involution, modified distributivity and zero-term rules. The tests compare with an independent integer-pair oracle and inspect exact numerators and denominators, without relying on Wheel equality. Finite samples are regression checks, not a proof for all rational values.

Reference: https://www2.math.su.se/reports/2001/11/2001-11.pdf.

The imported operators accept defined Numeric values or WheelConvertible adapters. They replace the lexical native operator dispatcher, so implicit arithmetic on strings is not supported. Convert such inputs explicitly before arithmetic. Operators outside the importing scope remain native.

INSTALLATION AND TESTING

From a source checkout with Raku, zef, and App::Prove6 available:

zef install .
prove6 -I. -lv t

To run an example directly from the checkout, use raku -I. -e 'use Wheel; say 0 / 0'. The -I. option lets the loader resolve both provided names through META6.json.

The tests cover arithmetic, equality, the symbolic alias, and lexical isolation. Use prove6 for the .rakutest files.

AUTHOR

Fernando Correa de Oliveira fco@cpan.org

COPYRIGHT AND LICENSE

Copyright 2026 Fernando Correa de Oliveira.

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.