@@ -460,17 +460,12 @@ end PolyReduce.
460460
461461(* ==================================================================== *)
462462abstract theory PolyReduceZp.
463- type coeff.
464-
465- op p : { int | 2 <= p } as ge2_p.
466463
467- clone import ZModRing as Zp with
468- op p <= p
469- proof ge2_p by exact/ge2_p.
464+ clone import ZModRing as Zp.
470465
471466clone import PolyReduce with
472- type coeff <- Zp.zmod,
473- theory Coeff <- ZModpRing.
467+ type coeff <= Zp.zmod,
468+ theory Coeff <= ZModpRing.
474469
475470(* ==================================================================== *)
476471(* We already know that polyXnD1 is finite. However, we prove here that *)
@@ -526,3 +521,220 @@ lemma reduced_dpoly d p : p \in dpoly n d => reduced p.
526521proof. by rewrite supp_dpoly // => -[ltn_deg _]; apply/reducedP. qed.
527522
528523end PolyReduceZp.
524+
525+ (* ==================================================================== *)
526+ (* PolyReduceZpCentered: same scaffolding as [PolyReduceZp] but the *)
527+ (* coefficient sub-theory is [ZqCentered] (extends [ZModRing] with *)
528+ (* centered representation [crepr], absolute value `|_|`, and the *)
529+ (* abs_zp lemma family). *)
530+ (* *)
531+ (* Built by first cloning [ZqCentered] (to get the extended Zp), then *)
532+ (* clone-including [PolyReduceZp] with PolyReduceZp' s internal Zp *)
533+ (* rebound to ours — so the polynomial-ring construction and the *)
534+ (* distributions are inherited without copy-paste. *)
535+ (* ==================================================================== *)
536+ require import ZModPCentered Nneg.
537+
538+ abstract theory PolyReduceZpCentered.
539+
540+ clone import ZpCentered as ZpC.
541+
542+ clone import PolyReduceZp with
543+ theory Zp <- Zp.
544+ import PolyReduce.
545+ import Zp.
546+
547+ (* ==================================================================== *)
548+ (* Distributions over polyXnD1 — duplicated from PolyReduceZp because *)
549+ (* PolyReduceZp' s internal Zp is not exposed as a rebindable theory *)
550+ (* parameter, so we cannot clone-include it with our extended Zp. *)
551+ (* ==================================================================== *)
552+ op dpolyX (dcoeff : zmod distr) : polyXnD1 distr =
553+ dmap (dpoly n dcoeff) pinject.
554+
555+ lemma dpolyX_ll d : is_lossless d => is_lossless (dpolyX d).
556+ proof. by move=> ll_d; apply/dmap_ll/BasePoly.dpoly_ll. qed.
557+
558+ lemma dpolyX_uni d : is_uniform d => is_uniform (dpolyX d).
559+ proof.
560+ move=> uni_d; apply/dmap_uni_in_inj/dpoly_uni/uni_d => // .
561+ move=> p q; rewrite !supp_dpoly // ; case=> [degp _] [deqq _].
562+ by move/eqv_pi/reduce_eqP; rewrite !reduce_reduced // !reducedP.
563+ qed.
564+
565+ lemma dpolyX_full d : is_full d => is_full (dpolyX d).
566+ proof.
567+ move=> fu_d; apply/dmap_fu_in=> p; exists (crepr p).
568+ by rewrite creprK /=; apply/dpoly_fu/deg_crepr.
569+ qed.
570+
571+ lemma dpolyX_suppP d p :
572+ p \in dpolyX d <=> (forall i, 0 <= i < n => p.[i] \in d).
573+ proof. split.
574+ - case /supp_dmap=> q [+ ->>] i rg_i.
575+ rewrite supp_dpoly => // -[? /(_ i rg_i)].
576+ by rewrite piK // ; apply/reducedP.
577+ - move=> h; apply/supp_dmap; exists (crepr p).
578+ by rewrite creprK /= &(supp_dpoly) // deg_crepr.
579+ qed.
580+
581+ (* -------------------------------------------------------------------- *)
582+ op dpolyXnD1 = dpolyX Zp.DZmodP.dunifin.
583+
584+ lemma dpolyXnD1_ll : is_lossless dpolyXnD1.
585+ proof. by apply/dpolyX_ll/DZmodP.dunifin_ll. qed.
586+
587+ lemma dpolyXnD1_uni : is_uniform dpolyXnD1.
588+ proof. by apply/dpolyX_uni/DZmodP.dunifin_uni. qed.
589+
590+ lemma dpolyXnD1_full : is_full dpolyXnD1.
591+ proof. by apply/dpolyX_full/DZmodP.dunifin_fu. qed.
592+
593+ lemma dpolyXnD1_funi : is_funiform dpolyXnD1.
594+ proof. by apply/is_full_funiform/dpolyXnD1_uni/dpolyXnD1_full. qed.
595+
596+ (* -------------------------------------------------------------------- *)
597+ lemma reduced_dpoly d p : p \in dpoly n d => reduced p.
598+ proof. by rewrite supp_dpoly // => -[ltn_deg _]; apply/reducedP. qed.
599+
600+ (* ==================================================================== *)
601+ (* Centered-representation infinity-norm machinery on polyXnD1. *)
602+ (* *)
603+ (* Two complementary views, equivalent under non-negative bounds: *)
604+ (* - predicate-style checks: poly_infnorm_le, poly_infnorm_lt *)
605+ (* - computed norm: inf_norm : polyXnD1 -> Nneg.nneg *)
606+ (* The soundness lemmas tie them together. *)
607+ (* ==================================================================== *)
608+
609+ (* -------------------------------------------------------------------- *)
610+ (* Predicate-style inf-norm bound checks on coefficients. *)
611+
612+ op poly_infnorm_lt (q : polyXnD1) (b : int ) : bool =
613+ forall i, 0 <= i < n => `|q.[i]| < b.
614+
615+ op poly_infnorm_le (q : polyXnD1) (b : int ) : bool =
616+ forall i, 0 <= i < n => `|q.[i]| <= b.
617+
618+ (* -------------------------------------------------------------------- *)
619+ (* Basic monotonicity / equivalence lemmas. *)
620+
621+ lemma poly_infnorm_lt_le (q : polyXnD1) (b : int ) :
622+ poly_infnorm_lt q b => poly_infnorm_le q b.
623+ proof. by move=> H i Hi; have := H i Hi; smt(). qed.
624+
625+ lemma poly_infnorm_le_mono (q : polyXnD1) (b1 b2 : int ) :
626+ b1 <= b2 => poly_infnorm_le q b1 => poly_infnorm_le q b2.
627+ proof. by move=> Hb H i Hi; have := H i Hi; smt(). qed.
628+
629+ lemma poly_infnorm_lt_mono (q : polyXnD1) (b1 b2 : int ) :
630+ b1 <= b2 => poly_infnorm_lt q b1 => poly_infnorm_lt q b2.
631+ proof. by move=> Hb H i Hi; have := H i Hi; smt(). qed.
632+
633+ (* -------------------------------------------------------------------- *)
634+ (* Trivial bounds. *)
635+
636+ lemma poly_infnorm_le_ub (q : polyXnD1) :
637+ poly_infnorm_le q (p %/ 2 )
638+ by move=> i Hi; smt(abs_zp_ub).
639+
640+ lemma poly_infnorm_le_zero :
641+ poly_infnorm_le zeroXnD1 0 .
642+ proof. move=> i Hi; rewrite rcoeff0; smt(abs_zp_zero). qed.
643+
644+ (* -------------------------------------------------------------------- *)
645+ (* Triangle inequality and negation bounds. *)
646+
647+ lemma poly_infnorm_le_add (q r : polyXnD1) (bq br : int ) :
648+ poly_infnorm_le q bq
649+ => poly_infnorm_le r br
650+ => poly_infnorm_le (q + r) (bq + br).
651+ proof.
652+ move=> Hq Hr i Hi.
653+ rewrite rcoeffD; have := abs_zp_triangle q.[i] r.[i].
654+ have := Hq i Hi; have := Hr i Hi; smt().
655+ qed.
656+
657+ lemma poly_infnorm_lt_add (q r : polyXnD1) (bq br : int ) :
658+ poly_infnorm_lt q bq
659+ => poly_infnorm_lt r br
660+ => poly_infnorm_lt (q + r) (bq + br).
661+ proof.
662+ move=> Hq Hr i Hi.
663+ rewrite rcoeffD; have := abs_zp_triangle q.[i] r.[i].
664+ have := Hq i Hi; have := Hr i Hi; smt().
665+ qed.
666+
667+ lemma poly_infnorm_le_opp (q : polyXnD1) (b : int ) :
668+ poly_infnorm_le q b => poly_infnorm_le (- q) b.
669+ proof.
670+ move=> H i Hi.
671+ rewrite -rcoeffN -abs_zpN.
672+ have := H i Hi; smt().
673+ qed.
674+
675+ lemma poly_infnorm_lt_opp (q : polyXnD1) (b : int ) :
676+ poly_infnorm_lt q b => poly_infnorm_lt (- q) b.
677+ proof.
678+ move=> H i Hi.
679+ rewrite -rcoeffN -abs_zpN.
680+ have := H i Hi; smt().
681+ qed.
682+
683+ (* -------------------------------------------------------------------- *)
684+ (* Computed inf-norm via big-max of coefficient absolute values. *)
685+
686+ op inf_norm (q : polyXnD1) : Nneg.nneg =
687+ Nneg.BMaxN.bigi predT (fun i => Nneg.ofint `|q.[i]|) 0 n.
688+
689+ (* Soundness against the [_le] check (for non-negative bounds). *)
690+ lemma poly_infnorm_le_iff (q : polyXnD1) (b : int ) :
691+ 0 <= b =>
692+ (poly_infnorm_le q b <=> Nneg.(<=) (inf_norm q) (Nneg.ofint b)).
693+ proof.
694+ move=> ge0_b; rewrite /poly_infnorm_le /inf_norm Nneg.BMaxN.big_le_iff.
695+ have valK_b : Nneg.val (Nneg.ofint b) = b by apply Nneg.valK_pos.
696+ have step : forall a, 0 <= a =>
697+ Nneg.(<=) (Nneg.ofint a) (Nneg.ofint b) <=> a <= b.
698+ - move=> a ge0_a; rewrite /Nneg.(<=) valK_b.
699+ by have -> : Nneg.val (Nneg.ofint a) = a by apply Nneg.valK_pos.
700+ split.
701+ - move=> H; split; first by apply Nneg.zero_le.
702+ move=> i; rewrite mem_range => Hi _ /=.
703+ have ge0_a : 0 <= `|q.[i]| by smt ().
704+ by rewrite step // ; apply H; smt().
705+ - case=> _ H i Hi.
706+ have Hi' : i \in range 0 n by rewrite mem_range; smt().
707+ have ge0_a : 0 <= `|q.[i]| by smt ().
708+ have := H i Hi' _; first by [].
709+ by rewrite /= step.
710+ qed.
711+
712+ (* Soundness against the [_lt] check. Strictly-less bound means *)
713+ (* coefficient bounds by [b - 1 ] (since values are integers). *)
714+ lemma poly_infnorm_lt_iff (q : polyXnD1) (b : int ) :
715+ 1 <= b =>
716+ (poly_infnorm_lt q b <=> Nneg.(<=) (inf_norm q) (Nneg.ofint (b - 1 ))).
717+ proof.
718+ move=> ge1_b.
719+ have -> : poly_infnorm_lt q b <=> poly_infnorm_le q (b - 1 )
720+ by rewrite /poly_infnorm_lt /poly_infnorm_le; smt().
721+ by apply poly_infnorm_le_iff; smt().
722+ qed.
723+
724+ end PolyReduceZpCentered.
725+
726+ (* ==================================================================== *)
727+ (* Field version: when [p] is prime, additionally make available the *)
728+ (* prime-only coefficient lemmas (creprN, creprND, creprN2) on the same *)
729+ (* polyXnD1 coefficient instantiation. *)
730+ (* ==================================================================== *)
731+ abstract theory PolyReduceZpCenteredField.
732+
733+ clone import ZpCenteredField as ZpCF.
734+ import ZpC.
735+
736+ clone import PolyReduceZpCentered with
737+ theory ZpC <- ZpC.
738+ import Zp.
739+
740+ end PolyReduceZpCenteredField.
0 commit comments