(**************************************************************)
(*   Copyright Dominique Larchey-Wendling [*]                 *)
(*             Yannick Forster            [+]                 *)
(*                                                            *)
(*                             [*] Affiliation LORIA -- CNRS  *)
(*                             [+] Affiliation Saarland Univ. *)
(**************************************************************)
(*      This file is distributed under the terms of the       *)
(*         CeCILL v2 FREE SOFTWARE LICENSE AGREEMENT          *)
(**************************************************************)
(* ** Two infinite sequences of primes *)
From Undecidability.Shared.Libs.DLW
Set Implicit Arguments.
Local Notation "e #> x" := (vec_pos e x).
Local Notation "e [ v / x ]" := (vec_change e x v).
Set Implicit Arguments.
(* Unique decomposition with a prime *)
Hint Resolve prime_neq_0 : core.
(* The unboundedness of primes *)
Definition nxtprime n := proj1_sig (first_prime_above n).
Fact nxtprime_spec1 n : n < nxtprime n.
Fact notprime_bool_rec_spec n k : notprime_bool_rec n k = true <-> forall i, n <= i < k+n -> ~ prime i.
Definition nxtprime_bool n p := Nat.leb (S n) p && notprime_bool_rec (S n) (p - S n) && prime_bool p.
Fact nxtprime_bool_spec n p : nxtprime_bool n p = true <-> nxtprime n = p.
Definition nthprime (n : nat) := iter nxtprime 2 n.
Fact nthprime_nxt i p q : nthprime i = p -> nxtprime p = q -> nthprime (S i) = q.
(* Certified Erastosthene sieve would be helpfull here *)
Fact nthprime_0 : nthprime 0 = 2.
Definition ps : primestream.
Fact exp_app n m i v w : @exp (n+m) i (vec_app v w) = exp i v * exp (n+i) w.
Local Notation divides_mult_inv := prime_div_mult.
Hint Resolve not_prime_1 not_qs_1 : core.
Opaque ps qs.
Coercion tonat {n} := @pos2nat n.
Proof with eauto.
revert i j; induction v; intros i j Hi.
+ cbn; intros ? % divides_1_inv % not_qs_1; auto.
+ cbn; intros [ H % divides_pow | H  ] % divides_mult_inv; eauto.
* eapply primestream_divides in H; lia.
* eapply IHv in H; eauto.
Qed.

Lemma inv_exp q p1 p2 x y :
q <> 0
-> ~ divides q p1
-> ~ divides q p2
-> q ^ x * p1 = q ^ y * p2
-> x = y.