The leading coefficient, or 0 for the zero polynomial.
Instances For
The zero polynomial has leading coefficient 0. Registered as a simp
normal form so callers reasoning about leadingCoeff discharge the zero case
automatically.
The constant polynomial 1.
Equations
- Hex.DensePoly.instOne = { one := Hex.DensePoly.C 1 }
The leading coefficient of the constant polynomial C c is c itself,
covering both c = 0 (the empty backing array) and c ≠ 0. The simp form
lets callers read the leading coefficient off any constant.
The constant polynomial 1 has leading coefficient 1, hence is monic.
Specialises leadingCoeff_C and feeds the monicity facts about 1 that the
division and gcd routines rely on.
The constant polynomial 1 stores one coefficient when the coefficient
ring's 1 is nonzero.
A polynomial is monic when its leading coefficient is 1.
Equations
- p.Monic = (p.leadingCoeff = 1)
Instances For
A monic polynomial has leading coefficient 1. Forwarding lemma so callers
do not need to unfold Monic.
Characterization of Hex.DensePoly.Monic by the leading coefficient
equation.
For a nonzero normalized dense polynomial, leadingCoeff is the coefficient
at the last stored index.
The leading coefficient of a nonzero normalized dense polynomial is nonzero.
arrayDegreeAux coeffs fuel scans indices below fuel downward and returns the
greatest index whose coefficient is nonzero, or none if every coefficient below fuel is zero.
Equations
- Hex.DensePoly.arrayDegreeAux coeffs 0 = none
- Hex.DensePoly.arrayDegreeAux coeffs fuel.succ = if coeffs.getD fuel Zero.zero = Zero.zero then Hex.DensePoly.arrayDegreeAux coeffs fuel else some fuel
Instances For
arrayDegree? coeffs is the highest index of a nonzero coefficient of coeffs, or none
when every coefficient is zero, computed by scanning from coeffs.size downward.
Equations
- Hex.DensePoly.arrayDegree? coeffs = Hex.DensePoly.arrayDegreeAux coeffs coeffs.size
Instances For
One coefficient of a long-division elimination step: subtract coeff * q[j] from
position shift + j of next, the inner action folded by subtractScaledShift to wipe
out the leading term of the current remainder.
Equations
Instances For
Subtract coeff times the divisor q shifted up by shift positions from the
remainder rem, i.e. one full long-division step rem - coeff * xˢʰⁱᶠᵗ * q, realised by
folding subtractScaledShiftStep over every index of q.
Equations
- Hex.DensePoly.subtractScaledShift rem q shift coeff = List.foldl (Hex.DensePoly.subtractScaledShiftStep q shift coeff) rem (List.range q.size)
Instances For
Runtime implementation of divModArrayAux. Seeds the scan ceiling at rem.size, so
the first iteration is identical to the reference's arrayDegree? rem; thereafter the
ceiling tracks the working degree (see divModArrayAuxImplGo).
Equations
- Hex.DensePoly.divModArrayAuxImpl q qDegree scaleLead fuel quot rem = Hex.DensePoly.divModArrayAuxImplGo✝ q qDegree scaleLead fuel rem.size quot rem
Instances For
The fuel-bounded long-division loop: while the remainder's degree rd is at least
the divisor degree qDegree, pick the quotient coefficient scaleLead (rem[rd]), record
it in quot, eliminate the leading term via subtractScaledShift, and recurse, returning
the final (quotient, remainder) pair. The compiled runtime uses the value-equal
divModArrayAuxImpl (proved by divModArrayAux_eq_impl, registered @[csimp]), which
tracks the working degree instead of rescanning.
Equations
- One or more equations did not get rendered due to their size.
- Hex.DensePoly.divModArrayAux q qDegree scaleLead 0 quot rem = (quot, rem)
Instances For
Register the value-equal divModArrayAuxImpl as the compiled implementation of
divModArrayAux. Unlike @[implemented_by], the @[csimp] swap is backed by the proof
divModArrayAuxImpl_eq, so the runtime loop is verified equal to the specification.
Array-backed long division of dense polynomial p by q: returns (0, p) when q
is zero, otherwise seeds a zero quotient and runs divModArrayAux with p.size fuel,
packaging the resulting coefficient arrays back as DensePoly quotient and remainder.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Remainder-only array-backed long division. This mirrors divModArray but
does not allocate the quotient array or update it during elimination.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The remainder-only array implementation equals the remainder component of the verified quotient/remainder implementation.
The array-backed long division result depends only on the pointwise values of the leading-coefficient scaling function.
For a positive-degree divisor and any scaling function that cancels the leading coefficient, the array-backed long-division loop returns a remainder strictly smaller in degree than the divisor.
Divide by a monic polynomial. The remainder has degree below the divisor whenever the fuel is sufficient, which is the case for normalized dense polynomials.
Equations
- p.divModMonic q _hmonic = p.divModArray q id
Instances For
Polynomial division with remainder over a field.
Equations
Instances For
For a positive-degree divisor, the field-style divMod returns a remainder strictly smaller
in degree, given an explicit cancellation hypothesis for the coefficient ring. Concrete coefficient
libraries discharge hcancel once and re-export this as the unconditional
divMod_remainder_degree_lt_of_pos_degree via the DivModLaws instance.
For a size-one (degree-zero, nonzero) divisor, the field-style divMod returns zero
remainder, given an explicit cancellation hypothesis for the coefficient ring. Concrete coefficient
libraries discharge hcancel once and re-export the result via the DivModLaws instance.
Dividing by a size-zero (zero) polynomial returns the dividend as remainder.
The companion divMod_eq_zero_self_of_size_zero gives the full quotient-and-remainder pair.
Compiled remainder implementation that skips construction of the unused
quotient. The public specification remains mod; the plain GCD's @[csimp]
implementation uses this value-equal worker.
Equations
Instances For
Remainder from long division by a monic polynomial over a commutative ring.
Equations
- p.modByMonic q hmonic = (p.divModMonic q hmonic).snd
Instances For
The / notation on dense polynomials selects to DensePoly.div.
Equations
The % notation on dense polynomials selects to DensePoly.mod.
Equations
Commutative-ring divisibility for dense polynomials.
Equations
- Hex.DensePoly.instDvdOfAddOfMul = { dvd := fun (p q : Hex.DensePoly R) => ∃ (r : Hex.DensePoly R), q = p * r }
Tail-recursive extended Euclidean algorithm tracking only the coefficient of the left input. This avoids the second polynomial multiplication at every step when a consumer needs one inverse coefficient rather than both.
Equations
Instances For
One-sided extended gcd, returning the gcd and only the Bezout coefficient multiplying the left input.
Instances For
Tail-recursive Euclidean gcd tracking only the remainder sequence, without
the Bezout coefficients. xgcd/xgcdAux carry the Bezout accumulators s, t
and update them with a polynomial multiplication (q * s₁, q * t₁) at every
step on polynomials whose degree grows through the run; that is O(deg³) work
and pure waste when only the gcd value is wanted (the common case: the square-free
/ separability test gcd(f, f') = 1). gcdAux keeps only the remainders and is
O(deg²).
Equations
Instances For
Runtime GCD loop using remainder-only long division. Its public
specification remains gcdAux; the equality below supplies a proof-backed
compiler replacement.
Equations
- r₀.gcdAuxImpl r₁ 0 = r₀
- r₀.gcdAuxImpl r₁ fuel_1.succ = if r₁.isZero = true then r₀ else r₁.gcdAuxImpl (r₀.modImpl r₁) fuel_1
Instances For
Proof-backed compiled implementation of plain polynomial GCD that never constructs the discarded Euclidean quotient arrays.
The plain remainder gcd agrees with the gcd component of the extended
algorithm: XGCDResult.gcd never depends on the Bezout accumulators.
Polynomial gcd over a field. Computed by the plain remainder sequence
Hex.DensePoly.gcdAux, not the extended algorithm: the gcd value is independent of the
Bezout coefficients, and computing them costs an extra polynomial multiplication
per step (O(deg³) vs O(deg²)). Hex.DensePoly.xgcd stays available for callers that
genuinely need Bezout coefficients.
Instances For
Law package for the executable dense-polynomial division operations.
The algorithms remain available for any coefficient type with the required operations, but
theorems that use long-division invariants should require this class rather than claiming
those invariants for arbitrary, potentially unlawful Div and Sub instances.
Instances
Law package for the executable dense-polynomial gcd operations.
The generic algorithms are executable for any coefficient type with the required operations, but Euclidean gcd correctness is only true for lawful coefficient/division structures. Concrete coefficient libraries provide this package once they have proved the algorithmic invariants.
Instances
modByMonic is definitionally the second component of divModMonic.
Zero has zero remainder under monic division.
Zero has zero remainder for the executable division algorithm.
When the nonzero left input is strictly smaller than the right input,
resume gcd after its first two Euclidean steps. The explicit fuel is the
fuel of the original execution after those steps, so this preserves its exact
unnormalised remainder representative rather than merely an associate.
The array-backed long-division loop also short-circuits to (0, p) when the dividend
already has degree below the divisor.
If field-style coefficient division agrees pointwise with the monic scaling function, then
the executable monic division path agrees with the general divMod path away from the early
degree shortcut.
Division invariant: for positive-degree divisors, divMod returns a remainder whose
degree is strictly smaller than the divisor degree.
Monic division agrees with field-style division when the divisor is monic. This is the
implementation invariant relating the specialized divModMonic path to divMod.
The computed remainder has degree below a positive-degree divisor.
If q ∣ p, then p % q = 0.
Monic division and the generic % notation agree when the divisor is monic.