Library PrimeGapS1.MaynardSpecBridge
From Stdlib Require Import ZArith List Lia Znumtheory.
Import ListNotations.
From mathcomp Require Import all_ssreflect all_algebra.
Import GRing.Theory.
From PrimeGapS1 Require Import
MaynardFactQ MaynardBasis MaynardSpec CharPoly.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Local Open Scope ring_scope.
Lemma factZ_eq_Z_of_nat (n : nat) :
factZ n = BinInt.Z.of_nat n`!.
Proof.
elim: n ⇒ [//|n IH] /=.
rewrite IH factS.
by rewrite -multE Nat2Z.inj_mul.
Qed.
Lemma Z_to_int_factZ (n : nat) :
Z_to_int (factZ n) = Posz n`!.
Proof. by rewrite factZ_eq_Z_of_nat Z_to_int_of_nat. Qed.
Lemma factZ_to_rat (n : nat) :
((Z_to_int (factZ n))%:~R : rat) = factQ n.
Proof. by rewrite Z_to_int_factZ /factQ. Qed.
Lemma fact_dvd_fact (m n : nat) :
(m ≤ n)%nat → (m`! %| n`!)%nat.
Proof.
elim: n ⇒ [|n IH] H.
- by rewrite leqn0 in H; rewrite (eqP H).
- rewrite factS.
case: (leqP m n) ⇒ Hmn.
+ apply: dvdn_mull; exact: (IH Hmn).
+ have → : m = n.+1 by apply/eqP; rewrite eqn_leq H Hmn.
exact: dvdnn.
Qed.
Lemma Z_of_nat_dvd (a b : nat) :
(a %| b)%nat → (Z.of_nat a | Z.of_nat b)%Z.
Proof.
move⇒ /dvdnP[k Hk]. ∃ (Z.of_nat k).
by rewrite Hk -multE Nat2Z.inj_mul Z.mul_comm.
Qed.
Lemma factZ_dvd_double (x : nat) :
(factZ x | factZ (2 × x)%nat)%Z.
Proof.
rewrite !factZ_eq_Z_of_nat.
apply: Z_of_nat_dvd; apply: fact_dvd_fact.
by rewrite leq_pmull.
Qed.
Lemma factZ_pos (n : nat) : Z.lt 0 (factZ n).
Proof.
rewrite factZ_eq_Z_of_nat.
have /ltP H := fact_gt0 n.
lia.
Qed.
Lemma Z_to_int_pos_neq0 (z : Z) : Z.lt 0 z → Z_to_int z != 0.
Proof.
case: z ⇒ [|p _|p H] //.
rewrite Z_to_int_pos_pos eqz_nat -lt0n.
apply/ltP; exact: Pos2Nat.is_pos.
Qed.
Lemma Z_to_int_pos_rat_neq0 (z : Z) :
Z.lt 0 z → ((Z_to_int z)%:~R : rat) != 0.
Proof.
by move⇒ /Z_to_int_pos_neq0; rewrite intr_eq0.
Qed.
Lemma Z_to_int_div_exact (a b : Z) :
Z.lt 0 b → (b | a)%Z →
((Z_to_int (a / b))%:~R : rat)
= (Z_to_int a)%:~R / (Z_to_int b)%:~R.
Proof.
move⇒ Hbpos Hdvd.
have Hnz : ((Z_to_int b)%:~R : rat) != 0 by exact: Z_to_int_pos_rat_neq0.
apply: (canRL (mulfK Hnz)).
rewrite -intrM -Z_to_int_mul Z.mul_comm.
by rewrite -Zdivide_Zdiv_eq.
Qed.
Lemma dblratZ_to_rat (x : nat) :
((Z_to_int (dblratZ x))%:~R : rat)
= factQ (2 × x) / factQ x.
Proof.
rewrite /dblratZ Z_to_int_div_exact ?factZ_to_rat //.
- exact: factZ_pos.
- exact: factZ_dvd_double.
Qed.
Lemma prod_dblratZ_to_rat (a : list nat) :
((Z_to_int (prod_dblratZ a))%:~R : rat)
= \prod_(x <- a) (factQ (2 × x) / factQ x).
Proof.
elim: a ⇒ [|x a IH] /=.
- by rewrite Z_to_int_1_rat big_nil.
- rewrite Z_to_int_mul intrM dblratZ_to_rat IH.
by rewrite big_cons.
Qed.
Lemma cffZ_to_rat (a : list nat) :
((Z_to_int (cffZ a))%:~R : rat) = cff a.
Proof.
by rewrite /cffZ /cff prod_dblratZ_to_rat.
Qed.
Lemma bin_dvd_fact (n k : nat) :
(k ≤ n)%nat → (k`! × (n - k)`! %| n`!)%nat.
Proof.
move⇒ Hkn. apply/dvdnP. ∃ 'C(n,k).
by rewrite -(bin_fact Hkn).
Qed.
Lemma factZ_factZ_dvd (n k : nat) :
(k ≤ n)%nat →
(factZ k × factZ (n - k)%nat | factZ n)%Z.
Proof.
move⇒ Hkn.
rewrite !factZ_eq_Z_of_nat -Nat2Z.inj_mul.
apply: Z_of_nat_dvd. exact: bin_dvd_fact.
Qed.
Lemma factZ_factZ_pos (n k : nat) :
Z.lt 0 (factZ k × factZ (n - k)%nat).
Proof.
apply: Z.mul_pos_pos; exact: factZ_pos.
Qed.
Lemma binQ_factQ (n k : nat) :
(k ≤ n)%nat →
binQ n k = factQ n / (factQ k × factQ (n - k)%nat).
Proof.
move⇒ Hkn.
have Hnz : factQ k × factQ (n - k)%nat != 0
by rewrite mulf_neq0 ?factQ_neq0.
apply: (canRL (mulfK Hnz)).
rewrite /binQ /factQ -natrM -natrM.
apply/eqP. rewrite Num.Theory.eqr_nat. apply/eqP.
exact: bin_fact.
Qed.
Lemma Nat_leb_leqP k n : reflect (k ≤ n)%N (Nat.leb k n).
Proof. by apply: (iffP idP) ⇒ [/Nat.leb_le/leP|/leP/Nat.leb_le]. Qed.
Lemma binZ_to_rat (n k : nat) :
((Z_to_int (binZ n k))%:~R : rat) = binQ n k.
Proof.
rewrite /binZ.
case: Nat_leb_leqP ⇒ Hkn.
- rewrite Z_to_int_div_exact;
[|exact: factZ_factZ_pos|exact: factZ_factZ_dvd Hkn].
rewrite Z_to_int_mul intrM !factZ_to_rat.
by rewrite -binQ_factQ.
- rewrite Z_to_int_0 /=.
have {}Hkn : (n < k)%N by rewrite ltnNge; apply/negP.
rewrite /binQ (bin_small Hkn) /=.
by rewrite mulr0n.
Qed.
Lemma iota_seq_eq (m n : nat) : iota m n = List.seq m n.
Proof. exact: erefl. Qed.
Lemma flatten_concat T (s : seq (seq T)) :
flatten s = List.concat s.
Proof. exact: erefl. Qed.
Lemma seq_map_eq T1 T2 (f : T1 → T2) (l : seq T1) :
[seq f x | x <- l] = List.map f l.
Proof. exact: erefl. Qed.
Lemma flat_map_concat_map T1 T2 (f : T1 → list T2) (l : list T1) :
List.flat_map f l = List.concat (List.map f l).
Proof. by elim: l ⇒ [|x l IH] //=; rewrite IH. Qed.
Lemma compositions_auxZ_eq (r remaining : nat) :
compositions_auxZ r remaining = compositions_aux r remaining.
Proof.
elim: r remaining ⇒ [|r IH] remaining /=.
- case: (Nat.eqb_spec remaining 0) ⇒ [-> //|H].
by have → : (remaining == 0)%N = false by apply/eqP.
- rewrite flat_map_concat_map -flatten_concat.
rewrite -seq_map_eq -iota_seq_eq.
congr (flatten _). apply: eq_map ⇒ a /=.
by rewrite IH seq_map_eq.
Qed.
Lemma compositionsZ_eq_compositions (r n : nat) :
compositionsZ r n = compositions r n.
Proof. exact: compositions_auxZ_eq. Qed.
Lemma fold_left_Zadd_acc (xs : list Z) (acc : Z) :
List.fold_left Z.add xs acc = Z.add acc (List.fold_left Z.add xs Z0).
Proof.
elim: xs acc ⇒ [|x xs IH] acc /=.
- by rewrite Z.add_0_r.
- rewrite IH (IH (Z.add Z0 x)).
by rewrite Z.add_0_l Z.add_assoc.
Qed.
Lemma fold_left_Zadd_sum (xs : list Z) :
((Z_to_int (List.fold_left Z.add xs Z0))%:~R : rat) =
\sum_(z <- xs) ((Z_to_int z)%:~R).
Proof.
elim: xs ⇒ [|x xs IH] /=.
- rewrite big_nil. by [].
- rewrite fold_left_Zadd_acc /=.
rewrite Z_to_int_add intrD IH big_cons.
by rewrite addrC.
Qed.
Lemma G2Z_to_rat (n k : nat) :
((Z_to_int (G2Z n k))%:~R : rat) = G_2 n k.
Proof.
rewrite /G2Z /G_2.
case: n ⇒ [|n].
- by rewrite Z_to_int_1_rat.
- rewrite Z_to_int_mul intrM factZ_to_rat.
congr (_ × _).
rewrite fold_left_Zadd_sum -seq_map_eq -iota_seq_eq big_map.
apply: eq_big_seq ⇒ r Hr.
rewrite Z_to_int_mul intrM binZ_to_rat.
congr (_ × _).
rewrite fold_left_Zadd_sum -seq_map_eq -compositionsZ_eq_compositions big_map.
apply: eq_big_seq ⇒ a Ha.
by rewrite cffZ_to_rat.
Qed.
Definition qfrac (p : Z × Z) : rat :=
(Z_to_int p.1)%:~R / (Z_to_int p.2)%:~R.
Lemma qfrac_pair (a b : Z) :
qfrac (a, b) = (Z_to_int a)%:~R / (Z_to_int b)%:~R.
Proof. by []. Qed.
Lemma qfrac_qmul (p q : Z × Z) :
qfrac (qmul p q) = qfrac p × qfrac q.
Proof.
case: p ⇒ [a b]; case: q ⇒ [c d].
rewrite /qfrac /qmul /=.
rewrite !Z_to_int_mul !intrM.
by rewrite mulf_div.
Qed.
Lemma qfrac_qplus (p q : Z × Z) :
Z_to_int p.2 != 0 → Z_to_int q.2 != 0 →
qfrac (qplus p q) = qfrac p + qfrac q.
Proof.
case: p ⇒ [a b]; case: q ⇒ [c d] /= Hb Hd.
rewrite /qfrac /qplus /=.
rewrite Z_to_int_add !Z_to_int_mul !intrD !intrM.
by rewrite addf_div ?intr_eq0.
Qed.
Lemma alphaZ_to_rat (b c cp : nat) :
qfrac (alphaZ b c cp) = alpha b c cp.
Proof.
rewrite /qfrac /alphaZ /alpha /=.
by rewrite !Z_to_int_mul !intrM !factZ_to_rat binZ_to_rat.
Qed.
Lemma m1_num_den_to_rat (bi ci bj cj : nat) :
qfrac (m1_num_den bi ci bj cj) = M1_entry bi ci bj cj.
Proof.
rewrite /qfrac /m1_num_den /M1_entry.
rewrite Z_to_int_mul intrM !factZ_to_rat G2Z_to_rat.
by rewrite mulrAC.
Qed.
Lemma M1_spec_rat_eq (i j : nat) :
M1_spec_ij i j = qfrac (m1_num_den_at i j).
Proof.
rewrite /M1_spec_ij /m1_num_den_at.
by rewrite m1_num_den_to_rat.
Qed.
Lemma Z_to_int_factZ_neq0 (n : nat) : Z_to_int (factZ n) != 0.
Proof. apply: Z_to_int_pos_neq0. exact: factZ_pos. Qed.
Lemma Z_to_int_qplus_den_neq0 (a b : Z × Z) :
Z_to_int a.2 != 0 → Z_to_int b.2 != 0 →
Z_to_int (qplus a b).2 != 0.
Proof.
case: a ⇒ [n d]; case: b ⇒ [n' d'] /= Hd Hd'.
by rewrite Z_to_int_mul mulf_neq0.
Qed.
Lemma Z_to_int_qmul_den_neq0 (a b : Z × Z) :
Z_to_int a.2 != 0 → Z_to_int b.2 != 0 →
Z_to_int (qmul a b).2 != 0.
Proof.
case: a ⇒ [n d]; case: b ⇒ [n' d'] /= Hd Hd'.
by rewrite Z_to_int_mul mulf_neq0.
Qed.
Lemma Z_to_int_alphaZ_den_neq0 (b c cp : nat) :
Z_to_int (alphaZ b c cp).2 != 0.
Proof. by rewrite /alphaZ /=; exact: Z_to_int_factZ_neq0. Qed.
Lemma Z_to_int_m2_term_den_neq0 bi ci bj cj cp1 cp2 :
Z_to_int (m2_term_num_den bi ci bj cj cp1 cp2).2 != 0.
Proof.
rewrite /m2_term_num_den.
apply: Z_to_int_qmul_den_neq0.
- apply: Z_to_int_qmul_den_neq0; exact: Z_to_int_alphaZ_den_neq0.
- exact: Z_to_int_factZ_neq0.
Qed.
Lemma m2_term_to_rat (bi ci bj cj cp1 cp2 : nat) :
qfrac (m2_term_num_den bi ci bj cj cp1 cp2) =
let bp1 := (bi + 2 × ci - 2 × cp1 + 1)%N in
let bp2 := (bj + 2 × cj - 2 × cp2 + 1)%N in
let bsum := (bp1 + bp2)%N in
let csum := (cp1 + cp2)%N in
alpha bi ci cp1 × alpha bj cj cp2
× factQ bsum / factQ (K2 + bsum + 2 × csum)%N
× G_2 csum K2.
Proof.
cbv zeta.
rewrite /m2_term_num_den.
cbv zeta.
rewrite !qfrac_qmul !alphaZ_to_rat.
rewrite qfrac_pair.
rewrite Z_to_int_mul intrM factZ_to_rat factZ_to_rat G2Z_to_rat.
rewrite -(_ : K2n = K2) //.
by rewrite !mulrA mulrAC.
Qed.
Lemma fold_left_qplus_qfrac (l : list (Z × Z)) (acc : Z × Z) :
Z_to_int acc.2 != 0 →
(∀ t, List.In t l → Z_to_int t.2 != 0) →
qfrac (List.fold_left qplus l acc) =
qfrac acc + \sum_(t <- l) qfrac t.
Proof.
elim: l acc ⇒ [|t l IH] acc Hacc Hl /=.
- by rewrite big_nil addr0.
- have Ht : Z_to_int t.2 != 0 by apply: Hl; left.
rewrite IH.
+ rewrite qfrac_qplus //.
by rewrite big_cons addrA.
+ by apply: Z_to_int_qplus_den_neq0.
+ move⇒ t' Ht'. apply: Hl. by right.
Qed.
Lemma fold_left_qplus_den_neq0 (l : list (Z × Z)) (acc : Z × Z) :
Z_to_int acc.2 != 0 →
(∀ t, List.In t l → Z_to_int t.2 != 0) →
Z_to_int (List.fold_left qplus l acc).2 != 0.
Proof.
elim: l acc ⇒ [|x l IH] acc Hacc Hl //=.
apply: IH.
- apply: Z_to_int_qplus_den_neq0 ⇒ //. apply: Hl. by left.
- move⇒ t Ht. apply: Hl. by right.
Qed.
Lemma fold_left_inner_to_map (T : Type) (l : list T) (g : T → Z × Z) (acc : Z × Z) :
List.fold_left (fun acc' x ⇒ qplus acc' (g x)) l acc =
List.fold_left qplus (List.map g l) acc.
Proof. by elim: l acc ⇒ [|x l IH] acc //=; rewrite IH. Qed.
Lemma fold_left_pointwise_eq (T1 T2 : Type)
(f g : T1 → T2 → T1) (l : list T2) (acc : T1) :
(∀ a x, f a x = g a x) →
List.fold_left f l acc = List.fold_left g l acc.
Proof.
move⇒ Hfg. elim: l acc ⇒ [|x l IH] acc //=.
by rewrite Hfg IH.
Qed.
Lemma qfrac_init : qfrac (Z0, Zpos xH) = (0 : rat).
Proof.
rewrite /qfrac /=.
by rewrite mul0r.
Qed.
Lemma inner_row_sum (l : list nat) bi ci bj cj cp1 :
\sum_(t <- List.map (m2_term_num_den bi ci bj cj cp1) l) qfrac t =
\sum_(cp2 <- l) qfrac (m2_term_num_den bi ci bj cj cp1 cp2).
Proof. by rewrite -seq_map_eq big_map. Qed.
Lemma m2_outer_qfrac (outer : list nat) (acc : Z × Z) bi ci bj cj :
Z_to_int acc.2 != 0 →
qfrac (List.fold_left
(fun acc' cp1 ⇒ List.fold_left qplus
(List.map (m2_term_num_den bi ci bj cj cp1) (List.seq 0 (S cj)))
acc')
outer acc) =
qfrac acc +
\sum_(cp1 <- outer)
\sum_(cp2 <- List.seq 0 (S cj))
qfrac (m2_term_num_den bi ci bj cj cp1 cp2).
Proof.
elim: outer acc ⇒ [|cp1 outer IH] acc Hacc /=.
- by rewrite big_nil addr0.
- have Hin : ∀ t,
List.In t (List.map (m2_term_num_den bi ci bj cj cp1) (List.seq 0 (S cj))) →
Z_to_int t.2 != 0.
move⇒ t /List.in_map_iff[cp2 [<- _]]. exact: Z_to_int_m2_term_den_neq0.
have Hnext : Z_to_int (List.fold_left qplus
(List.map (m2_term_num_den bi ci bj cj cp1) (List.seq 0 (S cj))) acc).2 != 0
by apply: fold_left_qplus_den_neq0.
have Hterm0 : Z_to_int (m2_term_num_den bi ci bj cj cp1 0).2 != 0
by exact: Z_to_int_m2_term_den_neq0.
have Hacc' : Z_to_int (qplus acc (m2_term_num_den bi ci bj cj cp1 0)).2 != 0
by apply: Z_to_int_qplus_den_neq0.
have Hrest : ∀ t : Z × Z,
List.In t (List.map (m2_term_num_den bi ci bj cj cp1) (List.seq 1 cj)) →
Z_to_int t.2 != 0.
move⇒ t Ht. apply: Hin. by right.
rewrite IH //.
rewrite fold_left_qplus_qfrac //.
rewrite qfrac_qplus //.
rewrite -!addrA.
congr (qfrac acc + _).
rewrite [in RHS]big_cons.
rewrite [\sum_(cp2 <- (0%N :: _)) _]big_cons.
rewrite !addrA.
by rewrite inner_row_sum.
Qed.
Lemma m2_num_den_to_rat bi ci bj cj :
qfrac (m2_num_den bi ci bj cj) = M2_entry bi ci bj cj.
Proof.
rewrite /m2_num_den /M2_entry.
rewrite (fold_left_pointwise_eq
(g := fun acc' cp1 ⇒ List.fold_left qplus
(List.map (m2_term_num_den bi ci bj cj cp1) (List.seq 0 (S cj)))
acc'));
last by move⇒ a x; rewrite fold_left_inner_to_map.
rewrite m2_outer_qfrac; last by [].
rewrite qfrac_init add0r -iota_seq_eq.
apply: eq_big_seq ⇒ cp1 _.
rewrite -iota_seq_eq.
apply: eq_big_seq ⇒ cp2 _.
by rewrite m2_term_to_rat.
Qed.
Lemma M2_spec_rat_eq (i j : nat) :
M2_spec_ij i j = qfrac (m2_num_den_at i j).
Proof.
rewrite /M2_spec_ij /m2_num_den_at.
by rewrite m2_num_den_to_rat.
Qed.
Lemma m1_num_den_den_pos bi ci bj cj :
Z.lt 0 (m1_num_den bi ci bj cj).2.
Proof. exact: factZ_pos. Qed.
Lemma m1_num_den_at_den_pos i j : Z.lt 0 (m1_num_den_at i j).2.
Proof. exact: m1_num_den_den_pos. Qed.
Lemma qplus_den_pos (a b : Z × Z) :
Z.lt 0 a.2 → Z.lt 0 b.2 → Z.lt 0 (qplus a b).2.
Proof.
case: a ⇒ [na da]; case: b ⇒ [nb db] /= Ha Hb.
exact: Z.mul_pos_pos.
Qed.
Lemma fold_left_qplus_den_pos {T : Type} (l : list T)
(g : T → Z × Z) (acc : Z × Z) :
Z.lt 0 acc.2 →
(∀ x, Z.lt 0 (g x).2) →
Z.lt 0 (List.fold_left (fun a x ⇒ qplus a (g x)) l acc).2.
Proof.
elim: l acc ⇒ [//|x xs IH] acc Hacc Hg.
apply: IH; [|exact: Hg].
exact: qplus_den_pos Hacc (Hg x).
Qed.
Lemma m2_term_num_den_den_pos bi ci bj cj cp1 cp2 :
Z.lt 0 (m2_term_num_den bi ci bj cj cp1 cp2).2.
Proof.
apply: Z.mul_pos_pos; last exact: factZ_pos.
apply: Z.mul_pos_pos; exact: factZ_pos.
Qed.
Lemma m2_num_den_den_pos bi ci bj cj :
Z.lt 0 (m2_num_den bi ci bj cj).2.
Proof.
rewrite /m2_num_den.
have Hloop : ∀ (l : list nat) (acc : Z × Z),
Z.lt 0 acc.2 →
Z.lt 0 (List.fold_left
(fun a cp1 ⇒ List.fold_left
(fun b cp2 ⇒ qplus b
(m2_term_num_den bi ci bj cj cp1 cp2))
(List.seq 0 (S cj)) a)
l acc).2.
{ elim ⇒ [//|cp1 cp1_rest IH] acc Hacc.
apply: IH.
apply: fold_left_qplus_den_pos ⇒ // cp2.
exact: m2_term_num_den_den_pos. }
by apply: Hloop.
Qed.
Lemma m2_num_den_at_den_pos i j : Z.lt 0 (m2_num_den_at i j).2.
Proof. exact: m2_num_den_den_pos. Qed.
Definition Z2rat (z : Z) : rat := (Z_to_int z)%:~R.
Lemma qfrac_eq_div (a b c d : Z) :
Z.lt 0 b → Z.lt 0 d →
BinInt.Z.mul a d = BinInt.Z.mul c b →
qfrac (a, b) = Z2rat c / Z2rat d.
Proof.
move⇒ Hb Hd Heq.
rewrite /qfrac /Z2rat /=.
have Hbz : ((Z_to_int b)%:~R : rat) != 0 by exact: Z_to_int_pos_rat_neq0.
have Hdz : ((Z_to_int d)%:~R : rat) != 0 by exact: Z_to_int_pos_rat_neq0.
apply/eqP; rewrite eqr_div //.
by rewrite -!intrM -!Z_to_int_mul Heq.
Qed.