diff options
author | letouzey <letouzey@85f007b7-540e-0410-9357-904b9bb8a0f7> | 2010-02-10 13:43:19 +0000 |
---|---|---|
committer | letouzey <letouzey@85f007b7-540e-0410-9357-904b9bb8a0f7> | 2010-02-10 13:43:19 +0000 |
commit | 782372856e836ca106011fada44695c224ae572d (patch) | |
tree | 25d9606ac70aae1788e01f8862bcad8267f95c6f /theories/NArith/Ndiv_def.v | |
parent | e23adb436938ca6b43bb3ecc7111e952549b66f0 (diff) |
Euclidean division for NArith
There was already a Ndiv and Nmod, but hiddent in ZOdiv_def. We
higlight it by putting it in a separate file, prove its specification
without using Z (but for the moment can't avoid a detour via nat,
though), and then instantiate general results from Natural/Abstract/NDiv
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@12726 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'theories/NArith/Ndiv_def.v')
-rw-r--r-- | theories/NArith/Ndiv_def.v | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/theories/NArith/Ndiv_def.v b/theories/NArith/Ndiv_def.v new file mode 100644 index 000000000..17e821da0 --- /dev/null +++ b/theories/NArith/Ndiv_def.v @@ -0,0 +1,196 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) + + +Require Import BinPos BinNat Pnat Plus Compare_dec. + +Local Open Scope N_scope. + +Definition NPgeb (a:N)(b:positive) := + match a with + | 0 => false + | Npos na => match Pcompare na b Eq with Lt => false | _ => true end + end. + +Local Notation "a >=? b" := (NPgeb a b) (at level 70). + +Fixpoint Pdiv_eucl (a b:positive) : N * N := + match a with + | xH => + match b with xH => (1, 0) | _ => (0, 1) end + | xO a' => + let (q, r) := Pdiv_eucl a' b in + let r' := 2 * r in + if r' >=? b then (2 * q + 1, r' - Npos b) + else (2 * q, r') + | xI a' => + let (q, r) := Pdiv_eucl a' b in + let r' := 2 * r + 1 in + if r' >=? b then (2 * q + 1, r' - Npos b) + else (2 * q, r') + end. + +Definition Ndiv_eucl (a b:N) : N * N := + match a, b with + | 0, _ => (0, 0) + | _, 0 => (0, a) + | Npos na, Npos nb => Pdiv_eucl na nb + end. + +Definition Ndiv a b := fst (Ndiv_eucl a b). +Definition Nmod a b := snd (Ndiv_eucl a b). + +Infix "/" := Ndiv : N_scope. +Infix "mod" := Nmod (at level 40, no associativity) : N_scope. + +(** Auxiliary Results about [NPgeb] *) + +Lemma NPgeb_ge : forall a b, NPgeb a b = true -> a >= Npos b. +Proof. + destruct a; simpl; intros. + discriminate. + unfold Nge, Ncompare. now destruct Pcompare. +Qed. + +Lemma NPgeb_lt : forall a b, NPgeb a b = false -> a < Npos b. +Proof. + destruct a; simpl; intros. red; auto. + unfold Nlt, Ncompare. now destruct Pcompare. +Qed. + +Theorem NPgeb_correct: forall (a:N)(b:positive), + if NPgeb a b then a = a - Npos b + Npos b else True. +Proof. + destruct a as [|a]; simpl; intros b; auto. + generalize (Pcompare_Eq_eq a b). + case_eq (Pcompare a b Eq); intros; auto. + rewrite H0; auto. + now rewrite Pminus_mask_diag. + destruct (Pminus_mask_Gt a b H) as [d [H2 [H3 _]]]. + rewrite H2. rewrite <- H3. + simpl; f_equal; apply Pplus_comm. +Qed. + +Lemma Plt_add_cancel_l : forall n m p, (p+n < p+m -> n<m)%positive. +Proof. + intros n m p H. + unfold Plt in *. + rewrite nat_of_P_compare_morphism in *. + rewrite 2 nat_of_P_plus_morphism in *. + apply nat_compare_lt. + apply nat_compare_lt in H. + eapply plus_lt_reg_l; eauto. +Qed. + +Lemma Plt_add_not_lt : forall n m, ~(n+m < n)%positive. +Proof. + intros n m H. + unfold Plt in *. + rewrite nat_of_P_compare_morphism in *. + rewrite nat_of_P_plus_morphism in *. + apply nat_compare_lt in H. + absurd (nat_of_P m < 0)%nat. + red; inversion 1. + apply plus_lt_reg_l with (nat_of_P n). now rewrite plus_0_r. +Qed. + +Lemma Nlt_add_cancel_l : forall n m p, p+n < p+m -> n<m. +Proof. + intros. destruct p. simpl; auto. + destruct n; destruct m. + elim (Nlt_irrefl _ H). + red; auto. + rewrite Nplus_0_r in H. simpl in H. + elim (Plt_add_not_lt _ _ H). + apply Plt_add_cancel_l with p; auto. +Qed. + +Lemma NPgeb_ineq0 : forall a p, a < Npos p -> NPgeb (2*a) p = true -> + 2*a - Npos p < Npos p. +Proof. +intros a p LT GE. +apply Nlt_add_cancel_l with (Npos p). +rewrite Nplus_comm. +generalize (NPgeb_correct (2*a) p). rewrite GE. intros <-. +rewrite <- (Nmult_1_l (Npos p)). rewrite <- Nmult_plus_distr_r. +destruct a; auto. +Qed. + +Lemma NPgeb_ineq1 : forall a p, a < Npos p -> NPgeb (2*a+1) p = true -> + (2*a+1) - Npos p < Npos p. +Proof. +intros a p LT GE. +apply Nlt_add_cancel_l with (Npos p). +rewrite Nplus_comm. +generalize (NPgeb_correct (2*a+1) p). rewrite GE. intros <-. +rewrite <- (Nmult_1_l (Npos p)). rewrite <- Nmult_plus_distr_r. +destruct a; auto. +red; simpl. apply Pcompare_eq_Lt; auto. +Qed. + +(* Proofs of specifications for these euclidean divisions. *) + +Theorem Pdiv_eucl_correct: forall a b, + let (q,r) := Pdiv_eucl a b in Npos a = q * Npos b + r. +Proof. + induction a; cbv beta iota delta [Pdiv_eucl]; fold Pdiv_eucl; cbv zeta. + intros b; generalize (IHa b); case Pdiv_eucl. + intros q1 r1 Hq1. + assert (Npos a~1 = 2*q1*Npos b + (2*r1+1)) + by now rewrite Nplus_assoc, <- Nmult_assoc, <- Nmult_plus_distr_l, <- Hq1. + generalize (NPgeb_correct (2 * r1 + 1) b); case NPgeb; intros H'; auto. + rewrite Nmult_plus_distr_r, Nmult_1_l. + rewrite <- Nplus_assoc, (Nplus_comm (Npos b)), <- H'; auto. + intros b; generalize (IHa b); case Pdiv_eucl. + intros q1 r1 Hq1. + assert (Npos a~0 = 2*q1*Npos b + 2*r1) + by now rewrite <- Nmult_assoc, <- Nmult_plus_distr_l, <- Hq1. + generalize (NPgeb_correct (2 * r1) b); case NPgeb; intros H'; auto. + rewrite Nmult_plus_distr_r, Nmult_1_l. + rewrite <- Nplus_assoc, (Nplus_comm (Npos b)), <- H'; auto. + destruct b; auto. +Qed. + +Theorem Ndiv_eucl_correct: forall a b, + let (q,r) := Ndiv_eucl a b in a = b * q + r. +Proof. + destruct a as [|a]; destruct b as [|b]; simpl; auto. + generalize (Pdiv_eucl_correct a b); case Pdiv_eucl; intros q r. + destruct q. simpl; auto. rewrite Nmult_comm. intro EQ; exact EQ. +Qed. + +Theorem Ndiv_mod_eq : forall a b, + a = b * (a/b) + (a mod b). +Proof. + intros; generalize (Ndiv_eucl_correct a b). + unfold Ndiv, Nmod; destruct Ndiv_eucl; simpl; auto. +Qed. + +Theorem Pdiv_eucl_remainder : forall a b:positive, + snd (Pdiv_eucl a b) < Npos b. +Proof. + induction a; cbv beta iota delta [Pdiv_eucl]; fold Pdiv_eucl; cbv zeta. + intros b; generalize (IHa b); case Pdiv_eucl. + intros q1 r1 Hr1; simpl in Hr1. + case_eq (NPgeb (2*r1+1) b); intros; unfold snd. + apply NPgeb_ineq1; auto. + apply NPgeb_lt; auto. + intros b; generalize (IHa b); case Pdiv_eucl. + intros q1 r1 Hr1; simpl in Hr1. + case_eq (NPgeb (2*r1) b); intros; unfold snd. + apply NPgeb_ineq0; auto. + apply NPgeb_lt; auto. + destruct b; simpl; reflexivity. +Qed. + +Theorem Nmod_lt : forall (a b:N), b<>0 -> a mod b < b. +Proof. + destruct b as [ |b]; intro H; try solve [elim H;auto]. + destruct a as [ |a]; try solve [compute;auto]; unfold Nmod, Ndiv_eucl. + generalize (Pdiv_eucl_remainder a b); destruct Pdiv_eucl; simpl; auto. +Qed. |