(************************************************************************)
(*         *   The Coq Proof Assistant / The Coq 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             *)
(************************************************************************)
From Corelib Require Export PrimInt63.
Local Open Scope Z_scope.
Local Notation "0" := Z0 : Z_scope.
Local Notation "1" := (Zpos 1) : Z_scope.
Local Notation "2" := (Zpos 2) : Z_scope.
Local Infix "+" := Z.add : Z_scope.
Local Infix "-" := Z.sub : Z_scope.
Local Infix "*" := Z.mul : Z_scope.
Local Infix "^" := Z.pow : Z_scope.
Local Infix "<=" := Z.le : Z_scope.
Local Infix "<" := Z.lt : Z_scope.
Local Notation "x <= y < z" := (x <= y /\ y < z) : Z_scope.
Definition size := 63%nat.
(** The number of digits as an int *)
Definition digits := 63%uint63.
(** The biggest int *)
Definition max_int := Eval vm_compute in sub 0 1.
(** Access to the nth digits *)
Definition get_digit x p := ltb 0 (land x (lsl 1 p)).
Definition set_digit x p (b:bool) :=
if if leb 0 p then ltb p digits else false then
if b then lor x (lsl 1 p)
else land x (lxor max_int (lsl 1 p))
else x.
(** Translation to Z *)
Definition is_zero (i:int) := eqb i 0.
Definition is_even (i:int) := is_zero (land i 1).
Fixpoint to_Z_rec (n:nat) (i:int) :=
match n with
| O => 0
| S n =>
(if is_even i then Z.double else Z.succ_double) (to_Z_rec n (lsr i 1))
end.
Definition to_Z := to_Z_rec size.
Fixpoint of_pos_rec (n:nat) (p:positive) {struct p} :=
match n, p with
| O, _ => 0%uint63
| S n, xH => 1%uint63
| S n, xO p => lsl (of_pos_rec n p) 1
| S n, xI p => lor (lsl (of_pos_rec n p) 1) 1
end.
Definition of_pos := of_pos_rec size.
Definition of_Z z :=
match z with
| Zpos p => of_pos p
| 0 => 0%uint63
| Zneg p => sub 0 (of_pos p)
end.
Definition wB := 2 ^ (Z.of_nat size).
(* Bijection : uint63 <-> Bvector size *)

(** Specification of basic opetations *)
(* Arithmetic modulo operations *)
(* Note: axioms would be simpler if we were using of_Z instead: example: add_spec : forall x y, of_Z (x + y) = of_Z x + of_Z y. *)
Axiom add_spec : forall x y, to_Z (add x y) = Z.modulo (to_Z x + to_Z y) wB.