summaryrefslogtreecommitdiff
path: root/theories/Arith/Div2.v
diff options
context:
space:
mode:
Diffstat (limited to 'theories/Arith/Div2.v')
-rw-r--r--theories/Arith/Div2.v175
1 files changed, 175 insertions, 0 deletions
diff --git a/theories/Arith/Div2.v b/theories/Arith/Div2.v
new file mode 100644
index 00000000..c005f061
--- /dev/null
+++ b/theories/Arith/Div2.v
@@ -0,0 +1,175 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(*i $Id: Div2.v,v 1.15.2.1 2004/07/16 19:31:00 herbelin Exp $ i*)
+
+Require Import Lt.
+Require Import Plus.
+Require Import Compare_dec.
+Require Import Even.
+
+Open Local Scope nat_scope.
+
+Implicit Type n : nat.
+
+(** Here we define [n/2] and prove some of its properties *)
+
+Fixpoint div2 n : nat :=
+ match n with
+ | O => 0
+ | S O => 0
+ | S (S n') => S (div2 n')
+ end.
+
+(** Since [div2] is recursively defined on [0], [1] and [(S (S n))], it is
+ useful to prove the corresponding induction principle *)
+
+Lemma ind_0_1_SS :
+ forall P:nat -> Prop,
+ P 0 -> P 1 -> (forall n, P n -> P (S (S n))) -> forall n, P n.
+Proof.
+intros.
+cut (forall n, P n /\ P (S n)).
+intros. elim (H2 n). auto with arith.
+
+induction n0. auto with arith.
+intros. elim IHn0; auto with arith.
+Qed.
+
+(** [0 <n => n/2 < n] *)
+
+Lemma lt_div2 : forall n, 0 < n -> div2 n < n.
+Proof.
+intro n. pattern n in |- *. apply ind_0_1_SS.
+intro. inversion H.
+auto with arith.
+intros. simpl in |- *.
+case (zerop n0).
+intro. rewrite e. auto with arith.
+auto with arith.
+Qed.
+
+Hint Resolve lt_div2: arith.
+
+(** Properties related to the parity *)
+
+Lemma even_odd_div2 :
+ forall n,
+ (even n <-> div2 n = div2 (S n)) /\ (odd n <-> S (div2 n) = div2 (S n)).
+Proof.
+intro n. pattern n in |- *. apply ind_0_1_SS.
+(* n = 0 *)
+split. split; auto with arith.
+split. intro H. inversion H.
+intro H. absurd (S (div2 0) = div2 1); auto with arith.
+(* n = 1 *)
+split. split. intro. inversion H. inversion H1.
+intro H. absurd (div2 1 = div2 2).
+simpl in |- *. discriminate. assumption.
+split; auto with arith.
+(* n = (S (S n')) *)
+intros. decompose [and] H. unfold iff in H0, H1.
+decompose [and] H0. decompose [and] H1. clear H H0 H1.
+split; split; auto with arith.
+intro H. inversion H. inversion H1.
+change (S (div2 n0) = S (div2 (S n0))) in |- *. auto with arith.
+intro H. inversion H. inversion H1.
+change (S (S (div2 n0)) = S (div2 (S n0))) in |- *. auto with arith.
+Qed.
+
+(** Specializations *)
+
+Lemma even_div2 : forall n, even n -> div2 n = div2 (S n).
+Proof fun n => proj1 (proj1 (even_odd_div2 n)).
+
+Lemma div2_even : forall n, div2 n = div2 (S n) -> even n.
+Proof fun n => proj2 (proj1 (even_odd_div2 n)).
+
+Lemma odd_div2 : forall n, odd n -> S (div2 n) = div2 (S n).
+Proof fun n => proj1 (proj2 (even_odd_div2 n)).
+
+Lemma div2_odd : forall n, S (div2 n) = div2 (S n) -> odd n.
+Proof fun n => proj2 (proj2 (even_odd_div2 n)).
+
+Hint Resolve even_div2 div2_even odd_div2 div2_odd: arith.
+
+(** Properties related to the double ([2n]) *)
+
+Definition double n := n + n.
+
+Hint Unfold double: arith.
+
+Lemma double_S : forall n, double (S n) = S (S (double n)).
+Proof.
+intro. unfold double in |- *. simpl in |- *. auto with arith.
+Qed.
+
+Lemma double_plus : forall n (m:nat), double (n + m) = double n + double m.
+Proof.
+intros m n. unfold double in |- *.
+do 2 rewrite plus_assoc_reverse. rewrite (plus_permute n).
+reflexivity.
+Qed.
+
+Hint Resolve double_S: arith.
+
+Lemma even_odd_double :
+ forall n,
+ (even n <-> n = double (div2 n)) /\ (odd n <-> n = S (double (div2 n))).
+Proof.
+intro n. pattern n in |- *. apply ind_0_1_SS.
+(* n = 0 *)
+split; split; auto with arith.
+intro H. inversion H.
+(* n = 1 *)
+split; split; auto with arith.
+intro H. inversion H. inversion H1.
+(* n = (S (S n')) *)
+intros. decompose [and] H. unfold iff in H0, H1.
+decompose [and] H0. decompose [and] H1. clear H H0 H1.
+split; split.
+intro H. inversion H. inversion H1.
+simpl in |- *. rewrite (double_S (div2 n0)). auto with arith.
+simpl in |- *. rewrite (double_S (div2 n0)). intro H. injection H. auto with arith.
+intro H. inversion H. inversion H1.
+simpl in |- *. rewrite (double_S (div2 n0)). auto with arith.
+simpl in |- *. rewrite (double_S (div2 n0)). intro H. injection H. auto with arith.
+Qed.
+
+
+(** Specializations *)
+
+Lemma even_double : forall n, even n -> n = double (div2 n).
+Proof fun n => proj1 (proj1 (even_odd_double n)).
+
+Lemma double_even : forall n, n = double (div2 n) -> even n.
+Proof fun n => proj2 (proj1 (even_odd_double n)).
+
+Lemma odd_double : forall n, odd n -> n = S (double (div2 n)).
+Proof fun n => proj1 (proj2 (even_odd_double n)).
+
+Lemma double_odd : forall n, n = S (double (div2 n)) -> odd n.
+Proof fun n => proj2 (proj2 (even_odd_double n)).
+
+Hint Resolve even_double double_even odd_double double_odd: arith.
+
+(** Application:
+ - if [n] is even then there is a [p] such that [n = 2p]
+ - if [n] is odd then there is a [p] such that [n = 2p+1]
+
+ (Immediate: it is [n/2]) *)
+
+Lemma even_2n : forall n, even n -> {p : nat | n = double p}.
+Proof.
+intros n H. exists (div2 n). auto with arith.
+Qed.
+
+Lemma odd_S2n : forall n, odd n -> {p : nat | n = S (double p)}.
+Proof.
+intros n H. exists (div2 n). auto with arith.
+Qed.