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

Require Import ClassicalEpsilon.
Require Import ZArith.
Require Import BV_Gen.

(* range_pred can have an arbitrary value in this realization,
   provided the range is inhabited *)


Definition range_pred : BV_Gen.t -> Prop.
Admitted.

Definition range_inhabited : {x | range_pred x}.
Admitted.

Definition range_pred_dec: forall x: BV_Gen.t, {range_pred x} + {~range_pred x}.
intro r.
destruct (excluded_middle_informative (range_pred r)) as [P | P];
[left | right]; auto.
Qed.

Lemma of_int_to_uint: forall (r:t), (of_int (to_uint r) = r).
intros; unfold of_int, to_uint.
rewrite Nat2Z.id;
rewrite nat_to_bvec_bvec_to_nat; auto.
Qed.

(* Why3 goal *)
Definition t : Type.
exact (sig range_pred).
Defined.

(* Why3 goal *)
Definition rep_type : Type.
exact BV_Gen.t.
Defined.

(* Why3 goal *)
Definition to_rep : t -> rep_type.
intros [r _]; exact r.
Defined.

(* Why3 goal *)
Definition of_rep : rep_type -> t.
intros r.
destruct (range_pred_dec r) as [P | P].
apply (exist _ _ P).
apply range_inhabited.
Defined.

(* Why3 goal *)
Definition in_range : rep_type -> Prop.
exact range_pred.
Defined.

(* Why3 goal *)
Lemma inversion_axiom : forall (x:t), ((of_rep (to_rep x)) = x).
intros [r P].
unfold to_rep, of_rep.
destruct (range_pred_dec r) as [Q | Q].
rewrite (proof_irrelevance (range_pred r) Q P).
auto.
contradict Q; auto.
Qed.

(* Why3 goal *)
Lemma range_axiom : forall (x:t), in_range (to_rep x).
intros [r P]; unfold to_rep; auto.
Qed.

(* Why3 goal *)
Definition rep_to_int : rep_type -> Numbers.BinNums.Z.
exact to_uint.
Defined.

(* Why3 goal *)
Definition in_range_int : Numbers.BinNums.Z -> Prop.
intros r.
exact (in_range (of_int (r))).
Defined.

(* Why3 goal *)
Lemma coerce_axiom :
  forall (x:rep_type), in_range x -> ((to_rep (of_rep x)) = x).
intros r P.
unfold to_rep, of_rep.
destruct (range_pred_dec r) as [Q | Q]; auto.
contradict Q; auto.
Qed.

(* Why3 assumption *)
Definition to_int (x:t) : Numbers.BinNums.Z := rep_to_int (to_rep x).

(* Why3 goal *)
Lemma range_int_axiom : forall (x:t), in_range_int (to_int x).
intros [r P ]; unfold in_range_int, to_int, rep_to_int, to_rep.
rewrite of_int_to_uint; auto.
Qed.
