CoRN.stdlib_omissions.Z


Require Import ZArith NPeano stdlib_omissions.P.

Open Scope Z_scope.

Lemma iff_not (P Q : Prop) : (P Q) → (not P not Q).
Proof. tauto. Qed.

Definition nat_of_Z (x : Z) : nat :=
  match x with
  | Z0O
  | Zpos pnat_of_P p
  | Zneg pO
  end.

Lemma nat_of_Z_nonpos (x : Z) : x 0 → nat_of_Z x = 0%nat.
Proof.
  destruct x; simpl; try reflexivity.
  now intros [].
Qed.

Lemma nat_of_Z_nonneg (x : Z) : 0 xZ_of_nat (nat_of_Z x) = x.
Proof.
  destruct x; simpl.
    reflexivity.
   intros. apply Z_of_nat_of_P.
  now intros [].
Qed.

Definition N_of_Z (x : Z) : N :=
  match x with
  | Z0 ⇒ 0%N
  | Zpos pNpos p
  | Zneg p ⇒ 0%N
  end.

Lemma N_of_Z_nonpos (x : Z) : x 0 → N_of_Z x = 0%N.
Proof.
  destruct x; simpl; try reflexivity.
  now intros [].
Qed.

Lemma N_of_Z_nonneg (x : Z) : 0 xZ_of_N (N_of_Z x) = x.
Proof.
  destruct x; simpl; try reflexivity.
  now intros [].
Qed.


Lemma div_Zdiv (n m: nat): m 0%natZ_of_nat (n / m) = Z_of_nat n / Z_of_nat m.
Proof.
 intros.
 apply (Zdiv_unique (Z_of_nat n) (Z_of_nat m) (Z_of_nat (n/m)%nat) (Z_of_nat (n mod m))).
  split.
   auto with ×.
  apply inj_lt.
  apply Nat.mod_upper_bound.
  assumption.
 rewrite <- inj_mult.
 rewrite <- inj_plus.
 apply inj_eq.
 apply div_mod.
 assumption.
Qed.

Lemma mod_Zmod (n m: nat): m 0%natZ_of_nat (n mod m) = (Z_of_nat n) mod (Z_of_nat m).
Proof with auto with ×.
 intros.
 apply (Zmod_unique (Z_of_nat n) (Z_of_nat m) (Z_of_nat n / Z_of_nat m)).
  split...
  apply inj_lt.
  apply Nat.mod_upper_bound...
 rewrite <- div_Zdiv...
 rewrite <- inj_mult, <- inj_plus.
 apply inj_eq, div_mod...
Qed.

Lemma P_of_succ_nat_Zplus (m: nat): Zpos (P_of_succ_nat m) = Z_of_nat m + 1.
Proof with intuition.
 induction m...
 simpl.
 destruct (P_of_succ_nat m)...
Qed.

Lemma S_Zplus (n: nat): (Z_of_nat (S n) = Z_of_nat n + 1)%Z.
Proof.
 simpl Z_of_nat.
 rewrite P_of_succ_nat_Zplus.
 reflexivity.
Qed.

Lemma Zto_nat_nonpos (z : Z) : z 0 → Z.to_nat z = 0%nat.
Proof.
intro A; destruct z as [| p | p]; trivial.
unfold Z.le in A; now contradict A.
Qed.

Lemma Ple_Zle (p q: positive): Ple p q (Zpos p Zpos q).
Proof.
 rewrite Ple_le, inj_le_iff.
 do 2 rewrite <- Zpos_eq_Z_of_nat_o_nat_of_P.
 reflexivity.
Qed.

Lemma Ple_Zle_to_pos (z : Z) (p : positive) : (Z.to_pos z p)%positive z Zpos p.
Proof.
  destruct z as [| q | q]; simpl.
  + split; intros _; [apply Zle_0_pos | apply Pos.le_1_l].
  + apply Ple_Zle.
  + split; intros _; [apply Zle_neg_pos | apply Pos.le_1_l].
Qed.

Lemma le_Zle_to_nat (n : nat) (z : Z) : (Z.to_nat z n)%nat z Z.of_nat n.
Proof.
pose proof (le_0_n n). pose proof (Zle_0_nat n).
destruct (Z.neg_nonneg_cases z).
+ rewrite Zto_nat_nonpos by now apply Z.lt_le_incl. split; auto with zarith.
+ split; intro A.
  - apply inj_le in A. rewrite Z2Nat.id in A; trivial.
  - apply Z2Nat.inj_le in A; trivial. rewrite Nat2Z.id in A; trivial.
Qed.

Lemma lt_Zlt_to_nat (n : nat) (z : Z) : Z.of_nat n < z (n < Z.to_nat z)%nat.
Proof.
assert (A : (m n : nat), not (m n)%nat (n < m)%nat).
+ intros; split; [apply not_le | apply gt_not_le].
+ assert (A1 := le_Zle_to_nat n z). apply iff_not in A1.
  now rewrite A, Z.nle_gt in A1.
Qed.

Lemma add_pos_nonneg (a b: Z): 0 < a → 0 b → 0 < a+b.
Proof. intros. omega. Qed.