1
(************************************************************************)
2
(* v * The Coq Proof Assistant / The Coq Development Team *)
3
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
4
(* \VV/ **************************************************************)
5
(* // * This file is distributed under the terms of the *)
6
(* * GNU Lesser General Public License Version 2.1 *)
7
(************************************************************************)
11
(**********************************************************************)
12
(** Binary Integers (Pierre Cr�gut, CNET, Lannion, France) *)
13
(**********************************************************************)
15
Require Export BinPos.
16
Require Export BinInt.
22
Open Local Scope Z_scope.
24
(***************************)
25
(** * Comparison on integers *)
27
Lemma Zcompare_refl : forall n:Z, (n ?= n) = Eq.
29
intro x; destruct x as [| p| p]; simpl in |- *;
30
[ reflexivity | apply Pcompare_refl | rewrite Pcompare_refl; reflexivity ].
33
Lemma Zcompare_Eq_eq : forall n m:Z, (n ?= m) = Eq -> n = m.
35
intros x y; destruct x as [| x'| x']; destruct y as [| y'| y']; simpl in |- *;
36
intro H; reflexivity || (try discriminate H);
37
[ rewrite (Pcompare_Eq_eq x' y' H); reflexivity
38
| rewrite (Pcompare_Eq_eq x' y');
40
| destruct ((x' ?= y')%positive Eq); reflexivity || discriminate ] ].
43
Ltac destr_zcompare :=
44
match goal with |- context [Zcompare ?x ?y] =>
46
case_eq (Zcompare x y); intro H;
47
[generalize (Zcompare_Eq_eq _ _ H); clear H; intro H |
52
Lemma Zcompare_Eq_iff_eq : forall n m:Z, (n ?= m) = Eq <-> n = m.
54
intros x y; split; intro E;
55
[ apply Zcompare_Eq_eq; assumption | rewrite E; apply Zcompare_refl ].
58
Lemma Zcompare_antisym : forall n m:Z, CompOpp (n ?= m) = (m ?= n).
60
intros x y; destruct x; destruct y; simpl in |- *;
61
reflexivity || discriminate H || rewrite Pcompare_antisym;
65
Lemma Zcompare_Gt_Lt_antisym : forall n m:Z, (n ?= m) = Gt <-> (m ?= n) = Lt.
67
intros x y; split; intro H;
68
[ change Lt with (CompOpp Gt) in |- *; rewrite <- Zcompare_antisym;
69
rewrite H; reflexivity
70
| change Gt with (CompOpp Lt) in |- *; rewrite <- Zcompare_antisym;
71
rewrite H; reflexivity ].
74
(** * Transitivity of comparison *)
76
Lemma Zcompare_Gt_trans :
77
forall n m p:Z, (n ?= m) = Gt -> (m ?= p) = Gt -> (n ?= p) = Gt.
79
intros x y z; case x; case y; case z; simpl in |- *;
80
try (intros; discriminate H || discriminate H0); auto with arith;
81
[ intros p q r H H0; apply nat_of_P_gt_Gt_compare_complement_morphism;
82
unfold gt in |- *; apply lt_trans with (m := nat_of_P q);
83
apply nat_of_P_lt_Lt_compare_morphism; apply ZC1;
85
| intros p q r; do 3 rewrite <- ZC4; intros H H0;
86
apply nat_of_P_gt_Gt_compare_complement_morphism;
87
unfold gt in |- *; apply lt_trans with (m := nat_of_P q);
88
apply nat_of_P_lt_Lt_compare_morphism; apply ZC1;
92
(** * Comparison and opposite *)
94
Lemma Zcompare_opp : forall n m:Z, (n ?= m) = (- m ?= - n).
96
intros x y; case x; case y; simpl in |- *; auto with arith; intros;
97
rewrite <- ZC4; trivial with arith.
100
Hint Local Resolve Pcompare_refl.
102
(** * Comparison first-order specification *)
104
Lemma Zcompare_Gt_spec :
105
forall n m:Z, (n ?= m) = Gt -> exists h : positive, n + - m = Zpos h.
107
intros x y; case x; case y;
108
[ simpl in |- *; intros H; discriminate H
109
| simpl in |- *; intros p H; discriminate H
110
| intros p H; exists p; simpl in |- *; auto with arith
111
| intros p H; exists p; simpl in |- *; auto with arith
112
| intros q p H; exists (p - q)%positive; unfold Zplus, Zopp in |- *;
113
unfold Zcompare in H; rewrite H; trivial with arith
114
| intros q p H; exists (p + q)%positive; simpl in |- *; trivial with arith
115
| simpl in |- *; intros p H; discriminate H
116
| simpl in |- *; intros q p H; discriminate H
117
| unfold Zcompare in |- *; intros q p; rewrite <- ZC4; intros H;
118
exists (q - p)%positive; simpl in |- *; rewrite (ZC1 q p H);
119
trivial with arith ].
122
(** * Comparison and addition *)
124
Lemma weaken_Zcompare_Zplus_compatible :
125
(forall (n m:Z) (p:positive), (Zpos p + n ?= Zpos p + m) = (n ?= m)) ->
126
forall n m p:Z, (p + n ?= p + m) = (n ?= m).
128
intros H x y z; destruct z;
131
| rewrite (Zcompare_opp x y); rewrite Zcompare_opp;
132
do 2 rewrite Zopp_plus_distr; rewrite Zopp_neg;
136
Hint Local Resolve ZC4.
138
Lemma weak_Zcompare_Zplus_compatible :
139
forall (n m:Z) (p:positive), (Zpos p + n ?= Zpos p + m) = (n ?= m).
141
intros x y z; case x; case y; simpl in |- *; auto with arith;
142
[ intros p; apply nat_of_P_lt_Lt_compare_complement_morphism; apply ZL17
143
| intros p; ElimPcompare z p; intros E; rewrite E; auto with arith;
144
apply nat_of_P_gt_Gt_compare_complement_morphism;
145
rewrite nat_of_P_minus_morphism;
146
[ unfold gt in |- *; apply ZL16 | assumption ]
147
| intros p; ElimPcompare z p; intros E; auto with arith;
148
apply nat_of_P_gt_Gt_compare_complement_morphism;
149
unfold gt in |- *; apply ZL17
150
| intros p q; ElimPcompare q p; intros E; rewrite E;
151
[ rewrite (Pcompare_Eq_eq q p E); apply Pcompare_refl
152
| apply nat_of_P_lt_Lt_compare_complement_morphism;
153
do 2 rewrite nat_of_P_plus_morphism; apply plus_lt_compat_l;
154
apply nat_of_P_lt_Lt_compare_morphism with (1 := E)
155
| apply nat_of_P_gt_Gt_compare_complement_morphism; unfold gt in |- *;
156
do 2 rewrite nat_of_P_plus_morphism; apply plus_lt_compat_l;
157
exact (nat_of_P_gt_Gt_compare_morphism q p E) ]
158
| intros p q; ElimPcompare z p; intros E; rewrite E; auto with arith;
159
apply nat_of_P_gt_Gt_compare_complement_morphism;
160
rewrite nat_of_P_minus_morphism;
161
[ unfold gt in |- *; apply lt_trans with (m := nat_of_P z);
162
[ apply ZL16 | apply ZL17 ]
164
| intros p; ElimPcompare z p; intros E; rewrite E; auto with arith;
165
simpl in |- *; apply nat_of_P_lt_Lt_compare_complement_morphism;
166
rewrite nat_of_P_minus_morphism; [ apply ZL16 | assumption ]
167
| intros p q; ElimPcompare z q; intros E; rewrite E; auto with arith;
168
simpl in |- *; apply nat_of_P_lt_Lt_compare_complement_morphism;
169
rewrite nat_of_P_minus_morphism;
170
[ apply lt_trans with (m := nat_of_P z); [ apply ZL16 | apply ZL17 ]
172
| intros p q; ElimPcompare z q; intros E0; rewrite E0; ElimPcompare z p;
173
intros E1; rewrite E1; ElimPcompare q p; intros E2;
174
rewrite E2; auto with arith;
175
[ absurd ((q ?= p)%positive Eq = Lt);
176
[ rewrite <- (Pcompare_Eq_eq z q E0);
177
rewrite <- (Pcompare_Eq_eq z p E1); rewrite (Pcompare_refl z);
180
| absurd ((q ?= p)%positive Eq = Gt);
181
[ rewrite <- (Pcompare_Eq_eq z q E0);
182
rewrite <- (Pcompare_Eq_eq z p E1); rewrite (Pcompare_refl z);
185
| absurd ((z ?= p)%positive Eq = Lt);
186
[ rewrite (Pcompare_Eq_eq z q E0); rewrite <- (Pcompare_Eq_eq q p E2);
187
rewrite (Pcompare_refl q); discriminate
189
| absurd ((z ?= p)%positive Eq = Lt);
190
[ rewrite (Pcompare_Eq_eq z q E0); rewrite E2; discriminate
192
| absurd ((z ?= p)%positive Eq = Gt);
193
[ rewrite (Pcompare_Eq_eq z q E0); rewrite <- (Pcompare_Eq_eq q p E2);
194
rewrite (Pcompare_refl q); discriminate
196
| absurd ((z ?= p)%positive Eq = Gt);
197
[ rewrite (Pcompare_Eq_eq z q E0); rewrite E2; discriminate
199
| absurd ((z ?= q)%positive Eq = Lt);
200
[ rewrite (Pcompare_Eq_eq z p E1); rewrite (Pcompare_Eq_eq q p E2);
201
rewrite (Pcompare_refl p); discriminate
203
| absurd ((p ?= q)%positive Eq = Gt);
204
[ rewrite <- (Pcompare_Eq_eq z p E1); rewrite E0; discriminate
205
| apply ZC2; assumption ]
206
| simpl in |- *; rewrite (Pcompare_Eq_eq q p E2);
207
rewrite (Pcompare_refl (p - z)); auto with arith
208
| simpl in |- *; rewrite <- ZC4;
209
apply nat_of_P_gt_Gt_compare_complement_morphism;
210
rewrite nat_of_P_minus_morphism;
211
[ rewrite nat_of_P_minus_morphism;
212
[ unfold gt in |- *; apply plus_lt_reg_l with (p := nat_of_P z);
213
rewrite le_plus_minus_r;
214
[ rewrite le_plus_minus_r;
215
[ apply nat_of_P_lt_Lt_compare_morphism; assumption
216
| apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism;
218
| apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism;
220
| apply ZC2; assumption ]
221
| apply ZC2; assumption ]
222
| simpl in |- *; rewrite <- ZC4;
223
apply nat_of_P_lt_Lt_compare_complement_morphism;
224
rewrite nat_of_P_minus_morphism;
225
[ rewrite nat_of_P_minus_morphism;
226
[ apply plus_lt_reg_l with (p := nat_of_P z);
227
rewrite le_plus_minus_r;
228
[ rewrite le_plus_minus_r;
229
[ apply nat_of_P_lt_Lt_compare_morphism; apply ZC1;
231
| apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism;
233
| apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism;
235
| apply ZC2; assumption ]
236
| apply ZC2; assumption ]
237
| absurd ((z ?= q)%positive Eq = Lt);
238
[ rewrite (Pcompare_Eq_eq q p E2); rewrite E1; discriminate
240
| absurd ((q ?= p)%positive Eq = Lt);
241
[ cut ((q ?= p)%positive Eq = Gt);
242
[ intros E; rewrite E; discriminate
243
| apply nat_of_P_gt_Gt_compare_complement_morphism;
244
unfold gt in |- *; apply lt_trans with (m := nat_of_P z);
245
[ apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; assumption
246
| apply nat_of_P_lt_Lt_compare_morphism; assumption ] ]
248
| absurd ((z ?= q)%positive Eq = Gt);
249
[ rewrite (Pcompare_Eq_eq z p E1); rewrite (Pcompare_Eq_eq q p E2);
250
rewrite (Pcompare_refl p); discriminate
252
| absurd ((z ?= q)%positive Eq = Gt);
253
[ rewrite (Pcompare_Eq_eq z p E1); rewrite ZC1;
254
[ discriminate | assumption ]
256
| absurd ((z ?= q)%positive Eq = Gt);
257
[ rewrite (Pcompare_Eq_eq q p E2); rewrite E1; discriminate
259
| absurd ((q ?= p)%positive Eq = Gt);
262
| apply nat_of_P_gt_Gt_compare_complement_morphism;
263
unfold gt in |- *; apply lt_trans with (m := nat_of_P z);
264
[ apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; assumption
265
| apply nat_of_P_lt_Lt_compare_morphism; assumption ] ]
267
| simpl in |- *; rewrite (Pcompare_Eq_eq q p E2); apply Pcompare_refl
268
| simpl in |- *; apply nat_of_P_gt_Gt_compare_complement_morphism;
269
unfold gt in |- *; rewrite nat_of_P_minus_morphism;
270
[ rewrite nat_of_P_minus_morphism;
271
[ apply plus_lt_reg_l with (p := nat_of_P p);
272
rewrite le_plus_minus_r;
273
[ rewrite plus_comm; apply plus_lt_reg_l with (p := nat_of_P q);
274
rewrite plus_assoc; rewrite le_plus_minus_r;
275
[ rewrite (plus_comm (nat_of_P q)); apply plus_lt_compat_l;
276
apply nat_of_P_lt_Lt_compare_morphism;
278
| apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism;
279
apply ZC1; assumption ]
280
| apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism;
281
apply ZC1; assumption ]
284
| simpl in |- *; apply nat_of_P_lt_Lt_compare_complement_morphism;
285
rewrite nat_of_P_minus_morphism;
286
[ rewrite nat_of_P_minus_morphism;
287
[ apply plus_lt_reg_l with (p := nat_of_P q);
288
rewrite le_plus_minus_r;
289
[ rewrite plus_comm; apply plus_lt_reg_l with (p := nat_of_P p);
290
rewrite plus_assoc; rewrite le_plus_minus_r;
291
[ rewrite (plus_comm (nat_of_P p)); apply plus_lt_compat_l;
292
apply nat_of_P_lt_Lt_compare_morphism;
293
apply ZC1; assumption
294
| apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism;
295
apply ZC1; assumption ]
296
| apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism;
297
apply ZC1; assumption ]
302
Lemma Zcompare_plus_compat : forall n m p:Z, (p + n ?= p + m) = (n ?= m).
304
exact (weaken_Zcompare_Zplus_compatible weak_Zcompare_Zplus_compatible).
307
Lemma Zplus_compare_compat :
308
forall (r:comparison) (n m p q:Z),
309
(n ?= m) = r -> (p ?= q) = r -> (n + p ?= m + q) = r.
311
intros r x y z t; case r;
312
[ intros H1 H2; elim (Zcompare_Eq_iff_eq x y); elim (Zcompare_Eq_iff_eq z t);
313
intros H3 H4 H5 H6; rewrite H3;
315
[ elim (Zcompare_Eq_iff_eq (y + t) (y + t)); auto with arith
318
| intros H1 H2; elim (Zcompare_Gt_Lt_antisym (y + t) (x + z)); intros H3 H4;
319
apply H3; apply Zcompare_Gt_trans with (m := y + z);
320
[ rewrite Zcompare_plus_compat; elim (Zcompare_Gt_Lt_antisym t z);
322
| do 2 rewrite <- (Zplus_comm z); rewrite Zcompare_plus_compat;
323
elim (Zcompare_Gt_Lt_antisym y x); auto with arith ]
324
| intros H1 H2; apply Zcompare_Gt_trans with (m := x + t);
325
[ rewrite Zcompare_plus_compat; assumption
326
| do 2 rewrite <- (Zplus_comm t); rewrite Zcompare_plus_compat;
330
Lemma Zcompare_succ_Gt : forall n:Z, (Zsucc n ?= n) = Gt.
332
intro x; unfold Zsucc in |- *; pattern x at 2 in |- *;
333
rewrite <- (Zplus_0_r x); rewrite Zcompare_plus_compat;
337
Lemma Zcompare_Gt_not_Lt : forall n m:Z, (n ?= m) = Gt <-> (n ?= m + 1) <> Lt.
340
[ intro H; elim_compare x (y + 1);
341
[ intro H1; rewrite H1; discriminate
342
| intros H1; elim Zcompare_Gt_spec with (1 := H); intros h H2;
343
absurd ((nat_of_P h > 0)%nat /\ (nat_of_P h < 1)%nat);
344
[ unfold not in |- *; intros H3; elim H3; intros H4 H5;
345
absurd (nat_of_P h > 0)%nat;
346
[ unfold gt in |- *; apply le_not_lt; apply le_S_n; exact H5
349
[ elim (ZL4 h); intros i H3; rewrite H3; apply gt_Sn_O
350
| change (nat_of_P h < nat_of_P 1)%nat in |- *;
351
apply nat_of_P_lt_Lt_compare_morphism;
352
change ((Zpos h ?= 1) = Lt) in |- *; rewrite <- H2;
353
rewrite <- (fun m n:Z => Zcompare_plus_compat m n y);
354
rewrite (Zplus_comm x); rewrite Zplus_assoc;
355
rewrite Zplus_opp_r; simpl in |- *; exact H1 ] ]
356
| intros H1; rewrite H1; discriminate ]
357
| intros H; elim_compare x (y + 1);
358
[ intros H1; elim (Zcompare_Eq_iff_eq x (y + 1)); intros H2 H3;
359
rewrite (H2 H1); exact (Zcompare_succ_Gt y)
360
| intros H1; absurd ((x ?= y + 1) = Lt); assumption
361
| intros H1; apply Zcompare_Gt_trans with (m := Zsucc y);
362
[ exact H1 | exact (Zcompare_succ_Gt y) ] ] ].
365
(** * Successor and comparison *)
367
Lemma Zcompare_succ_compat : forall n m:Z, (Zsucc n ?= Zsucc m) = (n ?= m).
369
intros n m; unfold Zsucc in |- *; do 2 rewrite (fun t:Z => Zplus_comm t 1);
370
rewrite Zcompare_plus_compat; auto with arith.
373
(** * Multiplication and comparison *)
375
Lemma Zcompare_mult_compat :
376
forall (p:positive) (n m:Z), (Zpos p * n ?= Zpos p * m) = (n ?= m).
378
intros x; induction x as [p H| p H| ];
379
[ intros y z; cut (Zpos (xI p) = Zpos p + Zpos p + 1);
380
[ intros E; rewrite E; do 4 rewrite Zmult_plus_distr_l;
381
do 2 rewrite Zmult_1_l; apply Zplus_compare_compat;
382
[ apply Zplus_compare_compat; apply H | trivial with arith ]
383
| simpl in |- *; rewrite (Pplus_diag p); trivial with arith ]
384
| intros y z; cut (Zpos (xO p) = Zpos p + Zpos p);
385
[ intros E; rewrite E; do 2 rewrite Zmult_plus_distr_l;
386
apply Zplus_compare_compat; apply H
387
| simpl in |- *; rewrite (Pplus_diag p); trivial with arith ]
388
| intros y z; do 2 rewrite Zmult_1_l; trivial with arith ].
392
(** * Reverting [x ?= y] to trichotomy *)
395
forall (A:Type) (P:A -> Prop) (x:A), (forall y:A, x = y -> P y) -> P x.
400
Lemma Zcompare_elim :
401
forall (c1 c2 c3:Prop) (n m:Z),
404
(n > m -> c3) -> match n ?= m with
410
intros c1 c2 c3 x y; intros.
411
apply rename with (x := x ?= y); intro r; elim r;
412
[ intro; apply H; apply (Zcompare_Eq_eq x y); assumption
413
| unfold Zlt in H0; assumption
414
| unfold Zgt in H1; assumption ].
417
Lemma Zcompare_eq_case :
418
forall (c1 c2 c3:Prop) (n m:Z),
419
c1 -> n = m -> match n ?= m with
425
intros c1 c2 c3 x y; intros.
426
rewrite H0; rewrite Zcompare_refl.
430
(** * Decompose an egality between two [?=] relations into 3 implications *)
432
Lemma Zcompare_egal_dec :
435
((n ?= m) = Eq -> (p ?= q) = Eq) ->
436
(n > m -> p > q) -> (n ?= m) = (p ?= q).
439
unfold Zgt in |- *; unfold Zlt in |- *; case (x1 ?= y1); case (x2 ?= y2);
440
auto with arith; symmetry in |- *; auto with arith.
443
(** * Relating [x ?= y] to [Zle], [Zlt], [Zge] or [Zgt] *)
447
n <= m -> match n ?= m with
453
intros x y; unfold Zle in |- *; elim (x ?= y); auto with arith.
458
n < m -> match n ?= m with
464
intros x y; unfold Zlt in |- *; elim (x ?= y); intros;
465
discriminate || trivial with arith.
470
n >= m -> match n ?= m with
476
intros x y; unfold Zge in |- *; elim (x ?= y); auto with arith.
481
n > m -> match n ?= m with
487
intros x y; unfold Zgt in |- *; elim (x ?= y); intros;
488
discriminate || trivial with arith.
491
(*********************)
492
(** * Other properties *)
494
Lemma Zmult_compare_compat_l :
495
forall n m p:Z, p > 0 -> (n ?= m) = (p * n ?= p * m).
497
intros x y z H; destruct z.
499
rewrite Zcompare_mult_compat; reflexivity.
503
Lemma Zmult_compare_compat_r :
504
forall n m p:Z, p > 0 -> (n ?= m) = (n * p ?= m * p).
506
intros x y z H; rewrite (Zmult_comm x z); rewrite (Zmult_comm y z);
507
apply Zmult_compare_compat_l; assumption.