Ordered product of integer polynomial factors, using left-fold order.
Equations
- factors.polyProduct = Array.foldl (fun (x1 x2 : Hex.ZPoly) => x1 * x2) 1 factors
Instances For
Smallest measured factor count at which the balanced integer product tree beats the retained left fold on the Hensel linear-factor family.
Equations
Instances For
Exclusive end of the measured winning interval. At 1024 linear factors the left fold is reproducibly faster and also uses substantially less memory.
Equations
- Array.treeProductLimit = 1024
Instances For
The product-tree crossover was measured on monic linear factors whose non-leading coefficient has absolute value at most four. Larger-degree or wider factors follow the retained fold: BZ-shaped measurements show that a factor-count-only decision can reverse sharply as intermediate coefficient width grows. The guard also admits constants, zero, and non-monic linear factors satisfying the same coefficient bound.
Equations
Instances For
Select the product tree within its measured count and coefficient bounds.
Equations
- factors.useProductTree = (decide (Array.treeProductMin ≤ factors.size) && decide (factors.size < Array.treeProductLimit) && factors.treeProductEligible)
Instances For
Compiled ordered-product dispatcher. The balanced tree is selected only
on the measured small-linear-factor interval; both branches preserve the exact
ordered product observed by polyProduct.
Equations
- factors.polyProductImpl = if factors.useProductTree = true then (Hex.DensePoly.ProductTree.build Hex.ZPoly.fastPlan factors).root else Array.foldl (fun (x1 x2 : Hex.ZPoly) => x1 * x2) 1 factors
Instances For
The compiled product-tree dispatch is extensionally the specified ordered left fold, independently of its measured crossover constants.
Extended gcd witnesses scaled so their Bezout combination is monic when the raw Euclidean gcd is a nonzero constant unit.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The normalised xgcd witnesses still satisfy the Bezout identity, now for the normalised gcd component.
If the normalised xgcd component is 1, its lifted witnesses give the
integer-polynomial Bezout congruence needed to initialise a Hensel split.
Recursive list-shape worker behind multifactorLift. At each
non-singleton step it lifts the head factor g against the running
complementary product Array.polyProduct rest.toArray via henselLift, and
recurses with lifted.h as the new target on rest. The singleton case
returns the input reduced modulo p^k; the empty case returns the empty
array.
Equations
- One or more equations did not get rendered due to their size.
- Hex.ZPoly.multifactorLiftList p k f [] = #[]
- Hex.ZPoly.multifactorLiftList p k f [_g] = #[f.reduceModPow p k]
Instances For
Lift an ordered array of factors from congruence modulo p to congruence
modulo p^k.
Equations
- Hex.ZPoly.multifactorLift p k f factors = Hex.ZPoly.multifactorLiftList p k f factors.toList
Instances For
Recursive preconditions required by the sequential multifactor lift.
In the g :: h :: tail arm, the four conjuncts are exactly the inputs
henselLift_spec consumes for the binary split of g against the running
complementary product Array.polyProduct (h :: tail).toArray, followed by the
recursive precondition for the lifted complement:
LinearLiftLoopInvariantatn = 1; initial state for the linear loop;the step-degree invariant at every iteration
n ≥ 1;the step-Bezout congruence at every iteration
n ≥ 1;MultifactorLiftInvariantfor the recursive tail withlifted.has the new target.
The base cases impose the trivial obligations: congr 1 f (p ^ k) for the
empty list and no preconditions for a singleton.
This invariant is proof-internal: it is the correctness substrate consumed
by multifactorLift_spec and by the Mathlib-side lift-uniqueness statement
HexHenselTheory.multifactorLift_eq_multifactorLiftQuadratic, and is not
intended to be constructed directly by external callers. Unlike the quadratic
path, no multifactorLiftInvariant_of_factorsModP smart constructor is
provided: the four-conjunct shape mentions per-iteration LinearLiftLoopInvariant
and LinearLiftStepDegreeInvariant quantifications that would require
substrate lemmas (an of_product_bezout_monic constructor for
LinearLiftLoopInvariant, plus henselLift_h_congr_mod_base and
henselLift_h_monic analogues of the quadratic recursive correspondence) that
HexHensel/Linear.lean does not currently expose.
Callers wanting a consumer-facing Hensel-lift correctness surface should use
the quadratic flavour QuadraticMultifactorLiftInvariant, constructed from
natural mod-p factorisation facts by
quadraticMultifactorLiftInvariant_of_factorsModP (with the
QuadraticMultifactorLiftInvariant_of_choosePrimeData wrapper at the
Berlekamp-Zassenhaus boundary). The executable Berlekamp-Zassenhaus computation
already uses the quadratic invariant exclusively
(HexBerlekampZassenhaus/Basic.lean). A Mathlib-side downstream caller that
needs the linear-path lifted factors modulo p^k should obtain them via
HexHenselTheory.multifactorLift_eq_multifactorLiftQuadratic, which equates
the two paths under the Mathlib Polynomial.map (Int.castRingHom (ZMod (p^k)))
canonicalisation.
Equations
- One or more equations did not get rendered due to their size.
- Hex.ZPoly.MultifactorLiftInvariant p k f [] = Hex.ZPoly.congr 1 f (p ^ k)
- Hex.ZPoly.MultifactorLiftInvariant p k f [_g] = True
Instances For
Left identity for ZPoly multiplication, used to reason about
Array.polyProduct as a left fold from 1. Shared by the linear and
quadratic multifactor proofs.
Array.polyProduct of a singleton array is just the element.
Associativity helper for product invariants: folding (· * ·) over a
List ZPoly with seed g factors out as g times the same fold with seed
1. This is not a simp normal form because both sides contain the same
left fold.
Splitting Array.polyProduct across a singleton prepend: the head
factors out as a left multiplication. Used to relate the multifactor
recursion tree to the public ordered-product convention. Left untagged as
@[simp] because downstream Mathlib-side proofs use large recursive product terms
where this rewrite is better applied explicitly.
Array.polyProduct of the empty array is the multiplicative unit.
Array.polyProduct splits as a product across array concatenation.
Array.polyProduct over (g :: rest).toArray factors the head out as a
left multiplication. The List-flavoured analogue of
polyProduct_singleton_append. Left untagged as @[simp] for the same
downstream performance reason: callers use it explicitly at product-splitting
points.
Array.polyProduct of a two-element array is the product of the two
entries.
Array.polyProduct over a zero-length replicated list is the
multiplicative unit.
The product of the lifted factors is congruent to f modulo p^k, provided
each recursive binary split supplies the linear Hensel invariant package.