aboutsummaryrefslogtreecommitdiffhomepage
path: root/theories/Numbers/Natural/Axioms/NMiscFunct.v
blob: 82a92245337f258a024602f0f7cc847430b3ddc4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
Require Import Bool. (* To get the orb and negb function *)
Require Export NStrongRec.
Require Export NTimesOrder.

Module MiscFunctFunctor (Import NatMod : NBaseSig).
Module Export StrongRecPropertiesModule := StrongRecProperties NatMod.
Open Local Scope NatScope.

(*****************************************************)
(**                   Addition                       *)

Definition plus (x y : N) := recursion y (fun _ p => S p) x.

Lemma plus_step_wd : fun2_wd E E E (fun _ p => S p).
Proof.
unfold fun2_wd; intros _ _ _ p p' H; now rewrite H.
Qed.

Add Morphism plus with signature E ==> E ==> E as plus_wd.
Proof.
unfold plus.
intros x x' Exx' y y' Eyy'.
apply recursion_wd with (EA := E).
assumption.
unfold eq_fun2; intros _ _ _ p p' Epp'; now rewrite Epp'.
assumption.
Qed.

Theorem plus_0 : forall y, plus 0 y == y.
Proof.
intro y. unfold plus.
(*pose proof (recursion_0 E y (fun _ p => S p)) as H.*)
rewrite recursion_0. apply (proj1 E_equiv).
Qed.

Theorem plus_succ : forall x y, plus (S x) y == S (plus x y).
Proof.
intros x y; unfold plus.
now rewrite (recursion_succ E); [|apply plus_step_wd|].
Qed.

(*****************************************************)
(**                  Multiplication                  *)

Definition times (x y : N) := recursion 0 (fun _ p => plus p x) y.

Lemma times_step_wd : forall x, fun2_wd E E E (fun _ p => plus p x).
Proof.
unfold fun2_wd. intros. now apply plus_wd.
Qed.

Lemma times_step_equal :
  forall x x', x == x' -> eq_fun2 E E E (fun _ p => plus p x) (fun x p => plus p x').
Proof.
unfold eq_fun2; intros; apply plus_wd; assumption.
Qed.

Add Morphism times with signature E ==> E ==> E as times_wd.
Proof.
unfold times.
intros x x' Exx' y y' Eyy'.
apply recursion_wd with (EA := E).
reflexivity. apply times_step_equal. assumption. assumption.
Qed.

Theorem times_0_r : forall x, times x 0 == 0.
Proof.
intro. unfold times. now rewrite recursion_0.
Qed.

Theorem times_succ_r : forall x y, times x (S y) == plus (times x y) x.
Proof.
intros x y; unfold times.
now rewrite (recursion_succ E); [| apply times_step_wd |].
Qed.

(*****************************************************)
(**                   Less Than                      *)

Definition lt (m : N) : N -> bool :=
  recursion (if_zero false true)
            (fun _ f => fun n => recursion false (fun n' _ => f n') n)
            m.

(* It would be more efficient to make a three-way comparison, i.e.,
return Eq, Lt, or Gt, but since these are no-use default functions,
we define <= as (< or =) *)
Definition le (n m : N) := lt n m || e n m.

Theorem le_lt : forall n m, le n m <-> lt n m \/ n == m.
Proof.
intros n m. rewrite E_equiv_e. unfold le.
do 3 rewrite eq_true_unfold_pos.
assert (H : lt n m || e n m = true <-> lt n m = true \/ e n m = true).
split; [apply orb_prop | apply orb_true_intro].
now rewrite H.
Qed.

Theorem le_intro_left : forall n m, lt n m -> le n m.
Proof.
intros; rewrite le_lt; now left.
Qed.

Theorem le_intro_right : forall n m, n == m -> le n m.
Proof.
intros; rewrite le_lt; now right.
Qed.

Lemma lt_base_wd : eq_fun E eq_bool (if_zero false true) (if_zero false true).
unfold eq_fun, eq_bool; intros; apply if_zero_wd; now unfold LE_succet.
Qed.

Lemma lt_step_wd :
  let step := (fun _ f => fun n => recursion false (fun n' _ => f n') n) in
    eq_fun2 E (eq_fun E eq_bool) (eq_fun E eq_bool) step step.
Proof.
unfold eq_fun2, eq_fun, eq_bool.
intros x x' Exx' f f' Eff' y y' Eyy'.
apply recursion_wd with (EA := eq_bool); unfold eq_bool.
reflexivity.
unfold eq_fun2; intros; now apply Eff'.
assumption.
Qed.

Lemma lt_curry_wd : forall m m', m == m' -> eq_fun E eq_bool (lt m) (lt m').
Proof.
unfold lt.
intros m m' Emm'.
apply recursion_wd with (EA := eq_fun E eq_bool).
apply lt_base_wd.
apply lt_step_wd.
assumption.
Qed.

Add Morphism lt with signature E ==> E ==> eq_bool as lt_wd.
Proof.
unfold eq_fun; intros m m' Emm' n n' Enn'.
now apply lt_curry_wd.
Qed.

(* Note that if we unfold lt along with eq_fun above, then "apply" signals
as error "Impossible to unify", not just, e.g., "Cannot solve second-order
unification problem". Something is probably wrong. *)

Add Morphism le with signature E ==> E ==> eq_bool as le_wd.
Proof.
intros x1 x2 H1 x3 x4 H2; unfold le; rewrite H1; now rewrite H2.
Qed.

Theorem lt_base_eq : forall n, lt 0 n = if_zero false true n.
Proof.
intro n; unfold lt; now rewrite recursion_0.
Qed.

Theorem lt_step_eq : forall m n, lt (S m) n = recursion false (fun n' _ => lt m n') n.
Proof.
intros m n; unfold lt.
pose proof (recursion_succ (eq_fun E eq_bool) (if_zero false true)
  (fun _ f => fun n => recursion false (fun n' _ => f n') n)
  lt_base_wd lt_step_wd m n n) as H.
unfold eq_bool in H.
assert (H1 : n == n); [reflexivity | apply H in H1; now rewrite H1].
Qed.

Theorem lt_0 : forall n, ~ lt n 0.
Proof.
nondep_induct n.
rewrite lt_base_eq; rewrite if_zero_0; now intro.
intros n; rewrite lt_step_eq. rewrite recursion_0. now intro.
Qed.

(* Above, we rewrite applications of function. Is it possible to rewrite
functions themselves, i.e., rewrite (recursion lt_base lt_step (S n)) to
lt_step n (recursion lt_base lt_step n)? *)

Lemma lt_0_1 : lt 0 1.
Proof.
rewrite lt_base_eq; now rewrite if_zero_succ.
Qed.

Lemma lt_0_succn : forall n, lt 0 (S n).
Proof.
intro n; rewrite lt_base_eq; now rewrite if_zero_succ.
Qed.

Lemma lt_succn_succm : forall n m, lt (S n) (S m) <-> lt n m.
Proof.
intros n m.
rewrite lt_step_eq. rewrite (recursion_succ eq_bool).
reflexivity.
now unfold eq_bool.
unfold fun2_wd; intros; now apply lt_wd.
Qed.

Theorem lt_succ : forall m n, lt m (S n) <-> le m n.
Proof.
assert (A : forall m n, lt m (S n) <-> lt m n \/ m == n).
induct m.
nondep_induct n;
[split; intro; [now right | apply lt_0_1] |
intro n; split; intro; [left |]; apply lt_0_succn].
intros n IH. nondep_induct n0.
split.
intro. assert (H1 : lt n 0); [now apply -> lt_succn_succm | false_hyp H1 lt_0].
intro H; destruct H as [H | H].
false_hyp H lt_0. false_hyp H succ_0.
intro m. pose proof (IH m) as H; clear IH.
assert (lt (S n) (S (S m)) <-> lt n (S m)); [apply lt_succn_succm |].
assert (lt (S n) (S m) <-> lt n m); [apply lt_succn_succm |].
assert (S n == S m <-> n == m); [split; [ apply succ_inj | apply succ_wd]|]. tauto.
intros; rewrite le_lt; apply A.
Qed.

(*****************************************************)
(**                     Even                         *)

Definition even (x : N) := recursion true (fun _ p => negb p) x.

Lemma even_step_wd : fun2_wd E eq_bool eq_bool (fun x p => if p then false else true).
Proof.
unfold fun2_wd.
intros x x' Exx' b b' Ebb'.
unfold eq_bool; destruct b; destruct b'; now simpl.
Qed.

Add Morphism even with signature E ==> eq_bool as even_wd.
Proof.
unfold even; intros.
apply recursion_wd with (A := bool) (EA := eq_bool).
now unfold eq_bool.
unfold eq_fun2. intros _ _ _ b b' Ebb'. unfold eq_bool; destruct b; destruct b'; now simpl.
assumption.
Qed.

Theorem even_0 : even 0 = true.
Proof.
unfold even.
now rewrite recursion_0.
Qed.

Theorem even_succ : forall x : N, even (S x) = negb (even x).
Proof.
unfold even.
intro x; rewrite (recursion_succ (@eq bool)); try reflexivity.
unfold fun2_wd.
intros _ _ _ b b' Ebb'. destruct b; destruct b'; now simpl.
Qed.

(*****************************************************)
(**                Division by 2                     *)

Definition half_aux (x : N) : N * N :=
  recursion (0, 0) (fun _ p => let (x1, x2) := p in ((S x2, x1))) x.

Definition half (x : N) := snd (half_aux x).

Definition E2 := prod_rel E E.

Add Relation (prod N N) E2
reflexivity proved by (prod_rel_refl N N E E E_equiv E_equiv)
symmetry proved by (prod_rel_symm N N E E E_equiv E_equiv)
transitivity proved by (prod_rel_trans N N E E E_equiv E_equiv)
as E2_rel.

Lemma half_step_wd: fun2_wd E E2 E2 (fun _ p => let (x1, x2) := p in ((S x2, x1))).
Proof.
unfold fun2_wd, E2, prod_rel.
intros _ _ _ p1 p2 [H1 H2].
destruct p1; destruct p2; simpl in *.
now split; [rewrite H2 |].
Qed.

Add Morphism half with signature E ==> E as half_wd.
Proof.
unfold half.
assert (H: forall x y, x == y -> E2 (half_aux x) (half_aux y)).
intros x y Exy; unfold half_aux; apply recursion_wd with (EA := E2); unfold E2.
unfold E2.
unfold prod_rel; simpl; now split.
unfold eq_fun2, prod_rel; simpl.
intros _ _ _ p1 p2; destruct p1; destruct p2; simpl.
intros [H1 H2]; split; [rewrite H2 | assumption]. reflexivity. assumption.
unfold E2, prod_rel in H. intros x y Exy; apply H in Exy.
exact (proj2 Exy).
Qed.

(*****************************************************)
(**            Logarithm for the base 2              *)

Definition log (x : N) : N :=
strong_rec 0
           (fun x g =>
              if (e x 0) then 0
              else if (e x 1) then 0
              else S (g (half x)))
           x.

Add Morphism log with signature E ==> E as log_wd.
Proof.
intros x x' Exx'. unfold log.
apply strong_rec_wd with (EA := E); try (reflexivity || assumption).
unfold eq_fun2. intros y y' Eyy' g g' Egg'.
assert (H : e y 0 = e y' 0); [now apply e_wd|].
rewrite <- H; clear H.
assert (H : e y 1 = e y' 1); [now apply e_wd|].
rewrite <- H; clear H.
assert (H : S (g (half y)) == S (g' (half y')));
[apply succ_wd; apply Egg'; now apply half_wd|].
now destruct (e y 0); destruct (e y 1).
Qed.

(*********************************************************)
(** To get the properties of plus, times and lt defined  *)
(** via recursion, we form the corresponding modules and *)
(** apply the properties functors to these modules       *)

Module NDefaultPlusModule <: NPlusSig.

Module NBaseMod := NatMod.
(* If we used the name NBaseMod instead of NatMod then this would
produce many warnings like "Trying to mask the absolute name
NBaseMod", "Trying to mask the absolute name Nat.O" etc. *)

Definition plus := plus.

Add Morphism plus with signature E ==> E ==> E as plus_wd.
Proof.
exact plus_wd.
Qed.

Theorem plus_0_l : forall n, plus 0 n == n.
Proof.
exact plus_0.
Qed.

Theorem plus_succ_l : forall n m, plus (S n) m == S (plus n m).
Proof.
exact plus_succ.
Qed.

End NDefaultPlusModule.

Module NDefaultTimesModule <: NTimesSig.
Module NPlusMod := NDefaultPlusModule.

Definition times := times.

Add Morphism times with signature E ==> E ==> E as times_wd.
Proof.
exact times_wd.
Qed.

Definition times_0_r := times_0_r.
Definition times_succ_r := times_succ_r.

End NDefaultTimesModule.

Module NDefaultOrderModule <: NOrderSig.
Module NBaseMod := NatMod.

Definition lt := lt.
Definition le := le.

Add Morphism lt with signature E ==> E ==> eq_bool as lt_wd.
Proof.
exact lt_wd.
Qed.

Add Morphism le with signature E ==> E ==> eq_bool as le_wd.
Proof.
exact le_wd.
Qed.

(* This produces a warning about a morphism redeclaration. Why is not
there a warning after declaring lt? *)

Theorem le_lt : forall x y, le x y <-> lt x y \/ x == y.
Proof.
exact le_lt.
Qed.

Theorem lt_0 : forall x, ~ (lt x 0).
Proof.
exact lt_0.
Qed.

Theorem lt_succ : forall x y, lt x (S y) <-> le x y.
Proof.
exact lt_succ.
Qed.

End NDefaultOrderModule.

Module Export DefaultTimesOrderProperties :=
  NTimesOrderProperties NDefaultTimesModule NDefaultOrderModule.

End MiscFunctFunctor.


(*
 Local Variables:
 tags-file-name: "~/coq/trunk/theories/Numbers/TAGS"
 End:
*)