Linear merge of two sorted term lists: fl maps a coefficient
present only on the left, fr one present only on the right, fb
combines a collision, and zero results are dropped. add and sub are
instances.
Equations
- One or more equations did not get rendered due to their size.
- Hex.SparsePoly.mergeWith fl fr fb [] x✝ = List.filterMap (fun (t : Nat × R) => if fr t.snd = 0 then none else some (t.fst, fr t.snd)) x✝
- Hex.SparsePoly.mergeWith fl fr fb (a :: as) [] = List.filterMap (fun (t : Nat × R) => if fl t.snd = 0 then none else some (t.fst, fl t.snd)) (a :: as)
Instances For
The merge of two canonical term lists is canonical.
Coefficient description of the zero-filtered coefficient map used by the merge's one-sided cases.
Coefficient description of the merge. The three compatibility
hypotheses identify the structural choices with the pointwise fb
against an absent side's 0.
The canonical-form invariant, list-level: exponents strictly increase.
The canonical-form invariant, list-level: no stored coefficient is zero.
The stored exponents are exactly the exponents with a nonzero coefficient. Uses both canonical-form invariants: strict increase makes the stored coefficient the coefficient, and zero-freedom makes it nonzero.
Package a canonical term list as a polynomial.
Equations
- Hex.SparsePoly.ofCanonicalList l hs hnz = { terms := l.toArray, canonical := ⋯ }
Instances For
Map exponents and coefficients over a term list, dropping the terms
whose new coefficient is zero. neg, scale, and mulMonomial are
instances (with the identity exponent map or a shift).
Equations
Instances For
The map of a canonical term list along a strictly monotone exponent map is canonical.
Coefficient of the mapped list at a mapped exponent, for an exponent map injective into the stored exponents.
Add two sparse polynomials by a linear merge of the sorted term
arrays, O(s + t): sums at a matching exponent, and a zero sum stores
nothing.
Equations
Instances For
Equations
- Hex.SparsePoly.instAdd = { add := Hex.SparsePoly.add }
Coefficient law for add, under the pointwise hypotheses it
needs; the Lean.Grind.Semiring form is coeff_add.
Grind-classes form of coeff_add': addition is coefficientwise.
Subtract two sparse polynomials by a linear merge, O(s + t).
Equations
Instances For
Equations
- Hex.SparsePoly.instSub = { sub := Hex.SparsePoly.sub }
Coefficient law for sub, under the pointwise hypotheses it
needs; the Lean.Grind.Ring form is coeff_sub.
Grind-classes form of coeff_sub': subtraction is coefficientwise.
Negate a sparse polynomial: subtraction from zero, compiled as one
filtered coefficient map. Over a ring the exponents and the term count
are unchanged; [Sub R] alone does not supply that, so the zero filter
stays.
Equations
- s.neg = Hex.SparsePoly.ofCanonicalList (Hex.SparsePoly.mapTerms id (fun (x : Nat) (c : R) => 0 - c) s.terms.toList) ⋯ ⋯
Instances For
Equations
Coefficient law for neg, under the pointwise hypothesis it
needs; the Lean.Grind.Ring form is coeff_neg.
Grind-classes form of coeff_neg': negation is coefficientwise.
Multiply every coefficient by c, dropping the products that
vanish: c = 0 gives the zero polynomial, and a zero divisor c can
delete an interior term while leaving its neighbours.
Equations
- Hex.SparsePoly.scale c s = Hex.SparsePoly.ofCanonicalList (Hex.SparsePoly.mapTerms id (fun (x : Nat) (x_1 : R) => c * x_1) s.terms.toList) ⋯ ⋯
Instances For
Coefficient law for scale, under the pointwise hypothesis it
needs; the Lean.Grind.Semiring form is coeff_scale.
Grind-classes form of coeff_scale': scaling multiplies each coefficient.
Multiply by the monomial c · x^e: add e to every exponent and
multiply every coefficient by c. The exponent shift is strictly
monotone, so the only canonicalisation is the zero filter. This is the
cheap shift mul is built from, O(s).
Equations
- Hex.SparsePoly.mulMonomial e c s = Hex.SparsePoly.ofCanonicalList (Hex.SparsePoly.mapTerms (fun (e' : Nat) => e + e') (fun (x : Nat) (x_1 : R) => c * x_1) s.terms.toList) ⋯ ⋯
Instances For
Coefficient law for mulMonomial, under the pointwise
hypothesis it needs; the Lean.Grind.Semiring form is
coeff_mulMonomial.
Grind-classes form of coeff_mulMonomial': a monomial multiple shifts and scales the coefficients.
Multiply two sparse polynomials: the canonicalised pairwise product.
Every pair of exponents contributes, exponent sums collide freely, and
ofTerms combines the collisions and drops what cancels. The
pairwise products are built through the term Lists so the kernel can
reduce this specification (Array.flatMap stalls kernel reduction; the
value is unchanged). The @[csimp] implementation is selected by the
Phase-4 sparse-multiplication bench family; until then compiled code
runs this specification through ofTerms's sort-and-combine
twin.
Equations
Instances For
Equations
Tree accumulator for mulImpl: fold every pairwise product into an
Std.ExtTreeMap keyed on the exponent sum, replaying addCoeff
per key so the accumulated value is exactly the specification's
input-order fold. A stored 0 encodes an exponent whose partial sum
cancelled and is dropped at read-out.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Runtime implementation of mul, selected by the Phase-4
sparse-multiplication bench family (see the SPEC's measured note): the
ExtTreeMap accumulation, which beat sort-and-combine on both
collision shapes and the Johnson heap merge everywhere (value-equal to
mul by mul_eq_impl, registered @[csimp]).
Equations
Instances For
The specification and the tree accumulation compute the same
polynomial, with no algebra assumed: the tree replays the
addCoeff steps per key in the specification's input order.
Raise to a power by binary powering over mul. A caller
wanting f(x^k) should use substPow, never pow: the cost
difference is the whole reason this library exists.
Equations
Instances For
Equations
Divisibility by existence of a cofactor, matching the DensePoly
convention.
Equations
- Hex.SparsePoly.instDvdOfAddOfMul = { dvd := fun (p q : Hex.SparsePoly R) => ∃ (r : Hex.SparsePoly R), q = p * r }
Divisibility unfolds to a cofactor witness.
Addition is commutative.
Addition is associative.
Zero is a right identity for addition.
Zero is a left identity for addition.