aboutsummaryrefslogtreecommitdiff
path: root/theories/Numbers/Natural/Abstract/NMiscFunct.v
diff options
context:
space:
mode:
Diffstat (limited to 'theories/Numbers/Natural/Abstract/NMiscFunct.v')
-rw-r--r--theories/Numbers/Natural/Abstract/NMiscFunct.v404
1 files changed, 404 insertions, 0 deletions
diff --git a/theories/Numbers/Natural/Abstract/NMiscFunct.v b/theories/Numbers/Natural/Abstract/NMiscFunct.v
new file mode 100644
index 0000000000..82a9224533
--- /dev/null
+++ b/theories/Numbers/Natural/Abstract/NMiscFunct.v
@@ -0,0 +1,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:
+*)