# Library Coq.Numbers.Natural.BigN.NMake

# NMake

From a cyclic Z/nZ representation to arbitrary precision natural numbers.
NB: This file contain the part which is independent from the underlying representation. The representation-dependent (and macro-generated) part is now in NMake_gen.
Require Import BigNumPrelude ZArith CyclicAxioms.
Require Import Nbasic Wf_nat StreamMemo NSig NMake_gen.
Module Make (Import W0:CyclicType) <: NType.
Macro-generated part
Include NMake_gen.Make W0.

# Predecessor

Lemma spec_pred : forall x, [pred x] = Zmax 0 ([x]-1).

# Subtraction

Lemma spec_sub : forall x y, [sub x y] = Zmax 0 ([x]-[y]).

# Comparison

Theorem spec_compare : forall x y, compare x y = Zcompare [x] [y].
Definition eq_bool x y :=
match compare x y with
| Eq => true
| _ => false
end.
Theorem spec_eq_bool : forall x y, eq_bool x y = Zeq_bool [x] [y].
Theorem spec_eq_bool_aux: forall x y,
if eq_bool x y then [x] = [y] else [x] <> [y].
Definition lt n m := [n] < [m].
Definition le n m := [n] <= [m].
Definition min n m := match compare n m with Gt => m | _ => n end.
Definition max n m := match compare n m with Lt => m | _ => n end.
Theorem spec_max : forall n m, [max n m] = Zmax [n] [m].
Theorem spec_min : forall n m, [min n m] = Zmin [n] [m].

# Power

Fixpoint power_pos (x:t) (p:positive) {struct p} : t :=
match p with
| xH => x
| xO p => square (power_pos x p)
| xI p => mul (square (power_pos x p)) x
end.
Theorem spec_power_pos: forall x n, [power_pos x n] = [x] ^ Zpos n.
Definition power x (n:N) := match n with
| BinNat.N0 => one
| BinNat.Npos p => power_pos x p
end.
Theorem spec_power: forall x n, [power x n] = [x] ^ Z_of_N n.

# Div

Definition div_eucl x y :=
if eq_bool y zero then (zero,zero) else
match compare x y with
| Eq => (one, zero)
| Lt => (zero, x)
| Gt => div_gt x y
end.
Theorem spec_div_eucl: forall x y,
let (q,r) := div_eucl x y in
([q], [r]) = Zdiv_eucl [x] [y].
Definition div x y := fst (div_eucl x y).
Theorem spec_div:
forall x y, [div x y] = [x] / [y].

# Modulo

Definition modulo x y :=
if eq_bool y zero then zero else
match compare x y with
| Eq => zero
| Lt => x
| Gt => mod_gt x y
end.
Theorem spec_modulo:
forall x y, [modulo x y] = [x] mod [y].

# Gcd

Definition gcd_gt_body a b cont :=
match compare b zero with
| Gt =>
let r := mod_gt a b in
match compare r zero with
| Gt => cont r (mod_gt b r)
| _ => b
end
| _ => a
end.
Theorem Zspec_gcd_gt_body: forall a b cont p,
[a] > [b] -> [a] < 2 ^ p ->
(forall a1 b1, [a1] < 2 ^ (p - 1) -> [a1] > [b1] ->
Zis_gcd [a1] [b1] [cont a1 b1]) ->
Zis_gcd [a] [b] [gcd_gt_body a b cont].
Fixpoint gcd_gt_aux (p:positive) (cont:t->t->t) (a b:t) {struct p} : t :=
gcd_gt_body a b
(fun a b =>
match p with
| xH => cont a b
| xO p => gcd_gt_aux p (gcd_gt_aux p cont) a b
| xI p => gcd_gt_aux p (gcd_gt_aux p cont) a b
end).
Theorem Zspec_gcd_gt_aux: forall p n a b cont,
[a] > [b] -> [a] < 2 ^ (Zpos p + n) ->
(forall a1 b1, [a1] < 2 ^ n -> [a1] > [b1] ->
Zis_gcd [a1] [b1] [cont a1 b1]) ->
Zis_gcd [a] [b] [gcd_gt_aux p cont a b].
Definition gcd_cont a b :=
match compare one b with
| Eq => one
| _ => a
end.
Definition gcd_gt a b := gcd_gt_aux (digits a) gcd_cont a b.
Theorem spec_gcd_gt: forall a b,
[a] > [b] -> [gcd_gt a b] = Zgcd [a] [b].
Definition gcd a b :=
match compare a b with
| Eq => a
| Lt => gcd_gt b a
| Gt => gcd_gt a b
end.
Theorem spec_gcd: forall a b, [gcd a b] = Zgcd [a] [b].

# Conversion

Definition of_N x :=
match x with
| BinNat.N0 => zero
| Npos p => of_pos p
end.
Theorem spec_of_N: forall x,
[of_N x] = Z_of_N x.

# Shift

Definition shiftr n x :=
match compare n (Ndigits x) with
| Lt => unsafe_shiftr n x
| _ => N0 w_0
end.
Theorem spec_shiftr: forall n x,
[shiftr n x] = [x] / 2 ^ [n].
Definition shiftl_aux_body cont n x :=
match compare n (head0 x) with
Gt => cont n (double_size x)
| _ => unsafe_shiftl n x
end.
Theorem spec_shiftl_aux_body: forall n p x cont,
2^ Zpos p <= [head0 x] ->
(forall x, 2 ^ (Zpos p + 1) <= [head0 x]->
[cont n x] = [x] * 2 ^ [n]) ->
[shiftl_aux_body cont n x] = [x] * 2 ^ [n].
Fixpoint shiftl_aux p cont n x {struct p} :=
shiftl_aux_body
(fun n x => match p with
| xH => cont n x
| xO p => shiftl_aux p (shiftl_aux p cont) n x
| xI p => shiftl_aux p (shiftl_aux p cont) n x
end) n x.
Theorem spec_shiftl_aux: forall p q n x cont,
2 ^ (Zpos q) <= [head0 x] ->
(forall x, 2 ^ (Zpos p + Zpos q) <= [head0 x] ->
[cont n x] = [x] * 2 ^ [n]) ->
[shiftl_aux p cont n x] = [x] * 2 ^ [n].
Definition shiftl n x :=
shiftl_aux_body
(shiftl_aux_body
(shiftl_aux (digits n) unsafe_shiftl)) n x.
Theorem spec_shiftl: forall n x,
[shiftl n x] = [x] * 2 ^ [n].

# Zero and One

Theorem spec_0: [zero] = 0.
Theorem spec_1: [one] = 1.
End Make.