A term array is canonical when its exponents are strictly increasing and no stored coefficient is zero.
Equations
Instances For
A univariate polynomial over R as a canonical sorted array of
(exponent, coefficient) terms, ascending in exponent. Exponents are
Nat, so degrees like 10^6 cost nothing to store; only toDense
materialises a coefficient vector.
Per design principle 10, consumers read terms through the API
(coeff, support, numTerms, degree?, leadingCoeff, and the
ordered toTerms and foldTerms), not directly, so the representation
can change.
The stored
(exponent, coefficient)terms in strictly increasing exponent order, with no zero coefficients.- canonical : SparsePolyCanonical self.terms
Proof that
termsis canonical.
Instances For
The zero polynomial: the empty term array.
Instances For
Equations
- Hex.SparsePoly.instZero = { zero := Hex.SparsePoly.zero }
The number of stored terms, which is the size of the support.
Instances For
true exactly when the polynomial is zero.
Instances For
The stored exponents in increasing order; exactly the exponents whose coefficient is nonzero.
Instances For
The degree, or none for the zero polynomial. The terms ascend in
exponent, so the degree is the last stored exponent.
Instances For
The degree, with the zero polynomial given degree 0, matching
DensePoly.natDegree.
Instances For
The leading coefficient, which is 0 for the zero polynomial.
Instances For
The stored terms in increasing exponent order.
Instances For
Fold over the stored terms in increasing exponent order, O(t).
Equations
Instances For
The coefficient at exponent e in a term list: the first stored match,
0 when absent. On a canonical list the match is unique.
Equations
- Hex.SparsePoly.coeffList [] x✝ = 0
- Hex.SparsePoly.coeffList (t :: ts) x✝ = if t.fst = x✝ then t.snd else Hex.SparsePoly.coeffList ts x✝
Instances For
The coefficient at e. Kernel-facing specification (an ordered
List lookup); compiled code uses Hex.SparsePoly.coeffImpl, the
value-equal binary search selected by Hex.SparsePoly.coeff_eq_impl.
Equations
- s.coeff e = Hex.SparsePoly.coeffList s.terms.toList e
Instances For
Binary-search worker for coeffImpl: find the coefficient at
exponent e among indices in [lo, hi) of a term array sorted by
strictly increasing exponent.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Runtime implementation of coeff: binary search on the sorted
term array, O(log t) (value-equal to coeff by coeff_eq_impl,
registered @[csimp]).
Instances For
On a list with strictly increasing exponents, a stored term at
exponent e is the coefficient there.
On the range that the sortedness invariant confines the matching
exponent to, the binary search agrees with the ordered List lookup.
The kernel-facing List lookup and the binary search compute the same
coefficient on every canonical polynomial.
Linear canonicality check on a term list: adjacent exponents strictly
increase and no stored coefficient is zero. The pairwise form of the
invariant is the one induction wants; this adjacent form is the one an
O(t) check wants, and isCanonicalList_iff is the equivalence.
Equations
Instances For
The adjacent-pair check decides the pairwise invariant: < on Nat
is transitive, so strict increase between neighbours is strict increase
between every pair.
Linear canonicality check on a term array, O(t).
Equations
Instances For
The O(t) adjacent-pair check decides SparsePolyCanonical.
Equations
The tail of a sorted term list has coefficient 0 at the head's
exponent: strict increase means the head's exponent never recurs.
Two canonical term lists with the same coefficient function are equal.
This is the list-level content of SparsePoly.ext_coeff: strict exponent
increase forbids duplicates and fixes the order, and the zero-free
condition makes every stored term observable.
Extensionality: canonical representations of the same coefficient function are equal. Everything below is proved from this.
The coefficient stored at an exponent after adding c to a stored
coefficient d there, where d = 0 encodes "absent": a zero sum (and a
zero insertion) leaves the exponent absent, encoded as 0 again. On a
canonical representation the stored coefficient is 0 exactly when the
term is absent, so this is the whole observable effect of addTerm at
its target exponent.
Equations
Instances For
Ordered insert of c · x^e into a sorted term list: insert a new
term when c ≠ 0 and e is absent, replace the stored coefficient by
the sum when the sum is nonzero, and delete the term when the sum is
zero.
Equations
Instances For
Every exponent stored after an insert was stored before or is the inserted one.
The ordered insert preserves both halves of the canonical
invariant. This is the proof the whole library rests on: every
specialised operation re-establishes what addTermList establishes
here for arbitrary input.
Add c · x^e to s, combining with an existing term at e and
deleting the term when the sum is zero.
Kernel-facing specification (a single ordered List insert); compiled
code uses Hex.SparsePoly.addTermImpl, the value-equal binary search and
in-place array update selected by Hex.SparsePoly.addTerm_eq_impl.
Equations
Instances For
Equal term arrays give equal polynomials: the proof field is irrelevant.
The whole observable effect of the ordered insert: the coefficient
at e becomes addCoeff of the stored coefficient and c, and
every other coefficient is unchanged.
Coefficient description of addTerm: addCoeff at the
target exponent, unchanged elsewhere.
Binary-search worker for addTermImpl: the least index in
[lo, hi) whose exponent is at least e (or hi when there is none),
on an array sorted by strictly increasing exponent.
Equations
- One or more equations did not get rendered due to their size.
Instances For
On a sorted range, lowerBound splits the indices: every
exponent below the returned position is below e, every exponent at or
beyond it is at least e.
lowerBound never exceeds hi, with no sortedness needed:
this is what makes the insertion index valid.
The ordered insert, described at the splice position: with p
splitting the sorted list into exponents below e and at least e, the
insert is an index-p erase, set, insert, or append. This is the
list-level shape that the in-place array implementation mirrors.
In-place array worker for addTermImpl: binary search for the
splice position, then a single erase, set, insert, or push. O(log t)
search plus an O(t) shift.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Runtime implementation of addTerm: binary search and one
in-place array splice (value-equal to addTerm by
addTerm_eq_impl, registered @[csimp]).
Equations
- s.addTermImpl e c = { terms := Hex.SparsePoly.addTermArray s.terms e c, canonical := ⋯ }
Instances For
The ordered-List specification and the in-place splice compute the
same polynomial.
Register the in-place splice as the compiled implementation of
addTerm.
The canonical polynomial with the given terms. Exponents may repeat and may appear in any order, and coefficients at equal exponents are summed and zero results are dropped.
Kernel-facing specification (a fold of addTerm); compiled code
uses Hex.SparsePoly.ofTermsImpl, the value-equal stable sort and
combining pass selected by Hex.SparsePoly.ofTerms_eq_impl.
Equations
- Hex.SparsePoly.ofTerms ts = Array.foldl (fun (s : Hex.SparsePoly R) (t : Nat × R) => s.addTerm t.fst t.snd) 0 ts
Instances For
The zero polynomial has zero coefficients.
Coefficient description of the addTerm fold, with no algebra
assumed: at each exponent it is the addCoeff fold, in input
order, over the terms at that exponent.
Coefficient description of ofTerms, with no algebra assumed.
The coefficient of ofTerms ts at e is the sum, in input order, of
the coefficients of the terms of ts at e. The hzero hypothesis is
what identifies a fresh insertion c with the fold's 0 + c; a
coefficient type with Lean.Grind.Semiring discharges it from
add_zero and add_comm.
Combining worker for ofTermsImpl: walk a ≤-sorted term list with
the run exponent e and its accumulated coefficient acc, replaying the
addCoeff semantics of the addTerm fold within each
equal-exponent block and emitting the nonzero results.
Equations
Instances For
Combine the equal-exponent blocks of a ≤-sorted term list in one
pass, dropping zero results.
Equations
Instances For
The combining pass emits a canonical list whose exponents all lie at or above the run exponent.
Coefficient description of the combining pass: the run's own
exponent reads its accumulator folded over the rest of its block, and
every other exponent reads its whole block folded from 0.
Coefficient description of combineSorted on a ≤-sorted
list: each exponent reads its block folded from 0.
Runtime implementation of ofTerms: stable sort by exponent,
then one combining pass, O(m log m) on m input terms against the
specification's O(m²) worst case (value-equal to ofTerms by
ofTerms_eq_impl, registered @[csimp]). Stability is load-bearing:
it is what makes the per-block fold agree with the input-order fold of
the specification with no algebra assumed.
Equations
Instances For
The addTerm fold and the stable sort-and-combine pass build
the same polynomial, with no algebra assumed.
Register the stable sort-and-combine pass as the compiled
implementation of ofTerms.
The monomial c · x^e. The zero coefficient collapses to the zero
polynomial.
Equations
Instances For
The constant polynomial with value c. The zero constant collapses
to the zero polynomial.
Equations
Instances For
The variable x.
Equations
Instances For
Equations
- Hex.SparsePoly.instOne = { one := Hex.SparsePoly.C 1 }
#sp[(e₀, c₀), (e₁, c₁), …] constructs the canonical sparse
polynomial with the given (exponent, coefficient) terms: any order,
repeated exponents summed, zero coefficients dropped, mirroring #p[…]
for DensePoly.
Equations
- One or more equations did not get rendered due to their size.