(**************************************************************************)
(*                                                                        *)
(*  This file is part of WP plug-in of Frama-C.                           *)
(*                                                                        *)
(*  Copyright (C) 2007-2020                                               *)
(*    CEA (Commissariat a l'energie atomique et aux energies              *)
(*         alternatives)                                                  *)
(*                                                                        *)
(*  you can redistribute it and/or modify it under the terms of the GNU   *)
(*  Lesser General Public License as published by the Free Software       *)
(*  Foundation, version 2.1.                                              *)
(*                                                                        *)
(*  It is distributed in the hope that it will be useful,                 *)
(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
(*  GNU Lesser General Public License for more details.                   *)
(*                                                                        *)
(*  See the GNU Lesser General Public License version 2.1                 *)
(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
(*                                                                        *)
(**************************************************************************)

(* This file is generated by Why3's Coq-realize driver *)
(* Beware! Only edit allowed sections below    *)
Require Import BuiltIn.
Require BuiltIn.
Require bool.Bool.
Require int.Int.
Require int.Abs.
Require int.EuclideanDivision.
Require int.ComputerDivision.
Require int.ComputerOfEuclideanDivision.
Require real.Real.
Require real.RealInfix.
Require real.FromInt.

(* Why3 goal *)
Definition match_bool {a:Type} {a_WT:WhyType a} : bool -> a -> a -> a.
exact (fun b x y => if b then x else y).
Defined.

(* Why3 goal *)
Lemma match_bool1 {a:Type} {a_WT:WhyType a} :
  forall (p:bool) (x:a) (y:a),
  ((p = true) /\ ((match_bool p x y) = x)) \/
  ((p = false) /\ ((match_bool p x y) = y)).
Proof.
  intros p x y.
  destruct p; intuition.
Qed.

(* Why3 goal *)
Definition eqb {a:Type} {a_WT:WhyType a} : a -> a -> bool.
exact (fun x y => if why_decidable_eq x y then true else false).
Defined.

(* Why3 goal *)
Lemma eqb1 {a:Type} {a_WT:WhyType a} :
  forall (x:a) (y:a), ((eqb x y) = true) <-> (x = y).
Proof.
  intros x y.
  destruct a_WT.
  compute;destruct (why_decidable_eq x y);intuition discriminate.
Qed.

(* Why3 goal *)
Lemma eqb_false {a:Type} {a_WT:WhyType a} :
  forall (x:a) (y:a), ((eqb x y) = false) <-> ~ (x = y).
Proof.
  intros x y.
  destruct a_WT.
  compute;destruct (why_decidable_eq x y);intuition discriminate.
Qed.

(* Why3 goal *)
Definition neqb {a:Type} {a_WT:WhyType a} : a -> a -> bool.
exact (fun x y => if why_decidable_eq x y then false else true).
Defined.

(* Why3 goal *)
Lemma neqb1 {a:Type} {a_WT:WhyType a} :
  forall (x:a) (y:a), ((neqb x y) = true) <-> ~ (x = y).
Proof.
  intros x y.
  destruct a_WT.
  compute;destruct (why_decidable_eq x y);intuition discriminate.
Qed.

(* Why3 goal *)
Definition zlt : Z -> Z -> bool.
exact(Zlt_bool).
Defined.

(* Why3 goal *)
Definition zleq : Z -> Z -> bool.
exact(Zle_bool).
Defined.

(* Why3 goal *)
Lemma zlt1 : forall (x:Z) (y:Z), ((zlt x y) = true) <-> (x < y)%Z.
Proof.
  intros x y.
  assert (T:= Zlt_is_lt_bool x y).
  tauto.
Qed.

(* Why3 goal *)
Lemma zleq1 : forall (x:Z) (y:Z), ((zleq x y) = true) <-> (x <= y)%Z.
Proof.
  intros x y.
  assert (T:= Zle_is_le_bool x y).
  tauto.
Qed.

(* Why3 goal *)
Definition rlt : R -> R -> bool.
exact (fun x y => if Rlt_dec x y then true else false).
Defined.

(* Why3 goal *)
Definition rleq : R -> R -> bool.
exact (fun x y => if Rle_dec x y then true else false).
Defined.

(* Why3 goal *)
Lemma rlt1 : forall (x:R) (y:R), ((rlt x y) = true) <-> (x < y)%R.
Proof.
  intros x y.
  compute;destruct (Rlt_dec x y); intuition discriminate.
Qed.

(* Why3 goal *)
Lemma rleq1 : forall (x:R) (y:R), ((rleq x y) = true) <-> (x <= y)%R.
Proof.
  intros x y.
  compute;destruct (Rle_dec x y);intuition;discriminate.
Qed.

(* Why3 assumption *)
Definition real_of_int (x:Z) : R := (BuiltIn.IZR x).

Lemma lt_is_not_eqb1: forall x y, (x < y -> Z.eqb x y = false)%Z.
Proof.
  intros.
  rewrite Z.eqb_compare.
  rewrite H.
  reflexivity.
Qed.

Lemma lt_is_not_eqb2: forall x y, (y < x -> Z.eqb x y = false)%Z.
Proof.
  intros.
  rewrite Z.eqb_compare.
  rewrite (Z.lt_gt _ _ H).
  reflexivity.
Qed.

(* Why3 goal *)
Lemma c_euclidian :
  forall (n:Z) (d:Z), ~ (d = 0%Z) ->
  (n = (((ZArith.BinInt.Z.quot n d) * d)%Z + (ZArith.BinInt.Z.rem n d))%Z).
Proof.
  intros n d.
  intros H.
  rewrite Int.Comm1.
  exact (ComputerDivision.Div_mod n d H).
Qed.

(* Why3 goal *)
Lemma cmod_remainder :
  forall (n:Z) (d:Z),
  ((0%Z <= n)%Z -> (0%Z < d)%Z ->
   (0%Z <= (ZArith.BinInt.Z.rem n d))%Z /\ ((ZArith.BinInt.Z.rem n d) < d)%Z) /\
  (((n <= 0%Z)%Z -> (0%Z < d)%Z ->
    ((-d)%Z < (ZArith.BinInt.Z.rem n d))%Z /\
    ((ZArith.BinInt.Z.rem n d) <= 0%Z)%Z) /\
   (((0%Z <= n)%Z -> (d < 0%Z)%Z ->
     (0%Z <= (ZArith.BinInt.Z.rem n d))%Z /\
     ((ZArith.BinInt.Z.rem n d) < (-d)%Z)%Z) /\
    ((n <= 0%Z)%Z -> (d < 0%Z)%Z ->
     (d < (ZArith.BinInt.Z.rem n d))%Z /\
     ((ZArith.BinInt.Z.rem n d) <= 0%Z)%Z))).
Proof.
  intros n d.
  (split;[|split;[|split]]);intros;
  [exact (Zquot.Zrem_lt_pos_pos _ _ H H0)|
   exact (Zquot.Zrem_lt_neg_pos _ _ H H0)|
   exact (Zquot.Zrem_lt_pos_neg _ _ H H0)|
   exact (Zquot.Zrem_lt_neg_neg _ _ H H0)].
Qed.

(* Why3 goal *)
Lemma cdiv_neutral : forall (a:Z), ((ZArith.BinInt.Z.quot a 1%Z) = a).
Proof.
  intro a.
  exact (Z.quot_1_r a).
Qed.

(* Why3 goal *)
Lemma cdiv_inv :
  forall (a:Z), ~ (a = 0%Z) -> ((ZArith.BinInt.Z.quot a a) = 1%Z).
Proof.
  intros a h1.
  exact (Z.quot_same a h1).
Qed.

(* Why3 goal *)
Lemma cdiv_closed_remainder : forall (a:Z) (b:Z) (n:Z), (0%Z <= a)%Z ->
  ((0%Z <= b)%Z -> (((0%Z <= (b - a)%Z)%Z /\ ((b - a)%Z < n)%Z) ->
  (((ZArith.BinInt.Z.rem a n) = (ZArith.BinInt.Z.rem b n)) -> (a = b)))).
Proof.
  intros a b n PA PB Range Rem.
  Require Import ZArith.
  Open Scope Z_scope.
  pose (p := a/n).
  pose (q := b/n).
  replace (Z.rem a n) with (a mod n) in Rem by (rewrite Z.rem_mod_nonneg ; auto with zarith).
  replace (Z.rem b n) with (b mod n) in Rem by (rewrite Z.rem_mod_nonneg ; auto with zarith).
  assert (A : a = n * (a/n) + (a mod n)) by (apply Z.div_mod ; auto with zarith). fold p in A.
  assert (B : b = n * (b/n) + (b mod n)) by (apply Z.div_mod ; auto with zarith). fold q in B.
  assert (D : (b-a) = n * q - n * p) by (auto with zarith).
  rewrite <- Z.mul_sub_distr_l in D.
  assert (R : (b-a) = n * ((b-a)/n) + ((b-a) mod n)) by (apply Z.div_mod ; auto with zarith).
  assert (Q : (q-p) = (b-a) / n) by (apply Z.div_unique_exact ; auto with zarith).
  rewrite Q in D.
  assert (Z : (b-a) mod n = 0) by (auto with zarith).
  replace ((b - a) mod n) with (b-a) in Z by (symmetry ; apply Z.mod_small ; auto with zarith).
  auto with zarith.
Qed.

