Core API

Representations and arithmetic

All computational methods share an explicit Budget; see budgets and errors. Fields describe canonical representations; use validated factories when constructing values and preserve their invariants when inspecting fields.

Example

This computes \((x+1)^3\) and its derivative at \(x=3\), then checks a dense conversion and the kernel encoding. Zero and one have dedicated kernel representations, so the literal codec rejects those two polynomials.

arithmetic.mojo Download
"""Compute exact powers, derivatives, and kernel bytes with one shared budget."""
from std.testing import assert_equal
from apn_mojo import Rational
from polynomials import Budget, QQ, NoContext, MonomialOrder, SparsePoly, DensePoly, evaluate, evaluate_dense, derivative, to_kernel_bytes, from_kernel_bytes


def main() raises:
    var budget = Budget(1000000)
    var order = MonomialOrder()
    var x = SparsePoly[QQ].variable(0, order, NoContext(), budget)
    var one = SparsePoly[QQ].constant(QQ(Rational(1)), order, budget)
    var p = x.add(one, budget).pow(3, budget)
    var point: List[Tuple[Int64, QQ]] = [(Int64(0), QQ(Rational(3)))]
    var value = evaluate(p, point, budget)
    var slope = evaluate(derivative(p, 0, budget), point, budget)
    assert_equal(value, QQ(Rational(64)))
    assert_equal(slope, QQ(Rational(48)))

    var dense = DensePoly[QQ].from_sparse(p, budget)
    assert_equal(evaluate_dense(dense, point[0][1], budget), value)
    var bytes = to_kernel_bytes(p, budget)
    assert_equal(from_kernel_bytes(bytes[:], budget), p)
    assert_equal(len(bytes), 100)
    print("Value at 3:", value.value)
    print("Derivative at 3:", slope.value)
    print("Kernel bytes:", len(bytes))

Run from the repository root pixi run mojo run -I build docs/examples/arithmetic.mojo

Output

Value at 3: 64
Derivative at 3: 48
Kernel bytes: 100

Types and functions

PolyErrorKind

@fieldwise_init
struct PolyErrorKind(ImplicitlyCopyable, Equatable, Writable)

Classify a polynomial operation's failure.

Defined in src/polynomials/errors.mojo.

Field Type
code UInt8 The stable kind code.

PolyErrorKind.LIMIT

comptime LIMIT = Self(1)

The work budget is exhausted.

PolyErrorKind.CAPACITY

comptime CAPACITY = Self(2)

A size or work counter cannot be represented.

PolyErrorKind.DOMAIN

comptime DOMAIN = Self(3)

The operands do not belong to the operation's domain.

PolyErrorKind.UNSUPPORTED

comptime UNSUPPORTED = Self(4)

The operation is not supported for these operands.

PolyErrorKind.ENCODING

comptime ENCODING = Self(5)

The bytes do not encode a canonical polynomial.

PolyError

@fieldwise_init
struct PolyError(Copyable, Movable, Writable)

A typed failure, with no implicit conversion from plain Error.

Defined in src/polynomials/errors.mojo.

Field Type
kind PolyErrorKind The machine-readable failure kind.
message String The human-readable diagnostic.

Budget

struct Budget(ImplicitlyCopyable, Writable)

A deterministic abstract-work allowance shared by nested calls.

Defined in src/polynomials/errors.mojo.

Budget.__init__

def __init__(out self, steps: UInt64 = UInt64.MAX)

Create a budget.

Arguments.

  • steps: The initial work allowance.

Budget.charge

def charge(mut self, n: UInt64) raises PolyError

Charge before performing work; a rejected charge changes nothing.

Arguments.

  • n: The work to charge.

Raises.

  • PolyError: LIMIT if the allowance is insufficient.

Budget.remaining

def remaining(self) -> UInt64

Return the unspent allowance.

Returns. The remaining abstract work units.

CoefficientRing

trait CoefficientRing(Copyable, Equatable, Writable, Deinitable)

An exact commutative ring with explicit context and charged arithmetic.

Defined in src/polynomials/coefficients.mojo.

CoefficientRing.Context

comptime Context: Copyable & Equatable & Writable & Deinitable

The type describing the coefficient ring.

CoefficientRing.zero

@staticmethod
def zero(ctx: Self.Context) -> Self

Construct the additive identity.

Arguments.

  • ctx: The ring context.

Returns. Zero in that ring.

CoefficientRing.one

@staticmethod
def one(ctx: Self.Context) -> Self

Construct the multiplicative identity.

Arguments.

  • ctx: The ring context.

Returns. One in that ring.

CoefficientRing.context

def context(self) -> Self.Context

Report the ring context.

Returns. This value's ring.

CoefficientRing.is_zero

def is_zero(self) -> Bool

Test the additive identity in constant time.

Returns. Whether the value is zero.

CoefficientRing.size

def size(self) -> Int

Report the magnitude storage size in bytes.

Returns. A positive size used for precharging arithmetic.

CoefficientRing.add

def add(self, other: Self, mut budget: Budget) raises PolyError -> Self

Compute the exact sum.

Arguments.

  • other: The other coefficient in the same ring.
  • budget: The shared work allowance.

Returns. The result in the same ring.

Raises.

  • PolyError: DOMAIN for different rings, LIMIT or CAPACITY for work limits.

CoefficientRing.sub

def sub(self, other: Self, mut budget: Budget) raises PolyError -> Self

Compute the exact difference.

Arguments.

  • other: The other coefficient in the same ring.
  • budget: The shared work allowance.

Returns. The result in the same ring.

Raises.

  • PolyError: DOMAIN for different rings, LIMIT or CAPACITY for work limits.

CoefficientRing.mul

def mul(self, other: Self, mut budget: Budget) raises PolyError -> Self

Compute the exact product.

Arguments.

  • other: The other coefficient in the same ring.
  • budget: The shared work allowance.

Returns. The result in the same ring.

Raises.

  • PolyError: DOMAIN for different rings, LIMIT or CAPACITY for work limits.

CoefficientRing.neg

def neg(self, mut budget: Budget) raises PolyError -> Self

Compute the additive inverse.

Arguments.

  • budget: The shared work allowance.

Returns. The negated coefficient.

Raises.

  • PolyError: LIMIT or CAPACITY for work limits.

CoefficientField

trait CoefficientField(CoefficientRing)

A coefficient ring with inverses for nonzero elements.

Defined in src/polynomials/coefficients.mojo.

CoefficientField.inverse

def inverse(self, mut budget: Budget) raises PolyError -> Self

Compute the multiplicative inverse.

Arguments.

  • budget: The shared work allowance.

Returns. The inverse in this field.

Raises.

  • PolyError: DOMAIN for zero, LIMIT or CAPACITY for work limits.

NoContext

@fieldwise_init
struct NoContext(ImplicitlyCopyable, Equatable, Writable)

The unique context of integers, rationals, and Gaussian rationals.

Defined in src/polynomials/coefficients.mojo.

Modulus

struct Modulus(ImplicitlyCopyable, Equatable, Writable)

A validated prime strictly below two to the power 62.

Defined in src/polynomials/coefficients.mojo.

Field Type
value UInt64 The prime; callers must preserve the validated value.

Modulus.__init__

def __init__(out self, value: UInt64, mut budget: Budget) raises PolyError

Validate a prime field context using deterministic Miller-Rabin.

Arguments.

  • value: The proposed prime.
  • budget: The shared work allowance.

Raises.

  • PolyError: DOMAIN for a nonprime or out-of-range modulus, LIMIT on exhaustion.

Modulus.__init__

def __init__(out self, *, _prime_value: UInt64)

Recover an already validated internal prime context.

Arguments.

  • _prime_value: A prime previously checked by the public constructor.

ZZ

@fieldwise_init
struct ZZ(CoefficientRing)

An exact integer coefficient.

Defined in src/polynomials/coefficients.mojo.

Field Type
value Integer The canonical arbitrary-precision value.

ZZ.Context

comptime Context = NoContext

The unique ring context.

ZZ.zero

@staticmethod
def zero(ctx: NoContext) -> Self

Construct zero.

Arguments.

  • ctx: The ring context.

Returns. The additive identity.

ZZ.one

@staticmethod
def one(ctx: NoContext) -> Self

Construct one.

Arguments.

  • ctx: The ring context.

Returns. The multiplicative identity.

ZZ.context

def context(self) -> NoContext

Report the unique context.

Returns. The ring's context.

ZZ.is_zero

def is_zero(self) -> Bool

Test whether this coefficient is zero.

Returns. Whether the value is zero.

ZZ.size

def size(self) -> Int

Report a positive magnitude size in bytes.

Returns. The size used by the work model.

ZZ.add

def add(self, other: Self, mut budget: Budget) raises PolyError -> Self

Compute the exact sum after charging its size.

Arguments.

  • other: The other coefficient.
  • budget: The shared work allowance.

Returns. The exact result.

Raises.

  • PolyError: LIMIT or CAPACITY if the computation cannot proceed.

ZZ.sub

def sub(self, other: Self, mut budget: Budget) raises PolyError -> Self

Compute the exact difference after charging its size.

Arguments.

  • other: The other coefficient.
  • budget: The shared work allowance.

Returns. The exact result.

Raises.

  • PolyError: LIMIT or CAPACITY if the computation cannot proceed.

ZZ.mul

def mul(self, other: Self, mut budget: Budget) raises PolyError -> Self

Compute the exact product after charging its size.

Arguments.

  • other: The other coefficient.
  • budget: The shared work allowance.

Returns. The exact result.

Raises.

  • PolyError: LIMIT or CAPACITY if the computation cannot proceed.

ZZ.neg

def neg(self, mut budget: Budget) raises PolyError -> Self

Negate the coefficient after charging its size.

Arguments.

  • budget: The shared work allowance.

Returns. The additive inverse.

Raises.

  • PolyError: LIMIT if the allowance is insufficient.

QQ

@fieldwise_init
struct QQ(CoefficientField)

An exact rational coefficient.

Defined in src/polynomials/coefficients.mojo.

Field Type
value Rational The canonical arbitrary-precision value.

QQ.Context

comptime Context = NoContext

The unique ring context.

QQ.zero

@staticmethod
def zero(ctx: NoContext) -> Self

Construct zero.

Arguments.

  • ctx: The ring context.

Returns. The additive identity.

QQ.one

@staticmethod
def one(ctx: NoContext) -> Self

Construct one.

Arguments.

  • ctx: The ring context.

Returns. The multiplicative identity.

QQ.context

def context(self) -> NoContext

Report the unique context.

Returns. The ring's context.

QQ.is_zero

def is_zero(self) -> Bool

Test whether this coefficient is zero.

Returns. Whether the value is zero.

QQ.size

def size(self) -> Int

Report a positive magnitude size in bytes.

Returns. The size used by the work model.

QQ.add

def add(self, other: Self, mut budget: Budget) raises PolyError -> Self

Compute the exact sum after charging its size.

Arguments.

  • other: The other coefficient.
  • budget: The shared work allowance.

Returns. The exact result.

Raises.

  • PolyError: LIMIT or CAPACITY if the computation cannot proceed.

QQ.sub

def sub(self, other: Self, mut budget: Budget) raises PolyError -> Self

Compute the exact difference after charging its size.

Arguments.

  • other: The other coefficient.
  • budget: The shared work allowance.

Returns. The exact result.

Raises.

  • PolyError: LIMIT or CAPACITY if the computation cannot proceed.

QQ.mul

def mul(self, other: Self, mut budget: Budget) raises PolyError -> Self

Compute the exact product after charging its size.

Arguments.

  • other: The other coefficient.
  • budget: The shared work allowance.

Returns. The exact result.

Raises.

  • PolyError: LIMIT or CAPACITY if the computation cannot proceed.

QQ.neg

def neg(self, mut budget: Budget) raises PolyError -> Self

Negate the coefficient after charging its size.

Arguments.

  • budget: The shared work allowance.

Returns. The additive inverse.

Raises.

  • PolyError: LIMIT if the allowance is insufficient.

QQ.inverse

def inverse(self, mut budget: Budget) raises PolyError -> Self

Invert a nonzero rational.

Arguments.

  • budget: The shared work allowance.

Returns. The reciprocal.

Raises.

  • PolyError: DOMAIN on zero, LIMIT or CAPACITY on work limits.

QQi

@fieldwise_init
struct QQi(CoefficientField)

An exact Gaussian rational coefficient a + b*i, with rational a and b.

Defined in src/polynomials/exact_complex.mojo.

Field Type
value ExactComplex The canonical apn_mojo value with two exact rational components.

QQi.Context

comptime Context = NoContext

The unique field context; no precision or rounding mode is needed.

QQi.zero

@staticmethod
def zero(ctx: NoContext) -> Self

Construct zero.

Arguments.

  • ctx: The field context.

Returns. The additive identity.

QQi.one

@staticmethod
def one(ctx: NoContext) -> Self

Construct one.

Arguments.

  • ctx: The field context.

Returns. The multiplicative identity.

QQi.context

def context(self) -> NoContext

Report the unique field context.

Returns. The field's context.

QQi.is_zero

def is_zero(self) -> Bool

Test whether both exact components are zero.

Returns. Whether the value is zero.

QQi.size

def size(self) -> Int

Report the sum of the rational component sizes in bytes.

Returns. The positive size used by the work model.

QQi.add

def add(self, other: Self, mut budget: Budget) raises PolyError -> Self

Add the exact coefficients with budgeted rational arithmetic.

Arguments.

  • other: The other coefficient.
  • budget: The shared work allowance.

Returns. The exact sum.

Raises.

  • PolyError: LIMIT or CAPACITY on work limits.

QQi.sub

def sub(self, other: Self, mut budget: Budget) raises PolyError -> Self

Subtract the exact coefficients with budgeted rational arithmetic.

Arguments.

  • other: The other coefficient.
  • budget: The shared work allowance.

Returns. The exact difference.

Raises.

  • PolyError: LIMIT or CAPACITY on work limits.

QQi.mul

def mul(self, other: Self, mut budget: Budget) raises PolyError -> Self

Multiply exactly, charging each rational intermediate operation.

Arguments.

  • other: The other coefficient.
  • budget: The shared work allowance.

Returns. The exact product.

Raises.

  • PolyError: LIMIT or CAPACITY on work limits.

QQi.neg

def neg(self, mut budget: Budget) raises PolyError -> Self

Negate both rational components after charging their sizes.

Arguments.

  • budget: The shared work allowance.

Returns. The exact additive inverse.

Raises.

  • PolyError: LIMIT if the allowance is insufficient.

QQi.inverse

def inverse(self, mut budget: Budget) raises PolyError -> Self

Invert a nonzero coefficient using its conjugate and squared norm.

Arguments.

  • budget: The shared work allowance.

Returns. The exact reciprocal (a - bi)/(aa + b*b).

Raises.

  • PolyError: DOMAIN on zero, LIMIT or CAPACITY on work limits.

ModInt

struct ModInt(CoefficientField)

A canonical residue carrying its prime modulus.

Defined in src/polynomials/coefficients.mojo.

Field Type
value UInt64 The representative in the range zero through modulus minus one.
modulus UInt64 The validated prime modulus.

ModInt.Context

comptime Context = Modulus

The field context type.

ModInt.__init__

def __init__(out self, value: UInt64, ctx: Modulus)

Reduce a native unsigned integer in a validated field.

Arguments.

  • value: The integer to reduce.
  • ctx: A validated prime context.

ModInt.zero

@staticmethod
def zero(ctx: Modulus) -> Self

Construct field zero.

Arguments.

  • ctx: The prime field.

Returns. Its additive identity.

ModInt.one

@staticmethod
def one(ctx: Modulus) -> Self

Construct field one.

Arguments.

  • ctx: The prime field.

Returns. Its multiplicative identity.

ModInt.context

def context(self) -> Modulus

Recover the validated context.

Returns. The field of this residue.

ModInt.size

def size(self) -> Int

Report the native residue storage size.

Returns. Eight bytes.

ModInt.is_zero

def is_zero(self) -> Bool

Test for the additive identity.

Returns. Whether the residue is zero.

ModInt.add

def add(self, other: Self, mut budget: Budget) raises PolyError -> Self

Compute the modular sum.

Arguments.

  • other: The other residue in the same field.
  • budget: The shared work allowance.

Returns. The reduced result.

Raises.

  • PolyError: DOMAIN for mixed fields or LIMIT on exhaustion.

ModInt.sub

def sub(self, other: Self, mut budget: Budget) raises PolyError -> Self

Compute the modular difference.

Arguments.

  • other: The other residue in the same field.
  • budget: The shared work allowance.

Returns. The reduced result.

Raises.

  • PolyError: DOMAIN for mixed fields or LIMIT on exhaustion.

ModInt.mul

def mul(self, other: Self, mut budget: Budget) raises PolyError -> Self

Compute the modular product.

Arguments.

  • other: The other residue in the same field.
  • budget: The shared work allowance.

Returns. The reduced result.

Raises.

  • PolyError: DOMAIN for mixed fields or LIMIT on exhaustion.

ModInt.neg

def neg(self, mut budget: Budget) raises PolyError -> Self

Compute the additive inverse in this field.

Arguments.

  • budget: The shared work allowance.

Returns. The canonical additive inverse.

Raises.

  • PolyError: LIMIT on exhaustion.

ModInt.inverse

def inverse(self, mut budget: Budget) raises PolyError -> Self

Invert by Fermat's theorem using budgeted repeated squaring.

Arguments.

  • budget: The shared work allowance.

Returns. The multiplicative inverse.

Raises.

  • PolyError: DOMAIN for zero or LIMIT on exhaustion.

Monomial

struct Monomial(Copyable, Movable, Equatable, Hashable, Writable)

A product of variables with increasing indices and positive exponents.

Defined in src/polynomials/monomial.mojo.

Field Type
pairs List[Tuple[Int64, UInt32]] The canonical pairs; callers must preserve their invariant.

Monomial.__init__

def __init__(out self)

Construct the unit monomial.

Monomial.__init__

def __init__(out self, var pairs: List[Tuple[Int64, UInt32]], mut budget: Budget) raises PolyError

Validate and take ownership of canonical pairs.

Arguments.

  • pairs: Increasing indices with positive exponents.
  • budget: The shared work allowance.

Raises.

  • PolyError: DOMAIN for invalid pairs or LIMIT on exhaustion.

Monomial.check_invariants

def check_invariants(self, mut budget: Budget) raises PolyError

Check increasing indices and positive exponents.

Arguments.

  • budget: The shared work allowance.

Raises.

  • PolyError: DOMAIN for malformed pairs or LIMIT on exhaustion.

Monomial.degree

def degree(self, mut budget: Budget) raises PolyError -> UInt64

Sum the exponents with overflow checks.

Arguments.

  • budget: The shared work allowance.

Returns. The total degree.

Raises.

  • PolyError: CAPACITY on overflow or LIMIT on exhaustion.

Monomial.exponent

def exponent(self, index: Int64, mut budget: Budget) raises PolyError -> UInt32

Find a variable's exponent by binary search.

Arguments.

  • index: The variable index.
  • budget: The shared work allowance.

Returns. Its exponent, or zero if absent.

Raises.

  • PolyError: LIMIT on exhaustion.

Monomial.mul

def mul(self, other: Self, mut budget: Budget) raises PolyError -> Self

Multiply by merging exponent lists.

Arguments.

  • other: The other monomial.
  • budget: The shared work allowance.

Returns. The canonical product.

Raises.

  • PolyError: CAPACITY on exponent overflow or LIMIT on exhaustion.

Monomial.lcm

def lcm(self, other: Self, mut budget: Budget) raises PolyError -> Self

Take componentwise maximum exponents.

Arguments.

  • other: The other monomial.
  • budget: The shared work allowance.

Returns. The least common multiple.

Raises.

  • PolyError: LIMIT or CAPACITY on work limits.

Monomial.divides

def divides(self, other: Self, mut budget: Budget) raises PolyError -> Bool

Test componentwise exponent inclusion.

Arguments.

  • other: The proposed multiple.
  • budget: The shared work allowance.

Returns. Whether this monomial divides the other.

Raises.

  • PolyError: LIMIT on exhaustion.

Monomial.div

def div(self, other: Self, mut budget: Budget) raises PolyError -> Self

Divide by a monomial exactly.

Arguments.

  • other: The proposed divisor.
  • budget: The shared work allowance.

Returns. The canonical quotient.

Raises.

  • PolyError: DOMAIN if indivisible or LIMIT on exhaustion.

MonomialOrder

struct MonomialOrder(Copyable, Movable, Equatable, Writable)

An explicit variable order, or the kernel's canonical storage order.

Defined in src/polynomials/monomial.mojo.

Field Type
kind UInt8 One of KERNEL, LEX, GRLEX, or GREVLEX.
variables List[Int64] Variables from greatest to least; empty for KERNEL.

MonomialOrder.KERNEL

comptime KERNEL = UInt8(0)

Lexicographic pairs, with a proper prefix first.

MonomialOrder.LEX

comptime LEX = UInt8(1)

Lexicographic exponent order.

MonomialOrder.GRLEX

comptime GRLEX = UInt8(2)

Total degree followed by lexicographic order.

MonomialOrder.GREVLEX

comptime GREVLEX = UInt8(3)

Total degree followed by reversed last differing exponent.

MonomialOrder.__init__

def __init__(out self)

Construct the kernel storage order.

MonomialOrder.__init__

def __init__(out self, kind: UInt8, var variables: List[Int64], mut budget: Budget) raises PolyError

Validate and construct an explicit order.

Arguments.

  • kind: The order kind.
  • variables: The variable priority list.
  • budget: The shared work allowance.

Raises.

  • PolyError: DOMAIN for invalid kind or repeated variables, LIMIT on exhaustion.

MonomialOrder.validate

def validate(self, monomial: Monomial, mut budget: Budget) raises PolyError

Check that a canonical monomial belongs to this variable domain.

Arguments.

  • monomial: The monomial to validate.
  • budget: The shared work allowance.

Raises.

  • PolyError: DOMAIN for unknown variables or LIMIT on exhaustion.

MonomialOrder.compare

def compare(self, a: Monomial, b: Monomial, mut budget: Budget) raises PolyError -> Int

Compare monomials under this order after domain validation.

Arguments.

  • a: The left monomial.
  • b: The right monomial.
  • budget: The shared work allowance.

Returns. Minus one, zero, or one.

Raises.

  • PolyError: DOMAIN for unknown variables, LIMIT or CAPACITY for work limits.

Term

@fieldwise_init
struct Term[C: CoefficientRing](Copyable, Movable, Equatable, Writable)

One monomial and its coefficient.

Parameters.

  • C: The coefficient ring type.

Defined in src/polynomials/sparse.mojo.

Field Type
monomial Monomial The canonical monomial.
coefficient Self.C The coefficient in the polynomial's ring.

SparsePoly

struct SparsePoly[C: CoefficientRing](Copyable, Movable, Equatable, Writable)

A canonical polynomial whose nonzero terms increase in its order.

Parameters.

  • C: The coefficient ring type.

Defined in src/polynomials/sparse.mojo.

Field Type
order MonomialOrder The explicit monomial order.
ring Self.C.Context The coefficient ring context, including for the zero polynomial.
terms List[Term[Self.C]] The increasing nonzero terms; callers must preserve canonical form.

SparsePoly.__init__

def __init__(out self, var order: MonomialOrder, var ring: Self.C.Context)

Take ownership of a validated order and context to construct zero.

Arguments.

  • order: The owned order (no input-sized copy occurs here).
  • ring: The owned coefficient context.

SparsePoly.zero

@staticmethod
def zero(order: MonomialOrder, ring: Self.C.Context, mut budget: Budget) raises PolyError -> Self

Construct zero while charging the copied order.

Arguments.

  • order: The monomial order.
  • ring: The coefficient context.
  • budget: The shared work allowance.

Returns. The zero polynomial.

Raises.

  • PolyError: LIMIT on exhaustion.

SparsePoly.constant

@staticmethod
def constant(c: Self.C, order: MonomialOrder, mut budget: Budget) raises PolyError -> Self

Construct a constant with the coefficient's context.

Arguments.

  • c: The constant coefficient.
  • order: The monomial order.
  • budget: The shared work allowance.

Returns. The canonical constant polynomial.

Raises.

  • PolyError: LIMIT on exhaustion.

SparsePoly.variable

@staticmethod
def variable(index: Int64, order: MonomialOrder, ring: Self.C.Context, mut budget: Budget) raises PolyError -> Self

Construct a variable in the specified ring.

Arguments.

  • index: The variable index.
  • order: The monomial order.
  • ring: The coefficient context.
  • budget: The shared work allowance.

Returns. The variable polynomial.

Raises.

  • PolyError: DOMAIN for an unknown variable or LIMIT on exhaustion.

SparsePoly.from_terms

@staticmethod
def from_terms(var terms: List[Term[Self.C]], order: MonomialOrder, ring: Self.C.Context, mut budget: Budget) raises PolyError -> Self

Validate, sort, combine equal monomials, and remove zero coefficients.

Arguments.

  • terms: The owned unsorted terms.
  • order: The target order.
  • ring: The coefficient context.
  • budget: The shared work allowance.

Returns. The normalized polynomial.

Raises.

  • PolyError: DOMAIN for mixed rings or invalid monomials, LIMIT or CAPACITY on work limits.

SparsePoly.is_zero

def is_zero(self) -> Bool

Test for the empty canonical term list.

Returns. Whether the polynomial is zero.

SparsePoly.add

def add(self, other: Self, mut budget: Budget) raises PolyError -> Self

Add by a linear merge of canonical terms.

Arguments.

  • other: The other polynomial.
  • budget: The shared work allowance.

Returns. The canonical sum.

Raises.

  • PolyError: DOMAIN for incompatible operands, LIMIT or CAPACITY on work limits.

SparsePoly.sub

def sub(self, other: Self, mut budget: Budget) raises PolyError -> Self

Subtract by a linear merge of canonical terms.

Arguments.

  • other: The other polynomial.
  • budget: The shared work allowance.

Returns. The canonical difference.

Raises.

  • PolyError: DOMAIN for incompatible operands, LIMIT or CAPACITY on work limits.

SparsePoly.neg

def neg(self, mut budget: Budget) raises PolyError -> Self

Negate all coefficients without re-sorting.

Arguments.

  • budget: The shared work allowance.

Returns. The additive inverse.

Raises.

  • PolyError: LIMIT or CAPACITY on work limits.

SparsePoly.mul

def mul(self, other: Self, mut budget: Budget) raises PolyError -> Self

Multiply exact terms using sorted streams for admissible orders.

Arguments.

  • other: The other polynomial.
  • budget: The shared work allowance.

Returns. The canonical product.

Raises.

  • PolyError: DOMAIN for incompatible operands, LIMIT or CAPACITY on work limits.

SparsePoly.scale

def scale(self, c: Self.C, mut budget: Budget) raises PolyError -> Self

Multiply every coefficient by a scalar in the same ring.

Arguments.

  • c: The scalar.
  • budget: The shared work allowance.

Returns. The scaled canonical polynomial.

Raises.

  • PolyError: DOMAIN for a different coefficient ring, LIMIT or CAPACITY on work limits.

SparsePoly.pow

def pow(self, n: UInt64, mut budget: Budget) raises PolyError -> Self

Raise to a natural power by repeated squaring, with zero power equal to one.

Squaring runs from the exponent's leading bit down, so each step squares the power so far and multiplies by the base alone; the last and largest product is a square.

Arguments.

  • n: The exponent.
  • budget: The shared work allowance.

Returns. The canonical power in the same ring and order.

Raises.

  • PolyError: LIMIT or CAPACITY on work limits.

SparsePoly.leading

def leading(self, mut budget: Budget) raises PolyError -> Term[Self.C]

Copy the greatest term.

Arguments.

  • budget: The shared work allowance.

Returns. The leading term.

Raises.

  • PolyError: DOMAIN for zero or LIMIT on exhaustion.

SparsePoly.total_degree

def total_degree(self, mut budget: Budget) raises PolyError -> Int

Find the greatest total degree, or minus one for zero.

Arguments.

  • budget: The shared work allowance.

Returns. The total degree.

Raises.

  • PolyError: LIMIT on exhaustion or CAPACITY if the degree cannot fit Int.

SparsePoly.degree_in

def degree_in(self, index: Int64, mut budget: Budget) raises PolyError -> Int

Find the degree in one variable, or minus one for zero.

Arguments.

  • index: The variable index.
  • budget: The shared work allowance.

Returns. The greatest exponent of that variable.

Raises.

  • PolyError: LIMIT on exhaustion.

SparsePoly.variables

def variables(self, mut budget: Budget) raises PolyError -> List[Int64]

Collect occurring variable indices in increasing order.

Arguments.

  • budget: The shared work allowance.

Returns. The sorted distinct indices.

Raises.

  • PolyError: LIMIT on exhaustion.

SparsePoly.reorder

def reorder(self, order: MonomialOrder, mut budget: Budget) raises PolyError -> Self

Normalize under a new order.

Arguments.

  • order: The target monomial order.
  • budget: The shared work allowance.

Returns. The same polynomial in that order.

Raises.

  • PolyError: DOMAIN for absent variables, LIMIT or CAPACITY on work limits.

SparsePoly.check_invariants

def check_invariants(self, mut budget: Budget) raises PolyError

Check the ring, monomials, coefficients, and strict term order.

Arguments.

  • budget: The shared work allowance.

Raises.

  • PolyError: DOMAIN for a broken invariant or LIMIT on exhaustion.

PackedPoly

struct PackedPoly[C: CoefficientRing](Copyable, Movable, Equatable, Sized)

A sparse polynomial stored as one exponent word per term and a contiguous coefficient list.

The order is LEX over the variables 0..n-1 in that order. Each monomial is one word by mixed-radix substitution with radix_i = (largest exponent of variable i) + 1, variable 0 most significant, so word order is LEX order; the product of the radices is below 2**62. Products, powers and exact quotients emit their words directly, with no per-term monomial lists until to_sparse.

Parameters.

  • C: The coefficient ring type.

Defined in src/polynomials/packed.mojo.

PackedPoly.__init__

def __init__(out self, *, var _packed: _PackedPoly[Self.C])

Wrap packed storage whose radix is the exact exponent bound.

Arguments.

  • _packed: Canonical packed storage.

PackedPoly.from_sparse

@staticmethod
def from_sparse(p: SparsePoly[Self.C], mut budget: Budget) raises PolyError -> Optional[Self]

Pack a sparse polynomial, or return no value when it does not fit.

Arguments.

  • p: A polynomial in LEX order over the variables 0..n-1 in that order.
  • budget: The shared work allowance.

Returns. The packed polynomial, or None for another order or a key range of 2**62 or more.

Raises.

  • PolyError: LIMIT or CAPACITY on work limits.

PackedPoly.to_sparse

def to_sparse(self, mut budget: Budget) raises PolyError -> SparsePoly[Self.C]

Materialize the canonical sparse form.

Arguments.

  • budget: The shared work allowance.

Returns. The same polynomial as a SparsePoly.

Raises.

  • PolyError: LIMIT or CAPACITY on work limits.

PackedPoly.is_zero

def is_zero(self) -> Bool

Report whether the polynomial has no terms.

Returns. Whether the polynomial is zero.

PackedPoly holds a LEX polynomial over the variables 0..n-1 as one exponent word per term and a contiguous coefficient list, so large products and powers build no per-term monomial lists. Its radices are the exact exponent bounds: leading forms multiply without cancellation over an integral domain, so a product, power or quotient knows its radix before it is computed. packed_mul and packed_pow return no value when the result's key range would reach 2**62; packed_divide_exact returns no value when the divisor does not divide, as divide_exact does. Convert with to_sparse for operations that PackedPoly does not provide.

packed_mul

def packed_mul[C: CoefficientRing](a: PackedPoly[C], b: PackedPoly[C], mut budget: Budget) raises PolyError -> Optional[PackedPoly[C]]

Multiply packed polynomials, keeping the product packed.

ZZ coefficients of at most 63 bits and prime-field residues take the packed product kernel; other operands multiply as SparsePoly.mul does and are packed again.

Parameters.

  • C: The coefficient ring type.

Arguments.

  • a: The left factor.
  • b: The right factor in the same ring and order.
  • budget: The shared work allowance.

Returns. The product, or None when its key range would reach 2**62.

Raises.

  • PolyError: DOMAIN for incompatible operands, LIMIT or CAPACITY on work limits.

Defined in src/polynomials/packed.mojo.

packed_pow

def packed_pow[C: CoefficientRing](f: PackedPoly[C], n: UInt64, mut budget: Budget) raises PolyError -> Optional[PackedPoly[C]]

Raise a packed polynomial to a natural power, keeping the power packed.

Few-term ZZ bases take the power recurrence where SparsePoly.pow would; otherwise the power squares from the exponent's leading bit down with packed products. Zero power equals one.

Parameters.

  • C: The coefficient ring type.

Arguments.

  • f: The base.
  • n: The exponent.
  • budget: The shared work allowance.

Returns. The power, or None when its key range would reach 2**62.

Raises.

  • PolyError: LIMIT or CAPACITY on work limits.

Defined in src/polynomials/packed.mojo.

packed_divide_exact

def packed_divide_exact[C: CoefficientRing](f: PackedPoly[C], g: PackedPoly[C], mut budget: Budget) raises PolyError -> Optional[PackedPoly[C]]

Return the exact packed quotient f / g, or no value when g does not divide f.

ZZ divisors with coefficients of at most 63 bits and prime-field divisors take chunked packed division; other operands divide as divide_exact does. The quotient is packed in its own radix.

Parameters.

  • C: ZZ or a coefficient field.

Arguments.

  • f: The dividend.
  • g: The nonzero divisor in the same ring and order.
  • budget: The shared work allowance.

Returns. The quotient if g divides f, otherwise None.

Raises.

  • PolyError: DOMAIN for invalid operands, UNSUPPORTED for another ring, LIMIT or CAPACITY on work limits.

Defined in src/polynomials/packed.mojo.

CoefficientBuffer

struct CoefficientBuffer[T: Copyable & Deinitable](Copyable, Movable, Sized, Iterable, Equatable where conforms_to(T, Equatable), Writable where conforms_to(T, Writable))

Ascending coefficients in contiguous or chunked owned storage.

Copies own independent storage. Polynomial arrays share their enclosing immutable polynomial handle instead. Indexing never flattens chunks.

Parameters.

  • T: The coefficient type.

Defined in src/polynomials/coefficient_buffer.mojo.

CoefficientBuffer.IteratorType

comptime IteratorType[iterable_mut: Bool, //, iterable_origin: Origin[mut=iterable_mut]]: Iterator = _BufferIterator[Self.T, ImmOrigin(iterable_origin)]

The iterator that borrows the owner and yields independent values.

Parameters.

  • iterable_mut: Whether the source origin is mutable.
  • iterable_origin: The source lifetime.

CoefficientBuffer.__init__

def __init__(out self)

Construct an empty contiguous buffer.

CoefficientBuffer.__init__

@implicit
def __init__(out self, var values: List[Self.T])

Adopt a list without copying its coefficient storage.

Arguments.

  • values: The owned ascending coefficients.

CoefficientBuffer.__init__

def __init__(out self, *, copy: Self)

Copy coefficients into independently mutable storage.

Arguments.

  • copy: The source buffer.

CoefficientBuffer.write_to

def write_to[W: Writer](self, mut writer: W) where conforms_to(Self.T, Writable)

Write the coefficients in list notation.

Parameters.

  • W: The output writer type.

Arguments.

  • writer: The destination receiving the representation.

CoefficientBuffer.capacity

def capacity(self) -> Int

Return the total allocated coefficient capacity.

Returns. Initialized and spare slots, excluding chunk metadata.

CoefficientBuffer.is_contiguous

def is_contiguous(self) -> Bool

Test whether all coefficients occupy one list.

Returns. True for contiguous storage, including an empty buffer.

CoefficientBuffer.clear

def clear(mut self)

Release all coefficients and chunk metadata, leaving an empty buffer.

CoefficientBuffer.pop

def pop(mut self) -> Self.T

Remove and return the final coefficient.

Returns. The owned coefficient. The buffer must be nonempty.

CoefficientBuffer.append

def append(mut self, var value: Self.T)

Append a coefficient, preserving the current storage form.

Arguments.

  • value: The owned coefficient. Callers must charge growth first.

CoefficientBuffer.to_list

def to_list(self, mut budget: Budget) raises PolyError -> List[Self.T]

Copy into a mutable contiguous list with explicit allocation work.

Arguments.

  • budget: The shared work allowance for allocation and handle copies.

Returns. An independent list in coefficient order.

Raises.

  • PolyError: LIMIT or CAPACITY before unbudgeted work or allocation.

The buffer owns a contiguous list or bounded chunks. Indexing borrows entries; iteration yields independent coefficient values without flattening the buffer. copy() creates independent storage; to_list(budget) explicitly copies into a contiguous list. See dense coefficient storage for the buffer's operations.

DensePoly

struct DensePoly[C: CoefficientRing](Copyable, Movable, Equatable, Writable)

A canonical univariate polynomial with coefficients in ascending degree.

Parameters.

  • C: The coefficient ring type.

Defined in src/polynomials/dense.mojo.

Field Type
variable Int64 The variable index, retained even for constants and zero.
ring Self.C.Context The coefficient ring context.
coefficients CoefficientBuffer[Self.C] Owned contiguous or chunked coefficients, empty for zero and otherwise ending in a nonzero value.

DensePoly.__init__

def __init__(out self, variable: Int64, var ring: Self.C.Context)

Construct zero by taking ownership of its context.

Arguments.

  • variable: The retained variable index.
  • ring: The owned ring context.

DensePoly.from_coefficients

@staticmethod
def from_coefficients(variable: Int64, ring: Self.C.Context, var coefficients: List[Self.C], mut budget: Budget) raises PolyError -> Self

Validate the ring and trim trailing zero coefficients.

Arguments.

  • variable: The variable index.
  • ring: The coefficient context.
  • coefficients: The owned ascending coefficient vector.
  • budget: The shared work allowance.

Returns. The canonical dense polynomial.

Raises.

  • PolyError: DOMAIN for mixed contexts or LIMIT on exhaustion.

DensePoly.from_coefficients

@staticmethod
def from_coefficients(variable: Int64, ring: Self.C.Context, var coefficients: CoefficientBuffer[Self.C], mut budget: Budget) raises PolyError -> Self

Validate the ring and trim trailing zero coefficients.

Arguments.

  • variable: The variable index.
  • ring: The coefficient context.
  • coefficients: The owned ascending coefficient vector.
  • budget: The shared work allowance.

Returns. The canonical dense polynomial.

Raises.

  • PolyError: DOMAIN for mixed contexts or LIMIT on exhaustion.

DensePoly.karatsuba_threshold

@staticmethod
def karatsuba_threshold() -> Int

Report the measured crossover for this coefficient type.

Returns. 64 coefficients for ModInt, otherwise 32.

DensePoly.degree

def degree(self) -> Int

Return the stored degree, or minus one for zero.

Returns. The degree in constant time.

DensePoly.is_zero

def is_zero(self) -> Bool

Test whether the coefficient vector is empty.

Returns. Whether the polynomial is zero.

DensePoly.add

def add(self, other: Self, mut budget: Budget) raises PolyError -> Self

Add coefficient vectors in the same ring and variable.

Arguments.

  • other: The other polynomial.
  • budget: The shared work allowance.

Returns. The canonical sum.

Raises.

  • PolyError: DOMAIN for incompatible operands, LIMIT or CAPACITY on work limits.

DensePoly.sub

def sub(self, other: Self, mut budget: Budget) raises PolyError -> Self

Subtract coefficient vectors in the same ring and variable.

Arguments.

  • other: The other polynomial.
  • budget: The shared work allowance.

Returns. The canonical difference.

Raises.

  • PolyError: DOMAIN for incompatible operands, LIMIT or CAPACITY on work limits.

DensePoly.neg

def neg(self, mut budget: Budget) raises PolyError -> Self

Negate the coefficient vector.

Arguments.

  • budget: The shared work allowance.

Returns. The additive inverse.

Raises.

  • PolyError: LIMIT or CAPACITY on work limits.

DensePoly.scale

def scale(self, c: Self.C, mut budget: Budget) raises PolyError -> Self

Multiply all coefficients by a scalar.

Arguments.

  • c: The scalar in the same ring.
  • budget: The shared work allowance.

Returns. The scaled polynomial.

Raises.

  • PolyError: DOMAIN for a mixed ring, LIMIT or CAPACITY on work limits.

DensePoly.mul_schoolbook

def mul_schoolbook(self, other: Self, mut budget: Budget) raises PolyError -> Self

Multiply by direct convolution for testing and measurements.

Arguments.

  • other: The other polynomial.
  • budget: The shared work allowance.

Returns. The canonical product.

Raises.

  • PolyError: DOMAIN for incompatible operands, LIMIT or CAPACITY on work limits.

DensePoly.mul

def mul(self, other: Self, mut budget: Budget) raises PolyError -> Self

Multiply with schoolbook or an explicit-stack Karatsuba traversal.

Arguments.

  • other: The other polynomial.
  • budget: The shared work allowance.

Returns. The canonical product.

Raises.

  • PolyError: DOMAIN for incompatible operands, LIMIT or CAPACITY on work limits.

DensePoly.pow

def pow(self, n: UInt64, mut budget: Budget) raises PolyError -> Self

Raise to a natural power by repeated squaring.

Arguments.

  • n: The exponent.
  • budget: The shared work allowance.

Returns. The power; exponent zero gives one in the same ring and variable.

Raises.

  • PolyError: LIMIT or CAPACITY on work limits.

DensePoly.to_sparse

def to_sparse(self, order: MonomialOrder, mut budget: Budget) raises PolyError -> SparsePoly[Self.C]

Convert to canonical sparse form under an explicit order.

Arguments.

  • order: The sparse monomial order.
  • budget: The shared work allowance.

Returns. The sparse polynomial in the same coefficient ring.

Raises.

  • PolyError: DOMAIN for an unknown variable, CAPACITY for exponent overflow, LIMIT on exhaustion.

DensePoly.from_sparse

@staticmethod
def from_sparse(p: SparsePoly[Self.C], mut budget: Budget, *, variable: Optional[Int64] = None) raises PolyError -> Self

Convert a univariate sparse polynomial, optionally selecting its variable.

Arguments.

  • p: The sparse polynomial.
  • budget: The shared work allowance.
  • variable: The variable to retain; inferred from nonconstant terms, otherwise zero.

Returns. The dense polynomial in the same coefficient ring.

Raises.

  • PolyError: DOMAIN for another variable, LIMIT or CAPACITY on work limits.

DensePoly.check_invariants

def check_invariants(self, mut budget: Budget) raises PolyError

Check ring consistency and the nonzero leading coefficient.

Arguments.

  • budget: The shared work allowance.

Raises.

  • PolyError: DOMAIN for an invalid representation or LIMIT on exhaustion.

KARATSUBA_THRESHOLD

comptime KARATSUBA_THRESHOLD = 32

The measured Karatsuba threshold for arbitrary-precision coefficients.

Defined in src/polynomials/dense.mojo.

evaluate

def evaluate[C: CoefficientRing](p: SparsePoly[C], point: List[Tuple[Int64, C]], mut budget: Budget) raises PolyError -> C

Evaluate by nested sparse Horner schemes using an explicit work stack.

Parameters.

  • C: The coefficient ring type.

Arguments.

  • p: The polynomial.
  • point: Distinct variable indices and values in the same ring.
  • budget: The shared work allowance.

Returns. The exact value in the coefficient ring.

Raises.

  • PolyError: DOMAIN for missing or repeated variables or mixed rings, LIMIT or CAPACITY on work limits.

Defined in src/polynomials/evaluate.mojo.

evaluate_dense

def evaluate_dense[C: CoefficientRing](p: DensePoly[C], x: C, mut budget: Budget) raises PolyError -> C

Evaluate a dense polynomial by Horner's rule.

Parameters.

  • C: The coefficient ring type.

Arguments.

  • p: The polynomial.
  • x: The value in the coefficient ring.
  • budget: The shared work allowance.

Returns. The exact value.

Raises.

  • PolyError: DOMAIN for another ring, LIMIT or CAPACITY on work limits.

Defined in src/polynomials/evaluate.mojo.

substitute

def substitute[C: CoefficientRing](p: SparsePoly[C], index: Int64, q: SparsePoly[C], mut budget: Budget) raises PolyError -> SparsePoly[C]

Substitute a polynomial for one variable.

Parameters.

  • C: The coefficient ring type.

Arguments.

  • p: The source polynomial.
  • index: The variable to replace.
  • q: The replacement in the same ring and order.
  • budget: The shared work allowance.

Returns. The canonical substituted polynomial.

Raises.

  • PolyError: DOMAIN for incompatible operands, LIMIT or CAPACITY on work limits.

Defined in src/polynomials/evaluate.mojo.

derivative

def derivative[C: CoefficientRing](p: SparsePoly[C], index: Int64, mut budget: Budget) raises PolyError -> SparsePoly[C]

Differentiate formally in one variable in any coefficient ring.

Parameters.

  • C: The coefficient ring type.

Arguments.

  • p: The polynomial.
  • index: The variable to differentiate.
  • budget: The shared work allowance.

Returns. The canonical formal derivative.

Raises.

  • PolyError: LIMIT or CAPACITY on work limits.

Defined in src/polynomials/evaluate.mojo.

to_kernel_bytes

def to_kernel_bytes(p: SparsePoly[QQ], mut budget: Budget) raises PolyError -> List[UInt8]

Encode a polynomial as a canonical kernel literal.

Arguments.

  • p: The rational polynomial, in any monomial order.
  • budget: The shared work allowance.

Returns. The canonical little-endian payload.

Raises.

  • PolyError: ENCODING for zero or one, DOMAIN for broken invariants, CAPACITY beyond the kernel ceiling, LIMIT on exhaustion.

Defined in src/polynomials/codec.mojo.

from_kernel_bytes

def from_kernel_bytes(data: Span[UInt8, _], mut budget: Budget) raises PolyError -> SparsePoly[QQ]

Decode canonical kernel bytes without repairing malformed input.

Arguments.

  • data: The byte payload.
  • budget: The shared work allowance.

Returns. The canonical polynomial in KERNEL order.

Raises.

  • PolyError: ENCODING for malformed or noncanonical bytes, CAPACITY beyond the size ceiling, LIMIT on exhaustion.

Defined in src/polynomials/codec.mojo.

MAX_KERNEL_BYTES

comptime MAX_KERNEL_BYTES = 1048576

The kernel's one-mebibyte literal size ceiling.

Defined in src/polynomials/codec.mojo.