(* This file is generated by Why3's Coq driver *)
(* Beware! Only edit allowed sections below    *)
Require Import BuiltIn.
Require BuiltIn.
Require HighOrd.
Require int.Int.
Require int.Abs.
Require int.EuclideanDivision.
Require int.ComputerDivision.
Require map.Map.
Require number.Parity.
Require number.Divisibility.
Require number.Prime.

(* Why3 assumption *)
Inductive ref (a:Type) :=
  | ref'mk : a -> ref a.
Axiom ref_WhyType : forall (a:Type) {a_WT:WhyType a}, WhyType (ref a).
Existing Instance ref_WhyType.
Arguments ref'mk {a}.

(* Why3 assumption *)
Definition contents {a:Type} {a_WT:WhyType a} (v:ref a) : a :=
  match v with
  | ref'mk x => x
  end.

(* Why3 assumption *)
Definition no_prime_in (l:Numbers.BinNums.Z) (u:Numbers.BinNums.Z) : Prop :=
  forall (x:Numbers.BinNums.Z), (l < x)%Z /\ (x < u)%Z ->
  ~ number.Prime.prime x.

(* Why3 assumption *)
Definition first_primes (p:Numbers.BinNums.Z -> Numbers.BinNums.Z)
    (u:Numbers.BinNums.Z) : Prop :=
  ((p 0%Z) = 2%Z) /\
  (forall (i:Numbers.BinNums.Z) (j:Numbers.BinNums.Z),
   (0%Z <= i)%Z /\ (i < j)%Z /\ (j < u)%Z -> ((p i) < (p j))%Z) /\
  (forall (i:Numbers.BinNums.Z), (0%Z <= i)%Z /\ (i < u)%Z ->
   number.Prime.prime (p i)) /\
  (forall (i:Numbers.BinNums.Z), (0%Z <= i)%Z /\ (i < (u - 1%Z)%Z)%Z ->
   no_prime_in (p i) (p (i + 1%Z)%Z)).

Require Import Lia.

(* Why3 goal *)
Theorem exists_prime :
  forall (p:Numbers.BinNums.Z -> Numbers.BinNums.Z) (u:Numbers.BinNums.Z),
  (1%Z <= u)%Z -> first_primes p u -> forall (d:Numbers.BinNums.Z),
  (2%Z <= d)%Z /\ (d <= (p (u - 1%Z)%Z))%Z -> number.Prime.prime d ->
  exists i:Numbers.BinNums.Z, ((0%Z <= i)%Z /\ (i < u)%Z) /\ (d = (p i)).
(* Why3 intros p u h1 h2 d (h3,h4) h5. *)
Proof.
intros p u hu. generalize hu.
pattern u; apply natlike_ind; intros. 3: lia.
apply False_ind; lia.
assert (case: (x=0 \/ 0 < x)%Z) by lia. destruct case.
subst x.
exists Z0; split.
lia.
red in H1.
simpl in H2.
assert (d = 2)%Z by lia.
subst; lia.
ring_simplify (Z.succ x - 1)%Z in H2.
assert (case: (d <= p (x-1) \/ p (x-1) < d)%Z) by lia. destruct case.
destruct H0 with (d := d) as (i, (hi1, hi2)); intuition.
destruct H1 as (p0, (sorted, (only_primes, all_primes))).
red; split.
auto.
split; intros.
apply sorted; lia.
split; intros.
apply only_primes; lia.
apply all_primes; lia.
exists i; intuition.
assert (case: (d = p x \/ d < p x)%Z) by lia. destruct case.
exists x; intuition.
apply False_ind.
destruct H1 as (_, (_, (_, h))).
revert H3.
apply (h (x-1)%Z); try lia.
ring_simplify (x-1+1)%Z; now split.
Qed.

