@@ -1049,79 +1049,121 @@ Qed.
10491049Definition inIntSpan (V : zmodType) m (s : m.-tuple V) v :=
10501050 exists a : int ^ m, v = \sum_(i < m) s`_i *~ a i.
10511051
1052- Lemma dec_Qint_span (vT : vectType rat) m (s : m.-tuple vT) v :
1053- decidable (inIntSpan s v).
1052+ Lemma solve_Qint_span (vT : vectType rat) m (s : m.-tuple vT) v :
1053+ {b : int ^ m &
1054+ {p : seq (int ^ m) &
1055+ forall a : int ^ m,
1056+ v = \sum_(i < m) s`_i *~ a i <->
1057+ exists c : seq int, a = b + \sum_(i < size p) p`_i *~ c`_i}} +
1058+ (~ inIntSpan s v).
10541059Proof .
10551060have s_s (i : 'I_m): s`_i \in <<s>>%VS by rewrite memv_span ?memt_nth.
10561061have s_Zs a: \sum_(i < m) s`_i *~ a i \in <<s>>%VS.
10571062 by apply/rpred_sum => i _; apply/rpredMz.
10581063case s_v: (v \in <<s>>%VS); last by right=> [[a Dv]]; rewrite Dv s_Zs in s_v.
1059- pose S := \matrix_(i < m, j < _) coord (vbasis <<s>>) j s`_i.
1060- pose r := \rank S; pose k := (m - r)%N; pose Em := erefl m; pose Ek := erefl k.
1061- have Dm: (m = k + r)%N by rewrite subnK ?rank_leq_row.
1064+ move SE : (\matrix_(i < m, j < _) coord (vbasis <<s>>) j s`_i) => S.
1065+ move rE : (\rank S) => r; move kE : (m - r)%N => k.
1066+ have Dm: (m = k + r)%N by rewrite -kE -rE subnK ?rank_leq_row.
1067+ rewrite Dm in s s_s s_Zs s_v S SE rE kE *.
1068+ move=> {Dm m}; pose m := (k + r)%N.
10621069have [K kerK]: {K : 'M_(k, m) | map_mx intr K == kermx S}%MS.
1070+ move: (mxrank_ker S); rewrite rE kE => krk.
10631071 pose B := row_base (kermx S); pose d := \prod_ij denq (B ij.1 ij.2).
1064- exists (castmx (mxrank_ker S, Em) (map_mx numq (intr d *: B))).
1065- rewrite /k; case: _ / (mxrank_ker S); set B1 := map_mx _ _.
1066- have ->: B1 = (intr d *: B).
1067- apply/matrixP=> i j; rewrite 3!mxE mulrC [d](bigD1 (i, j)) // rmorphM mulrA.
1072+ exists (castmx (krk, erefl m) (map_mx numq (intr d *: B))).
1073+ rewrite map_castmx !eqmx_cast -map_mx_comp map_mx_id_in => [|i j]; last first.
1074+ rewrite mxE mulrC [d](bigD1 (i, j)) //= rmorphM mulrA.
10681075 by rewrite -numqE -rmorphM numq_int.
1069- suffices nz_d: d%:Q != 0 by rewrite !eqmx_scale // !eq_row_base andbb.
1076+ suff nz_d: d%:Q != 0 by rewrite !eqmx_scale // !eq_row_base andbb.
10701077 by rewrite intr_eq0; apply/prodf_neq0 => i _; apply: denq_neq0.
10711078have [L _ [G uG [D _ defK]]] := int_Smith_normal_form K.
1072- pose Gud := castmx (Dm, Em) G; pose G'lr := castmx (Em, Dm) (invmx G).
1073- have{K L D defK kerK} kerGu: map_mx intr (usubmx Gud) *m S = 0 .
1074- pose Kl : 'M[rat]_k:= map_mx intr (lsubmx (castmx (Ek, Dm) ( K *m invmx G) )).
1075- have{} defK: map_mx intr K = row_mx Kl 0 *m map_mx intr Gud .
1076- rewrite -[K](mulmxKV uG) -{2}[G](castmxK Dm Em) -/Gud .
1077- rewrite -[K *m _](castmxK Ek Dm) map_mxM map_castmx .
1078- rewrite -(hsubmxK (castmx _ _)) map_row_mx -/Kl map_castmx /Em .
1079- set Kr := map_mx _ _; case: _ / (esym Dm) (map_mx _ _) => /= GudQ .
1080- congr (row_mx _ _ *m _); apply/matrixP=> i j; rewrite !mxE defK mulmxK //=.
1081- rewrite castmxE mxE big1 //= => j1 _; rewrite mxE /= eqn_leq andbC.
1079+ have {K L D defK kerK} [kerGu kerS_sub_Gu]: map_mx intr (usubmx G) *m S = 0 /\
1080+ (kermx S <= map_mx intr (usubmx G))%MS .
1081+ pose Kl : 'M[rat]_k := map_mx intr (lsubmx (K *m invmx G)).
1082+ have {} defK: map_mx intr K = Kl *m map_mx intr (usubmx G) .
1083+ rewrite /Kl -map_mxM; congr map_mx .
1084+ rewrite -[LHS](mulmxKV uG) -{2}[G]vsubmxK -{1}[ K *m _]hsubmxK .
1085+ rewrite mul_row_col -[RHS]addr0; congr (_ + _) .
1086+ rewrite defK mulmxK //= -[RHS](mul0mx _ (dsubmx G)); congr (_ *m _) .
1087+ apply/matrixP => i j; rewrite !mxE big1 //= => j1 _ .
1088+ rewrite mxE /= eqn_leq andbC.
10821089 by rewrite leqNgt (leq_trans (valP j1)) ?mulr0 ?leq_addr.
1083- have /row_full_inj: row_full Kl; last apply.
1084- rewrite /row_full eqn_leq rank_leq_row /= -{1}[k](mxrank_ker S).
1085- rewrite -(eqmxP kerK) defK map_castmx mxrankMfree; last first.
1086- case: _ / (Dm); apply/row_freeP; exists (map_mx intr (invmx G)).
1087- by rewrite -map_mxM mulmxV ?map_mx1.
1088- by rewrite -mxrank_tr tr_row_mx trmx0 -addsmxE addsmx0 mxrank_tr.
1089- rewrite mulmx0 mulmxA (sub_kermxP _) // -(eqmxP kerK) defK.
1090- by rewrite -{2}[Gud]vsubmxK map_col_mx mul_row_col mul0mx addr0.
1091- pose T := map_mx intr (dsubmx Gud) *m S.
1092- have{kerGu} defS: map_mx intr (rsubmx G'lr) *m T = S.
1093- have: G'lr *m Gud = 1%:M by rewrite /G'lr /Gud; case: _ / (Dm); apply: mulVmx.
1094- rewrite -{1}[G'lr]hsubmxK -[Gud]vsubmxK mulmxA mul_row_col -map_mxM.
1095- move/(canRL (addKr _))->; rewrite -mulNmx raddfD /= map_mx1 map_mxM /=.
1090+ split; last by rewrite -(eqmxP kerK); apply/submxP; exists Kl.
1091+ suff /row_full_inj: row_full Kl.
1092+ by apply; rewrite mulmx0 mulmxA (sub_kermxP _) // -(eqmxP kerK) defK.
1093+ rewrite /row_full eqn_leq rank_leq_row /= -{1}kE -{2}rE -(mxrank_ker S).
1094+ by rewrite -(eqmxP kerK) defK mxrankM_maxl.
1095+ pose T := map_mx intr (dsubmx G) *m S.
1096+ have defS: map_mx intr (rsubmx (invmx G)) *m T = S.
1097+ rewrite mulmxA -map_mxM /=; move: (mulVmx uG).
1098+ rewrite -{2}[G]vsubmxK -{1}[invmx G]hsubmxK mul_row_col.
1099+ move/(canRL (addKr _)) ->; rewrite -mulNmx raddfD /= map_mx1 map_mxM /=.
10961100 by rewrite mulmxDl -mulmxA kerGu mulmx0 add0r mul1mx.
10971101pose vv := \row_j coord (vbasis <<s>>) j v.
10981102have uS: row_full S.
10991103 apply/row_fullP; exists (\matrix_(i, j) coord s j (vbasis <<s>>)`_i).
1100- apply/matrixP=> j1 j2; rewrite !mxE.
1104+ apply/matrixP => j1 j2; rewrite !mxE.
11011105 rewrite -(coord_free _ _ (basis_free (vbasisP _))).
11021106 rewrite -!tnth_nth (coord_span (vbasis_mem (mem_tnth j1 _))) linear_sum.
1103- by apply: eq_bigr => i _; rewrite !mxE (tnth_nth 0) !linearZ.
1107+ by apply: eq_bigr => /= i _; rewrite -SE !mxE (tnth_nth 0) !linearZ.
11041108have eqST: (S :=: T)%MS by apply/eqmxP; rewrite -{1}defS !submxMl.
1105- case Zv: (map_mx denq (vv *m pinvmx T) == const_mx 1).
1106- pose a := map_mx numq (vv *m pinvmx T) *m dsubmx Gud.
1107- left; exists [ffun j => a 0 j].
1108- transitivity (\sum_j (map_mx intr a *m S) 0 j *: (vbasis <<s>>)`_j).
1109+ case Zv: (map_mx denq (vv *m pinvmx T) == const_mx 1); last first.
1110+ right=> [[a Dv]]; case/eqP: Zv; apply/rowP.
1111+ have ->: vv = map_mx intr (\row_i a i) *m S.
1112+ apply/rowP => j; rewrite !mxE Dv linear_sum.
1113+ by apply: eq_bigr => i _; rewrite -SE -scaler_int linearZ !mxE.
1114+ rewrite -defS -2!mulmxA; have ->: T *m pinvmx T = 1%:M.
1115+ have uT: row_free T by rewrite /row_free -eqST rE.
1116+ by apply: (row_free_inj uT); rewrite mul1mx mulmxKpV.
1117+ by move=> i; rewrite mulmx1 -map_mxM 2!mxE denq_int mxE.
1118+ pose b := map_mx numq (vv *m pinvmx T) *m dsubmx G.
1119+ left; exists [ffun j => b 0 j], [seq [ffun j => (usubmx G) i j] | i : 'I_k].
1120+ rewrite size_image card_ord => a; rewrite -[a](addNKr [ffun j => b 0 j]).
1121+ move: (_ + a) => h; under eq_bigr => i _ do rewrite !ffunE mulrzDr.
1122+ rewrite big_split /=.
1123+ have <-: v = \sum_(i < m) s`_i *~ b 0 i.
1124+ transitivity (\sum_j (map_mx intr b *m S) 0 j *: (vbasis <<s>>)`_j).
11091125 rewrite {1}(coord_vbasis s_v); apply: eq_bigr => j _; congr (_ *: _).
1110- have ->: map_mx intr a = vv *m pinvmx T *m map_mx intr (dsubmx Gud ).
1111- rewrite map_mxM /=; congr (_ *m _); apply/rowP=> i; rewrite 2!mxE numqE .
1112- by have /eqP/rowP/ (_ i)/[!mxE]-> := Zv ; rewrite mulr1 .
1113- by rewrite -(mulmxA _ _ S) mulmxKpV ?mxE // -eqST submx_full .
1126+ suff ->: map_mx intr b = vv *m pinvmx T *m map_mx intr (dsubmx G ).
1127+ by rewrite -(mulmxA _ _ S) mulmxKpV ?mxE // -eqST submx_full .
1128+ rewrite map_mxM /=; congr (_ *m _); apply/rowP => i ; rewrite 2!mxE numqE .
1129+ by have /eqP/rowP/(_ i)/[!mxE] -> := Zv; rewrite mulr1 .
11141130 rewrite (coord_vbasis (s_Zs _)); apply: eq_bigr => j _; congr (_ *: _).
1115- rewrite linear_sum mxE; apply: eq_bigr => /= i _.
1116- by rewrite mxE mulrzl mxE ffunE raddfMz.
1117- right=> [[a Dv]]; case/eqP: Zv; apply/rowP.
1118- have ->: vv = map_mx intr (\row_i a i) *m S.
1119- apply/rowP=> j; rewrite !mxE Dv linear_sum.
1120- by apply: eq_bigr => i _; rewrite !mxE raddfMz mulrzl.
1121- rewrite -defS -2!mulmxA; have ->: T *m pinvmx T = 1%:M.
1122- have uT: row_free T by rewrite /row_free -eqST.
1123- by apply: (row_free_inj uT); rewrite mul1mx mulmxKpV.
1124- by move=> i; rewrite mulmx1 -map_mxM 2!mxE denq_int mxE.
1131+ rewrite linear_sum mxE; apply: eq_bigr => i _.
1132+ by rewrite -SE -scaler_int linearZ [b]lock !mxE.
1133+ split.
1134+ rewrite -[LHS]addr0 => /addrI hP; pose c := \row_i h i *m lsubmx (invmx G).
1135+ exists [seq c 0 i | i : 'I_k]; congr (_ + _).
1136+ have/sub_kermxP: map_mx intr (\row_i h i) *m S = 0.
1137+ transitivity (\row_j coord (vbasis <<s>>) j (\sum_(i < m) s`_i *~ h i)).
1138+ apply/rowP => j; rewrite !mxE linear_sum; apply: eq_bigr => i _.
1139+ by rewrite -SE !mxE -scaler_int linearZ.
1140+ by apply/rowP => j; rewrite !mxE -hP linear0.
1141+ case/submx_trans/(_ kerS_sub_Gu)/submxP => c' /[dup].
1142+ move/(congr1 (mulmx^~ (map_mx intr (lsubmx (invmx G))))).
1143+ rewrite -mulmxA -!map_mxM [in RHS]mulmx_lsub mul_usub_mx -/c mulmxV //=.
1144+ rewrite scalar_mx_block -/(ulsubmx _) block_mxKul map_scalar_mx mulmx1.
1145+ move=> <- {c'}; rewrite -map_mxM /= => defh; apply/ffunP => j.
1146+ move/rowP/(_ j): defh; rewrite sum_ffunE !mxE => /intr_inj ->.
1147+ apply: eq_bigr => i _; rewrite ffunMzE mulrzz mulrC.
1148+ rewrite (nth_map i) ?size_enum_ord // nth_ord_enum ffunE.
1149+ by rewrite (nth_map i) ?size_enum_ord // nth_ord_enum.
1150+ case=> c /addrI -> {h}; rewrite -[LHS]addr0; congr (_ + _).
1151+ pose h := \row_(j < k) c`_j *m usubmx G.
1152+ transitivity (\sum_j (map_mx intr h *m S) 0 j *: (vbasis <<s>>)`_j).
1153+ by rewrite map_mxM -mulmxA kerGu mulmx0 big1 // => j _; rewrite mxE scale0r.
1154+ rewrite (coord_vbasis (s_Zs _)); apply: eq_bigr => i _; congr (_ *: _).
1155+ rewrite linear_sum -SE mxE; apply: eq_bigr => j _.
1156+ rewrite -scaler_int linearZ !mxE sum_ffunE; congr (_%:~R * _).
1157+ apply: {i} eq_bigr => i _; rewrite mxE ffunMzE mulrzz mulrC.
1158+ by rewrite (nth_map i) ?size_enum_ord // ffunE nth_ord_enum.
1159+ Qed .
1160+
1161+ Lemma dec_Qint_span (vT : vectType rat) m (s : m.-tuple vT) v :
1162+ decidable (inIntSpan s v).
1163+ Proof .
1164+ have [[b [p aP]]|] := solve_Qint_span s v; last by right.
1165+ left; exists b; apply/(aP b); exists [::]; rewrite big1 ?addr0 // => i _.
1166+ by rewrite nth_nil mulr0z.
11251167Qed .
11261168
11271169Lemma eisenstein_crit (p : nat) (q : {poly int}) : prime p -> (size q != 1)%N ->
0 commit comments