(********************************************************************)
(*                                                                  *)
(*  The Why3 Verification Platform   /   The Why3 Development Team  *)
(*  Copyright 2010-2018   --   Inria - CNRS - Paris-Sud University  *)
(*                                                                  *)
(*  This software is distributed under the terms of the GNU Lesser  *)
(*  General Public License version 2.1, with the special exception  *)
(*  on linking described in file LICENSE.                           *)
(*                                                                  *)
(********************************************************************)

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

Require Import Flocq.Core.Fcore.
Require Import Fourier.

(* Why3 goal *)
Notation truncate := Ztrunc.

(* Why3 goal *)
Lemma Truncate_int : forall (i:Z), ((truncate (BuiltIn.IZR i)) = i).
Proof.
  intro i.
  rewrite <-Z2R_IZR.
  apply Ztrunc_Z2R.
Qed.

(* Why3 goal *)
Lemma Truncate_down_pos : forall (x:R), (0%R <= x)%R ->
  (((BuiltIn.IZR (truncate x)) <= x)%R /\
  (x < (BuiltIn.IZR ((truncate x) + 1%Z)%Z))%R).
Proof.
  intros x h.
  rewrite (Ztrunc_floor x h), <-Z2R_IZR, <-Z2R_IZR.
  split.
  apply Zfloor_lb.
  rewrite Z2R_plus; simpl.
  apply Zfloor_ub.
Qed.

(* Why3 goal *)
Lemma Truncate_up_neg : forall (x:R), (x <= 0%R)%R ->
  (((BuiltIn.IZR ((truncate x) - 1%Z)%Z) < x)%R /\
  (x <= (BuiltIn.IZR (truncate x)))%R).
Proof.
  intros x h.
  rewrite (Ztrunc_ceil x h), <-Z2R_IZR, <-Z2R_IZR.
  split;[|apply Zceil_ub].
  case (Req_dec (Z2R (Zfloor x)) x); intro.
  rewrite <-H, Zceil_Z2R, H, Z2R_minus; simpl.
  fourier.
  rewrite (Zceil_floor_neq _ H).
  rewrite Z2R_minus, Z2R_plus; simpl.
  pose proof (Zfloor_lb x).
  destruct (Rle_lt_or_eq_dec _ _ H0); try easy.
  fourier.
Qed.

(* Why3 goal *)
Lemma Real_of_truncate : forall (x:R),
  ((x - 1%R)%R <= (BuiltIn.IZR (truncate x)))%R /\
  ((BuiltIn.IZR (truncate x)) <= (x + 1%R)%R)%R.
Proof.
  intro x.
  rewrite <- (Z2R_IZR (truncate x)).
  destruct (Rle_lt_dec x 0).
  + rewrite Ztrunc_ceil; auto.
    destruct (Req_dec (Z2R (Zfloor x)) x).
    rewrite <-H at 2 3; rewrite Zceil_Z2R, H; split; fourier.
    rewrite Zceil_floor_neq; auto.
    pose proof (Zfloor_lb x);
      pose proof (Zfloor_ub x).
    rewrite Z2R_plus; simpl Z2R; split; fourier.
  + rewrite Ztrunc_floor by fourier.
    pose proof (Zfloor_lb x);
      pose proof (Zfloor_ub x).
    split; fourier.
Qed.

(* Why3 goal *)
Lemma Truncate_monotonic : forall (x:R) (y:R), (x <= y)%R ->
  ((truncate x) <= (truncate y))%Z.
Proof.
  apply Ztrunc_le.
Qed.

(* Why3 goal *)
Lemma Truncate_monotonic_int1 : forall (x:R) (i:Z),
  (x <= (BuiltIn.IZR i))%R -> ((truncate x) <= i)%Z.
Proof.
  intros x i h.
  rewrite <-Z2R_IZR in h.
  destruct (Rle_lt_dec x 0).
  + rewrite Ztrunc_ceil; auto.
    apply Zceil_glb; assumption.
  + rewrite Ztrunc_floor by fourier.
    apply le_Z2R.
    apply Rle_trans with (r2:=x);[apply Zfloor_lb|assumption].
Qed.

(* Why3 goal *)
Lemma Truncate_monotonic_int2 : forall (x:R) (i:Z),
  ((BuiltIn.IZR i) <= x)%R -> (i <= (truncate x))%Z.
Proof.
  intros x i h.
  rewrite <-Z2R_IZR in h.
  destruct (Rle_lt_dec x 0).
  + rewrite Ztrunc_ceil; auto.
    apply le_Z2R.
    apply Rle_trans with (r2:=x);[assumption|apply Zceil_ub].
  + rewrite Ztrunc_floor by fourier.
    apply Zfloor_lub; assumption.
Qed.

(* Why3 goal *)
Notation floor := Zfloor.

(* Why3 goal *)
Notation ceil := Zceil.

(* Why3 goal *)
Lemma Floor_int : forall (i:Z), ((floor (BuiltIn.IZR i)) = i).
Proof.
  intro i; rewrite <-Z2R_IZR.
  apply Zfloor_Z2R.
Qed.

(* Why3 goal *)
Lemma Ceil_int : forall (i:Z), ((ceil (BuiltIn.IZR i)) = i).
Proof.
  intro i; rewrite <-Z2R_IZR.
  apply Zceil_Z2R.
Qed.

(* Why3 goal *)
Lemma Floor_down : forall (x:R), ((BuiltIn.IZR (floor x)) <= x)%R /\
  (x < (BuiltIn.IZR ((floor x) + 1%Z)%Z))%R.
Proof.
  intro x.
  rewrite <-Z2R_IZR, <-Z2R_IZR; split.
  apply Zfloor_lb.
  rewrite Z2R_plus.
  apply Zfloor_ub.
Qed.

Lemma ceil_lb: forall x, ((Z2R (ceil x) - 1) < x).
Proof.
  intro.
  case (Req_dec (Z2R (Zfloor x)) x); intro.
  rewrite <-H, Zceil_Z2R, H; simpl; fourier.
  rewrite (Zceil_floor_neq _ H).
  rewrite Z2R_plus; simpl.
  pose proof (Zfloor_lb x).
  destruct (Rle_lt_or_eq_dec _ _ H0); try easy.
  fourier.
Qed.

(* Why3 goal *)
Lemma Ceil_up : forall (x:R), ((BuiltIn.IZR ((ceil x) - 1%Z)%Z) < x)%R /\
  (x <= (BuiltIn.IZR (ceil x)))%R.
Proof.
intro x.
rewrite <-Z2R_IZR, <-Z2R_IZR; split; [|apply Zceil_ub].
rewrite Z2R_minus.
apply ceil_lb.
Qed.

(* Why3 goal *)
Lemma Floor_monotonic : forall (x:R) (y:R), (x <= y)%R ->
  ((floor x) <= (floor y))%Z.
Proof.
  apply Zfloor_le.
Qed.

(* Why3 goal *)
Lemma Ceil_monotonic : forall (x:R) (y:R), (x <= y)%R ->
  ((ceil x) <= (ceil y))%Z.
Proof.
  apply Zceil_le.
Qed.

