(** [Z.of_N] produce non-negative integers *)

(* Specifications: *)
Lemma is_nonneg n : 0 <= Z.of_nat n.
(** [Z.of_nat] is a bijection between [nat] and non-negative [Z], with [Z.to_nat] (or [Z.abs_nat]) as reciprocal. See [Z2Nat.id] below for the dual equation. *)
Lemma id n : Z.to_nat (Z.of_nat n) = n.
(** [Z.of_nat] is hence injective *)
Lemma inj n m : Z.of_nat n = Z.of_nat m -> n = m.
Lemma inj_iff n m : Z.of_nat n = Z.of_nat m <-> n = m.
(** [Z.of_nat] and usual operations *)
Lemma inj_compare n m : (Z.of_nat n ?= Z.of_nat m) = (n ?= m)%nat.
Lemma inj_le n m : (n<=m)%nat <-> Z.of_nat n <= Z.of_nat m.
Lemma inj_lt n m : (n<m)%nat <-> Z.of_nat n < Z.of_nat m.
Lemma inj_ge n m : (n>=m)%nat <-> Z.of_nat n >= Z.of_nat m.
Lemma inj_gt n m : (n>m)%nat <-> Z.of_nat n > Z.of_nat m.
Lemma inj_abs_nat z : Z.of_nat (Z.abs_nat z) = Z.abs z.
Lemma inj_add n m : Z.of_nat (n+m) = Z.of_nat n + Z.of_nat m.
Register inj_add as num.Nat2Z.inj_add.
Lemma inj_mul n m : Z.of_nat (n*m) = Z.of_nat n * Z.of_nat m.
Register inj_mul as num.Nat2Z.inj_mul.
Lemma inj_sub_max n m : Z.of_nat (n-m) = Z.max 0 (Z.of_nat n - Z.of_nat m).
Lemma inj_sub n m : (m<=n)%nat -> Z.of_nat (n-m) = Z.of_nat n - Z.of_nat m.
Register inj_sub as num.Nat2Z.inj_sub.
Lemma inj_pred_max n : Z.of_nat (Nat.pred n) = Z.max 0 (Z.pred (Z.of_nat n)).
Lemma inj_pred n : (0<n)%nat -> Z.of_nat (Nat.pred n) = Z.pred (Z.of_nat n).
Lemma inj_min n m : Z.of_nat (Nat.min n m) = Z.min (Z.of_nat n) (Z.of_nat m).
Lemma inj_max n m : Z.of_nat (Nat.max n m) = Z.max (Z.of_nat n) (Z.of_nat m).
Lemma inj_div n m : Z.of_nat (n / m) = Z.of_nat n / Z.of_nat m.
Lemma inj_mod n m : Z.of_nat (n mod m) = (Z.of_nat n mod Z.of_nat m)%Z.
Lemma inj_pow n m : Z.of_nat (n^m) = (Z.of_nat n)^(Z.of_nat m).
Lemma inj_div2 n : Z.of_nat (Nat.div2 n) = Z.div2 (Z.of_nat n).
(** [Z.to_nat] is hence injective for non-negative integers. *)
Lemma inj n m : 0<=n -> 0<=m -> Z.to_nat n = Z.to_nat m -> n = m.
Lemma inj_iff n m : 0<=n -> 0<=m -> (Z.to_nat n = Z.to_nat m <-> n = m).
(** [Z.to_nat], basic equations *)
Lemma inj_0 : Z.to_nat 0 = O.
Lemma inj_pos n : Z.to_nat (Zpos n) = Pos.to_nat n.
Lemma inj_neg n : Z.to_nat (Zneg n) = O.
(** [Z.to_nat] and operations *)
Lemma inj_add n m : 0<=n -> 0<=m ->
Z.to_nat (n+m) = (Z.to_nat n + Z.to_nat m)%nat.
Lemma inj_mul n m : 0<=n -> 0<=m ->
Z.to_nat (n*m) = (Z.to_nat n * Z.to_nat m)%nat.
Lemma inj_succ n : 0<=n -> Z.to_nat (Z.succ n) = S (Z.to_nat n).
Lemma inj_sub n m : 0<=m -> Z.to_nat (n - m) = (Z.to_nat n - Z.to_nat m)%nat.
Lemma inj_pred n : Z.to_nat (Z.pred n) = Nat.pred (Z.to_nat n).
Lemma inj_compare n m : 0<=n -> 0<=m ->
(Z.to_nat n ?= Z.to_nat m)%nat = (n ?= m).
Lemma inj_le n m : 0<=n -> 0<=m -> (n<=m <-> (Z.to_nat n <= Z.to_nat m)%nat).
Lemma inj_lt n m : 0<=n -> 0<=m -> (n<m <-> (Z.to_nat n < Z.to_nat m)%nat).
Lemma inj_min n m : Z.to_nat (Z.min n m) = Nat.min (Z.to_nat n) (Z.to_nat m).
Lemma inj_max n m : Z.to_nat (Z.max n m) = Nat.max (Z.to_nat n) (Z.to_nat m).
Lemma inj_div n m : 0<=n -> 0<=m -> Z.to_nat (n / m) = (Z.to_nat n / Z.to_nat m)%nat.
Lemma inj_mod n m : 0<=n -> 0<=m -> Z.to_nat (n mod m) = (Z.to_nat n mod Z.to_nat m)%nat.
Lemma inj_pow n m : 0 <= n -> 0 <= m -> Z.to_nat (n ^ m) = (Z.to_nat n ^ Z.to_nat m)%nat.
End Z2Nat.