Multiply every coefficient by c.
Kernel-facing specification: one map over the reference coefficient list.
Compiled code uses Hex.DensePoly.scaleImpl, the value-equal
Array.map pass selected by
Hex.DensePoly.scale_eq_impl.
Equations
- Hex.DensePoly.scale c p = Hex.DensePoly.ofList (List.map (fun (a : R) => c * a) p.toList)
Instances For
Runtime implementation of scale: one Array.map pass over the stored
coefficients (value-equal to scale by scale_eq_impl, registered
@[csimp]).
Equations
- Hex.DensePoly.scaleImpl c p = Hex.DensePoly.ofCoeffs (Array.map (fun (a : R) => c * a) p.toArray)
Instances For
Multiply by x^n.
Kernel-facing specification: one replicate-append of the reference
coefficient list. Compiled code uses
Hex.DensePoly.shiftImpl, the value-equal Array.append
implementation selected by Hex.DensePoly.shift_eq_impl.
Equations
- Hex.DensePoly.shift n p = if p.isZero = true then 0 else Hex.DensePoly.ofList (List.replicate n Zero.zero ++ p.toList)
Instances For
Runtime implementation of shift: one Array append with no intermediate
list (value-equal to shift by shift_eq_impl, registered @[csimp]).
Equations
- Hex.DensePoly.shiftImpl n p = if p.isZero = true then 0 else Hex.DensePoly.ofCoeffs (Array.replicate n Zero.zero ++ p.toArray)
Instances For
Coefficient law for scalar multiplication. The explicit zero law records the fact that
scaling a missing coefficient still gives the default coefficient 0.
Scaling the zero polynomial yields the zero polynomial: scale c 0 = 0.
A simp/grind normal form, so callers need no c * 0 = 0 hypothesis to
discharge the scaled-zero case.
Semiring-specialized coefficient law for scalar multiplication, registered as a normalizing
rewrite because the required c * 0 = 0 law is available from the semiring structure.
Scaling twice multiplies the two scalars.
Semiring-specialized left zero law for scalar multiplication.
Coefficient law for shifting by x^n: coefficients below n are zero and later
coefficients are read from the original polynomial with the index shifted down.
Shifting the zero polynomial by any power leaves it zero: shift n 0 = 0.
A simp/grind normal form for the degenerate input to shift.
Shifting by x^0 is the identity: shift 0 p = p. A simp/grind normal
form so a trivial shift drops out of multiplication and division proofs.
Combined coefficient law for a scaled shift. The zero-law hypothesis is the only algebraic fact needed to normalize coefficients that are outside the support.
Semiring-specialized coefficient law for a scaled shift, registered as a normalizing rewrite for the common algebraic setting.
The zero polynomial has coefficient 0 at every index.
Zip two coefficient lists with f, padding the shorter list with literal
Zero.zero arguments: overhang entries become f p Zero.zero / f Zero.zero q
rather than being passed through, so every output entry is literally
f (xs.getD i) (ys.getD i); the value the Array.ofFn runtime impls
reproduce with no algebraic laws on R.
Equations
- Hex.DensePoly.zipPad f [] x✝ = List.map (fun (y : R) => f Zero.zero y) x✝
- Hex.DensePoly.zipPad f (x_2 :: xs) [] = f x_2 Zero.zero :: Hex.DensePoly.zipPad f xs []
- Hex.DensePoly.zipPad f (x_2 :: xs) (y :: ys) = f x_2 y :: Hex.DensePoly.zipPad f xs ys
Instances For
Add two dense polynomials coefficientwise.
Kernel-facing specification: a single padded walk of the two coefficient
lists. Compiled code uses Hex.DensePoly.addImpl, the value-equal,
one-allocation Array.ofFn loop selected by
Hex.DensePoly.add_eq_impl.
Equations
- p.add q = Hex.DensePoly.ofCoeffs (Hex.DensePoly.zipPad (fun (x1 x2 : R) => x1 + x2) p.toList q.toList).toArray
Instances For
Runtime implementation of add: one Array.ofFn allocation over the
padded index range (value-equal to add by add_eq_impl, registered
@[csimp]).
Equations
Instances For
The reference add and the Array.ofFn runtime loop compute the same
polynomial: each output coefficient is literally p.coeff i + q.coeff i on
both sides, so no algebraic laws on R are needed.
Register the Array.ofFn loop as the compiled implementation of add.
Equations
- Hex.DensePoly.instAdd = { add := Hex.DensePoly.add }
Subtract two dense polynomials coefficientwise.
Like Hex.DensePoly.add, this is a kernel-reduction-friendly
specification. Compiled code uses Hex.DensePoly.subImpl, the
value-equal Array.ofFn loop selected by
Hex.DensePoly.sub_eq_impl.
Equations
- p.sub q = Hex.DensePoly.ofCoeffs (Hex.DensePoly.zipPad (fun (x1 x2 : R) => x1 - x2) p.toList q.toList).toArray
Instances For
Runtime implementation of sub (value-equal to sub by sub_eq_impl,
registered @[csimp]).
Equations
Instances For
The reference sub and the Array.ofFn runtime loop compute the same
polynomial.
Register the Array.ofFn loop as the compiled implementation of sub.
Equations
- Hex.DensePoly.instSub = { sub := Hex.DensePoly.sub }
Coefficientwise additive inverse, expressed through executable subtraction.
Kernel-facing specification (one Hex.DensePoly.sub against the zero
polynomial); compiled code uses Hex.DensePoly.negImpl, the value-equal
Array.map pass selected by Hex.DensePoly.neg_eq_impl.
Instances For
Runtime implementation of neg: one Array.map pass over the stored
coefficients (value-equal to neg by neg_eq_impl, registered @[csimp]).
Instances For
Equations
Semiring structures provide the zero-addition compatibility law used by coefficient lemmas.
Ring structures provide the zero-subtraction compatibility law used by coefficient lemmas.
Ring structures provide the zero-subtraction negation law used by coefficient lemmas.
One row of the schoolbook convolution: add c times each entry of qs
into the corresponding entry of acc, dropping contributions past the end of
acc (matching the dropped out-of-bounds Array.set! writes of mulImpl).
Equations
- Hex.DensePoly.mulRow c x✝ [] = x✝
- Hex.DensePoly.mulRow c [] (head :: tail) = []
- Hex.DensePoly.mulRow c (a :: acc) (q :: qs) = (a + c * q) :: Hex.DensePoly.mulRow c acc qs
Instances For
All rows of the schoolbook convolution: for each coefficient of ps in
ascending-degree order, add its scaled copy of qs into the accumulator at the
matching offset. The accumulator entry at the current offset is final once its
row is applied, so each step emits one finished coefficient and recurses on the
tail. Additions reach each accumulator entry in exactly the order of the
Array-based mulImpl loop, which is what makes mul_eq_impl provable
without any algebraic laws on R.
Equations
- Hex.DensePoly.mulRows qs [] x✝ = x✝
- Hex.DensePoly.mulRows qs (x_2 :: xs) [] = []
- Hex.DensePoly.mulRows [] (x_2 :: xs) (y :: ys) = y :: Hex.DensePoly.mulRows [] xs ys
- Hex.DensePoly.mulRows (q :: qs') (x_2 :: xs) (y :: ys) = (y + x_2 * q) :: Hex.DensePoly.mulRows (q :: qs') xs (Hex.DensePoly.mulRow x_2 ys qs')
Instances For
Schoolbook dense polynomial multiplication by direct coefficient convolution.
This definition is the kernel-reduction-friendly specification: the accumulator
is a plain list walked head-first, so reducing a concrete product costs one
cons-step per (i, j) coefficient pair instead of an O(size) list traversal
per Array access. Compiled code instead runs the in-place Array loop
Hex.DensePoly.mulImpl, selected by
Hex.DensePoly.mul_eq_impl.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Runtime implementation of mul: the same schoolbook convolution computed
by in-place Array writes (value-equal to mul by mul_eq_impl, registered
@[csimp]).
The inner j-loop reads the loop-invariant coefficient p.coeff i from a single
let-bound value (pi) instead of re-projecting it on every (i, j) step, so
the compiled inner loop performs one bounds-checked coefficient read per i
rather than per (i, j). The let is a zeta reduction away from the bare
convolution, so it does not change the value, the coeff_mul characterization, or any
proof.
Equations
- One or more equations did not get rendered due to their size.
Instances For
One inner schoolbook multiplication step, projected to coefficient n.
Instances For
The schoolbook coefficient fold matching the executable multiplication loop order.
Equations
- p.mulCoeffSum q n = List.foldl (fun (acc : R) (i : Nat) => List.foldl (p.mulCoeffStep q n i) acc (List.range q.size)) Zero.zero (List.range p.size)
Instances For
mulCoeffSum collapsed to a single fold over the row index i, each row
contributing p.coeff i * q.coeff (n - i) when i ≤ n and n - i is in range
(closed form from foldl_mulCoeffStep_range). Public so lazy-reduction
convolution kernels can relate their per-coefficient Nat sums to the reference
product coefficient.
The specification mul and the Array-loop mulImpl compute the same
polynomial: both sides perform the same coefficient additions in the same
order, so no algebraic laws on R are needed.
Equations
Characterising coefficient law for multiplication: each coefficient of p * q is computed by
the same nested schoolbook fold as the executable multiplication loop.
List-level Horner evaluation, reading coefficients from low to high degree.
The body of the eval specification.
Equations
- Hex.DensePoly.evalCoeffList [] x✝ = Zero.zero
- Hex.DensePoly.evalCoeffList (c :: cs) x✝ = Hex.DensePoly.evalCoeffList cs x✝ * x✝ + c
Instances For
Evaluate a polynomial using Horner's method.
Kernel-facing specification: one cons walk of the coefficient list, highest
degree innermost. Compiled code uses Hex.DensePoly.evalImpl, the
value-equal downward Array.foldr loop with no intermediate list or
reverse allocation, selected by Hex.DensePoly.eval_eq_impl.
Equations
- p.eval x = Hex.DensePoly.evalCoeffList p.toList x
Instances For
Runtime implementation of eval: a downward Array.foldr Horner loop over
the stored coefficients, with no intermediate coefficient-list or reverse
allocation (value-equal to eval by eval_eq_impl, registered @[csimp]).
Instances For
The reference eval and the Array.foldr runtime loop compute the same value.
Register the Array.foldr loop as the compiled implementation of eval.
List-level Horner composition, reading coefficients from low to high
degree and preserving the acc * q + C c step orientation (for generic R
this differs from composeScalarCoeffList's C c + q * acc).
Equations
- Hex.DensePoly.composeCoeffList [] x✝ = 0
- Hex.DensePoly.composeCoeffList (c :: cs) x✝ = Hex.DensePoly.composeCoeffList cs x✝ * x✝ + Hex.DensePoly.C c
Instances For
Compose polynomials using Horner's method.
Kernel-facing specification: one cons walk of the coefficient list. Compiled
code uses Hex.DensePoly.composeImpl, the value-equal downward
Array.foldr loop selected by
Hex.DensePoly.compose_eq_impl.
Equations
- p.compose q = Hex.DensePoly.composeCoeffList p.toList q
Instances For
Runtime implementation of compose: a downward Array.foldr Horner loop
(value-equal to compose by compose_eq_impl, registered @[csimp]).
Equations
- p.composeImpl q = Array.foldr (fun (coeff : R) (acc : Hex.DensePoly R) => acc * q + Hex.DensePoly.C coeff) 0 p.toArray
Instances For
The reference compose and the Array.foldr runtime loop compute the same
polynomial.
Register the Array.foldr loop as the compiled implementation of
compose.
Left-composition by the zero polynomial is zero.
Composition of a constant polynomial. The explicit zero-addition law is needed because
the generic Add/Mul/Zero interfaces do not provide algebraic simplification rules.
Semiring-specialized composition law for constants. This packages the zero-addition
law needed by the generic compose_C.
List-level Horner form for composition, reading coefficients from low to high degree.
Equations
- Hex.DensePoly.composeScalarCoeffList [] x✝ = 0
- Hex.DensePoly.composeScalarCoeffList (c :: cs) x✝ = Hex.DensePoly.C c + x✝ * Hex.DensePoly.composeScalarCoeffList cs x✝
Instances For
DensePoly.compose agrees with the list-level Horner form over the stored coefficients
when the caller supplies the algebraic step that commutes a Horner tail past q.
Iterated polynomial power used by the compose power-sum characterisation.
Equations
- q.composePower 0 = Hex.DensePoly.C 1
- q.composePower n.succ = q * q.composePower n
Instances For
List-backed power-sum form for composition, starting at a coefficient base index.
Equations
- Hex.DensePoly.composeCoeffPowerSumFrom [] x✝¹ x✝ = 0
- Hex.DensePoly.composeCoeffPowerSumFrom (c :: cs) x✝¹ x✝ = Hex.DensePoly.C c * x✝.composePower x✝¹ + Hex.DensePoly.composeCoeffPowerSumFrom cs (x✝¹ + 1) x✝
Instances For
Coefficient-indexed bounded power-sum form for composition.
Equations
- Hex.DensePoly.composeCoeffPowerSumUpTo coeff 0 x✝¹ x✝ = 0
- Hex.DensePoly.composeCoeffPowerSumUpTo coeff n.succ x✝¹ x✝ = Hex.DensePoly.C (coeff x✝¹) * x✝.composePower x✝¹ + Hex.DensePoly.composeCoeffPowerSumUpTo coeff n (x✝¹ + 1) x✝
Instances For
composeCoeffPowerSumFrom over a consecutive range is the bounded coefficient-indexed
power sum.
The reference coefficient list is the range of coefficient reads over p.size.
Index-carrying derivative walk: entry j of derivList i cs is
((i + j + 1 : Nat) : R) * cs[j]. Applied at i = 0 to the coefficient
tail, it produces the formal-derivative coefficients in one cons walk.
Equations
- Hex.DensePoly.derivList x✝ [] = []
- Hex.DensePoly.derivList x✝ (c :: cs) = ↑(x✝ + 1) * c :: Hex.DensePoly.derivList (x✝ + 1) cs
Instances For
Formal derivative. The coefficient of x^i becomes (i + 1) * a_(i+1).
Kernel-facing specification: one cons walk of the coefficient tail. Compiled
code uses Hex.DensePoly.derivativeImpl, the value-equal
Array.ofFn loop selected by
Hex.DensePoly.derivative_eq_impl.
Equations
Instances For
Runtime implementation of derivative: one Array.ofFn allocation
(value-equal to derivative by derivative_eq_impl, registered @[csimp]).
Equations
- p.derivativeImpl = Hex.DensePoly.ofCoeffs (Array.ofFn fun (i : Fin (p.size - 1)) => ↑(↑i + 1) * p.coeff (↑i + 1))
Instances For
The reference derivative and the Array.ofFn runtime loop compute the same
polynomial.
Register the Array.ofFn loop as the compiled implementation of
derivative.
The derivative stores at most one fewer coefficient than its input.
Semiring-specialized coefficient law for addition.
Scaling distributes over polynomial addition.
Ring-specialized coefficient law for subtraction.
Coefficient law for negation, expressed through subtraction from zero. The explicit zero law is inherited from the generic subtraction coefficient theorem.
Ring-specialized coefficient law for negation.
Semiring-specialized right zero law for dense polynomial addition.
Semiring-specialized left zero law for dense polynomial addition.
Ring-specialized right zero law for dense polynomial subtraction.
Ring-specialized left zero law for dense polynomial subtraction.
Ring-specialized negation of the zero dense polynomial.
Horner evaluation sends the zero dense polynomial to 0.
Evaluation law for addition. The explicit laws package the zero-preservation and
one-step Horner distributivity needed by the generic Add/Mul interface.
Semiring-specialized evaluation law for addition.
Evaluation law for subtraction. The explicit laws package the zero-preservation and
one-step Horner distributivity needed by the generic Sub/Mul interface.
Ring-specialized evaluation law for subtraction.
Evaluation law for negation, expressed through subtraction from zero.
Ring-specialized evaluation law for negation.
Evaluation of a constant polynomial. The explicit zero laws are needed because the
generic Add/Mul/Zero interfaces do not provide algebraic simplification rules.
Semiring-specialized evaluation law for constants. This packages the
zero-multiplication and zero-addition laws needed by the generic eval_C.
Semiring-specialized evaluation law for monomials.
The formal derivative of the zero polynomial is zero.
Characterising coefficient law for the formal derivative: the coefficient of
x^n in derivative p is (n + 1) * p.coeff (n + 1). The explicit zero law
((n + 1 : Nat) : R) * 0 = 0 is needed because the generic NatCast/Mul/Zero
interface does not guarantee it, mirroring the hypothesis on
Hex.DensePoly.coeff_scale.
Semiring-specialized coefficient law for the formal derivative, registered
as a normalizing rewrite because semirings provide the required a * 0 = 0
law.
The formal derivative of a constant polynomial is zero over a semiring.
The formal derivative of a degree-zero monomial is zero over a semiring.
The formal derivative of c * x^(n + 1) is (n + 1) * c * x^n over a semiring.