aboutsummaryrefslogtreecommitdiff
path: root/theories/Numbers/Integer
diff options
context:
space:
mode:
Diffstat (limited to 'theories/Numbers/Integer')
-rw-r--r--theories/Numbers/Integer/Axioms/ZAxioms.v120
-rw-r--r--theories/Numbers/Integer/Axioms/ZDomain.v42
-rw-r--r--theories/Numbers/Integer/Axioms/ZOrder.v447
-rw-r--r--theories/Numbers/Integer/Axioms/ZPlus.v222
-rw-r--r--theories/Numbers/Integer/Axioms/ZPlusOrder.v160
-rw-r--r--theories/Numbers/Integer/Axioms/ZTimes.v135
-rw-r--r--theories/Numbers/Integer/Axioms/ZTimesOrder.v92
-rw-r--r--theories/Numbers/Integer/NatPairs/CommRefl.v185
-rw-r--r--theories/Numbers/Integer/NatPairs/ZNatPairs.v45
9 files changed, 1448 insertions, 0 deletions
diff --git a/theories/Numbers/Integer/Axioms/ZAxioms.v b/theories/Numbers/Integer/Axioms/ZAxioms.v
new file mode 100644
index 0000000000..4f0eab8e35
--- /dev/null
+++ b/theories/Numbers/Integer/Axioms/ZAxioms.v
@@ -0,0 +1,120 @@
+Require Import NumPrelude.
+Require Import ZDomain.
+
+Module Type IntSignature.
+Declare Module Export DomainModule : DomainSignature.
+
+Parameter Inline O : Z.
+Parameter Inline S : Z -> Z.
+Parameter Inline P : Z -> Z.
+
+Notation "0" := O.
+
+Add Morphism S with signature E ==> E as S_wd.
+Add Morphism P with signature E ==> E as P_wd.
+
+Axiom S_inj : forall x y : Z, S x == S y -> x == y.
+Axiom S_P : forall x : Z, S (P x) == x.
+
+Axiom induction :
+ forall Q : Z -> Prop,
+ pred_wd E Q -> Q 0 ->
+ (forall x, Q x -> Q (S x)) ->
+ (forall x, Q x -> Q (P x)) -> forall x, Q x.
+
+End IntSignature.
+
+
+Module IntProperties (Export IntModule : IntSignature).
+
+Module Export DomainPropertiesModule := DomainProperties DomainModule.
+
+Ltac induct n :=
+ try intros until n;
+ pattern n; apply induction; clear n;
+ [unfold NumPrelude.pred_wd;
+ let n := fresh "n" in
+ let m := fresh "m" in
+ let H := fresh "H" in intros n m H; qmorphism n m | | |].
+
+Theorem P_inj : forall x y, P x == P y -> x == y.
+Proof.
+intros x y H.
+setoid_replace x with (S (P x)); [| symmetry; apply S_P].
+setoid_replace y with (S (P y)); [| symmetry; apply S_P].
+now rewrite H.
+Qed.
+
+Theorem P_S : forall x, P (S x) == x.
+Proof.
+intro x.
+apply S_inj.
+now rewrite S_P.
+Qed.
+
+(* The following tactics are intended for replacing a certain
+occurrence of a term t in the goal by (S (P t)) or by (P (S t)).
+Unfortunately, this cannot be done by setoid_replace tactic for two
+reasons. First, it seems impossible to do rewriting when one side of
+the equation in question (S_P or P_S) is a variable, due to bug 1604.
+This does not work even when the predicate is an identifier (e.g.,
+when one tries to rewrite (Q x) into (Q (S (P x)))). Second, the
+setoid_rewrite tactic, like the ordinary rewrite tactic, does not
+allow specifying the exact occurrence of the term to be rewritten. Now
+while not in the setoid context, this occurrence can be specified
+using the pattern tactic, it does not work with setoids, since pattern
+creates a lambda abstractuion, and setoid_rewrite does not work with
+them. *)
+
+Ltac rewrite_SP t set_tac repl thm :=
+let x := fresh "x" in
+set_tac x t;
+setoid_replace x with (repl x); [| symmetry; apply thm];
+unfold x; clear x.
+
+Tactic Notation "rewrite_S_P" constr(t) :=
+rewrite_SP t ltac:(fun x t => (set (x := t))) (fun x => (S (P x))) S_P.
+
+Tactic Notation "rewrite_S_P" constr(t) "at" integer(k) :=
+rewrite_SP t ltac:(fun x t => (set (x := t) in |-* at k)) (fun x => (S (P x))) S_P.
+
+Tactic Notation "rewrite_P_S" constr(t) :=
+rewrite_SP t ltac:(fun x t => (set (x := t))) (fun x => (P (S x))) P_S.
+
+Tactic Notation "rewrite_P_S" constr(t) "at" integer(k) :=
+rewrite_SP t ltac:(fun x t => (set (x := t) in |-* at k)) (fun x => (P (S x))) P_S.
+
+(* One can add tactic notations for replacements in assumptions rather
+than in the goal. For the reason of many possible variants, the core
+of the tactic is factored out. *)
+
+Section Induction.
+
+Variable Q : Z -> Prop.
+Hypothesis Q_wd : pred_wd E Q.
+
+Add Morphism Q with signature E ==> iff as Q_morph.
+Proof Q_wd.
+
+Theorem induction_n :
+ forall n, Q n ->
+ (forall m, Q m -> Q (S m)) ->
+ (forall m, Q m -> Q (P m)) -> forall m, Q m.
+Proof.
+induct n.
+intros; now apply induction.
+intros n IH H1 H2 H3; apply IH; try assumption. apply H3 in H1; now rewrite P_S in H1.
+intros n IH H1 H2 H3; apply IH; try assumption. apply H2 in H1; now rewrite S_P in H1.
+Qed.
+
+End Induction.
+
+Ltac induct_n k n :=
+ try intros until k;
+ pattern k; apply induction_n with (n := n); clear k;
+ [unfold NumPrelude.pred_wd;
+ let n := fresh "n" in
+ let m := fresh "m" in
+ let H := fresh "H" in intros n m H; qmorphism n m | | |].
+
+End IntProperties.
diff --git a/theories/Numbers/Integer/Axioms/ZDomain.v b/theories/Numbers/Integer/Axioms/ZDomain.v
new file mode 100644
index 0000000000..00eab8842f
--- /dev/null
+++ b/theories/Numbers/Integer/Axioms/ZDomain.v
@@ -0,0 +1,42 @@
+Require Import NumPrelude.
+
+Module Type DomainSignature.
+
+Parameter Z : Set.
+Parameter E : relation Z.
+Parameter e : Z -> Z -> bool.
+
+Axiom E_equiv_e : forall x y : Z, E x y <-> e x y.
+Axiom E_equiv : equiv Z E.
+
+Add Relation Z E
+ reflexivity proved by (proj1 E_equiv)
+ symmetry proved by (proj2 (proj2 E_equiv))
+ transitivity proved by (proj1 (proj2 E_equiv))
+as E_rel.
+
+Notation "x == y" := (E x y) (at level 70).
+Notation "x # y" := (~ E x y) (at level 70).
+
+End DomainSignature.
+
+Module DomainProperties (Export DomainModule : DomainSignature).
+
+Add Morphism e with signature E ==> E ==> eq_bool as e_wd.
+Proof.
+intros x x' Exx' y y' Eyy'.
+case_eq (e x y); case_eq (e x' y'); intros H1 H2; trivial.
+assert (x == y); [apply <- E_equiv_e; now rewrite H2 |
+assert (x' == y'); [rewrite <- Exx'; now rewrite <- Eyy' |
+rewrite <- H1; assert (H3 : e x' y'); [now apply -> E_equiv_e | now inversion H3]]].
+assert (x' == y'); [apply <- E_equiv_e; now rewrite H1 |
+assert (x == y); [rewrite Exx'; now rewrite Eyy' |
+rewrite <- H2; assert (H3 : e x y); [now apply -> E_equiv_e | now inversion H3]]].
+Qed.
+
+Theorem neq_symm : forall n m, n # m -> m # n.
+Proof.
+intros n m H1 H2; symmetry in H2; false_hyp H2 H1.
+Qed.
+
+End DomainProperties.
diff --git a/theories/Numbers/Integer/Axioms/ZOrder.v b/theories/Numbers/Integer/Axioms/ZOrder.v
new file mode 100644
index 0000000000..b1983d6f7f
--- /dev/null
+++ b/theories/Numbers/Integer/Axioms/ZOrder.v
@@ -0,0 +1,447 @@
+Require Import NumPrelude.
+Require Import ZDomain.
+Require Import ZAxioms.
+Require Import Coq.ZArith.Zmisc. (* for iter_nat *)
+
+Module Type OrderSignature.
+Declare Module Export IntModule : IntSignature.
+
+Parameter Inline lt : Z -> Z -> bool.
+Parameter Inline le : Z -> Z -> bool.
+Add Morphism lt with signature E ==> E ==> eq_bool as lt_wd.
+Add Morphism le with signature E ==> E ==> eq_bool as le_wd.
+
+Notation "n < m" := (lt n m).
+Notation "n <= m" := (le n m).
+
+Axiom le_lt : forall n m, n <= m <-> n < m \/ n == m.
+Axiom lt_irr : forall n, ~ (n < n).
+Axiom lt_S : forall n m, n < (S m) <-> n <= m.
+
+End OrderSignature.
+
+
+Module OrderProperties (Export OrderModule : OrderSignature).
+Module Export IntPropertiesModule := IntProperties IntModule.
+
+Ltac le_intro1 := rewrite le_lt; left.
+Ltac le_intro2 := rewrite le_lt; right.
+Ltac le_elim H := rewrite le_lt in H; destruct H as [H | H].
+
+Theorem le_refl : forall n, n <= n.
+Proof.
+intro n; now le_intro2.
+Qed.
+
+Theorem lt_n_Sn : forall n, n < S n.
+Proof.
+intro n. rewrite lt_S. now le_intro2.
+Qed.
+
+Theorem le_n_Sn : forall n, n <= S n.
+Proof.
+intro; le_intro1; apply lt_n_Sn.
+Qed.
+
+Theorem lt_Pn_n : forall n, P n < n.
+Proof.
+intro n; rewrite_S_P n at 2; apply lt_n_Sn.
+Qed.
+
+Theorem le_Pn_n : forall n, P n <= n.
+Proof.
+intro; le_intro1; apply lt_Pn_n.
+Qed.
+
+Theorem lt_n_Sm : forall n m, n < m -> n < S m.
+Proof.
+intros. rewrite lt_S. now le_intro1.
+Qed.
+
+Theorem le_n_Sm : forall n m, n <= m -> n <= S m.
+Proof.
+intros n m H; rewrite <- lt_S in H; now le_intro1.
+Qed.
+
+Theorem lt_n_m_P : forall n m, n < m <-> n <= P m.
+Proof.
+intros n m; rewrite_S_P m; rewrite P_S; apply lt_S.
+Qed.
+
+Theorem not_le_n_Pn : forall n, ~ n <= P n.
+Proof.
+intros n H; le_elim H.
+apply lt_n_Sm in H; rewrite S_P in H; false_hyp H lt_irr.
+pose proof (lt_Pn_n n) as H1; rewrite <- H in H1; false_hyp H1 lt_irr.
+Qed.
+
+Theorem le_S : forall n m, n <= S m <-> n <= m \/ n == S m.
+Proof.
+intros n m; rewrite le_lt. now rewrite lt_S.
+Qed.
+
+Theorem lt_P : forall n m, (P n) < m <-> n <= m.
+Proof.
+intro n; induct_n m (P n).
+split; intro H. false_hyp H lt_irr. false_hyp H not_le_n_Pn.
+intros m IH; split; intro H.
+apply -> lt_S in H; le_elim H.
+apply -> IH in H; now apply le_n_Sm.
+rewrite <- H; rewrite S_P; now le_intro2.
+apply -> le_S in H; destruct H as [H | H].
+apply <- IH in H. now apply lt_n_Sm. rewrite H; rewrite P_S; apply lt_n_Sn.
+intros m IH; split; intro H.
+pose proof H as H1. apply lt_n_Sm in H; rewrite S_P in H.
+apply -> IH in H; le_elim H. now apply -> lt_n_m_P.
+rewrite H in H1; false_hyp H1 lt_irr.
+pose proof H as H1. apply le_n_Sm in H. rewrite S_P in H.
+apply <- IH in H. apply -> lt_n_m_P in H. le_elim H.
+assumption. apply P_inj in H; rewrite H in H1; false_hyp H1 not_le_n_Pn.
+Qed.
+
+Theorem lt_Pn_m : forall n m, n < m -> P n < m.
+Proof.
+intros; rewrite lt_P; now le_intro1.
+Qed.
+
+Theorem le_Pn_m : forall n m, n <= m -> P n <= m.
+Proof.
+intros n m H; rewrite <- lt_P in H; now le_intro1.
+Qed.
+
+Theorem lt_n_m_S : forall n m, n < m <-> S n <= m.
+Proof.
+intros n m; rewrite_P_S n; rewrite S_P; apply lt_P.
+Qed.
+
+Theorem lt_Sn_m : forall n m, S n < m -> n < m.
+Proof.
+intros n m H; rewrite_P_S n; now apply lt_Pn_m.
+Qed.
+
+Theorem le_Sn_m : forall n m, S n <= m -> n <= m.
+Proof.
+intros n m H; rewrite <- lt_n_m_S in H; now le_intro1.
+Qed.
+
+Theorem lt_n_Pm : forall n m, n < P m -> n < m.
+Proof.
+intros n m H; rewrite_S_P m; now apply lt_n_Sm.
+Qed.
+
+Theorem le_n_Pm : forall n m, n <= P m -> n <= m.
+Proof.
+intros n m H; rewrite <- lt_n_m_P in H; now le_intro1.
+Qed.
+
+Theorem lt_respects_S : forall n m, n < m <-> S n < S m.
+Proof.
+intros n m. rewrite lt_n_m_S. symmetry. apply lt_S.
+Qed.
+
+Theorem le_respects_S : forall n m, n <= m <-> S n <= S m.
+Proof.
+intros n m. do 2 rewrite le_lt.
+firstorder using lt_respects_S S_wd S_inj.
+Qed.
+
+Theorem lt_respects_P : forall n m, n < m <-> P n < P m.
+Proof.
+intros n m. rewrite lt_n_m_P. symmetry; apply lt_P.
+Qed.
+
+Theorem le_respects_P : forall n m, n <= m <-> P n <= P m.
+Proof.
+intros n m. do 2 rewrite le_lt.
+firstorder using lt_respects_P P_wd P_inj.
+Qed.
+
+Theorem lt_S_P : forall n m, S n < m <-> n < P m.
+Proof.
+intros n m; rewrite_P_S n at 2; apply lt_respects_P.
+Qed.
+
+Theorem le_S_P : forall n m, S n <= m <-> n <= P m.
+Proof.
+intros n m; rewrite_P_S n at 2; apply le_respects_P.
+Qed.
+
+Theorem lt_P_S : forall n m, P n < m <-> n < S m.
+Proof.
+intros n m; rewrite_S_P n at 2; apply lt_respects_S.
+Qed.
+
+Theorem le_P_S : forall n m, P n <= m <-> n <= S m.
+Proof.
+intros n m; rewrite_S_P n at 2; apply le_respects_S.
+Qed.
+
+Theorem lt_neq : forall n m, n < m -> n # m.
+Proof.
+intros n m H1 H2; rewrite H2 in H1; false_hyp H1 lt_irr.
+Qed.
+
+Theorem lt_trans : forall n m p, n < m -> m < p -> n < p.
+Proof.
+intros n m; induct_n n m.
+intros p H _; false_hyp H lt_irr.
+intros n IH p H1 H2. apply lt_Sn_m in H1. pose proof (IH p H1 H2) as H3.
+rewrite lt_n_m_S in H3; le_elim H3.
+assumption. rewrite <- H3 in H2. rewrite lt_S in H2; le_elim H2.
+elimtype False; apply lt_irr with (n := n); now apply IH.
+rewrite H2 in H1; false_hyp H1 lt_irr.
+intros n IH p H1 H2. apply lt_Pn_m. rewrite lt_P in H1; le_elim H1.
+now apply IH. now rewrite H1.
+Qed.
+
+Theorem le_trans : forall n m p, n <= m -> m <= p -> n <= p.
+Proof.
+intros n m p H1 H2; le_elim H1.
+le_elim H2. le_intro1; now apply lt_trans with (m := m).
+le_intro1; now rewrite <- H2. now rewrite H1.
+Qed.
+
+Theorem le_lt_trans : forall n m p, n <= m -> m < p -> n < p.
+Proof.
+intros n m p H1 H2; le_elim H1.
+now apply lt_trans with (m := m). now rewrite H1.
+Qed.
+
+Theorem lt_le_trans : forall n m p, n < m -> m <= p -> n < p.
+Proof.
+intros n m p H1 H2; le_elim H2.
+now apply lt_trans with (m := m). now rewrite <- H2.
+Qed.
+
+Theorem lt_asymm : forall n m, n < m -> ~ m < n.
+Proof.
+intros n m H1 H2; apply lt_irr with (n := n); now apply lt_trans with (m := m).
+Qed.
+
+Theorem le_antisym : forall n m, n <= m -> m <= n -> n == m.
+Proof.
+intros n m H1 H2; le_elim H1; le_elim H2.
+elimtype False; apply lt_irr with (n := n); now apply lt_trans with (m := m).
+now symmetry. assumption. assumption.
+Qed.
+
+Theorem not_lt_Sn_n : forall n, ~ S n < n.
+Proof.
+intros n H; apply (lt_asymm n (S n)). apply lt_n_Sn. assumption.
+Qed.
+
+Theorem not_le_Sn_n : forall n, ~ S n <= n.
+Proof.
+intros n H; le_elim H. false_hyp H not_lt_Sn_n.
+pose proof (lt_n_Sn n) as H1. rewrite H in H1; false_hyp H1 lt_irr.
+Qed.
+
+Theorem lt_gt : forall n m, n < m -> m < n -> False.
+Proof.
+intros n m H1 H2; apply lt_irr with (n := n); now apply lt_trans with (m := m).
+Qed.
+
+Theorem lt_total : forall n m, n < m \/ n == m \/ m < n.
+Proof.
+intros n m; induct_n n m.
+right; now left.
+intros n IH; destruct IH as [H | [H | H]].
+rewrite lt_n_m_S in H. rewrite le_lt in H; tauto.
+right; right; rewrite H; apply lt_n_Sn.
+right; right; now apply lt_n_Sm.
+intros n IH; destruct IH as [H | [H | H]].
+left; now apply lt_Pn_m.
+left; rewrite H; apply lt_Pn_n.
+rewrite lt_n_m_P in H. rewrite le_lt in H.
+setoid_replace (m == P n) with (P n == m) in H using relation iff. tauto.
+split; intro; now symmetry.
+Qed.
+
+Theorem le_gt : forall n m, n <= m <-> ~ m < n.
+Proof.
+intros n m. rewrite -> le_lt.
+pose proof (lt_total n m). pose proof (lt_gt n m).
+assert (n == m -> ~ m < n); [intro A; rewrite A; apply lt_irr |].
+tauto.
+Qed.
+
+Theorem lt_ge : forall n m, n < m <-> ~ m <= n.
+Proof.
+intros n m. rewrite -> le_lt.
+pose proof (lt_total m n). pose proof (lt_gt n m).
+assert (n < m -> m # n); [intros A B; rewrite B in A; false_hyp A lt_irr |].
+tauto.
+Qed.
+
+Theorem lt_discrete : forall n m, n < m -> m < S n -> False.
+Proof.
+intros n m H1 H2; apply -> lt_S in H2; apply -> lt_ge in H1; false_hyp H2 H1.
+Qed.
+
+(* Decidability of order can be proved either from totality or from the fact
+that < and <= are boolean functions *)
+
+(** A corollary of having an order is that Z is infinite in both
+directions *)
+
+Theorem neq_Sn_n : forall n, S n # n.
+Proof.
+intros n H. pose proof (lt_n_Sn n) as H1. rewrite H in H1. false_hyp H1 lt_irr.
+Qed.
+
+Theorem neq_Pn_n : forall n, P n # n.
+Proof.
+intros n H. apply S_wd in H. rewrite S_P in H. now apply neq_Sn_n with (n := n).
+Qed.
+
+Lemma lt_n_Skn :
+ forall (n : Z) (k : nat), n < iter_nat (Datatypes.S k) Z S n.
+Proof.
+intro n; induction k as [| k IH]; simpl in *.
+apply lt_n_Sn. now apply lt_n_Sm.
+Qed.
+
+Lemma lt_Pkn_n :
+ forall (n : Z) (k : nat), iter_nat (Datatypes.S k) Z P n < n.
+Proof.
+intro n; induction k as [| k IH]; simpl in *.
+apply lt_Pn_n. now apply lt_Pn_m.
+Qed.
+
+Theorem neq_n_Skn :
+ forall (n : Z) (k : nat), iter_nat (Datatypes.S k) Z S n # n.
+Proof.
+intros n k H. pose proof (lt_n_Skn n k) as H1. rewrite H in H1.
+false_hyp H1 lt_irr.
+Qed.
+
+Theorem neq_Pkn_n :
+ forall (n : Z) (k : nat), iter_nat (Datatypes.S k) Z P n # n.
+Proof.
+intros n k H. pose proof (lt_Pkn_n n k) as H1. rewrite H in H1.
+false_hyp H1 lt_irr.
+Qed.
+
+(** Stronger variant of induction with assumptions n >= 0 (n <= 0)
+in the induction step *)
+
+Section Induction.
+
+Variable Q : Z -> Prop.
+Hypothesis Q_wd : pred_wd E Q.
+
+Add Morphism Q with signature E ==> iff as Q_morph.
+Proof Q_wd.
+
+Section Center.
+
+Variable z : Z. (* Q z is the basis of induction *)
+
+Section RightInduction.
+
+Let Q' := fun n : Z => forall m, z <= m -> m < n -> Q m.
+
+Add Morphism Q' with signature E ==> iff as Q'_pos_wd.
+Proof.
+intros x1 x2 H; unfold Q'; qmorphism x1 x2.
+Qed.
+
+Theorem right_induction :
+ Q z -> (forall n, z <= n -> Q n -> Q (S n)) -> forall n, z <= n -> Q n.
+Proof.
+intros Qz QS k k_ge_z.
+assert (H : forall n, Q' n). induct_n n z; unfold Q'.
+intros m H1 H2. apply -> le_gt in H1; false_hyp H2 H1.
+intros n IH m H2 H3.
+rewrite lt_S in H3; le_elim H3. now apply IH.
+le_elim H2. rewrite_S_P m.
+apply QS. now apply -> lt_n_m_P. apply IH. now apply -> lt_n_m_P.
+rewrite H3; apply lt_Pn_n. now rewrite <- H2.
+intros n IH m H2 H3. apply IH. assumption. now apply lt_n_Pm.
+pose proof (H (S k)) as H1; unfold Q' in H1. apply H1.
+apply k_ge_z. apply lt_n_Sn.
+Qed.
+
+End RightInduction.
+
+Section LeftInduction.
+
+Let Q' := fun n : Z => forall m, m <= z -> n < m -> Q m.
+
+Add Morphism Q' with signature E ==> iff as Q'_neg_wd.
+Proof.
+intros x1 x2 H; unfold Q'; qmorphism x1 x2.
+Qed.
+
+Theorem left_induction :
+ Q z -> (forall n, n <= z -> Q n -> Q (P n)) -> forall n, n <= z -> Q n.
+Proof.
+intros Qz QP k k_le_z.
+assert (H : forall n, Q' n). induct_n n z; unfold Q'.
+intros m H1 H2. apply -> le_gt in H1; false_hyp H2 H1.
+intros n IH m H2 H3. apply IH. assumption. now apply lt_Sn_m.
+intros n IH m H2 H3.
+rewrite lt_P in H3; le_elim H3. now apply IH.
+le_elim H2. rewrite_P_S m.
+apply QP. now apply -> lt_n_m_S. apply IH. now apply -> lt_n_m_S.
+rewrite H3; apply lt_n_Sn. now rewrite H2.
+pose proof (H (P k)) as H1; unfold Q' in H1. apply H1.
+apply k_le_z. apply lt_Pn_n.
+Qed.
+
+End LeftInduction.
+
+Theorem induction_ord_n :
+ Q z ->
+ (forall n, z <= n -> Q n -> Q (S n)) ->
+ (forall n, n <= z -> Q n -> Q (P n)) ->
+ forall n, Q n.
+Proof.
+intros Qz QS QP n.
+destruct (lt_total n z) as [H | [H | H]].
+now apply left_induction; [| | le_intro1].
+now rewrite H.
+now apply right_induction; [| | le_intro1].
+Qed.
+
+End Center.
+
+Theorem induction_ord :
+ Q 0 ->
+ (forall n, 0 <= n -> Q n -> Q (S n)) ->
+ (forall n, n <= 0 -> Q n -> Q (P n)) ->
+ forall n, Q n.
+Proof (induction_ord_n 0).
+
+Theorem lt_ind : forall (n : Z),
+ Q (S n) ->
+ (forall m : Z, n < m -> Q m -> Q (S m)) ->
+ forall m : Z, n < m -> Q m.
+Proof.
+intros n H1 H2 m H3.
+apply right_induction with (S n). assumption.
+intros; apply H2; try assumption. now apply <- lt_n_m_S.
+now apply -> lt_n_m_S.
+Qed.
+
+Theorem le_ind : forall (n : Z),
+ Q n ->
+ (forall m : Z, n <= m -> Q m -> Q (S m)) ->
+ forall m : Z, n <= m -> Q m.
+Proof.
+intros n H1 H2 m H3.
+now apply right_induction with n.
+Qed.
+
+End Induction.
+
+Ltac induct_ord n :=
+ try intros until n;
+ pattern n; apply induction_ord; clear n;
+ [unfold NumPrelude.pred_wd;
+ let n := fresh "n" in
+ let m := fresh "m" in
+ let H := fresh "H" in intros n m H; qmorphism n m | | |].
+
+End OrderProperties.
+
diff --git a/theories/Numbers/Integer/Axioms/ZPlus.v b/theories/Numbers/Integer/Axioms/ZPlus.v
new file mode 100644
index 0000000000..1b5aa73fb2
--- /dev/null
+++ b/theories/Numbers/Integer/Axioms/ZPlus.v
@@ -0,0 +1,222 @@
+Require Import NumPrelude.
+Require Import ZDomain.
+Require Import ZAxioms.
+
+Module Type PlusSignature.
+Declare Module Export IntModule : IntSignature.
+
+Parameter Inline plus : Z -> Z -> Z.
+Parameter Inline minus : Z -> Z -> Z.
+Parameter Inline uminus : Z -> Z.
+
+Notation "x + y" := (plus x y).
+Notation "x - y" := (minus x y).
+Notation "- x" := (uminus x).
+
+Add Morphism plus with signature E ==> E ==> E as plus_wd.
+Add Morphism minus with signature E ==> E ==> E as minus_wd.
+Add Morphism uminus with signature E ==> E as uminus_wd.
+
+Axiom plus_0 : forall n, 0 + n == n.
+Axiom plus_S : forall n m, (S n) + m == S (n + m).
+
+Axiom minus_0 : forall n, n - 0 == n.
+Axiom minus_S : forall n m, n - (S m) == P (n - m).
+
+Axiom uminus_0 : - 0 == 0.
+Axiom uminus_S : forall n, - (S n) == P (- n).
+
+End PlusSignature.
+
+Module PlusProperties (Export PlusModule : PlusSignature).
+
+Module Export IntPropertiesModule := IntProperties IntModule.
+
+Theorem plus_P : forall n m, P n + m == P (n + m).
+Proof.
+intros n m. rewrite_S_P n at 2. rewrite plus_S. now rewrite P_S.
+Qed.
+
+Theorem minus_P : forall n m, n - (P m) == S (n - m).
+Proof.
+intros n m. rewrite_S_P m at 2. rewrite minus_S. now rewrite S_P.
+Qed.
+
+Theorem uminus_P : forall n, - (P n) == S (- n).
+Proof.
+intro n. rewrite_S_P n at 2. rewrite uminus_S. now rewrite S_P.
+Qed.
+
+Theorem plus_n_0 : forall n, n + 0 == n.
+Proof.
+induct n.
+now rewrite plus_0.
+intros n IH. rewrite plus_S. now rewrite IH.
+intros n IH. rewrite plus_P. now rewrite IH.
+Qed.
+
+Theorem plus_n_Sm : forall n m, n + S m == S (n + m).
+Proof.
+intros n m; induct n.
+now do 2 rewrite plus_0.
+intros n IH. do 2 rewrite plus_S. now rewrite IH.
+intros n IH. do 2 rewrite plus_P. rewrite IH. rewrite P_S; now rewrite S_P.
+Qed.
+
+Theorem plus_n_Pm : forall n m, n + P m == P (n + m).
+Proof.
+intros n m; rewrite_S_P m at 2. rewrite plus_n_Sm; now rewrite P_S.
+Qed.
+
+Theorem plus_opp_minus : forall n m, n + (- m) == n - m.
+Proof.
+induct m.
+rewrite uminus_0; rewrite minus_0; now rewrite plus_n_0.
+intros m IH. rewrite uminus_S; rewrite minus_S. rewrite plus_n_Pm; now rewrite IH.
+intros m IH. rewrite uminus_P; rewrite minus_P. rewrite plus_n_Sm; now rewrite IH.
+Qed.
+
+Theorem minus_0_n : forall n, 0 - n == - n.
+Proof.
+intro n; rewrite <- plus_opp_minus; now rewrite plus_0.
+Qed.
+
+Theorem minus_Sn_m : forall n m, S n - m == S (n - m).
+Proof.
+intros n m; do 2 rewrite <- plus_opp_minus; now rewrite plus_S.
+Qed.
+
+Theorem minus_Pn_m : forall n m, P n - m == P (n - m).
+Proof.
+intros n m. rewrite_S_P n at 2; rewrite minus_Sn_m; now rewrite P_S.
+Qed.
+
+Theorem plus_assoc : forall n m p, n + (m + p) == (n + m) + p.
+Proof.
+intros n m p; induct n.
+now do 2 rewrite plus_0.
+intros n IH. do 3 rewrite plus_S. now rewrite IH.
+intros n IH. do 3 rewrite plus_P. now rewrite IH.
+Qed.
+
+Theorem plus_comm : forall n m, n + m == m + n.
+Proof.
+intros n m; induct n.
+rewrite plus_0; now rewrite plus_n_0.
+intros n IH; rewrite plus_S; rewrite plus_n_Sm; now rewrite IH.
+intros n IH; rewrite plus_P; rewrite plus_n_Pm; now rewrite IH.
+Qed.
+
+Theorem minus_diag : forall n, n - n == 0.
+Proof.
+induct n.
+now rewrite minus_0.
+intros n IH. rewrite minus_S; rewrite minus_Sn_m; rewrite P_S; now rewrite IH.
+intros n IH. rewrite minus_P; rewrite minus_Pn_m; rewrite S_P; now rewrite IH.
+Qed.
+
+Theorem plus_opp_r : forall n, n + (- n) == 0.
+Proof.
+intro n; rewrite plus_opp_minus; now rewrite minus_diag.
+Qed.
+
+Theorem plus_opp_l : forall n, - n + n == 0.
+Proof.
+intro n; rewrite plus_comm; apply plus_opp_r.
+Qed.
+
+Theorem minus_swap : forall n m, - m + n == n - m.
+Proof.
+intros n m; rewrite <- plus_opp_minus; now rewrite plus_comm.
+Qed.
+
+Theorem plus_minus_inverse : forall n m, n + (m - n) == m.
+Proof.
+intros n m; rewrite <- minus_swap. rewrite plus_assoc;
+rewrite plus_opp_r; now rewrite plus_0.
+Qed.
+
+Theorem plus_minus_distr : forall n m p, n + (m - p) == (n + m) - p.
+Proof.
+intros n m p; do 2 rewrite <- plus_opp_minus; now rewrite plus_assoc.
+Qed.
+
+Theorem double_opp : forall n, - (- n) == n.
+Proof.
+induct n.
+now do 2 rewrite uminus_0.
+intros n IH. rewrite uminus_S; rewrite uminus_P; now rewrite IH.
+intros n IH. rewrite uminus_P; rewrite uminus_S; now rewrite IH.
+Qed.
+
+Theorem opp_plus_distr : forall n m, - (n + m) == - n + (- m).
+Proof.
+intros n m; induct n.
+rewrite uminus_0; now do 2 rewrite plus_0.
+intros n IH. rewrite plus_S; do 2 rewrite uminus_S. rewrite IH. now rewrite plus_P.
+intros n IH. rewrite plus_P; do 2 rewrite uminus_P. rewrite IH. now rewrite plus_S.
+Qed.
+
+Theorem opp_minus_distr : forall n m, - (n - m) == - n + m.
+Proof.
+intros n m; rewrite <- plus_opp_minus; rewrite opp_plus_distr.
+now rewrite double_opp.
+Qed.
+
+Theorem opp_inj : forall n m, - n == - m -> n == m.
+Proof.
+intros n m H. apply uminus_wd in H. now do 2 rewrite double_opp in H.
+Qed.
+
+Theorem minus_plus_distr : forall n m p, n - (m + p) == (n - m) - p.
+Proof.
+intros n m p; rewrite <- plus_opp_minus. rewrite opp_plus_distr. rewrite plus_assoc.
+now do 2 rewrite plus_opp_minus.
+Qed.
+
+Theorem minus_minus_distr : forall n m p, n - (m - p) == (n - m) + p.
+Proof.
+intros n m p; rewrite <- plus_opp_minus. rewrite opp_minus_distr. rewrite plus_assoc.
+now rewrite plus_opp_minus.
+Qed.
+
+Theorem plus_minus_swap : forall n m p, n + m - p == n - p + m.
+Proof.
+intros n m p. rewrite <- plus_minus_distr.
+rewrite <- (plus_opp_minus n p). rewrite <- plus_assoc. now rewrite minus_swap.
+Qed.
+
+Theorem plus_cancel_l : forall n m p, n + m == n + p -> m == p.
+Proof.
+intros n m p H.
+assert (H1 : - n + n + m == -n + n + p).
+do 2 rewrite <- plus_assoc; now rewrite H.
+rewrite plus_opp_l in H1; now do 2 rewrite plus_0 in H1.
+Qed.
+
+Theorem plus_cancel_r : forall n m p, n + m == p + m -> n == p.
+Proof.
+intros n m p H.
+rewrite plus_comm in H. set (k := m + n) in H. rewrite plus_comm in H.
+unfold k in H; clear k. now apply plus_cancel_l with m.
+Qed.
+
+Theorem plus_minus_l : forall n m p, m + p == n -> p == n - m.
+Proof.
+intros n m p H.
+assert (H1 : - m + m + p == - m + n).
+rewrite <- plus_assoc; now rewrite H.
+rewrite plus_opp_l in H1. rewrite plus_0 in H1. now rewrite minus_swap in H1.
+Qed.
+
+Theorem plus_minus_r : forall n m p, m + p == n -> m == n - p.
+Proof.
+intros n m p H; rewrite plus_comm in H; now apply plus_minus_l in H.
+Qed.
+
+Lemma minus_eq : forall n m, n - m == 0 -> n == m.
+Proof.
+intros n m H. rewrite <- (plus_minus_inverse m n). rewrite H. apply plus_n_0.
+Qed.
+
+End PlusProperties.
diff --git a/theories/Numbers/Integer/Axioms/ZPlusOrder.v b/theories/Numbers/Integer/Axioms/ZPlusOrder.v
new file mode 100644
index 0000000000..abaaa664f7
--- /dev/null
+++ b/theories/Numbers/Integer/Axioms/ZPlusOrder.v
@@ -0,0 +1,160 @@
+Require Import ZOrder.
+Require Import ZPlus.
+(* Warning: Trying to mask the absolute name "Plus"!!! *)
+
+Module PlusOrderProperties (Export PlusModule : PlusSignature)
+ (Export OrderModule : OrderSignature with
+ Module IntModule := PlusModule.IntModule).
+
+Module Export PlusPropertiesModule := PlusProperties PlusModule.
+Module Export OrderPropertiesModule := OrderProperties OrderModule.
+
+Theorem plus_lt_compat_l : forall n m p, n < m <-> p + n < p + m.
+Proof.
+intros n m p; induct p.
+now do 2 rewrite plus_0.
+intros p IH. do 2 rewrite plus_S. now rewrite <- lt_respects_S.
+intros p IH. do 2 rewrite plus_P. now rewrite <- lt_respects_P.
+Qed.
+
+Theorem plus_lt_compat_r : forall n m p, n < m <-> n + p < m + p.
+Proof.
+intros n m p; rewrite (plus_comm n p); rewrite (plus_comm m p);
+apply plus_lt_compat_l.
+Qed.
+
+Theorem plus_le_compat_l : forall n m p, n <= m <-> p + n <= p + m.
+Proof.
+intros n m p; do 2 rewrite <- lt_S. rewrite <- plus_n_Sm;
+apply plus_lt_compat_l.
+Qed.
+
+Theorem plus_le_compat_r : forall n m p, n <= m <-> n + p <= m + p.
+Proof.
+intros n m p; rewrite (plus_comm n p); rewrite (plus_comm m p);
+apply plus_le_compat_l.
+Qed.
+
+Theorem plus_lt_compat : forall n m p q, n < m -> p < q -> n + p < m + q.
+Proof.
+intros n m p q H1 H2. apply lt_trans with (m := m + p).
+now apply -> plus_lt_compat_r. now apply -> plus_lt_compat_l.
+Qed.
+
+Theorem plus_lt_le_compat : forall n m p q, n < m -> p <= q -> n + p < m + q.
+Proof.
+intros n m p q H1 H2. le_elim H2. now apply plus_lt_compat.
+rewrite H2. now apply -> plus_lt_compat_r.
+Qed.
+
+Theorem plus_le_lt_compat : forall n m p q, n <= m -> p < q -> n + p < m + q.
+Proof.
+intros n m p q H1 H2. le_elim H1. now apply plus_lt_compat.
+rewrite H1. now apply -> plus_lt_compat_l.
+Qed.
+
+Theorem plus_le_compat : forall n m p q, n <= m -> p <= q -> n + p <= m + q.
+Proof.
+intros n m p q H1 H2. le_elim H1. le_intro1; now apply plus_lt_le_compat.
+rewrite H1. now apply -> plus_le_compat_l.
+Qed.
+
+Theorem plus_pos : forall n m, 0 <= n -> 0 <= m -> 0 <= n + m.
+Proof.
+intros; rewrite <- (plus_0 0); now apply plus_le_compat.
+Qed.
+
+Lemma lt_opp_forward : forall n m, n < m -> - m < - n.
+Proof.
+induct n.
+induct_ord m.
+intro H; false_hyp H lt_irr.
+intros m H1 IH H2. rewrite uminus_S. rewrite uminus_0 in *.
+le_elim H1. apply IH in H1. now apply lt_Pn_m.
+rewrite <- H1; rewrite uminus_0; apply lt_Pn_n.
+intros m H1 IH H2. apply lt_n_Pm in H2. apply -> le_gt in H1. false_hyp H2 H1.
+intros n IH m H. rewrite uminus_S.
+apply -> lt_S_P in H. apply IH in H. rewrite uminus_P in H. now apply -> lt_S_P.
+intros n IH m H. rewrite uminus_P.
+apply -> lt_P_S in H. apply IH in H. rewrite uminus_S in H. now apply -> lt_P_S.
+Qed.
+
+Theorem lt_opp : forall n m, n < m <-> - m < - n.
+Proof.
+intros n m; split.
+apply lt_opp_forward.
+intro; rewrite <- (double_opp n); rewrite <- (double_opp m);
+now apply lt_opp_forward.
+Qed.
+
+Theorem le_opp : forall n m, n <= m <-> - m <= - n.
+Proof.
+intros n m; do 2 rewrite -> le_lt; rewrite <- lt_opp.
+assert (n == m <-> - m == - n).
+split; intro; [now apply uminus_wd | now apply opp_inj].
+tauto.
+Qed.
+
+Theorem lt_opp_neg : forall n, n < 0 <-> 0 < - n.
+Proof.
+intro n. set (k := 0) in |-* at 2.
+setoid_replace k with (- k); unfold k; clear k.
+apply lt_opp. now rewrite uminus_0.
+Qed.
+
+Theorem le_opp_neg : forall n, n <= 0 <-> 0 <= - n.
+Proof.
+intro n. set (k := 0) in |-* at 2.
+setoid_replace k with (- k); unfold k; clear k.
+apply le_opp. now rewrite uminus_0.
+Qed.
+
+Theorem lt_opp_pos : forall n, 0 < n <-> - n < 0.
+Proof.
+intro n. set (k := 0) in |-* at 2.
+setoid_replace k with (- k); unfold k; clear k.
+apply lt_opp. now rewrite uminus_0.
+Qed.
+
+Theorem le_opp_pos : forall n, 0 <= n <-> - n <= 0.
+Proof.
+intro n. set (k := 0) in |-* at 2.
+setoid_replace k with (- k); unfold k; clear k.
+apply le_opp. now rewrite uminus_0.
+Qed.
+
+Theorem minus_lt_decr_r : forall n m p, n < m <-> p - m < p - n.
+Proof.
+intros n m p. do 2 rewrite <- plus_opp_minus. rewrite <- plus_lt_compat_l.
+apply lt_opp.
+Qed.
+
+Theorem minus_le_nonincr_r : forall n m p, n <= m <-> p - m <= p - n.
+Proof.
+intros n m p. do 2 rewrite <- plus_opp_minus. rewrite <- plus_le_compat_l.
+apply le_opp.
+Qed.
+
+Theorem minus_lt_incr_l : forall n m p, n < m <-> n - p < m - p.
+Proof.
+intros n m p. do 2 rewrite <- plus_opp_minus. now rewrite <- plus_lt_compat_r.
+Qed.
+
+Theorem minus_le_nondecr_l : forall n m p, n <= m <-> n - p <= m - p.
+Proof.
+intros n m p. do 2 rewrite <- plus_opp_minus. now rewrite <- plus_le_compat_r.
+Qed.
+
+Theorem lt_plus_swap : forall n m p, n + p < m <-> n < m - p.
+Proof.
+intros n m p. rewrite (minus_lt_incr_l (n + p) m p).
+rewrite <- plus_minus_distr. rewrite minus_diag. now rewrite plus_n_0.
+Qed.
+
+Theorem le_plus_swap : forall n m p, n + p <= m <-> n <= m - p.
+Proof.
+intros n m p. rewrite (minus_le_nondecr_l (n + p) m p).
+rewrite <- plus_minus_distr. rewrite minus_diag. now rewrite plus_n_0.
+Qed.
+
+End PlusOrderProperties.
diff --git a/theories/Numbers/Integer/Axioms/ZTimes.v b/theories/Numbers/Integer/Axioms/ZTimes.v
new file mode 100644
index 0000000000..3f9c7c4ce6
--- /dev/null
+++ b/theories/Numbers/Integer/Axioms/ZTimes.v
@@ -0,0 +1,135 @@
+Require Import NumPrelude.
+Require Import ZDomain.
+Require Import ZAxioms.
+Require Import ZPlus.
+
+Module Type TimesSignature.
+Declare Module Export PlusModule : PlusSignature.
+
+Parameter Inline times : Z -> Z -> Z.
+
+Notation "x * y" := (times x y).
+
+Add Morphism times with signature E ==> E ==> E as times_wd.
+
+Axiom times_0 : forall n, n * 0 == 0.
+Axiom times_S : forall n m, n * (S m) == n * m + n.
+
+(* Here recursion is done on the second argument to conform to the
+usual definition of ordinal multiplication in set theory, which is not
+commutative. It seems, however, that this definition in set theory is
+unfortunate for two reasons. First, multiplication of two ordinals A
+and B can be defined as (an order type of) the cartesian product B x A
+(not A x B) ordered lexicographically. For example, omega * 2 =
+2 x omega = {(0,0) < (0,1) < (0,2) < ... < (1,0) < (1,1) < (1,2) < ...},
+while 2 * omega = omega x 2 = {(0,0) < (0,1) < (1,0) < (1,1) < (2,0) <
+(2,1) < ...} = omega. Secondly, the way the product 2 * 3 is said in
+French (deux fois trois) and Russian (dvazhdy tri) implies 3 + 3, not
+2 + 2 + 2. So it would possibly be more reasonable to define multiplication
+(here as well as in set theory) by recursion on the first argument. *)
+
+End TimesSignature.
+
+Module TimesProperties (Export TimesModule : TimesSignature).
+
+Module Export PlusPropertiesModule := PlusProperties PlusModule.
+
+Theorem times_P : forall n m, n * (P m) == n * m - n.
+Proof.
+intros n m. rewrite_S_P m at 2. rewrite times_S. rewrite <- plus_minus_distr.
+rewrite minus_diag. now rewrite plus_n_0.
+Qed.
+
+Theorem times_0_n : forall n, 0 * n == 0.
+Proof.
+induct n.
+now rewrite times_0.
+intros n IH. rewrite times_S. rewrite IH; now rewrite plus_0.
+intros n IH. rewrite times_P. rewrite IH; now rewrite minus_0.
+Qed.
+
+Theorem times_Sn_m : forall n m, (S n) * m == n * m + m.
+Proof.
+induct m.
+do 2 rewrite times_0. now rewrite plus_0.
+intros m IH. do 2 rewrite times_S. rewrite IH.
+do 2 rewrite <- plus_assoc. apply plus_wd. reflexivity.
+do 2 rewrite plus_n_Sm; now rewrite plus_comm.
+intros m IH. do 2 rewrite times_P. rewrite IH.
+rewrite <- plus_minus_swap. do 2 rewrite <- plus_minus_distr.
+apply plus_wd. reflexivity.
+rewrite minus_S. now rewrite minus_Pn_m.
+Qed.
+
+Theorem times_Pn_m : forall n m, (P n) * m == n * m - m.
+Proof.
+intros n m. rewrite_S_P n at 2. rewrite times_Sn_m.
+rewrite <- plus_minus_distr. rewrite minus_diag; now rewrite plus_n_0.
+Qed.
+
+Theorem times_comm : forall n m, n * m == m * n.
+Proof.
+intros n m; induct n.
+rewrite times_0_n; now rewrite times_0.
+intros n IH. rewrite times_Sn_m; rewrite times_S; now rewrite IH.
+intros n IH. rewrite times_Pn_m; rewrite times_P; now rewrite IH.
+Qed.
+
+Theorem times_opp_r : forall n m, n * (- m) == - (n * m).
+Proof.
+intros n m; induct m.
+rewrite uminus_0; rewrite times_0; now rewrite uminus_0.
+intros m IH. rewrite uminus_S. rewrite times_P; rewrite times_S. rewrite IH.
+rewrite <- plus_opp_minus; now rewrite opp_plus_distr.
+intros m IH. rewrite uminus_P. rewrite times_P; rewrite times_S. rewrite IH.
+now rewrite opp_minus_distr.
+Qed.
+
+Theorem times_opp_l : forall n m, (- n) * m == - (n * m).
+Proof.
+intros n m; rewrite (times_comm (- n) m); rewrite (times_comm n m);
+now rewrite times_opp_r.
+Qed.
+
+Theorem times_opp_opp : forall n m, (- n) * (- m) == n * m.
+Proof.
+intros n m. rewrite times_opp_l. rewrite times_opp_r. now rewrite double_opp.
+Qed.
+
+Theorem times_plus_distr_r : forall n m p, n * (m + p) == n * m + n * p.
+Proof.
+intros n m p; induct m.
+rewrite times_0; now do 2 rewrite plus_0.
+intros m IH. rewrite plus_S. do 2 rewrite times_S. rewrite IH.
+do 2 rewrite <- plus_assoc; apply plus_wd; [reflexivity | apply plus_comm].
+intros m IH. rewrite plus_P. do 2 rewrite times_P. rewrite IH.
+apply plus_minus_swap.
+Qed.
+
+Theorem times_plus_distr_l : forall n m p, (n + m) * p == n * p + m * p.
+Proof.
+intros n m p; rewrite (times_comm (n + m) p); rewrite times_plus_distr_r;
+rewrite (times_comm p n); now rewrite (times_comm p m).
+Qed.
+
+Theorem times_minus_distr_r : forall n m p, n * (m - p) == n * m - n * p.
+Proof.
+intros n m p.
+do 2 rewrite <- plus_opp_minus. rewrite times_plus_distr_r. now rewrite times_opp_r.
+Qed.
+
+Theorem times_minus_distr_l : forall n m p, (n - m) * p == n * p - m * p.
+Proof.
+intros n m p.
+do 2 rewrite <- plus_opp_minus. rewrite times_plus_distr_l. now rewrite times_opp_l.
+Qed.
+
+Theorem times_assoc : forall n m p, n * (m * p) == (n * m) * p.
+Proof.
+intros n m p; induct p.
+now do 3 rewrite times_0.
+intros p IH. do 2 rewrite times_S. rewrite times_plus_distr_r. now rewrite IH.
+intros p IH. do 2 rewrite times_P. rewrite times_minus_distr_r. now rewrite IH.
+Qed.
+
+End TimesProperties.
diff --git a/theories/Numbers/Integer/Axioms/ZTimesOrder.v b/theories/Numbers/Integer/Axioms/ZTimesOrder.v
new file mode 100644
index 0000000000..1f8b0a9478
--- /dev/null
+++ b/theories/Numbers/Integer/Axioms/ZTimesOrder.v
@@ -0,0 +1,92 @@
+Require Import ZPlus.
+Require Import ZTimes.
+Require Import ZOrder.
+(* Warning: Trying to mask the absolute name "Plus"!!! *)
+Require Import ZPlusOrder.
+
+Module TimesOrderProperties (Export TimesModule : TimesSignature)
+ (Export OrderModule : OrderSignature with
+ Module IntModule := TimesModule.PlusModule.IntModule).
+
+Module Export TimesPropertiesModule := TimesProperties TimesModule.
+Module Export PlusOrderPropertiesModule :=
+ PlusOrderProperties TimesModule.PlusModule OrderModule.
+
+Theorem mult_lt_compat_r : forall n m p, 0 < p -> n < m -> n * p < m * p.
+Proof.
+intros n m p; induct_ord p.
+intros H _; false_hyp H lt_irr.
+intros p H IH H1 H2. do 2 rewrite times_S.
+apply -> lt_S in H1; le_elim H1.
+apply plus_lt_compat. now apply IH. assumption.
+rewrite <- H1. do 2 rewrite times_0; now do 2 rewrite plus_0.
+intros p H IH H1 H2. apply lt_n_Pm in H1. apply -> le_gt in H.
+false_hyp H1 H.
+Qed.
+
+Theorem mult_lt_compat_l : forall n m p, 0 < p -> n < m -> p * n < p * m.
+Proof.
+intros n m p. rewrite (times_comm p n); rewrite (times_comm p m).
+apply mult_lt_compat_r.
+Qed.
+
+Theorem mult_lt_le_compat_r : forall n m p, 0 < p -> n <= m -> n * p <= m * p.
+Proof.
+intros n m p H1 H2; le_elim H2.
+le_intro1; now apply mult_lt_compat_r.
+rewrite H2. now le_intro2.
+Qed.
+
+Theorem mult_lt_le_compat_l : forall n m p, 0 < p -> n <= m -> p * n <= p * m.
+Proof.
+intros n m p. rewrite (times_comm p n); rewrite (times_comm p m).
+apply mult_lt_le_compat_r.
+Qed.
+
+(* And so on *)
+
+Theorem mult_pos_pos : forall n m, 0 < n -> 0 < m -> 0 < n * m.
+Proof.
+intros n m; set (k := 0) in |-* at 3;
+setoid_replace k with (n * 0); unfold k; clear k.
+apply mult_lt_compat_l. now rewrite times_0.
+Qed.
+
+Theorem mult_pos_neg : forall n m, 0 < n -> m < 0 -> n * m < 0.
+Proof.
+intros n m; set (k := 0) in |-* at 3;
+setoid_replace k with (n * 0); unfold k; clear k.
+apply mult_lt_compat_l. now rewrite times_0.
+Qed.
+(* The same proof script as for mult_pos_pos! *)
+
+Theorem mult_neg_pos : forall n m, n < 0 -> 0 < m -> n * m < 0.
+Proof.
+intros n m H1 H2; rewrite times_comm; now apply mult_pos_neg.
+Qed.
+
+Theorem mult_neg_neg : forall n m, n < 0 -> m < 0 -> 0 < n * m.
+Proof.
+intros n m H1 H2. setoid_replace (n * m) with (- - (n * m));
+[| symmetry; apply double_opp].
+rewrite <- times_opp_l. rewrite <- times_opp_r.
+apply -> lt_opp_neg in H1. apply -> lt_opp_neg in H2.
+now apply mult_pos_pos.
+Qed.
+
+(** With order, Z is an integral domain *)
+Theorem mult_neq_0 : forall n m, n # 0 -> m # 0 -> n * m # 0.
+Proof.
+intros n m H1 H2.
+destruct (lt_total n 0) as [H3 | [H3 | H3]];
+destruct (lt_total m 0) as [H4 | [H4 | H4]].
+apply neq_symm. apply lt_neq. now apply mult_neg_neg.
+false_hyp H4 H2.
+apply lt_neq; now apply mult_neg_pos.
+false_hyp H3 H1. false_hyp H3 H1. false_hyp H3 H1.
+apply lt_neq; now apply mult_pos_neg.
+false_hyp H4 H2.
+apply neq_symm. apply lt_neq. now apply mult_pos_pos.
+Qed.
+
+End TimesOrderProperties.
diff --git a/theories/Numbers/Integer/NatPairs/CommRefl.v b/theories/Numbers/Integer/NatPairs/CommRefl.v
new file mode 100644
index 0000000000..673a1fe50d
--- /dev/null
+++ b/theories/Numbers/Integer/NatPairs/CommRefl.v
@@ -0,0 +1,185 @@
+Require Import Arith.
+Require Import List.
+Require Import Setoid.
+
+Inductive bin : Set := node : bin->bin->bin | leaf : nat->bin.
+
+Fixpoint flatten_aux (t fin:bin){struct t} : bin :=
+ match t with
+ | node t1 t2 => flatten_aux t1 (flatten_aux t2 fin)
+ | x => node x fin
+ end.
+
+Fixpoint flatten (t:bin) : bin :=
+ match t with
+ | node t1 t2 => flatten_aux t1 (flatten t2)
+ | x => x
+ end.
+
+Fixpoint nat_le_bool (n m:nat){struct m} : bool :=
+ match n, m with
+ | O, _ => true
+ | S _, O => false
+ | S n, S m => nat_le_bool n m
+ end.
+
+Fixpoint insert_bin (n:nat)(t:bin){struct t} : bin :=
+ match t with
+ | leaf m => match nat_le_bool n m with
+ | true => node (leaf n)(leaf m)
+ | false => node (leaf m)(leaf n)
+ end
+ | node (leaf m) t' => match nat_le_bool n m with
+ | true => node (leaf n) t
+ | false =>
+ node (leaf m)(insert_bin n t')
+ end
+ | t => node (leaf n) t
+ end.
+
+Fixpoint sort_bin (t:bin) : bin :=
+ match t with
+ | node (leaf n) t' => insert_bin n (sort_bin t')
+ | t => t
+ end.
+
+Section commut_eq.
+Variable A : Set.
+Variable E : relation A.
+Variable f : A -> A -> A.
+
+Hypothesis E_equiv : equiv A E.
+Hypothesis comm : forall x y : A, f x y = f y x.
+Hypothesis assoc : forall x y z : A, f x (f y z) = f (f x y) z.
+
+Notation "x == y" := (E x y) (at level 70).
+
+Add Relation A E
+ reflexivity proved by (proj1 E_equiv)
+ symmetry proved by (proj2 (proj2 E_equiv))
+ transitivity proved by (proj1 (proj2 E_equiv))
+as E_rel.
+
+Fixpoint bin_A (l:list A)(def:A)(t:bin){struct t} : A :=
+ match t with
+ | node t1 t2 => f (bin_A l def t1)(bin_A l def t2)
+ | leaf n => nth n l def
+ end.
+ Theorem flatten_aux_valid_A :
+ forall (l:list A)(def:A)(t t':bin),
+ f (bin_A l def t)(bin_A l def t') == bin_A l def (flatten_aux t t').
+Proof.
+ intros l def t; elim t; simpl; auto.
+ intros t1 IHt1 t2 IHt2 t'. rewrite <- IHt1; rewrite <- IHt2.
+ symmetry; apply assoc.
+Qed.
+ Theorem flatten_valid_A :
+ forall (l:list A)(def:A)(t:bin),
+ bin_A l def t == bin_A l def (flatten t).
+Proof.
+ intros l def t; elim t; simpl; trivial.
+ intros t1 IHt1 t2 IHt2; rewrite <- flatten_aux_valid_A; rewrite <- IHt2.
+ trivial.
+Qed.
+
+Theorem flatten_valid_A_2 :
+ forall (t t':bin)(l:list A)(def:A),
+ bin_A l def (flatten t) == bin_A l def (flatten t')->
+ bin_A l def t == bin_A l def t'.
+Proof.
+ intros t t' l def Heq.
+ rewrite (flatten_valid_A l def t); rewrite (flatten_valid_A l def t').
+ trivial.
+Qed.
+
+Theorem insert_is_f : forall (l:list A)(def:A)(n:nat)(t:bin),
+ bin_A l def (insert_bin n t) ==
+ f (nth n l def) (bin_A l def t).
+Proof.
+ intros l def n t; elim t.
+ intros t1; case t1.
+ intros t1' t1'' IHt1 t2 IHt2.
+ simpl.
+ auto.
+ intros n0 IHt1 t2 IHt2.
+ simpl.
+ case (nat_le_bool n n0).
+ simpl.
+ auto.
+ simpl.
+ rewrite IHt2.
+ repeat rewrite assoc; rewrite (comm (nth n l def)); auto.
+ simpl.
+ intros n0; case (nat_le_bool n n0); auto.
+ rewrite comm; auto.
+Qed.
+
+Theorem sort_eq : forall (l:list A)(def:A)(t:bin),
+ bin_A l def (sort_bin t) == bin_A l def t.
+Proof.
+ intros l def t; elim t.
+ intros t1 IHt1; case t1.
+ auto.
+ intros n t2 IHt2; simpl; rewrite insert_is_f.
+ rewrite IHt2; auto.
+ auto.
+Qed.
+
+
+Theorem sort_eq_2 :
+ forall (l:list A)(def:A)(t1 t2:bin),
+ bin_A l def (sort_bin t1) == bin_A l def (sort_bin t2)->
+ bin_A l def t1 == bin_A l def t2.
+Proof.
+ intros l def t1 t2.
+ rewrite <- (sort_eq l def t1); rewrite <- (sort_eq l def t2).
+ trivial.
+Qed.
+
+End commut_eq.
+
+
+Ltac term_list f l v :=
+ match v with
+ | (f ?X1 ?X2) =>
+ let l1 := term_list f l X2 in term_list f l1 X1
+ | ?X1 => constr:(cons X1 l)
+ end.
+
+Ltac compute_rank l n v :=
+ match l with
+ | (cons ?X1 ?X2) =>
+ let tl := constr:X2 in
+ match constr:(X1 == v) with
+ | (?X1 == ?X1) => n
+ | _ => compute_rank tl (S n) v
+ end
+ end.
+
+Ltac model_aux l f v :=
+ match v with
+ | (f ?X1 ?X2) =>
+ let r1 := model_aux l f X1 with r2 := model_aux l f X2 in
+ constr:(node r1 r2)
+ | ?X1 => let n := compute_rank l 0 X1 in constr:(leaf n)
+ | _ => constr:(leaf 0)
+ end.
+
+Ltac comm_eq A f assoc_thm comm_thm :=
+ match goal with
+ | [ |- (?X1 == ?X2 :>A) ] =>
+ let l := term_list f (nil (A:=A)) X1 in
+ let term1 := model_aux l f X1
+ with term2 := model_aux l f X2 in
+ (change (bin_A A f l X1 term1 == bin_A A f l X1 term2);
+ apply flatten_valid_A_2 with (1 := assoc_thm);
+ apply sort_eq_2 with (1 := comm_thm)(2 := assoc_thm);
+ auto)
+ end.
+
+(*
+Theorem reflection_test4 : forall x y z:nat, x+(y+z) = (z+x)+y.
+Proof.
+ intros x y z. comm_eq nat plus plus_assoc plus_comm.
+Qed.
+*) \ No newline at end of file
diff --git a/theories/Numbers/Integer/NatPairs/ZNatPairs.v b/theories/Numbers/Integer/NatPairs/ZNatPairs.v
new file mode 100644
index 0000000000..d2634970db
--- /dev/null
+++ b/theories/Numbers/Integer/NatPairs/ZNatPairs.v
@@ -0,0 +1,45 @@
+Require Import NDomain.
+Require Import NAxioms.
+Require Import NPlus.
+Require Import NTimes.
+Require Import NLt.
+Require Import NPlusLt.
+Require Import NTimesLt.
+
+Require Import ZDomain.
+Require Import ZAxioms.
+Require Import ZPlus.
+Require Import ZTimes.
+Require Import ZOrder.
+Require Import ZPlusOrder.
+Require Import ZTimesOrder.
+
+Module NatPairsDomain (Export PlusModule : NPlus.PlusSignature) <:
+ ZDomain.DomainSignature.
+
+Module Export PlusPropertiesModule := NPlus.PlusProperties PlusModule.
+
+Definition Z : Set := (N * N)%type.
+Definition E (p1 p2 : Z) := (fst p1) + (snd p2) == (fst p2) + (snd p1).
+Definition e (p1 p2 : Z) := e ((fst p1) + (snd p2)) ((fst p2) + (snd p1)).
+
+Theorem E_equiv_e : forall x y : Z, E x y <-> e x y.
+Proof.
+intros x y; unfold E, e; apply E_equiv_e.
+Qed.
+
+Theorem E_equiv : equiv Z E.
+Proof.
+split; [| split]; unfold reflexive, symmetric, transitive, E.
+now intro x.
+intros x y z H1 H2.
+comm_eq N
+
+
+
+assert (H : ((fst x) + (snd y)) + ((fst y) + (snd z)) ==
+ ((fst y) + (snd x)) + ((fst z) + (snd y))); [now apply plus_wd |].
+assert (H : (fst y) + (snd y) + (fst x) + (snd z) ==
+ (fst y) + (snd y) + (snd x) + (fst z)).
+
+