(************************************************************************)
(*         *      The Rocq Prover / The Rocq Development Team           *)
(*  v      *         Copyright INRIA, CNRS and contributors             *)
(* <O___,, * (see version control and CREDITS file for authors & dates) *)
(*   \VV/  **************************************************************)
(*    //   *    This file is distributed under the terms of the         *)
(*         *     GNU Lesser General Public License Version 2.1          *)
(*         *     (see LICENSE file for the text of the license)         *)
(************************************************************************)
(*            Benjamin Gregoire, Laurent Thery, INRIA, 2007             *)
(************************************************************************)
Require Export DoubleType.
Require ZArith.
Require Export PrimInt63 Uint63Axioms.
Notation int := int (only parsing).
Notation lsl := lsl (only parsing).
Notation lsr := lsr (only parsing).
Notation land := land (only parsing).
Notation lor := lor (only parsing).
Notation lxor := lxor (only parsing).
Notation add := add (only parsing).
Notation sub := sub (only parsing).
Notation mul := mul (only parsing).
Notation mulc := mulc (only parsing).
Notation div := div (only parsing).
Notation mod := mod (only parsing).
Notation eqb := eqb (only parsing).
Notation ltb := ltb (only parsing).
Notation leb := leb (only parsing).
Notation size := Uint63Axioms.size (only parsing).
Notation digits := Uint63Axioms.digits (only parsing).
Notation max_int := Uint63Axioms.max_int (only parsing).
Notation get_digit := Uint63Axioms.get_digit (only parsing).
Notation set_digit := Uint63Axioms.set_digit (only parsing).
Notation is_zero := Uint63Axioms.is_zero (only parsing).
Notation is_even := Uint63Axioms.is_even (only parsing).
Notation bit := Uint63Axioms.bit (only parsing).
Notation addcarry := Uint63Axioms.addcarry (only parsing).
Notation to_Z := Uint63Axioms.to_Z (only parsing).
Notation of_pos := Uint63Axioms.of_pos (only parsing).
Notation of_Z := Uint63Axioms.of_Z (only parsing).
Notation wB := Uint63Axioms.wB (only parsing).
Notation of_to_Z := Uint63Axioms.of_to_Z (only parsing).
Notation lsl_spec := Uint63Axioms.lsl_spec (only parsing).
Notation lsr_spec := Uint63Axioms.lsr_spec (only parsing).
Notation land_spec := Uint63Axioms.land_spec (only parsing).
Notation lor_spec := Uint63Axioms.lor_spec (only parsing).
Notation lxor_spec := Uint63Axioms.lxor_spec (only parsing).
Notation add_spec := Uint63Axioms.add_spec (only parsing).
Notation sub_spec := Uint63Axioms.sub_spec (only parsing).
Notation mul_spec := Uint63Axioms.mul_spec (only parsing).
Notation mulc_spec := Uint63Axioms.mulc_spec (only parsing).
Notation div_spec := Uint63Axioms.div_spec (only parsing).
Notation mod_spec := Uint63Axioms.mod_spec (only parsing).
Notation eqb_correct := Uint63Axioms.eqb_correct (only parsing).
Notation eqb_refl := Uint63Axioms.eqb_refl (only parsing).
Notation ltb_spec := Uint63Axioms.ltb_spec (only parsing).
Notation leb_spec := Uint63Axioms.leb_spec (only parsing).
Notation compare_def_spec := Uint63Axioms.compare_def_spec (only parsing).
Notation head0_spec := Uint63Axioms.head0_spec (only parsing).
Notation tail0_spec := Uint63Axioms.tail0_spec (only parsing).
Notation addc_def_spec := Uint63Axioms.addc_def_spec (only parsing).
Notation addcarryc_def_spec := Uint63Axioms.addcarryc_def_spec (only parsing).
Notation subc_def_spec := Uint63Axioms.subc_def_spec (only parsing).
Notation subcarryc_def_spec := Uint63Axioms.subcarryc_def_spec (only parsing).
Notation diveucl_def_spec := Uint63Axioms.diveucl_def_spec (only parsing).
Notation diveucl_21_spec := Uint63Axioms.diveucl_21_spec (only parsing).
Notation addmuldiv_def_spec := Uint63Axioms.addmuldiv_def_spec (only parsing).
Local Open Scope uint63_scope.
Module Import Uint63NotationsInternalB.
Infix "<<" := lsl (at level 30, no associativity) : uint63_scope.
Infix ">>" := lsr (at level 30, no associativity) : uint63_scope.
Infix "land" := land (at level 40, left associativity) : uint63_scope.
Infix "lor" := lor (at level 40, left associativity) : uint63_scope.
Infix "lxor" := lxor (at level 40, left associativity) : uint63_scope.
Infix "+" := add : uint63_scope.
Infix "-" := sub : uint63_scope.
Infix "*" := mul : uint63_scope.
Infix "/" := div : uint63_scope.
Infix "mod" := mod (at level 40, no associativity) : uint63_scope.
Infix "=?" := eqb (at level 70, no associativity) : uint63_scope.
Infix "<?" := ltb (at level 70, no associativity) : uint63_scope.
Infix "<=?" := leb (at level 70, no associativity) : uint63_scope.
Infix "≤?" := leb (at level 70, no associativity) : uint63_scope.
End Uint63NotationsInternalB.
Register Inline max_int.
Register Inline is_zero.
Register Inline is_even.
(* Register bit as PrimInline. *)
(** Extra modulo operations *)
Definition opp (i:int) := 0 - i.
Register Inline opp.
Definition oppcarry i := max_int - i.
Register Inline oppcarry.
Definition succ i := i + 1.
Register Inline succ.
Definition pred i := i - 1.
Register Inline pred.
Register Inline addcarry.
Definition subcarry i j := i - j - 1.
Register Inline subcarry.
(** Exact arithmetic operations *)
Notation addc := addc (only parsing).
Notation addcarryc := addcarryc (only parsing).
Notation subc := subc (only parsing).
Notation subcarryc := subcarryc (only parsing).
Notation diveucl := diveucl (only parsing).
Notation diveucl_21 := diveucl_21 (only parsing).
Notation addmuldiv := addmuldiv (only parsing).
Module Import Uint63NotationsInternalC.
Notation "- x" := (opp x) : uint63_scope.
Notation "n '+c' m" := (addc n m) (at level 50, no associativity) : uint63_scope.
Notation "n '-c' m" := (subc n m) (at level 50, no associativity) : uint63_scope.
End Uint63NotationsInternalC.
Definition oppc (i:int) := 0 -c i.
Register Inline oppc.
Definition succc i := i +c 1.
Register Inline succc.
Definition predc i := i -c 1.
Register Inline predc.
Notation compare := compare (only parsing).
Notation to_nat i := (Z.to_nat (to_Z i)).
Notation of_nat n := (of_Z (Z.of_nat n)).
Module Import Uint63NotationsInternalD.
Notation "n ?= m" := (compare n m) (at level 70, no associativity) : uint63_scope.
Notation "'φ' x" := (to_Z x) (at level 0) : uint63_scope.
Notation "'Φ' x" :=
(zn2z_to_Z wB to_Z x) (at level 0) : uint63_scope.
End Uint63NotationsInternalD.

(* Specifications: *)
Lemma to_Z_rec_bounded size : forall x, (0 <= to_Z_rec size x < 2 ^ Z.of_nat size)%Z.
Corollary to_Z_bounded : forall x, (0 <= φ  x  < wB)%Z.
(* Results about pow2 *)
Lemma pow2_pos n : 0 <= n → 2 ^ n > 0.
Lemma eqb_spec : forall x y, (x =? y) = true <-> x = y.
Lemma eqb_false_spec : forall x y, (x =? y) = false <-> x <> y.
Lemma eqb_false_complete : forall x y, x <> y -> (x =? y) = false.
Lemma eqb_false_correct : forall x y, (x =? y) = false -> x <> y.
Definition eqs (i j : int) : {i = j} + { i <> j } :=
(if i =? j as b return ((b = true -> i = j) -> (b = false -> i <> j) -> {i=j} + {i <> j} )
then fun (Heq : true = true -> i = j) _ => left _ (Heq (eq_refl true))
else fun _ (Hdiff : false = false -> i <> j) => right _ (Hdiff (eq_refl false)))
(eqb_correct i j)
(eqb_false_correct i j).
Lemma eq_dec : forall i j:int, i = j \/ i <> j.
Definition cast i j :=
(if i =? j as b return ((b = true -> i = j) -> option (forall P : int -> Type, P i -> P j))
then fun Heq : true = true -> i = j =>
Some
(fun (P : int -> Type) (Hi : P i) =>
match Heq (eq_refl true) in (_ = y) return (P y) with
| eq_refl => Hi
end)
else fun _ : false = true -> i = j => None) (eqb_correct i j).