Require Export NArith.
Open Scope N_scope.
intros n m; case n; case m; unfold N.le; simpl; try (intros; discriminate).
intros p; elim p using Pind; simpl.
intros H1; inversion H1.
intros n1 _; rewrite nat_of_P_succ_morphism.
intros H1; inversion H1.
intros p1 p2 H1 H2; absurd (nat_of_P p2 > nat_of_P p1)%nat; auto with arith.
apply nat_of_P_gt_Gt_compare_morphism; auto.
Qed.
intros n m; case n; case m; unfold N.le; simpl; auto with arith.
intros n1 H1; case H1; auto.
intros m1 n1 H1; case (le_or_lt n1 m1); auto with arith.
intros H2; case H1.
apply nat_of_P_gt_Gt_compare_complement_morphism.
repeat rewrite  nat_of_P_o_P_of_succ_nat_eq_succ; auto with arith.
Qed.
intros; apply le_Nle; repeat rewrite N2Nat.id; auto.
Qed.
intros n m; case n; case m; unfold N.lt; simpl; try (intros; discriminate); auto.
intros H1; inversion H1.
intros p H1; inversion H1.
intros; apply nat_of_P_lt_Lt_compare_complement_morphism; auto.
Qed.
intros n m; case n; case m; unfold N.lt; simpl; try (intros; discriminate); auto with arith.
intros m1 n1 H1.
rewrite <- (Nat2N.id (S n1)); rewrite <- (Nat2N.id (S m1)).
simpl; apply nat_of_P_lt_Lt_compare_morphism; auto.
Qed.
intros; apply lt_Nlt; repeat rewrite N2Nat.id; auto.
Qed.
intros n m; case n; case m; unfold N.ge; simpl; try (intros; discriminate); auto.
intros p; elim p using Pind; simpl.
intros H1; inversion H1.
intros n1 _; rewrite nat_of_P_succ_morphism.
intros H1; inversion H1.
intros p1 p2 H1 H2; absurd (nat_of_P p2 < nat_of_P p1)%nat; auto with arith.
apply nat_of_P_lt_Lt_compare_morphism; auto.
Qed.
intros n m; case n; case m; unfold N.ge; simpl; try (intros; discriminate); auto with arith.
intros n1 H1; case H1; auto.
intros m1 n1 H1.
case (le_or_lt m1 n1); auto with arith.
intros H2; case H1.
apply nat_of_P_lt_Lt_compare_complement_morphism.
repeat rewrite  nat_of_P_o_P_of_succ_nat_eq_succ; auto with arith.
Qed.
intros; apply ge_Nge; repeat rewrite N2Nat.id; auto.
Qed.
intros n m; case n; case m; unfold N.gt; simpl; try (intros; discriminate); auto.
intros H1; inversion H1.
intros p H1; inversion H1.
intros; apply nat_of_P_gt_Gt_compare_complement_morphism; auto.
Qed.
intros n m; case n; case m; unfold N.gt; simpl; try (intros; discriminate); auto with arith.
intros m1 n1 H1.
rewrite <- (Nat2N.id (S n1)); rewrite <- (Nat2N.id (S m1)).
simpl; apply nat_of_P_gt_Gt_compare_morphism; auto.
Qed.
intros; apply gt_Ngt; repeat rewrite N2Nat.id; auto.
Qed.
intros n m H; rewrite H; auto.
Qed.
Ltac to_nat_op  :=
match goal with
H: (N.lt _ _) |- _ => generalize (Nlt_lt_rev _ _ H); clear H; intros H
|     H: (N.gt _ _) |- _ => generalize (Ngt_gt_rev _ _ H); clear H; intros H
|     H: (N.le _ _) |- _ => generalize (Nle_le_rev _ _ H); clear H; intros H
|     H: (N.ge _ _) |- _ => generalize (Nge_ge_rev _ _ H); clear H; intros H
|     H: (@eq N _ _) |- _ => generalize (Neq_eq_rev _ _ H); clear H; intros H
|      |- (N.lt _ _)  => apply Nlt_lt
|      |- (N.le _ _)  => apply Nle_le
|      |- (N.gt _ _)  => apply Ngt_gt
|      |- (N.ge _ _)  => apply Nge_ge
|      |- (@eq N _ _)  => apply Nat2N.inj
end.
Ltac set_to_nat :=
let nn := fresh "nn" in
match goal with
|- context [(N.to_nat (?X + ?Y)%N)]  => rewrite N2Nat.inj_add
|      |- context [(N.to_nat (?X * ?Y)%N)]  => rewrite N2Nat.inj_mul
|      |- context [(N.to_nat ?X)]  => set (nn:=N.to_nat X) in * |- *
|      H: context [(N.to_nat (?X + ?Y)%N)] |- _ => rewrite N2Nat.inj_add in H
|      H: context [(N.to_nat (?X + ?Y)%N)] |- _ => rewrite N2Nat.inj_mul in H
|      H: context [(N.to_nat ?X)] |- _ => set (nn:=N.to_nat X) in * |- *
end.
Ltac to_nat := repeat to_nat_op; repeat set_to_nat.
intros; to_nat; apply le_gt_trans with nn1; auto.
Qed.
intros; to_nat; apply gt_le_trans with nn1; auto.
Qed.

Theorem Nle_add_l :
forall x y, x <= y + x.