mutable Design
mutable is the execution-oriented layer of luna-poly. It reuses the mathematical semantics and canonicalization rules of immut, while exposing explicitly mutating container operations.
Responsibilities
- Re-export shared
corecapability traits through themutablefacade. - Provide
DensePolynomial,TermPolynomial,SparsePolynomial, andExponentVectoraligned withimmut. - Provide
from_immutandto_immutconversions. - Provide setters,
clear,copy, and_inplaceoperations for incremental construction and updates. - Keep ordinary algebraic operators non-mutating.
Mutation Boundary
Public methods that mutate the receiver include:
DensePolynomial::set_coefficientDensePolynomial::clearDensePolynomial::add_inplaceDensePolynomial::mul_inplaceDensePolynomial::scale_inplaceTermPolynomial::clearTermPolynomial::add_term_inplaceTermPolynomial::add_inplaceTermPolynomial::mul_inplaceTermPolynomial::scale_inplaceSparsePolynomial::set_coefficientSparsePolynomial::clearSparsePolynomial::add_term_inplaceSparsePolynomial::add_inplaceSparsePolynomial::mul_inplaceSparsePolynomial::scale_inplace
Other ordinary operators and methods such as scale, pow, and substitute return new values.
Relationship With immut
Many mutable operations convert through immut and then convert back. This keeps the two layers aligned on:
- trailing-zero removal for univariate polynomials,
- exponent-vector canonicalization and degree semantics,
- multivariate term merging and zero deletion,
- natural-number exponentiation and
arithmetic.PowNatChecked.
mutable.ExponentVector is a wrapper around immut.ExponentVector; it remains value-oriented so it can be used as a stable key.
Canonical Form
Mutating operations must restore canonical form before returning:
DensePolynomialremoves trailing zero coefficients.TermPolynomialmerges duplicate terms and removes zero coefficients.SparsePolynomialremoves map entries whose coefficients become zero.
New in-place operations must preserve these invariants.
Usage Boundary
Prefer immut by default. Use mutable when code needs step-by-step updates, fewer explicit intermediate values, or integration with an existing mutable algorithm.
Generic code should depend on UnivariatePolynomial, MultivariatePolynomial, ContextualPolynomial, MutablePolynomial, or the relevant Type::ops() record instead of matching on a concrete mutable storage type.
Mutable containers also implement HasShape, so execution-oriented algorithms can inspect the same PolynomialShape metadata as immutable code. The mutable facade re-exports the luna-generic algebra traits used by the linear-algebra package, and mutable Type::ops() records expose construction, addition, multiplication, evaluation, scaling, and powers for generic algorithms.
Checked methods mirror the immutable layer and return None for contract failures. Existing convenience methods remain aborting wrappers.
Mutable context substitution delegates to the immutable context model. Mutable wrappers expose the same scalar/polynomial substitution and partial-evaluation APIs, but the canonical result is produced by the immutable implementation and then wrapped back into mutable.ContextPolynomial. The same checked failure contracts apply: foreign variables, duplicate assignments, unknown type_theory names, and incompatible replacement polynomial contexts return None.