(************************************************************************)
(*         *      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)         *)
(************************************************************************)
(*                      Evgeny Makarov, INRIA, 2007                     *)
(************************************************************************)
Require Export NZAxioms.
(** * From [CyclicType] to [NZAxiomsSig] *)
(** A [Z/nZ] representation given by a module type [CyclicType] implements [NZAxiomsSig], e.g. the common properties between N and Z with no ordering. Notice that the [n] in [Z/nZ] is a power of 2. *)
Module NZCyclicAxiomsMod (Import Cyclic : CyclicType) <: NZAxiomsSig.
Local Open Scope Z_scope.
Local Notation wB := (base ZnZ.digits).
Local Notation "[| x |]" := (ZnZ.to_Z x) (at level 0, x at level 99).
Definition eq (n m : t) := [| n |] = [| m |].
Definition zero := ZnZ.zero.
Definition one := ZnZ.one.
Definition two := ZnZ.succ ZnZ.one.
Definition succ := ZnZ.succ.
Definition pred := ZnZ.pred.
Definition add := ZnZ.add.
Definition sub := ZnZ.sub.
Definition mul := ZnZ.mul.
Local Infix "=="  := eq (at level 70).
Local Notation "0" := zero.
Local Notation S := succ.
Local Notation P := pred.
Local Infix "+" := add.
Local Infix "-" := sub.
Local Infix "*" := mul.
Global Hint Rewrite ZnZ.spec_0 ZnZ.spec_1 ZnZ.spec_succ ZnZ.spec_pred
ZnZ.spec_add ZnZ.spec_mul ZnZ.spec_sub : cyclic.
Ltac zify :=
unfold eq, zero, one, two, succ, pred, add, sub, mul in *;
autorewrite with cyclic.
Ltac zcongruence := repeat red; intros; zify; congruence.
#[global]
Instance eq_equiv : Equivalence eq.
Local Obligation Tactic := zcongruence.
#[global]
Program Instance succ_wd : Proper (eq ==> eq) succ.
#[global]
Program Instance pred_wd : Proper (eq ==> eq) pred.
#[global]
Program Instance add_wd : Proper (eq ==> eq ==> eq) add.
#[global]
Program Instance sub_wd : Proper (eq ==> eq ==> eq) sub.
#[global]
Program Instance mul_wd : Proper (eq ==> eq ==> eq) mul.

(* Specifications: *)
Theorem gt_wB_1 : 1 < wB.
Theorem gt_wB_0 : 0 < wB.
Lemma one_mod_wB : 1 mod wB = 1.
Lemma succ_mod_wB : forall n : Z, (n + 1) mod wB = ((n mod wB) + 1) mod wB.
Lemma pred_mod_wB : forall n : Z, (n - 1) mod wB = ((n mod wB) - 1) mod wB.
Lemma NZ_to_Z_mod : forall n, [| n |] mod wB = [| n |].
Theorem pred_succ : forall n, P (S n) == n.
Theorem one_succ : one == succ zero.
Theorem two_succ : two == succ one.
Section Induction.