diff options
author | Samuel Mimram <smimram@debian.org> | 2008-07-25 15:13:01 +0200 |
---|---|---|
committer | Samuel Mimram <smimram@debian.org> | 2008-07-25 15:13:01 +0200 |
commit | d18b6226c9ecdb0ebbef6d29fb9f0c09ba78a5fa (patch) | |
tree | f9a2c15acb3448f4e78f4e8b7328f751fb144aa0 /theories | |
parent | 4892a9c7ae62f552fa42701788b2bd08a7f3bc08 (diff) | |
parent | a0cfa4f118023d35b767a999d5a2ac4b082857b4 (diff) |
Merge commit 'upstream/8.2.beta3+dfsg'
Diffstat (limited to 'theories')
292 files changed, 51229 insertions, 17572 deletions
diff --git a/theories/Arith/Arith_base.v b/theories/Arith/Arith_base.v index b076de2a..fbdf2a41 100644 --- a/theories/Arith/Arith_base.v +++ b/theories/Arith/Arith_base.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id$ i*) +(*i $Id: Arith_base.v 11072 2008-06-08 16:13:37Z herbelin $ i*) Require Export Le. Require Export Lt. @@ -18,3 +18,5 @@ Require Export Between. Require Export Peano_dec. Require Export Compare_dec. Require Export Factorial. +Require Export EqNat. +Require Export Wf_nat. diff --git a/theories/Arith/Compare_dec.v b/theories/Arith/Compare_dec.v index b431fd05..e6cb5be4 100644 --- a/theories/Arith/Compare_dec.v +++ b/theories/Arith/Compare_dec.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Compare_dec.v 9941 2007-07-05 12:42:35Z letouzey $ i*) +(*i $Id: Compare_dec.v 10295 2007-11-06 22:46:21Z letouzey $ i*) Require Import Le. Require Import Lt. @@ -170,7 +170,7 @@ Proof. exact (lt_irrefl n). intros. apply not_gt. - swap H. + contradict H. destruct (nat_compare_gt n m); auto. Qed. @@ -184,7 +184,7 @@ Proof. exact (lt_irrefl m). intros. apply not_lt. - swap H. + contradict H. destruct (nat_compare_lt n m); auto. Qed. diff --git a/theories/Arith/Div.v b/theories/Arith/Div.v deleted file mode 100644 index 1dec34e2..00000000 --- a/theories/Arith/Div.v +++ /dev/null @@ -1,64 +0,0 @@ -(************************************************************************) -(* 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: Div.v 9245 2006-10-17 12:53:34Z notin $ i*) - -(** Euclidean division *) - -V7only [Import nat_scope.]. -Open Local Scope nat_scope. - -Require Le. -Require Euclid_def. -Require Compare_dec. - -Implicit Variables Type n,a,b,q,r:nat. - -Fixpoint inf_dec [n:nat] : nat->bool := - [m:nat] Cases n m of - O _ => true - | (S n') O => false - | (S n') (S m') => (inf_dec n' m') - end. - -Theorem div1 : (b:nat)(gt b O)->(a:nat)(diveucl a b). - Realizer Fix div1 {div1/2: nat->nat->diveucl := - [b,a]Cases a of - O => (O,O) - | (S n) => - let (q,r) = (div1 b n) in - if (le_gt_dec b (S r)) then ((S q),O) - else (q,(S r)) - end}. - Program_all. - Rewrite e. - Replace b with (S r). - Simpl. - Elim plus_n_O; Auto with arith. - Apply le_antisym; Auto with arith. - Elim plus_n_Sm; Auto with arith. -Qed. - -Theorem div2 : (b:nat)(gt b O)->(a:nat)(diveucl a b). - Realizer Fix div1 {div1/2: nat->nat->diveucl := - [b,a]Cases a of - O => (O,O) - | (S n) => - let (q,r) = (div1 b n) in - if (inf_dec b (S r)) :: :: { {(le b (S r))}+{(gt b (S r))} } - then ((S q),O) - else (q,(S r)) - end}. - Program_all. - Rewrite e. - Replace b with (S r). - Simpl. - Elim plus_n_O; Auto with arith. - Apply le_antisym; Auto with arith. - Elim plus_n_Sm; Auto with arith. -Qed. diff --git a/theories/Arith/Div2.v b/theories/Arith/Div2.v index c32759b2..1216a545 100644 --- a/theories/Arith/Div2.v +++ b/theories/Arith/Div2.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Div2.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Div2.v 10625 2008-03-06 11:21:01Z notin $ i*) Require Import Lt. Require Import Plus. @@ -169,12 +169,12 @@ Hint Resolve even_double double_even odd_double double_odd: arith. Lemma even_2n : forall n, even n -> {p : nat | n = double p}. Proof. intros n H. exists (div2 n). auto with arith. -Qed. +Defined. Lemma odd_S2n : forall n, odd n -> {p : nat | n = S (double p)}. Proof. intros n H. exists (div2 n). auto with arith. -Qed. +Defined. (** Doubling before dividing by two brings back to the initial number. *) diff --git a/theories/Arith/EqNat.v b/theories/Arith/EqNat.v index 82d05e2c..a9244455 100644 --- a/theories/Arith/EqNat.v +++ b/theories/Arith/EqNat.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: EqNat.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: EqNat.v 9966 2007-07-10 23:54:53Z letouzey $ i*) (** Equality on natural numbers *) @@ -89,3 +89,13 @@ Proof. intros n H1 H2. discriminate H2. intros n H1 z H2 H3. case (H2 _ H3). reflexivity. Defined. + +Lemma beq_nat_true : forall x y, beq_nat x y = true -> x=y. +Proof. + induction x; destruct y; simpl; auto; intros; discriminate. +Qed. + +Lemma beq_nat_false : forall x y, beq_nat x y = false -> x<>y. +Proof. + induction x; destruct y; simpl; auto; intros; discriminate. +Qed. diff --git a/theories/Arith/Even.v b/theories/Arith/Even.v index 83c0ce17..1484666b 100644 --- a/theories/Arith/Even.v +++ b/theories/Arith/Even.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Even.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Even.v 10410 2007-12-31 13:11:55Z msozeau $ i*) (** Here we define the predicates [even] and [odd] by mutual induction and we prove the decidability and the exclusion of those predicates. @@ -40,7 +40,7 @@ Proof. induction n. auto with arith. elim IHn; auto with arith. -Qed. +Defined. Lemma not_even_and_odd : forall n, even n -> odd n -> False. Proof. diff --git a/theories/Arith/Max.v b/theories/Arith/Max.v index e0222e41..95af67f8 100644 --- a/theories/Arith/Max.v +++ b/theories/Arith/Max.v @@ -6,9 +6,9 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Max.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Max.v 9883 2007-06-07 18:44:59Z letouzey $ i*) -Require Import Arith. +Require Import Le. Open Local Scope nat_scope. @@ -30,6 +30,13 @@ Proof. auto with arith. Qed. +Theorem max_assoc : forall m n p : nat, max m (max n p) = max (max m n) p. +Proof. + induction m; destruct n; destruct p; trivial. + simpl. + auto using IHm. +Qed. + Lemma max_comm : forall n m, max n m = max m n. Proof. induction n; induction m; simpl in |- *; auto with arith. diff --git a/theories/Arith/Min.v b/theories/Arith/Min.v index db14e74b..aa009963 100644 --- a/theories/Arith/Min.v +++ b/theories/Arith/Min.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Min.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Min.v 9660 2007-02-19 11:36:30Z notin $ i*) Require Import Le. @@ -25,11 +25,28 @@ Fixpoint min n m {struct n} : nat := (** * Simplifications of [min] *) +Lemma min_0_l : forall n : nat, min 0 n = 0. +Proof. + trivial. +Qed. + +Lemma min_0_r : forall n : nat, min n 0 = 0. +Proof. + destruct n; trivial. +Qed. + Lemma min_SS : forall n m, S (min n m) = min (S n) (S m). Proof. auto with arith. Qed. +Lemma min_assoc : forall m n p : nat, min m (min n p) = min (min m n) p. +Proof. + induction m; destruct n; destruct p; trivial. + simpl. + auto using (IHm n p). +Qed. + Lemma min_comm : forall n m, min n m = min m n. Proof. induction n; induction m; simpl in |- *; auto with arith. diff --git a/theories/Arith/Minus.v b/theories/Arith/Minus.v index 2380c2de..b961886d 100644 --- a/theories/Arith/Minus.v +++ b/theories/Arith/Minus.v @@ -6,13 +6,13 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Minus.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Minus.v 11072 2008-06-08 16:13:37Z herbelin $ i*) (** [minus] (difference between two natural numbers) is defined in [Init/Peano.v] as: << Fixpoint minus (n m:nat) {struct n} : nat := match n, m with - | O, _ => 0 + | O, _ => n | S k, O => S k | S k, S l => k - l end @@ -51,11 +51,18 @@ Qed. (** * Diagonal *) -Lemma minus_n_n : forall n, 0 = n - n. +Lemma minus_diag : forall n, n - n = 0. Proof. induction n; simpl in |- *; auto with arith. Qed. -Hint Resolve minus_n_n: arith v62. + +Lemma minus_diag_reverse : forall n, 0 = n - n. +Proof. + auto using minus_diag. +Qed. +Hint Resolve minus_diag_reverse: arith v62. + +Notation minus_n_n := minus_diag_reverse. (** * Simplification *) @@ -97,23 +104,39 @@ Hint Resolve le_plus_minus_r: arith v62. (** * Relation with order *) -Theorem le_minus : forall n m, n - m <= n. +Theorem minus_le_compat_r : forall n m p : nat, n <= m -> n - p <= m - p. Proof. - intros i h; pattern i, h in |- *; apply nat_double_ind; - [ auto - | auto - | intros m n H; simpl in |- *; apply le_trans with (m := m); auto ]. + intros n m p; generalize n m; clear n m; induction p as [|p HI]. + intros n m; rewrite <- (minus_n_O n); rewrite <- (minus_n_O m); trivial. + + intros n m Hnm; apply le_elim_rel with (n:=n) (m:=m); auto with arith. + intros q r H _. simpl. auto using HI. +Qed. + +Theorem minus_le_compat_l : forall n m p : nat, n <= m -> p - m <= p - n. +Proof. + intros n m p; generalize n m; clear n m; induction p as [|p HI]. + trivial. + + intros n m Hnm; apply le_elim_rel with (n:=n) (m:=m); trivial. + intros q; destruct q; auto with arith. + simpl. + apply le_trans with (m := p - 0); [apply HI | rewrite <- minus_n_O]; + auto with arith. + + intros q r Hqr _. simpl. auto using HI. +Qed. + +Corollary le_minus : forall n m, n - m <= n. +Proof. + intros n m; rewrite minus_n_O; auto using minus_le_compat_l with arith. Qed. Lemma lt_minus : forall n m, m <= n -> 0 < m -> n - m < n. Proof. intros n m Le; pattern m, n in |- *; apply le_elim_rel; simpl in |- *; - auto with arith. - intros; absurd (0 < 0); auto with arith. - intros p q lepq Hp gtp. - elim (le_lt_or_eq 0 p); auto with arith. - auto with arith. - induction 1; elim minus_n_O; auto with arith. + auto using le_minus with arith. + intros; absurd (0 < 0); auto with arith. Qed. Hint Resolve lt_minus: arith v62. diff --git a/theories/Arith/Mult.v b/theories/Arith/Mult.v index 2315e12c..a43579f9 100644 --- a/theories/Arith/Mult.v +++ b/theories/Arith/Mult.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Mult.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Mult.v 11015 2008-05-28 20:06:42Z herbelin $ i*) Require Export Plus. Require Export Minus. @@ -104,6 +104,43 @@ Proof. Qed. Hint Resolve mult_assoc: arith v62. +(** ** Inversion lemmas *) + +Lemma mult_is_O : forall n m, n * m = 0 -> n = 0 \/ m = 0. +Proof. + destruct n as [| n]. + intros; left; trivial. + + simpl; intros m H; right. + assert (H':m = 0 /\ n * m = 0) by apply (plus_is_O _ _ H). + destruct H'; trivial. +Qed. + +Lemma mult_is_one : forall n m, n * m = 1 -> n = 1 /\ m = 1. +Proof. + destruct n as [|n]. + simpl; intros m H; elim (O_S _ H). + + simpl; intros m H. + destruct (plus_is_one _ _ H) as [[Hm Hnm] | [Hm Hnm]]. + rewrite Hm in H; simpl in H; rewrite mult_0_r in H; elim (O_S _ H). + rewrite Hm in Hnm; rewrite mult_1_r in Hnm; auto. +Qed. + +(** ** Multiplication and successor *) + +Lemma mult_succ_l : forall n m:nat, S n * m = n * m + m. +Proof. + intros; simpl. rewrite plus_comm. reflexivity. +Qed. + +Lemma mult_succ_r : forall n m:nat, n * S m = n * m + n. +Proof. + induction n as [| p H]; intro m; simpl. + reflexivity. + rewrite H, <- plus_n_Sm; apply f_equal; rewrite plus_assoc; reflexivity. +Qed. + (** * Compatibility with orders *) Lemma mult_O_le : forall n m, m = 0 \/ n <= m * n. @@ -223,4 +260,4 @@ Qed. Ltac tail_simpl := repeat rewrite <- plus_tail_plus; repeat rewrite <- mult_tail_mult; - simpl in |- *.
\ No newline at end of file + simpl in |- *. diff --git a/theories/Arith/Peano_dec.v b/theories/Arith/Peano_dec.v index 9ae80d79..cc970ae4 100644 --- a/theories/Arith/Peano_dec.v +++ b/theories/Arith/Peano_dec.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Peano_dec.v 9941 2007-07-05 12:42:35Z letouzey $ i*) +(*i $Id: Peano_dec.v 9698 2007-03-12 17:11:32Z letouzey $ i*) Require Import Decidable. diff --git a/theories/Arith/Plus.v b/theories/Arith/Plus.v index 74d0dc93..6d510447 100644 --- a/theories/Arith/Plus.v +++ b/theories/Arith/Plus.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Plus.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Plus.v 9750 2007-04-06 00:58:14Z letouzey $ i*) (** Properties of addition. [add] is defined in [Init/Peano.v] as: << @@ -198,16 +198,14 @@ Qed. tail-recursive, whereas [plus] is not. This can be useful when extracting programs. *) -Fixpoint plus_acc q n {struct n} : nat := +Fixpoint tail_plus n m {struct n} : nat := match n with - | O => q - | S p => plus_acc (S q) p + | O => m + | S n => tail_plus n (S m) end. -Definition tail_plus n m := plus_acc m n. - Lemma plus_tail_plus : forall n m, n + m = tail_plus n m. -unfold tail_plus in |- *; induction n as [| n IHn]; simpl in |- *; auto. +induction n as [| n IHn]; simpl in |- *; auto. intro m; rewrite <- IHn; simpl in |- *; auto. Qed. diff --git a/theories/Arith/Wf_nat.v b/theories/Arith/Wf_nat.v index 11fcd161..6ad640eb 100644 --- a/theories/Arith/Wf_nat.v +++ b/theories/Arith/Wf_nat.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Wf_nat.v 9341 2006-11-06 13:08:10Z notin $ i*) +(*i $Id: Wf_nat.v 11072 2008-06-08 16:13:37Z herbelin $ i*) (** Well-founded relations and natural numbers *) @@ -50,10 +50,12 @@ Defined. the ML-like program for [induction_ltof1] is : [[ - let induction_ltof1 F a = indrec ((f a)+1) a - where rec indrec = - function 0 -> (function a -> error) - |(S m) -> (function a -> (F a (function y -> indrec y m)));; +let induction_ltof1 f F a = + let rec indrec n k = + match n with + | O -> error + | S m -> F k (indrec m) + in indrec (f a + 1) a ]] the ML-like program for [induction_ltof2] is : @@ -210,3 +212,67 @@ Lemma well_founded_inv_rel_inv_lt_rel : forall (A:Set) (F:A -> nat -> Prop), well_founded (inv_lt_rel A F). intros; apply (well_founded_inv_lt_rel_compat A (inv_lt_rel A F) F); trivial. Qed. + +(** A constructive proof that any non empty decidable subset of + natural numbers has a least element *) + +Set Implicit Arguments. + +Require Import Le. +Require Import Compare_dec. +Require Import Decidable. + +Definition has_unique_least_element (A:Type) (R:A->A->Prop) (P:A->Prop) := + exists! x, P x /\ forall x', P x' -> R x x'. + +Lemma dec_inh_nat_subset_has_unique_least_element : + forall P:nat->Prop, (forall n, P n \/ ~ P n) -> + (exists n, P n) -> has_unique_least_element le P. +Proof. + intros P Pdec (n0,HPn0). + assert + (forall n, (exists n', n'<n /\ P n' /\ forall n'', P n'' -> n'<=n'') + \/(forall n', P n' -> n<=n')). + induction n. + right. + intros n' Hn'. + apply le_O_n. + destruct IHn. + left; destruct H as (n', (Hlt', HPn')). + exists n'; split. + apply lt_S; assumption. + assumption. + destruct (Pdec n). + left; exists n; split. + apply lt_n_Sn. + split; assumption. + right. + intros n' Hltn'. + destruct (le_lt_eq_dec n n') as [Hltn|Heqn]. + apply H; assumption. + assumption. + destruct H0. + rewrite Heqn; assumption. + destruct (H n0) as [(n,(Hltn,(Hmin,Huniqn)))|]; [exists n | exists n0]; + repeat split; + assumption || intros n' (HPn',Hminn'); apply le_antisym; auto. +Qed. + +Unset Implicit Arguments. + +(** [n]th iteration of the function [f] *) + +Fixpoint iter_nat (n:nat) (A:Type) (f:A -> A) (x:A) {struct n} : A := + match n with + | O => x + | S n' => f (iter_nat n' A f x) + end. + +Theorem iter_nat_plus : + forall (n m:nat) (A:Type) (f:A -> A) (x:A), + iter_nat (n + m) A f x = iter_nat n A f (iter_nat m A f x). +Proof. + simple induction n; + [ simpl in |- *; auto with arith + | intros; simpl in |- *; apply f_equal with (f := f); apply H ]. +Qed. diff --git a/theories/Bool/Bool.v b/theories/Bool/Bool.v index e126ad35..47b9fc83 100644 --- a/theories/Bool/Bool.v +++ b/theories/Bool/Bool.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Bool.v 9246 2006-10-17 14:01:18Z herbelin $ i*) +(*i $Id: Bool.v 10812 2008-04-17 16:42:37Z letouzey $ i*) (** The type [bool] is defined in the prelude as [Inductive bool : Set := true : bool | false : bool] *) @@ -126,9 +126,8 @@ Proof. destruct a; destruct b; simpl in |- *; intro; discriminate H || reflexivity. Qed. - (************************) -(** * Logical combinators *) +(** * A synonym of [if] on [bool] *) (************************) Definition ifb (b1 b2 b3:bool) : bool := @@ -137,31 +136,8 @@ Definition ifb (b1 b2 b3:bool) : bool := | false => b3 end. -Definition andb (b1 b2:bool) : bool := ifb b1 b2 false. - -Definition orb (b1 b2:bool) : bool := ifb b1 true b2. - -Definition implb (b1 b2:bool) : bool := ifb b1 b2 true. - -Definition xorb (b1 b2:bool) : bool := - match b1, b2 with - | true, true => false - | true, false => true - | false, true => true - | false, false => false - end. - -Definition negb (b:bool) := if b then false else true. - -Infix "||" := orb (at level 50, left associativity) : bool_scope. -Infix "&&" := andb (at level 40, left associativity) : bool_scope. - Open Scope bool_scope. -Delimit Scope bool_scope with bool. - -Bind Scope bool_scope with bool. - (****************************) (** * De Morgan laws *) (****************************) @@ -220,7 +196,7 @@ Qed. Lemma if_negb : - forall (A:Set) (b:bool) (x y:A), + forall (A:Type) (b:bool) (x y:A), (if negb b then x else y) = (if b then y else x). Proof. destruct b; trivial. @@ -332,12 +308,11 @@ Hint Resolve orb_comm orb_assoc: bool v62. (** * Properties of [andb] *) (*******************************) -Lemma andb_prop : forall a b:bool, a && b = true -> a = true /\ b = true. +Lemma andb_true_iff : + forall b1 b2:bool, b1 && b2 = true <-> b1 = true /\ b2 = true. Proof. - destruct a; destruct b; simpl in |- *; try (intro H; discriminate H); - auto with bool. + destruct b1; destruct b2; intuition. Qed. -Hint Resolve andb_prop: bool v62. Lemma andb_true_eq : forall a b:bool, true = a && b -> true = a /\ true = b. @@ -345,13 +320,6 @@ Proof. destruct a; destruct b; auto. Defined. -Lemma andb_true_intro : - forall b1 b2:bool, b1 = true /\ b2 = true -> b1 && b2 = true. -Proof. - destruct b1; destruct b2; simpl in |- *; tauto || auto with bool. -Qed. -Hint Resolve andb_true_intro: bool v62. - Lemma andb_false_intro1 : forall b1 b2:bool, b1 = false -> b1 && b2 = false. Proof. destruct b1; destruct b2; simpl in |- *; tauto || auto with bool. @@ -715,3 +683,43 @@ Lemma negb_prop_involutive : forall b, Is_true b -> ~ Is_true (negb b). Proof. destruct b; intuition. Qed. + +(** Rewrite rules about andb, orb and if (used in romega) *) + +Lemma andb_if : forall (A:Type)(a a':A)(b b' : bool), + (if b && b' then a else a') = + (if b then if b' then a else a' else a'). +Proof. + destruct b; destruct b'; auto. +Qed. + +Lemma negb_if : forall (A:Type)(a a':A)(b:bool), + (if negb b then a else a') = + (if b then a' else a). +Proof. + destruct b; auto. +Qed. + +(*****************************************) +(** * Alternative versions of [andb] and [orb] + with lazy behavior (for vm_compute) *) +(*****************************************) + +Notation "a &&& b" := (if a then b else false) + (at level 40, left associativity) : lazy_bool_scope. +Notation "a ||| b" := (if a then true else b) + (at level 50, left associativity) : lazy_bool_scope. + +Open Local Scope lazy_bool_scope. + +Lemma andb_lazy_alt : forall a b : bool, a && b = a &&& b. +Proof. + unfold andb; auto. +Qed. + +Lemma orb_lazy_alt : forall a b : bool, a || b = a ||| b. +Proof. + unfold orb; auto. +Qed. + + diff --git a/theories/Bool/Bvector.v b/theories/Bool/Bvector.v index 659630c5..0e8ea33c 100644 --- a/theories/Bool/Bvector.v +++ b/theories/Bool/Bvector.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Bvector.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Bvector.v 11004 2008-05-28 09:09:12Z herbelin $ i*) (** Bit vectors. Contribution by Jean Duprat (ENS Lyon). *) @@ -25,10 +25,10 @@ Malheureusement, cette verification a posteriori amene a faire de nombreux lemmes pour gerer les longueurs. La seconde idée est de faire un type dépendant dans lequel la longueur est un paramètre de construction. Cela complique un -peu les inductions structurelles, la solution qui a ma préférence -est alors d'utiliser un terme de preuve comme définition, car le -mécanisme d'inférence du type du filtrage n'est pas aussi puissant que -celui implanté par les tactiques d'élimination. +peu les inductions structurelles et dans certains cas on +utilisera un terme de preuve comme définition, car le +mécanisme d'inférence du type du filtrage n'est pas toujours +aussi puissant que celui implanté par les tactiques d'élimination. *) Section VECTORS. @@ -52,39 +52,39 @@ Inductive vector : nat -> Type := | Vnil : vector 0 | Vcons : forall (a:A) (n:nat), vector n -> vector (S n). -Definition Vhead : forall n:nat, vector (S n) -> A. -Proof. - intros n v; inversion v; exact a. -Defined. +Definition Vhead (n:nat) (v:vector (S n)) := + match v with + | Vcons a _ _ => a + end. -Definition Vtail : forall n:nat, vector (S n) -> vector n. -Proof. - intros n v; inversion v as [|_ n0 H0 H1]; exact H0. -Defined. +Definition Vtail (n:nat) (v:vector (S n)) := + match v with + | Vcons _ _ v => v + end. Definition Vlast : forall n:nat, vector (S n) -> A. Proof. induction n as [| n f]; intro v. inversion v. exact a. - + inversion v as [| n0 a H0 H1]. exact (f H0). Defined. -Definition Vconst : forall (a:A) (n:nat), vector n. -Proof. - induction n as [| n v]. - exact Vnil. +Fixpoint Vconst (a:A) (n:nat) := + match n return vector n with + | O => Vnil + | S n => Vcons a _ (Vconst a n) + end. - exact (Vcons a n v). -Defined. +(** Shifting and truncating *) Lemma Vshiftout : forall n:nat, vector (S n) -> vector n. Proof. induction n as [| n f]; intro v. exact Vnil. - + inversion v as [| a n0 H0 H1]. exact (Vcons a n (f H0)). Defined. @@ -123,25 +123,23 @@ Proof. auto with *. Defined. -Lemma Vextend : forall n p:nat, vector n -> vector p -> vector (n + p). -Proof. - induction n as [| n f]; intros p v v0. - simpl in |- *; exact v0. - - inversion v as [| a n0 H0 H1]. - simpl in |- *; exact (Vcons a (n + p) (f p H0 v0)). -Defined. +(** Concatenation of two vectors *) + +Fixpoint Vextend n p (v:vector n) (w:vector p) : vector (n+p) := + match v with + | Vnil => w + | Vcons a n' v' => Vcons a (n'+p) (Vextend n' p v' w) + end. + +(** Uniform application on the arguments of the vector *) Variable f : A -> A. -Lemma Vunary : forall n:nat, vector n -> vector n. -Proof. - induction n as [| n g]; intro v. - exact Vnil. - - inversion v as [| a n0 H0 H1]. - exact (Vcons (f a) n (g H0)). -Defined. +Fixpoint Vunary n (v:vector n) : vector n := + match v with + | Vnil => Vnil + | Vcons a n' v' => Vcons (f a) n' (Vunary n' v') + end. Variable g : A -> A -> A. @@ -154,14 +152,15 @@ Proof. exact (Vcons (g a a0) n (h H0 H2)). Defined. -Definition Vid : forall n:nat, vector n -> vector n. -Proof. - destruct n; intro X. - exact Vnil. - exact (Vcons (Vhead _ X) _ (Vtail _ X)). -Defined. +(** Eta-expansion of a vector *) + +Definition Vid n : vector n -> vector n := + match n with + | O => fun _ => Vnil + | _ => fun v => Vcons (Vhead _ v) _ (Vtail _ v) + end. -Lemma Vid_eq : forall (n:nat) (v:vector n), v=(Vid n v). +Lemma Vid_eq : forall (n:nat) (v:vector n), v = Vid n v. Proof. destruct v; auto. Qed. diff --git a/theories/Classes/EquivDec.v b/theories/Classes/EquivDec.v new file mode 100644 index 00000000..debe953a --- /dev/null +++ b/theories/Classes/EquivDec.v @@ -0,0 +1,158 @@ +(* -*- coq-prog-args: ("-emacs-U" "-nois") -*- *) +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Decidable equivalences. + * + * Author: Matthieu Sozeau + * Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + * 91405 Orsay, France *) + +(* $Id: EquivDec.v 10919 2008-05-11 22:04:26Z msozeau $ *) + +Set Implicit Arguments. +Unset Strict Implicit. + +(** Export notations. *) + +Require Export Coq.Classes.Equivalence. + +(** The [DecidableSetoid] class asserts decidability of a [Setoid]. It can be useful in proofs to reason more + classically. *) + +Require Import Coq.Logic.Decidable. + +Open Scope equiv_scope. + +Class [ equiv : Equivalence A ] => DecidableEquivalence := + setoid_decidable : forall x y : A, decidable (x === y). + +(** The [EqDec] class gives a decision procedure for a particular setoid equality. *) + +Class [ equiv : Equivalence A ] => EqDec := + equiv_dec : forall x y : A, { x === y } + { x =/= y }. + +(** We define the [==] overloaded notation for deciding equality. It does not take precedence + of [==] defined in the type scope, hence we can have both at the same time. *) + +Notation " x == y " := (equiv_dec (x :>) (y :>)) (no associativity, at level 70). + +Definition swap_sumbool {A B} (x : { A } + { B }) : { B } + { A } := + match x with + | left H => @right _ _ H + | right H => @left _ _ H + end. + +Require Import Coq.Program.Program. + +Open Local Scope program_scope. + +(** Invert the branches. *) + +Program Definition nequiv_dec [ EqDec A ] (x y : A) : { x =/= y } + { x === y } := swap_sumbool (x == y). + +(** Overloaded notation for inequality. *) + +Infix "=/=" := nequiv_dec (no associativity, at level 70). + +(** Define boolean versions, losing the logical information. *) + +Definition equiv_decb [ EqDec A ] (x y : A) : bool := + if x == y then true else false. + +Definition nequiv_decb [ EqDec A ] (x y : A) : bool := + negb (equiv_decb x y). + +Infix "==b" := equiv_decb (no associativity, at level 70). +Infix "<>b" := nequiv_decb (no associativity, at level 70). + +(** Decidable leibniz equality instances. *) + +Require Import Coq.Arith.Peano_dec. + +(** The equiv is burried inside the setoid, but we can recover it by specifying which setoid we're talking about. *) + +Program Instance nat_eq_eqdec : ! EqDec nat eq := + equiv_dec := eq_nat_dec. + +Require Import Coq.Bool.Bool. + +Program Instance bool_eqdec : ! EqDec bool eq := + equiv_dec := bool_dec. + +Program Instance unit_eqdec : ! EqDec unit eq := + equiv_dec x y := in_left. + + Next Obligation. + Proof. + destruct x ; destruct y. + reflexivity. + Qed. + +Program Instance prod_eqdec [ EqDec A eq, EqDec B eq ] : + ! EqDec (prod A B) eq := + equiv_dec x y := + let '(x1, x2) := x in + let '(y1, y2) := y in + if x1 == y1 then + if x2 == y2 then in_left + else in_right + else in_right. + + Solve Obligations using unfold complement, equiv ; program_simpl. + +Program Instance sum_eqdec [ EqDec A eq, EqDec B eq ] : + ! EqDec (sum A B) eq := + equiv_dec x y := + match x, y with + | inl a, inl b => if a == b then in_left else in_right + | inr a, inr b => if a == b then in_left else in_right + | inl _, inr _ | inr _, inl _ => in_right + end. + + Solve Obligations using unfold complement, equiv ; program_simpl. + +(** Objects of function spaces with countable domains like bool have decidable equality. *) + +Require Import Coq.Program.FunctionalExtensionality. + +Program Instance bool_function_eqdec [ EqDec A eq ] : ! EqDec (bool -> A) eq := + equiv_dec f g := + if f true == g true then + if f false == g false then in_left + else in_right + else in_right. + + Solve Obligations using try red ; unfold equiv, complement ; program_simpl. + + Next Obligation. + Proof. + extensionality x. + destruct x ; auto. + Qed. + +Require Import List. + +Program Instance list_eqdec [ eqa : EqDec A eq ] : ! EqDec (list A) eq := + equiv_dec := + fix aux (x : list A) y { struct x } := + match x, y with + | nil, nil => in_left + | cons hd tl, cons hd' tl' => + if hd == hd' then + if aux tl tl' then in_left else in_right + else in_right + | _, _ => in_right + end. + + Solve Obligations using unfold equiv, complement in * ; program_simpl ; intuition (discriminate || eauto). + + Next Obligation. + Proof. clear aux. red in H0. subst. + destruct y; intuition (discriminate || eauto). + Defined.
\ No newline at end of file diff --git a/theories/Classes/Equivalence.v b/theories/Classes/Equivalence.v new file mode 100644 index 00000000..70bf3483 --- /dev/null +++ b/theories/Classes/Equivalence.v @@ -0,0 +1,144 @@ +(* -*- coq-prog-args: ("-emacs-U" "-nois") -*- *) +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Typeclass-based setoids. Definitions on [Equivalence]. + + Author: Matthieu Sozeau + Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + 91405 Orsay, France *) + +(* $Id: Equivalence.v 10919 2008-05-11 22:04:26Z msozeau $ *) + +Require Export Coq.Program.Basics. +Require Import Coq.Program.Tactics. + +Require Import Coq.Classes.Init. +Require Import Relation_Definitions. +Require Import Coq.Classes.RelationClasses. +Require Export Coq.Classes.Morphisms. + +Set Implicit Arguments. +Unset Strict Implicit. + +Open Local Scope signature_scope. + +Definition equiv [ Equivalence A R ] : relation A := R. + +Typeclasses unfold equiv. + +(** Overloaded notations for setoid equivalence and inequivalence. Not to be confused with [eq] and [=]. *) + +Notation " x === y " := (equiv x y) (at level 70, no associativity) : equiv_scope. + +Notation " x =/= y " := (complement equiv x y) (at level 70, no associativity) : equiv_scope. + +Open Local Scope equiv_scope. + +(** Overloading for [PER]. *) + +Definition pequiv [ PER A R ] : relation A := R. + +Typeclasses unfold pequiv. + +(** Overloaded notation for partial equivalence. *) + +Infix "=~=" := pequiv (at level 70, no associativity) : equiv_scope. + +(** Shortcuts to make proof search easier. *) + +Program Instance equiv_reflexive [ sa : Equivalence A ] : Reflexive equiv. + +Program Instance equiv_symmetric [ sa : Equivalence A ] : Symmetric equiv. + + Next Obligation. + Proof. + symmetry ; auto. + Qed. + +Program Instance equiv_transitive [ sa : Equivalence A ] : Transitive equiv. + + Next Obligation. + Proof. + transitivity y ; auto. + Qed. + +(** Use the [substitute] command which substitutes an equivalence in every hypothesis. *) + +Ltac setoid_subst H := + match type of H with + ?x === ?y => substitute H ; clear H x + end. + +Ltac setoid_subst_nofail := + match goal with + | [ H : ?x === ?y |- _ ] => setoid_subst H ; setoid_subst_nofail + | _ => idtac + end. + +(** [subst*] will try its best at substituting every equality in the goal. *) + +Tactic Notation "subst" "*" := subst_no_fail ; setoid_subst_nofail. + +(** Simplify the goal w.r.t. equivalence. *) + +Ltac equiv_simplify_one := + match goal with + | [ H : ?x === ?x |- _ ] => clear H + | [ H : ?x === ?y |- _ ] => setoid_subst H + | [ |- ?x =/= ?y ] => let name:=fresh "Hneq" in intro name + | [ |- ~ ?x === ?y ] => let name:=fresh "Hneq" in intro name + end. + +Ltac equiv_simplify := repeat equiv_simplify_one. + +(** "reify" relations which are equivalences to applications of the overloaded [equiv] method + for easy recognition in tactics. *) + +Ltac equivify_tac := + match goal with + | [ s : Equivalence ?A ?R, H : ?R ?x ?y |- _ ] => change R with (@equiv A R s) in H + | [ s : Equivalence ?A ?R |- context C [ ?R ?x ?y ] ] => change (R x y) with (@equiv A R s x y) + end. + +Ltac equivify := repeat equivify_tac. + +Section Respecting. + + (** Here we build an equivalence instance for functions which relates respectful ones only, + we do not export it. *) + + Definition respecting [ Equivalence A (R : relation A), Equivalence B (R' : relation B) ] : Type := + { morph : A -> B | respectful R R' morph morph }. + + Program Instance respecting_equiv [ Equivalence A R, Equivalence B R' ] : + Equivalence respecting + (fun (f g : respecting) => forall (x y : A), R x y -> R' (proj1_sig f x) (proj1_sig g y)). + + Solve Obligations using unfold respecting in * ; simpl_relation ; program_simpl. + + Next Obligation. + Proof. + unfold respecting in *. program_simpl. red in H2,H3,H4. + transitivity (y x0) ; auto. + transitivity (y y0) ; auto. + symmetry. auto. + Qed. + +End Respecting. + +(** The default equivalence on function spaces, with higher-priority than [eq]. *) + +Program Instance pointwise_equivalence [ Equivalence A eqA ] : + Equivalence (B -> A) (pointwise_relation eqA) | 9. + + Next Obligation. + Proof. + transitivity (y x0) ; auto. + Qed. + diff --git a/theories/Classes/Functions.v b/theories/Classes/Functions.v new file mode 100644 index 00000000..49fc4f89 --- /dev/null +++ b/theories/Classes/Functions.v @@ -0,0 +1,42 @@ +(* -*- coq-prog-args: ("-emacs-U" "-nois") -*- *) +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Functional morphisms. + + Author: Matthieu Sozeau + Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + 91405 Orsay, France *) + +(* $Id: Functions.v 10739 2008-04-01 14:45:20Z herbelin $ *) + +Require Import Coq.Classes.RelationClasses. +Require Import Coq.Classes.Morphisms. + +Set Implicit Arguments. +Unset Strict Implicit. + +Class [ m : Morphism (A -> B) (RA ++> RB) f ] => Injective : Prop := + injective : forall x y : A, RB (f x) (f y) -> RA x y. + +Class [ m : Morphism (A -> B) (RA ++> RB) f ] => Surjective : Prop := + surjective : forall y, exists x : A, RB y (f x). + +Definition Bijective [ m : Morphism (A -> B) (RA ++> RB) (f : A -> B) ] := + Injective m /\ Surjective m. + +Class [ m : Morphism (A -> B) (eqA ++> eqB) ] => MonoMorphism := + monic :> Injective m. + +Class [ m : Morphism (A -> B) (eqA ++> eqB) ] => EpiMorphism := + epic :> Surjective m. + +Class [ m : Morphism (A -> B) (eqA ++> eqB) ] => IsoMorphism := + monomorphism :> MonoMorphism m ; epimorphism :> EpiMorphism m. + +Class [ m : Morphism (A -> A) (eqA ++> eqA), ! IsoMorphism m ] => AutoMorphism. diff --git a/theories/Classes/Init.v b/theories/Classes/Init.v new file mode 100644 index 00000000..6ba0c61e --- /dev/null +++ b/theories/Classes/Init.v @@ -0,0 +1,21 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Initialization code for typeclasses, setting up the default tactic + for instance search. + + Author: Matthieu Sozeau + Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + 91405 Orsay, France *) + +(* $Id: Init.v 10739 2008-04-01 14:45:20Z herbelin $ *) + +(* Ltac typeclass_instantiation := typeclasses eauto || eauto. *) + +Tactic Notation "clapply" ident(c) := + eapply @c ; eauto with typeclass_instances. diff --git a/theories/Classes/Morphisms.v b/theories/Classes/Morphisms.v new file mode 100644 index 00000000..f21c68a6 --- /dev/null +++ b/theories/Classes/Morphisms.v @@ -0,0 +1,467 @@ +(* -*- coq-prog-args: ("-emacs-U" "-top" "Coq.Classes.Morphisms"); compile-command: "make -C ../.. TIME='time'" -*- *) +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Typeclass-based morphism definition and standard, minimal instances. + + Author: Matthieu Sozeau + Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + 91405 Orsay, France *) + +(* $Id: Morphisms.v 11092 2008-06-10 18:28:26Z msozeau $ *) + +Require Import Coq.Program.Basics. +Require Import Coq.Program.Tactics. +Require Import Coq.Relations.Relation_Definitions. +Require Export Coq.Classes.RelationClasses. + +Set Implicit Arguments. +Unset Strict Implicit. + +(** * Morphisms. + + We now turn to the definition of [Morphism] and declare standard instances. + These will be used by the [setoid_rewrite] tactic later. *) + +(** A morphism on a relation [R] is an object respecting the relation (in its kernel). + The relation [R] will be instantiated by [respectful] and [A] by an arrow type + for usual morphisms. *) + +Class Morphism A (R : relation A) (m : A) : Prop := + respect : R m m. + +(** We make the type implicit, it can be infered from the relations. *) + +Implicit Arguments Morphism [A]. + +(** We allow to unfold the [relation] definition while doing morphism search. *) + +Typeclasses unfold relation. + +(** Respectful morphisms. *) + +(** The fully dependent version, not used yet. *) + +Definition respectful_hetero + (A B : Type) + (C : A -> Type) (D : B -> Type) + (R : A -> B -> Prop) + (R' : forall (x : A) (y : B), C x -> D y -> Prop) : + (forall x : A, C x) -> (forall x : B, D x) -> Prop := + fun f g => forall x y, R x y -> R' x y (f x) (g y). + +(** The non-dependent version is an instance where we forget dependencies. *) + +Definition respectful (A B : Type) + (R : relation A) (R' : relation B) : relation (A -> B) := + Eval compute in @respectful_hetero A A (fun _ => B) (fun _ => B) R (fun _ _ => R'). + +(** Notations reminiscent of the old syntax for declaring morphisms. *) + +Delimit Scope signature_scope with signature. +Arguments Scope Morphism [type_scope signature_scope]. + +Notation " R ++> R' " := (@respectful _ _ (R%signature) (R'%signature)) + (right associativity, at level 55) : signature_scope. + +Notation " R ==> R' " := (@respectful _ _ (R%signature) (R'%signature)) + (right associativity, at level 55) : signature_scope. + +Notation " R --> R' " := (@respectful _ _ (inverse (R%signature)) (R'%signature)) + (right associativity, at level 55) : signature_scope. + +Arguments Scope respectful [type_scope type_scope signature_scope signature_scope]. + +Open Local Scope signature_scope. + +(** We can build a PER on the Coq function space if we have PERs on the domain and + codomain. *) + +Program Instance respectful_per [ PER A (R : relation A), PER B (R' : relation B) ] : + PER (A -> B) (R ==> R'). + + Next Obligation. + Proof with auto. + assert(R x0 x0). + transitivity y0... symmetry... + transitivity (y x0)... + Qed. + +(** Subrelations induce a morphism on the identity, not used for morphism search yet. *) + +Lemma subrelation_id_morphism [ subrelation A Râ‚ Râ‚‚ ] : Morphism (Râ‚ ==> Râ‚‚) id. +Proof. firstorder. Qed. + +(** The subrelation property goes through products as usual. *) + +Instance morphisms_subrelation [ sub : subrelation A Râ‚ Râ‚‚ ] : + ! subrelation (B -> A) (R ==> Râ‚) (R ==> Râ‚‚). +Proof. firstorder. Qed. + +Instance morphisms_subrelation_left [ sub : subrelation A Râ‚‚ Râ‚ ] : + ! subrelation (A -> B) (Râ‚ ==> R) (Râ‚‚ ==> R) | 3. +Proof. firstorder. Qed. + +(** [Morphism] is itself a covariant morphism for [subrelation]. *) + +Lemma subrelation_morphism [ sub : subrelation A Râ‚ Râ‚‚, mor : Morphism A Râ‚ m ] : Morphism Râ‚‚ m. +Proof. + intros. apply sub. apply mor. +Qed. + +Instance morphism_subrelation_morphism : + Morphism (subrelation ++> @eq _ ==> impl) (@Morphism A). +Proof. reduce. subst. firstorder. Qed. + +(** We use an external tactic to manage the application of subrelation, which is otherwise + always applicable. We allow its use only once per branch. *) + +Inductive subrelation_done : Prop := + did_subrelation : subrelation_done. + +Ltac subrelation_tac := + match goal with + | [ _ : subrelation_done |- _ ] => fail 1 + | [ |- @Morphism _ _ _ ] => let H := fresh "H" in + set(H:=did_subrelation) ; eapply @subrelation_morphism + end. + +Hint Extern 4 (@Morphism _ _ _) => subrelation_tac : typeclass_instances. + +(** Essential subrelation instances for [iff], [impl] and [pointwise_relation]. *) + +Instance iff_impl_subrelation : subrelation iff impl. +Proof. firstorder. Qed. + +Instance iff_inverse_impl_subrelation : subrelation iff (inverse impl). +Proof. firstorder. Qed. + +Instance pointwise_subrelation [ sub : subrelation A R R' ] : + subrelation (pointwise_relation (A:=B) R) (pointwise_relation R') | 4. +Proof. reduce. unfold pointwise_relation in *. apply sub. apply H. Qed. + +(** The complement of a relation conserves its morphisms. *) + +Program Instance complement_morphism + [ mR : Morphism (A -> A -> Prop) (RA ==> RA ==> iff) R ] : + Morphism (RA ==> RA ==> iff) (complement R). + + Next Obligation. + Proof. + unfold complement. + pose (mR x y H x0 y0 H0). + intuition. + Qed. + +(** The [inverse] too, actually the [flip] instance is a bit more general. *) + +Program Instance flip_morphism + [ mor : Morphism (A -> B -> C) (RA ==> RB ==> RC) f ] : + Morphism (RB ==> RA ==> RC) (flip f). + + Next Obligation. + Proof. + apply mor ; auto. + Qed. + +(** Every Transitive relation gives rise to a binary morphism on [impl], + contravariant in the first argument, covariant in the second. *) + +Program Instance trans_contra_co_morphism + [ Transitive A R ] : Morphism (R --> R ++> impl) R. + + Next Obligation. + Proof with auto. + transitivity x... + transitivity x0... + Qed. + +(* (** Dually... *) *) + +(* Program Instance [ Transitive A R ] => *) +(* trans_co_contra_inv_impl_morphism : Morphism (R ++> R --> inverse impl) R. *) + +(* Next Obligation. *) +(* Proof with auto. *) +(* apply* trans_contra_co_morphism ; eauto. eauto. *) +(* Qed. *) + +(** Morphism declarations for partial applications. *) + +Program Instance trans_contra_inv_impl_morphism + [ Transitive A R ] : Morphism (R --> inverse impl) (R x). + + Next Obligation. + Proof with auto. + transitivity y... + Qed. + +Program Instance trans_co_impl_morphism + [ Transitive A R ] : Morphism (R ==> impl) (R x). + + Next Obligation. + Proof with auto. + transitivity x0... + Qed. + +Program Instance trans_sym_co_inv_impl_morphism + [ Transitive A R, Symmetric A R ] : Morphism (R ==> inverse impl) (R x). + + Next Obligation. + Proof with auto. + transitivity y... + Qed. + +Program Instance trans_sym_contra_impl_morphism + [ Transitive A R, Symmetric _ R ] : Morphism (R --> impl) (R x). + + Next Obligation. + Proof with auto. + transitivity x0... + Qed. + +Program Instance equivalence_partial_app_morphism + [ Equivalence A R ] : Morphism (R ==> iff) (R x). + + Next Obligation. + Proof with auto. + split. intros ; transitivity x0... + intros. + transitivity y... + symmetry... + Qed. + +(** Every Transitive relation induces a morphism by "pushing" an [R x y] on the left of an [R x z] proof + to get an [R y z] goal. *) + +Program Instance trans_co_eq_inv_impl_morphism + [ Transitive A R ] : Morphism (R ==> (@eq A) ==> inverse impl) R. + + Next Obligation. + Proof with auto. + transitivity y... + Qed. + +(* Program Instance [ Transitive A R ] => *) +(* trans_contra_eq_impl_morphism : Morphism (R --> (@eq A) ==> impl) R. *) + +(* Next Obligation. *) +(* Proof with auto. *) +(* transitivity x... *) +(* Qed. *) + +(** Every Symmetric and Transitive relation gives rise to an equivariant morphism. *) + +Program Instance trans_sym_morphism + [ Transitive A R, Symmetric _ R ] : Morphism (R ==> R ==> iff) R. + + Next Obligation. + Proof with auto. + split ; intros. + transitivity x0... transitivity x... + + transitivity y... transitivity y0... + Qed. + +Program Instance equiv_morphism [ Equivalence A R ] : + Morphism (R ==> R ==> iff) R. + + Next Obligation. + Proof with auto. + split ; intros. + transitivity x0... transitivity x... symmetry... + + transitivity y... transitivity y0... symmetry... + Qed. + +(** In case the rewrite happens at top level. *) + +Program Instance iff_inverse_impl_id : + Morphism (iff ==> inverse impl) id. + +Program Instance inverse_iff_inverse_impl_id : + Morphism (iff --> inverse impl) id. + +Program Instance iff_impl_id : + Morphism (iff ==> impl) id. + +Program Instance inverse_iff_impl_id : + Morphism (iff --> impl) id. + +(** Coq functions are morphisms for leibniz equality, + applied only if really needed. *) + +(* Instance (A : Type) [ Reflexive B R ] => *) +(* eq_reflexive_morphism : Morphism (@Logic.eq A ==> R) m | 3. *) +(* Proof. simpl_relation. Qed. *) + +Instance reflexive_eq_dom_reflexive (A : Type) [ Reflexive B R' ] : + Reflexive (@Logic.eq A ==> R'). +Proof. simpl_relation. Qed. + +(** [respectful] is a morphism for relation equivalence. *) + +Instance respectful_morphism : + Morphism (relation_equivalence ++> relation_equivalence ++> relation_equivalence) (@respectful A B). +Proof. + reduce. + unfold respectful, relation_equivalence, predicate_equivalence in * ; simpl in *. + split ; intros. + + rewrite <- H0. + apply H1. + rewrite H. + assumption. + + rewrite H0. + apply H1. + rewrite <- H. + assumption. +Qed. + +(** Every element in the carrier of a reflexive relation is a morphism for this relation. + We use a proxy class for this case which is used internally to discharge reflexivity constraints. + The [Reflexive] instance will almost always be used, but it won't apply in general to any kind of + [Morphism (A -> B) _ _] goal, making proof-search much slower. A cleaner solution would be to be able + to set different priorities in different hint bases and select a particular hint database for + resolution of a type class constraint.*) + +Class MorphismProxy A (R : relation A) (m : A) : Prop := + respect_proxy : R m m. + +Instance reflexive_morphism_proxy + [ Reflexive A R ] (x : A) : MorphismProxy A R x | 1. +Proof. firstorder. Qed. + +Instance morphism_morphism_proxy + [ Morphism A R x ] : MorphismProxy A R x | 2. +Proof. firstorder. Qed. + +(* Instance (A : Type) [ Reflexive B R ] => *) +(* eq_reflexive_morphism : Morphism (@Logic.eq A ==> R) m | 3. *) +(* Proof. simpl_relation. Qed. *) + +(** [R] is Reflexive, hence we can build the needed proof. *) + +Lemma Reflexive_partial_app_morphism [ Morphism (A -> B) (R ==> R') m, MorphismProxy A R x ] : + Morphism R' (m x). +Proof. simpl_relation. Qed. + +Ltac partial_application_tactic := + let tac x := + match type of x with + | Type => fail 1 + | _ => eapply @Reflexive_partial_app_morphism + end + in + let on_morphism m := + match m with + | ?m' ?x => tac x + | ?m' _ ?x => tac x + | ?m' _ _ ?x => tac x + | ?m' _ _ _ ?x => tac x + | ?m' _ _ _ _ ?x => tac x + | ?m' _ _ _ _ _ ?x => tac x + | ?m' _ _ _ _ _ _ ?x => tac x + | ?m' _ _ _ _ _ _ _ ?x => tac x + | ?m' _ _ _ _ _ _ _ _ ?x => tac x + end + in + match goal with + | [ |- @Morphism _ _ ?m ] => on_morphism m + end. + +(* Program Instance [ Morphism (A -> B) (R ==> R') m, Reflexive A R ] (x : A) => *) +(* reflexive_partial_app_morphism : Morphism R' (m x). *) + +Hint Extern 4 (@Morphism _ _ _) => partial_application_tactic : typeclass_instances. + +Lemma inverse_respectful : forall (A : Type) (R : relation A) (B : Type) (R' : relation B), + relation_equivalence (inverse (R ==> R')) (inverse R ==> inverse R'). +Proof. + intros. + unfold flip, respectful. + split ; intros ; intuition. +Qed. + +(** Special-purpose class to do normalization of signatures w.r.t. inverse. *) + +Class (A : Type) => Normalizes (m : relation A) (m' : relation A) : Prop := + normalizes : relation_equivalence m m'. + +Instance inverse_respectful_norm : + Normalizes (A -> B) (inverse R ==> inverse R') (inverse (R ==> R')) . +Proof. firstorder. Qed. + +(* If not an inverse on the left, do a double inverse. *) + +Instance not_inverse_respectful_norm : + Normalizes (A -> B) (R ==> inverse R') (inverse (inverse R ==> R')) | 4. +Proof. firstorder. Qed. + +Instance inverse_respectful_rec_norm [ Normalizes B R' (inverse R'') ] : + Normalizes (A -> B) (inverse R ==> R') (inverse (R ==> R'')). +Proof. red ; intros. + pose normalizes as r. + setoid_rewrite r. + setoid_rewrite inverse_respectful. + reflexivity. +Qed. + +(** Once we have normalized, we will apply this instance to simplify the problem. *) + +Program Instance morphism_inverse_morphism + [ Morphism A R m ] : Morphism (inverse R) m | 2. + +(** Bootstrap !!! *) + +Instance morphism_morphism : Morphism (relation_equivalence ==> @eq _ ==> iff) (@Morphism A). +Proof. + simpl_relation. + reduce in H. + split ; red ; intros. + setoid_rewrite <- H. + apply H0. + setoid_rewrite H. + apply H0. +Qed. + +Lemma morphism_releq_morphism [ Normalizes A R R', Morphism _ R' m ] : Morphism R m. +Proof. + intros. + pose respect as r. + pose normalizes as norm. + setoid_rewrite norm. + assumption. +Qed. + +Inductive normalization_done : Prop := did_normalization. + +Ltac morphism_normalization := + match goal with + | [ _ : normalization_done |- _ ] => fail 1 + | [ |- @Morphism _ _ _ ] => let H := fresh "H" in + set(H:=did_normalization) ; eapply @morphism_releq_morphism + end. + +Hint Extern 6 (@Morphism _ _ _) => morphism_normalization : typeclass_instances. + +(** Every reflexive relation gives rise to a morphism, only for immediately solving goals without variables. *) + +Lemma reflexive_morphism [ Reflexive A R ] (x : A) + : Morphism R x. +Proof. firstorder. Qed. + +Ltac morphism_reflexive := + match goal with + | [ _ : normalization_done |- _ ] => fail 1 + | [ _ : subrelation_done |- _ ] => fail 1 + | [ |- @Morphism _ _ _ ] => eapply @reflexive_morphism + end. + +Hint Extern 4 (@Morphism _ _ _) => morphism_reflexive : typeclass_instances.
\ No newline at end of file diff --git a/theories/Classes/Morphisms_Prop.v b/theories/Classes/Morphisms_Prop.v new file mode 100644 index 00000000..7dc1f95e --- /dev/null +++ b/theories/Classes/Morphisms_Prop.v @@ -0,0 +1,132 @@ +(* -*- coq-prog-args: ("-emacs-U" "-top" "Coq.Classes.Morphisms") -*- *) +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Morphism instances for propositional connectives. + + Author: Matthieu Sozeau + Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + 91405 Orsay, France *) + +Require Import Coq.Classes.Morphisms. +Require Import Coq.Program.Basics. +Require Import Coq.Program.Tactics. + +(** Standard instances for [not], [iff] and [impl]. *) + +(** Logical negation. *) + +Program Instance not_impl_morphism : + Morphism (impl --> impl) not. + +Program Instance not_iff_morphism : + Morphism (iff ++> iff) not. + +(** Logical conjunction. *) + +Program Instance and_impl_iff_morphism : + Morphism (impl ==> impl ==> impl) and. + +(* Program Instance and_impl_iff_morphism : *) +(* Morphism (impl ==> iff ==> impl) and. *) + +(* Program Instance and_iff_impl_morphism : *) +(* Morphism (iff ==> impl ==> impl) and. *) + +(* Program Instance and_inverse_impl_iff_morphism : *) +(* Morphism (inverse impl ==> iff ==> inverse impl) and. *) + +(* Program Instance and_iff_inverse_impl_morphism : *) +(* Morphism (iff ==> inverse impl ==> inverse impl) and. *) + +Program Instance and_iff_morphism : + Morphism (iff ==> iff ==> iff) and. + +(** Logical disjunction. *) + +Program Instance or_impl_iff_morphism : + Morphism (impl ==> impl ==> impl) or. + +(* Program Instance or_impl_iff_morphism : *) +(* Morphism (impl ==> iff ==> impl) or. *) + +(* Program Instance or_iff_impl_morphism : *) +(* Morphism (iff ==> impl ==> impl) or. *) + +(* Program Instance or_inverse_impl_iff_morphism : *) +(* Morphism (inverse impl ==> iff ==> inverse impl) or. *) + +(* Program Instance or_iff_inverse_impl_morphism : *) +(* Morphism (iff ==> inverse impl ==> inverse impl) or. *) + +Program Instance or_iff_morphism : + Morphism (iff ==> iff ==> iff) or. + +(** Logical implication [impl] is a morphism for logical equivalence. *) + +Program Instance iff_iff_iff_impl_morphism : Morphism (iff ==> iff ==> iff) impl. + +(** Morphisms for quantifiers *) + +Program Instance ex_iff_morphism {A : Type} : Morphism (pointwise_relation iff ==> iff) (@ex A). + + Next Obligation. + Proof. + unfold pointwise_relation in H. + split ; intros. + destruct H0 as [xâ‚ Hâ‚]. + exists xâ‚. rewrite H in Hâ‚. assumption. + + destruct H0 as [xâ‚ Hâ‚]. + exists xâ‚. rewrite H. assumption. + Qed. + +Program Instance ex_impl_morphism {A : Type} : + Morphism (pointwise_relation impl ==> impl) (@ex A). + + Next Obligation. + Proof. + unfold pointwise_relation in H. + exists H0. apply H. assumption. + Qed. + +Program Instance ex_inverse_impl_morphism {A : Type} : + Morphism (pointwise_relation (inverse impl) ==> inverse impl) (@ex A). + + Next Obligation. + Proof. + unfold pointwise_relation in H. + exists H0. apply H. assumption. + Qed. + +Program Instance all_iff_morphism {A : Type} : + Morphism (pointwise_relation iff ==> iff) (@all A). + + Next Obligation. + Proof. + unfold pointwise_relation, all in *. + intuition ; specialize (H x0) ; intuition. + Qed. + +Program Instance all_impl_morphism {A : Type} : + Morphism (pointwise_relation impl ==> impl) (@all A). + + Next Obligation. + Proof. + unfold pointwise_relation, all in *. + intuition ; specialize (H x0) ; intuition. + Qed. + +Program Instance all_inverse_impl_morphism {A : Type} : + Morphism (pointwise_relation (inverse impl) ==> inverse impl) (@all A). + + Next Obligation. + Proof. + unfold pointwise_relation, all in *. + intuition ; specialize (H x0) ; intuition. + Qed. diff --git a/theories/Classes/Morphisms_Relations.v b/theories/Classes/Morphisms_Relations.v new file mode 100644 index 00000000..5018fa01 --- /dev/null +++ b/theories/Classes/Morphisms_Relations.v @@ -0,0 +1,50 @@ +(* -*- coq-prog-args: ("-emacs-U" "-top" "Coq.Classes.Morphisms") -*- *) +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Morphism instances for relations. + + Author: Matthieu Sozeau + Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + 91405 Orsay, France *) + +Require Import Coq.Classes.Morphisms. +Require Import Coq.Program.Program. + +(** Morphisms for relations *) + +Instance relation_conjunction_morphism : Morphism (relation_equivalence (A:=A) ==> + relation_equivalence ==> relation_equivalence) relation_conjunction. + Proof. firstorder. Qed. + +Instance relation_disjunction_morphism : Morphism (relation_equivalence (A:=A) ==> + relation_equivalence ==> relation_equivalence) relation_disjunction. + Proof. firstorder. Qed. + +(* Predicate equivalence is exactly the same as the pointwise lifting of [iff]. *) + +Require Import List. + +Lemma predicate_equivalence_pointwise (l : list Type) : + Morphism (@predicate_equivalence l ==> pointwise_lifting iff l) id. +Proof. do 2 red. unfold predicate_equivalence. auto. Qed. + +Lemma predicate_implication_pointwise (l : list Type) : + Morphism (@predicate_implication l ==> pointwise_lifting impl l) id. +Proof. do 2 red. unfold predicate_implication. auto. Qed. + +(** The instanciation at relation allows to rewrite applications of relations [R x y] to [R' x y] *) +(* when [R] and [R'] are in [relation_equivalence]. *) + +Instance relation_equivalence_pointwise : + Morphism (relation_equivalence ==> pointwise_relation (A:=A) (pointwise_relation (A:=A) iff)) id. +Proof. intro. apply (predicate_equivalence_pointwise (cons A (cons A nil))). Qed. + +Instance subrelation_pointwise : + Morphism (subrelation ==> pointwise_relation (A:=A) (pointwise_relation (A:=A) impl)) id. +Proof. intro. apply (predicate_implication_pointwise (cons A (cons A nil))). Qed. diff --git a/theories/Classes/RelationClasses.v b/theories/Classes/RelationClasses.v new file mode 100644 index 00000000..a9a53068 --- /dev/null +++ b/theories/Classes/RelationClasses.v @@ -0,0 +1,400 @@ +(* -*- coq-prog-args: ("-emacs-U" "-top" "Coq.Classes.RelationClasses") -*- *) +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Typeclass-based relations, tactics and standard instances. + This is the basic theory needed to formalize morphisms and setoids. + + Author: Matthieu Sozeau + Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + 91405 Orsay, France *) + +(* $Id: RelationClasses.v 11092 2008-06-10 18:28:26Z msozeau $ *) + +Require Export Coq.Classes.Init. +Require Import Coq.Program.Basics. +Require Import Coq.Program.Tactics. +Require Export Coq.Relations.Relation_Definitions. + +Notation inverse R := (flip (R:relation _) : relation _). + +Definition complement {A} (R : relation A) : relation A := fun x y => R x y -> False. + +Definition pointwise_relation {A B : Type} (R : relation B) : relation (A -> B) := + fun f g => forall x : A, R (f x) (g x). + +(** These are convertible. *) + +Lemma complement_inverse : forall A (R : relation A), complement (inverse R) = inverse (complement R). +Proof. reflexivity. Qed. + +(** We rebind relations in separate classes to be able to overload each proof. *) + +Set Implicit Arguments. +Unset Strict Implicit. + +Class Reflexive A (R : relation A) := + reflexivity : forall x, R x x. + +Class Irreflexive A (R : relation A) := + irreflexivity :> Reflexive A (complement R). + +Class Symmetric A (R : relation A) := + symmetry : forall x y, R x y -> R y x. + +Class Asymmetric A (R : relation A) := + asymmetry : forall x y, R x y -> R y x -> False. + +Class Transitive A (R : relation A) := + transitivity : forall x y z, R x y -> R y z -> R x z. + +Implicit Arguments Reflexive [A]. +Implicit Arguments Irreflexive [A]. +Implicit Arguments Symmetric [A]. +Implicit Arguments Asymmetric [A]. +Implicit Arguments Transitive [A]. + +Hint Resolve @irreflexivity : ord. + +Unset Implicit Arguments. + +(** We can already dualize all these properties. *) + +Program Instance flip_Reflexive [ Reflexive A R ] : Reflexive (flip R) := + reflexivity := reflexivity (R:=R). + +Program Instance flip_Irreflexive [ Irreflexive A R ] : Irreflexive (flip R) := + irreflexivity := irreflexivity (R:=R). + +Program Instance flip_Symmetric [ Symmetric A R ] : Symmetric (flip R). + + Solve Obligations using unfold flip ; program_simpl ; clapply Symmetric. + +Program Instance flip_Asymmetric [ Asymmetric A R ] : Asymmetric (flip R). + + Solve Obligations using program_simpl ; unfold flip in * ; intros ; clapply asymmetry. + +Program Instance flip_Transitive [ Transitive A R ] : Transitive (flip R). + + Solve Obligations using unfold flip ; program_simpl ; clapply transitivity. + +Program Instance Reflexive_complement_Irreflexive [ Reflexive A (R : relation A) ] + : Irreflexive (complement R). + + Next Obligation. + Proof. + unfold complement. + red. intros H. + intros H' ; apply H'. + apply (reflexivity H). + Qed. + + +Program Instance complement_Symmetric [ Symmetric A (R : relation A) ] : Symmetric (complement R). + + Next Obligation. + Proof. + red ; intros H'. + apply (H (symmetry H')). + Qed. + +(** * Standard instances. *) + +Ltac reduce_hyp H := + match type of H with + | context [ _ <-> _ ] => fail 1 + | _ => red in H ; try reduce_hyp H + end. + +Ltac reduce_goal := + match goal with + | [ |- _ <-> _ ] => fail 1 + | _ => red ; intros ; try reduce_goal + end. + +Tactic Notation "reduce" "in" hyp(Hid) := reduce_hyp Hid. + +Ltac reduce := reduce_goal. + +Tactic Notation "apply" "*" constr(t) := + first [ refine t | refine (t _) | refine (t _ _) | refine (t _ _ _) | refine (t _ _ _ _) | + refine (t _ _ _ _ _) | refine (t _ _ _ _ _ _) | refine (t _ _ _ _ _ _ _) ]. + +Ltac simpl_relation := + unfold flip, impl, arrow ; try reduce ; program_simpl ; + try ( solve [ intuition ]). + +Ltac obligations_tactic ::= simpl_relation. + +(** Logical implication. *) + +Program Instance impl_Reflexive : Reflexive impl. +Program Instance impl_Transitive : Transitive impl. + +(** Logical equivalence. *) + +Program Instance iff_Reflexive : Reflexive iff. +Program Instance iff_Symmetric : Symmetric iff. +Program Instance iff_Transitive : Transitive iff. + +(** Leibniz equality. *) + +Program Instance eq_Reflexive : Reflexive (@eq A). +Program Instance eq_Symmetric : Symmetric (@eq A). +Program Instance eq_Transitive : Transitive (@eq A). + +(** Various combinations of reflexivity, symmetry and transitivity. *) + +(** A [PreOrder] is both Reflexive and Transitive. *) + +Class PreOrder A (R : relation A) : Prop := + PreOrder_Reflexive :> Reflexive R ; + PreOrder_Transitive :> Transitive R. + +(** A partial equivalence relation is Symmetric and Transitive. *) + +Class PER (carrier : Type) (pequiv : relation carrier) : Prop := + PER_Symmetric :> Symmetric pequiv ; + PER_Transitive :> Transitive pequiv. + +(** Equivalence relations. *) + +Class Equivalence (carrier : Type) (equiv : relation carrier) : Prop := + Equivalence_Reflexive :> Reflexive equiv ; + Equivalence_Symmetric :> Symmetric equiv ; + Equivalence_Transitive :> Transitive equiv. + +(** An Equivalence is a PER plus reflexivity. *) + +Instance Equivalence_PER [ Equivalence A R ] : PER A R := + PER_Symmetric := Equivalence_Symmetric ; + PER_Transitive := Equivalence_Transitive. + +(** We can now define antisymmetry w.r.t. an equivalence relation on the carrier. *) + +Class [ Equivalence A eqA ] => Antisymmetric (R : relation A) := + antisymmetry : forall x y, R x y -> R y x -> eqA x y. + +Program Instance flip_antiSymmetric [ eq : Equivalence A eqA, ! Antisymmetric eq R ] : + Antisymmetric eq (flip R). + +(** Leibinz equality [eq] is an equivalence relation. + The instance has low priority as it is always applicable + if only the type is constrained. *) + +Program Instance eq_equivalence : Equivalence A (@eq A) | 10. + +(** Logical equivalence [iff] is an equivalence relation. *) + +Program Instance iff_equivalence : Equivalence Prop iff. + +(** We now develop a generalization of results on relations for arbitrary predicates. + The resulting theory can be applied to homogeneous binary relations but also to + arbitrary n-ary predicates. *) + +Require Import List. + +(* Notation " [ ] " := nil : list_scope. *) +(* Notation " [ x ; .. ; y ] " := (cons x .. (cons y nil) ..) (at level 1) : list_scope. *) + +(* Open Local Scope list_scope. *) + +(** A compact representation of non-dependent arities, with the codomain singled-out. *) + +Fixpoint arrows (l : list Type) (r : Type) : Type := + match l with + | nil => r + | A :: l' => A -> arrows l' r + end. + +(** We can define abbreviations for operation and relation types based on [arrows]. *) + +Definition unary_operation A := arrows (cons A nil) A. +Definition binary_operation A := arrows (cons A (cons A nil)) A. +Definition ternary_operation A := arrows (cons A (cons A (cons A nil))) A. + +(** We define n-ary [predicate]s as functions into [Prop]. *) + +Notation predicate l := (arrows l Prop). + +(** Unary predicates, or sets. *) + +Definition unary_predicate A := predicate (cons A nil). + +(** Homogeneous binary relations, equivalent to [relation A]. *) + +Definition binary_relation A := predicate (cons A (cons A nil)). + +(** We can close a predicate by universal or existential quantification. *) + +Fixpoint predicate_all (l : list Type) : predicate l -> Prop := + match l with + | nil => fun f => f + | A :: tl => fun f => forall x : A, predicate_all tl (f x) + end. + +Fixpoint predicate_exists (l : list Type) : predicate l -> Prop := + match l with + | nil => fun f => f + | A :: tl => fun f => exists x : A, predicate_exists tl (f x) + end. + +(** Pointwise extension of a binary operation on [T] to a binary operation + on functions whose codomain is [T]. + For an operator on [Prop] this lifts the operator to a binary operation. *) + +Fixpoint pointwise_extension {T : Type} (op : binary_operation T) + (l : list Type) : binary_operation (arrows l T) := + match l with + | nil => fun R R' => op R R' + | A :: tl => fun R R' => + fun x => pointwise_extension op tl (R x) (R' x) + end. + +(** Pointwise lifting, equivalent to doing [pointwise_extension] and closing using [predicate_all]. *) + +Fixpoint pointwise_lifting (op : binary_relation Prop) (l : list Type) : binary_relation (predicate l) := + match l with + | nil => fun R R' => op R R' + | A :: tl => fun R R' => + forall x, pointwise_lifting op tl (R x) (R' x) + end. + +(** The n-ary equivalence relation, defined by lifting the 0-ary [iff] relation. *) + +Definition predicate_equivalence {l : list Type} : binary_relation (predicate l) := + pointwise_lifting iff l. + +(** The n-ary implication relation, defined by lifting the 0-ary [impl] relation. *) + +Definition predicate_implication {l : list Type} := + pointwise_lifting impl l. + +(** Notations for pointwise equivalence and implication of predicates. *) + +Infix "<∙>" := predicate_equivalence (at level 95, no associativity) : predicate_scope. +Infix "-∙>" := predicate_implication (at level 70) : predicate_scope. + +Open Local Scope predicate_scope. + +(** The pointwise liftings of conjunction and disjunctions. + Note that these are [binary_operation]s, building new relations out of old ones. *) + +Definition predicate_intersection := pointwise_extension and. +Definition predicate_union := pointwise_extension or. + +Infix "/∙\" := predicate_intersection (at level 80, right associativity) : predicate_scope. +Infix "\∙/" := predicate_union (at level 85, right associativity) : predicate_scope. + +(** The always [True] and always [False] predicates. *) + +Fixpoint true_predicate {l : list Type} : predicate l := + match l with + | nil => True + | A :: tl => fun _ => @true_predicate tl + end. + +Fixpoint false_predicate {l : list Type} : predicate l := + match l with + | nil => False + | A :: tl => fun _ => @false_predicate tl + end. + +Notation "∙⊤∙" := true_predicate : predicate_scope. +Notation "∙⊥∙" := false_predicate : predicate_scope. + +(** Predicate equivalence is an equivalence, and predicate implication defines a preorder. *) + +Program Instance predicate_equivalence_equivalence : + Equivalence (predicate l) predicate_equivalence. + + Next Obligation. + induction l ; firstorder. + Qed. + + Next Obligation. + induction l ; firstorder. + Qed. + + Next Obligation. + fold pointwise_lifting. + induction l. firstorder. + intros. simpl in *. pose (IHl (x x0) (y x0) (z x0)). + firstorder. + Qed. + +Program Instance predicate_implication_preorder : + PreOrder (predicate l) predicate_implication. + + Next Obligation. + induction l ; firstorder. + Qed. + + Next Obligation. + induction l. firstorder. + unfold predicate_implication in *. simpl in *. + intro. pose (IHl (x x0) (y x0) (z x0)). firstorder. + Qed. + +(** We define the various operations which define the algebra on binary relations, + from the general ones. *) + +Definition relation_equivalence {A : Type} : relation (relation A) := + @predicate_equivalence (cons _ (cons _ nil)). + +Class subrelation {A:Type} (R R' : relation A) : Prop := + is_subrelation : @predicate_implication (cons A (cons A nil)) R R'. + +Implicit Arguments subrelation [[A]]. + +Definition relation_conjunction {A} (R : relation A) (R' : relation A) : relation A := + @predicate_intersection (cons A (cons A nil)) R R'. + +Definition relation_disjunction {A} (R : relation A) (R' : relation A) : relation A := + @predicate_union (cons A (cons A nil)) R R'. + +(** Relation equivalence is an equivalence, and subrelation defines a partial order. *) + +Instance relation_equivalence_equivalence (A : Type) : + Equivalence (relation A) relation_equivalence. +Proof. intro A. exact (@predicate_equivalence_equivalence (cons A (cons A nil))). Qed. + +Instance relation_implication_preorder : PreOrder (relation A) subrelation. +Proof. intro A. exact (@predicate_implication_preorder (cons A (cons A nil))). Qed. + +(** *** Partial Order. + A partial order is a preorder which is additionally antisymmetric. + We give an equivalent definition, up-to an equivalence relation + on the carrier. *) + +Class [ equ : Equivalence A eqA, PreOrder A R ] => PartialOrder := + partial_order_equivalence : relation_equivalence eqA (relation_conjunction R (inverse R)). + +(** The equivalence proof is sufficient for proving that [R] must be a morphism + for equivalence (see Morphisms). + It is also sufficient to show that [R] is antisymmetric w.r.t. [eqA] *) + +Instance partial_order_antisym [ PartialOrder A eqA R ] : ! Antisymmetric A eqA R. +Proof with auto. + reduce_goal. pose proof partial_order_equivalence as poe. do 3 red in poe. + apply <- poe. firstorder. +Qed. + +(** The partial order defined by subrelation and relation equivalence. *) + +Program Instance subrelation_partial_order : + ! PartialOrder (relation A) relation_equivalence subrelation. + + Next Obligation. + Proof. + unfold relation_equivalence in *. firstorder. + Qed. + +Lemma inverse_pointwise_relation A (R : relation A) : + relation_equivalence (pointwise_relation (inverse R)) (inverse (pointwise_relation (A:=A) R)). +Proof. reflexivity. Qed. diff --git a/theories/Classes/SetoidAxioms.v b/theories/Classes/SetoidAxioms.v new file mode 100644 index 00000000..9264b6d2 --- /dev/null +++ b/theories/Classes/SetoidAxioms.v @@ -0,0 +1,35 @@ +(* -*- coq-prog-args: ("-emacs-U" "-nois") -*- *) +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Extensionality axioms that can be used when reasoning with setoids. + * + * Author: Matthieu Sozeau + * Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + * 91405 Orsay, France *) + +(* $Id: SetoidAxioms.v 10739 2008-04-01 14:45:20Z herbelin $ *) + +Require Import Coq.Program.Program. + +Set Implicit Arguments. +Unset Strict Implicit. + +Require Export Coq.Classes.SetoidClass. + +(* Application of the extensionality axiom to turn a goal on leibinz equality to + a setoid equivalence. *) + +Axiom setoideq_eq : forall [ sa : Setoid a ] (x y : a), x == y -> x = y. + +(** Application of the extensionality principle for setoids. *) + +Ltac setoid_extensionality := + match goal with + [ |- @eq ?A ?X ?Y ] => apply (setoideq_eq (a:=A) (x:=X) (y:=Y)) + end. diff --git a/theories/Classes/SetoidClass.v b/theories/Classes/SetoidClass.v new file mode 100644 index 00000000..a9bdaa8f --- /dev/null +++ b/theories/Classes/SetoidClass.v @@ -0,0 +1,181 @@ +(* -*- coq-prog-args: ("-emacs-U" "-nois") -*- *) +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Typeclass-based setoids, tactics and standard instances. + + Author: Matthieu Sozeau + Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + 91405 Orsay, France *) + +(* $Id: SetoidClass.v 11065 2008-06-06 22:39:43Z msozeau $ *) + +Set Implicit Arguments. +Unset Strict Implicit. + +Require Import Coq.Program.Program. + +Require Import Coq.Classes.Init. +Require Export Coq.Classes.RelationClasses. +Require Export Coq.Classes.Morphisms. +Require Import Coq.Classes.Functions. + +(** A setoid wraps an equivalence. *) + +Class Setoid A := + equiv : relation A ; + setoid_equiv :> Equivalence A equiv. + +Typeclasses unfold equiv. + +(* Too dangerous instance *) +(* Program Instance [ eqa : Equivalence A eqA ] => *) +(* equivalence_setoid : Setoid A := *) +(* equiv := eqA ; setoid_equiv := eqa. *) + +(** Shortcuts to make proof search easier. *) + +Definition setoid_refl [ sa : Setoid A ] : Reflexive equiv. +Proof. eauto with typeclass_instances. Qed. + +Definition setoid_sym [ sa : Setoid A ] : Symmetric equiv. +Proof. eauto with typeclass_instances. Qed. + +Definition setoid_trans [ sa : Setoid A ] : Transitive equiv. +Proof. eauto with typeclass_instances. Qed. + +Existing Instance setoid_refl. +Existing Instance setoid_sym. +Existing Instance setoid_trans. + +(** Standard setoids. *) + +(* Program Instance eq_setoid : Setoid A := *) +(* equiv := eq ; setoid_equiv := eq_equivalence. *) + +Program Instance iff_setoid : Setoid Prop := + equiv := iff ; setoid_equiv := iff_equivalence. + +(** Overloaded notations for setoid equivalence and inequivalence. Not to be confused with [eq] and [=]. *) + +(** Subset objects should be first coerced to their underlying type, but that notation doesn't work in the standard case then. *) +(* Notation " x == y " := (equiv (x :>) (y :>)) (at level 70, no associativity) : type_scope. *) + +Notation " x == y " := (equiv x y) (at level 70, no associativity) : type_scope. + +Notation " x =/= y " := (complement equiv x y) (at level 70, no associativity) : type_scope. + +(** Use the [clsubstitute] command which substitutes an equality in every hypothesis. *) + +Ltac clsubst H := + match type of H with + ?x == ?y => substitute H ; clear H x + end. + +Ltac clsubst_nofail := + match goal with + | [ H : ?x == ?y |- _ ] => clsubst H ; clsubst_nofail + | _ => idtac + end. + +(** [subst*] will try its best at substituting every equality in the goal. *) + +Tactic Notation "clsubst" "*" := clsubst_nofail. + +Lemma nequiv_equiv_trans : forall [ Setoid A ] (x y z : A), x =/= y -> y == z -> x =/= z. +Proof with auto. + intros; intro. + assert(z == y) by (symmetry ; auto). + assert(x == y) by (transitivity z ; eauto). + contradiction. +Qed. + +Lemma equiv_nequiv_trans : forall [ Setoid A ] (x y z : A), x == y -> y =/= z -> x =/= z. +Proof. + intros; intro. + assert(y == x) by (symmetry ; auto). + assert(y == z) by (transitivity x ; eauto). + contradiction. +Qed. + +Ltac setoid_simplify_one := + match goal with + | [ H : (?x == ?x)%type |- _ ] => clear H + | [ H : (?x == ?y)%type |- _ ] => clsubst H + | [ |- (?x =/= ?y)%type ] => let name:=fresh "Hneq" in intro name + end. + +Ltac setoid_simplify := repeat setoid_simplify_one. + +Ltac setoidify_tac := + match goal with + | [ s : Setoid ?A, H : ?R ?x ?y |- _ ] => change R with (@equiv A R s) in H + | [ s : Setoid ?A |- context C [ ?R ?x ?y ] ] => change (R x y) with (@equiv A R s x y) + end. + +Ltac setoidify := repeat setoidify_tac. + +(** Every setoid relation gives rise to a morphism, in fact every partial setoid does. *) + +Program Definition setoid_morphism [ sa : Setoid A ] : Morphism (equiv ++> equiv ++> iff) equiv := + trans_sym_morphism. + +(** Add this very useful instance in the database. *) + +Implicit Arguments setoid_morphism [[!sa]]. +Existing Instance setoid_morphism. + +Program Definition setoid_partial_app_morphism [ sa : Setoid A ] (x : A) : Morphism (equiv ++> iff) (equiv x) := + Reflexive_partial_app_morphism. + +Existing Instance setoid_partial_app_morphism. + +Definition type_eq : relation Type := + fun x y => x = y. + +Program Instance type_equivalence : Equivalence Type type_eq. + +Ltac morphism_tac := try red ; unfold arrow ; intros ; program_simpl ; try tauto. + +Ltac obligations_tactic ::= morphism_tac. + +(** These are morphisms used to rewrite at the top level of a proof, + using [iff_impl_id_morphism] if the proof is in [Prop] and + [eq_arrow_id_morphism] if it is in Type. *) + +Program Instance iff_impl_id_morphism : Morphism (iff ++> impl) Basics.id. + +(* Program Instance eq_arrow_id_morphism : ? Morphism (eq +++> arrow) id. *) + +(* Definition compose_respect (A B C : Type) (R : relation (A -> B)) (R' : relation (B -> C)) *) +(* (x y : A -> C) : Prop := forall (f : A -> B) (g : B -> C), R f f -> R' g g. *) + +(* Program Instance (A B C : Type) (R : relation (A -> B)) (R' : relation (B -> C)) *) +(* [ mg : ? Morphism R' g ] [ mf : ? Morphism R f ] => *) +(* compose_morphism : ? Morphism (compose_respect R R') (g o f). *) + +(* Next Obligation. *) +(* Proof. *) +(* apply (respect (m0:=mg)). *) +(* apply (respect (m0:=mf)). *) +(* assumption. *) +(* Qed. *) + +(** Partial setoids don't require reflexivity so we can build a partial setoid on the function space. *) + +Class PartialSetoid (carrier : Type) := + pequiv : relation carrier ; + pequiv_prf :> PER carrier pequiv. + +(** Overloaded notation for partial setoid equivalence. *) + +Infix "=~=" := pequiv (at level 70, no associativity) : type_scope. + +(** Reset the default Program tactic. *) + +Ltac obligations_tactic ::= program_simpl. diff --git a/theories/Classes/SetoidDec.v b/theories/Classes/SetoidDec.v new file mode 100644 index 00000000..cf3d202d --- /dev/null +++ b/theories/Classes/SetoidDec.v @@ -0,0 +1,126 @@ +(* -*- coq-prog-args: ("-emacs-U" "-nois") -*- *) +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Decidable setoid equality theory. + * + * Author: Matthieu Sozeau + * Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + * 91405 Orsay, France *) + +(* $Id: SetoidDec.v 10919 2008-05-11 22:04:26Z msozeau $ *) + +Set Implicit Arguments. +Unset Strict Implicit. + +(** Export notations. *) + +Require Export Coq.Classes.SetoidClass. + +(** The [DecidableSetoid] class asserts decidability of a [Setoid]. It can be useful in proofs to reason more + classically. *) + +Require Import Coq.Logic.Decidable. + +Class [ Setoid A ] => DecidableSetoid := + setoid_decidable : forall x y : A, decidable (x == y). + +(** The [EqDec] class gives a decision procedure for a particular setoid equality. *) + +Class [ Setoid A ] => EqDec := + equiv_dec : forall x y : A, { x == y } + { x =/= y }. + +(** We define the [==] overloaded notation for deciding equality. It does not take precedence + of [==] defined in the type scope, hence we can have both at the same time. *) + +Notation " x == y " := (equiv_dec (x :>) (y :>)) (no associativity, at level 70). + +Definition swap_sumbool {A B} (x : { A } + { B }) : { B } + { A } := + match x with + | left H => @right _ _ H + | right H => @left _ _ H + end. + +Require Import Coq.Program.Program. + +Open Local Scope program_scope. + +(** Invert the branches. *) + +Program Definition nequiv_dec [ EqDec A ] (x y : A) : { x =/= y } + { x == y } := swap_sumbool (x == y). + +(** Overloaded notation for inequality. *) + +Infix "=/=" := nequiv_dec (no associativity, at level 70). + +(** Define boolean versions, losing the logical information. *) + +Definition equiv_decb [ EqDec A ] (x y : A) : bool := + if x == y then true else false. + +Definition nequiv_decb [ EqDec A ] (x y : A) : bool := + negb (equiv_decb x y). + +Infix "==b" := equiv_decb (no associativity, at level 70). +Infix "<>b" := nequiv_decb (no associativity, at level 70). + +(** Decidable leibniz equality instances. *) + +Require Import Coq.Arith.Arith. + +(** The equiv is burried inside the setoid, but we can recover it by specifying which setoid we're talking about. *) + +Program Instance eq_setoid : Setoid A := + equiv := eq ; setoid_equiv := eq_equivalence. + +Program Instance nat_eq_eqdec : EqDec (@eq_setoid nat) := + equiv_dec := eq_nat_dec. + +Require Import Coq.Bool.Bool. + +Program Instance bool_eqdec : EqDec (@eq_setoid bool) := + equiv_dec := bool_dec. + +Program Instance unit_eqdec : EqDec (@eq_setoid unit) := + equiv_dec x y := in_left. + + Next Obligation. + Proof. + destruct x ; destruct y. + reflexivity. + Qed. + +Program Instance prod_eqdec [ ! EqDec (@eq_setoid A), ! EqDec (@eq_setoid B) ] : EqDec (@eq_setoid (prod A B)) := + equiv_dec x y := + let '(x1, x2) := x in + let '(y1, y2) := y in + if x1 == y1 then + if x2 == y2 then in_left + else in_right + else in_right. + + Solve Obligations using unfold complement ; program_simpl. + +(** Objects of function spaces with countable domains like bool have decidable equality. *) + +Require Import Coq.Program.FunctionalExtensionality. + +Program Instance bool_function_eqdec [ ! EqDec (@eq_setoid A) ] : EqDec (@eq_setoid (bool -> A)) := + equiv_dec f g := + if f true == g true then + if f false == g false then in_left + else in_right + else in_right. + + Solve Obligations using try red ; unfold equiv, complement ; program_simpl. + + Next Obligation. + Proof. + extensionality x. + destruct x ; auto. + Qed. diff --git a/theories/Classes/SetoidTactics.v b/theories/Classes/SetoidTactics.v new file mode 100644 index 00000000..b29a52cc --- /dev/null +++ b/theories/Classes/SetoidTactics.v @@ -0,0 +1,176 @@ +(* -*- coq-prog-args: ("-emacs-U" "-top" "Coq.Classes.SetoidTactics") -*- *) +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Tactics for typeclass-based setoids. + * + * Author: Matthieu Sozeau + * Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + * 91405 Orsay, France *) + +(* $Id: SetoidTactics.v 10921 2008-05-12 12:27:25Z msozeau $ *) + +Require Export Coq.Classes.RelationClasses. +Require Export Coq.Classes.Morphisms. +Require Export Coq.Classes.Morphisms_Prop. +Require Export Coq.Classes.Equivalence. +Require Export Coq.Relations.Relation_Definitions. + +Set Implicit Arguments. +Unset Strict Implicit. + +(** Default relation on a given support. Can be used by tactics + to find a sensible default relation on any carrier. Users can + declare an [Instance A RA] anywhere to declare default relations. + This is also done by the [Declare Relation A RA] command with no + parameters for backward compatibility. *) + +Class DefaultRelation A (R : relation A). + +(** To search for the default relation, just call [default_relation]. *) + +Definition default_relation [ DefaultRelation A R ] := R. + +(** Every [Equivalence] gives a default relation, if no other is given (lowest priority). *) + +Instance equivalence_default [ Equivalence A R ] : DefaultRelation A R | 4. + +(** The setoid_replace tactics in Ltac, defined in terms of default relations and + the setoid_rewrite tactic. *) + +Ltac setoidreplace H t := + let Heq := fresh "Heq" in + cut(H) ; unfold default_relation ; [ intro Heq ; setoid_rewrite Heq ; clear Heq | t ]. + +Ltac setoidreplacein H H' t := + let Heq := fresh "Heq" in + cut(H) ; unfold default_relation ; [ intro Heq ; setoid_rewrite Heq in H' ; clear Heq | t ]. + +Ltac setoidreplaceinat H H' t occs := + let Heq := fresh "Heq" in + cut(H) ; unfold default_relation ; [ intro Heq ; setoid_rewrite Heq in H' at occs ; clear Heq | t ]. + +Ltac setoidreplaceat H t occs := + let Heq := fresh "Heq" in + cut(H) ; unfold default_relation ; [ intro Heq ; setoid_rewrite Heq at occs ; clear Heq | t ]. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) := + setoidreplace (default_relation x y) idtac. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "at" int_or_var_list(o) := + setoidreplaceat (default_relation x y) idtac o. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "in" hyp(id) := + setoidreplacein (default_relation x y) id idtac. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "in" hyp(id) + "at" int_or_var_list(o) := + setoidreplaceinat (default_relation x y) id idtac o. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "by" tactic3(t) := + setoidreplace (default_relation x y) ltac:t. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "at" int_or_var_list(o) + "by" tactic3(t) := + setoidreplaceat (default_relation x y) ltac:t o. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "in" hyp(id) + "by" tactic3(t) := + setoidreplacein (default_relation x y) id ltac:t. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "in" hyp(id) + "at" int_or_var_list(o) + "by" tactic3(t) := + setoidreplaceinat (default_relation x y) id ltac:t o. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "using" "relation" constr(rel) := + setoidreplace (rel x y) idtac. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "using" "relation" constr(rel) + "at" int_or_var_list(o) := + setoidreplaceat (rel x y) idtac o. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "using" "relation" constr(rel) + "by" tactic3(t) := + setoidreplace (rel x y) ltac:t. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "using" "relation" constr(rel) + "at" int_or_var_list(o) + "by" tactic3(t) := + setoidreplaceat (rel x y) ltac:t o. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "using" "relation" constr(rel) + "in" hyp(id) := + setoidreplacein (rel x y) id idtac. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "using" "relation" constr(rel) + "in" hyp(id) + "at" int_or_var_list(o) := + setoidreplaceinat (rel x y) id idtac o. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "using" "relation" constr(rel) + "in" hyp(id) + "by" tactic3(t) := + setoidreplacein (rel x y) id ltac:t. + +Tactic Notation "setoid_replace" constr(x) "with" constr(y) + "using" "relation" constr(rel) + "in" hyp(id) + "at" int_or_var_list(o) + "by" tactic3(t) := + setoidreplaceinat (rel x y) id ltac:t o. + +(** The [add_morphism_tactic] tactic is run at each [Add Morphism] command before giving the hand back + to the user to discharge the proof. It essentially amounts to unfold the right amount of [respectful] calls + and substitute leibniz equalities. One can redefine it using [Ltac add_morphism_tactic ::= t]. *) + +Require Import Coq.Program.Tactics. + +Open Local Scope signature_scope. + +Ltac red_subst_eq_morphism concl := + match concl with + | @Logic.eq ?A ==> ?R' => red ; intros ; subst ; red_subst_eq_morphism R' + | ?R ==> ?R' => red ; intros ; red_subst_eq_morphism R' + | _ => idtac + end. + +Ltac destruct_morphism := + match goal with + | [ |- @Morphism ?A ?R ?m ] => red + end. + +Ltac reverse_arrows x := + match x with + | @Logic.eq ?A ==> ?R' => revert_last ; reverse_arrows R' + | ?R ==> ?R' => do 3 revert_last ; reverse_arrows R' + | _ => idtac + end. + +Ltac default_add_morphism_tactic := + intros ; + (try destruct_morphism) ; + match goal with + | [ |- (?x ==> ?y) _ _ ] => red_subst_eq_morphism (x ==> y) ; reverse_arrows (x ==> y) + end. + +Ltac add_morphism_tactic := default_add_morphism_tactic. diff --git a/theories/FSets/FMapAVL.v b/theories/FSets/FMapAVL.v index 4807ed66..8cb1236e 100644 --- a/theories/FSets/FMapAVL.v +++ b/theories/FSets/FMapAVL.v @@ -9,35 +9,35 @@ (* Finite map library. *) -(* $Id: FMapAVL.v 9862 2007-05-25 16:57:06Z letouzey $ *) +(* $Id: FMapAVL.v 11033 2008-06-01 22:56:50Z letouzey $ *) -(** This module implements map using AVL trees. - It follows the implementation from Ocaml's standard library. *) +(** * FMapAVL *) -Require Import FSetInterface. -Require Import FMapInterface. -Require Import FMapList. +(** This module implements maps using AVL trees. + It follows the implementation from Ocaml's standard library. + + See the comments at the beginning of FSetAVL for more details. +*) -Require Import ZArith. -Require Import Int. +Require Import FMapInterface FMapList ZArith Int. -Set Firstorder Depth 3. Set Implicit Arguments. Unset Strict Implicit. +(** Notations and helper lemma about pairs *) -Module Raw (I:Int)(X: OrderedType). -Import I. -Module II:=MoreInt(I). -Import II. -Open Local Scope Int_scope. +Notation "s #1" := (fst s) (at level 9, format "s '#1'") : pair_scope. +Notation "s #2" := (snd s) (at level 9, format "s '#2'") : pair_scope. -Module E := X. -Module MX := OrderedTypeFacts X. -Module PX := KeyOrderedType X. -Module L := FMapList.Raw X. -Import MX. -Import PX. +(** * The Raw functor + + Functor of pure functions + separate proofs of invariant + preservation *) + +Module Raw (Import I:Int)(X: OrderedType). +Open Local Scope pair_scope. +Open Local Scope lazy_bool_scope. +Open Local Scope Int_scope. Definition key := X.t. @@ -45,30 +45,391 @@ Definition key := X.t. Section Elt. -Variable elt : Set. +Variable elt : Type. -(* Now in KeyOrderedType: -Definition eqk (p p':key*elt) := X.eq (fst p) (fst p'). -Definition eqke (p p':key*elt) := - X.eq (fst p) (fst p') /\ (snd p) = (snd p'). -Definition ltk (p p':key*elt) := X.lt (fst p) (fst p'). -*) +(** * Trees -Notation eqk := (eqk (elt:= elt)). -Notation eqke := (eqke (elt:= elt)). -Notation ltk := (ltk (elt:= elt)). + The fifth field of [Node] is the height of the tree *) -Inductive tree : Set := +Inductive tree := | Leaf : tree | Node : tree -> key -> elt -> tree -> int -> tree. Notation t := tree. -(** The Sixth field of [Node] is the height of the tree *) +(** * Basic functions on trees: height and cardinal *) + +Definition height (m : t) : int := + match m with + | Leaf => 0 + | Node _ _ _ _ h => h + end. + +Fixpoint cardinal (m : t) : nat := + match m with + | Leaf => 0%nat + | Node l _ _ r _ => S (cardinal l + cardinal r) + end. + +(** * Empty Map *) + +Definition empty := Leaf. + +(** * Emptyness test *) + +Definition is_empty m := match m with Leaf => true | _ => false end. + +(** * Appartness *) + +(** The [mem] function is deciding appartness. It exploits the [bst] property + to achieve logarithmic complexity. *) + +Fixpoint mem x m : bool := + match m with + | Leaf => false + | Node l y _ r _ => match X.compare x y with + | LT _ => mem x l + | EQ _ => true + | GT _ => mem x r + end + end. + +Fixpoint find x m : option elt := + match m with + | Leaf => None + | Node l y d r _ => match X.compare x y with + | LT _ => find x l + | EQ _ => Some d + | GT _ => find x r + end + end. + +(** * Helper functions *) -(** * Occurrence in a tree *) +(** [create l x r] creates a node, assuming [l] and [r] + to be balanced and [|height l - height r| <= 2]. *) -Inductive MapsTo (x : key)(e : elt) : tree -> Prop := +Definition create l x e r := + Node l x e r (max (height l) (height r) + 1). + +(** [bal l x e r] acts as [create], but performs one step of + rebalancing if necessary, i.e. assumes [|height l - height r| <= 3]. *) + +Definition assert_false := create. + +Fixpoint bal l x d r := + let hl := height l in + let hr := height r in + if gt_le_dec hl (hr+2) then + match l with + | Leaf => assert_false l x d r + | Node ll lx ld lr _ => + if ge_lt_dec (height ll) (height lr) then + create ll lx ld (create lr x d r) + else + match lr with + | Leaf => assert_false l x d r + | Node lrl lrx lrd lrr _ => + create (create ll lx ld lrl) lrx lrd (create lrr x d r) + end + end + else + if gt_le_dec hr (hl+2) then + match r with + | Leaf => assert_false l x d r + | Node rl rx rd rr _ => + if ge_lt_dec (height rr) (height rl) then + create (create l x d rl) rx rd rr + else + match rl with + | Leaf => assert_false l x d r + | Node rll rlx rld rlr _ => + create (create l x d rll) rlx rld (create rlr rx rd rr) + end + end + else + create l x d r. + +(** * Insertion *) + +Fixpoint add x d m := + match m with + | Leaf => Node Leaf x d Leaf 1 + | Node l y d' r h => + match X.compare x y with + | LT _ => bal (add x d l) y d' r + | EQ _ => Node l y d r h + | GT _ => bal l y d' (add x d r) + end + end. + +(** * Extraction of minimum binding + + Morally, [remove_min] is to be applied to a non-empty tree + [t = Node l x e r h]. Since we can't deal here with [assert false] + for [t=Leaf], we pre-unpack [t] (and forget about [h]). +*) + +Fixpoint remove_min l x d r : t*(key*elt) := + match l with + | Leaf => (r,(x,d)) + | Node ll lx ld lr lh => + let (l',m) := remove_min ll lx ld lr in + (bal l' x d r, m) + end. + +(** * Merging two trees + + [merge t1 t2] builds the union of [t1] and [t2] assuming all elements + of [t1] to be smaller than all elements of [t2], and + [|height t1 - height t2| <= 2]. +*) + +Fixpoint merge s1 s2 := match s1,s2 with + | Leaf, _ => s2 + | _, Leaf => s1 + | _, Node l2 x2 d2 r2 h2 => + match remove_min l2 x2 d2 r2 with + (s2',(x,d)) => bal s1 x d s2' + end +end. + +(** * Deletion *) + +Fixpoint remove x m := match m with + | Leaf => Leaf + | Node l y d r h => + match X.compare x y with + | LT _ => bal (remove x l) y d r + | EQ _ => merge l r + | GT _ => bal l y d (remove x r) + end + end. + +(** * join + + Same as [bal] but does not assume anything regarding heights of [l] + and [r]. +*) + +Fixpoint join l : key -> elt -> t -> t := + match l with + | Leaf => add + | Node ll lx ld lr lh => fun x d => + fix join_aux (r:t) : t := match r with + | Leaf => add x d l + | Node rl rx rd rr rh => + if gt_le_dec lh (rh+2) then bal ll lx ld (join lr x d r) + else if gt_le_dec rh (lh+2) then bal (join_aux rl) rx rd rr + else create l x d r + end + end. + +(** * Splitting + + [split x m] returns a triple [(l, o, r)] where + - [l] is the set of elements of [m] that are [< x] + - [r] is the set of elements of [m] that are [> x] + - [o] is the result of [find x m]. +*) + +Record triple := mktriple { t_left:t; t_opt:option elt; t_right:t }. +Notation "<< l , b , r >>" := (mktriple l b r) (at level 9). + +Fixpoint split x m : triple := match m with + | Leaf => << Leaf, None, Leaf >> + | Node l y d r h => + match X.compare x y with + | LT _ => let (ll,o,rl) := split x l in << ll, o, join rl y d r >> + | EQ _ => << l, Some d, r >> + | GT _ => let (rl,o,rr) := split x r in << join l y d rl, o, rr >> + end + end. + +(** * Concatenation + + Same as [merge] but does not assume anything about heights. +*) + +Definition concat m1 m2 := + match m1, m2 with + | Leaf, _ => m2 + | _ , Leaf => m1 + | _, Node l2 x2 d2 r2 _ => + let (m2',xd) := remove_min l2 x2 d2 r2 in + join m1 xd#1 xd#2 m2' + end. + +(** * Elements *) + +(** [elements_tree_aux acc t] catenates the elements of [t] in infix + order to the list [acc] *) + +Fixpoint elements_aux (acc : list (key*elt)) m : list (key*elt) := + match m with + | Leaf => acc + | Node l x d r _ => elements_aux ((x,d) :: elements_aux acc r) l + end. + +(** then [elements] is an instanciation with an empty [acc] *) + +Definition elements := elements_aux nil. + +(** * Fold *) + +Fixpoint fold (A : Type) (f : key -> elt -> A -> A) (m : t) : A -> A := + fun a => match m with + | Leaf => a + | Node l x d r _ => fold f r (f x d (fold f l a)) + end. + +(** * Comparison *) + +Variable cmp : elt->elt->bool. + +(** ** Enumeration of the elements of a tree *) + +Inductive enumeration := + | End : enumeration + | More : key -> elt -> t -> enumeration -> enumeration. + +(** [cons m e] adds the elements of tree [m] on the head of + enumeration [e]. *) + +Fixpoint cons m e : enumeration := + match m with + | Leaf => e + | Node l x d r h => cons l (More x d r e) + end. + +(** One step of comparison of elements *) + +Definition equal_more x1 d1 (cont:enumeration->bool) e2 := + match e2 with + | End => false + | More x2 d2 r2 e2 => + match X.compare x1 x2 with + | EQ _ => cmp d1 d2 &&& cont (cons r2 e2) + | _ => false + end + end. + +(** Comparison of left tree, middle element, then right tree *) + +Fixpoint equal_cont m1 (cont:enumeration->bool) e2 := + match m1 with + | Leaf => cont e2 + | Node l1 x1 d1 r1 _ => + equal_cont l1 (equal_more x1 d1 (equal_cont r1 cont)) e2 + end. + +(** Initial continuation *) + +Definition equal_end e2 := match e2 with End => true | _ => false end. + +(** The complete comparison *) + +Definition equal m1 m2 := equal_cont m1 equal_end (cons m2 End). + +End Elt. +Notation t := tree. +Notation "<< l , b , r >>" := (mktriple l b r) (at level 9). +Notation "t #l" := (t_left t) (at level 9, format "t '#l'"). +Notation "t #o" := (t_opt t) (at level 9, format "t '#o'"). +Notation "t #r" := (t_right t) (at level 9, format "t '#r'"). + + +(** * Map *) + +Fixpoint map (elt elt' : Type)(f : elt -> elt')(m : t elt) : t elt' := + match m with + | Leaf => Leaf _ + | Node l x d r h => Node (map f l) x (f d) (map f r) h + end. + +(* * Mapi *) + +Fixpoint mapi (elt elt' : Type)(f : key -> elt -> elt')(m : t elt) : t elt' := + match m with + | Leaf => Leaf _ + | Node l x d r h => Node (mapi f l) x (f x d) (mapi f r) h + end. + +(** * Map with removal *) + +Fixpoint map_option (elt elt' : Type)(f : key -> elt -> option elt')(m : t elt) + : t elt' := + match m with + | Leaf => Leaf _ + | Node l x d r h => + match f x d with + | Some d' => join (map_option f l) x d' (map_option f r) + | None => concat (map_option f l) (map_option f r) + end + end. + +(** * Optimized map2 + + Suggestion by B. Gregoire: a [map2] function with specialized + arguments allowing to bypass some tree traversal. Instead of one + [f0] of type [key -> option elt -> option elt' -> option elt''], + we ask here for: + - [f] which is a specialisation of [f0] when first option isn't [None] + - [mapl] treats a [tree elt] with [f0] when second option is [None] + - [mapr] treats a [tree elt'] with [f0] when first option is [None] + + The idea is that [mapl] and [mapr] can be instantaneous (e.g. + the identity or some constant function). +*) + +Section Map2_opt. +Variable elt elt' elt'' : Type. +Variable f : key -> elt -> option elt' -> option elt''. +Variable mapl : t elt -> t elt''. +Variable mapr : t elt' -> t elt''. + +Fixpoint map2_opt m1 m2 := + match m1, m2 with + | Leaf, _ => mapr m2 + | _, Leaf => mapl m1 + | Node l1 x1 d1 r1 h1, _ => + let (l2',o2,r2') := split x1 m2 in + match f x1 d1 o2 with + | Some e => join (map2_opt l1 l2') x1 e (map2_opt r1 r2') + | None => concat (map2_opt l1 l2') (map2_opt r1 r2') + end + end. + +End Map2_opt. + +(** * Map2 + + The [map2] function of the Map interface can be implemented + via [map2_opt] and [map_option]. +*) + +Section Map2. +Variable elt elt' elt'' : Type. +Variable f : option elt -> option elt' -> option elt''. + +Definition map2 : t elt -> t elt' -> t elt'' := + map2_opt + (fun _ d o => f (Some d) o) + (map_option (fun _ d => f (Some d) None)) + (map_option (fun _ d' => f None (Some d'))). + +End Map2. + + + +(** * Invariants *) + +Section Invariants. +Variable elt : Type. + +(** ** Occurrence in a tree *) + +Inductive MapsTo (x : key)(e : elt) : t elt -> Prop := | MapsRoot : forall l r h y, X.eq x y -> MapsTo x e (Node l y e r h) | MapsLeft : forall l r h y e', @@ -76,7 +437,7 @@ Inductive MapsTo (x : key)(e : elt) : tree -> Prop := | MapsRight : forall l r h y e', MapsTo x e r -> MapsTo x e (Node l y e' r h). -Inductive In (x : key) : tree -> Prop := +Inductive In (x : key) : t elt -> Prop := | InRoot : forall l r h y e, X.eq x y -> In x (Node l y e r h) | InLeft : forall l r h y e', @@ -84,58 +445,66 @@ Inductive In (x : key) : tree -> Prop := | InRight : forall l r h y e', In x r -> In x (Node l y e' r h). -Definition In0 (k:key)(m:t) : Prop := exists e:elt, MapsTo k e m. +Definition In0 k m := exists e:elt, MapsTo k e m. -(** * Binary search trees *) +(** ** Binary search trees *) (** [lt_tree x s]: all elements in [s] are smaller than [x] (resp. greater for [gt_tree]) *) -Definition lt_tree x s := forall y:key, In y s -> X.lt y x. -Definition gt_tree x s := forall y:key, In y s -> X.lt x y. +Definition lt_tree x m := forall y, In y m -> X.lt y x. +Definition gt_tree x m := forall y, In y m -> X.lt x y. (** [bst t] : [t] is a binary search tree *) -Inductive bst : tree -> Prop := - | BSLeaf : bst Leaf - | BSNode : forall x e l r h, - bst l -> bst r -> lt_tree x l -> gt_tree x r -> bst (Node l x e r h). +Inductive bst : t elt -> Prop := + | BSLeaf : bst (Leaf _) + | BSNode : forall x e l r h, bst l -> bst r -> + lt_tree x l -> gt_tree x r -> bst (Node l x e r h). -(** * AVL trees *) +End Invariants. -(** [avl s] : [s] is a properly balanced AVL tree, - i.e. for any node the heights of the two children - differ by at most 2 *) -Definition height (s : tree) : int := - match s with - | Leaf => 0 - | Node _ _ _ _ h => h - end. +(** * Correctness proofs, isolated in a sub-module *) -Inductive avl : tree -> Prop := - | RBLeaf : avl Leaf - | RBNode : forall x e l r h, - avl l -> - avl r -> - -(2) <= height l - height r <= 2 -> - h = max (height l) (height r) + 1 -> - avl (Node l x e r h). +Module Proofs. + Module MX := OrderedTypeFacts X. + Module PX := KeyOrderedType X. + Module L := FMapList.Raw X. -(* We should end this section before the big proofs that follows, - otherwise the discharge takes a lot of time. *) -End Elt. +Functional Scheme mem_ind := Induction for mem Sort Prop. +Functional Scheme find_ind := Induction for find Sort Prop. +Functional Scheme bal_ind := Induction for bal Sort Prop. +Functional Scheme add_ind := Induction for add Sort Prop. +Functional Scheme remove_min_ind := Induction for remove_min Sort Prop. +Functional Scheme merge_ind := Induction for merge Sort Prop. +Functional Scheme remove_ind := Induction for remove Sort Prop. +Functional Scheme concat_ind := Induction for concat Sort Prop. +Functional Scheme split_ind := Induction for split Sort Prop. +Functional Scheme map_option_ind := Induction for map_option Sort Prop. +Functional Scheme map2_opt_ind := Induction for map2_opt Sort Prop. -(** Some helpful hints and tactics. *) +(** * Automation and dedicated tactics. *) -Notation t := tree. -Hint Constructors tree. -Hint Constructors MapsTo. -Hint Constructors In. -Hint Constructors bst. -Hint Constructors avl. +Hint Constructors tree MapsTo In bst. Hint Unfold lt_tree gt_tree. +Tactic Notation "factornode" ident(l) ident(x) ident(d) ident(r) ident(h) + "as" ident(s) := + set (s:=Node l x d r h) in *; clearbody s; clear l x d r h. + +(** A tactic for cleaning hypothesis after use of functional induction. *) + +Ltac clearf := + match goal with + | H : (@Logic.eq (Compare _ _ _ _) _ _) |- _ => clear H; clearf + | H : (@Logic.eq (sumbool _ _) _ _) |- _ => clear H; clearf + | _ => idtac + end. + +(** A tactic to repeat [inversion_clear] on all hyps of the + form [(f (Node ...))] *) + Ltac inv f := match goal with | H:f (Leaf _) |- _ => inversion_clear H; inv f @@ -149,14 +518,6 @@ Ltac inv f := | _ => idtac end. -Ltac safe_inv f := match goal with - | H:f (Node _ _ _ _ _) |- _ => - generalize H; inversion_clear H; safe_inv f - | H:f _ (Node _ _ _ _ _) |- _ => - generalize H; inversion_clear H; safe_inv f - | _ => intros - end. - Ltac inv_all f := match goal with | H: f _ |- _ => inversion_clear H; inv f @@ -166,55 +527,54 @@ Ltac inv_all f := | _ => idtac end. +(** Helper tactic concerning order of elements. *) + Ltac order := match goal with - | H: lt_tree ?x ?s, H1: In ?y ?s |- _ => generalize (H _ H1); clear H; order - | H: gt_tree ?x ?s, H1: In ?y ?s |- _ => generalize (H _ H1); clear H; order + | U: lt_tree _ ?s, V: In _ ?s |- _ => generalize (U _ V); clear U; order + | U: gt_tree _ ?s, V: In _ ?s |- _ => generalize (U _ V); clear U; order | _ => MX.order end. Ltac intuition_in := repeat progress (intuition; inv In; inv MapsTo). -Ltac firstorder_in := repeat progress (firstorder; inv In; inv MapsTo). - -Lemma height_non_negative : forall elt (s : t elt), avl s -> height s >= 0. -Proof. - induction s; simpl; intros; auto with zarith. - inv avl; intuition; omega_max. -Qed. - -Ltac avl_nn_hyp H := - let nz := fresh "nz" in assert (nz := height_non_negative H). -Ltac avl_nn h := - let t := type of h in - match type of t with - | Prop => avl_nn_hyp h - | _ => match goal with H : avl h |- _ => avl_nn_hyp H end - end. - -(* Repeat the previous tactic. - Drawback: need to clear the [avl _] hyps ... Thank you Ltac *) +(* Function/Functional Scheme can't deal with internal fix. + Let's do its job by hand: *) + +Ltac join_tac := + intros l; induction l as [| ll _ lx ld lr Hlr lh]; + [ | intros x d r; induction r as [| rl Hrl rx rd rr _ rh]; unfold join; + [ | destruct (gt_le_dec lh (rh+2)); + [ match goal with |- context [ bal ?u ?v ?w ?z ] => + replace (bal u v w z) + with (bal ll lx ld (join lr x d (Node rl rx rd rr rh))); [ | auto] + end + | destruct (gt_le_dec rh (lh+2)); + [ match goal with |- context [ bal ?u ?v ?w ?z ] => + replace (bal u v w z) + with (bal (join (Node ll lx ld lr lh) x d rl) rx rd rr); [ | auto] + end + | ] ] ] ]; intros. -Ltac avl_nns := - match goal with - | H:avl _ |- _ => avl_nn_hyp H; clear H; avl_nns - | _ => idtac - end. +Section Elt. +Variable elt:Type. +Implicit Types m r : t elt. +(** * Basic results about [MapsTo], [In], [lt_tree], [gt_tree], [height] *) (** Facts about [MapsTo] and [In]. *) -Lemma MapsTo_In : forall elt k e (m:t elt), MapsTo k e m -> In k m. +Lemma MapsTo_In : forall k e m, MapsTo k e m -> In k m. Proof. induction 1; auto. Qed. Hint Resolve MapsTo_In. -Lemma In_MapsTo : forall elt k (m:t elt), In k m -> exists e, MapsTo k e m. +Lemma In_MapsTo : forall k m, In k m -> exists e, MapsTo k e m. Proof. induction 1; try destruct IHIn as (e,He); exists e; auto. Qed. -Lemma In_alt : forall elt k (m:t elt), In0 k m <-> In k m. +Lemma In_alt : forall k m, In0 k m <-> In k m. Proof. split. intros (e,H); eauto. @@ -222,64 +582,70 @@ Proof. Qed. Lemma MapsTo_1 : - forall elt (m:t elt) x y e, X.eq x y -> MapsTo x e m -> MapsTo y e m. + forall m x y e, X.eq x y -> MapsTo x e m -> MapsTo y e m. Proof. induction m; simpl; intuition_in; eauto. Qed. Hint Immediate MapsTo_1. Lemma In_1 : - forall elt (m:t elt) x y, X.eq x y -> In x m -> In y m. + forall m x y, X.eq x y -> In x m -> In y m. Proof. - intros elt m x y; induction m; simpl; intuition_in; eauto. + intros m x y; induction m; simpl; intuition_in; eauto. Qed. +Lemma In_node_iff : + forall l x e r h y, + In y (Node l x e r h) <-> In y l \/ X.eq y x \/ In y r. +Proof. + intuition_in. +Qed. (** Results about [lt_tree] and [gt_tree] *) -Lemma lt_leaf : forall elt x, lt_tree x (Leaf elt). +Lemma lt_leaf : forall x, lt_tree x (Leaf elt). Proof. unfold lt_tree in |- *; intros; intuition_in. Qed. -Lemma gt_leaf : forall elt x, gt_tree x (Leaf elt). +Lemma gt_leaf : forall x, gt_tree x (Leaf elt). Proof. unfold gt_tree in |- *; intros; intuition_in. Qed. -Lemma lt_tree_node : forall elt x y (l:t elt) r e h, +Lemma lt_tree_node : forall x y l r e h, lt_tree x l -> lt_tree x r -> X.lt y x -> lt_tree x (Node l y e r h). Proof. - unfold lt_tree in *; firstorder_in; order. + unfold lt_tree in *; intuition_in; order. Qed. -Lemma gt_tree_node : forall elt x y (l:t elt) r e h, +Lemma gt_tree_node : forall x y l r e h, gt_tree x l -> gt_tree x r -> X.lt x y -> gt_tree x (Node l y e r h). Proof. - unfold gt_tree in *; firstorder_in; order. + unfold gt_tree in *; intuition_in; order. Qed. Hint Resolve lt_leaf gt_leaf lt_tree_node gt_tree_node. -Lemma lt_left : forall elt x y (l: t elt) r e h, +Lemma lt_left : forall x y l r e h, lt_tree x (Node l y e r h) -> lt_tree x l. Proof. intuition_in. Qed. -Lemma lt_right : forall elt x y (l:t elt) r e h, +Lemma lt_right : forall x y l r e h, lt_tree x (Node l y e r h) -> lt_tree x r. Proof. intuition_in. Qed. -Lemma gt_left : forall elt x y (l:t elt) r e h, +Lemma gt_left : forall x y l r e h, gt_tree x (Node l y e r h) -> gt_tree x l. Proof. intuition_in. Qed. -Lemma gt_right : forall elt x y (l:t elt) r e h, +Lemma gt_right : forall x y l r e h, gt_tree x (Node l y e r h) -> gt_tree x r. Proof. intuition_in. @@ -288,731 +654,639 @@ Qed. Hint Resolve lt_left lt_right gt_left gt_right. Lemma lt_tree_not_in : - forall elt x (t : t elt), lt_tree x t -> ~ In x t. + forall x m, lt_tree x m -> ~ In x m. Proof. intros; intro; generalize (H _ H0); order. Qed. Lemma lt_tree_trans : - forall elt x y, X.lt x y -> forall (t:t elt), lt_tree x t -> lt_tree y t. + forall x y, X.lt x y -> forall m, lt_tree x m -> lt_tree y m. Proof. - firstorder eauto. + eauto. Qed. Lemma gt_tree_not_in : - forall elt x (t : t elt), gt_tree x t -> ~ In x t. + forall x m, gt_tree x m -> ~ In x m. Proof. intros; intro; generalize (H _ H0); order. Qed. Lemma gt_tree_trans : - forall elt x y, X.lt y x -> forall (t:t elt), gt_tree x t -> gt_tree y t. + forall x y, X.lt y x -> forall m, gt_tree x m -> gt_tree y m. Proof. - firstorder eauto. + eauto. Qed. Hint Resolve lt_tree_not_in lt_tree_trans gt_tree_not_in gt_tree_trans. -(** Results about [avl] *) +(** * Empty map *) -Lemma avl_node : forall elt x e (l:t elt) r, - avl l -> - avl r -> - -(2) <= height l - height r <= 2 -> - avl (Node l x e r (max (height l) (height r) + 1)). +Definition Empty m := forall (a:key)(e:elt) , ~ MapsTo a e m. + +Lemma empty_bst : bst (empty elt). Proof. - intros; auto. + unfold empty; auto. Qed. -Hint Resolve avl_node. -(** * Helper functions *) - -(** [create l x r] creates a node, assuming [l] and [r] - to be balanced and [|height l - height r| <= 2]. *) +Lemma empty_1 : Empty (empty elt). +Proof. + unfold empty, Empty; intuition_in. +Qed. -Definition create elt (l:t elt) x e r := - Node l x e r (max (height l) (height r) + 1). +(** * Emptyness test *) -Lemma create_bst : - forall elt (l:t elt) x e r, bst l -> bst r -> lt_tree x l -> gt_tree x r -> - bst (create l x e r). +Lemma is_empty_1 : forall m, Empty m -> is_empty m = true. Proof. - unfold create; auto. + destruct m as [|r x e l h]; simpl; auto. + intro H; elim (H x e); auto. Qed. -Hint Resolve create_bst. -Lemma create_avl : - forall elt (l:t elt) x e r, avl l -> avl r -> -(2) <= height l - height r <= 2 -> - avl (create l x e r). -Proof. - unfold create; auto. +Lemma is_empty_2 : forall m, is_empty m = true -> Empty m. +Proof. + destruct m; simpl; intros; try discriminate; red; intuition_in. Qed. -Lemma create_height : - forall elt (l:t elt) x e r, avl l -> avl r -> -(2) <= height l - height r <= 2 -> - height (create l x e r) = max (height l) (height r) + 1. -Proof. - unfold create; intros; auto. +(** * Appartness *) + +Lemma mem_1 : forall m x, bst m -> In x m -> mem x m = true. +Proof. + intros m x; functional induction (mem x m); auto; intros; clearf; + inv bst; intuition_in; order. Qed. -Lemma create_in : - forall elt (l:t elt) x e r y, In y (create l x e r) <-> X.eq y x \/ In y l \/ In y r. -Proof. - unfold create; split; [ inversion_clear 1 | ]; intuition. +Lemma mem_2 : forall m x, mem x m = true -> In x m. +Proof. + intros m x; functional induction (mem x m); auto; intros; discriminate. Qed. -(** trick for emulating [assert false] in Coq *) +Lemma find_1 : forall m x e, bst m -> MapsTo x e m -> find x m = Some e. +Proof. + intros m x; functional induction (find x m); auto; intros; clearf; + inv bst; intuition_in; simpl; auto; + try solve [order | absurd (X.lt x y); eauto | absurd (X.lt y x); eauto]. +Qed. -Notation assert_false := Leaf. +Lemma find_2 : forall m x e, find x m = Some e -> MapsTo x e m. +Proof. + intros m x; functional induction (find x m); subst; intros; clearf; + try discriminate. + constructor 2; auto. + inversion H; auto. + constructor 3; auto. +Qed. -(** [bal l x e r] acts as [create], but performs one step of - rebalancing if necessary, i.e. assumes [|height l - height r| <= 3]. *) +Lemma find_iff : forall m x e, bst m -> + (find x m = Some e <-> MapsTo x e m). +Proof. + split; auto using find_1, find_2. +Qed. -Definition bal elt (l: tree elt) x e r := - let hl := height l in - let hr := height r in - if gt_le_dec hl (hr+2) then - match l with - | Leaf => assert_false _ - | Node ll lx le lr _ => - if ge_lt_dec (height ll) (height lr) then - create ll lx le (create lr x e r) - else - match lr with - | Leaf => assert_false _ - | Node lrl lrx lre lrr _ => - create (create ll lx le lrl) lrx lre (create lrr x e r) - end - end - else - if gt_le_dec hr (hl+2) then - match r with - | Leaf => assert_false _ - | Node rl rx re rr _ => - if ge_lt_dec (height rr) (height rl) then - create (create l x e rl) rx re rr - else - match rl with - | Leaf => assert_false _ - | Node rll rlx rle rlr _ => - create (create l x e rll) rlx rle (create rlr rx re rr) - end - end - else - create l x e r. - -Ltac bal_tac := - intros elt l x e r; - unfold bal; - destruct (gt_le_dec (height l) (height r + 2)); - [ destruct l as [ |ll lx le lr lh]; - [ | destruct (ge_lt_dec (height ll) (height lr)); - [ | destruct lr ] ] - | destruct (gt_le_dec (height r) (height l + 2)); - [ destruct r as [ |rl rx re rr rh]; - [ | destruct (ge_lt_dec (height rr) (height rl)); - [ | destruct rl ] ] - | ] ]; intros. - -Ltac bal_tac_imp := match goal with - | |- context [ assert_false ] => - inv avl; avl_nns; simpl in *; false_omega - | _ => idtac -end. +Lemma find_in : forall m x, find x m <> None -> In x m. +Proof. + intros. + case_eq (find x m); [intros|congruence]. + apply MapsTo_In with e; apply find_2; auto. +Qed. -Lemma bal_bst : forall elt (l:t elt) x e r, bst l -> bst r -> - lt_tree x l -> gt_tree x r -> bst (bal l x e r). +Lemma in_find : forall m x, bst m -> In x m -> find x m <> None. Proof. - bal_tac; - inv bst; repeat apply create_bst; auto; unfold create; - apply lt_tree_node || apply gt_tree_node; auto; - eapply lt_tree_trans || eapply gt_tree_trans || eauto; eauto. + intros. + destruct (In_MapsTo H0) as (d,Hd). + rewrite (find_1 H Hd); discriminate. Qed. -Lemma bal_avl : forall elt (l:t elt) x e r, avl l -> avl r -> - -(3) <= height l - height r <= 3 -> avl (bal l x e r). +Lemma find_in_iff : forall m x, bst m -> + (find x m <> None <-> In x m). Proof. - bal_tac; inv avl; repeat apply create_avl; simpl in *; auto; omega_max. + split; auto using find_in, in_find. Qed. -Lemma bal_height_1 : forall elt (l:t elt) x e r, avl l -> avl r -> - -(3) <= height l - height r <= 3 -> - 0 <= height (bal l x e r) - max (height l) (height r) <= 1. +Lemma not_find_iff : forall m x, bst m -> + (find x m = None <-> ~In x m). Proof. - bal_tac; inv avl; avl_nns; simpl in *; omega_max. + split; intros. + red; intros. + elim (in_find H H1 H0). + case_eq (find x m); [ intros | auto ]. + elim H0; apply find_in; congruence. Qed. -Lemma bal_height_2 : - forall elt (l:t elt) x e r, avl l -> avl r -> -(2) <= height l - height r <= 2 -> - height (bal l x e r) == max (height l) (height r) +1. +Lemma find_find : forall m m' x, + find x m = find x m' <-> + (forall d, find x m = Some d <-> find x m' = Some d). Proof. - bal_tac; inv avl; simpl in *; omega_max. + intros; destruct (find x m); destruct (find x m'); split; intros; + try split; try congruence. + rewrite H; auto. + symmetry; rewrite <- H; auto. + rewrite H; auto. Qed. -Lemma bal_in : forall elt (l:t elt) x e r y, avl l -> avl r -> - (In y (bal l x e r) <-> X.eq y x \/ In y l \/ In y r). +Lemma find_mapsto_equiv : forall m m' x, bst m -> bst m' -> + (find x m = find x m' <-> + (forall d, MapsTo x d m <-> MapsTo x d m')). Proof. - bal_tac; bal_tac_imp; repeat rewrite create_in; intuition_in. + intros m m' x Hm Hm'. + rewrite find_find. + split; intros H d; specialize H with d. + rewrite <- 2 find_iff; auto. + rewrite 2 find_iff; auto. Qed. -Lemma bal_mapsto : forall elt (l:t elt) x e r y e', avl l -> avl r -> - (MapsTo y e' (bal l x e r) <-> MapsTo y e' (create l x e r)). +Lemma find_in_equiv : forall m m' x, bst m -> bst m' -> + find x m = find x m' -> + (In x m <-> In x m'). Proof. - bal_tac; bal_tac_imp; unfold create; intuition_in. + split; intros; apply find_in; [ rewrite <- H1 | rewrite H1 ]; + apply in_find; auto. Qed. -Ltac omega_bal := match goal with - | H:avl ?l, H':avl ?r |- context [ bal ?l ?x ?e ?r ] => - generalize (bal_height_1 x e H H') (bal_height_2 x e H H'); - omega_max - end. +(** * Helper functions *) -(** * Insertion *) +Lemma create_bst : + forall l x e r, bst l -> bst r -> lt_tree x l -> gt_tree x r -> + bst (create l x e r). +Proof. + unfold create; auto. +Qed. +Hint Resolve create_bst. -Function add (elt:Set)(x:key)(e:elt)(s:t elt) { struct s } : t elt := match s with - | Leaf => Node (Leaf _) x e (Leaf _) 1 - | Node l y e' r h => - match X.compare x y with - | LT _ => bal (add x e l) y e' r - | EQ _ => Node l y e r h - | GT _ => bal l y e' (add x e r) - end - end. +Lemma create_in : + forall l x e r y, + In y (create l x e r) <-> X.eq y x \/ In y l \/ In y r. +Proof. + unfold create; split; [ inversion_clear 1 | ]; intuition. +Qed. -Lemma add_avl_1 : forall elt (m:t elt) x e, avl m -> - avl (add x e m) /\ 0 <= height (add x e m) - height m <= 1. -Proof. - intros elt m x e; functional induction (add x e m); intros; inv avl; simpl in *. - intuition; try constructor; simpl; auto; try omega_max. - (* LT *) - destruct IHt; auto. - split. - apply bal_avl; auto; omega_max. - omega_bal. - (* EQ *) - intuition; omega_max. - (* GT *) - destruct IHt; auto. - split. - apply bal_avl; auto; omega_max. - omega_bal. +Lemma bal_bst : forall l x e r, bst l -> bst r -> + lt_tree x l -> gt_tree x r -> bst (bal l x e r). +Proof. + intros l x e r; functional induction (bal l x e r); intros; clearf; + inv bst; repeat apply create_bst; auto; unfold create; try constructor; + (apply lt_tree_node || apply gt_tree_node); auto; + (eapply lt_tree_trans || eapply gt_tree_trans); eauto. Qed. +Hint Resolve bal_bst. -Lemma add_avl : forall elt (m:t elt) x e, avl m -> avl (add x e m). +Lemma bal_in : forall l x e r y, + In y (bal l x e r) <-> X.eq y x \/ In y l \/ In y r. Proof. - intros; generalize (add_avl_1 x e H); intuition. + intros l x e r; functional induction (bal l x e r); intros; clearf; + rewrite !create_in; intuition_in. Qed. -Hint Resolve add_avl. -Lemma add_in : forall elt (m:t elt) x y e, avl m -> - (In y (add x e m) <-> X.eq y x \/ In y m). +Lemma bal_mapsto : forall l x e r y e', + MapsTo y e' (bal l x e r) <-> MapsTo y e' (create l x e r). Proof. - intros elt m x y e; functional induction (add x e m); auto; intros. - intuition_in. - (* LT *) - inv avl. - rewrite bal_in; auto. - rewrite (IHt H0); intuition_in. - (* EQ *) - inv avl. - firstorder_in. - eapply In_1; eauto. - (* GT *) - inv avl. - rewrite bal_in; auto. - rewrite (IHt H1); intuition_in. + intros l x e r; functional induction (bal l x e r); intros; clearf; + unfold assert_false, create; intuition_in. Qed. -Lemma add_bst : forall elt (m:t elt) x e, bst m -> avl m -> bst (add x e m). -Proof. - intros elt m x e; functional induction (add x e m); - intros; inv bst; inv avl; auto; apply bal_bst; auto. - (* lt_tree -> lt_tree (add ...) *) - red; red in H4. - intros. - rewrite (add_in x y0 e H) in H0. - intuition. - eauto. - (* gt_tree -> gt_tree (add ...) *) - red; red in H4. - intros. - rewrite (add_in x y0 e H5) in H0. - intuition. - apply lt_eq with x; auto. +Lemma bal_find : forall l x e r y, + bst l -> bst r -> lt_tree x l -> gt_tree x r -> + find y (bal l x e r) = find y (create l x e r). +Proof. + intros; rewrite find_mapsto_equiv; auto; intros; apply bal_mapsto. Qed. -Lemma add_1 : forall elt (m:t elt) x y e, avl m -> X.eq x y -> MapsTo y e (add x e m). +(** * Insertion *) + +Lemma add_in : forall m x y e, + In y (add x e m) <-> X.eq y x \/ In y m. +Proof. + intros m x y e; functional induction (add x e m); auto; intros; + try (rewrite bal_in, IHt); intuition_in. + apply In_1 with x; auto. +Qed. + +Lemma add_bst : forall m x e, bst m -> bst (add x e m). +Proof. + intros m x e; functional induction (add x e m); intros; + inv bst; try apply bal_bst; auto; + intro z; rewrite add_in; intuition. + apply MX.eq_lt with x; auto. + apply MX.lt_eq with x; auto. +Qed. +Hint Resolve add_bst. + +Lemma add_1 : forall m x y e, X.eq x y -> MapsTo y e (add x e m). Proof. - intros elt m x y e; functional induction (add x e m); - intros; inv bst; inv avl; try rewrite bal_mapsto; unfold create; eauto. -Qed. + intros m x y e; functional induction (add x e m); + intros; inv bst; try rewrite bal_mapsto; unfold create; eauto. +Qed. -Lemma add_2 : forall elt (m:t elt) x y e e', avl m -> ~X.eq x y -> +Lemma add_2 : forall m x y e e', ~X.eq x y -> MapsTo y e m -> MapsTo y e (add x e' m). Proof. - intros elt m x y e e'; induction m; simpl; auto. + intros m x y e e'; induction m; simpl; auto. destruct (X.compare x k); - intros; inv bst; inv avl; try rewrite bal_mapsto; unfold create; auto; + intros; inv bst; try rewrite bal_mapsto; unfold create; auto; inv MapsTo; auto; order. Qed. -Lemma add_3 : forall elt (m:t elt) x y e e', avl m -> ~X.eq x y -> +Lemma add_3 : forall m x y e e', ~X.eq x y -> MapsTo y e (add x e' m) -> MapsTo y e m. Proof. - intros elt m x y e e'; induction m; simpl; auto. - intros; inv avl; inv MapsTo; auto; order. - destruct (X.compare x k); intro; inv avl; + intros m x y e e'; induction m; simpl; auto. + intros; inv MapsTo; auto; order. + destruct (X.compare x k); intro; try rewrite bal_mapsto; auto; unfold create; intros; inv MapsTo; auto; - order. + order. Qed. - -(** * Extraction of minimum binding - - morally, [remove_min] is to be applied to a non-empty tree - [t = Node l x e r h]. Since we can't deal here with [assert false] - for [t=Leaf], we pre-unpack [t] (and forget about [h]). -*) - -Function remove_min (elt:Set)(l:t elt)(x:key)(e:elt)(r:t elt) { struct l } : t elt*(key*elt) := - match l with - | Leaf => (r,(x,e)) - | Node ll lx le lr lh => let (l',m) := (remove_min ll lx le lr : t elt*(key*elt)) in (bal l' x e r, m) - end. - -Lemma remove_min_avl_1 : forall elt (l:t elt) x e r h, avl (Node l x e r h) -> - avl (fst (remove_min l x e r)) /\ - 0 <= height (Node l x e r h) - height (fst (remove_min l x e r)) <= 1. +Lemma add_find : forall m x y e, bst m -> + find y (add x e m) = + match X.compare y x with EQ _ => Some e | _ => find y m end. Proof. - intros elt l x e r; functional induction (remove_min l x e r); simpl in *; intros. - inv avl; simpl in *; split; auto. - avl_nns; omega_max. - (* l = Node *) - inversion_clear H. - destruct (IHp lh); auto. - split; simpl in *. - rewrite_all e1. simpl in *. - apply bal_avl; subst;auto; omega_max. - rewrite_all e1;simpl in *;omega_bal. + intros. + assert (~X.eq x y -> find y (add x e m) = find y m). + intros; rewrite find_mapsto_equiv; auto. + split; eauto using add_2, add_3. + destruct X.compare; try (apply H0; order). + auto using find_1, add_1. Qed. -Lemma remove_min_avl : forall elt (l:t elt) x e r h, avl (Node l x e r h) -> - avl (fst (remove_min l x e r)). -Proof. - intros; generalize (remove_min_avl_1 H); intuition. -Qed. +(** * Extraction of minimum binding *) -Lemma remove_min_in : forall elt (l:t elt) x e r h y, avl (Node l x e r h) -> - (In y (Node l x e r h) <-> - X.eq y (fst (snd (remove_min l x e r))) \/ In y (fst (remove_min l x e r))). +Lemma remove_min_in : forall l x e r h y, + In y (Node l x e r h) <-> + X.eq y (remove_min l x e r)#2#1 \/ In y (remove_min l x e r)#1. Proof. - intros elt l x e r; functional induction (remove_min l x e r); simpl in *; intros. + intros l x e r; functional induction (remove_min l x e r); simpl in *; intros. intuition_in. - (* l = Node *) - inversion_clear H. - generalize (remove_min_avl H0). - - rewrite_all e1; simpl; intros. - rewrite bal_in; auto. - generalize (IHp lh y H0). - intuition. - inversion_clear H7; intuition. + rewrite e0 in *; simpl; intros. + rewrite bal_in, In_node_iff, IHp; intuition. Qed. -Lemma remove_min_mapsto : forall elt (l:t elt) x e r h y e', avl (Node l x e r h) -> - (MapsTo y e' (Node l x e r h) <-> - ((X.eq y (fst (snd (remove_min l x e r))) /\ e' = (snd (snd (remove_min l x e r)))) - \/ MapsTo y e' (fst (remove_min l x e r)))). +Lemma remove_min_mapsto : forall l x e r h y e', + MapsTo y e' (Node l x e r h) <-> + ((X.eq y (remove_min l x e r)#2#1) /\ e' = (remove_min l x e r)#2#2) + \/ MapsTo y e' (remove_min l x e r)#1. Proof. - intros elt l x e r; functional induction (remove_min l x e r); simpl in *; intros. + intros l x e r; functional induction (remove_min l x e r); simpl in *; intros. intuition_in; subst; auto. - (* l = Node *) - inversion_clear H. - generalize (remove_min_avl H0). - rewrite_all e1; simpl; intros. + rewrite e0 in *; simpl; intros. rewrite bal_mapsto; auto; unfold create. - simpl in *;destruct (IHp lh y e'). - auto. + simpl in *;destruct (IHp _x y e'). intuition. - inversion_clear H2; intuition. - inversion_clear H9; intuition. + inversion_clear H1; intuition. + inversion_clear H3; intuition. Qed. -Lemma remove_min_bst : forall elt (l:t elt) x e r h, - bst (Node l x e r h) -> avl (Node l x e r h) -> bst (fst (remove_min l x e r)). +Lemma remove_min_bst : forall l x e r h, + bst (Node l x e r h) -> bst (remove_min l x e r)#1. Proof. - intros elt l x e r; functional induction (remove_min l x e r); simpl in *; intros. + intros l x e r; functional induction (remove_min l x e r); simpl in *; intros. inv bst; auto. inversion_clear H; inversion_clear H0. apply bal_bst; auto. - rewrite_all e1;simpl in *;firstorder. + rewrite e0 in *; simpl in *; apply (IHp _x); auto. intro; intros. - generalize (remove_min_in y H). - rewrite_all e1; simpl in *. + generalize (remove_min_in ll lx ld lr _x y). + rewrite e0; simpl in *. destruct 1. - apply H3; intuition. + apply H2; intuition. Qed. +Hint Resolve remove_min_bst. -Lemma remove_min_gt_tree : forall elt (l:t elt) x e r h, - bst (Node l x e r h) -> avl (Node l x e r h) -> - gt_tree (fst (snd (remove_min l x e r))) (fst (remove_min l x e r)). +Lemma remove_min_gt_tree : forall l x e r h, + bst (Node l x e r h) -> + gt_tree (remove_min l x e r)#2#1 (remove_min l x e r)#1. Proof. - intros elt l x e r; functional induction (remove_min l x e r); simpl in *; intros. + intros l x e r; functional induction (remove_min l x e r); simpl in *; intros. inv bst; auto. - inversion_clear H; inversion_clear H0. + inversion_clear H. intro; intro. - rewrite_all e1;simpl in *. - generalize (IHp lh H1 H); clear H7 H6 IHp. - generalize (remove_min_avl H). - generalize (remove_min_in (fst m) H). - rewrite e1; simpl; intros. - rewrite (bal_in x e y H7 H5) in H0. - destruct H6. - firstorder. - apply lt_eq with x; auto. - apply X.lt_trans with x; auto. -Qed. - -(** * Merging two trees - - [merge t1 t2] builds the union of [t1] and [t2] assuming all elements - of [t1] to be smaller than all elements of [t2], and - [|height t1 - height t2| <= 2]. -*) - -Function merge (elt:Set) (s1 s2 : t elt) : tree elt := match s1,s2 with - | Leaf, _ => s2 - | _, Leaf => s1 - | _, Node l2 x2 e2 r2 h2 => - match remove_min l2 x2 e2 r2 with - (s2',(x,e)) => bal s1 x e s2' - end -end. - -Lemma merge_avl_1 : forall elt (s1 s2:t elt), avl s1 -> avl s2 -> - -(2) <= height s1 - height s2 <= 2 -> - avl (merge s1 s2) /\ - 0<= height (merge s1 s2) - max (height s1) (height s2) <=1. -Proof. - intros elt s1 s2; functional induction (merge s1 s2); simpl in *; intros. - split; auto; avl_nns; omega_max. - destruct s1;try contradiction;clear y. - split; auto; avl_nns; simpl in *; omega_max. - destruct s1;try contradiction;clear y. - generalize (remove_min_avl_1 H0). - rewrite e3; simpl;destruct 1. - split. - apply bal_avl; auto. - simpl; omega_max. - omega_bal. + rewrite e0 in *;simpl in *. + generalize (IHp _x H0). + generalize (remove_min_in ll lx ld lr _x m#1). + rewrite e0; simpl; intros. + rewrite (bal_in l' x d r y) in H. + assert (In m#1 (Node ll lx ld lr _x)) by (rewrite H4; auto); clear H4. + assert (X.lt m#1 x) by order. + decompose [or] H; order. +Qed. +Hint Resolve remove_min_gt_tree. + +Lemma remove_min_find : forall l x e r h y, + bst (Node l x e r h) -> + find y (Node l x e r h) = + match X.compare y (remove_min l x e r)#2#1 with + | LT _ => None + | EQ _ => Some (remove_min l x e r)#2#2 + | GT _ => find y (remove_min l x e r)#1 + end. +Proof. + intros. + destruct X.compare. + rewrite not_find_iff; auto. + rewrite remove_min_in; red; destruct 1 as [H'|H']; [ order | ]. + generalize (remove_min_gt_tree H H'); order. + apply find_1; auto. + rewrite remove_min_mapsto; auto. + rewrite find_mapsto_equiv; eauto; intros. + rewrite remove_min_mapsto; intuition; order. Qed. -Lemma merge_avl : forall elt (s1 s2:t elt), avl s1 -> avl s2 -> - -(2) <= height s1 - height s2 <= 2 -> avl (merge s1 s2). -Proof. - intros; generalize (merge_avl_1 H H0 H1); intuition. -Qed. +(** * Merging two trees *) -Lemma merge_in : forall elt (s1 s2:t elt) y, bst s1 -> avl s1 -> bst s2 -> avl s2 -> - (In y (merge s1 s2) <-> In y s1 \/ In y s2). +Lemma merge_in : forall m1 m2 y, bst m1 -> bst m2 -> + (In y (merge m1 m2) <-> In y m1 \/ In y m2). Proof. - intros elt s1 s2; functional induction (merge s1 s2);intros. + intros m1 m2; functional induction (merge m1 m2);intros; + try factornode _x _x0 _x1 _x2 _x3 as m1. intuition_in. intuition_in. - destruct s1;try contradiction;clear y. -(* rewrite H_eq_2; rewrite H_eq_2 in H_eq_1; clear H_eq_2. *) - replace s2' with (fst (remove_min l2 x2 e2 r2)); [|rewrite e3; auto]. - rewrite bal_in; auto. - generalize (remove_min_avl H2); rewrite e3; simpl; auto. - generalize (remove_min_in y0 H2); rewrite e3; simpl; intro. - rewrite H3; intuition. + rewrite bal_in, remove_min_in, e1; simpl; intuition. Qed. -Lemma merge_mapsto : forall elt (s1 s2:t elt) y e, bst s1 -> avl s1 -> bst s2 -> avl s2 -> - (MapsTo y e (merge s1 s2) <-> MapsTo y e s1 \/ MapsTo y e s2). +Lemma merge_mapsto : forall m1 m2 y e, bst m1 -> bst m2 -> + (MapsTo y e (merge m1 m2) <-> MapsTo y e m1 \/ MapsTo y e m2). Proof. - intros elt s1 s2; functional induction (@merge elt s1 s2); intros. + intros m1 m2; functional induction (merge m1 m2); intros; + try factornode _x _x0 _x1 _x2 _x3 as m1. intuition_in. intuition_in. - destruct s1;try contradiction;clear y. - replace s2' with (fst (remove_min l2 x2 e2 r2)); [|rewrite e3; auto]. - rewrite bal_mapsto; auto; unfold create. - generalize (remove_min_avl H2); rewrite e3; simpl; auto. - generalize (remove_min_mapsto y0 e H2); rewrite e3; simpl; intro. - rewrite H3; intuition (try subst; auto). - inversion_clear H3; intuition. + rewrite bal_mapsto, remove_min_mapsto, e1; simpl; auto. + unfold create. + intuition; subst; auto. + inversion_clear H1; intuition. Qed. -Lemma merge_bst : forall elt (s1 s2:t elt), bst s1 -> avl s1 -> bst s2 -> avl s2 -> - (forall y1 y2 : key, In y1 s1 -> In y2 s2 -> X.lt y1 y2) -> - bst (merge s1 s2). +Lemma merge_bst : forall m1 m2, bst m1 -> bst m2 -> + (forall y1 y2 : key, In y1 m1 -> In y2 m2 -> X.lt y1 y2) -> + bst (merge m1 m2). Proof. - intros elt s1 s2; functional induction (@merge elt s1 s2); intros; auto. - + intros m1 m2; functional induction (merge m1 m2); intros; auto; + try factornode _x _x0 _x1 _x2 _x3 as m1. apply bal_bst; auto. - destruct s1;try contradiction. - generalize (remove_min_bst H1); rewrite e3; simpl in *; auto. - destruct s1;try contradiction. + generalize (remove_min_bst H0); rewrite e1; simpl in *; auto. intro; intro. - apply H3; auto. - generalize (remove_min_in x H2); rewrite e3; simpl; intuition. - destruct s1;try contradiction. - generalize (remove_min_gt_tree H1); rewrite e3; simpl; auto. -Qed. - -(** * Deletion *) - -Function remove (elt:Set)(x:key)(s:t elt) { struct s } : t elt := match s with - | Leaf => Leaf _ - | Node l y e r h => - match X.compare x y with - | LT _ => bal (remove x l) y e r - | EQ _ => merge l r - | GT _ => bal l y e (remove x r) - end - end. - -Lemma remove_avl_1 : forall elt (s:t elt) x, avl s -> - avl (remove x s) /\ 0 <= height s - height (remove x s) <= 1. -Proof. - intros elt s x; functional induction (@remove elt x s); intros. - split; auto; omega_max. - (* LT *) - inv avl. - destruct (IHt H0). - split. - apply bal_avl; auto. - omega_max. - omega_bal. - (* EQ *) - inv avl. - generalize (merge_avl_1 H0 H1 H2). - intuition omega_max. - (* GT *) - inv avl. - destruct (IHt H1). - split. - apply bal_avl; auto. - omega_max. - omega_bal. + apply H1; auto. + generalize (remove_min_in l2 x2 d2 r2 _x4 x); rewrite e1; simpl; intuition. + generalize (remove_min_gt_tree H0); rewrite e1; simpl; auto. Qed. -Lemma remove_avl : forall elt (s:t elt) x, avl s -> avl (remove x s). -Proof. - intros; generalize (remove_avl_1 x H); intuition. -Qed. -Hint Resolve remove_avl. +(** * Deletion *) -Lemma remove_in : forall elt (s:t elt) x y, bst s -> avl s -> - (In y (remove x s) <-> ~ X.eq y x /\ In y s). +Lemma remove_in : forall m x y, bst m -> + (In y (remove x m) <-> ~ X.eq y x /\ In y m). Proof. - intros elt s x; functional induction (@remove elt x s); simpl; intros. + intros m x; functional induction (remove x m); simpl; intros. intuition_in. (* LT *) - inv avl; inv bst; clear e1. + inv bst; clear e0. rewrite bal_in; auto. generalize (IHt y0 H0); intuition; [ order | order | intuition_in ]. (* EQ *) - inv avl; inv bst; clear e1. + inv bst; clear e0. rewrite merge_in; intuition; [ order | order | intuition_in ]. - elim H9; eauto. + elim H4; eauto. (* GT *) - inv avl; inv bst; clear e1. + inv bst; clear e0. rewrite bal_in; auto. - generalize (IHt y0 H5); intuition; [ order | order | intuition_in ]. + generalize (IHt y0 H1); intuition; [ order | order | intuition_in ]. Qed. -Lemma remove_bst : forall elt (s:t elt) x, bst s -> avl s -> bst (remove x s). +Lemma remove_bst : forall m x, bst m -> bst (remove x m). Proof. - intros elt s x; functional induction (@remove elt x s); simpl; intros. + intros m x; functional induction (remove x m); simpl; intros. auto. (* LT *) - inv avl; inv bst. + inv bst. apply bal_bst; auto. intro; intro. rewrite (remove_in x y0 H0) in H; auto. destruct H; eauto. (* EQ *) - inv avl; inv bst. + inv bst. apply merge_bst; eauto. (* GT *) - inv avl; inv bst. + inv bst. apply bal_bst; auto. intro; intro. - rewrite (remove_in x y0 H5) in H; auto. + rewrite (remove_in x y0 H1) in H; auto. destruct H; eauto. Qed. -Lemma remove_1 : forall elt (m:t elt) x y, bst m -> avl m -> X.eq x y -> ~ In y (remove x m). +Lemma remove_1 : forall m x y, bst m -> X.eq x y -> ~ In y (remove x m). Proof. intros; rewrite remove_in; intuition. -Qed. +Qed. -Lemma remove_2 : forall elt (m:t elt) x y e, bst m -> avl m -> ~X.eq x y -> +Lemma remove_2 : forall m x y e, bst m -> ~X.eq x y -> MapsTo y e m -> MapsTo y e (remove x m). Proof. - intros elt m x y e; induction m; simpl; auto. + intros m x y e; induction m; simpl; auto. destruct (X.compare x k); - intros; inv bst; inv avl; try rewrite bal_mapsto; unfold create; auto; + intros; inv bst; try rewrite bal_mapsto; unfold create; auto; try solve [inv MapsTo; auto]. rewrite merge_mapsto; auto. inv MapsTo; auto; order. Qed. -Lemma remove_3 : forall elt (m:t elt) x y e, bst m -> avl m -> +Lemma remove_3 : forall m x y e, bst m -> MapsTo y e (remove x m) -> MapsTo y e m. Proof. - intros elt m x y e; induction m; simpl; auto. - destruct (X.compare x k); intros Bs Av; inv avl; inv bst; + intros m x y e; induction m; simpl; auto. + destruct (X.compare x k); intros Bs; inv bst; try rewrite bal_mapsto; auto; unfold create. - intros; inv MapsTo; auto. + intros; inv MapsTo; auto. rewrite merge_mapsto; intuition. intros; inv MapsTo; auto. Qed. -Section Elt2. +(** * join *) -Variable elt:Set. +Lemma join_in : forall l x d r y, + In y (join l x d r) <-> X.eq y x \/ In y l \/ In y r. +Proof. + join_tac. + simpl. + rewrite add_in; intuition_in. + rewrite add_in; intuition_in. + rewrite bal_in, Hlr; clear Hlr Hrl; intuition_in. + rewrite bal_in, Hrl; clear Hlr Hrl; intuition_in. + apply create_in. +Qed. -Notation eqk := (eqk (elt:= elt)). -Notation eqke := (eqke (elt:= elt)). -Notation ltk := (ltk (elt:= elt)). +Lemma join_bst : forall l x d r, bst l -> bst r -> + lt_tree x l -> gt_tree x r -> bst (join l x d r). +Proof. + join_tac; auto; try (simpl; auto; fail); inv bst; apply bal_bst; auto; + clear Hrl Hlr z; intro; intros; rewrite join_in in *. + intuition; [ apply MX.lt_eq with x | ]; eauto. + intuition; [ apply MX.eq_lt with x | ]; eauto. +Qed. +Hint Resolve join_bst. -(** * Empty map *) +Lemma join_find : forall l x d r y, + bst l -> bst r -> lt_tree x l -> gt_tree x r -> + find y (join l x d r) = find y (create l x d r). +Proof. + join_tac; auto; inv bst; + simpl (join (Leaf elt)); + try (assert (X.lt lx x) by auto); + try (assert (X.lt x rx) by auto); + rewrite ?add_find, ?bal_find; auto. -Definition Empty m := forall (a : key)(e:elt) , ~ MapsTo a e m. + simpl; destruct X.compare; auto. + rewrite not_find_iff; auto; intro; order. -Definition empty := (Leaf elt). + simpl; repeat (destruct X.compare; auto); try (order; fail). + rewrite not_find_iff by auto; intro. + assert (X.lt y x) by auto; order. -Lemma empty_bst : bst empty. + simpl; rewrite Hlr; simpl; auto. + repeat (destruct X.compare; auto); order. + intros u Hu; rewrite join_in in Hu. + destruct Hu as [Hu|[Hu|Hu]]; try generalize (H2 _ Hu); order. + + simpl; rewrite Hrl; simpl; auto. + repeat (destruct X.compare; auto); order. + intros u Hu; rewrite join_in in Hu. + destruct Hu as [Hu|[Hu|Hu]]; order. +Qed. + +(** * split *) + +Lemma split_in_1 : forall m x, bst m -> forall y, + (In y (split x m)#l <-> In y m /\ X.lt y x). Proof. - unfold empty; auto. + intros m x; functional induction (split x m); simpl; intros; + inv bst; try clear e0. + intuition_in. + rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order. + intuition_in; order. + rewrite join_in. + rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order. Qed. -Lemma empty_avl : avl empty. +Lemma split_in_2 : forall m x, bst m -> forall y, + (In y (split x m)#r <-> In y m /\ X.lt x y). Proof. - unfold empty; auto. + intros m x; functional induction (split x m); subst; simpl; intros; + inv bst; try clear e0. + intuition_in. + rewrite join_in. + rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order. + intuition_in; order. + rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order. Qed. -Lemma empty_1 : Empty empty. +Lemma split_in_3 : forall m x, bst m -> + (split x m)#o = find x m. Proof. - unfold empty, Empty; intuition_in. + intros m x; functional induction (split x m); subst; simpl; auto; + intros; inv bst; try clear e0; + destruct X.compare; try (order;fail); rewrite <-IHt, e1; auto. Qed. -(** * Emptyness test *) - -Definition is_empty (s:t elt) := match s with Leaf => true | _ => false end. +Lemma split_bst : forall m x, bst m -> + bst (split x m)#l /\ bst (split x m)#r. +Proof. + intros m x; functional induction (split x m); subst; simpl; intros; + inv bst; try clear e0; try rewrite e1 in *; simpl in *; intuition; + apply join_bst; auto. + intros y0. + generalize (split_in_2 x H0 y0); rewrite e1; simpl; intuition. + intros y0. + generalize (split_in_1 x H1 y0); rewrite e1; simpl; intuition. +Qed. -Lemma is_empty_1 : forall s, Empty s -> is_empty s = true. +Lemma split_lt_tree : forall m x, bst m -> lt_tree x (split x m)#l. Proof. - destruct s as [|r x e l h]; simpl; auto. - intro H; elim (H x e); auto. + intros m x B y Hy; rewrite split_in_1 in Hy; intuition. Qed. -Lemma is_empty_2 : forall s, is_empty s = true -> Empty s. -Proof. - destruct s; simpl; intros; try discriminate; red; intuition_in. +Lemma split_gt_tree : forall m x, bst m -> gt_tree x (split x m)#r. +Proof. + intros m x B y Hy; rewrite split_in_2 in Hy; intuition. Qed. -(** * Appartness *) +Lemma split_find : forall m x y, bst m -> + find y m = match X.compare y x with + | LT _ => find y (split x m)#l + | EQ _ => (split x m)#o + | GT _ => find y (split x m)#r + end. +Proof. + intros m x; functional induction (split x m); subst; simpl; intros; + inv bst; try clear e0; try rewrite e1 in *; simpl in *; + [ destruct X.compare; auto | .. ]; + try match goal with E:split ?x ?t = _, B:bst ?t |- _ => + generalize (split_in_1 x B)(split_in_2 x B)(split_bst x B); + rewrite E; simpl; destruct 3 end. -(** The [mem] function is deciding appartness. It exploits the [bst] property - to achieve logarithmic complexity. *) + rewrite join_find, IHt; auto; clear IHt; simpl. + repeat (destruct X.compare; auto); order. + intro y1; rewrite H4; intuition. -Function mem (x:key)(m:t elt) { struct m } : bool := - match m with - | Leaf => false - | Node l y e r _ => match X.compare x y with - | LT _ => mem x l - | EQ _ => true - | GT _ => mem x r - end - end. -Implicit Arguments mem. + repeat (destruct X.compare; auto); order. -Lemma mem_1 : forall s x, bst s -> In x s -> mem x s = true. -Proof. - intros s x. - functional induction (mem x s); inversion_clear 1; auto. - intuition_in. - intuition_in; firstorder; absurd (X.lt x y); eauto. - intuition_in; firstorder; absurd (X.lt y x); eauto. + rewrite join_find, IHt; auto; clear IHt; simpl. + repeat (destruct X.compare; auto); order. + intros y1; rewrite H; intuition. Qed. -Lemma mem_2 : forall s x, mem x s = true -> In x s. -Proof. - intros s x. - functional induction (mem x s); firstorder; intros; try discriminate. -Qed. - -Function find (x:key)(m:t elt) { struct m } : option elt := - match m with - | Leaf => None - | Node l y e r _ => match X.compare x y with - | LT _ => find x l - | EQ _ => Some e - | GT _ => find x r - end - end. +(** * Concatenation *) -Lemma find_1 : forall m x e, bst m -> MapsTo x e m -> find x m = Some e. -Proof. - intros m x e. - functional induction (find x m); inversion_clear 1; auto. +Lemma concat_in : forall m1 m2 y, + In y (concat m1 m2) <-> In y m1 \/ In y m2. +Proof. + intros m1 m2; functional induction (concat m1 m2); intros; + try factornode _x _x0 _x1 _x2 _x3 as m1. + intuition_in. intuition_in. - intuition_in; firstorder; absurd (X.lt x y); eauto. - intuition_in; auto. - absurd (X.lt x y); eauto. - absurd (X.lt y x); eauto. - intuition_in; firstorder; absurd (X.lt y x); eauto. + rewrite join_in, remove_min_in, e1; simpl; intuition. Qed. -Lemma find_2 : forall m x e, find x m = Some e -> MapsTo x e m. -Proof. - intros m x. - functional induction (find x m); subst;firstorder; intros; try discriminate. - inversion H; subst; auto. -Qed. - -(** An all-in-one spec for [add] used later in the naive [map2] *) - -Lemma add_spec : forall m x y e , bst m -> avl m -> - find x (add y e m) = if eq_dec x y then Some e else find x m. -Proof. -intros. -destruct (eq_dec x y). -apply find_1. -apply add_bst; auto. -eapply MapsTo_1 with y; eauto. -apply add_1; auto. -case_eq (find x m); intros. -apply find_1. -apply add_bst; auto. -apply add_2; auto. -apply find_2; auto. -case_eq (find x (add y e m)); auto; intros. -rewrite <- H1; symmetry. -apply find_1; auto. -eapply add_3; eauto. -apply find_2; eauto. +Lemma concat_bst : forall m1 m2, bst m1 -> bst m2 -> + (forall y1 y2, In y1 m1 -> In y2 m2 -> X.lt y1 y2) -> + bst (concat m1 m2). +Proof. + intros m1 m2; functional induction (concat m1 m2); intros; auto; + try factornode _x _x0 _x1 _x2 _x3 as m1. + apply join_bst; auto. + change (bst (m2',xd)#1); rewrite <-e1; eauto. + intros y Hy. + apply H1; auto. + rewrite remove_min_in, e1; simpl; auto. + change (gt_tree (m2',xd)#2#1 (m2',xd)#1); rewrite <-e1; eauto. Qed. +Hint Resolve concat_bst. -(** * Elements *) +Lemma concat_find : forall m1 m2 y, bst m1 -> bst m2 -> + (forall y1 y2, In y1 m1 -> In y2 m2 -> X.lt y1 y2) -> + find y (concat m1 m2) = + match find y m2 with Some d => Some d | None => find y m1 end. +Proof. + intros m1 m2; functional induction (concat m1 m2); intros; auto; + try factornode _x _x0 _x1 _x2 _x3 as m1. + simpl; destruct (find y m2); auto. -(** [elements_tree_aux acc t] catenates the elements of [t] in infix - order to the list [acc] *) + generalize (remove_min_find y H0)(remove_min_in l2 x2 d2 r2 _x4) + (remove_min_bst H0)(remove_min_gt_tree H0); + rewrite e1; simpl fst; simpl snd; intros. + + inv bst. + rewrite H2, join_find; auto; clear H2. + simpl; destruct X.compare; simpl; auto. + destruct (find y m2'); auto. + symmetry; rewrite not_find_iff; auto; intro. + apply (MX.lt_not_gt l); apply H1; auto; rewrite H3; auto. -Fixpoint elements_aux (acc : list (key*elt)) (t : t elt) {struct t} : list (key*elt) := - match t with - | Leaf => acc - | Node l x e r _ => elements_aux ((x,e) :: elements_aux acc r) l - end. + intros z Hz; apply H1; auto; rewrite H3; auto. +Qed. -(** then [elements] is an instanciation with an empty [acc] *) -Definition elements := elements_aux nil. +(** * Elements *) -Lemma elements_aux_mapsto : forall s acc x e, +Notation eqk := (PX.eqk (elt:= elt)). +Notation eqke := (PX.eqke (elt:= elt)). +Notation ltk := (PX.ltk (elt:= elt)). + +Lemma elements_aux_mapsto : forall (s:t elt) acc x e, InA eqke (x,e) (elements_aux acc s) <-> MapsTo x e s \/ InA eqke (x,e) acc. Proof. induction s as [ | l Hl x e r Hr h ]; simpl; auto. @@ -1025,13 +1299,13 @@ Proof. destruct H0; simpl in *; subst; intuition. Qed. -Lemma elements_mapsto : forall s x e, InA eqke (x,e) (elements s) <-> MapsTo x e s. +Lemma elements_mapsto : forall (s:t elt) x e, InA eqke (x,e) (elements s) <-> MapsTo x e s. Proof. intros; generalize (elements_aux_mapsto s nil x e); intuition. inversion_clear H0. Qed. -Lemma elements_in : forall s x, L.PX.In x (elements s) <-> In x s. +Lemma elements_in : forall (s:t elt) x, L.PX.In x (elements s) <-> In x s. Proof. intros. unfold L.PX.In. @@ -1043,7 +1317,7 @@ Proof. unfold L.PX.MapsTo; rewrite elements_mapsto; auto. Qed. -Lemma elements_aux_sort : forall s acc, bst s -> sort ltk acc -> +Lemma elements_aux_sort : forall (s:t elt) acc, bst s -> sort ltk acc -> (forall x e y, InA eqke (x,e) acc -> In y s -> X.lt y x) -> sort ltk (elements_aux acc s). Proof. @@ -1052,7 +1326,7 @@ Proof. apply Hl; auto. constructor. apply Hr; eauto. - apply (InA_InfA (eqke_refl (elt:=elt))); intros (y',e') H6. + apply (InA_InfA (PX.eqke_refl (elt:=elt))); intros (y',e') H6. destruct (elements_aux_mapsto r acc y' e'); intuition. red; simpl; eauto. red; simpl; eauto. @@ -1070,20 +1344,49 @@ Proof. Qed. Hint Resolve elements_sort. +Lemma elements_nodup : forall s : t elt, bst s -> NoDupA eqk (elements s). +Proof. + intros; apply PX.Sort_NoDupA; auto. +Qed. -(** * Fold *) +Lemma elements_aux_cardinal : + forall (m:t elt) acc, (length acc + cardinal m)%nat = length (elements_aux acc m). +Proof. + simple induction m; simpl; intuition. + rewrite <- H; simpl. + rewrite <- H0; omega. +Qed. -Fixpoint fold (A : Set) (f : key -> elt -> A -> A)(s : t elt) {struct s} : A -> A := - fun a => match s with - | Leaf => a - | Node l x e r _ => fold f r (f x e (fold f l a)) - end. +Lemma elements_cardinal : forall (m:t elt), cardinal m = length (elements m). +Proof. + exact (fun m => elements_aux_cardinal m nil). +Qed. -Definition fold' (A : Set) (f : key -> elt -> A -> A)(s : t elt) := +Lemma elements_app : + forall (s:t elt) acc, elements_aux acc s = elements s ++ acc. +Proof. + induction s; simpl; intros; auto. + rewrite IHs1, IHs2. + unfold elements; simpl. + rewrite 2 IHs1, IHs2, <- !app_nil_end, !app_ass; auto. +Qed. + +Lemma elements_node : + forall (t1 t2:t elt) x e z l, + elements t1 ++ (x,e) :: elements t2 ++ l = + elements (Node t1 x e t2 z) ++ l. +Proof. + unfold elements; simpl; intros. + rewrite !elements_app, <- !app_nil_end, !app_ass; auto. +Qed. + +(** * Fold *) + +Definition fold' (A : Type) (f : key -> elt -> A -> A)(s : t elt) := L.fold f (elements s). Lemma fold_equiv_aux : - forall (A : Set) (s : t elt) (f : key -> elt -> A -> A) (a : A) acc, + forall (A : Type) (s : t elt) (f : key -> elt -> A -> A) (a : A) acc, L.fold f (elements_aux acc s) a = L.fold f acc (fold f s a). Proof. simple induction s. @@ -1095,7 +1398,7 @@ Proof. Qed. Lemma fold_equiv : - forall (A : Set) (s : t elt) (f : key -> elt -> A -> A) (a : A), + forall (A : Type) (s : t elt) (f : key -> elt -> A -> A) (a : A), fold f s a = fold' f s a. Proof. unfold fold', elements in |- *. @@ -1106,8 +1409,8 @@ Proof. Qed. Lemma fold_1 : - forall (s:t elt)(Hs:bst s)(A : Set)(i:A)(f : key -> elt -> A -> A), - fold f s i = fold_left (fun a p => f (fst p) (snd p) a) (elements s) i. + forall (s:t elt)(Hs:bst s)(A : Type)(i:A)(f : key -> elt -> A -> A), + fold f s i = fold_left (fun a p => f p#1 p#2 a) (elements s) i. Proof. intros. rewrite fold_equiv. @@ -1118,288 +1421,93 @@ Qed. (** * Comparison *) -Definition Equal (cmp:elt->elt->bool) m m' := - (forall k, In k m <-> In k m') /\ - (forall k e e', MapsTo k e m -> MapsTo k e' m' -> cmp e e' = true). - -(** ** Enumeration of the elements of a tree *) - -Inductive enumeration : Set := - | End : enumeration - | More : key -> elt -> t elt -> enumeration -> enumeration. - -(** [flatten_e e] returns the list of elements of [e] i.e. the list - of elements actually compared *) +(** [flatten_e e] returns the list of elements of the enumeration [e] + i.e. the list of elements actually compared *) -Fixpoint flatten_e (e : enumeration) : list (key*elt) := match e with +Fixpoint flatten_e (e : enumeration elt) : list (key*elt) := match e with | End => nil | More x e t r => (x,e) :: elements t ++ flatten_e r end. -(** [sorted_e e] expresses that elements in the enumeration [e] are - sorted, and that all trees in [e] are binary search trees. *) - -Inductive In_e (p:key*elt) : enumeration -> Prop := - | InEHd1 : - forall (y : key)(d:elt) (s : t elt) (e : enumeration), - eqke p (y,d) -> In_e p (More y d s e) - | InEHd2 : - forall (y : key) (d:elt) (s : t elt) (e : enumeration), - MapsTo (fst p) (snd p) s -> In_e p (More y d s e) - | InETl : - forall (y : key) (d:elt) (s : t elt) (e : enumeration), - In_e p e -> In_e p (More y d s e). - -Hint Constructors In_e. - -Inductive sorted_e : enumeration -> Prop := - | SortedEEnd : sorted_e End - | SortedEMore : - forall (x : key) (d:elt) (s : t elt) (e : enumeration), - bst s -> - (gt_tree x s) -> - sorted_e e -> - (forall p, In_e p e -> ltk (x,d) p) -> - (forall p, - MapsTo (fst p) (snd p) s -> forall q, In_e q e -> ltk p q) -> - sorted_e (More x d s e). - -Hint Constructors sorted_e. - -Lemma in_flatten_e : - forall p e, InA eqke p (flatten_e e) -> In_e p e. -Proof. - simple induction e; simpl in |- *; intuition. - inversion_clear H. - inversion_clear H0; auto. - elim (InA_app H1); auto. - destruct (elements_mapsto t a b); auto. +Lemma flatten_e_elements : + forall (l:t elt) r x d z e, + elements l ++ flatten_e (More x d r e) = + elements (Node l x d r z) ++ flatten_e e. +Proof. + intros; simpl; apply elements_node. Qed. -Lemma sorted_flatten_e : - forall e : enumeration, sorted_e e -> sort ltk (flatten_e e). +Lemma cons_1 : forall (s:t elt) e, + flatten_e (cons s e) = elements s ++ flatten_e e. Proof. - simple induction e; simpl in |- *; intuition. - apply cons_sort. - apply (SortA_app (eqke_refl (elt:=elt))); inversion_clear H0; auto. - intros; apply H5; auto. - rewrite <- elements_mapsto; auto; destruct x; auto. - apply in_flatten_e; auto. - inversion_clear H0. - apply In_InfA; intros. - intros; elim (in_app_or _ _ _ H0); intuition. - generalize (In_InA (eqke_refl (elt:=elt)) H6). - destruct y; rewrite elements_mapsto; eauto. - apply H4; apply in_flatten_e; auto. - apply In_InA; auto. + induction s; simpl; auto; intros. + rewrite IHs1; apply flatten_e_elements; auto. Qed. -Lemma elements_app : - forall s acc, elements_aux acc s = elements s ++ acc. +(** Proof of correction for the comparison *) + +Variable cmp : elt->elt->bool. + +Definition IfEq b l1 l2 := L.equal cmp l1 l2 = b. + +Lemma cons_IfEq : forall b x1 x2 d1 d2 l1 l2, + X.eq x1 x2 -> cmp d1 d2 = true -> + IfEq b l1 l2 -> + IfEq b ((x1,d1)::l1) ((x2,d2)::l2). Proof. - simple induction s; simpl in |- *; intuition. - rewrite H0. - rewrite H. - unfold elements; simpl. - do 2 rewrite H. - rewrite H0. - repeat rewrite <- app_nil_end. - repeat rewrite app_ass; auto. + unfold IfEq; destruct b; simpl; intros; destruct X.compare; simpl; + try rewrite H0; auto; order. Qed. -Lemma compare_flatten_1 : - forall t1 t2 x e z l, - elements t1 ++ (x,e) :: elements t2 ++ l = - elements (Node t1 x e t2 z) ++ l. +Lemma equal_end_IfEq : forall e2, + IfEq (equal_end e2) nil (flatten_e e2). Proof. - simpl in |- *; unfold elements in |- *; simpl in |- *; intuition. - repeat rewrite elements_app. - repeat rewrite <- app_nil_end. - repeat rewrite app_ass; auto. + destruct e2; red; auto. Qed. -(** key lemma for correctness *) - -Lemma flatten_e_elements : - forall l r x d z e, - elements l ++ flatten_e (More x d r e) = - elements (Node l x d r z) ++ flatten_e e. +Lemma equal_more_IfEq : + forall x1 d1 (cont:enumeration elt -> bool) x2 d2 r2 e2 l, + IfEq (cont (cons r2 e2)) l (elements r2 ++ flatten_e e2) -> + IfEq (equal_more cmp x1 d1 cont (More x2 d2 r2 e2)) ((x1,d1)::l) + (flatten_e (More x2 d2 r2 e2)). Proof. - intros; simpl. - apply compare_flatten_1. + unfold IfEq; simpl; intros; destruct X.compare; simpl; auto. + rewrite <-andb_lazy_alt; f_equal; auto. Qed. -Open Local Scope Z_scope. - -(** termination of [compare_aux] *) - -Fixpoint measure_e_t (s : t elt) : Z := match s with - | Leaf => 0 - | Node l _ _ r _ => 1 + measure_e_t l + measure_e_t r - end. - -Fixpoint measure_e (e : enumeration) : Z := match e with - | End => 0 - | More _ _ s r => 1 + measure_e_t s + measure_e r - end. - -Ltac Measure_e_t := unfold measure_e_t in |- *; fold measure_e_t in |- *. -Ltac Measure_e := unfold measure_e in |- *; fold measure_e in |- *. - -Lemma measure_e_t_0 : forall s : t elt, measure_e_t s >= 0. +Lemma equal_cont_IfEq : forall m1 cont e2 l, + (forall e, IfEq (cont e) l (flatten_e e)) -> + IfEq (equal_cont cmp m1 cont e2) (elements m1 ++ l) (flatten_e e2). Proof. - simple induction s. - simpl in |- *; omega. - intros. - Measure_e_t; omega. + induction m1 as [|l1 Hl1 x1 d1 r1 Hr1 h1]; simpl; intros; auto. + rewrite <- elements_node; simpl. + apply Hl1; auto. + clear e2; intros [|x2 d2 r2 e2]. + simpl; red; auto. + apply equal_more_IfEq. + rewrite <- cons_1; auto. Qed. -Ltac Measure_e_t_0 s := generalize (@measure_e_t_0 s); intro. - -Lemma measure_e_0 : forall e : enumeration, measure_e e >= 0. +Lemma equal_IfEq : forall (m1 m2:t elt), + IfEq (equal cmp m1 m2) (elements m1) (elements m2). Proof. - simple induction e. - simpl in |- *; omega. + intros; unfold equal. + rewrite (app_nil_end (elements m1)). + replace (elements m2) with (flatten_e (cons m2 (End _))) + by (rewrite cons_1; simpl; rewrite <-app_nil_end; auto). + apply equal_cont_IfEq. intros. - Measure_e; Measure_e_t_0 t; omega. + apply equal_end_IfEq; auto. Qed. -Ltac Measure_e_0 e := generalize (@measure_e_0 e); intro. - -(** Induction principle over the sum of the measures for two lists *) +Definition Equivb m m' := + (forall k, In k m <-> In k m') /\ + (forall k e e', MapsTo k e m -> MapsTo k e' m' -> cmp e e' = true). -Definition compare_rec2 : - forall P : enumeration -> enumeration -> Set, - (forall x x' : enumeration, - (forall y y' : enumeration, - measure_e y + measure_e y' < measure_e x + measure_e x' -> P y y') -> - P x x') -> - forall x x' : enumeration, P x x'. +Lemma Equivb_elements : forall s s', + Equivb s s' <-> L.Equivb cmp (elements s) (elements s'). Proof. - intros P H x x'. - apply well_founded_induction_type_2 - with (R := fun yy' xx' : enumeration * enumeration => - measure_e (fst yy') + measure_e (snd yy') < - measure_e (fst xx') + measure_e (snd xx')); auto. - apply Wf_nat.well_founded_lt_compat - with (f := fun xx' : enumeration * enumeration => - Zabs_nat (measure_e (fst xx') + measure_e (snd xx'))). - intros; apply Zabs.Zabs_nat_lt. - Measure_e_0 (fst x0); Measure_e_0 (snd x0); Measure_e_0 (fst y); - Measure_e_0 (snd y); intros; omega. -Qed. - -(** [cons t e] adds the elements of tree [t] on the head of - enumeration [e]. Code: - -let rec cons s e = match s with - | Empty -> e - | Node(l, k, d, r, _) -> cons l (More(k, d, r, e)) -*) - -Definition cons : forall s e, bst s -> sorted_e e -> - (forall x y, MapsTo (fst x) (snd x) s -> In_e y e -> ltk x y) -> - { r : enumeration - | sorted_e r /\ - measure_e r = measure_e_t s + measure_e e /\ - flatten_e r = elements s ++ flatten_e e - }. -Proof. - simple induction s; intuition. - (* s = Leaf *) - exists e; intuition. - (* s = Node t k e t0 z *) - clear H0. - case (H (More k e t0 e0)); clear H; intuition. - inv bst; auto. - constructor; inversion_clear H1; auto. - inversion_clear H0; inv bst; intuition. - destruct y; red; red in H4; simpl in *; intuition. - apply lt_eq with k; eauto. - destruct y; red; simpl in *; intuition. - apply X.lt_trans with k; eauto. - exists x; intuition. - generalize H4; Measure_e; intros; Measure_e_t; omega. - rewrite H5. - apply flatten_e_elements. -Qed. - -Definition equal_aux : - forall (cmp: elt -> elt -> bool)(e1 e2:enumeration), - sorted_e e1 -> sorted_e e2 -> - { L.Equal cmp (flatten_e e1) (flatten_e e2) } + - { ~ L.Equal cmp (flatten_e e1) (flatten_e e2) }. -Proof. - intros cmp e1 e2; pattern e1, e2 in |- *; apply compare_rec2. - simple destruct x; simple destruct x'; intuition. - (* x = x' = End *) - left; unfold L.Equal in |- *; intuition. - inversion H2. - (* x = End x' = More *) - right; simpl in |- *; auto. - destruct 1. - destruct (H2 k). - destruct H5; auto. - exists e; auto. - inversion H5. - (* x = More x' = End *) - right; simpl in |- *; auto. - destruct 1. - destruct (H2 k). - destruct H4; auto. - exists e; auto. - inversion H4. - (* x = More k e t e0, x' = More k0 e3 t0 e4 *) - case (X.compare k k0); intro. - (* k < k0 *) - right. - destruct 1. - clear H3 H. - assert (L.PX.In k (flatten_e (More k0 e3 t0 e4))). - destruct (H2 k). - apply H; simpl; exists e; auto. - destruct H. - generalize (Sort_In_cons_2 (sorted_flatten_e H1) (InA_eqke_eqk H)). - compute. - intuition order. - (* k = k0 *) - case_eq (cmp e e3). - intros EQ. - destruct (@cons t e0) as [c1 (H2,(H3,H4))]; try inversion_clear H0; auto. - destruct (@cons t0 e4) as [c2 (H5,(H6,H7))]; try inversion_clear H1; auto. - destruct (H c1 c2); clear H; intuition. - Measure_e; omega. - left. - rewrite H4 in e6; rewrite H7 in e6. - simpl; rewrite <- L.equal_cons; auto. - apply (sorted_flatten_e H0). - apply (sorted_flatten_e H1). - right. - simpl; rewrite <- L.equal_cons; auto. - apply (sorted_flatten_e H0). - apply (sorted_flatten_e H1). - swap f. - rewrite H4; rewrite H7; auto. - right. - destruct 1. - rewrite (H4 k) in H2; try discriminate; simpl; auto. - (* k > k0 *) - right. - destruct 1. - clear H3 H. - assert (L.PX.In k0 (flatten_e (More k e t e0))). - destruct (H2 k0). - apply H3; simpl; exists e3; auto. - destruct H. - generalize (Sort_In_cons_2 (sorted_flatten_e H0) (InA_eqke_eqk H)). - compute. - intuition order. -Qed. - -Lemma Equal_elements : forall cmp s s', - Equal cmp s s' <-> L.Equal cmp (elements s) (elements s'). -Proof. -unfold Equal, L.Equal; split; split; intros. +unfold Equivb, L.Equivb; split; split; intros. do 2 rewrite elements_in; firstorder. destruct H. apply (H2 k); rewrite <- elements_mapsto; auto. @@ -1408,95 +1516,46 @@ destruct H. apply (H2 k); unfold L.PX.MapsTo; rewrite elements_mapsto; auto. Qed. -Definition equal : forall cmp s s', bst s -> bst s' -> - {Equal cmp s s'} + {~ Equal cmp s s'}. +Lemma equal_Equivb : forall (s s': t elt), bst s -> bst s' -> + (equal cmp s s' = true <-> Equivb s s'). Proof. - intros cmp s1 s2 s1_bst s2_bst; simpl. - destruct (@cons s1 End); auto. - inversion_clear 2. - destruct (@cons s2 End); auto. - inversion_clear 2. - simpl in a; rewrite <- app_nil_end in a. - simpl in a0; rewrite <- app_nil_end in a0. - destruct (@equal_aux cmp x x0); intuition. - left. - rewrite H4 in e; rewrite H5 in e. - rewrite Equal_elements; auto. - right. - swap n. - rewrite H4; rewrite H5. - rewrite <- Equal_elements; auto. + intros s s' B B'. + rewrite Equivb_elements, <- equal_IfEq. + split; [apply L.equal_2|apply L.equal_1]; auto. Qed. -End Elt2. - -Section Elts. - -Variable elt elt' elt'' : Set. +End Elt. Section Map. +Variable elt elt' : Type. Variable f : elt -> elt'. -Fixpoint map (m:t elt) {struct m} : t elt' := - match m with - | Leaf => Leaf _ - | Node l v d r h => Node (map l) v (f d) (map r) h - end. - -Lemma map_height : forall m, height (map m) = height m. -Proof. -destruct m; simpl; auto. -Qed. - -Lemma map_avl : forall m, avl m -> avl (map m). -Proof. -induction m; simpl; auto. -inversion_clear 1; constructor; auto; do 2 rewrite map_height; auto. -Qed. - -Lemma map_1 : forall (m: tree elt)(x:key)(e:elt), - MapsTo x e m -> MapsTo x (f e) (map m). +Lemma map_1 : forall (m: t elt)(x:key)(e:elt), + MapsTo x e m -> MapsTo x (f e) (map f m). Proof. induction m; simpl; inversion_clear 1; auto. Qed. Lemma map_2 : forall (m: t elt)(x:key), - In x (map m) -> In x m. + In x (map f m) -> In x m. Proof. induction m; simpl; inversion_clear 1; auto. Qed. -Lemma map_bst : forall m, bst m -> bst (map m). +Lemma map_bst : forall m, bst m -> bst (map f m). Proof. induction m; simpl; auto. -inversion_clear 1; constructor; auto. -red; intros; apply H2; apply map_2; auto. -red; intros; apply H3; apply map_2; auto. +inversion_clear 1; constructor; auto; + red; auto using map_2. Qed. End Map. -Section Mapi. -Variable f : key -> elt -> elt'. - -Fixpoint mapi (m:t elt) {struct m} : t elt' := - match m with - | Leaf => Leaf _ - | Node l v d r h => Node (mapi l) v (f v d) (mapi r) h - end. - -Lemma mapi_height : forall m, height (mapi m) = height m. -Proof. -destruct m; simpl; auto. -Qed. - -Lemma mapi_avl : forall m, avl m -> avl (mapi m). -Proof. -induction m; simpl; auto. -inversion_clear 1; constructor; auto; do 2 rewrite mapi_height; auto. -Qed. +Section Mapi. +Variable elt elt' : Type. +Variable f : key -> elt -> elt'. Lemma mapi_1 : forall (m: tree elt)(x:key)(e:elt), - MapsTo x e m -> exists y, X.eq y x /\ MapsTo x (f y e) (mapi m). + MapsTo x e m -> exists y, X.eq y x /\ MapsTo x (f y e) (mapi f m). Proof. induction m; simpl; inversion_clear 1; auto. exists k; auto. @@ -1507,198 +1566,242 @@ exists x0; intuition. Qed. Lemma mapi_2 : forall (m: t elt)(x:key), - In x (mapi m) -> In x m. + In x (mapi f m) -> In x m. Proof. induction m; simpl; inversion_clear 1; auto. Qed. -Lemma mapi_bst : forall m, bst m -> bst (mapi m). +Lemma mapi_bst : forall m, bst m -> bst (mapi f m). Proof. induction m; simpl; auto. -inversion_clear 1; constructor; auto. -red; intros; apply H2; apply mapi_2; auto. -red; intros; apply H3; apply mapi_2; auto. +inversion_clear 1; constructor; auto; + red; auto using mapi_2. Qed. End Mapi. -Section Map2. -Variable f : option elt -> option elt' -> option elt''. - -(* Not exactly pretty nor perfect, but should suffice as a first naive implem. - Anyway, map2 isn't in Ocaml... -*) - -Definition anti_elements (l:list (key*elt'')) := L.fold (@add _) l (empty _). +Section Map_option. +Variable elt elt' : Type. +Variable f : key -> elt -> option elt'. +Hypothesis f_compat : forall x x' d, X.eq x x' -> f x d = f x' d. -Definition map2 (m:t elt)(m':t elt') : t elt'' := - anti_elements (L.map2 f (elements m) (elements m')). - -Lemma anti_elements_avl_aux : forall (l:list (key*elt''))(m:t elt''), - avl m -> avl (L.fold (@add _) l m). +Lemma map_option_2 : forall (m:t elt)(x:key), + In x (map_option f m) -> exists d, MapsTo x d m /\ f x d <> None. Proof. -unfold anti_elements; induction l. -simpl; auto. -simpl; destruct a; intros. -apply IHl. -apply add_avl; auto. +intros m; functional induction (map_option f m); simpl; auto; intros. +inversion H. +rewrite join_in in H; destruct H as [H|[H|H]]. +exists d; split; auto; rewrite (f_compat d H), e0; discriminate. +destruct (IHt _ H) as (d0 & ? & ?); exists d0; auto. +destruct (IHt0 _ H) as (d0 & ? & ?); exists d0; auto. +rewrite concat_in in H; destruct H as [H|H]. +destruct (IHt _ H) as (d0 & ? & ?); exists d0; auto. +destruct (IHt0 _ H) as (d0 & ? & ?); exists d0; auto. Qed. -Lemma anti_elements_avl : forall l, avl (anti_elements l). +Lemma map_option_bst : forall m, bst m -> bst (map_option f m). Proof. -unfold anti_elements, empty; intros; apply anti_elements_avl_aux; auto. -Qed. +intros m; functional induction (map_option f m); simpl; auto; intros; + inv bst. +apply join_bst; auto; intros y H; + destruct (map_option_2 H) as (d0 & ? & ?); eauto using MapsTo_In. +apply concat_bst; auto; intros y y' H H'. +destruct (map_option_2 H) as (d0 & ? & ?). +destruct (map_option_2 H') as (d0' & ? & ?). +eapply X.lt_trans with x; eauto using MapsTo_In. +Qed. +Hint Resolve map_option_bst. + +Ltac nonify e := + replace e with (@None elt) by + (symmetry; rewrite not_find_iff; auto; intro; order). + +Lemma map_option_find : forall (m:t elt)(x:key), + bst m -> + find x (map_option f m) = + match (find x m) with Some d => f x d | None => None end. +Proof. +intros m; functional induction (map_option f m); simpl; auto; intros; + inv bst; rewrite join_find || rewrite concat_find; auto; simpl; + try destruct X.compare; simpl; auto. +rewrite (f_compat d e); auto. +intros y H; + destruct (map_option_2 H) as (? & ? & ?); eauto using MapsTo_In. +intros y H; + destruct (map_option_2 H) as (? & ? & ?); eauto using MapsTo_In. + +rewrite <- IHt, IHt0; auto; nonify (find x0 r); auto. +rewrite IHt, IHt0; auto; nonify (find x0 r); nonify (find x0 l); auto. +rewrite (f_compat d e); auto. +rewrite <- IHt0, IHt; auto; nonify (find x0 l); auto. + destruct (find x0 (map_option f r)); auto. + +intros y y' H H'. +destruct (map_option_2 H) as (? & ? & ?). +destruct (map_option_2 H') as (? & ? & ?). +eapply X.lt_trans with x; eauto using MapsTo_In. +Qed. + +End Map_option. + +Section Map2_opt. +Variable elt elt' elt'' : Type. +Variable f0 : key -> option elt -> option elt' -> option elt''. +Variable f : key -> elt -> option elt' -> option elt''. +Variable mapl : t elt -> t elt''. +Variable mapr : t elt' -> t elt''. +Hypothesis f0_f : forall x d o, f x d o = f0 x (Some d) o. +Hypothesis mapl_bst : forall m, bst m -> bst (mapl m). +Hypothesis mapr_bst : forall m', bst m' -> bst (mapr m'). +Hypothesis mapl_f0 : forall x m, bst m -> + find x (mapl m) = + match find x m with Some d => f0 x (Some d) None | None => None end. +Hypothesis mapr_f0 : forall x m', bst m' -> + find x (mapr m') = + match find x m' with Some d' => f0 x None (Some d') | None => None end. +Hypothesis f0_compat : forall x x' o o', X.eq x x' -> f0 x o o' = f0 x' o o'. + +Notation map2_opt := (map2_opt f mapl mapr). + +Lemma map2_opt_2 : forall m m' y, bst m -> bst m' -> + In y (map2_opt m m') -> In y m \/ In y m'. +Proof. +intros m m'; functional induction (map2_opt m m'); intros; + auto; try factornode _x0 _x1 _x2 _x3 _x4 as m2; + try (generalize (split_in_1 x1 H0 y)(split_in_2 x1 H0 y) + (split_bst x1 H0); rewrite e1; simpl; destruct 3; inv bst). + +right; apply find_in. +generalize (in_find (mapr_bst H0) H1); rewrite mapr_f0; auto. +destruct (find y m2); auto; intros; discriminate. + +factornode l1 x1 d1 r1 _x as m1. +left; apply find_in. +generalize (in_find (mapl_bst H) H1); rewrite mapl_f0; auto. +destruct (find y m1); auto; intros; discriminate. + +rewrite join_in in H1; destruct H1 as [H'|[H'|H']]; auto. +destruct (IHt1 y H6 H4 H'); intuition. +destruct (IHt0 y H7 H5 H'); intuition. + +rewrite concat_in in H1; destruct H1 as [H'|H']; auto. +destruct (IHt1 y H6 H4 H'); intuition. +destruct (IHt0 y H7 H5 H'); intuition. +Qed. + +Lemma map2_opt_bst : forall m m', bst m -> bst m' -> + bst (map2_opt m m'). +Proof. +intros m m'; functional induction (map2_opt m m'); intros; + auto; try factornode _x0 _x1 _x2 _x3 _x4 as m2; inv bst; + generalize (split_in_1 x1 H0)(split_in_2 x1 H0)(split_bst x1 H0); + rewrite e1; simpl in *; destruct 3. + +apply join_bst; auto. +intros y Hy; specialize H with y. +destruct (map2_opt_2 H1 H6 Hy); intuition. +intros y Hy; specialize H5 with y. +destruct (map2_opt_2 H2 H7 Hy); intuition. + +apply concat_bst; auto. +intros y y' Hy Hy'; specialize H with y; specialize H5 with y'. +apply X.lt_trans with x1. +destruct (map2_opt_2 H1 H6 Hy); intuition. +destruct (map2_opt_2 H2 H7 Hy'); intuition. +Qed. +Hint Resolve map2_opt_bst. + +Ltac map2_aux := + match goal with + | H : In ?x _ \/ In ?x ?m, + H' : find ?x ?m = find ?x ?m', B:bst ?m, B':bst ?m' |- _ => + destruct H; [ intuition_in; order | + rewrite <-(find_in_equiv B B' H'); auto ] + end. -Lemma anti_elements_bst_aux : forall (l:list (key*elt''))(m:t elt''), - bst m -> avl m -> bst (L.fold (@add _) l m). -Proof. -induction l. -simpl; auto. -simpl; destruct a; intros. -apply IHl. -apply add_bst; auto. -apply add_avl; auto. -Qed. +Ltac nonify t := + match t with (find ?y (map2_opt ?m ?m')) => + replace t with (@None elt''); + [ | symmetry; rewrite not_find_iff; auto; intro; + destruct (@map2_opt_2 m m' y); auto; order ] + end. -Lemma anti_elements_bst : forall l, bst (anti_elements l). -Proof. -unfold anti_elements, empty; intros; apply anti_elements_bst_aux; auto. -Qed. +Lemma map2_opt_1 : forall m m' y, bst m -> bst m' -> + In y m \/ In y m' -> + find y (map2_opt m m') = f0 y (find y m) (find y m'). +Proof. +intros m m'; functional induction (map2_opt m m'); intros; + auto; try factornode _x0 _x1 _x2 _x3 _x4 as m2; + try (generalize (split_in_1 x1 H0)(split_in_2 x1 H0) + (split_in_3 x1 H0)(split_bst x1 H0)(split_find x1 y H0) + (split_lt_tree (x:=x1) H0)(split_gt_tree (x:=x1) H0); + rewrite e1; simpl in *; destruct 4; intros; inv bst; + subst o2; rewrite H7, ?join_find, ?concat_find; auto). + +simpl; destruct H1; [ inversion_clear H1 | ]. +rewrite mapr_f0; auto. +generalize (in_find H0 H1); destruct (find y m2); intuition. + +factornode l1 x1 d1 r1 _x as m1. +destruct H1; [ | inversion_clear H1 ]. +rewrite mapl_f0; auto. +generalize (in_find H H1); destruct (find y m1); intuition. + +simpl; destruct X.compare; auto. +apply IHt1; auto; map2_aux. +rewrite (@f0_compat y x1), <- f0_f; auto. +apply IHt0; auto; map2_aux. +intros z Hz; destruct (@map2_opt_2 l1 l2' z); auto. +intros z Hz; destruct (@map2_opt_2 r1 r2' z); auto. + +destruct X.compare. +nonify (find y (map2_opt r1 r2')). +apply IHt1; auto; map2_aux. +nonify (find y (map2_opt r1 r2')). +nonify (find y (map2_opt l1 l2')). +rewrite (@f0_compat y x1), <- f0_f; auto. +nonify (find y (map2_opt l1 l2')). +rewrite IHt0; auto; [ | map2_aux ]. +destruct (f0 y (find y r1) (find y r2')); auto. +intros y1 y2 Hy1 Hy2; apply X.lt_trans with x1. + destruct (@map2_opt_2 l1 l2' y1); auto. + destruct (@map2_opt_2 r1 r2' y2); auto. +Qed. + +End Map2_opt. -Lemma anti_elements_mapsto_aux : forall (l:list (key*elt'')) m k e, - bst m -> avl m -> NoDupA (eqk (elt:=elt'')) l -> - (forall x, L.PX.In x l -> In x m -> False) -> - (MapsTo k e (L.fold (@add _) l m) <-> L.PX.MapsTo k e l \/ MapsTo k e m). -Proof. -induction l. -simpl; auto. -intuition. -inversion H4. -simpl; destruct a; intros. -rewrite IHl; clear IHl. -apply add_bst; auto. -apply add_avl; auto. -inversion H1; auto. -intros. -inversion_clear H1. -assert (~X.eq x k). - swap H5. - destruct H3. - apply InA_eqA with (x,x0); eauto. -apply (H2 x). -destruct H3; exists x0; auto. -revert H4; do 2 rewrite <- In_alt; destruct 1; exists x0; auto. -eapply add_3; eauto. -intuition. -assert (find k0 (add k e m) = Some e0). - apply find_1; auto. - apply add_bst; auto. -clear H4. -rewrite add_spec in H3; auto. -destruct (eq_dec k0 k). -inversion_clear H3; subst; auto. -right; apply find_2; auto. -inversion_clear H4; auto. -compute in H3; destruct H3. -subst; right; apply add_1; auto. -inversion_clear H1. -destruct (eq_dec k0 k). -destruct (H2 k); eauto. -right; apply add_2; auto. -Qed. - -Lemma anti_elements_mapsto : forall l k e, NoDupA (eqk (elt:=elt'')) l -> - (MapsTo k e (anti_elements l) <-> L.PX.MapsTo k e l). -Proof. -intros. -unfold anti_elements. -rewrite anti_elements_mapsto_aux; auto; unfold empty; auto. -inversion 2. -intuition. -inversion H1. -Qed. +Section Map2. +Variable elt elt' elt'' : Type. +Variable f : option elt -> option elt' -> option elt''. -Lemma map2_avl : forall (m: t elt)(m': t elt'), avl (map2 m m'). +Lemma map2_bst : forall m m', bst m -> bst m' -> bst (map2 f m m'). Proof. -unfold map2; intros; apply anti_elements_avl; auto. +unfold map2; intros. +apply map2_opt_bst with (fun _ => f); auto using map_option_bst; + intros; rewrite map_option_find; auto. Qed. -Lemma map2_bst : forall (m: t elt)(m': t elt'), bst (map2 m m'). +Lemma map2_1 : forall m m' y, bst m -> bst m' -> + In y m \/ In y m' -> find y (map2 f m m') = f (find y m) (find y m'). Proof. -unfold map2; intros; apply anti_elements_bst; auto. -Qed. - -Lemma find_elements : forall (elt:Set)(m: t elt) x, bst m -> - L.find x (elements m) = find x m. -Proof. -intros. -case_eq (find x m); intros. -apply L.find_1. -apply elements_sort; auto. -red; rewrite elements_mapsto. -apply find_2; auto. -case_eq (L.find x (elements m)); auto; intros. -rewrite <- H0; symmetry. -apply find_1; auto. -rewrite <- elements_mapsto. -apply L.find_2; auto. -Qed. - -Lemma find_anti_elements : forall (l: list (key*elt'')) x, sort (@ltk _) l -> - find x (anti_elements l) = L.find x l. -Proof. -intros. -case_eq (L.find x l); intros. -apply find_1. -apply anti_elements_bst; auto. -rewrite anti_elements_mapsto. -apply L.PX.Sort_NoDupA; auto. -apply L.find_2; auto. -case_eq (find x (anti_elements l)); auto; intros. -rewrite <- H0; symmetry. -apply L.find_1; auto. -rewrite <- anti_elements_mapsto. -apply L.PX.Sort_NoDupA; auto. -apply find_2; auto. -Qed. - -Lemma map2_1 : forall (m: t elt)(m': t elt')(x:key), bst m -> bst m' -> - In x m \/ In x m' -> find x (map2 m m') = f (find x m) (find x m'). -Proof. unfold map2; intros. -rewrite find_anti_elements; auto. -rewrite <- find_elements; auto. -rewrite <- find_elements; auto. -apply L.map2_1; auto. -apply elements_sort; auto. -apply elements_sort; auto. -do 2 rewrite elements_in; auto. -apply L.map2_sorted; auto. -apply elements_sort; auto. -apply elements_sort; auto. +rewrite (map2_opt_1 (f0:=fun _ => f)); + auto using map_option_bst; intros; rewrite map_option_find; auto. Qed. -Lemma map2_2 : forall (m: t elt)(m': t elt')(x:key), bst m -> bst m' -> - In x (map2 m m') -> In x m \/ In x m'. +Lemma map2_2 : forall m m' y, bst m -> bst m' -> + In y (map2 f m m') -> In y m \/ In y m'. Proof. unfold map2; intros. -do 2 rewrite <- elements_in. -apply L.map2_2 with (f:=f); auto. -apply elements_sort; auto. -apply elements_sort; auto. -revert H1. -rewrite <- In_alt. -destruct 1. -exists x0. -rewrite <- anti_elements_mapsto; auto. -apply L.PX.Sort_NoDupA; auto. -apply L.map2_sorted; auto. -apply elements_sort; auto. -apply elements_sort; auto. +eapply map2_opt_2 with (f0:=fun _ => f); eauto; intros. + apply map_option_bst; auto. + apply map_option_bst; auto. + rewrite map_option_find; auto. + rewrite map_option_find; auto. Qed. End Map2. -End Elts. +End Proofs. End Raw. (** * Encapsulation @@ -1710,178 +1813,184 @@ Module IntMake (I:Int)(X: OrderedType) <: S with Module E := X. Module E := X. Module Raw := Raw I X. + Import Raw.Proofs. - Record bbst (elt:Set) : Set := - Bbst {this :> Raw.tree elt; is_bst : Raw.bst this; is_avl: Raw.avl this}. + Record bst (elt:Type) := + Bst {this :> Raw.tree elt; is_bst : Raw.bst this}. - Definition t := bbst. + Definition t := bst. Definition key := E.t. Section Elt. - Variable elt elt' elt'': Set. + Variable elt elt' elt'': Type. Implicit Types m : t elt. Implicit Types x y : key. Implicit Types e : elt. - Definition empty : t elt := Bbst (Raw.empty_bst elt) (Raw.empty_avl elt). + Definition empty : t elt := Bst (empty_bst elt). Definition is_empty m : bool := Raw.is_empty m.(this). - Definition add x e m : t elt := - Bbst (Raw.add_bst x e m.(is_bst) m.(is_avl)) (Raw.add_avl x e m.(is_avl)). - Definition remove x m : t elt := - Bbst (Raw.remove_bst x m.(is_bst) m.(is_avl)) (Raw.remove_avl x m.(is_avl)). + Definition add x e m : t elt := Bst (add_bst x e m.(is_bst)). + Definition remove x m : t elt := Bst (remove_bst x m.(is_bst)). Definition mem x m : bool := Raw.mem x m.(this). Definition find x m : option elt := Raw.find x m.(this). - Definition map f m : t elt' := - Bbst (Raw.map_bst f m.(is_bst)) (Raw.map_avl f m.(is_avl)). + Definition map f m : t elt' := Bst (map_bst f m.(is_bst)). Definition mapi (f:key->elt->elt') m : t elt' := - Bbst (Raw.mapi_bst f m.(is_bst)) (Raw.mapi_avl f m.(is_avl)). + Bst (mapi_bst f m.(is_bst)). Definition map2 f m (m':t elt') : t elt'' := - Bbst (Raw.map2_bst f m m') (Raw.map2_avl f m m'). + Bst (map2_bst f m.(is_bst) m'.(is_bst)). Definition elements m : list (key*elt) := Raw.elements m.(this). - Definition fold (A:Set) (f:key->elt->A->A) m i := Raw.fold (A:=A) f m.(this) i. - Definition equal cmp m m' : bool := - if (Raw.equal cmp m.(is_bst) m'.(is_bst)) then true else false. + Definition cardinal m := Raw.cardinal m.(this). + Definition fold (A:Type) (f:key->elt->A->A) m i := Raw.fold (A:=A) f m.(this) i. + Definition equal cmp m m' : bool := Raw.equal cmp m.(this) m'.(this). Definition MapsTo x e m : Prop := Raw.MapsTo x e m.(this). Definition In x m : Prop := Raw.In0 x m.(this). - Definition Empty m : Prop := Raw.Empty m.(this). + Definition Empty m : Prop := Empty m.(this). - Definition eq_key : (key*elt) -> (key*elt) -> Prop := @Raw.PX.eqk elt. - Definition eq_key_elt : (key*elt) -> (key*elt) -> Prop := @Raw.PX.eqke elt. - Definition lt_key : (key*elt) -> (key*elt) -> Prop := @Raw.PX.ltk elt. + Definition eq_key : (key*elt) -> (key*elt) -> Prop := @PX.eqk elt. + Definition eq_key_elt : (key*elt) -> (key*elt) -> Prop := @PX.eqke elt. + Definition lt_key : (key*elt) -> (key*elt) -> Prop := @PX.ltk elt. Lemma MapsTo_1 : forall m x y e, E.eq x y -> MapsTo x e m -> MapsTo y e m. - Proof. intros m; exact (@Raw.MapsTo_1 _ m.(this)). Qed. + Proof. intros m; exact (@MapsTo_1 _ m.(this)). Qed. Lemma mem_1 : forall m x, In x m -> mem x m = true. Proof. - unfold In, mem; intros m x; rewrite Raw.In_alt; simpl; apply Raw.mem_1; auto. + unfold In, mem; intros m x; rewrite In_alt; simpl; apply mem_1; auto. apply m.(is_bst). Qed. Lemma mem_2 : forall m x, mem x m = true -> In x m. Proof. - unfold In, mem; intros m x; rewrite Raw.In_alt; simpl; apply Raw.mem_2; auto. + unfold In, mem; intros m x; rewrite In_alt; simpl; apply mem_2; auto. Qed. Lemma empty_1 : Empty empty. - Proof. exact (@Raw.empty_1 elt). Qed. + Proof. exact (@empty_1 elt). Qed. Lemma is_empty_1 : forall m, Empty m -> is_empty m = true. - Proof. intros m; exact (@Raw.is_empty_1 _ m.(this)). Qed. + Proof. intros m; exact (@is_empty_1 _ m.(this)). Qed. Lemma is_empty_2 : forall m, is_empty m = true -> Empty m. - Proof. intros m; exact (@Raw.is_empty_2 _ m.(this)). Qed. + Proof. intros m; exact (@is_empty_2 _ m.(this)). Qed. Lemma add_1 : forall m x y e, E.eq x y -> MapsTo y e (add x e m). - Proof. intros m x y e; exact (@Raw.add_1 elt _ x y e m.(is_avl)). Qed. + Proof. intros m x y e; exact (@add_1 elt _ x y e). Qed. Lemma add_2 : forall m x y e e', ~ E.eq x y -> MapsTo y e m -> MapsTo y e (add x e' m). - Proof. intros m x y e e'; exact (@Raw.add_2 elt _ x y e e' m.(is_avl)). Qed. + Proof. intros m x y e e'; exact (@add_2 elt _ x y e e'). Qed. Lemma add_3 : forall m x y e e', ~ E.eq x y -> MapsTo y e (add x e' m) -> MapsTo y e m. - Proof. intros m x y e e'; exact (@Raw.add_3 elt _ x y e e' m.(is_avl)). Qed. + Proof. intros m x y e e'; exact (@add_3 elt _ x y e e'). Qed. Lemma remove_1 : forall m x y, E.eq x y -> ~ In y (remove x m). Proof. - unfold In, remove; intros m x y; rewrite Raw.In_alt; simpl; apply Raw.remove_1; auto. + unfold In, remove; intros m x y; rewrite In_alt; simpl; apply remove_1; auto. apply m.(is_bst). - apply m.(is_avl). Qed. Lemma remove_2 : forall m x y e, ~ E.eq x y -> MapsTo y e m -> MapsTo y e (remove x m). - Proof. intros m x y e; exact (@Raw.remove_2 elt _ x y e m.(is_bst) m.(is_avl)). Qed. + Proof. intros m x y e; exact (@remove_2 elt _ x y e m.(is_bst)). Qed. Lemma remove_3 : forall m x y e, MapsTo y e (remove x m) -> MapsTo y e m. - Proof. intros m x y e; exact (@Raw.remove_3 elt _ x y e m.(is_bst) m.(is_avl)). Qed. + Proof. intros m x y e; exact (@remove_3 elt _ x y e m.(is_bst)). Qed. Lemma find_1 : forall m x e, MapsTo x e m -> find x m = Some e. - Proof. intros m x e; exact (@Raw.find_1 elt _ x e m.(is_bst)). Qed. + Proof. intros m x e; exact (@find_1 elt _ x e m.(is_bst)). Qed. Lemma find_2 : forall m x e, find x m = Some e -> MapsTo x e m. - Proof. intros m; exact (@Raw.find_2 elt m.(this)). Qed. + Proof. intros m; exact (@find_2 elt m.(this)). Qed. - Lemma fold_1 : forall m (A : Set) (i : A) (f : key -> elt -> A -> A), + Lemma fold_1 : forall m (A : Type) (i : A) (f : key -> elt -> A -> A), fold f m i = fold_left (fun a p => f (fst p) (snd p) a) (elements m) i. - Proof. intros m; exact (@Raw.fold_1 elt m.(this) m.(is_bst)). Qed. + Proof. intros m; exact (@fold_1 elt m.(this) m.(is_bst)). Qed. Lemma elements_1 : forall m x e, MapsTo x e m -> InA eq_key_elt (x,e) (elements m). Proof. - intros; unfold elements, MapsTo, eq_key_elt; rewrite Raw.elements_mapsto; auto. + intros; unfold elements, MapsTo, eq_key_elt; rewrite elements_mapsto; auto. Qed. Lemma elements_2 : forall m x e, InA eq_key_elt (x,e) (elements m) -> MapsTo x e m. Proof. - intros; unfold elements, MapsTo, eq_key_elt; rewrite <- Raw.elements_mapsto; auto. + intros; unfold elements, MapsTo, eq_key_elt; rewrite <- elements_mapsto; auto. Qed. Lemma elements_3 : forall m, sort lt_key (elements m). - Proof. intros m; exact (@Raw.elements_sort elt m.(this) m.(is_bst)). Qed. + Proof. intros m; exact (@elements_sort elt m.(this) m.(is_bst)). Qed. - Definition Equal cmp m m' := + Lemma elements_3w : forall m, NoDupA eq_key (elements m). + Proof. intros m; exact (@elements_nodup elt m.(this) m.(is_bst)). Qed. + + Lemma cardinal_1 : forall m, cardinal m = length (elements m). + Proof. intro m; exact (@elements_cardinal elt m.(this)). Qed. + + Definition Equal m m' := forall y, find y m = find y m'. + Definition Equiv (eq_elt:elt->elt->Prop) m m' := (forall k, In k m <-> In k m') /\ - (forall k e e', MapsTo k e m -> MapsTo k e' m' -> cmp e e' = true). + (forall k e e', MapsTo k e m -> MapsTo k e' m' -> eq_elt e e'). + Definition Equivb cmp := Equiv (Cmp cmp). - Lemma Equal_Equal : forall cmp m m', Equal cmp m m' <-> Raw.Equal cmp m m'. + Lemma Equivb_Equivb : forall cmp m m', + Equivb cmp m m' <-> Raw.Proofs.Equivb cmp m m'. Proof. - intros; unfold Equal, Raw.Equal, In; intuition. - generalize (H0 k); do 2 rewrite Raw.In_alt; intuition. - generalize (H0 k); do 2 rewrite Raw.In_alt; intuition. - generalize (H0 k); do 2 rewrite <- Raw.In_alt; intuition. - generalize (H0 k); do 2 rewrite <- Raw.In_alt; intuition. - Qed. + intros; unfold Equivb, Equiv, Raw.Proofs.Equivb, In; intuition. + generalize (H0 k); do 2 rewrite In_alt; intuition. + generalize (H0 k); do 2 rewrite In_alt; intuition. + generalize (H0 k); do 2 rewrite <- In_alt; intuition. + generalize (H0 k); do 2 rewrite <- In_alt; intuition. + Qed. Lemma equal_1 : forall m m' cmp, - Equal cmp m m' -> equal cmp m m' = true. + Equivb cmp m m' -> equal cmp m m' = true. Proof. - unfold equal; intros m m' cmp; rewrite Equal_Equal. - destruct (@Raw.equal _ cmp m m'); auto. + unfold equal; intros (m,b) (m',b') cmp; rewrite Equivb_Equivb; + intros; simpl in *; rewrite equal_Equivb; auto. Qed. Lemma equal_2 : forall m m' cmp, - equal cmp m m' = true -> Equal cmp m m'. + equal cmp m m' = true -> Equivb cmp m m'. Proof. - unfold equal; intros; rewrite Equal_Equal. - destruct (@Raw.equal _ cmp m m'); auto; try discriminate. - Qed. + unfold equal; intros (m,b) (m',b') cmp; rewrite Equivb_Equivb; + intros; simpl in *; rewrite <-equal_Equivb; auto. + Qed. End Elt. - Lemma map_1 : forall (elt elt':Set)(m: t elt)(x:key)(e:elt)(f:elt->elt'), + Lemma map_1 : forall (elt elt':Type)(m: t elt)(x:key)(e:elt)(f:elt->elt'), MapsTo x e m -> MapsTo x (f e) (map f m). - Proof. intros elt elt' m x e f; exact (@Raw.map_1 elt elt' f m.(this) x e). Qed. + Proof. intros elt elt' m x e f; exact (@map_1 elt elt' f m.(this) x e). Qed. - Lemma map_2 : forall (elt elt':Set)(m:t elt)(x:key)(f:elt->elt'), In x (map f m) -> In x m. + Lemma map_2 : forall (elt elt':Type)(m:t elt)(x:key)(f:elt->elt'), In x (map f m) -> In x m. Proof. - intros elt elt' m x f; do 2 unfold In in *; do 2 rewrite Raw.In_alt; simpl. - apply Raw.map_2; auto. + intros elt elt' m x f; do 2 unfold In in *; do 2 rewrite In_alt; simpl. + apply map_2; auto. Qed. - Lemma mapi_1 : forall (elt elt':Set)(m: t elt)(x:key)(e:elt) + Lemma mapi_1 : forall (elt elt':Type)(m: t elt)(x:key)(e:elt) (f:key->elt->elt'), MapsTo x e m -> exists y, E.eq y x /\ MapsTo x (f y e) (mapi f m). - Proof. intros elt elt' m x e f; exact (@Raw.mapi_1 elt elt' f m.(this) x e). Qed. - Lemma mapi_2 : forall (elt elt':Set)(m: t elt)(x:key) + Proof. intros elt elt' m x e f; exact (@mapi_1 elt elt' f m.(this) x e). Qed. + Lemma mapi_2 : forall (elt elt':Type)(m: t elt)(x:key) (f:key->elt->elt'), In x (mapi f m) -> In x m. Proof. - intros elt elt' m x f; unfold In in *; do 2 rewrite Raw.In_alt; simpl; apply Raw.mapi_2; auto. - Qed. + intros elt elt' m x f; unfold In in *; do 2 rewrite In_alt; simpl; apply mapi_2; auto. + Qed. - Lemma map2_1 : forall (elt elt' elt'':Set)(m: t elt)(m': t elt') + Lemma map2_1 : forall (elt elt' elt'':Type)(m: t elt)(m': t elt') (x:key)(f:option elt->option elt'->option elt''), In x m \/ In x m' -> find x (map2 f m m') = f (find x m) (find x m'). Proof. unfold find, map2, In; intros elt elt' elt'' m m' x f. - do 2 rewrite Raw.In_alt; intros; simpl; apply Raw.map2_1; auto. + do 2 rewrite In_alt; intros; simpl; apply map2_1; auto. apply m.(is_bst). apply m'.(is_bst). Qed. - Lemma map2_2 : forall (elt elt' elt'':Set)(m: t elt)(m': t elt') + Lemma map2_2 : forall (elt elt' elt'':Type)(m: t elt)(m': t elt') (x:key)(f:option elt->option elt'->option elt''), In x (map2 f m m') -> In x m \/ In x m'. Proof. unfold In, map2; intros elt elt' elt'' m m' x f. - do 3 rewrite Raw.In_alt; intros; simpl in *; eapply Raw.map2_2; eauto. + do 3 rewrite In_alt; intros; simpl in *; eapply map2_2; eauto. apply m.(is_bst). apply m'.(is_bst). Qed. @@ -1891,158 +2000,185 @@ End IntMake. Module IntMake_ord (I:Int)(X: OrderedType)(D : OrderedType) <: Sord with Module Data := D - with Module MapS.E := X. + with Module MapS.E := X. Module Data := D. - Module MapS := IntMake(I)(X). - Import MapS. + Module Import MapS := IntMake(I)(X). + Module LO := FMapList.Make_ord(X)(D). + Module R := Raw. + Module P := Raw.Proofs. + + Definition t := MapS.t D.t. + + Definition cmp e e' := + match D.compare e e' with EQ _ => true | _ => false end. + + (** One step of comparison of elements *) + + Definition compare_more x1 d1 (cont:R.enumeration D.t -> comparison) e2 := + match e2 with + | R.End => Gt + | R.More x2 d2 r2 e2 => + match X.compare x1 x2 with + | EQ _ => match D.compare d1 d2 with + | EQ _ => cont (R.cons r2 e2) + | LT _ => Lt + | GT _ => Gt + end + | LT _ => Lt + | GT _ => Gt + end + end. - Module MD := OrderedTypeFacts(D). - Import MD. + (** Comparison of left tree, middle element, then right tree *) - Module LO := FMapList.Make_ord(X)(D). + Fixpoint compare_cont s1 (cont:R.enumeration D.t -> comparison) e2 := + match s1 with + | R.Leaf => cont e2 + | R.Node l1 x1 d1 r1 _ => + compare_cont l1 (compare_more x1 d1 (compare_cont r1 cont)) e2 + end. + + (** Initial continuation *) + + Definition compare_end (e2:R.enumeration D.t) := + match e2 with R.End => Eq | _ => Lt end. + + (** The complete comparison *) - Definition t := MapS.t D.t. + Definition compare_pure s1 s2 := + compare_cont s1 compare_end (R.cons s2 (Raw.End _)). - Definition cmp e e' := match D.compare e e' with EQ _ => true | _ => false end. + (** Correctness of this comparison *) - Definition elements (m:t) := - LO.MapS.Build_slist (Raw.elements_sort m.(is_bst)). + Definition Cmp c := + match c with + | Eq => LO.eq_list + | Lt => LO.lt_list + | Gt => (fun l1 l2 => LO.lt_list l2 l1) + end. + + Lemma cons_Cmp : forall c x1 x2 d1 d2 l1 l2, + X.eq x1 x2 -> D.eq d1 d2 -> + Cmp c l1 l2 -> Cmp c ((x1,d1)::l1) ((x2,d2)::l2). + Proof. + destruct c; simpl; intros; P.MX.elim_comp; auto. + Qed. + Hint Resolve cons_Cmp. + + Lemma compare_end_Cmp : + forall e2, Cmp (compare_end e2) nil (P.flatten_e e2). + Proof. + destruct e2; simpl; auto. + Qed. + + Lemma compare_more_Cmp : forall x1 d1 cont x2 d2 r2 e2 l, + Cmp (cont (R.cons r2 e2)) l (R.elements r2 ++ P.flatten_e e2) -> + Cmp (compare_more x1 d1 cont (R.More x2 d2 r2 e2)) ((x1,d1)::l) + (P.flatten_e (R.More x2 d2 r2 e2)). + Proof. + simpl; intros; destruct X.compare; simpl; + try destruct D.compare; simpl; auto; P.MX.elim_comp; auto. + Qed. + + Lemma compare_cont_Cmp : forall s1 cont e2 l, + (forall e, Cmp (cont e) l (P.flatten_e e)) -> + Cmp (compare_cont s1 cont e2) (R.elements s1 ++ l) (P.flatten_e e2). + Proof. + induction s1 as [|l1 Hl1 x1 d1 r1 Hr1 h1]; simpl; intros; auto. + rewrite <- P.elements_node; simpl. + apply Hl1; auto. clear e2. intros [|x2 d2 r2 e2]. + simpl; auto. + apply compare_more_Cmp. + rewrite <- P.cons_1; auto. + Qed. + + Lemma compare_Cmp : forall s1 s2, + Cmp (compare_pure s1 s2) (R.elements s1) (R.elements s2). + Proof. + intros; unfold compare_pure. + rewrite (app_nil_end (R.elements s1)). + replace (R.elements s2) with (P.flatten_e (R.cons s2 (R.End _))) by + (rewrite P.cons_1; simpl; rewrite <- app_nil_end; auto). + auto using compare_cont_Cmp, compare_end_Cmp. + Qed. - Definition eq : t -> t -> Prop := - fun m1 m2 => LO.eq (elements m1) (elements m2). + (** The dependent-style [compare] *) - Definition lt : t -> t -> Prop := - fun m1 m2 => LO.lt (elements m1) (elements m2). + Definition eq (m1 m2 : t) := LO.eq_list (elements m1) (elements m2). + Definition lt (m1 m2 : t) := LO.lt_list (elements m1) (elements m2). - Lemma eq_1 : forall m m', Equal cmp m m' -> eq m m'. + Definition compare (s s':t) : Compare lt eq s s'. + Proof. + intros (s,b) (s',b'). + generalize (compare_Cmp s s'). + destruct compare_pure; intros; [apply EQ|apply LT|apply GT]; red; auto. + Defined. + + (* Proofs about [eq] and [lt] *) + + Definition selements (m1 : t) := + LO.MapS.Build_slist (P.elements_sort m1.(is_bst)). + + Definition seq (m1 m2 : t) := LO.eq (selements m1) (selements m2). + Definition slt (m1 m2 : t) := LO.lt (selements m1) (selements m2). + + Lemma eq_seq : forall m1 m2, eq m1 m2 <-> seq m1 m2. + Proof. + unfold eq, seq, selements, elements, LO.eq; intuition. + Qed. + + Lemma lt_slt : forall m1 m2, lt m1 m2 <-> slt m1 m2. + Proof. + unfold lt, slt, selements, elements, LO.lt; intuition. + Qed. + + Lemma eq_1 : forall (m m' : t), Equivb cmp m m' -> eq m m'. Proof. intros m m'. - unfold eq. - rewrite Equal_Equal. - rewrite Raw.Equal_elements. - intros. - apply LO.eq_1. - auto. + rewrite eq_seq; unfold seq. + rewrite Equivb_Equivb. + rewrite P.Equivb_elements. + auto using LO.eq_1. Qed. - Lemma eq_2 : forall m m', eq m m' -> Equal cmp m m'. + Lemma eq_2 : forall m m', eq m m' -> Equivb cmp m m'. Proof. intros m m'. - unfold eq. - rewrite Equal_Equal. - rewrite Raw.Equal_elements. + rewrite eq_seq; unfold seq. + rewrite Equivb_Equivb. + rewrite P.Equivb_elements. intros. generalize (LO.eq_2 H). auto. Qed. - + Lemma eq_refl : forall m : t, eq m m. Proof. - unfold eq; intros; apply LO.eq_refl. + intros; rewrite eq_seq; unfold seq; intros; apply LO.eq_refl. Qed. Lemma eq_sym : forall m1 m2 : t, eq m1 m2 -> eq m2 m1. Proof. - unfold eq; intros; apply LO.eq_sym; auto. + intros m1 m2; rewrite 2 eq_seq; unfold seq; intros; apply LO.eq_sym; auto. Qed. Lemma eq_trans : forall m1 m2 m3 : t, eq m1 m2 -> eq m2 m3 -> eq m1 m3. Proof. - unfold eq; intros; eapply LO.eq_trans; eauto. + intros m1 m2 M3; rewrite 3 eq_seq; unfold seq. + intros; eapply LO.eq_trans; eauto. Qed. Lemma lt_trans : forall m1 m2 m3 : t, lt m1 m2 -> lt m2 m3 -> lt m1 m3. Proof. - unfold lt; intros; eapply LO.lt_trans; eauto. + intros m1 m2 m3; rewrite 3 lt_slt; unfold slt; + intros; eapply LO.lt_trans; eauto. Qed. Lemma lt_not_eq : forall m1 m2 : t, lt m1 m2 -> ~ eq m1 m2. Proof. - unfold lt, eq; intros; apply LO.lt_not_eq; auto. - Qed. - - Import Raw. - - Definition flatten_slist (e:enumeration D.t)(He:sorted_e e) := - LO.MapS.Build_slist (sorted_flatten_e He). - - Open Local Scope Z_scope. - - Definition compare_aux : - forall (e1 e2:enumeration D.t)(He1:sorted_e e1)(He2: sorted_e e2), - Compare LO.lt LO.eq (flatten_slist He1) (flatten_slist He2). - Proof. - intros e1 e2; pattern e1, e2 in |- *; apply compare_rec2. - simple destruct x; simple destruct x'; intuition. - (* x = x' = End *) - constructor 2. - compute; auto. - (* x = End x' = More *) - constructor 1. - compute; auto. - (* x = More x' = End *) - constructor 3. - compute; auto. - (* x = More k t0 t1 e, x' = More k0 t2 t3 e0 *) - case (X.compare k k0); intro. - (* k < k0 *) - constructor 1. - compute; MX.elim_comp; auto. - (* k = k0 *) - destruct (D.compare t t1). - constructor 1. - compute; MX.elim_comp; auto. - destruct (@cons _ t0 e) as [c1 (H2,(H3,H4))]; try inversion_clear He1; auto. - destruct (@cons _ t2 e0) as [c2 (H5,(H6,H7))]; try inversion_clear He2; auto. - assert (measure_e c1 + measure_e c2 < - measure_e (More k t t0 e) + - measure_e (More k0 t1 t2 e0)). - unfold measure_e in *; fold measure_e in *; omega. - destruct (H c1 c2 H0 H2 H5); clear H. - constructor 1. - unfold flatten_slist, LO.lt in *; simpl; simpl in l. - MX.elim_comp. - right; split; auto. - rewrite <- H7; rewrite <- H4; auto. - constructor 2. - unfold flatten_slist, LO.eq in *; simpl; simpl in e5. - MX.elim_comp. - split; auto. - rewrite <- H7; rewrite <- H4; auto. - constructor 3. - unfold flatten_slist, LO.lt in *; simpl; simpl in l. - MX.elim_comp. - right; split; auto. - rewrite <- H7; rewrite <- H4; auto. - constructor 3. - compute; MX.elim_comp; auto. - (* k > k0 *) - constructor 3. - compute; MX.elim_comp; auto. - Qed. - - Definition compare : forall m1 m2, Compare lt eq m1 m2. - Proof. - intros (m1,m1_bst,m1_avl) (m2,m2_bst,m2_avl); simpl. - destruct (@cons _ m1 (End _)) as [x1 (H1,H11)]; auto. - apply SortedEEnd. - inversion_clear 2. - destruct (@cons _ m2 (End _)) as [x2 (H2,H22)]; auto. - apply SortedEEnd. - inversion_clear 2. - simpl in H11; rewrite <- app_nil_end in H11. - simpl in H22; rewrite <- app_nil_end in H22. - destruct (compare_aux H1 H2); intuition. - constructor 1. - unfold lt, LO.lt, IntMake_ord.elements, flatten_slist in *; simpl in *. - rewrite <- H0; rewrite <- H4; auto. - constructor 2. - unfold eq, LO.eq, IntMake_ord.elements, flatten_slist in *; simpl in *. - rewrite <- H0; rewrite <- H4; auto. - constructor 3. - unfold lt, LO.lt, IntMake_ord.elements, flatten_slist in *; simpl in *. - rewrite <- H0; rewrite <- H4; auto. + intros m1 m2; rewrite lt_slt, eq_seq; unfold slt, seq; + intros; apply LO.lt_not_eq; auto. Qed. End IntMake_ord. @@ -2056,3 +2192,4 @@ Module Make_ord (X: OrderedType)(D: OrderedType) <: Sord with Module Data := D with Module MapS.E := X :=IntMake_ord(Z_as_Int)(X)(D). + diff --git a/theories/FSets/FMapFacts.v b/theories/FSets/FMapFacts.v index 0105095a..b307efe3 100644 --- a/theories/FSets/FMapFacts.v +++ b/theories/FSets/FMapFacts.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: FMapFacts.v 8882 2006-05-31 21:55:30Z letouzey $ *) +(* $Id: FMapFacts.v 10782 2008-04-12 16:08:04Z msozeau $ *) (** * Finite maps library *) @@ -15,20 +15,24 @@ different styles: equivalence and boolean equalities. *) -Require Import Bool. -Require Import OrderedType. +Require Import Bool DecidableType DecidableTypeEx OrderedType. Require Export FMapInterface. Set Implicit Arguments. Unset Strict Implicit. -Module Facts (M: S). -Module ME := OrderedTypeFacts M.E. -Import ME. -Import M. -Import Logic. (* to unmask [eq] *) -Import Peano. (* to unmask [lt] *) +(** * Facts about weak maps *) -Lemma MapsTo_fun : forall (elt:Set) m x (e e':elt), +Module WFacts (E:DecidableType)(Import M:WSfun E). + +Notation eq_dec := E.eq_dec. +Definition eqb x y := if eq_dec x y then true else false. + +Lemma eq_bool_alt : forall b b', b=b' <-> (b=true <-> b'=true). +Proof. + destruct b; destruct b'; intuition. +Qed. + +Lemma MapsTo_fun : forall (elt:Type) m x (e e':elt), MapsTo x e m -> MapsTo x e' m -> e=e'. Proof. intros. @@ -36,19 +40,14 @@ generalize (find_1 H) (find_1 H0); clear H H0. intros; rewrite H in H0; injection H0; auto. Qed. -(** * Specifications written using equivalences *) +(** ** Specifications written using equivalences *) Section IffSpec. -Variable elt elt' elt'': Set. +Variable elt elt' elt'': Type. Implicit Type m: t elt. Implicit Type x y z: key. Implicit Type e: elt. -Lemma MapsTo_iff : forall m x y e, E.eq x y -> (MapsTo x e m <-> MapsTo y e m). -Proof. -split; apply MapsTo_1; auto. -Qed. - Lemma In_iff : forall m x y, E.eq x y -> (In x m <-> In y m). Proof. unfold In. @@ -57,12 +56,34 @@ apply (MapsTo_1 H H0); auto. apply (MapsTo_1 (E.eq_sym H) H0); auto. Qed. +Lemma MapsTo_iff : forall m x y e, E.eq x y -> (MapsTo x e m <-> MapsTo y e m). +Proof. +split; apply MapsTo_1; auto. +Qed. + +Lemma mem_in_iff : forall m x, In x m <-> mem x m = true. +Proof. +split; [apply mem_1|apply mem_2]. +Qed. + +Lemma not_mem_in_iff : forall m x, ~In x m <-> mem x m = false. +Proof. +intros; rewrite mem_in_iff; destruct (mem x m); intuition. +Qed. + +Lemma In_dec : forall m x, { In x m } + { ~ In x m }. +Proof. + intros. + generalize (mem_in_iff m x). + destruct (mem x m); [left|right]; intuition. +Qed. + Lemma find_mapsto_iff : forall m x e, MapsTo x e m <-> find x m = Some e. Proof. split; [apply find_1|apply find_2]. Qed. -Lemma not_find_mapsto_iff : forall m x, ~In x m <-> find x m = None. +Lemma not_find_in_iff : forall m x, ~In x m <-> find x m = None. Proof. intros. generalize (find_mapsto_iff m x); destruct (find x m). @@ -74,17 +95,13 @@ intros; intros (e,H1). rewrite H in H1; discriminate. Qed. -Lemma mem_in_iff : forall m x, In x m <-> mem x m = true. -Proof. -split; [apply mem_1|apply mem_2]. -Qed. - -Lemma not_mem_in_iff : forall m x, ~In x m <-> mem x m = false. +Lemma in_find_iff : forall m x, In x m <-> find x m <> None. Proof. -intros; rewrite mem_in_iff; destruct (mem x m); intuition. +intros; rewrite <- not_find_in_iff, mem_in_iff. +destruct mem; intuition. Qed. -Lemma equal_iff : forall m m' cmp, Equal cmp m m' <-> equal cmp m m' = true. +Lemma equal_iff : forall m m' cmp, Equivb cmp m m' <-> equal cmp m m' = true. Proof. split; [apply equal_1|apply equal_2]. Qed. @@ -114,9 +131,9 @@ intros. intuition. destruct (eq_dec x y); [left|right]. split; auto. -symmetry; apply (MapsTo_fun (e':=e) H); auto. +symmetry; apply (MapsTo_fun (e':=e) H); auto with map. split; auto; apply add_3 with x e; auto. -subst; auto. +subst; auto with map. Qed. Lemma add_in_iff : forall m x y e, In y (add x e m) <-> E.eq x y \/ In y m. @@ -204,33 +221,33 @@ split. case_eq (find x m); intros. exists e. split. -apply (MapsTo_fun (m:=map f m) (x:=x)); auto. -apply find_2; auto. +apply (MapsTo_fun (m:=map f m) (x:=x)); auto with map. +apply find_2; auto with map. assert (In x (map f m)) by (exists b; auto). destruct (map_2 H1) as (a,H2). rewrite (find_1 H2) in H; discriminate. intros (a,(H,H0)). -subst b; auto. +subst b; auto with map. Qed. Lemma map_in_iff : forall m x (f : elt -> elt'), In x (map f m) <-> In x m. Proof. -split; intros; eauto. +split; intros; eauto with map. destruct H as (a,H). -exists (f a); auto. +exists (f a); auto with map. Qed. Lemma mapi_in_iff : forall m x (f:key->elt->elt'), In x (mapi f m) <-> In x m. Proof. -split; intros; eauto. +split; intros; eauto with map. destruct H as (a,H). destruct (mapi_1 f H) as (y,(H0,H1)). exists (f y a); auto. Qed. -(* Unfortunately, we don't have simple equivalences for [mapi] +(** Unfortunately, we don't have simple equivalences for [mapi] and [MapsTo]. The only correct one needs compatibility of [f]. *) Lemma mapi_inv : forall m x b (f : key -> elt -> elt'), @@ -240,9 +257,9 @@ Proof. intros; case_eq (find x m); intros. exists e. destruct (@mapi_1 _ _ m x e f) as (y,(H1,H2)). -apply find_2; auto. -exists y; repeat split; auto. -apply (MapsTo_fun (m:=mapi f m) (x:=x)); auto. +apply find_2; auto with map. +exists y; repeat split; auto with map. +apply (MapsTo_fun (m:=mapi f m) (x:=x)); auto with map. assert (In x (mapi f m)) by (exists b; auto). destruct (mapi_2 H1) as (a,H2). rewrite (find_1 H2) in H0; discriminate. @@ -287,11 +304,11 @@ Ltac map_iff := rewrite map_mapsto_iff || rewrite map_in_iff || rewrite mapi_in_iff)). -(** * Specifications written using boolean predicates *) +(** ** Specifications written using boolean predicates *) Section BoolSpec. -Lemma mem_find_b : forall (elt:Set)(m:t elt)(x:key), mem x m = if find x m then true else false. +Lemma mem_find_b : forall (elt:Type)(m:t elt)(x:key), mem x m = if find x m then true else false. Proof. intros. generalize (find_mapsto_iff m x)(mem_in_iff m x); unfold In. @@ -303,7 +320,7 @@ destruct H0 as (e,H0). destruct (H e); intuition discriminate. Qed. -Variable elt elt' elt'' : Set. +Variable elt elt' elt'' : Type. Implicit Types m : t elt. Implicit Types x y z : key. Implicit Types e : elt. @@ -345,24 +362,24 @@ Qed. Lemma add_eq_o : forall m x y e, E.eq x y -> find y (add x e m) = Some e. Proof. -auto. +auto with map. Qed. Lemma add_neq_o : forall m x y e, ~ E.eq x y -> find y (add x e m) = find y m. Proof. intros. -case_eq (find y m); intros; auto. -case_eq (find y (add x e m)); intros; auto. +case_eq (find y m); intros; auto with map. +case_eq (find y (add x e m)); intros; auto with map. rewrite <- H0; symmetry. -apply find_1; apply add_3 with x e; auto. +apply find_1; apply add_3 with x e; auto with map. Qed. -Hint Resolve add_neq_o. +Hint Resolve add_neq_o : map. Lemma add_o : forall m x y e, find y (add x e m) = if eq_dec x y then Some e else find y m. Proof. -intros; destruct (eq_dec x y); auto. +intros; destruct (eq_dec x y); auto with map. Qed. Lemma add_eq_b : forall m x y e, @@ -394,23 +411,23 @@ destruct (find y (remove x m)); auto. destruct 2. exists e; rewrite H0; auto. Qed. -Hint Resolve remove_eq_o. +Hint Resolve remove_eq_o : map. Lemma remove_neq_o : forall m x y, ~ E.eq x y -> find y (remove x m) = find y m. Proof. intros. -case_eq (find y m); intros; auto. -case_eq (find y (remove x m)); intros; auto. +case_eq (find y m); intros; auto with map. +case_eq (find y (remove x m)); intros; auto with map. rewrite <- H0; symmetry. -apply find_1; apply remove_3 with x; auto. +apply find_1; apply remove_3 with x; auto with map. Qed. -Hint Resolve remove_neq_o. +Hint Resolve remove_neq_o : map. Lemma remove_o : forall m x y, find y (remove x m) = if eq_dec x y then None else find y m. Proof. -intros; destruct (eq_dec x y); auto. +intros; destruct (eq_dec x y); auto with map. Qed. Lemma remove_eq_b : forall m x y, @@ -432,7 +449,7 @@ intros; do 2 rewrite mem_find_b; rewrite remove_o; unfold eqb. destruct (eq_dec x y); auto. Qed. -Definition option_map (A:Set)(B:Set)(f:A->B)(o:option A) : option B := +Definition option_map (A B:Type)(f:A->B)(o:option A) : option B := match o with | Some a => Some (f a) | None => None @@ -494,15 +511,15 @@ Proof. intros. case_eq (find x m); intros. rewrite <- H0. -apply map2_1; auto. -left; exists e; auto. +apply map2_1; auto with map. +left; exists e; auto with map. case_eq (find x m'); intros. rewrite <- H0; rewrite <- H1. apply map2_1; auto. -right; exists e; auto. +right; exists e; auto with map. rewrite H. -case_eq (find x (map2 f m m')); intros; auto. -assert (In x (map2 f m m')) by (exists e; auto). +case_eq (find x (map2 f m m')); intros; auto with map. +assert (In x (map2 f m m')) by (exists e; auto with map). destruct (map2_2 H3) as [(e0,H4)|(e0,H4)]. rewrite (find_1 H4) in H0; discriminate. rewrite (find_1 H4) in H1; discriminate. @@ -514,21 +531,18 @@ Proof. intros. assert (forall e, find x m = Some e <-> InA (eq_key_elt (elt:=elt)) (x,e) (elements m)). intros; rewrite <- find_mapsto_iff; apply elements_mapsto_iff. -assert (NoDupA (eq_key (elt:=elt)) (elements m)). - apply SortA_NoDupA with (lt_key (elt:=elt)); unfold eq_key, lt_key; intuition eauto. - destruct y; simpl in *. - apply (E.lt_not_eq H0 H1). - exact (elements_3 m). +assert (H0:=elements_3w m). generalize (fun e => @findA_NoDupA _ _ _ E.eq_sym E.eq_trans eq_dec (elements m) x e H0). -unfold eqb. -destruct (find x m); destruct (findA (fun y : E.t => if eq_dec x y then true else false) (elements m)); +fold (eqb x). +destruct (find x m); destruct (findA (eqb x) (elements m)); simpl; auto; intros. symmetry; rewrite <- H1; rewrite <- H; auto. symmetry; rewrite <- H1; rewrite <- H; auto. rewrite H; rewrite H1; auto. Qed. -Lemma elements_b : forall m x, mem x m = existsb (fun p => eqb x (fst p)) (elements m). +Lemma elements_b : forall m x, + mem x m = existsb (fun p => eqb x (fst p)) (elements m). Proof. intros. generalize (mem_in_iff m x)(elements_in_iff m x) @@ -554,4 +568,1026 @@ Qed. End BoolSpec. +Section Equalities. + +Variable elt:Type. + +(** * Relations between [Equal], [Equiv] and [Equivb]. *) + +(** First, [Equal] is [Equiv] with Leibniz on elements. *) + +Lemma Equal_Equiv : forall (m m' : t elt), + Equal m m' <-> Equiv (@Logic.eq elt) m m'. +Proof. + unfold Equal, Equiv; split; intros. + split; intros. + rewrite in_find_iff, in_find_iff, H; intuition. + rewrite find_mapsto_iff in H0,H1; congruence. + destruct H. + specialize (H y). + specialize (H0 y). + do 2 rewrite in_find_iff in H. + generalize (find_mapsto_iff m y)(find_mapsto_iff m' y). + do 2 destruct find; auto; intros. + f_equal; apply H0; [rewrite H1|rewrite H2]; auto. + destruct H as [H _]; now elim H. + destruct H as [_ H]; now elim H. +Qed. + +(** [Equivb] and [Equiv] and equivalent when [eq_elt] and [cmp] + are related. *) + +Section Cmp. +Variable eq_elt : elt->elt->Prop. +Variable cmp : elt->elt->bool. + +Definition compat_cmp := + forall e e', cmp e e' = true <-> eq_elt e e'. + +Lemma Equiv_Equivb : compat_cmp -> + forall m m', Equiv eq_elt m m' <-> Equivb cmp m m'. +Proof. + unfold Equivb, Equiv, Cmp; intuition. + red in H; rewrite H; eauto. + red in H; rewrite <-H; eauto. +Qed. +End Cmp. + +(** Composition of the two last results: relation between [Equal] + and [Equivb]. *) + +Lemma Equal_Equivb : forall cmp, + (forall e e', cmp e e' = true <-> e = e') -> + forall (m m':t elt), Equal m m' <-> Equivb cmp m m'. +Proof. + intros; rewrite Equal_Equiv. + apply Equiv_Equivb; auto. +Qed. + +Lemma Equal_Equivb_eqdec : + forall eq_elt_dec : (forall e e', { e = e' } + { e <> e' }), + let cmp := fun e e' => if eq_elt_dec e e' then true else false in + forall (m m':t elt), Equal m m' <-> Equivb cmp m m'. +Proof. +intros; apply Equal_Equivb. +unfold cmp; clear cmp; intros. +destruct eq_elt_dec; now intuition. +Qed. + +End Equalities. + +(** * [Equal] is a setoid equality. *) + +Lemma Equal_refl : forall (elt:Type)(m : t elt), Equal m m. +Proof. red; reflexivity. Qed. + +Lemma Equal_sym : forall (elt:Type)(m m' : t elt), + Equal m m' -> Equal m' m. +Proof. unfold Equal; auto. Qed. + +Lemma Equal_trans : forall (elt:Type)(m m' m'' : t elt), + Equal m m' -> Equal m' m'' -> Equal m m''. +Proof. unfold Equal; congruence. Qed. + +Definition Equal_ST : forall elt:Type, Setoid_Theory (t elt) (@Equal _). +Proof. +constructor; red; [apply Equal_refl | apply Equal_sym | apply Equal_trans]. +Qed. + +Add Relation key E.eq + reflexivity proved by E.eq_refl + symmetry proved by E.eq_sym + transitivity proved by E.eq_trans + as KeySetoid. + +Implicit Arguments Equal [[elt]]. + +Add Parametric Relation (elt : Type) : (t elt) Equal + reflexivity proved by (@Equal_refl elt) + symmetry proved by (@Equal_sym elt) + transitivity proved by (@Equal_trans elt) + as EqualSetoid. + +Add Parametric Morphism elt : (@In elt) with signature E.eq ==> Equal ==> iff as In_m. +Proof. +unfold Equal; intros k k' Hk m m' Hm. +rewrite (In_iff m Hk), in_find_iff, in_find_iff, Hm; intuition. +Qed. + +Add Parametric Morphism elt : (@MapsTo elt) + with signature E.eq ==> @Logic.eq _ ==> Equal ==> iff as MapsTo_m. +Proof. +unfold Equal; intros k k' Hk e m m' Hm. +rewrite (MapsTo_iff m e Hk), find_mapsto_iff, find_mapsto_iff, Hm; + intuition. +Qed. + +Add Parametric Morphism elt : (@Empty elt) with signature Equal ==> iff as Empty_m. +Proof. +unfold Empty; intros m m' Hm; intuition. +rewrite <-Hm in H0; eauto. +rewrite Hm in H0; eauto. +Qed. + +Add Parametric Morphism elt : (@is_empty elt) with signature Equal ==> @Logic.eq _ as is_empty_m. +Proof. +intros m m' Hm. +rewrite eq_bool_alt, <-is_empty_iff, <-is_empty_iff, Hm; intuition. +Qed. + +Add Parametric Morphism elt : (@mem elt) with signature E.eq ==> Equal ==> @Logic.eq _ as mem_m. +Proof. +intros k k' Hk m m' Hm. +rewrite eq_bool_alt, <- mem_in_iff, <-mem_in_iff, Hk, Hm; intuition. +Qed. + +Add Parametric Morphism elt : (@find elt) with signature E.eq ==> Equal ==> @Logic.eq _ as find_m. +Proof. +intros k k' Hk m m' Hm. +generalize (find_mapsto_iff m k)(find_mapsto_iff m' k') + (not_find_in_iff m k)(not_find_in_iff m' k'); +do 2 destruct find; auto; intros. +rewrite <- H, Hk, Hm, H0; auto. +rewrite <- H1, Hk, Hm, H2; auto. +symmetry; rewrite <- H2, <-Hk, <-Hm, H1; auto. +Qed. + +Add Parametric Morphism elt : (@add elt) with signature + E.eq ==> @Logic.eq _ ==> Equal ==> Equal as add_m. +Proof. +intros k k' Hk e m m' Hm y. +rewrite add_o, add_o; do 2 destruct eq_dec; auto. +elim n; rewrite <-Hk; auto. +elim n; rewrite Hk; auto. +Qed. + +Add Parametric Morphism elt : (@remove elt) with signature + E.eq ==> Equal ==> Equal as remove_m. +Proof. +intros k k' Hk m m' Hm y. +rewrite remove_o, remove_o; do 2 destruct eq_dec; auto. +elim n; rewrite <-Hk; auto. +elim n; rewrite Hk; auto. +Qed. + +Add Parametric Morphism elt elt' : (@map elt elt') with signature @Logic.eq _ ==> Equal ==> Equal as map_m. +Proof. +intros f m m' Hm y. +rewrite map_o, map_o, Hm; auto. +Qed. + +(* Later: Add Morphism cardinal *) + +(* old name: *) +Notation not_find_mapsto_iff := not_find_in_iff. + +End WFacts. + +(** * Same facts for full maps *) + +Module Facts (M:S). + Module D := OT_as_DT M.E. + Include WFacts D M. End Facts. + +(** * Additional Properties for weak maps + + Results about [fold], [elements], induction principles... +*) + +Module WProperties (E:DecidableType)(M:WSfun E). + Module Import F:=WFacts E M. + Import M. + + Section Elt. + Variable elt:Type. + + Definition Add x (e:elt) m m' := forall y, find y m' = find y (add x e m). + + Notation eqke := (@eq_key_elt elt). + Notation eqk := (@eq_key elt). + + Lemma elements_Empty : forall m:t elt, Empty m <-> elements m = nil. + Proof. + intros. + unfold Empty. + split; intros. + assert (forall a, ~ List.In a (elements m)). + red; intros. + apply (H (fst a) (snd a)). + rewrite elements_mapsto_iff. + rewrite InA_alt; exists a; auto. + split; auto; split; auto. + destruct (elements m); auto. + elim (H0 p); simpl; auto. + red; intros. + rewrite elements_mapsto_iff in H0. + rewrite InA_alt in H0; destruct H0. + rewrite H in H0; destruct H0 as (_,H0); inversion H0. + Qed. + + Lemma elements_empty : elements (@empty elt) = nil. + Proof. + rewrite <-elements_Empty; apply empty_1. + Qed. + + Lemma fold_Empty : forall m (A:Type)(f:key->elt->A->A)(i:A), + Empty m -> fold f m i = i. + Proof. + intros. + rewrite fold_1. + rewrite elements_Empty in H; rewrite H; simpl; auto. + Qed. + + Lemma NoDupA_eqk_eqke : forall l, NoDupA eqk l -> NoDupA eqke l. + Proof. + induction 1; auto. + constructor; auto. + contradict H. + destruct x as (x,y). + rewrite InA_alt in *; destruct H as ((a,b),((H1,H2),H3)); simpl in *. + exists (a,b); auto. + Qed. + + Lemma fold_Equal : forall m1 m2 (A:Type)(eqA:A->A->Prop)(st:Setoid_Theory A eqA) + (f:key->elt->A->A)(i:A), + compat_op eqke eqA (fun y =>f (fst y) (snd y)) -> + transpose eqA (fun y => f (fst y) (snd y)) -> + Equal m1 m2 -> + eqA (fold f m1 i) (fold f m2 i). + Proof. + assert (eqke_refl : forall p, eqke p p). + red; auto. + assert (eqke_sym : forall p p', eqke p p' -> eqke p' p). + intros (x1,x2) (y1,y2); unfold eq_key_elt; simpl; intuition. + assert (eqke_trans : forall p p' p'', eqke p p' -> eqke p' p'' -> eqke p p''). + intros (x1,x2) (y1,y2) (z1,z2); unfold eq_key_elt; simpl. + intuition; eauto; congruence. + intros; do 2 rewrite fold_1; do 2 rewrite <- fold_left_rev_right. + apply fold_right_equivlistA with (eqA:=eqke) (eqB:=eqA); auto. + apply NoDupA_rev; auto; apply NoDupA_eqk_eqke; apply elements_3w. + apply NoDupA_rev; auto; apply NoDupA_eqk_eqke; apply elements_3w. + red; intros. + do 2 rewrite InA_rev. + destruct x; do 2 rewrite <- elements_mapsto_iff. + do 2 rewrite find_mapsto_iff. + rewrite H1; split; auto. + Qed. + + Lemma fold_Add : forall m1 m2 x e (A:Type)(eqA:A->A->Prop)(st:Setoid_Theory A eqA) + (f:key->elt->A->A)(i:A), + compat_op eqke eqA (fun y =>f (fst y) (snd y)) -> + transpose eqA (fun y =>f (fst y) (snd y)) -> + ~In x m1 -> Add x e m1 m2 -> + eqA (fold f m2 i) (f x e (fold f m1 i)). + Proof. + assert (eqke_refl : forall p, eqke p p). + red; auto. + assert (eqke_sym : forall p p', eqke p p' -> eqke p' p). + intros (x1,x2) (y1,y2); unfold eq_key_elt; simpl; intuition. + assert (eqke_trans : forall p p' p'', eqke p p' -> eqke p' p'' -> eqke p p''). + intros (x1,x2) (y1,y2) (z1,z2); unfold eq_key_elt; simpl. + intuition; eauto; congruence. + intros; do 2 rewrite fold_1; do 2 rewrite <- fold_left_rev_right. + set (f':=fun y x0 => f (fst y) (snd y) x0) in *. + change (f x e (fold_right f' i (rev (elements m1)))) + with (f' (x,e) (fold_right f' i (rev (elements m1)))). + apply fold_right_add with (eqA:=eqke)(eqB:=eqA); auto. + apply NoDupA_rev; auto; apply NoDupA_eqk_eqke; apply elements_3w. + apply NoDupA_rev; auto; apply NoDupA_eqk_eqke; apply elements_3w. + rewrite InA_rev. + contradict H1. + exists e. + rewrite elements_mapsto_iff; auto. + intros a. + rewrite InA_cons; do 2 rewrite InA_rev; + destruct a as (a,b); do 2 rewrite <- elements_mapsto_iff. + do 2 rewrite find_mapsto_iff; unfold eq_key_elt; simpl. + rewrite H2. + rewrite add_o. + destruct (eq_dec x a); intuition. + inversion H3; auto. + f_equal; auto. + elim H1. + exists b; apply MapsTo_1 with a; auto with map. + elim n; auto. + Qed. + + Lemma cardinal_fold : forall m : t elt, + cardinal m = fold (fun _ _ => S) m 0. + Proof. + intros; rewrite cardinal_1, fold_1. + symmetry; apply fold_left_length; auto. + Qed. + + Lemma cardinal_Empty : forall m : t elt, + Empty m <-> cardinal m = 0. + Proof. + intros. + rewrite cardinal_1, elements_Empty. + destruct (elements m); intuition; discriminate. + Qed. + + Lemma Equal_cardinal : forall m m' : t elt, + Equal m m' -> cardinal m = cardinal m'. + Proof. + intros; do 2 rewrite cardinal_fold. + apply fold_Equal with (eqA:=@eq _); auto. + constructor; auto; congruence. + red; auto. + red; auto. + Qed. + + Lemma cardinal_1 : forall m : t elt, Empty m -> cardinal m = 0. + Proof. + intros; rewrite <- cardinal_Empty; auto. + Qed. + + Lemma cardinal_2 : + forall m m' x e, ~ In x m -> Add x e m m' -> cardinal m' = S (cardinal m). + Proof. + intros; do 2 rewrite cardinal_fold. + change S with ((fun _ _ => S) x e). + apply fold_Add; auto. + constructor; intros; auto; congruence. + red; simpl; auto. + red; simpl; auto. + Qed. + + Lemma cardinal_inv_1 : forall m : t elt, + cardinal m = 0 -> Empty m. + Proof. + intros; rewrite cardinal_Empty; auto. + Qed. + Hint Resolve cardinal_inv_1 : map. + + Lemma cardinal_inv_2 : + forall m n, cardinal m = S n -> { p : key*elt | MapsTo (fst p) (snd p) m }. + Proof. + intros; rewrite M.cardinal_1 in *. + generalize (elements_mapsto_iff m). + destruct (elements m); try discriminate. + exists p; auto. + rewrite H0; destruct p; simpl; auto. + constructor; red; auto. + Qed. + + Lemma cardinal_inv_2b : + forall m, cardinal m <> 0 -> { p : key*elt | MapsTo (fst p) (snd p) m }. + Proof. + intros. + generalize (@cardinal_inv_2 m); destruct cardinal. + elim H;auto. + eauto. + Qed. + + Lemma map_induction : + forall P : t elt -> Type, + (forall m, Empty m -> P m) -> + (forall m m', P m -> forall x e, ~In x m -> Add x e m m' -> P m') -> + forall m, P m. + Proof. + intros; remember (cardinal m) as n; revert m Heqn; induction n; intros. + apply X; apply cardinal_inv_1; auto. + + destruct (cardinal_inv_2 (sym_eq Heqn)) as ((x,e),H0); simpl in *. + assert (Add x e (remove x m) m). + red; intros. + rewrite add_o; rewrite remove_o; destruct (eq_dec x y); eauto with map. + apply X0 with (remove x m) x e; auto with map. + apply IHn; auto with map. + assert (S n = S (cardinal (remove x m))). + rewrite Heqn; eapply cardinal_2; eauto with map. + inversion H1; auto with map. + Qed. + + (** * Let's emulate some functions not present in the interface *) + + Definition filter (f : key -> elt -> bool)(m : t elt) := + fold (fun k e m => if f k e then add k e m else m) m (empty _). + + Definition for_all (f : key -> elt -> bool)(m : t elt) := + fold (fun k e b => if f k e then b else false) m true. + + Definition exists_ (f : key -> elt -> bool)(m : t elt) := + fold (fun k e b => if f k e then true else b) m false. + + Definition partition (f : key -> elt -> bool)(m : t elt) := + (filter f m, filter (fun k e => negb (f k e))). + + Section Specs. + Variable f : key -> elt -> bool. + Hypothesis Hf : forall e, compat_bool E.eq (fun k => f k e). + + Lemma filter_iff : forall m k e, + MapsTo k e (filter f m) <-> MapsTo k e m /\ f k e = true. + Proof. + unfold filter; intros. + rewrite fold_1. + rewrite <- fold_left_rev_right. + rewrite (elements_mapsto_iff m). + rewrite <- (InA_rev eqke (k,e) (elements m)). + assert (NoDupA eqk (rev (elements m))). + apply NoDupA_rev; auto; try apply elements_3w; auto. + intros (k1,e1); compute; auto. + intros (k1,e1)(k2,e2); compute; auto. + intros (k1,e1)(k2,e2)(k3,e3); compute; eauto. + induction (rev (elements m)); simpl; auto. + + rewrite empty_mapsto_iff. + intuition. + inversion H1. + + destruct a as (k',e'); simpl. + inversion_clear H. + case_eq (f k' e'); intros; simpl; + try rewrite add_mapsto_iff; rewrite IHl; clear IHl; intuition. + constructor; red; auto. + rewrite (Hf e' H2),H4 in H; auto. + inversion_clear H3. + compute in H2; destruct H2; auto. + destruct (E.eq_dec k' k); auto. + elim H0. + rewrite InA_alt in *; destruct H2 as (w,Hw); exists w; intuition. + red in H2; red; simpl in *; intuition. + rewrite e0; auto. + inversion_clear H3; auto. + compute in H2; destruct H2. + rewrite (Hf e H2),H3,H in H4; discriminate. + Qed. + + Lemma for_all_iff : forall m, + for_all f m = true <-> (forall k e, MapsTo k e m -> f k e = true). + Proof. + cut (forall m : t elt, + for_all f m = true <-> + (forall k e, InA eqke (k,e) (rev (elements m)) -> f k e = true)). + intros; rewrite H; split; intros. + apply H0; rewrite InA_rev, <- elements_mapsto_iff; auto. + apply H0; rewrite InA_rev, <- elements_mapsto_iff in H1; auto. + + unfold for_all; intros. + rewrite fold_1. + rewrite <- fold_left_rev_right. + assert (NoDupA eqk (rev (elements m))). + apply NoDupA_rev; auto; try apply elements_3w; auto. + intros (k1,e1); compute; auto. + intros (k1,e1)(k2,e2); compute; auto. + intros (k1,e1)(k2,e2)(k3,e3); compute; eauto. + induction (rev (elements m)); simpl; auto. + + intuition. + inversion H1. + + destruct a as (k,e); simpl. + inversion_clear H. + case_eq (f k e); intros; simpl; + try rewrite IHl; clear IHl; intuition. + inversion_clear H3; auto. + compute in H4; destruct H4. + rewrite (Hf e0 H3), H4; auto. + rewrite <-H, <-(H2 k e); auto. + constructor; red; auto. + Qed. + + Lemma exists_iff : forall m, + exists_ f m = true <-> + (exists p, MapsTo (fst p) (snd p) m /\ f (fst p) (snd p) = true). + Proof. + cut (forall m : t elt, + exists_ f m = true <-> + (exists p, InA eqke p (rev (elements m)) + /\ f (fst p) (snd p) = true)). + intros; rewrite H; split; intros. + destruct H0 as ((k,e),Hke); exists (k,e). + rewrite InA_rev, <-elements_mapsto_iff in Hke; auto. + destruct H0 as ((k,e),Hke); exists (k,e). + rewrite InA_rev, <-elements_mapsto_iff; auto. + unfold exists_; intros. + rewrite fold_1. + rewrite <- fold_left_rev_right. + assert (NoDupA eqk (rev (elements m))). + apply NoDupA_rev; auto; try apply elements_3w; auto. + intros (k1,e1); compute; auto. + intros (k1,e1)(k2,e2); compute; auto. + intros (k1,e1)(k2,e2)(k3,e3); compute; eauto. + induction (rev (elements m)); simpl; auto. + + intuition; try discriminate. + destruct H0 as ((k,e),(Hke,_)); inversion Hke. + + destruct a as (k,e); simpl. + inversion_clear H. + case_eq (f k e); intros; simpl; + try rewrite IHl; clear IHl; intuition. + exists (k,e); simpl; split; auto. + constructor; red; auto. + destruct H2 as ((k',e'),(Hke',Hf')); exists (k',e'); simpl; auto. + destruct H2 as ((k',e'),(Hke',Hf')); simpl in *. + inversion_clear Hke'. + compute in H2; destruct H2. + rewrite (Hf e' H2), H3,H in Hf'; discriminate. + exists (k',e'); auto. + Qed. + End Specs. + + (** specialized versions analyzing only keys (resp. elements) *) + + Definition filter_dom (f : key -> bool) := filter (fun k _ => f k). + Definition filter_range (f : elt -> bool) := filter (fun _ => f). + Definition for_all_dom (f : key -> bool) := for_all (fun k _ => f k). + Definition for_all_range (f : elt -> bool) := for_all (fun _ => f). + Definition exists_dom (f : key -> bool) := exists_ (fun k _ => f k). + Definition exists_range (f : elt -> bool) := exists_ (fun _ => f). + Definition partition_dom (f : key -> bool) := partition (fun k _ => f k). + Definition partition_range (f : elt -> bool) := partition (fun _ => f). + + End Elt. + + Add Parametric Morphism elt : (@cardinal elt) with signature Equal ==> @Logic.eq _ as cardinal_m. + Proof. intros; apply Equal_cardinal; auto. Qed. + +End WProperties. + +(** * Same Properties for full maps *) + +Module Properties (M:S). + Module D := OT_as_DT M.E. + Include WProperties D M. +End Properties. + +(** * Properties specific to maps with ordered keys *) + +Module OrdProperties (M:S). + Module Import ME := OrderedTypeFacts M.E. + Module Import O:=KeyOrderedType M.E. + Module Import P:=Properties M. + Import F. + Import M. + + Section Elt. + Variable elt:Type. + + Notation eqke := (@eqke elt). + Notation eqk := (@eqk elt). + Notation ltk := (@ltk elt). + Notation cardinal := (@cardinal elt). + Notation Equal := (@Equal elt). + Notation Add := (@Add elt). + + Definition Above x (m:t elt) := forall y, In y m -> E.lt y x. + Definition Below x (m:t elt) := forall y, In y m -> E.lt x y. + + Section Elements. + + Lemma sort_equivlistA_eqlistA : forall l l' : list (key*elt), + sort ltk l -> sort ltk l' -> equivlistA eqke l l' -> eqlistA eqke l l'. + Proof. + apply SortA_equivlistA_eqlistA; eauto; + unfold O.eqke, O.ltk; simpl; intuition; eauto. + Qed. + + Ltac clean_eauto := unfold O.eqke, O.ltk; simpl; intuition; eauto. + + Definition gtb (p p':key*elt) := match E.compare (fst p) (fst p') with GT _ => true | _ => false end. + Definition leb p := fun p' => negb (gtb p p'). + + Definition elements_lt p m := List.filter (gtb p) (elements m). + Definition elements_ge p m := List.filter (leb p) (elements m). + + Lemma gtb_1 : forall p p', gtb p p' = true <-> ltk p' p. + Proof. + intros (x,e) (y,e'); unfold gtb, O.ltk; simpl. + destruct (E.compare x y); intuition; try discriminate; ME.order. + Qed. + + Lemma leb_1 : forall p p', leb p p' = true <-> ~ltk p' p. + Proof. + intros (x,e) (y,e'); unfold leb, gtb, O.ltk; simpl. + destruct (E.compare x y); intuition; try discriminate; ME.order. + Qed. + + Lemma gtb_compat : forall p, compat_bool eqke (gtb p). + Proof. + red; intros (x,e) (a,e') (b,e'') H; red in H; simpl in *; destruct H. + generalize (gtb_1 (x,e) (a,e'))(gtb_1 (x,e) (b,e'')); + destruct (gtb (x,e) (a,e')); destruct (gtb (x,e) (b,e'')); auto. + unfold O.ltk in *; simpl in *; intros. + symmetry; rewrite H2. + apply ME.eq_lt with a; auto. + rewrite <- H1; auto. + unfold O.ltk in *; simpl in *; intros. + rewrite H1. + apply ME.eq_lt with b; auto. + rewrite <- H2; auto. + Qed. + + Lemma leb_compat : forall p, compat_bool eqke (leb p). + Proof. + red; intros x a b H. + unfold leb; f_equal; apply gtb_compat; auto. + Qed. + + Hint Resolve gtb_compat leb_compat elements_3 : map. + + Lemma elements_split : forall p m, + elements m = elements_lt p m ++ elements_ge p m. + Proof. + unfold elements_lt, elements_ge, leb; intros. + apply filter_split with (eqA:=eqk) (ltA:=ltk); eauto with map. + intros; destruct x; destruct y; destruct p. + rewrite gtb_1 in H; unfold O.ltk in H; simpl in *. + assert (~ltk (t1,e0) (k,e1)). + unfold gtb, O.ltk in *; simpl in *. + destruct (E.compare k t1); intuition; try discriminate; ME.order. + unfold O.ltk in *; simpl in *; ME.order. + Qed. + + Lemma elements_Add : forall m m' x e, ~In x m -> Add x e m m' -> + eqlistA eqke (elements m') + (elements_lt (x,e) m ++ (x,e):: elements_ge (x,e) m). + Proof. + intros; unfold elements_lt, elements_ge. + apply sort_equivlistA_eqlistA; auto with map. + apply (@SortA_app _ eqke); auto with map. + apply (@filter_sort _ eqke); auto with map; clean_eauto. + constructor; auto with map. + apply (@filter_sort _ eqke); auto with map; clean_eauto. + rewrite (@InfA_alt _ eqke); auto with map; try (clean_eauto; fail). + intros. + rewrite filter_InA in H1; auto with map; destruct H1. + rewrite leb_1 in H2. + destruct y; unfold O.ltk in *; simpl in *. + rewrite <- elements_mapsto_iff in H1. + assert (~E.eq x t0). + contradict H. + exists e0; apply MapsTo_1 with t0; auto. + ME.order. + apply (@filter_sort _ eqke); auto with map; clean_eauto. + intros. + rewrite filter_InA in H1; auto with map; destruct H1. + rewrite gtb_1 in H3. + destruct y; destruct x0; unfold O.ltk in *; simpl in *. + inversion_clear H2. + red in H4; simpl in *; destruct H4. + ME.order. + rewrite filter_InA in H4; auto with map; destruct H4. + rewrite leb_1 in H4. + unfold O.ltk in *; simpl in *; ME.order. + red; intros a; destruct a. + rewrite InA_app_iff; rewrite InA_cons. + do 2 (rewrite filter_InA; auto with map). + do 2 rewrite <- elements_mapsto_iff. + rewrite leb_1; rewrite gtb_1. + rewrite find_mapsto_iff; rewrite (H0 t0); rewrite <- find_mapsto_iff. + rewrite add_mapsto_iff. + unfold O.eqke, O.ltk; simpl. + destruct (E.compare t0 x); intuition. + right; split; auto; ME.order. + ME.order. + elim H. + exists e0; apply MapsTo_1 with t0; auto. + right; right; split; auto; ME.order. + ME.order. + right; split; auto; ME.order. + Qed. + + Lemma elements_Add_Above : forall m m' x e, + Above x m -> Add x e m m' -> + eqlistA eqke (elements m') (elements m ++ (x,e)::nil). + Proof. + intros. + apply sort_equivlistA_eqlistA; auto with map. + apply (@SortA_app _ eqke); auto with map. + intros. + inversion_clear H2. + destruct x0; destruct y. + rewrite <- elements_mapsto_iff in H1. + unfold O.eqke, O.ltk in *; simpl in *; destruct H3. + apply ME.lt_eq with x; auto. + apply H; firstorder. + inversion H3. + red; intros a; destruct a. + rewrite InA_app_iff; rewrite InA_cons; rewrite InA_nil. + do 2 rewrite <- elements_mapsto_iff. + rewrite find_mapsto_iff; rewrite (H0 t0); rewrite <- find_mapsto_iff. + rewrite add_mapsto_iff; unfold O.eqke; simpl. + intuition. + destruct (ME.eq_dec x t0); auto. + elimtype False. + assert (In t0 m). + exists e0; auto. + generalize (H t0 H1). + ME.order. + Qed. + + Lemma elements_Add_Below : forall m m' x e, + Below x m -> Add x e m m' -> + eqlistA eqke (elements m') ((x,e)::elements m). + Proof. + intros. + apply sort_equivlistA_eqlistA; auto with map. + change (sort ltk (((x,e)::nil) ++ elements m)). + apply (@SortA_app _ eqke); auto with map. + intros. + inversion_clear H1. + destruct y; destruct x0. + rewrite <- elements_mapsto_iff in H2. + unfold O.eqke, O.ltk in *; simpl in *; destruct H3. + apply ME.eq_lt with x; auto. + apply H; firstorder. + inversion H3. + red; intros a; destruct a. + rewrite InA_cons. + do 2 rewrite <- elements_mapsto_iff. + rewrite find_mapsto_iff; rewrite (H0 t0); rewrite <- find_mapsto_iff. + rewrite add_mapsto_iff; unfold O.eqke; simpl. + intuition. + destruct (ME.eq_dec x t0); auto. + elimtype False. + assert (In t0 m). + exists e0; auto. + generalize (H t0 H1). + ME.order. + Qed. + + Lemma elements_Equal_eqlistA : forall (m m': t elt), + Equal m m' -> eqlistA eqke (elements m) (elements m'). + Proof. + intros. + apply sort_equivlistA_eqlistA; auto with map. + red; intros. + destruct x; do 2 rewrite <- elements_mapsto_iff. + do 2 rewrite find_mapsto_iff; rewrite H; split; auto. + Qed. + + End Elements. + + Section Min_Max_Elt. + + (** We emulate two [max_elt] and [min_elt] functions. *) + + Fixpoint max_elt_aux (l:list (key*elt)) := match l with + | nil => None + | (x,e)::nil => Some (x,e) + | (x,e)::l => max_elt_aux l + end. + Definition max_elt m := max_elt_aux (elements m). + + Lemma max_elt_Above : + forall m x e, max_elt m = Some (x,e) -> Above x (remove x m). + Proof. + red; intros. + rewrite remove_in_iff in H0. + destruct H0. + rewrite elements_in_iff in H1. + destruct H1. + unfold max_elt in *. + generalize (elements_3 m). + revert x e H y x0 H0 H1. + induction (elements m). + simpl; intros; try discriminate. + intros. + destruct a; destruct l; simpl in *. + injection H; clear H; intros; subst. + inversion_clear H1. + red in H; simpl in *; intuition. + elim H0; eauto. + inversion H. + change (max_elt_aux (p::l) = Some (x,e)) in H. + generalize (IHl x e H); clear IHl; intros IHl. + inversion_clear H1; [ | inversion_clear H2; eauto ]. + red in H3; simpl in H3; destruct H3. + destruct p as (p1,p2). + destruct (ME.eq_dec p1 x). + apply ME.lt_eq with p1; auto. + inversion_clear H2. + inversion_clear H5. + red in H2; simpl in H2; ME.order. + apply E.lt_trans with p1; auto. + inversion_clear H2. + inversion_clear H5. + red in H2; simpl in H2; ME.order. + eapply IHl; eauto. + econstructor; eauto. + red; eauto. + inversion H2; auto. + Qed. + + Lemma max_elt_MapsTo : + forall m x e, max_elt m = Some (x,e) -> MapsTo x e m. + Proof. + intros. + unfold max_elt in *. + rewrite elements_mapsto_iff. + induction (elements m). + simpl; try discriminate. + destruct a; destruct l; simpl in *. + injection H; intros; subst; constructor; red; auto. + constructor 2; auto. + Qed. + + Lemma max_elt_Empty : + forall m, max_elt m = None -> Empty m. + Proof. + intros. + unfold max_elt in *. + rewrite elements_Empty. + induction (elements m); auto. + destruct a; destruct l; simpl in *; try discriminate. + assert (H':=IHl H); discriminate. + Qed. + + Definition min_elt m : option (key*elt) := match elements m with + | nil => None + | (x,e)::_ => Some (x,e) + end. + + Lemma min_elt_Below : + forall m x e, min_elt m = Some (x,e) -> Below x (remove x m). + Proof. + unfold min_elt, Below; intros. + rewrite remove_in_iff in H0; destruct H0. + rewrite elements_in_iff in H1. + destruct H1. + generalize (elements_3 m). + destruct (elements m). + try discriminate. + destruct p; injection H; intros; subst. + inversion_clear H1. + red in H2; destruct H2; simpl in *; ME.order. + inversion_clear H4. + rewrite (@InfA_alt _ eqke) in H3; eauto. + apply (H3 (y,x0)); auto. + unfold lt_key; simpl; intuition; eauto. + intros (x1,x2) (y1,y2) (z1,z2); compute; intuition; eauto. + intros (x1,x2) (y1,y2) (z1,z2); compute; intuition; eauto. + Qed. + + Lemma min_elt_MapsTo : + forall m x e, min_elt m = Some (x,e) -> MapsTo x e m. + Proof. + intros. + unfold min_elt in *. + rewrite elements_mapsto_iff. + destruct (elements m). + simpl; try discriminate. + destruct p; simpl in *. + injection H; intros; subst; constructor; red; auto. + Qed. + + Lemma min_elt_Empty : + forall m, min_elt m = None -> Empty m. + Proof. + intros. + unfold min_elt in *. + rewrite elements_Empty. + destruct (elements m); auto. + destruct p; simpl in *; discriminate. + Qed. + + End Min_Max_Elt. + + Section Induction_Principles. + + Lemma map_induction_max : + forall P : t elt -> Type, + (forall m, Empty m -> P m) -> + (forall m m', P m -> forall x e, Above x m -> Add x e m m' -> P m') -> + forall m, P m. + Proof. + intros; remember (cardinal m) as n; revert m Heqn; induction n; intros. + apply X; apply cardinal_inv_1; auto. + + case_eq (max_elt m); intros. + destruct p. + assert (Add k e (remove k m) m). + red; intros. + rewrite add_o; rewrite remove_o; destruct (eq_dec k y); eauto. + apply find_1; apply MapsTo_1 with k; auto. + apply max_elt_MapsTo; auto. + apply X0 with (remove k m) k e; auto with map. + apply IHn. + assert (S n = S (cardinal (remove k m))). + rewrite Heqn. + eapply cardinal_2; eauto with map. + inversion H1; auto. + eapply max_elt_Above; eauto. + + apply X; apply max_elt_Empty; auto. + Qed. + + Lemma map_induction_min : + forall P : t elt -> Type, + (forall m, Empty m -> P m) -> + (forall m m', P m -> forall x e, Below x m -> Add x e m m' -> P m') -> + forall m, P m. + Proof. + intros; remember (cardinal m) as n; revert m Heqn; induction n; intros. + apply X; apply cardinal_inv_1; auto. + + case_eq (min_elt m); intros. + destruct p. + assert (Add k e (remove k m) m). + red; intros. + rewrite add_o; rewrite remove_o; destruct (eq_dec k y); eauto. + apply find_1; apply MapsTo_1 with k; auto. + apply min_elt_MapsTo; auto. + apply X0 with (remove k m) k e; auto. + apply IHn. + assert (S n = S (cardinal (remove k m))). + rewrite Heqn. + eapply cardinal_2; eauto with map. + inversion H1; auto. + eapply min_elt_Below; eauto. + + apply X; apply min_elt_Empty; auto. + Qed. + + End Induction_Principles. + + Section Fold_properties. + + (** The following lemma has already been proved on Weak Maps, + but with one additionnal hypothesis (some [transpose] fact). *) + + Lemma fold_Equal : forall s1 s2 (A:Type)(eqA:A->A->Prop)(st:Setoid_Theory A eqA) + (f:key->elt->A->A)(i:A), + compat_op eqke eqA (fun y =>f (fst y) (snd y)) -> + Equal s1 s2 -> + eqA (fold f s1 i) (fold f s2 i). + Proof. + intros. + do 2 rewrite fold_1. + do 2 rewrite <- fold_left_rev_right. + apply fold_right_eqlistA with (eqA:=eqke) (eqB:=eqA); auto. + apply eqlistA_rev. + apply elements_Equal_eqlistA; auto. + Qed. + + Lemma fold_Add : forall s1 s2 x e (A:Type)(eqA:A->A->Prop)(st:Setoid_Theory A eqA) + (f:key->elt->A->A)(i:A), + compat_op eqke eqA (fun y =>f (fst y) (snd y)) -> + transpose eqA (fun y =>f (fst y) (snd y)) -> + ~In x s1 -> Add x e s1 s2 -> + eqA (fold f s2 i) (f x e (fold f s1 i)). + Proof. + intros; do 2 rewrite fold_1; do 2 rewrite <- fold_left_rev_right. + set (f':=fun y x0 => f (fst y) (snd y) x0) in *. + change (f x e (fold_right f' i (rev (elements s1)))) + with (f' (x,e) (fold_right f' i (rev (elements s1)))). + trans_st (fold_right f' i + (rev (elements_lt (x, e) s1 ++ (x,e) :: elements_ge (x, e) s1))). + apply fold_right_eqlistA with (eqA:=eqke) (eqB:=eqA); auto. + apply eqlistA_rev. + apply elements_Add; auto. + rewrite distr_rev; simpl. + rewrite app_ass; simpl. + rewrite (elements_split (x,e) s1). + rewrite distr_rev; simpl. + apply fold_right_commutes with (eqA:=eqke) (eqB:=eqA); auto. + Qed. + + Lemma fold_Add_Above : forall s1 s2 x e (A:Type)(eqA:A->A->Prop)(st:Setoid_Theory A eqA) + (f:key->elt->A->A)(i:A), + compat_op eqke eqA (fun y =>f (fst y) (snd y)) -> + Above x s1 -> Add x e s1 s2 -> + eqA (fold f s2 i) (f x e (fold f s1 i)). + Proof. + intros; do 2 rewrite fold_1; do 2 rewrite <- fold_left_rev_right. + set (f':=fun y x0 => f (fst y) (snd y) x0) in *. + trans_st (fold_right f' i (rev (elements s1 ++ (x,e)::nil))). + apply fold_right_eqlistA with (eqA:=eqke) (eqB:=eqA); auto. + apply eqlistA_rev. + apply elements_Add_Above; auto. + rewrite distr_rev; simpl. + refl_st. + Qed. + + Lemma fold_Add_Below : forall s1 s2 x e (A:Type)(eqA:A->A->Prop)(st:Setoid_Theory A eqA) + (f:key->elt->A->A)(i:A), + compat_op eqke eqA (fun y =>f (fst y) (snd y)) -> + Below x s1 -> Add x e s1 s2 -> + eqA (fold f s2 i) (fold f s1 (f x e i)). + Proof. + intros; do 2 rewrite fold_1; do 2 rewrite <- fold_left_rev_right. + set (f':=fun y x0 => f (fst y) (snd y) x0) in *. + trans_st (fold_right f' i (rev (((x,e)::nil)++elements s1))). + apply fold_right_eqlistA with (eqA:=eqke) (eqB:=eqA); auto. + apply eqlistA_rev. + simpl; apply elements_Add_Below; auto. + rewrite distr_rev; simpl. + rewrite fold_right_app. + refl_st. + Qed. + + End Fold_properties. + + End Elt. + +End OrdProperties. + + + + + diff --git a/theories/FSets/FMapFullAVL.v b/theories/FSets/FMapFullAVL.v new file mode 100644 index 00000000..57cbbcc4 --- /dev/null +++ b/theories/FSets/FMapFullAVL.v @@ -0,0 +1,823 @@ + +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* Finite map library. *) + +(* $Id: FMapFullAVL.v 10748 2008-04-03 18:28:26Z letouzey $ *) + +(** * FMapFullAVL + + This file contains some complements to [FMapAVL]. + + - Functor [AvlProofs] proves that trees of [FMapAVL] are not only + binary search trees, but moreover well-balanced ones. This is done + by proving that all operations preserve the balancing. + + - We then pack the previous elements in a [IntMake] functor + similar to the one of [FMapAVL], but richer. + + - In final [IntMake_ord] functor, the [compare] function is + different from the one in [FMapAVL]: this non-structural + version is closer to the original Ocaml code. + +*) + +Require Import Recdef FMapInterface FMapList ZArith Int FMapAVL. + +Set Implicit Arguments. +Unset Strict Implicit. + +Module AvlProofs (Import I:Int)(X: OrderedType). +Module Import Raw := Raw I X. +Module Import II:=MoreInt(I). +Import Raw.Proofs. +Open Local Scope pair_scope. +Open Local Scope Int_scope. + +Section Elt. +Variable elt : Type. +Implicit Types m r : t elt. + +(** * AVL trees *) + +(** [avl s] : [s] is a properly balanced AVL tree, + i.e. for any node the heights of the two children + differ by at most 2 *) + +Inductive avl : t elt -> Prop := + | RBLeaf : avl (Leaf _) + | RBNode : forall x e l r h, + avl l -> + avl r -> + -(2) <= height l - height r <= 2 -> + h = max (height l) (height r) + 1 -> + avl (Node l x e r h). + + +(** * Automation and dedicated tactics about [avl]. *) + +Hint Constructors avl. + +Lemma height_non_negative : forall (s : t elt), avl s -> + height s >= 0. +Proof. + induction s; simpl; intros; auto with zarith. + inv avl; intuition; omega_max. +Qed. + +Ltac avl_nn_hyp H := + let nz := fresh "nz" in assert (nz := height_non_negative H). + +Ltac avl_nn h := + let t := type of h in + match type of t with + | Prop => avl_nn_hyp h + | _ => match goal with H : avl h |- _ => avl_nn_hyp H end + end. + +(* Repeat the previous tactic. + Drawback: need to clear the [avl _] hyps ... Thank you Ltac *) + +Ltac avl_nns := + match goal with + | H:avl _ |- _ => avl_nn_hyp H; clear H; avl_nns + | _ => idtac + end. + + +(** * Basic results about [avl], [height] *) + +Lemma avl_node : forall x e l r, avl l -> avl r -> + -(2) <= height l - height r <= 2 -> + avl (Node l x e r (max (height l) (height r) + 1)). +Proof. + intros; auto. +Qed. +Hint Resolve avl_node. + +(** Results about [height] *) + +Lemma height_0 : forall l, avl l -> height l = 0 -> + l = Leaf _. +Proof. + destruct 1; intuition; simpl in *. + avl_nns; simpl in *; elimtype False; omega_max. +Qed. + + +(** * Empty map *) + +Lemma empty_avl : avl (empty elt). +Proof. + unfold empty; auto. +Qed. + + +(** * Helper functions *) + +Lemma create_avl : + forall l x e r, avl l -> avl r -> -(2) <= height l - height r <= 2 -> + avl (create l x e r). +Proof. + unfold create; auto. +Qed. + +Lemma create_height : + forall l x e r, avl l -> avl r -> -(2) <= height l - height r <= 2 -> + height (create l x e r) = max (height l) (height r) + 1. +Proof. + unfold create; intros; auto. +Qed. + +Lemma bal_avl : forall l x e r, avl l -> avl r -> + -(3) <= height l - height r <= 3 -> avl (bal l x e r). +Proof. + intros l x e r; functional induction (bal l x e r); intros; clearf; + inv avl; simpl in *; + match goal with |- avl (assert_false _ _ _ _) => avl_nns + | _ => repeat apply create_avl; simpl in *; auto + end; omega_max. +Qed. + +Lemma bal_height_1 : forall l x e r, avl l -> avl r -> + -(3) <= height l - height r <= 3 -> + 0 <= height (bal l x e r) - max (height l) (height r) <= 1. +Proof. + intros l x e r; functional induction (bal l x e r); intros; clearf; + inv avl; avl_nns; simpl in *; omega_max. +Qed. + +Lemma bal_height_2 : + forall l x e r, avl l -> avl r -> -(2) <= height l - height r <= 2 -> + height (bal l x e r) == max (height l) (height r) +1. +Proof. + intros l x e r; functional induction (bal l x e r); intros; clearf; + inv avl; avl_nns; simpl in *; omega_max. +Qed. + +Ltac omega_bal := match goal with + | H:avl ?l, H':avl ?r |- context [ bal ?l ?x ?e ?r ] => + generalize (bal_height_1 x e H H') (bal_height_2 x e H H'); + omega_max + end. + +(** * Insertion *) + +Lemma add_avl_1 : forall m x e, avl m -> + avl (add x e m) /\ 0 <= height (add x e m) - height m <= 1. +Proof. + intros m x e; functional induction (add x e m); intros; inv avl; simpl in *. + intuition; try constructor; simpl; auto; try omega_max. + (* LT *) + destruct IHt; auto. + split. + apply bal_avl; auto; omega_max. + omega_bal. + (* EQ *) + intuition; omega_max. + (* GT *) + destruct IHt; auto. + split. + apply bal_avl; auto; omega_max. + omega_bal. +Qed. + +Lemma add_avl : forall m x e, avl m -> avl (add x e m). +Proof. + intros; generalize (add_avl_1 x e H); intuition. +Qed. +Hint Resolve add_avl. + +(** * Extraction of minimum binding *) + +Lemma remove_min_avl_1 : forall l x e r h, avl (Node l x e r h) -> + avl (remove_min l x e r)#1 /\ + 0 <= height (Node l x e r h) - height (remove_min l x e r)#1 <= 1. +Proof. + intros l x e r; functional induction (remove_min l x e r); simpl in *; intros. + inv avl; simpl in *; split; auto. + avl_nns; omega_max. + inversion_clear H. + rewrite e0 in IHp;simpl in IHp;destruct (IHp _x); auto. + split; simpl in *. + apply bal_avl; auto; omega_max. + omega_bal. +Qed. + +Lemma remove_min_avl : forall l x e r h, avl (Node l x e r h) -> + avl (remove_min l x e r)#1. +Proof. + intros; generalize (remove_min_avl_1 H); intuition. +Qed. + +(** * Merging two trees *) + +Lemma merge_avl_1 : forall m1 m2, avl m1 -> avl m2 -> + -(2) <= height m1 - height m2 <= 2 -> + avl (merge m1 m2) /\ + 0<= height (merge m1 m2) - max (height m1) (height m2) <=1. +Proof. + intros m1 m2; functional induction (merge m1 m2); intros; + try factornode _x _x0 _x1 _x2 _x3 as m1. + simpl; split; auto; avl_nns; omega_max. + simpl; split; auto; avl_nns; omega_max. + generalize (remove_min_avl_1 H0). + rewrite e1; destruct 1. + split. + apply bal_avl; auto. + omega_max. + omega_bal. +Qed. + +Lemma merge_avl : forall m1 m2, avl m1 -> avl m2 -> + -(2) <= height m1 - height m2 <= 2 -> avl (merge m1 m2). +Proof. + intros; generalize (merge_avl_1 H H0 H1); intuition. +Qed. + + +(** * Deletion *) + +Lemma remove_avl_1 : forall m x, avl m -> + avl (remove x m) /\ 0 <= height m - height (remove x m) <= 1. +Proof. + intros m x; functional induction (remove x m); intros. + split; auto; omega_max. + (* LT *) + inv avl. + destruct (IHt H0). + split. + apply bal_avl; auto. + omega_max. + omega_bal. + (* EQ *) + inv avl. + generalize (merge_avl_1 H0 H1 H2). + intuition omega_max. + (* GT *) + inv avl. + destruct (IHt H1). + split. + apply bal_avl; auto. + omega_max. + omega_bal. +Qed. + +Lemma remove_avl : forall m x, avl m -> avl (remove x m). +Proof. + intros; generalize (remove_avl_1 x H); intuition. +Qed. +Hint Resolve remove_avl. + + +(** * Join *) + +Lemma join_avl_1 : forall l x d r, avl l -> avl r -> + avl (join l x d r) /\ + 0<= height (join l x d r) - max (height l) (height r) <= 1. +Proof. + join_tac. + + split; simpl; auto. + destruct (add_avl_1 x d H0). + avl_nns; omega_max. + set (l:=Node ll lx ld lr lh) in *. + split; auto. + destruct (add_avl_1 x d H). + simpl (height (Leaf elt)). + avl_nns; omega_max. + + inversion_clear H. + assert (height (Node rl rx rd rr rh) = rh); auto. + set (r := Node rl rx rd rr rh) in *; clearbody r. + destruct (Hlr x d r H2 H0); clear Hrl Hlr. + set (j := join lr x d r) in *; clearbody j. + simpl. + assert (-(3) <= height ll - height j <= 3) by omega_max. + split. + apply bal_avl; auto. + omega_bal. + + inversion_clear H0. + assert (height (Node ll lx ld lr lh) = lh); auto. + set (l := Node ll lx ld lr lh) in *; clearbody l. + destruct (Hrl H H1); clear Hrl Hlr. + set (j := join l x d rl) in *; clearbody j. + simpl. + assert (-(3) <= height j - height rr <= 3) by omega_max. + split. + apply bal_avl; auto. + omega_bal. + + clear Hrl Hlr. + assert (height (Node ll lx ld lr lh) = lh); auto. + assert (height (Node rl rx rd rr rh) = rh); auto. + set (l := Node ll lx ld lr lh) in *; clearbody l. + set (r := Node rl rx rd rr rh) in *; clearbody r. + assert (-(2) <= height l - height r <= 2) by omega_max. + split. + apply create_avl; auto. + rewrite create_height; auto; omega_max. +Qed. + +Lemma join_avl : forall l x d r, avl l -> avl r -> avl (join l x d r). +Proof. + intros; destruct (join_avl_1 x d H H0); auto. +Qed. +Hint Resolve join_avl. + +(** concat *) + +Lemma concat_avl : forall m1 m2, avl m1 -> avl m2 -> avl (concat m1 m2). +Proof. + intros m1 m2; functional induction (concat m1 m2); auto. + intros; apply join_avl; auto. + generalize (remove_min_avl H0); rewrite e1; simpl; auto. +Qed. +Hint Resolve concat_avl. + +(** split *) + +Lemma split_avl : forall m x, avl m -> + avl (split x m)#l /\ avl (split x m)#r. +Proof. + intros m x; functional induction (split x m); simpl; auto. + rewrite e1 in IHt;simpl in IHt;inversion_clear 1; intuition. + simpl; inversion_clear 1; auto. + rewrite e1 in IHt;simpl in IHt;inversion_clear 1; intuition. +Qed. + +End Elt. +Hint Constructors avl. + +Section Map. +Variable elt elt' : Type. +Variable f : elt -> elt'. + +Lemma map_height : forall m, height (map f m) = height m. +Proof. +destruct m; simpl; auto. +Qed. + +Lemma map_avl : forall m, avl m -> avl (map f m). +Proof. +induction m; simpl; auto. +inversion_clear 1; constructor; auto; do 2 rewrite map_height; auto. +Qed. + +End Map. + +Section Mapi. +Variable elt elt' : Type. +Variable f : key -> elt -> elt'. + +Lemma mapi_height : forall m, height (mapi f m) = height m. +Proof. +destruct m; simpl; auto. +Qed. + +Lemma mapi_avl : forall m, avl m -> avl (mapi f m). +Proof. +induction m; simpl; auto. +inversion_clear 1; constructor; auto; do 2 rewrite mapi_height; auto. +Qed. + +End Mapi. + +Section Map_option. +Variable elt elt' : Type. +Variable f : key -> elt -> option elt'. + +Lemma map_option_avl : forall m, avl m -> avl (map_option f m). +Proof. +induction m; simpl; auto; intros. +inv avl; destruct (f k e); auto using join_avl, concat_avl. +Qed. + +End Map_option. + +Section Map2_opt. +Variable elt elt' elt'' : Type. +Variable f : key -> elt -> option elt' -> option elt''. +Variable mapl : t elt -> t elt''. +Variable mapr : t elt' -> t elt''. +Hypothesis mapl_avl : forall m, avl m -> avl (mapl m). +Hypothesis mapr_avl : forall m', avl m' -> avl (mapr m'). + +Notation map2_opt := (map2_opt f mapl mapr). + +Lemma map2_opt_avl : forall m1 m2, avl m1 -> avl m2 -> + avl (map2_opt m1 m2). +Proof. +intros m1 m2; functional induction (map2_opt m1 m2); auto; +factornode _x0 _x1 _x2 _x3 _x4 as r2; intros; +destruct (split_avl x1 H0); rewrite e1 in *; simpl in *; inv avl; +auto using join_avl, concat_avl. +Qed. + +End Map2_opt. + +Section Map2. +Variable elt elt' elt'' : Type. +Variable f : option elt -> option elt' -> option elt''. + +Lemma map2_avl : forall m1 m2, avl m1 -> avl m2 -> avl (map2 f m1 m2). +Proof. +unfold map2; auto using map2_opt_avl, map_option_avl. +Qed. + +End Map2. +End AvlProofs. + +(** * Encapsulation + + We can implement [S] with balanced binary search trees. + When compared to [FMapAVL], we maintain here two invariants + (bst and avl) instead of only bst, which is enough for fulfilling + the FMap interface. +*) + +Module IntMake (I:Int)(X: OrderedType) <: S with Module E := X. + + Module E := X. + Module Import AvlProofs := AvlProofs I X. + Import Raw. + Import Raw.Proofs. + + Record bbst (elt:Type) := + Bbst {this :> tree elt; is_bst : bst this; is_avl: avl this}. + + Definition t := bbst. + Definition key := E.t. + + Section Elt. + Variable elt elt' elt'': Type. + + Implicit Types m : t elt. + Implicit Types x y : key. + Implicit Types e : elt. + + Definition empty : t elt := Bbst (empty_bst elt) (empty_avl elt). + Definition is_empty m : bool := is_empty m.(this). + Definition add x e m : t elt := + Bbst (add_bst x e m.(is_bst)) (add_avl x e m.(is_avl)). + Definition remove x m : t elt := + Bbst (remove_bst x m.(is_bst)) (remove_avl x m.(is_avl)). + Definition mem x m : bool := mem x m.(this). + Definition find x m : option elt := find x m.(this). + Definition map f m : t elt' := + Bbst (map_bst f m.(is_bst)) (map_avl f m.(is_avl)). + Definition mapi (f:key->elt->elt') m : t elt' := + Bbst (mapi_bst f m.(is_bst)) (mapi_avl f m.(is_avl)). + Definition map2 f m (m':t elt') : t elt'' := + Bbst (map2_bst f m.(is_bst) m'.(is_bst)) (map2_avl f m.(is_avl) m'.(is_avl)). + Definition elements m : list (key*elt) := elements m.(this). + Definition cardinal m := cardinal m.(this). + Definition fold (A:Type) (f:key->elt->A->A) m i := fold (A:=A) f m.(this) i. + Definition equal cmp m m' : bool := equal cmp m.(this) m'.(this). + + Definition MapsTo x e m : Prop := MapsTo x e m.(this). + Definition In x m : Prop := In0 x m.(this). + Definition Empty m : Prop := Empty m.(this). + + Definition eq_key : (key*elt) -> (key*elt) -> Prop := @PX.eqk elt. + Definition eq_key_elt : (key*elt) -> (key*elt) -> Prop := @PX.eqke elt. + Definition lt_key : (key*elt) -> (key*elt) -> Prop := @PX.ltk elt. + + Lemma MapsTo_1 : forall m x y e, E.eq x y -> MapsTo x e m -> MapsTo y e m. + Proof. intros m; exact (@MapsTo_1 _ m.(this)). Qed. + + Lemma mem_1 : forall m x, In x m -> mem x m = true. + Proof. + unfold In, mem; intros m x; rewrite In_alt; simpl; apply mem_1; auto. + apply m.(is_bst). + Qed. + + Lemma mem_2 : forall m x, mem x m = true -> In x m. + Proof. + unfold In, mem; intros m x; rewrite In_alt; simpl; apply mem_2; auto. + Qed. + + Lemma empty_1 : Empty empty. + Proof. exact (@empty_1 elt). Qed. + + Lemma is_empty_1 : forall m, Empty m -> is_empty m = true. + Proof. intros m; exact (@is_empty_1 _ m.(this)). Qed. + Lemma is_empty_2 : forall m, is_empty m = true -> Empty m. + Proof. intros m; exact (@is_empty_2 _ m.(this)). Qed. + + Lemma add_1 : forall m x y e, E.eq x y -> MapsTo y e (add x e m). + Proof. intros m x y e; exact (@add_1 elt _ x y e). Qed. + Lemma add_2 : forall m x y e e', ~ E.eq x y -> MapsTo y e m -> MapsTo y e (add x e' m). + Proof. intros m x y e e'; exact (@add_2 elt _ x y e e'). Qed. + Lemma add_3 : forall m x y e e', ~ E.eq x y -> MapsTo y e (add x e' m) -> MapsTo y e m. + Proof. intros m x y e e'; exact (@add_3 elt _ x y e e'). Qed. + + Lemma remove_1 : forall m x y, E.eq x y -> ~ In y (remove x m). + Proof. + unfold In, remove; intros m x y; rewrite In_alt; simpl; apply remove_1; auto. + apply m.(is_bst). + Qed. + Lemma remove_2 : forall m x y e, ~ E.eq x y -> MapsTo y e m -> MapsTo y e (remove x m). + Proof. intros m x y e; exact (@remove_2 elt _ x y e m.(is_bst)). Qed. + Lemma remove_3 : forall m x y e, MapsTo y e (remove x m) -> MapsTo y e m. + Proof. intros m x y e; exact (@remove_3 elt _ x y e m.(is_bst)). Qed. + + + Lemma find_1 : forall m x e, MapsTo x e m -> find x m = Some e. + Proof. intros m x e; exact (@find_1 elt _ x e m.(is_bst)). Qed. + Lemma find_2 : forall m x e, find x m = Some e -> MapsTo x e m. + Proof. intros m; exact (@find_2 elt m.(this)). Qed. + + Lemma fold_1 : forall m (A : Type) (i : A) (f : key -> elt -> A -> A), + fold f m i = fold_left (fun a p => f (fst p) (snd p) a) (elements m) i. + Proof. intros m; exact (@fold_1 elt m.(this) m.(is_bst)). Qed. + + Lemma elements_1 : forall m x e, + MapsTo x e m -> InA eq_key_elt (x,e) (elements m). + Proof. + intros; unfold elements, MapsTo, eq_key_elt; rewrite elements_mapsto; auto. + Qed. + + Lemma elements_2 : forall m x e, + InA eq_key_elt (x,e) (elements m) -> MapsTo x e m. + Proof. + intros; unfold elements, MapsTo, eq_key_elt; rewrite <- elements_mapsto; auto. + Qed. + + Lemma elements_3 : forall m, sort lt_key (elements m). + Proof. intros m; exact (@elements_sort elt m.(this) m.(is_bst)). Qed. + + Lemma elements_3w : forall m, NoDupA eq_key (elements m). + Proof. intros m; exact (@elements_nodup elt m.(this) m.(is_bst)). Qed. + + Lemma cardinal_1 : forall m, cardinal m = length (elements m). + Proof. intro m; exact (@elements_cardinal elt m.(this)). Qed. + + Definition Equal m m' := forall y, find y m = find y m'. + Definition Equiv (eq_elt:elt->elt->Prop) m m' := + (forall k, In k m <-> In k m') /\ + (forall k e e', MapsTo k e m -> MapsTo k e' m' -> eq_elt e e'). + Definition Equivb cmp := Equiv (Cmp cmp). + + Lemma Equivb_Equivb : forall cmp m m', + Equivb cmp m m' <-> Raw.Proofs.Equivb cmp m m'. + Proof. + intros; unfold Equivb, Equiv, Raw.Proofs.Equivb, In; intuition. + generalize (H0 k); do 2 rewrite In_alt; intuition. + generalize (H0 k); do 2 rewrite In_alt; intuition. + generalize (H0 k); do 2 rewrite <- In_alt; intuition. + generalize (H0 k); do 2 rewrite <- In_alt; intuition. + Qed. + + Lemma equal_1 : forall m m' cmp, + Equivb cmp m m' -> equal cmp m m' = true. + Proof. + unfold equal; intros (m,b,a) (m',b',a') cmp; rewrite Equivb_Equivb; + intros; simpl in *; rewrite equal_Equivb; auto. + Qed. + + Lemma equal_2 : forall m m' cmp, + equal cmp m m' = true -> Equivb cmp m m'. + Proof. + unfold equal; intros (m,b,a) (m',b',a') cmp; rewrite Equivb_Equivb; + intros; simpl in *; rewrite <-equal_Equivb; auto. + Qed. + + End Elt. + + Lemma map_1 : forall (elt elt':Type)(m: t elt)(x:key)(e:elt)(f:elt->elt'), + MapsTo x e m -> MapsTo x (f e) (map f m). + Proof. intros elt elt' m x e f; exact (@map_1 elt elt' f m.(this) x e). Qed. + + Lemma map_2 : forall (elt elt':Type)(m:t elt)(x:key)(f:elt->elt'), In x (map f m) -> In x m. + Proof. + intros elt elt' m x f; do 2 unfold In in *; do 2 rewrite In_alt; simpl. + apply map_2; auto. + Qed. + + Lemma mapi_1 : forall (elt elt':Type)(m: t elt)(x:key)(e:elt) + (f:key->elt->elt'), MapsTo x e m -> + exists y, E.eq y x /\ MapsTo x (f y e) (mapi f m). + Proof. intros elt elt' m x e f; exact (@mapi_1 elt elt' f m.(this) x e). Qed. + Lemma mapi_2 : forall (elt elt':Type)(m: t elt)(x:key) + (f:key->elt->elt'), In x (mapi f m) -> In x m. + Proof. + intros elt elt' m x f; unfold In in *; do 2 rewrite In_alt; simpl; apply mapi_2; auto. + Qed. + + Lemma map2_1 : forall (elt elt' elt'':Type)(m: t elt)(m': t elt') + (x:key)(f:option elt->option elt'->option elt''), + In x m \/ In x m' -> + find x (map2 f m m') = f (find x m) (find x m'). + Proof. + unfold find, map2, In; intros elt elt' elt'' m m' x f. + do 2 rewrite In_alt; intros; simpl; apply map2_1; auto. + apply m.(is_bst). + apply m'.(is_bst). + Qed. + + Lemma map2_2 : forall (elt elt' elt'':Type)(m: t elt)(m': t elt') + (x:key)(f:option elt->option elt'->option elt''), + In x (map2 f m m') -> In x m \/ In x m'. + Proof. + unfold In, map2; intros elt elt' elt'' m m' x f. + do 3 rewrite In_alt; intros; simpl in *; eapply map2_2; eauto. + apply m.(is_bst). + apply m'.(is_bst). + Qed. + +End IntMake. + + +Module IntMake_ord (I:Int)(X: OrderedType)(D : OrderedType) <: + Sord with Module Data := D + with Module MapS.E := X. + + Module Data := D. + Module Import MapS := IntMake(I)(X). + Import AvlProofs. + Import Raw.Proofs. + Module Import MD := OrderedTypeFacts(D). + Module LO := FMapList.Make_ord(X)(D). + + Definition t := MapS.t D.t. + + Definition cmp e e' := + match D.compare e e' with EQ _ => true | _ => false end. + + Definition elements (m:t) := + LO.MapS.Build_slist (Raw.Proofs.elements_sort m.(is_bst)). + + (** * As comparison function, we propose here a non-structural + version faithful to the code of Ocaml's Map library, instead of + the structural version of FMapAVL *) + + Fixpoint cardinal_e (e:Raw.enumeration D.t) := + match e with + | Raw.End => 0%nat + | Raw.More _ _ r e => S (Raw.cardinal r + cardinal_e e) + end. + + Lemma cons_cardinal_e : forall m e, + cardinal_e (Raw.cons m e) = (Raw.cardinal m + cardinal_e e)%nat. + Proof. + induction m; simpl; intros; auto. + rewrite IHm1; simpl; rewrite <- plus_n_Sm; auto with arith. + Qed. + + Definition cardinal_e_2 ee := + (cardinal_e (fst ee) + cardinal_e (snd ee))%nat. + + Function compare_aux (ee:Raw.enumeration D.t * Raw.enumeration D.t) + { measure cardinal_e_2 ee } : comparison := + match ee with + | (Raw.End, Raw.End) => Eq + | (Raw.End, Raw.More _ _ _ _) => Lt + | (Raw.More _ _ _ _, Raw.End) => Gt + | (Raw.More x1 d1 r1 e1, Raw.More x2 d2 r2 e2) => + match X.compare x1 x2 with + | EQ _ => match D.compare d1 d2 with + | EQ _ => compare_aux (Raw.cons r1 e1, Raw.cons r2 e2) + | LT _ => Lt + | GT _ => Gt + end + | LT _ => Lt + | GT _ => Gt + end + end. + Proof. + intros; unfold cardinal_e_2; simpl; + abstract (do 2 rewrite cons_cardinal_e; romega with * ). + Defined. + + Definition Cmp c := + match c with + | Eq => LO.eq_list + | Lt => LO.lt_list + | Gt => (fun l1 l2 => LO.lt_list l2 l1) + end. + + Lemma cons_Cmp : forall c x1 x2 d1 d2 l1 l2, + X.eq x1 x2 -> D.eq d1 d2 -> + Cmp c l1 l2 -> Cmp c ((x1,d1)::l1) ((x2,d2)::l2). + Proof. + destruct c; simpl; intros; MX.elim_comp; auto. + Qed. + Hint Resolve cons_Cmp. + + Lemma compare_aux_Cmp : forall e, + Cmp (compare_aux e) (flatten_e (fst e)) (flatten_e (snd e)). + Proof. + intros e; functional induction (compare_aux e); simpl in *; + auto; intros; try clear e0; try clear e3; try MX.elim_comp; auto. + rewrite 2 cons_1 in IHc; auto. + Qed. + + Lemma compare_Cmp : forall m1 m2, + Cmp (compare_aux (Raw.cons m1 (Raw.End _), Raw.cons m2 (Raw.End _))) + (Raw.elements m1) (Raw.elements m2). + Proof. + intros. + assert (H1:=cons_1 m1 (Raw.End _)). + assert (H2:=cons_1 m2 (Raw.End _)). + simpl in *; rewrite <- app_nil_end in *; rewrite <-H1,<-H2. + apply (@compare_aux_Cmp (Raw.cons m1 (Raw.End _), + Raw.cons m2 (Raw.End _))). + Qed. + + Definition eq (m1 m2 : t) := LO.eq_list (Raw.elements m1) (Raw.elements m2). + Definition lt (m1 m2 : t) := LO.lt_list (Raw.elements m1) (Raw.elements m2). + + Definition compare (s s':t) : Compare lt eq s s'. + Proof. + intros (s,b,a) (s',b',a'). + generalize (compare_Cmp s s'). + destruct compare_aux; intros; [apply EQ|apply LT|apply GT]; red; auto. + Defined. + + + (* Proofs about [eq] and [lt] *) + + Definition selements (m1 : t) := + LO.MapS.Build_slist (elements_sort m1.(is_bst)). + + Definition seq (m1 m2 : t) := LO.eq (selements m1) (selements m2). + Definition slt (m1 m2 : t) := LO.lt (selements m1) (selements m2). + + Lemma eq_seq : forall m1 m2, eq m1 m2 <-> seq m1 m2. + Proof. + unfold eq, seq, selements, elements, LO.eq; intuition. + Qed. + + Lemma lt_slt : forall m1 m2, lt m1 m2 <-> slt m1 m2. + Proof. + unfold lt, slt, selements, elements, LO.lt; intuition. + Qed. + + Lemma eq_1 : forall (m m' : t), MapS.Equivb cmp m m' -> eq m m'. + Proof. + intros m m'. + rewrite eq_seq; unfold seq. + rewrite Equivb_Equivb. + rewrite Equivb_elements. + auto using LO.eq_1. + Qed. + + Lemma eq_2 : forall m m', eq m m' -> MapS.Equivb cmp m m'. + Proof. + intros m m'. + rewrite eq_seq; unfold seq. + rewrite Equivb_Equivb. + rewrite Equivb_elements. + intros. + generalize (LO.eq_2 H). + auto. + Qed. + + Lemma eq_refl : forall m : t, eq m m. + Proof. + intros; rewrite eq_seq; unfold seq; intros; apply LO.eq_refl. + Qed. + + Lemma eq_sym : forall m1 m2 : t, eq m1 m2 -> eq m2 m1. + Proof. + intros m1 m2; rewrite 2 eq_seq; unfold seq; intros; apply LO.eq_sym; auto. + Qed. + + Lemma eq_trans : forall m1 m2 m3 : t, eq m1 m2 -> eq m2 m3 -> eq m1 m3. + Proof. + intros m1 m2 M3; rewrite 3 eq_seq; unfold seq. + intros; eapply LO.eq_trans; eauto. + Qed. + + Lemma lt_trans : forall m1 m2 m3 : t, lt m1 m2 -> lt m2 m3 -> lt m1 m3. + Proof. + intros m1 m2 m3; rewrite 3 lt_slt; unfold slt; + intros; eapply LO.lt_trans; eauto. + Qed. + + Lemma lt_not_eq : forall m1 m2 : t, lt m1 m2 -> ~ eq m1 m2. + Proof. + intros m1 m2; rewrite lt_slt, eq_seq; unfold slt, seq; + intros; apply LO.lt_not_eq; auto. + Qed. + +End IntMake_ord. + +(* For concrete use inside Coq, we propose an instantiation of [Int] by [Z]. *) + +Module Make (X: OrderedType) <: S with Module E := X + :=IntMake(Z_as_Int)(X). + +Module Make_ord (X: OrderedType)(D: OrderedType) + <: Sord with Module Data := D + with Module MapS.E := X + :=IntMake_ord(Z_as_Int)(X)(D). + diff --git a/theories/FSets/FMapIntMap.v b/theories/FSets/FMapIntMap.v deleted file mode 100644 index c7681bd4..00000000 --- a/theories/FSets/FMapIntMap.v +++ /dev/null @@ -1,622 +0,0 @@ -(***********************************************************************) -(* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) -(* \VV/ *************************************************************) -(* // * This file is distributed under the terms of the *) -(* * GNU Lesser General Public License Version 2.1 *) -(***********************************************************************) - -(* Finite sets library. - * Authors: Pierre Letouzey and Jean-Christophe Filliâtre - * Institution: LRI, CNRS UMR 8623 - Université Paris Sud - * 91405 Orsay, France *) - -(* $Id: FMapIntMap.v 8876 2006-05-30 13:43:15Z letouzey $ *) - -Require Import Bool. -Require Import NArith Ndigits Ndec Nnat. -Require Import Allmaps. -Require Import OrderedType. -Require Import OrderedTypeEx. -Require Import FMapInterface FMapList. - - -Set Implicit Arguments. - -(** * An implementation of [FMapInterface.S] based on [IntMap] *) - -(** Keys are of type [N]. The main functions are directly taken from - [IntMap]. Since they have no exact counterpart in [IntMap], functions - [fold], [map2] and [equal] are for now obtained by translation - to sorted lists. *) - -(** [N] is an ordered type, using not the usual order on numbers, - but lexicographic ordering on bits (lower bit considered first). *) - -Module NUsualOrderedType <: UsualOrderedType. - Definition t:=N. - Definition eq:=@eq N. - Definition eq_refl := @refl_equal t. - Definition eq_sym := @sym_eq t. - Definition eq_trans := @trans_eq t. - - Definition lt p q:= Nless p q = true. - - Definition lt_trans := Nless_trans. - - Lemma lt_not_eq : forall x y : t, lt x y -> ~ eq x y. - Proof. - intros; intro. - rewrite H0 in H. - red in H. - rewrite Nless_not_refl in H; discriminate. - Qed. - - Definition compare : forall x y : t, Compare lt eq x y. - Proof. - intros x y. - destruct (Nless_total x y) as [[H|H]|H]. - apply LT; unfold lt; auto. - apply GT; unfold lt; auto. - apply EQ; auto. - Qed. - -End NUsualOrderedType. - - -(** The module of maps over [N] keys based on [IntMap] *) - -Module MapIntMap <: S with Module E:=NUsualOrderedType. - - Module E:=NUsualOrderedType. - Module ME:=OrderedTypeFacts(E). - Module PE:=KeyOrderedType(E). - - Definition key := N. - - Definition t := Map. - - Section A. - Variable A:Set. - - Definition empty : t A := M0 A. - - Definition is_empty (m : t A) : bool := - MapEmptyp _ (MapCanonicalize _ m). - - Definition find (x:key)(m: t A) : option A := MapGet _ m x. - - Definition mem (x:key)(m: t A) : bool := - match find x m with - | Some _ => true - | None => false - end. - - Definition add (x:key)(v:A)(m:t A) : t A := MapPut _ m x v. - - Definition remove (x:key)(m:t A) : t A := MapRemove _ m x. - - Definition elements (m : t A) : list (N*A) := alist_of_Map _ m. - - Definition MapsTo (x:key)(v:A)(m:t A) := find x m = Some v. - - Definition In (x:key)(m:t A) := exists e:A, MapsTo x e m. - - Definition Empty m := forall (a : key)(e:A) , ~ MapsTo a e m. - - Definition eq_key (p p':key*A) := E.eq (fst p) (fst p'). - - Definition eq_key_elt (p p':key*A) := - E.eq (fst p) (fst p') /\ (snd p) = (snd p'). - - Definition lt_key (p p':key*A) := E.lt (fst p) (fst p'). - - Lemma Empty_alt : forall m, Empty m <-> forall a, find a m = None. - Proof. - unfold Empty, MapsTo. - intuition. - generalize (H a). - destruct (find a m); intuition. - elim (H0 a0); auto. - rewrite H in H0; discriminate. - Qed. - - Section Spec. - Variable m m' m'' : t A. - Variable x y z : key. - Variable e e' : A. - - Lemma MapsTo_1 : E.eq x y -> MapsTo x e m -> MapsTo y e m. - Proof. intros; rewrite <- H; auto. Qed. - - Lemma find_1 : MapsTo x e m -> find x m = Some e. - Proof. unfold MapsTo; auto. Qed. - - Lemma find_2 : find x m = Some e -> MapsTo x e m. - Proof. red; auto. Qed. - - Lemma empty_1 : Empty empty. - Proof. - rewrite Empty_alt; intros; unfold empty, find; simpl; auto. - Qed. - - Lemma is_empty_1 : Empty m -> is_empty m = true. - Proof. - unfold Empty, is_empty, find; intros. - cut (MapCanonicalize _ m = M0 _). - intros; rewrite H0; simpl; auto. - apply mapcanon_unique. - apply mapcanon_exists_2. - constructor. - red; red; simpl; intros. - rewrite <- (mapcanon_exists_1 _ m). - unfold MapsTo, find in *. - generalize (H a). - destruct (MapGet _ m a); auto. - intros; generalize (H0 a0); destruct 1; auto. - Qed. - - Lemma is_empty_2 : is_empty m = true -> Empty m. - Proof. - unfold Empty, is_empty, MapsTo, find; intros. - generalize (MapEmptyp_complete _ _ H); clear H; intros. - rewrite (mapcanon_exists_1 _ m). - rewrite H; simpl; auto. - discriminate. - Qed. - - Lemma mem_1 : In x m -> mem x m = true. - Proof. - unfold In, MapsTo, mem. - destruct (find x m); auto. - destruct 1; discriminate. - Qed. - - Lemma mem_2 : forall m x, mem x m = true -> In x m. - Proof. - unfold In, MapsTo, mem. - intros. - destruct (find x0 m0); auto; try discriminate. - exists a; auto. - Qed. - - Lemma add_1 : E.eq x y -> MapsTo y e (add x e m). - Proof. - unfold MapsTo, find, add. - intro H; rewrite H; clear H. - rewrite MapPut_semantics. - rewrite Neqb_correct; auto. - Qed. - - Lemma add_2 : ~ E.eq x y -> MapsTo y e m -> MapsTo y e (add x e' m). - Proof. - unfold MapsTo, find, add. - intros. - rewrite MapPut_semantics. - rewrite H0. - generalize (Neqb_complete x y). - destruct (Neqb x y); auto. - intros. - elim H; auto. - apply H1; auto. - Qed. - - Lemma add_3 : ~ E.eq x y -> MapsTo y e (add x e' m) -> MapsTo y e m. - Proof. - unfold MapsTo, find, add. - rewrite MapPut_semantics. - intro H. - generalize (Neqb_complete x y). - destruct (Neqb x y); auto. - intros; elim H; auto. - apply H0; auto. - Qed. - - Lemma remove_1 : E.eq x y -> ~ In y (remove x m). - Proof. - unfold In, MapsTo, find, remove. - rewrite MapRemove_semantics. - intro H. - rewrite H; rewrite Neqb_correct. - red; destruct 1; discriminate. - Qed. - - Lemma remove_2 : ~ E.eq x y -> MapsTo y e m -> MapsTo y e (remove x m). - Proof. - unfold MapsTo, find, remove. - rewrite MapRemove_semantics. - intros. - rewrite H0. - generalize (Neqb_complete x y). - destruct (Neqb x y); auto. - intros; elim H; apply H1; auto. - Qed. - - Lemma remove_3 : MapsTo y e (remove x m) -> MapsTo y e m. - Proof. - unfold MapsTo, find, remove. - rewrite MapRemove_semantics. - destruct (Neqb x y); intros; auto. - discriminate. - Qed. - - Lemma alist_sorted_sort : forall l, alist_sorted A l=true -> sort lt_key l. - Proof. - induction l. - auto. - simpl. - destruct a. - destruct l. - auto. - destruct p. - intros; destruct (andb_prop _ _ H); auto. - Qed. - - Lemma elements_3 : sort lt_key (elements m). - Proof. - unfold elements. - apply alist_sorted_sort. - apply alist_of_Map_sorts. - Qed. - - Lemma elements_1 : - MapsTo x e m -> InA eq_key_elt (x,e) (elements m). - Proof. - unfold MapsTo, find, elements. - rewrite InA_alt. - intro H. - exists (x,e). - split. - red; simpl; unfold E.eq; auto. - rewrite alist_of_Map_semantics in H. - generalize H. - set (l:=alist_of_Map A m); clearbody l; clear. - induction l; simpl; auto. - intro; discriminate. - destruct a; simpl; auto. - generalize (Neqb_complete a x). - destruct (Neqb a x); auto. - left. - injection H0; auto. - intros; f_equal; auto. - Qed. - - Lemma elements_2 : - InA eq_key_elt (x,e) (elements m) -> MapsTo x e m. - Proof. - generalize elements_3. - unfold MapsTo, find, elements. - rewrite InA_alt. - intros H ((e0,a),(H0,H1)). - red in H0; simpl in H0; unfold E.eq in H0; destruct H0; subst. - rewrite alist_of_Map_semantics. - generalize H H1; clear H H1. - set (l:=alist_of_Map A m); clearbody l; clear. - induction l; simpl; auto. - intro; contradiction. - intros. - destruct a0; simpl. - inversion H1. - injection H0; intros; subst. - rewrite Neqb_correct; auto. - assert (InA eq_key (e0,a) l). - rewrite InA_alt. - exists (e0,a); split; auto. - red; simpl; auto; red; auto. - generalize (PE.Sort_In_cons_1 H H2). - unfold PE.ltk; simpl. - intros H3; generalize (E.lt_not_eq H3). - generalize (Neqb_complete a0 e0). - destruct (Neqb a0 e0); auto. - destruct 2. - apply H4; auto. - inversion H; auto. - Qed. - - Definition Equal cmp m m' := - (forall k, In k m <-> In k m') /\ - (forall k e e', MapsTo k e m -> MapsTo k e' m' -> cmp e e' = true). - - (** unfortunately, the [MapFold] of [IntMap] isn't compatible with - the FMap interface. We use a naive version for now : *) - - Definition fold (B:Set)(f:key -> A -> B -> B)(m:t A)(i:B) : B := - fold_left (fun a p => f (fst p) (snd p) a) (elements m) i. - - Lemma fold_1 : - forall (B:Set) (i : B) (f : key -> A -> B -> B), - fold f m i = fold_left (fun a p => f (fst p) (snd p) a) (elements m) i. - Proof. auto. Qed. - - End Spec. - - Variable B : Set. - - Fixpoint mapi_aux (pf:N->N)(f : N -> A -> B)(m:t A) { struct m }: t B := - match m with - | M0 => M0 _ - | M1 x y => M1 _ x (f (pf x) y) - | M2 m0 m1 => M2 _ (mapi_aux (fun n => pf (Ndouble n)) f m0) - (mapi_aux (fun n => pf (Ndouble_plus_one n)) f m1) - end. - - Definition mapi := mapi_aux (fun n => n). - - Definition map (f:A->B) := mapi (fun _ => f). - - End A. - - Lemma mapi_aux_1 : forall (elt elt':Set)(m: t elt)(pf:N->N)(x:key)(e:elt) - (f:key->elt->elt'), MapsTo x e m -> - exists y, E.eq y x /\ MapsTo x (f (pf y) e) (mapi_aux pf f m). - Proof. - unfold MapsTo; induction m; simpl; auto. - inversion 1. - - intros. - exists x; split; [red; auto|]. - generalize (Neqb_complete a x). - destruct (Neqb a x); try discriminate. - injection H; intros; subst; auto. - rewrite H1; auto. - - intros. - exists x; split; [red;auto|]. - destruct x; simpl in *. - destruct (IHm1 (fun n : N => pf (Ndouble n)) _ _ f H) as (y,(Hy,Hy')). - rewrite Hy in Hy'; simpl in Hy'; auto. - destruct p; simpl in *. - destruct (IHm2 (fun n : N => pf (Ndouble_plus_one n)) _ _ f H) as (y,(Hy,Hy')). - rewrite Hy in Hy'; simpl in Hy'; auto. - destruct (IHm1 (fun n : N => pf (Ndouble n)) _ _ f H) as (y,(Hy,Hy')). - rewrite Hy in Hy'; simpl in Hy'; auto. - destruct (IHm2 (fun n : N => pf (Ndouble_plus_one n)) _ _ f H) as (y,(Hy,Hy')). - rewrite Hy in Hy'; simpl in Hy'; auto. - Qed. - - Lemma mapi_1 : forall (elt elt':Set)(m: t elt)(x:key)(e:elt) - (f:key->elt->elt'), MapsTo x e m -> - exists y, E.eq y x /\ MapsTo x (f y e) (mapi f m). - Proof. - intros elt elt' m; exact (mapi_aux_1 (fun n => n)). - Qed. - - Lemma mapi_aux_2 : forall (elt elt':Set)(m: t elt)(pf:N->N)(x:key) - (f:key->elt->elt'), In x (mapi_aux pf f m) -> In x m. - Proof. - unfold In, MapsTo. - induction m; simpl in *. - intros pf x f (e,He); inversion He. - intros pf x f (e,He). - exists a0. - destruct (Neqb a x); try discriminate; auto. - intros pf x f (e,He). - destruct x; [|destruct p]; eauto. - Qed. - - Lemma mapi_2 : forall (elt elt':Set)(m: t elt)(x:key) - (f:key->elt->elt'), In x (mapi f m) -> In x m. - Proof. - intros elt elt' m; exact (mapi_aux_2 m (fun n => n)). - Qed. - - Lemma map_1 : forall (elt elt':Set)(m: t elt)(x:key)(e:elt)(f:elt->elt'), - MapsTo x e m -> MapsTo x (f e) (map f m). - Proof. - unfold map; intros. - destruct (@mapi_1 _ _ m x e (fun _ => f)) as (e',(_,H0)); auto. - Qed. - - Lemma map_2 : forall (elt elt':Set)(m: t elt)(x:key)(f:elt->elt'), - In x (map f m) -> In x m. - Proof. - unfold map; intros. - eapply mapi_2; eauto. - Qed. - - Module L := FMapList.Raw E. - - (** Not exactly pretty nor perfect, but should suffice as a first naive implem. - Anyway, map2 isn't in Ocaml... - *) - - Definition anti_elements (A:Set)(l:list (key*A)) := L.fold (@add _) l (empty _). - - Definition map2 (A B C:Set)(f:option A->option B -> option C)(m:t A)(m':t B) : t C := - anti_elements (L.map2 f (elements m) (elements m')). - - Lemma add_spec : forall (A:Set)(m:t A) x y e, - find x (add y e m) = if ME.eq_dec x y then Some e else find x m. - Proof. - intros. - destruct (ME.eq_dec x y). - apply find_1. - eapply MapsTo_1 with y; eauto. - red; auto. - apply add_1; auto. - red; auto. - case_eq (find x m); intros. - apply find_1. - apply add_2; unfold E.eq in *; auto. - case_eq (find x (add y e m)); auto; intros. - rewrite <- H; symmetry. - apply find_1; auto. - apply (@add_3 _ m y x a e); unfold E.eq in *; auto. - Qed. - - Lemma anti_elements_mapsto_aux : forall (A:Set)(l:list (key*A)) m k e, - NoDupA (eq_key (A:=A)) l -> - (forall x, L.PX.In x l -> In x m -> False) -> - (MapsTo k e (L.fold (@add _) l m) <-> L.PX.MapsTo k e l \/ MapsTo k e m). - Proof. - induction l. - simpl; auto. - intuition. - inversion H2. - simpl; destruct a; intros. - rewrite IHl; clear IHl. - inversion H; auto. - intros. - inversion_clear H. - assert (~E.eq x k). - swap H3. - destruct H1. - apply InA_eqA with (x,x0); eauto. - unfold eq_key, E.eq; eauto. - unfold eq_key, E.eq; congruence. - apply (H0 x). - destruct H1; exists x0; auto. - revert H2. - unfold In. - intros (e',He'). - exists e'; apply (@add_3 _ m k x e' a); unfold E.eq; auto. - intuition. - red in H2. - rewrite add_spec in H2; auto. - destruct (ME.eq_dec k0 k). - inversion_clear H2; subst; auto. - right; apply find_2; auto. - inversion_clear H2; auto. - compute in H1; destruct H1. - subst; right; apply add_1; auto. - red; auto. - inversion_clear H. - destruct (ME.eq_dec k0 k). - unfold E.eq in *; subst. - destruct (H0 k); eauto. - red; eauto. - right; apply add_2; unfold E.eq in *; auto. - Qed. - - Lemma anti_elements_mapsto : forall (A:Set) l k e, NoDupA (eq_key (A:=A)) l -> - (MapsTo k e (anti_elements l) <-> L.PX.MapsTo k e l). - Proof. - intros. - unfold anti_elements. - rewrite anti_elements_mapsto_aux; auto; unfold empty; auto. - inversion 2. - inversion H2. - intuition. - inversion H1. - Qed. - - Lemma find_anti_elements : forall (A:Set)(l: list (key*A)) x, sort (@lt_key _) l -> - find x (anti_elements l) = L.find x l. - Proof. - intros. - case_eq (L.find x l); intros. - apply find_1. - rewrite anti_elements_mapsto. - apply L.PX.Sort_NoDupA; auto. - apply L.find_2; auto. - case_eq (find x (anti_elements l)); auto; intros. - rewrite <- H0; symmetry. - apply L.find_1; auto. - rewrite <- anti_elements_mapsto. - apply L.PX.Sort_NoDupA; auto. - apply find_2; auto. - Qed. - - Lemma find_elements : forall (A:Set)(m: t A) x, - L.find x (elements m) = find x m. - Proof. - intros. - case_eq (find x m); intros. - apply L.find_1. - apply elements_3; auto. - red; apply elements_1. - apply find_2; auto. - case_eq (L.find x (elements m)); auto; intros. - rewrite <- H; symmetry. - apply find_1; auto. - apply elements_2. - apply L.find_2; auto. - Qed. - - Lemma elements_in : forall (A:Set)(s:t A) x, L.PX.In x (elements s) <-> In x s. - Proof. - intros. - unfold L.PX.In, In. - firstorder. - exists x0. - red; rewrite <- find_elements; auto. - apply L.find_1; auto. - apply elements_3. - exists x0. - apply L.find_2. - rewrite find_elements; auto. - Qed. - - Lemma map2_1 : forall (A B C:Set)(m: t A)(m': t B)(x:key) - (f:option A->option B ->option C), - In x m \/ In x m' -> find x (map2 f m m') = f (find x m) (find x m'). - Proof. - unfold map2; intros. - rewrite find_anti_elements; auto. - rewrite <- find_elements; auto. - rewrite <- find_elements; auto. - apply L.map2_1; auto. - apply elements_3; auto. - apply elements_3; auto. - do 2 rewrite elements_in; auto. - apply L.map2_sorted; auto. - apply elements_3; auto. - apply elements_3; auto. - Qed. - - Lemma map2_2 : forall (A B C: Set)(m: t A)(m': t B)(x:key) - (f:option A->option B ->option C), - In x (map2 f m m') -> In x m \/ In x m'. - Proof. - unfold map2; intros. - do 2 rewrite <- elements_in. - apply L.map2_2 with (f:=f); auto. - apply elements_3; auto. - apply elements_3; auto. - destruct H. - exists x0. - rewrite <- anti_elements_mapsto; auto. - apply L.PX.Sort_NoDupA; auto. - apply L.map2_sorted; auto. - apply elements_3; auto. - apply elements_3; auto. - Qed. - - (** same trick for [equal] *) - - Definition equal (A:Set)(cmp:A -> A -> bool)(m m' : t A) : bool := - L.equal cmp (elements m) (elements m'). - - Lemma equal_1 : - forall (A:Set)(m: t A)(m': t A)(cmp: A -> A -> bool), - Equal cmp m m' -> equal cmp m m' = true. - Proof. - unfold equal, Equal. - intros. - apply L.equal_1. - apply elements_3. - apply elements_3. - unfold L.Equal. - destruct H. - split; intros. - do 2 rewrite elements_in; auto. - apply (H0 k); - red; rewrite <- find_elements; apply L.find_1; auto; - apply elements_3. - Qed. - - Lemma equal_2 : - forall (A:Set)(m: t A)(m': t A)(cmp: A -> A -> bool), - equal cmp m m' = true -> Equal cmp m m'. - Proof. - unfold equal, Equal. - intros. - destruct (L.equal_2 (elements_3 m) (elements_3 m') H); clear H. - split. - intros; do 2 rewrite <- elements_in; auto. - intros; apply (H1 k); - apply L.find_2; rewrite find_elements;auto. - Qed. - -End MapIntMap. - diff --git a/theories/FSets/FMapInterface.v b/theories/FSets/FMapInterface.v index dde74a0a..1e475887 100644 --- a/theories/FSets/FMapInterface.v +++ b/theories/FSets/FMapInterface.v @@ -6,42 +6,72 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: FMapInterface.v 8671 2006-03-29 08:31:28Z letouzey $ *) +(* $Id: FMapInterface.v 10616 2008-03-04 17:33:35Z letouzey $ *) (** * Finite map library *) -(** This file proposes an interface for finite maps *) +(** This file proposes interfaces for finite maps *) -(* begin hide *) +Require Export Bool DecidableType OrderedType. Set Implicit Arguments. Unset Strict Implicit. -Require Import FSetInterface. -(* end hide *) - -(** When compared with Ocaml Map, this signature has been split in two: - - The first part [S] contains the usual operators (add, find, ...) - It only requires a ordered key type, the data type can be arbitrary. - The only function that asks more is [equal], whose first argument should - be an equality on data. - - Then, [Sord] extends [S] with a complete comparison function. For - that, the data type should have a decidable total ordering. + +(** When compared with Ocaml Map, this signature has been split in + several parts : + + - The first parts [WSfun] and [WS] propose signatures for weak + maps, which are maps with no ordering on the key type nor the + data type. [WSfun] and [WS] are almost identical, apart from the + fact that [WSfun] is expressed in a functorial way whereas [WS] + is self-contained. For obtaining an instance of such signatures, + a decidable equality on keys in enough (see for example + [FMapWeakList]). These signatures contain the usual operators + (add, find, ...). The only function that asks for more is + [equal], whose first argument should be a comparison on data. + + - Then comes [Sfun] and [S], that extend [WSfun] and [WS] to the + case where the key type is ordered. The main novelty is that + [elements] is required to produce sorted lists. + + - Finally, [Sord] extends [S] with a complete comparison function. For + that, the data type should have a decidable total ordering as well. + + If unsure, what you're looking for is probably [S]: apart from [Sord], + all other signatures are subsets of [S]. + + Some additional differences with Ocaml: + + - no [iter] function, useless since Coq is purely functional + - [option] types are used instead of [Not_found] exceptions + - more functions are provided: [elements] and [cardinal] and [map2] + *) -Module Type S. +Definition Cmp (elt:Type)(cmp:elt->elt->bool) e1 e2 := cmp e1 e2 = true. - Declare Module E : OrderedType. +(** ** Weak signature for maps + + No requirements for an ordering on keys nor elements, only decidability + of equality on keys. First, a functorial signature: *) + +Module Type WSfun (E : EqualityType). + + (** The module E of base objects is meant to be a [DecidableType] + (and used to be so). But requiring only an [EqualityType] here + allows subtyping between weak and ordered maps. *) Definition key := E.t. - Parameter t : Set -> Set. (** the abstract type of maps *) + Parameter t : Type -> Type. + (** the abstract type of maps *) Section Types. - Variable elt:Set. + Variable elt:Type. Parameter empty : t elt. - (** The empty map. *) + (** The empty map. *) Parameter is_empty : t elt -> bool. (** Test whether a map is empty or not. *) @@ -53,8 +83,7 @@ Module Type S. Parameter find : key -> t elt -> option elt. (** [find x m] returns the current binding of [x] in [m], - or raises [Not_found] if no such binding exists. - NB: in Coq, the exception mechanism becomes a option type. *) + or [None] if no such binding exists. *) Parameter remove : key -> t elt -> t elt. (** [remove x m] returns a map containing the same bindings as [m], @@ -64,45 +93,36 @@ Module Type S. (** [mem x m] returns [true] if [m] contains a binding for [x], and [false] otherwise. *) - (** Coq comment: [iter] is useless in a purely functional world *) - (** val iter : (key -> 'a -> unit) -> 'a t -> unit *) - (** iter f m applies f to all bindings in map m. f receives the key as - first argument, and the associated value as second argument. - The bindings are passed to f in increasing order with respect to the - ordering over the type of the keys. Only current bindings are - presented to f: bindings hidden by more recent bindings are not - passed to f. *) - - Variable elt' : Set. - Variable elt'': Set. + Variable elt' elt'' : Type. Parameter map : (elt -> elt') -> t elt -> t elt'. (** [map f m] returns a map with same domain as [m], where the associated value a of all bindings of [m] has been replaced by the result of the - application of [f] to [a]. The bindings are passed to [f] in - increasing order with respect to the ordering over the type of the - keys. *) + application of [f] to [a]. Since Coq is purely functional, the order + in which the bindings are passed to [f] is irrelevant. *) Parameter mapi : (key -> elt -> elt') -> t elt -> t elt'. - (** Same as [S.map], but the function receives as arguments both the + (** Same as [map], but the function receives as arguments both the key and the associated value for each binding of the map. *) - Parameter map2 : (option elt -> option elt' -> option elt'') -> t elt -> t elt' -> t elt''. - (** Not present in Ocaml. - [map f m m'] creates a new map whose bindings belong to the ones of either - [m] or [m']. The presence and value for a key [k] is determined by [f e e'] - where [e] and [e'] are the (optional) bindings of [k] in [m] and [m']. *) + Parameter map2 : + (option elt -> option elt' -> option elt'') -> t elt -> t elt' -> t elt''. + (** [map2 f m m'] creates a new map whose bindings belong to the ones + of either [m] or [m']. The presence and value for a key [k] is + determined by [f e e'] where [e] and [e'] are the (optional) bindings + of [k] in [m] and [m']. *) Parameter elements : t elt -> list (key*elt). - (** Not present in Ocaml. - [elements m] returns an assoc list corresponding to the bindings of [m]. - Elements of this list are sorted with respect to their first components. - Useful to specify [fold] ... *) + (** [elements m] returns an assoc list corresponding to the bindings + of [m], in any order. *) - Parameter fold : forall A: Set, (key -> elt -> A -> A) -> t elt -> A -> A. + Parameter cardinal : t elt -> nat. + (** [cardinal m] returns the number of bindings in [m]. *) + + Parameter fold : forall A: Type, (key -> elt -> A -> A) -> t elt -> A -> A. (** [fold f m a] computes [(f kN dN ... (f k1 d1 a)...)], where [k1] ... [kN] are the keys of all bindings in [m] - (in increasing order), and [d1] ... [dN] are the associated data. *) + (in any order), and [d1] ... [dN] are the associated data. *) Parameter equal : (elt -> elt -> bool) -> t elt -> t elt -> bool. (** [equal cmp m1 m2] tests whether the maps [m1] and [m2] are equal, @@ -127,8 +147,6 @@ Module Type S. Definition eq_key_elt (p p':key*elt) := E.eq (fst p) (fst p') /\ (snd p) = (snd p'). - Definition lt_key (p p':key*elt) := E.lt (fst p) (fst p'). - (** Specification of [MapsTo] *) Parameter MapsTo_1 : E.eq x y -> MapsTo x e m -> MapsTo y e m. @@ -162,61 +180,123 @@ Module Type S. MapsTo x e m -> InA eq_key_elt (x,e) (elements m). Parameter elements_2 : InA eq_key_elt (x,e) (elements m) -> MapsTo x e m. - Parameter elements_3 : sort lt_key (elements m). + (** When compared with ordered maps, here comes the only + property that is really weaker: *) + Parameter elements_3w : NoDupA eq_key (elements m). + + (** Specification of [cardinal] *) + Parameter cardinal_1 : cardinal m = length (elements m). (** Specification of [fold] *) Parameter fold_1 : - forall (A : Set) (i : A) (f : key -> elt -> A -> A), + forall (A : Type) (i : A) (f : key -> elt -> A -> A), fold f m i = fold_left (fun a p => f (fst p) (snd p) a) (elements m) i. + + (** Equality of maps *) - Definition Equal cmp m m' := + (** Caveat: there are at least three distinct equality predicates on maps. + - The simpliest (and maybe most natural) way is to consider keys up to + their equivalence [E.eq], but elements up to Leibniz equality, in + the spirit of [eq_key_elt] above. This leads to predicate [Equal]. + - Unfortunately, this [Equal] predicate can't be used to describe + the [equal] function, since this function (for compatibility with + ocaml) expects a boolean comparison [cmp] that may identify more + elements than Leibniz. So logical specification of [equal] is done + via another predicate [Equivb] + - This predicate [Equivb] is quite ad-hoc with its boolean [cmp], + it can be generalized in a [Equiv] expecting a more general + (possibly non-decidable) equality predicate on elements *) + + Definition Equal m m' := forall y, find y m = find y m'. + Definition Equiv (eq_elt:elt->elt->Prop) m m' := (forall k, In k m <-> In k m') /\ - (forall k e e', MapsTo k e m -> MapsTo k e' m' -> cmp e e' = true). + (forall k e e', MapsTo k e m -> MapsTo k e' m' -> eq_elt e e'). + Definition Equivb (cmp: elt->elt->bool) := Equiv (Cmp cmp). - Variable cmp : elt -> elt -> bool. + (** Specification of [equal] *) - (** Specification of [equal] *) - Parameter equal_1 : Equal cmp m m' -> equal cmp m m' = true. - Parameter equal_2 : equal cmp m m' = true -> Equal cmp m m'. + Variable cmp : elt -> elt -> bool. - End Spec. - End Types. + Parameter equal_1 : Equivb cmp m m' -> equal cmp m m' = true. + Parameter equal_2 : equal cmp m m' = true -> Equivb cmp m m'. + + End Spec. + End Types. (** Specification of [map] *) - Parameter map_1 : forall (elt elt':Set)(m: t elt)(x:key)(e:elt)(f:elt->elt'), + Parameter map_1 : forall (elt elt':Type)(m: t elt)(x:key)(e:elt)(f:elt->elt'), MapsTo x e m -> MapsTo x (f e) (map f m). - Parameter map_2 : forall (elt elt':Set)(m: t elt)(x:key)(f:elt->elt'), + Parameter map_2 : forall (elt elt':Type)(m: t elt)(x:key)(f:elt->elt'), In x (map f m) -> In x m. (** Specification of [mapi] *) - Parameter mapi_1 : forall (elt elt':Set)(m: t elt)(x:key)(e:elt) + Parameter mapi_1 : forall (elt elt':Type)(m: t elt)(x:key)(e:elt) (f:key->elt->elt'), MapsTo x e m -> exists y, E.eq y x /\ MapsTo x (f y e) (mapi f m). - Parameter mapi_2 : forall (elt elt':Set)(m: t elt)(x:key) + Parameter mapi_2 : forall (elt elt':Type)(m: t elt)(x:key) (f:key->elt->elt'), In x (mapi f m) -> In x m. (** Specification of [map2] *) - Parameter map2_1 : forall (elt elt' elt'':Set)(m: t elt)(m': t elt') + Parameter map2_1 : forall (elt elt' elt'':Type)(m: t elt)(m': t elt') (x:key)(f:option elt->option elt'->option elt''), In x m \/ In x m' -> find x (map2 f m m') = f (find x m) (find x m'). - Parameter map2_2 : forall (elt elt' elt'':Set)(m: t elt)(m': t elt') + Parameter map2_2 : forall (elt elt' elt'':Type)(m: t elt)(m': t elt') (x:key)(f:option elt->option elt'->option elt''), In x (map2 f m m') -> In x m \/ In x m'. - (* begin hide *) - Hint Immediate MapsTo_1 mem_2 is_empty_2. - - Hint Resolve mem_1 is_empty_1 is_empty_2 add_1 add_2 add_3 remove_1 - remove_2 remove_3 find_1 find_2 fold_1 map_1 map_2 mapi_1 mapi_2. - (* end hide *) + Hint Immediate MapsTo_1 mem_2 is_empty_2 + map_2 mapi_2 add_3 remove_3 find_2 + : map. + Hint Resolve mem_1 is_empty_1 is_empty_2 add_1 add_2 remove_1 + remove_2 find_1 fold_1 map_1 mapi_1 mapi_2 + : map. +End WSfun. + + +(** ** Static signature for Weak Maps + + Similar to [WSfun] but expressed in a self-contained way. *) + +Module Type WS. + Declare Module E : EqualityType. + Include Type WSfun E. +End WS. + + + +(** ** Maps on ordered keys, functorial signature *) + +Module Type Sfun (E : OrderedType). + Include Type WSfun E. + Section elt. + Variable elt:Type. + Definition lt_key (p p':key*elt) := E.lt (fst p) (fst p'). + (* Additional specification of [elements] *) + Parameter elements_3 : forall m, sort lt_key (elements m). + (** Remark: since [fold] is specified via [elements], this stronger + specification of [elements] has an indirect impact on [fold], + which can now be proved to receive elements in increasing order. *) + End elt. +End Sfun. + + + +(** ** Maps on ordered keys, self-contained signature *) + +Module Type S. + Declare Module E : OrderedType. + Include Type Sfun E. End S. + +(** ** Maps with ordering both on keys and datas *) + Module Type Sord. - + Declare Module Data : OrderedType. Declare Module MapS : S. Import MapS. @@ -234,12 +314,11 @@ Module Type Sord. Definition cmp e e' := match Data.compare e e' with EQ _ => true | _ => false end. - Parameter eq_1 : forall m m', Equal cmp m m' -> eq m m'. - Parameter eq_2 : forall m m', eq m m' -> Equal cmp m m'. + Parameter eq_1 : forall m m', Equivb cmp m m' -> eq m m'. + Parameter eq_2 : forall m m', eq m m' -> Equivb cmp m m'. Parameter compare : forall m1 m2, Compare lt eq m1 m2. - (** Total ordering between maps. The first argument (in Coq: Data.compare) - is a total ordering used to compare data associated with equal keys - in the two maps. *) + (** Total ordering between maps. [Data.compare] is a total ordering + used to compare data associated with equal keys in the two maps. *) -End Sord.
\ No newline at end of file +End Sord. diff --git a/theories/FSets/FMapList.v b/theories/FSets/FMapList.v index 067f5a3e..23bf8196 100644 --- a/theories/FSets/FMapList.v +++ b/theories/FSets/FMapList.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: FMapList.v 9035 2006-07-09 15:42:09Z herbelin $ *) +(* $Id: FMapList.v 10616 2008-03-04 17:33:35Z letouzey $ *) (** * Finite map library *) @@ -14,7 +14,6 @@ [FMapInterface.S] using lists of pairs ordered (increasing) with respect to left projection. *) -Require Import FSetInterface. Require Import FMapInterface. Set Implicit Arguments. @@ -22,26 +21,14 @@ Unset Strict Implicit. Module Raw (X:OrderedType). -Module E := X. -Module MX := OrderedTypeFacts X. -Module PX := KeyOrderedType X. -Import MX. -Import PX. +Module Import MX := OrderedTypeFacts X. +Module Import PX := KeyOrderedType X. Definition key := X.t. -Definition t (elt:Set) := list (X.t * elt). +Definition t (elt:Type) := list (X.t * elt). Section Elt. -Variable elt : Set. - -(* Now in KeyOrderedType: -Definition eqk (p p':key*elt) := X.eq (fst p) (fst p'). -Definition eqke (p p':key*elt) := - X.eq (fst p) (fst p') /\ (snd p) = (snd p'). -Definition ltk (p p':key*elt) := X.lt (fst p) (fst p'). -Definition MapsTo (k:key)(e:elt):= InA eqke (k,e). -Definition In k m := exists e:elt, MapsTo k e m. -*) +Variable elt : Type. Notation eqk := (eqk (elt:=elt)). Notation eqke := (eqke (elt:=elt)). @@ -347,15 +334,22 @@ Proof. auto. Qed. +Lemma elements_3w : forall m (Hm:Sort m), NoDupA eqk (elements m). +Proof. + intros. + apply Sort_NoDupA. + apply elements_3; auto. +Qed. + (** * [fold] *) -Function fold (A:Set)(f:key->elt->A->A)(m:t elt) (acc:A) {struct m} : A := +Function fold (A:Type)(f:key->elt->A->A)(m:t elt) (acc:A) {struct m} : A := match m with | nil => acc | (k,e)::m' => fold f m' (f k e acc) end. -Lemma fold_1 : forall m (A:Set)(i:A)(f:key->elt->A->A), +Lemma fold_1 : forall m (A:Type)(i:A)(f:key->elt->A->A), fold f m i = fold_left (fun a p => f (fst p) (snd p) a) (elements m) i. Proof. intros; functional induction (fold f m i); auto. @@ -374,29 +368,24 @@ Function equal (cmp:elt->elt->bool)(m m' : t elt) { struct m } : bool := | _, _ => false end. -Definition Equal cmp m m' := +Definition Equivb cmp m m' := (forall k, In k m <-> In k m') /\ (forall k e e', MapsTo k e m -> MapsTo k e' m' -> cmp e e' = true). Lemma equal_1 : forall m (Hm:Sort m) m' (Hm': Sort m') cmp, - Equal cmp m m' -> equal cmp m m' = true. + Equivb cmp m m' -> equal cmp m m' = true. Proof. intros m Hm m' Hm' cmp; generalize Hm Hm'; clear Hm Hm'. - functional induction (equal cmp m m'); simpl; subst;auto; unfold Equal; - intuition; subst; match goal with - | [H: X.compare _ _ = _ |- _ ] => clear H - | _ => idtac - end. - - - + functional induction (equal cmp m m'); simpl; subst;auto; unfold Equivb; + intuition; subst. + match goal with H: X.compare _ _ = _ |- _ => clear H end. assert (cmp_e_e':cmp e e' = true). apply H1 with x; auto. rewrite cmp_e_e'; simpl. apply IHb; auto. inversion_clear Hm; auto. inversion_clear Hm'; auto. - unfold Equal; intuition. + unfold Equivb; intuition. destruct (H0 k). assert (In k ((x,e) ::l)). destruct H as (e'', hyp); exists e''; auto. @@ -459,14 +448,12 @@ Qed. Lemma equal_2 : forall m (Hm:Sort m) m' (Hm:Sort m') cmp, - equal cmp m m' = true -> Equal cmp m m'. + equal cmp m m' = true -> Equivb cmp m m'. Proof. intros m Hm m' Hm' cmp; generalize Hm Hm'; clear Hm Hm'. - functional induction (equal cmp m m'); simpl; subst;auto; unfold Equal; - intuition; try discriminate; subst; match goal with - | [H: X.compare _ _ = _ |- _ ] => clear H - | _ => idtac - end. + functional induction (equal cmp m m'); simpl; subst;auto; unfold Equivb; + intuition; try discriminate; subst; + try match goal with H: X.compare _ _ = _ |- _ => clear H end. inversion H0. @@ -502,13 +489,13 @@ Proof. elim (Sort_Inf_NotIn H2 H3). exists e0; apply MapsTo_eq with k; auto; order. apply H8 with k; auto. -Qed. +Qed. -(** This lemma isn't part of the spec of [Equal], but is used in [FMapAVL] *) +(** This lemma isn't part of the spec of [Equivb], but is used in [FMapAVL] *) Lemma equal_cons : forall cmp l1 l2 x y, Sort (x::l1) -> Sort (y::l2) -> eqk x y -> cmp (snd x) (snd y) = true -> - (Equal cmp l1 l2 <-> Equal cmp (x :: l1) (y :: l2)). + (Equivb cmp l1 l2 <-> Equivb cmp (x :: l1) (y :: l2)). Proof. intros. inversion H; subst. @@ -527,7 +514,7 @@ Proof. rewrite H2; simpl; auto. Qed. -Variable elt':Set. +Variable elt':Type. (** * [map] and [mapi] *) @@ -548,7 +535,7 @@ Section Elt2. (* A new section is necessary for previous definitions to work with different [elt], especially [MapsTo]... *) -Variable elt elt' : Set. +Variable elt elt' : Type. (** Specification of [map] *) @@ -684,10 +671,10 @@ Section Elt3. (** * [map2] *) -Variable elt elt' elt'' : Set. +Variable elt elt' elt'' : Type. Variable f : option elt -> option elt' -> option elt''. -Definition option_cons (A:Set)(k:key)(o:option A)(l:list (key*A)) := +Definition option_cons (A:Type)(k:key)(o:option A)(l:list (key*A)) := match o with | Some e => (k,e)::l | None => l @@ -739,7 +726,7 @@ Fixpoint combine (m : t elt) : t elt' -> t oee' := end end. -Definition fold_right_pair (A B C:Set)(f: A->B->C->C)(l:list (A*B))(i:C) := +Definition fold_right_pair (A B C:Type)(f: A->B->C->C)(l:list (A*B))(i:C) := List.fold_right (fun p => f (fst p) (snd p)) i l. Definition map2_alt m m' := @@ -1038,12 +1025,12 @@ Module E := X. Definition key := E.t. -Record slist (elt:Set) : Set := +Record slist (elt:Type) := {this :> Raw.t elt; sorted : sort (@Raw.PX.ltk elt) this}. -Definition t (elt:Set) : Set := slist elt. +Definition t (elt:Type) : Type := slist elt. Section Elt. - Variable elt elt' elt'':Set. + Variable elt elt' elt'':Type. Implicit Types m : t elt. Implicit Types x y : key. @@ -1060,13 +1047,19 @@ Section Elt. Definition map2 f m (m':t elt') : t elt'' := Build_slist (Raw.map2_sorted f m.(sorted) m'.(sorted)). Definition elements m : list (key*elt) := @Raw.elements elt m.(this). - Definition fold (A:Set)(f:key->elt->A->A) m (i:A) : A := @Raw.fold elt A f m.(this) i. + Definition cardinal m := length m.(this). + Definition fold (A:Type)(f:key->elt->A->A) m (i:A) : A := @Raw.fold elt A f m.(this) i. Definition equal cmp m m' : bool := @Raw.equal elt cmp m.(this) m'.(this). Definition MapsTo x e m : Prop := Raw.PX.MapsTo x e m.(this). Definition In x m : Prop := Raw.PX.In x m.(this). Definition Empty m : Prop := Raw.Empty m.(this). - Definition Equal cmp m m' : Prop := @Raw.Equal elt cmp m.(this) m'.(this). + + Definition Equal m m' := forall y, find y m = find y m'. + Definition Equiv (eq_elt:elt->elt->Prop) m m' := + (forall k, In k m <-> In k m') /\ + (forall k e e', MapsTo k e m -> MapsTo k e' m' -> eq_elt e e'). + Definition Equivb cmp m m' : Prop := @Raw.Equivb elt cmp m.(this) m'.(this). Definition eq_key : (key*elt) -> (key*elt) -> Prop := @Raw.PX.eqk elt. Definition eq_key_elt : (key*elt) -> (key*elt) -> Prop:= @Raw.PX.eqke elt. @@ -1113,34 +1106,39 @@ Section Elt. Proof. intros m; exact (@Raw.elements_2 elt m.(this)). Qed. Lemma elements_3 : forall m, sort lt_key (elements m). Proof. intros m; exact (@Raw.elements_3 elt m.(this) m.(sorted)). Qed. + Lemma elements_3w : forall m, NoDupA eq_key (elements m). + Proof. intros m; exact (@Raw.elements_3w elt m.(this) m.(sorted)). Qed. + + Lemma cardinal_1 : forall m, cardinal m = length (elements m). + Proof. intros; reflexivity. Qed. - Lemma fold_1 : forall m (A : Set) (i : A) (f : key -> elt -> A -> A), + Lemma fold_1 : forall m (A : Type) (i : A) (f : key -> elt -> A -> A), fold f m i = fold_left (fun a p => f (fst p) (snd p) a) (elements m) i. Proof. intros m; exact (@Raw.fold_1 elt m.(this)). Qed. - Lemma equal_1 : forall m m' cmp, Equal cmp m m' -> equal cmp m m' = true. + Lemma equal_1 : forall m m' cmp, Equivb cmp m m' -> equal cmp m m' = true. Proof. intros m m'; exact (@Raw.equal_1 elt m.(this) m.(sorted) m'.(this) m'.(sorted)). Qed. - Lemma equal_2 : forall m m' cmp, equal cmp m m' = true -> Equal cmp m m'. + Lemma equal_2 : forall m m' cmp, equal cmp m m' = true -> Equivb cmp m m'. Proof. intros m m'; exact (@Raw.equal_2 elt m.(this) m.(sorted) m'.(this) m'.(sorted)). Qed. End Elt. - Lemma map_1 : forall (elt elt':Set)(m: t elt)(x:key)(e:elt)(f:elt->elt'), + Lemma map_1 : forall (elt elt':Type)(m: t elt)(x:key)(e:elt)(f:elt->elt'), MapsTo x e m -> MapsTo x (f e) (map f m). Proof. intros elt elt' m; exact (@Raw.map_1 elt elt' m.(this)). Qed. - Lemma map_2 : forall (elt elt':Set)(m: t elt)(x:key)(f:elt->elt'), + Lemma map_2 : forall (elt elt':Type)(m: t elt)(x:key)(f:elt->elt'), In x (map f m) -> In x m. Proof. intros elt elt' m; exact (@Raw.map_2 elt elt' m.(this)). Qed. - Lemma mapi_1 : forall (elt elt':Set)(m: t elt)(x:key)(e:elt) + Lemma mapi_1 : forall (elt elt':Type)(m: t elt)(x:key)(e:elt) (f:key->elt->elt'), MapsTo x e m -> exists y, E.eq y x /\ MapsTo x (f y e) (mapi f m). Proof. intros elt elt' m; exact (@Raw.mapi_1 elt elt' m.(this)). Qed. - Lemma mapi_2 : forall (elt elt':Set)(m: t elt)(x:key) + Lemma mapi_2 : forall (elt elt':Type)(m: t elt)(x:key) (f:key->elt->elt'), In x (mapi f m) -> In x m. Proof. intros elt elt' m; exact (@Raw.mapi_2 elt elt' m.(this)). Qed. - Lemma map2_1 : forall (elt elt' elt'':Set)(m: t elt)(m': t elt') + Lemma map2_1 : forall (elt elt' elt'':Type)(m: t elt)(m': t elt') (x:key)(f:option elt->option elt'->option elt''), In x m \/ In x m' -> find x (map2 f m m') = f (find x m) (find x m'). @@ -1148,7 +1146,7 @@ Section Elt. intros elt elt' elt'' m m' x f; exact (@Raw.map2_1 elt elt' elt'' f m.(this) m.(sorted) m'.(this) m'.(sorted) x). Qed. - Lemma map2_2 : forall (elt elt' elt'':Set)(m: t elt)(m': t elt') + Lemma map2_2 : forall (elt elt' elt'':Type)(m: t elt)(m': t elt') (x:key)(f:option elt->option elt'->option elt''), In x (map2 f m m') -> In x m \/ In x m'. Proof. @@ -1229,7 +1227,7 @@ Proof. unfold equal, eq in H6; simpl in H6; auto. Qed. -Lemma eq_1 : forall m m', Equal cmp m m' -> eq m m'. +Lemma eq_1 : forall m m', Equivb cmp m m' -> eq m m'. Proof. intros. generalize (@equal_1 D.t m m' cmp). @@ -1237,7 +1235,7 @@ Proof. intuition. Qed. -Lemma eq_2 : forall m m', eq m m' -> Equal cmp m m'. +Lemma eq_2 : forall m m', eq m m' -> Equivb cmp m m'. Proof. intros. generalize (@equal_2 D.t m m' cmp). diff --git a/theories/FSets/FMapPositive.v b/theories/FSets/FMapPositive.v index 44724767..9bc2a599 100644 --- a/theories/FSets/FMapPositive.v +++ b/theories/FSets/FMapPositive.v @@ -11,11 +11,12 @@ * Institution: LRI, CNRS UMR 8623 - Université Paris Sud * 91405 Orsay, France *) -(* $Id: FMapPositive.v 9862 2007-05-25 16:57:06Z letouzey $ *) +(* $Id: FMapPositive.v 10739 2008-04-01 14:45:20Z herbelin $ *) Require Import Bool. Require Import ZArith. Require Import OrderedType. +Require Import OrderedTypeEx. Require Import FMapInterface. Set Implicit Arguments. @@ -36,9 +37,12 @@ Open Local Scope positive_scope. usual order (see [OrderedTypeEx]), we use here a lexicographic order over bits, which is more natural here (lower bits are considered first). *) -Module PositiveOrderedTypeBits <: OrderedType. +Module PositiveOrderedTypeBits <: UsualOrderedType. Definition t:=positive. Definition eq:=@eq positive. + Definition eq_refl := @refl_equal t. + Definition eq_sym := @sym_eq t. + Definition eq_trans := @trans_eq t. Fixpoint bits_lt (p q:positive) { struct p } : Prop := match p, q with @@ -52,15 +56,6 @@ Module PositiveOrderedTypeBits <: OrderedType. Definition lt:=bits_lt. - Lemma eq_refl : forall x : t, eq x x. - Proof. red; auto. Qed. - - Lemma eq_sym : forall x y : t, eq x y -> eq y x. - Proof. red; auto. Qed. - - Lemma eq_trans : forall x y z : t, eq x y -> eq y z -> eq x z. - Proof. red; intros; transitivity y; auto. Qed. - Lemma bits_lt_trans : forall x y z : positive, bits_lt x y -> bits_lt y z -> bits_lt x z. Proof. induction x. @@ -171,17 +166,18 @@ Qed. Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. Module E:=PositiveOrderedTypeBits. + Module ME:=KeyOrderedType E. Definition key := positive. - Inductive tree (A : Set) : Set := + Inductive tree (A : Type) := | Leaf : tree A | Node : tree A -> option A -> tree A -> tree A. Definition t := tree. Section A. - Variable A:Set. + Variable A:Type. Implicit Arguments Leaf [A]. @@ -280,6 +276,15 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. Definition elements (m : t A) := xelements m xH. + (** [cardinal] *) + + Fixpoint cardinal (m : t A) : nat := + match m with + | Leaf => 0%nat + | Node l None r => (cardinal l + cardinal r)%nat + | Node l (Some _) r => S (cardinal l + cardinal r) + end. + Section CompcertSpec. Theorem gempty: @@ -560,6 +565,16 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. exact (xelements_complete i xH m v H). Qed. + Lemma cardinal_1 : + forall (m: t A), cardinal m = length (elements m). + Proof. + unfold elements. + intros m; set (p:=1); clearbody p; revert m p. + induction m; simpl; auto; intros. + rewrite (IHm1 (append p 2)), (IHm2 (append p 3)); auto. + destruct o; rewrite app_length; simpl; omega. + Qed. + End CompcertSpec. Definition MapsTo (i:positive)(v:A)(m:t A) := find i m = Some v. @@ -793,11 +808,17 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. apply xelements_sort; auto. Qed. + Lemma elements_3w : NoDupA eq_key (elements m). + Proof. + change eq_key with (@ME.eqk A). + apply ME.Sort_NoDupA; apply elements_3; auto. + Qed. + End FMapSpec. (** [map] and [mapi] *) - Variable B : Set. + Variable B : Type. Fixpoint xmapi (f : positive -> A -> B) (m : t A) (i : positive) {struct m} : t B := @@ -815,7 +836,7 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. End A. Lemma xgmapi: - forall (A B: Set) (f: positive -> A -> B) (i j : positive) (m: t A), + forall (A B: Type) (f: positive -> A -> B) (i j : positive) (m: t A), find i (xmapi f m j) = option_map (f (append j i)) (find i m). Proof. induction i; intros; destruct m; simpl; auto. @@ -825,7 +846,7 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. Qed. Theorem gmapi: - forall (A B: Set) (f: positive -> A -> B) (i: positive) (m: t A), + forall (A B: Type) (f: positive -> A -> B) (i: positive) (m: t A), find i (mapi f m) = option_map (f i) (find i m). Proof. intros. @@ -836,7 +857,7 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. Qed. Lemma mapi_1 : - forall (elt elt':Set)(m: t elt)(x:key)(e:elt)(f:key->elt->elt'), + forall (elt elt':Type)(m: t elt)(x:key)(e:elt)(f:key->elt->elt'), MapsTo x e m -> exists y, E.eq y x /\ MapsTo x (f y e) (mapi f m). Proof. @@ -851,7 +872,7 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. Qed. Lemma mapi_2 : - forall (elt elt':Set)(m: t elt)(x:key)(f:key->elt->elt'), + forall (elt elt':Type)(m: t elt)(x:key)(f:key->elt->elt'), In x (mapi f m) -> In x m. Proof. intros. @@ -864,21 +885,21 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. simpl in *; discriminate. Qed. - Lemma map_1 : forall (elt elt':Set)(m: t elt)(x:key)(e:elt)(f:elt->elt'), + Lemma map_1 : forall (elt elt':Type)(m: t elt)(x:key)(e:elt)(f:elt->elt'), MapsTo x e m -> MapsTo x (f e) (map f m). Proof. intros; unfold map. destruct (mapi_1 (fun _ => f) H); intuition. Qed. - Lemma map_2 : forall (elt elt':Set)(m: t elt)(x:key)(f:elt->elt'), + Lemma map_2 : forall (elt elt':Type)(m: t elt)(x:key)(f:elt->elt'), In x (map f m) -> In x m. Proof. intros; unfold map in *; eapply mapi_2; eauto. Qed. Section map2. - Variable A B C : Set. + Variable A B C : Type. Variable f : option A -> option B -> option C. Implicit Arguments Leaf [A]. @@ -927,10 +948,10 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. End map2. - Definition map2 (elt elt' elt'':Set)(f:option elt->option elt'->option elt'') := + Definition map2 (elt elt' elt'':Type)(f:option elt->option elt'->option elt'') := _map2 (fun o1 o2 => match o1,o2 with None,None => None | _, _ => f o1 o2 end). - Lemma map2_1 : forall (elt elt' elt'':Set)(m: t elt)(m': t elt') + Lemma map2_1 : forall (elt elt' elt'':Type)(m: t elt)(m': t elt') (x:key)(f:option elt->option elt'->option elt''), In x m \/ In x m' -> find x (map2 f m m') = f (find x m) (find x m'). @@ -946,7 +967,7 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. destruct H; intuition; try discriminate. Qed. - Lemma map2_2 : forall (elt elt' elt'':Set)(m: t elt)(m': t elt') + Lemma map2_2 : forall (elt elt' elt'':Type)(m: t elt)(m': t elt') (x:key)(f:option elt->option elt'->option elt''), In x (map2 f m m') -> In x m \/ In x m'. Proof. @@ -962,17 +983,17 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. Qed. - Definition fold (A B : Set) (f: positive -> A -> B -> B) (tr: t A) (v: B) := + Definition fold (A : Type)(B : Type) (f: positive -> A -> B -> B) (tr: t A) (v: B) := List.fold_left (fun a p => f (fst p) (snd p) a) (elements tr) v. Lemma fold_1 : - forall (A:Set)(m:t A)(B:Set)(i : B) (f : key -> A -> B -> B), + forall (A:Type)(m:t A)(B:Type)(i : B) (f : key -> A -> B -> B), fold f m i = fold_left (fun a p => f (fst p) (snd p) a) (elements m) i. Proof. intros; unfold fold; auto. Qed. - Fixpoint equal (A:Set)(cmp : A -> A -> bool)(m1 m2 : t A) {struct m1} : bool := + Fixpoint equal (A:Type)(cmp : A -> A -> bool)(m1 m2 : t A) {struct m1} : bool := match m1, m2 with | Leaf, _ => is_empty m2 | _, Leaf => is_empty m1 @@ -985,12 +1006,15 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. && equal cmp l1 l2 && equal cmp r1 r2 end. - Definition Equal (A:Set)(cmp:A->A->bool)(m m':t A) := + Definition Equal (A:Type)(m m':t A) := + forall y, find y m = find y m'. + Definition Equiv (A:Type)(eq_elt:A->A->Prop) m m' := (forall k, In k m <-> In k m') /\ - (forall k e e', MapsTo k e m -> MapsTo k e' m' -> cmp e e' = true). + (forall k e e', MapsTo k e m -> MapsTo k e' m' -> eq_elt e e'). + Definition Equivb (A:Type)(cmp: A->A->bool) := Equiv (Cmp cmp). - Lemma equal_1 : forall (A:Set)(m m':t A)(cmp:A->A->bool), - Equal cmp m m' -> equal cmp m m' = true. + Lemma equal_1 : forall (A:Type)(m m':t A)(cmp:A->A->bool), + Equivb cmp m m' -> equal cmp m m' = true. Proof. induction m. (* m = Leaf *) @@ -1024,11 +1048,11 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. destruct H2; red in H2; simpl in H2; discriminate. (* m' = Node *) destruct 1. - assert (Equal cmp m1 m'1). + assert (Equivb cmp m1 m'1). split. intros k; generalize (H (xO k)); unfold In, MapsTo; simpl; auto. intros k e e'; generalize (H0 (xO k) e e'); unfold In, MapsTo; simpl; auto. - assert (Equal cmp m2 m'2). + assert (Equivb cmp m2 m'2). split. intros k; generalize (H (xI k)); unfold In, MapsTo; simpl; auto. intros k e e'; generalize (H0 (xI k) e e'); unfold In, MapsTo; simpl; auto. @@ -1043,8 +1067,8 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. apply andb_true_intro; split; auto. Qed. - Lemma equal_2 : forall (A:Set)(m m':t A)(cmp:A->A->bool), - equal cmp m m' = true -> Equal cmp m m'. + Lemma equal_2 : forall (A:Type)(m m':t A)(cmp:A->A->bool), + equal cmp m m' = true -> Equivb cmp m m'. Proof. induction m. (* m = Leaf *) @@ -1103,7 +1127,7 @@ Module PositiveMapAdditionalFacts. (* Derivable from the Map interface *) Theorem gsspec: - forall (A:Set)(i j: positive) (x: A) (m: t A), + forall (A:Type)(i j: positive) (x: A) (m: t A), find i (add j x m) = if peq_dec i j then Some x else find i m. Proof. intros. @@ -1112,7 +1136,7 @@ Module PositiveMapAdditionalFacts. (* Not derivable from the Map interface *) Theorem gsident: - forall (A:Set)(i: positive) (m: t A) (v: A), + forall (A:Type)(i: positive) (m: t A) (v: A), find i m = Some v -> add i v m = m. Proof. induction i; intros; destruct m; simpl; simpl in H; try congruence. @@ -1121,7 +1145,7 @@ Module PositiveMapAdditionalFacts. Qed. Lemma xmap2_lr : - forall (A B : Set)(f g: option A -> option A -> option B)(m : t A), + forall (A B : Type)(f g: option A -> option A -> option B)(m : t A), (forall (i j : option A), f i j = g j i) -> xmap2_l f m = xmap2_r g m. Proof. @@ -1132,7 +1156,7 @@ Module PositiveMapAdditionalFacts. Qed. Theorem map2_commut: - forall (A B: Set) (f g: option A -> option A -> option B), + forall (A B: Type) (f g: option A -> option A -> option B), (forall (i j: option A), f i j = g j i) -> forall (m1 m2: t A), _map2 f m1 m2 = _map2 g m2 m1. diff --git a/theories/FSets/FMapWeak.v b/theories/FSets/FMapWeak.v deleted file mode 100644 index 1ad190a4..00000000 --- a/theories/FSets/FMapWeak.v +++ /dev/null @@ -1,15 +0,0 @@ -(***********************************************************************) -(* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) -(* \VV/ *************************************************************) -(* // * This file is distributed under the terms of the *) -(* * GNU Lesser General Public License Version 2.1 *) -(***********************************************************************) - -(* $Id: FMapWeak.v 8844 2006-05-22 17:22:36Z letouzey $ *) - -Require Export DecidableType. -Require Export DecidableTypeEx. -Require Export FMapWeakInterface. -Require Export FMapWeakList. -Require Export FMapWeakFacts.
\ No newline at end of file diff --git a/theories/FSets/FMapWeakFacts.v b/theories/FSets/FMapWeakFacts.v deleted file mode 100644 index 18f73a3f..00000000 --- a/theories/FSets/FMapWeakFacts.v +++ /dev/null @@ -1,599 +0,0 @@ -(***********************************************************************) -(* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) -(* \VV/ *************************************************************) -(* // * This file is distributed under the terms of the *) -(* * GNU Lesser General Public License Version 2.1 *) -(***********************************************************************) - -(* $Id: FMapWeakFacts.v 8882 2006-05-31 21:55:30Z letouzey $ *) - -(** * Finite maps library *) - -(** This functor derives additional facts from [FMapWeakInterface.S]. These - facts are mainly the specifications of [FMapWeakInterface.S] written using - different styles: equivalence and boolean equalities. -*) - -Require Import Bool. -Require Import OrderedType. -Require Export FMapWeakInterface. -Set Implicit Arguments. -Unset Strict Implicit. - -Module Facts (M: S). -Import M. -Import Logic. (* to unmask [eq] *) -Import Peano. (* to unmask [lt] *) - -Lemma MapsTo_fun : forall (elt:Set) m x (e e':elt), - MapsTo x e m -> MapsTo x e' m -> e=e'. -Proof. -intros. -generalize (find_1 H) (find_1 H0); clear H H0. -intros; rewrite H in H0; injection H0; auto. -Qed. - -(** * Specifications written using equivalences *) - -Section IffSpec. -Variable elt elt' elt'': Set. -Implicit Type m: t elt. -Implicit Type x y z: key. -Implicit Type e: elt. - -Lemma MapsTo_iff : forall m x y e, E.eq x y -> (MapsTo x e m <-> MapsTo y e m). -Proof. -split; apply MapsTo_1; auto. -Qed. - -Lemma In_iff : forall m x y, E.eq x y -> (In x m <-> In y m). -Proof. -unfold In. -split; intros (e0,H0); exists e0. -apply (MapsTo_1 H H0); auto. -apply (MapsTo_1 (E.eq_sym H) H0); auto. -Qed. - -Lemma find_mapsto_iff : forall m x e, MapsTo x e m <-> find x m = Some e. -Proof. -split; [apply find_1|apply find_2]. -Qed. - -Lemma not_find_mapsto_iff : forall m x, ~In x m <-> find x m = None. -Proof. -intros. -generalize (find_mapsto_iff m x); destruct (find x m). -split; intros; try discriminate. -destruct H0. -exists e; rewrite H; auto. -split; auto. -intros; intros (e,H1). -rewrite H in H1; discriminate. -Qed. - -Lemma mem_in_iff : forall m x, In x m <-> mem x m = true. -Proof. -split; [apply mem_1|apply mem_2]. -Qed. - -Lemma not_mem_in_iff : forall m x, ~In x m <-> mem x m = false. -Proof. -intros; rewrite mem_in_iff; destruct (mem x m); intuition. -Qed. - -Lemma equal_iff : forall m m' cmp, Equal cmp m m' <-> equal cmp m m' = true. -Proof. -split; [apply equal_1|apply equal_2]. -Qed. - -Lemma empty_mapsto_iff : forall x e, MapsTo x e (empty elt) <-> False. -Proof. -intuition; apply (empty_1 H). -Qed. - -Lemma empty_in_iff : forall x, In x (empty elt) <-> False. -Proof. -unfold In. -split; [intros (e,H); rewrite empty_mapsto_iff in H|]; intuition. -Qed. - -Lemma is_empty_iff : forall m, Empty m <-> is_empty m = true. -Proof. -split; [apply is_empty_1|apply is_empty_2]. -Qed. - -Lemma add_mapsto_iff : forall m x y e e', - MapsTo y e' (add x e m) <-> - (E.eq x y /\ e=e') \/ - (~E.eq x y /\ MapsTo y e' m). -Proof. -intros. -intuition. -destruct (E.eq_dec x y); [left|right]. -split; auto. -symmetry; apply (MapsTo_fun (e':=e) H); auto. -split; auto; apply add_3 with x e; auto. -subst; auto. -Qed. - -Lemma add_in_iff : forall m x y e, In y (add x e m) <-> E.eq x y \/ In y m. -Proof. -unfold In; split. -intros (e',H). -destruct (E.eq_dec x y) as [E|E]; auto. -right; exists e'; auto. -apply (add_3 E H). -destruct (E.eq_dec x y) as [E|E]; auto. -intros. -exists e; apply add_1; auto. -intros [H|(e',H)]. -destruct E; auto. -exists e'; apply add_2; auto. -Qed. - -Lemma add_neq_mapsto_iff : forall m x y e e', - ~ E.eq x y -> (MapsTo y e' (add x e m) <-> MapsTo y e' m). -Proof. -split; [apply add_3|apply add_2]; auto. -Qed. - -Lemma add_neq_in_iff : forall m x y e, - ~ E.eq x y -> (In y (add x e m) <-> In y m). -Proof. -split; intros (e',H0); exists e'. -apply (add_3 H H0). -apply add_2; auto. -Qed. - -Lemma remove_mapsto_iff : forall m x y e, - MapsTo y e (remove x m) <-> ~E.eq x y /\ MapsTo y e m. -Proof. -intros. -split; intros. -split. -assert (In y (remove x m)) by (exists e; auto). -intro H1; apply (remove_1 H1 H0). -apply remove_3 with x; auto. -apply remove_2; intuition. -Qed. - -Lemma remove_in_iff : forall m x y, In y (remove x m) <-> ~E.eq x y /\ In y m. -Proof. -unfold In; split. -intros (e,H). -split. -assert (In y (remove x m)) by (exists e; auto). -intro H1; apply (remove_1 H1 H0). -exists e; apply remove_3 with x; auto. -intros (H,(e,H0)); exists e; apply remove_2; auto. -Qed. - -Lemma remove_neq_mapsto_iff : forall m x y e, - ~ E.eq x y -> (MapsTo y e (remove x m) <-> MapsTo y e m). -Proof. -split; [apply remove_3|apply remove_2]; auto. -Qed. - -Lemma remove_neq_in_iff : forall m x y, - ~ E.eq x y -> (In y (remove x m) <-> In y m). -Proof. -split; intros (e',H0); exists e'. -apply (remove_3 H0). -apply remove_2; auto. -Qed. - -Lemma elements_mapsto_iff : forall m x e, - MapsTo x e m <-> InA (@eq_key_elt _) (x,e) (elements m). -Proof. -split; [apply elements_1 | apply elements_2]. -Qed. - -Lemma elements_in_iff : forall m x, - In x m <-> exists e, InA (@eq_key_elt _) (x,e) (elements m). -Proof. -unfold In; split; intros (e,H); exists e; [apply elements_1 | apply elements_2]; auto. -Qed. - -Lemma map_mapsto_iff : forall m x b (f : elt -> elt'), - MapsTo x b (map f m) <-> exists a, b = f a /\ MapsTo x a m. -Proof. -split. -case_eq (find x m); intros. -exists e. -split. -apply (MapsTo_fun (m:=map f m) (x:=x)); auto. -apply find_2; auto. -assert (In x (map f m)) by (exists b; auto). -destruct (map_2 H1) as (a,H2). -rewrite (find_1 H2) in H; discriminate. -intros (a,(H,H0)). -subst b; auto. -Qed. - -Lemma map_in_iff : forall m x (f : elt -> elt'), - In x (map f m) <-> In x m. -Proof. -split; intros; eauto. -destruct H as (a,H). -exists (f a); auto. -Qed. - -Lemma mapi_in_iff : forall m x (f:key->elt->elt'), - In x (mapi f m) <-> In x m. -Proof. -split; intros; eauto. -destruct H as (a,H). -destruct (mapi_1 f H) as (y,(H0,H1)). -exists (f y a); auto. -Qed. - -(* Unfortunately, we don't have simple equivalences for [mapi] - and [MapsTo]. The only correct one needs compatibility of [f]. *) - -Lemma mapi_inv : forall m x b (f : key -> elt -> elt'), - MapsTo x b (mapi f m) -> - exists a, exists y, E.eq y x /\ b = f y a /\ MapsTo x a m. -Proof. -intros; case_eq (find x m); intros. -exists e. -destruct (@mapi_1 _ _ m x e f) as (y,(H1,H2)). -apply find_2; auto. -exists y; repeat split; auto. -apply (MapsTo_fun (m:=mapi f m) (x:=x)); auto. -assert (In x (mapi f m)) by (exists b; auto). -destruct (mapi_2 H1) as (a,H2). -rewrite (find_1 H2) in H0; discriminate. -Qed. - -Lemma mapi_1bis : forall m x e (f:key->elt->elt'), - (forall x y e, E.eq x y -> f x e = f y e) -> - MapsTo x e m -> MapsTo x (f x e) (mapi f m). -Proof. -intros. -destruct (mapi_1 f H0) as (y,(H1,H2)). -replace (f x e) with (f y e) by auto. -auto. -Qed. - -Lemma mapi_mapsto_iff : forall m x b (f:key->elt->elt'), - (forall x y e, E.eq x y -> f x e = f y e) -> - (MapsTo x b (mapi f m) <-> exists a, b = f x a /\ MapsTo x a m). -Proof. -split. -intros. -destruct (mapi_inv H0) as (a,(y,(H1,(H2,H3)))). -exists a; split; auto. -subst b; auto. -intros (a,(H0,H1)). -subst b. -apply mapi_1bis; auto. -Qed. - -(** Things are even worse for [map2] : we don't try to state any - equivalence, see instead boolean results below. *) - -End IffSpec. - -(** Useful tactic for simplifying expressions like [In y (add x e (remove z m))] *) - -Ltac map_iff := - repeat (progress ( - rewrite add_mapsto_iff || rewrite add_in_iff || - rewrite remove_mapsto_iff || rewrite remove_in_iff || - rewrite empty_mapsto_iff || rewrite empty_in_iff || - rewrite map_mapsto_iff || rewrite map_in_iff || - rewrite mapi_in_iff)). - -(** * Specifications written using boolean predicates *) - -Section BoolSpec. - -Definition eqb x y := if E.eq_dec x y then true else false. - -Lemma mem_find_b : forall (elt:Set)(m:t elt)(x:key), mem x m = if find x m then true else false. -Proof. -intros. -generalize (find_mapsto_iff m x)(mem_in_iff m x); unfold In. -destruct (find x m); destruct (mem x m); auto. -intros. -rewrite <- H0; exists e; rewrite H; auto. -intuition. -destruct H0 as (e,H0). -destruct (H e); intuition discriminate. -Qed. - -Variable elt elt' elt'' : Set. -Implicit Types m : t elt. -Implicit Types x y z : key. -Implicit Types e : elt. - -Lemma mem_b : forall m x y, E.eq x y -> mem x m = mem y m. -Proof. -intros. -generalize (mem_in_iff m x) (mem_in_iff m y)(In_iff m H). -destruct (mem x m); destruct (mem y m); intuition. -Qed. - -Lemma find_o : forall m x y, E.eq x y -> find x m = find y m. -Proof. -intros. -generalize (find_mapsto_iff m x) (find_mapsto_iff m y) (fun e => MapsTo_iff m e H). -destruct (find x m); destruct (find y m); intros. -rewrite <- H0; rewrite H2; rewrite H1; auto. -symmetry; rewrite <- H1; rewrite <- H2; rewrite H0; auto. -rewrite <- H0; rewrite H2; rewrite H1; auto. -auto. -Qed. - -Lemma empty_o : forall x, find x (empty elt) = None. -Proof. -intros. -case_eq (find x (empty elt)); intros; auto. -generalize (find_2 H). -rewrite empty_mapsto_iff; intuition. -Qed. - -Lemma empty_a : forall x, mem x (empty elt) = false. -Proof. -intros. -case_eq (mem x (empty elt)); intros; auto. -generalize (mem_2 H). -rewrite empty_in_iff; intuition. -Qed. - -Lemma add_eq_o : forall m x y e, - E.eq x y -> find y (add x e m) = Some e. -Proof. -auto. -Qed. - -Lemma add_neq_o : forall m x y e, - ~ E.eq x y -> find y (add x e m) = find y m. -Proof. -intros. -case_eq (find y m); intros; auto. -case_eq (find y (add x e m)); intros; auto. -rewrite <- H0; symmetry. -apply find_1; apply add_3 with x e; auto. -Qed. -Hint Resolve add_neq_o. - -Lemma add_o : forall m x y e, - find y (add x e m) = if E.eq_dec x y then Some e else find y m. -Proof. -intros; destruct (E.eq_dec x y); auto. -Qed. - -Lemma add_eq_b : forall m x y e, - E.eq x y -> mem y (add x e m) = true. -Proof. -intros; rewrite mem_find_b; rewrite add_eq_o; auto. -Qed. - -Lemma add_neq_b : forall m x y e, - ~E.eq x y -> mem y (add x e m) = mem y m. -Proof. -intros; do 2 rewrite mem_find_b; rewrite add_neq_o; auto. -Qed. - -Lemma add_b : forall m x y e, - mem y (add x e m) = eqb x y || mem y m. -Proof. -intros; do 2 rewrite mem_find_b; rewrite add_o; unfold eqb. -destruct (E.eq_dec x y); simpl; auto. -Qed. - -Lemma remove_eq_o : forall m x y, - E.eq x y -> find y (remove x m) = None. -Proof. -intros. -generalize (remove_1 (m:=m) H). -generalize (find_mapsto_iff (remove x m) y). -destruct (find y (remove x m)); auto. -destruct 2. -exists e; rewrite H0; auto. -Qed. -Hint Resolve remove_eq_o. - -Lemma remove_neq_o : forall m x y, - ~ E.eq x y -> find y (remove x m) = find y m. -Proof. -intros. -case_eq (find y m); intros; auto. -case_eq (find y (remove x m)); intros; auto. -rewrite <- H0; symmetry. -apply find_1; apply remove_3 with x; auto. -Qed. -Hint Resolve remove_neq_o. - -Lemma remove_o : forall m x y, - find y (remove x m) = if E.eq_dec x y then None else find y m. -Proof. -intros; destruct (E.eq_dec x y); auto. -Qed. - -Lemma remove_eq_b : forall m x y, - E.eq x y -> mem y (remove x m) = false. -Proof. -intros; rewrite mem_find_b; rewrite remove_eq_o; auto. -Qed. - -Lemma remove_neq_b : forall m x y, - ~ E.eq x y -> mem y (remove x m) = mem y m. -Proof. -intros; do 2 rewrite mem_find_b; rewrite remove_neq_o; auto. -Qed. - -Lemma remove_b : forall m x y, - mem y (remove x m) = negb (eqb x y) && mem y m. -Proof. -intros; do 2 rewrite mem_find_b; rewrite remove_o; unfold eqb. -destruct (E.eq_dec x y); auto. -Qed. - -Definition option_map (A:Set)(B:Set)(f:A->B)(o:option A) : option B := - match o with - | Some a => Some (f a) - | None => None - end. - -Lemma map_o : forall m x (f:elt->elt'), - find x (map f m) = option_map f (find x m). -Proof. -intros. -generalize (find_mapsto_iff (map f m) x) (find_mapsto_iff m x) - (fun b => map_mapsto_iff m x b f). -destruct (find x (map f m)); destruct (find x m); simpl; auto; intros. -rewrite <- H; rewrite H1; exists e0; rewrite H0; auto. -destruct (H e) as [_ H2]. -rewrite H1 in H2. -destruct H2 as (a,(_,H2)); auto. -rewrite H0 in H2; discriminate. -rewrite <- H; rewrite H1; exists e; rewrite H0; auto. -Qed. - -Lemma map_b : forall m x (f:elt->elt'), - mem x (map f m) = mem x m. -Proof. -intros; do 2 rewrite mem_find_b; rewrite map_o. -destruct (find x m); simpl; auto. -Qed. - -Lemma mapi_b : forall m x (f:key->elt->elt'), - mem x (mapi f m) = mem x m. -Proof. -intros. -generalize (mem_in_iff (mapi f m) x) (mem_in_iff m x) (mapi_in_iff m x f). -destruct (mem x (mapi f m)); destruct (mem x m); simpl; auto; intros. -symmetry; rewrite <- H0; rewrite <- H1; rewrite H; auto. -rewrite <- H; rewrite H1; rewrite H0; auto. -Qed. - -Lemma mapi_o : forall m x (f:key->elt->elt'), - (forall x y e, E.eq x y -> f x e = f y e) -> - find x (mapi f m) = option_map (f x) (find x m). -Proof. -intros. -generalize (find_mapsto_iff (mapi f m) x) (find_mapsto_iff m x) - (fun b => mapi_mapsto_iff m x b H). -destruct (find x (mapi f m)); destruct (find x m); simpl; auto; intros. -rewrite <- H0; rewrite H2; exists e0; rewrite H1; auto. -destruct (H0 e) as [_ H3]. -rewrite H2 in H3. -destruct H3 as (a,(_,H3)); auto. -rewrite H1 in H3; discriminate. -rewrite <- H0; rewrite H2; exists e; rewrite H1; auto. -Qed. - -Lemma map2_1bis : forall (m: t elt)(m': t elt') x - (f:option elt->option elt'->option elt''), - f None None = None -> - find x (map2 f m m') = f (find x m) (find x m'). -Proof. -intros. -case_eq (find x m); intros. -rewrite <- H0. -apply map2_1; auto. -left; exists e; auto. -case_eq (find x m'); intros. -rewrite <- H0; rewrite <- H1. -apply map2_1; auto. -right; exists e; auto. -rewrite H. -case_eq (find x (map2 f m m')); intros; auto. -assert (In x (map2 f m m')) by (exists e; auto). -destruct (map2_2 H3) as [(e0,H4)|(e0,H4)]. -rewrite (find_1 H4) in H0; discriminate. -rewrite (find_1 H4) in H1; discriminate. -Qed. - -Fixpoint findA (A B:Set)(f : A -> bool) (l:list (A*B)) : option B := - match l with - | nil => None - | (a,b)::l => if f a then Some b else findA f l - end. - -Lemma findA_NoDupA : - forall (A B:Set) - (eqA:A->A->Prop) - (eqA_sym: forall a b, eqA a b -> eqA b a) - (eqA_trans: forall a b c, eqA a b -> eqA b c -> eqA a c) - (eqA_dec : forall a a', { eqA a a' }+{~eqA a a' }) - (l:list (A*B))(x:A)(e:B), - NoDupA (fun p p' => eqA (fst p) (fst p')) l -> - (InA (fun p p' => eqA (fst p) (fst p') /\ snd p = snd p') (x,e) l <-> - findA (fun y:A => if eqA_dec x y then true else false) l = Some e). -Proof. -induction l; simpl; intros. -split; intros; try discriminate. -inversion H0. -destruct a as (y,e'). -inversion_clear H. -split; intros. -inversion_clear H. -simpl in *; destruct H2; subst e'. -destruct (eqA_dec x y); intuition. -destruct (eqA_dec x y); simpl. -destruct H0. -generalize e0 H2 eqA_trans eqA_sym; clear. -induction l. -inversion 2. -inversion_clear 2; intros; auto. -destruct a. -compute in H; destruct H. -subst b. -constructor 1; auto. -simpl. -apply eqA_trans with x; auto. -rewrite <- IHl; auto. -destruct (eqA_dec x y); simpl in *. -inversion H; clear H; intros; subst e'; auto. -constructor 2. -rewrite IHl; auto. -Qed. - -Lemma elements_o : forall m x, - find x m = findA (eqb x) (elements m). -Proof. -intros. -assert (forall e, find x m = Some e <-> InA (eq_key_elt (elt:=elt)) (x,e) (elements m)). - intros; rewrite <- find_mapsto_iff; apply elements_mapsto_iff. -assert (NoDupA (eq_key (elt:=elt)) (elements m)). - exact (elements_3 m). -generalize (fun e => @findA_NoDupA _ _ _ E.eq_sym E.eq_trans E.eq_dec (elements m) x e H0). -unfold eqb. -destruct (find x m); destruct (findA (fun y : E.t => if E.eq_dec x y then true else false) (elements m)); - simpl; auto; intros. -symmetry; rewrite <- H1; rewrite <- H; auto. -symmetry; rewrite <- H1; rewrite <- H; auto. -rewrite H; rewrite H1; auto. -Qed. - -Lemma elements_b : forall m x, mem x m = existsb (fun p => eqb x (fst p)) (elements m). -Proof. -intros. -generalize (mem_in_iff m x)(elements_in_iff m x) - (existsb_exists (fun p => eqb x (fst p)) (elements m)). -destruct (mem x m); destruct (existsb (fun p => eqb x (fst p)) (elements m)); auto; intros. -symmetry; rewrite H1. -destruct H0 as (H0,_). -destruct H0 as (e,He); [ intuition |]. -rewrite InA_alt in He. -destruct He as ((y,e'),(Ha1,Ha2)). -compute in Ha1; destruct Ha1; subst e'. -exists (y,e); split; simpl; auto. -unfold eqb; destruct (E.eq_dec x y); intuition. -rewrite <- H; rewrite H0. -destruct H1 as (H1,_). -destruct H1 as ((y,e),(Ha1,Ha2)); [intuition|]. -simpl in Ha2. -unfold eqb in *; destruct (E.eq_dec x y); auto; try discriminate. -exists e; rewrite InA_alt. -exists (y,e); intuition. -compute; auto. -Qed. - -End BoolSpec. - -End Facts. diff --git a/theories/FSets/FMapWeakInterface.v b/theories/FSets/FMapWeakInterface.v deleted file mode 100644 index b6df4da5..00000000 --- a/theories/FSets/FMapWeakInterface.v +++ /dev/null @@ -1,201 +0,0 @@ -(***********************************************************************) -(* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) -(* \VV/ *************************************************************) -(* // * This file is distributed under the terms of the *) -(* * GNU Lesser General Public License Version 2.1 *) -(***********************************************************************) - -(* $Id: FMapWeakInterface.v 8639 2006-03-16 19:21:55Z letouzey $ *) - -(** * Finite map library *) - -(** This file proposes an interface for finite maps over keys with decidable - equality, but no decidable order. *) - -Set Implicit Arguments. -Unset Strict Implicit. -Require Import FSetInterface. -Require Import FSetWeakInterface. - -Module Type S. - - Declare Module E : DecidableType. - - Definition key := E.t. - - Parameter t : Set -> Set. (** the abstract type of maps *) - - Section Types. - - Variable elt:Set. - - Parameter empty : t elt. - (** The empty map. *) - - Parameter is_empty : t elt -> bool. - (** Test whether a map is empty or not. *) - - Parameter add : key -> elt -> t elt -> t elt. - (** [add x y m] returns a map containing the same bindings as [m], - plus a binding of [x] to [y]. If [x] was already bound in [m], - its previous binding disappears. *) - - Parameter find : key -> t elt -> option elt. - (** [find x m] returns the current binding of [x] in [m], - or raises [Not_found] if no such binding exists. - NB: in Coq, the exception mechanism becomes a option type. *) - - Parameter remove : key -> t elt -> t elt. - (** [remove x m] returns a map containing the same bindings as [m], - except for [x] which is unbound in the returned map. *) - - Parameter mem : key -> t elt -> bool. - (** [mem x m] returns [true] if [m] contains a binding for [x], - and [false] otherwise. *) - - (** Coq comment: [iter] is useless in a purely functional world *) - (** val iter : (key -> 'a -> unit) -> 'a t -> unit *) - (** iter f m applies f to all bindings in map m. f receives the key as - first argument, and the associated value as second argument. - The bindings are passed to f in increasing order with respect to the - ordering over the type of the keys. Only current bindings are - presented to f: bindings hidden by more recent bindings are not - passed to f. *) - - Variable elt' : Set. - Variable elt'': Set. - - Parameter map : (elt -> elt') -> t elt -> t elt'. - (** [map f m] returns a map with same domain as [m], where the associated - value a of all bindings of [m] has been replaced by the result of the - application of [f] to [a]. The bindings are passed to [f] in - increasing order with respect to the ordering over the type of the - keys. *) - - Parameter mapi : (key -> elt -> elt') -> t elt -> t elt'. - (** Same as [S.map], but the function receives as arguments both the - key and the associated value for each binding of the map. *) - - Parameter map2 : (option elt -> option elt' -> option elt'') -> t elt -> t elt' -> t elt''. - (** Not present in Ocaml. - [map f m m'] creates a new map whose bindings belong to the ones of either - [m] or [m']. The presence and value for a key [k] is determined by [f e e'] - where [e] and [e'] are the (optional) bindings of [k] in [m] and [m']. *) - - Parameter elements : t elt -> list (key*elt). - (** Not present in Ocaml. - [elements m] returns an assoc list corresponding to the bindings of [m]. - Elements of this list are sorted with respect to their first components. - Useful to specify [fold] ... *) - - Parameter fold : forall A: Set, (key -> elt -> A -> A) -> t elt -> A -> A. - (** [fold f m a] computes [(f kN dN ... (f k1 d1 a)...)], - where [k1] ... [kN] are the keys of all bindings in [m] - (in increasing order), and [d1] ... [dN] are the associated data. *) - - Parameter equal : (elt -> elt -> bool) -> t elt -> t elt -> bool. - (** [equal cmp m1 m2] tests whether the maps [m1] and [m2] are equal, - that is, contain equal keys and associate them with equal data. - [cmp] is the equality predicate used to compare the data associated - with the keys. *) - - Section Spec. - - Variable m m' m'' : t elt. - Variable x y z : key. - Variable e e' : elt. - - Parameter MapsTo : key -> elt -> t elt -> Prop. - - Definition In (k:key)(m: t elt) : Prop := exists e:elt, MapsTo k e m. - - Definition Empty m := forall (a : key)(e:elt) , ~ MapsTo a e m. - - Definition eq_key (p p':key*elt) := E.eq (fst p) (fst p'). - - Definition eq_key_elt (p p':key*elt) := - E.eq (fst p) (fst p') /\ (snd p) = (snd p'). - - (** Specification of [MapsTo] *) - Parameter MapsTo_1 : E.eq x y -> MapsTo x e m -> MapsTo y e m. - - (** Specification of [mem] *) - Parameter mem_1 : In x m -> mem x m = true. - Parameter mem_2 : mem x m = true -> In x m. - - (** Specification of [empty] *) - Parameter empty_1 : Empty empty. - - (** Specification of [is_empty] *) - Parameter is_empty_1 : Empty m -> is_empty m = true. - Parameter is_empty_2 : is_empty m = true -> Empty m. - - (** Specification of [add] *) - Parameter add_1 : E.eq x y -> MapsTo y e (add x e m). - Parameter add_2 : ~ E.eq x y -> MapsTo y e m -> MapsTo y e (add x e' m). - Parameter add_3 : ~ E.eq x y -> MapsTo y e (add x e' m) -> MapsTo y e m. - - (** Specification of [remove] *) - Parameter remove_1 : E.eq x y -> ~ In y (remove x m). - Parameter remove_2 : ~ E.eq x y -> MapsTo y e m -> MapsTo y e (remove x m). - Parameter remove_3 : MapsTo y e (remove x m) -> MapsTo y e m. - - (** Specification of [find] *) - Parameter find_1 : MapsTo x e m -> find x m = Some e. - Parameter find_2 : find x m = Some e -> MapsTo x e m. - - (** Specification of [elements] *) - Parameter elements_1 : - MapsTo x e m -> InA eq_key_elt (x,e) (elements m). - Parameter elements_2 : - InA eq_key_elt (x,e) (elements m) -> MapsTo x e m. - Parameter elements_3 : NoDupA eq_key (elements m). - - (** Specification of [fold] *) - Parameter fold_1 : - forall (A : Set) (i : A) (f : key -> elt -> A -> A), - fold f m i = fold_left (fun a p => f (fst p) (snd p) a) (elements m) i. - - Definition Equal cmp m m' := - (forall k, In k m <-> In k m') /\ - (forall k e e', MapsTo k e m -> MapsTo k e' m' -> cmp e e' = true). - - Variable cmp : elt -> elt -> bool. - - (** Specification of [equal] *) - Parameter equal_1 : Equal cmp m m' -> equal cmp m m' = true. - Parameter equal_2 : equal cmp m m' = true -> Equal cmp m m'. - - End Spec. - End Types. - - (** Specification of [map] *) - Parameter map_1 : forall (elt elt':Set)(m: t elt)(x:key)(e:elt)(f:elt->elt'), - MapsTo x e m -> MapsTo x (f e) (map f m). - Parameter map_2 : forall (elt elt':Set)(m: t elt)(x:key)(f:elt->elt'), - In x (map f m) -> In x m. - - (** Specification of [mapi] *) - Parameter mapi_1 : forall (elt elt':Set)(m: t elt)(x:key)(e:elt) - (f:key->elt->elt'), MapsTo x e m -> - exists y, E.eq y x /\ MapsTo x (f y e) (mapi f m). - Parameter mapi_2 : forall (elt elt':Set)(m: t elt)(x:key) - (f:key->elt->elt'), In x (mapi f m) -> In x m. - - (** Specification of [map2] *) - Parameter map2_1 : forall (elt elt' elt'':Set)(m: t elt)(m': t elt') - (x:key)(f:option elt->option elt'->option elt''), - In x m \/ In x m' -> - find x (map2 f m m') = f (find x m) (find x m'). - - Parameter map2_2 : forall (elt elt' elt'':Set)(m: t elt)(m': t elt') - (x:key)(f:option elt->option elt'->option elt''), - In x (map2 f m m') -> In x m \/ In x m'. - - Hint Immediate MapsTo_1 mem_2 is_empty_2. - - Hint Resolve mem_1 is_empty_1 is_empty_2 add_1 add_2 add_3 remove_1 - remove_2 remove_3 find_1 find_2 fold_1 map_1 map_2 mapi_1 mapi_2. - -End S. diff --git a/theories/FSets/FMapWeakList.v b/theories/FSets/FMapWeakList.v index 890485a8..be09e41a 100644 --- a/theories/FSets/FMapWeakList.v +++ b/theories/FSets/FMapWeakList.v @@ -6,39 +6,28 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: FMapWeakList.v 8985 2006-06-23 16:12:45Z jforest $ *) +(* $Id: FMapWeakList.v 10616 2008-03-04 17:33:35Z letouzey $ *) (** * Finite map library *) (** This file proposes an implementation of the non-dependant interface - [FMapInterface.S] using lists of pairs, unordered but without redundancy. *) + [FMapInterface.WS] using lists of pairs, unordered but without redundancy. *) -Require Import FSetInterface. -Require Import FSetWeakInterface. -Require Import FMapWeakInterface. +Require Import FMapInterface. Set Implicit Arguments. Unset Strict Implicit. -Arguments Scope list [type_scope]. - Module Raw (X:DecidableType). -Module PX := KeyDecidableType X. -Import PX. +Module Import PX := KeyDecidableType X. Definition key := X.t. -Definition t (elt:Set) := list (X.t * elt). +Definition t (elt:Type) := list (X.t * elt). Section Elt. -Variable elt : Set. - -(* now in KeyDecidableType: -Definition eqk (p p':key*elt) := X.eq (fst p) (fst p'). -Definition eqke (p p':key*elt) := - X.eq (fst p) (fst p') /\ (snd p) = (snd p'). -*) +Variable elt : Type. Notation eqk := (eqk (elt:=elt)). Notation eqke := (eqke (elt:=elt)). @@ -221,10 +210,10 @@ Proof. destruct a as (x',e'). simpl; case (X.eq_dec x x'); inversion_clear Hm; auto. constructor; auto. - swap H. + contradict H. apply InA_eqk with (x,e); auto. constructor; auto. - swap H; apply add_3' with x e; auto. + contradict H; apply add_3' with x e; auto. Qed. (* Not part of the exported specifications, used later for [combine]. *) @@ -272,8 +261,8 @@ Proof. inversion_clear Hm. subst. - swap H0. - destruct H2 as (e,H2); unfold PX.MapsTo in H2. + contradict H0. + destruct H0 as (e,H2); unfold PX.MapsTo in H2. apply InA_eqk with (y,e); auto. compute; apply X.eq_trans with x; auto. @@ -323,7 +312,7 @@ Proof. destruct a as (x',e'). simpl; case (X.eq_dec x x'); auto. constructor; auto. - swap H; apply remove_3' with x; auto. + contradict H; apply remove_3' with x; auto. Qed. (** * [elements] *) @@ -340,20 +329,20 @@ Proof. auto. Qed. -Lemma elements_3 : forall m (Hm:NoDupA m), NoDupA (elements m). +Lemma elements_3w : forall m (Hm:NoDupA m), NoDupA (elements m). Proof. auto. Qed. (** * [fold] *) -Function fold (A:Set)(f:key->elt->A->A)(m:t elt) (acc : A) {struct m} : A := +Function fold (A:Type)(f:key->elt->A->A)(m:t elt) (acc : A) {struct m} : A := match m with | nil => acc | (k,e)::m' => fold f m' (f k e acc) end. -Lemma fold_1 : forall m (A:Set)(i:A)(f:key->elt->A->A), +Lemma fold_1 : forall m (A:Type)(i:A)(f:key->elt->A->A), fold f m i = fold_left (fun a p => f (fst p) (snd p) a) (elements m) i. Proof. intros; functional induction (@fold A f m i); auto. @@ -377,7 +366,7 @@ Definition Submap cmp m m' := (forall k, In k m -> In k m') /\ (forall k e e', MapsTo k e m -> MapsTo k e' m' -> cmp e e' = true). -Definition Equal cmp m m' := +Definition Equivb cmp m m' := (forall k, In k m <-> In k m') /\ (forall k e e', MapsTo k e m -> MapsTo k e' m' -> cmp e e' = true). @@ -444,17 +433,17 @@ Qed. (** Specification of [equal] *) Lemma equal_1 : forall m (Hm:NoDupA m) m' (Hm': NoDupA m') cmp, - Equal cmp m m' -> equal cmp m m' = true. + Equivb cmp m m' -> equal cmp m m' = true. Proof. - unfold Equal, equal. + unfold Equivb, equal. intuition. apply andb_true_intro; split; apply submap_1; unfold Submap; firstorder. Qed. Lemma equal_2 : forall m (Hm:NoDupA m) m' (Hm':NoDupA m') cmp, - equal cmp m m' = true -> Equal cmp m m'. + equal cmp m m' = true -> Equivb cmp m m'. Proof. - unfold Equal, equal. + unfold Equivb, equal. intros. destruct (andb_prop _ _ H); clear H. generalize (submap_2 Hm Hm' H0). @@ -462,7 +451,7 @@ Proof. firstorder. Qed. -Variable elt':Set. +Variable elt':Type. (** * [map] and [mapi] *) @@ -483,7 +472,7 @@ Section Elt2. (* A new section is necessary for previous definitions to work with different [elt], especially [MapsTo]... *) -Variable elt elt' : Set. +Variable elt elt' : Type. (** Specification of [map] *) @@ -533,12 +522,12 @@ Proof. destruct a as (x',e'). inversion_clear Hm. constructor; auto. - swap H. + contradict H. (* il faut un map_1 avec eqk au lieu de eqke *) clear IHm H0. induction m; simpl in *; auto. - inversion H1. - destruct a; inversion H1; auto. + inversion H. + destruct a; inversion H; auto. Qed. (** Specification of [mapi] *) @@ -593,17 +582,17 @@ Proof. destruct a as (x',e'). inversion_clear Hm; auto. constructor; auto. - swap H. + contradict H. clear IHm H0. induction m; simpl in *; auto. - inversion_clear H1. - destruct a; inversion_clear H1; auto. + inversion_clear H. + destruct a; inversion_clear H; auto. Qed. End Elt2. Section Elt3. -Variable elt elt' elt'' : Set. +Variable elt elt' elt'' : Type. Notation oee' := (option elt * option elt')%type. @@ -613,7 +602,7 @@ Definition combine_l (m:t elt)(m':t elt') : t oee' := Definition combine_r (m:t elt)(m':t elt') : t oee' := mapi (fun k e' => (find k m, Some e')) m'. -Definition fold_right_pair (A B C:Set)(f:A->B->C->C)(l:list (A*B))(i:C) := +Definition fold_right_pair (A B C:Type)(f:A->B->C->C)(l:list (A*B))(i:C) := List.fold_right (fun p => f (fst p) (snd p)) i l. Definition combine (m:t elt)(m':t elt') : t oee' := @@ -737,7 +726,7 @@ Qed. Variable f : option elt -> option elt' -> option elt''. -Definition option_cons (A:Set)(k:key)(o:option A)(l:list (key*A)) := +Definition option_cons (A:Type)(k:key)(o:option A)(l:list (key*A)) := match o with | Some e => (k,e)::l | None => l @@ -765,13 +754,13 @@ Proof. inversion_clear H1. destruct a; destruct o; simpl; auto. constructor; auto. - swap H. + contradict H. clear IHl1. induction l1. - inversion H1. + inversion H. inversion_clear H0. destruct a; destruct o; simpl in *; auto. - inversion_clear H1; auto. + inversion_clear H; auto. Qed. Definition at_least_one_then_f (o:option elt)(o':option elt') := @@ -807,7 +796,7 @@ Proof. rewrite H2. unfold f'; simpl. destruct (f oo oo'); simpl. - destruct (X.eq_dec x k); try absurd_hyp n; auto. + destruct (X.eq_dec x k); try contradict n; auto. destruct (IHm0 H1) as (_,H4); apply H4; auto. case_eq (find x m0); intros; auto. elim H0. @@ -817,7 +806,7 @@ Proof. (* k < x *) unfold f'; simpl. destruct (f oo oo'); simpl. - destruct (X.eq_dec x k); [ absurd_hyp n; auto | auto]. + destruct (X.eq_dec x k); [ contradict n; auto | auto]. destruct (IHm0 H1) as (H3,_); apply H3; auto. destruct (IHm0 H1) as (H3,_); apply H3; auto. @@ -831,7 +820,7 @@ Proof. (* k < x *) unfold f'; simpl. destruct (f oo oo'); simpl. - destruct (X.eq_dec x k); [ absurd_hyp n; auto | auto]. + destruct (X.eq_dec x k); [ contradict n; auto | auto]. destruct (IHm0 H1) as (_,H4); apply H4; auto. destruct (IHm0 H1) as (_,H4); apply H4; auto. Qed. @@ -873,18 +862,18 @@ End Elt3. End Raw. -Module Make (X: DecidableType) <: S with Module E:=X. +Module Make (X: DecidableType) <: WS with Module E:=X. Module Raw := Raw X. Module E := X. Definition key := E.t. - Record slist (elt:Set) : Set := + Record slist (elt:Type) := {this :> Raw.t elt; NoDup : NoDupA (@Raw.PX.eqk elt) this}. - Definition t (elt:Set) := slist elt. + Definition t (elt:Type) := slist elt. Section Elt. - Variable elt elt' elt'':Set. + Variable elt elt' elt'':Type. Implicit Types m : t elt. Implicit Types x y : key. @@ -901,13 +890,18 @@ Section Elt. Definition map2 f m (m':t elt') : t elt'' := Build_slist (Raw.map2_NoDup f m.(NoDup) m'.(NoDup)). Definition elements m : list (key*elt) := @Raw.elements elt m.(this). - Definition fold (A:Set)(f:key->elt->A->A) m (i:A) : A := @Raw.fold elt A f m.(this) i. + Definition cardinal m := length m.(this). + Definition fold (A:Type)(f:key->elt->A->A) m (i:A) : A := @Raw.fold elt A f m.(this) i. Definition equal cmp m m' : bool := @Raw.equal elt cmp m.(this) m'.(this). - Definition MapsTo x e m : Prop := Raw.PX.MapsTo x e m.(this). Definition In x m : Prop := Raw.PX.In x m.(this). Definition Empty m : Prop := Raw.Empty m.(this). - Definition Equal cmp m m' : Prop := @Raw.Equal elt cmp m.(this) m'.(this). + + Definition Equal m m' := forall y, find y m = find y m'. + Definition Equiv (eq_elt:elt->elt->Prop) m m' := + (forall k, In k m <-> In k m') /\ + (forall k e e', MapsTo k e m -> MapsTo k e' m' -> eq_elt e e'). + Definition Equivb cmp m m' : Prop := @Raw.Equivb elt cmp m.(this) m'.(this). Definition eq_key : (key*elt) -> (key*elt) -> Prop := @Raw.PX.eqk elt. Definition eq_key_elt : (key*elt) -> (key*elt) -> Prop:= @Raw.PX.eqke elt. @@ -951,36 +945,39 @@ Section Elt. Proof. intros m; exact (@Raw.elements_1 elt m.(this)). Qed. Lemma elements_2 : forall m x e, InA eq_key_elt (x,e) (elements m) -> MapsTo x e m. Proof. intros m; exact (@Raw.elements_2 elt m.(this)). Qed. - Lemma elements_3 : forall m, NoDupA eq_key (elements m). - Proof. intros m; exact (@Raw.elements_3 elt m.(this) m.(NoDup)). Qed. + Lemma elements_3w : forall m, NoDupA eq_key (elements m). + Proof. intros m; exact (@Raw.elements_3w elt m.(this) m.(NoDup)). Qed. + + Lemma cardinal_1 : forall m, cardinal m = length (elements m). + Proof. intros; reflexivity. Qed. - Lemma fold_1 : forall m (A : Set) (i : A) (f : key -> elt -> A -> A), + Lemma fold_1 : forall m (A : Type) (i : A) (f : key -> elt -> A -> A), fold f m i = fold_left (fun a p => f (fst p) (snd p) a) (elements m) i. Proof. intros m; exact (@Raw.fold_1 elt m.(this)). Qed. - Lemma equal_1 : forall m m' cmp, Equal cmp m m' -> equal cmp m m' = true. + Lemma equal_1 : forall m m' cmp, Equivb cmp m m' -> equal cmp m m' = true. Proof. intros m m'; exact (@Raw.equal_1 elt m.(this) m.(NoDup) m'.(this) m'.(NoDup)). Qed. - Lemma equal_2 : forall m m' cmp, equal cmp m m' = true -> Equal cmp m m'. + Lemma equal_2 : forall m m' cmp, equal cmp m m' = true -> Equivb cmp m m'. Proof. intros m m'; exact (@Raw.equal_2 elt m.(this) m.(NoDup) m'.(this) m'.(NoDup)). Qed. End Elt. - Lemma map_1 : forall (elt elt':Set)(m: t elt)(x:key)(e:elt)(f:elt->elt'), + Lemma map_1 : forall (elt elt':Type)(m: t elt)(x:key)(e:elt)(f:elt->elt'), MapsTo x e m -> MapsTo x (f e) (map f m). Proof. intros elt elt' m; exact (@Raw.map_1 elt elt' m.(this)). Qed. - Lemma map_2 : forall (elt elt':Set)(m: t elt)(x:key)(f:elt->elt'), + Lemma map_2 : forall (elt elt':Type)(m: t elt)(x:key)(f:elt->elt'), In x (map f m) -> In x m. Proof. intros elt elt' m; exact (@Raw.map_2 elt elt' m.(this)). Qed. - Lemma mapi_1 : forall (elt elt':Set)(m: t elt)(x:key)(e:elt) + Lemma mapi_1 : forall (elt elt':Type)(m: t elt)(x:key)(e:elt) (f:key->elt->elt'), MapsTo x e m -> exists y, E.eq y x /\ MapsTo x (f y e) (mapi f m). Proof. intros elt elt' m; exact (@Raw.mapi_1 elt elt' m.(this)). Qed. - Lemma mapi_2 : forall (elt elt':Set)(m: t elt)(x:key) + Lemma mapi_2 : forall (elt elt':Type)(m: t elt)(x:key) (f:key->elt->elt'), In x (mapi f m) -> In x m. Proof. intros elt elt' m; exact (@Raw.mapi_2 elt elt' m.(this)). Qed. - Lemma map2_1 : forall (elt elt' elt'':Set)(m: t elt)(m': t elt') + Lemma map2_1 : forall (elt elt' elt'':Type)(m: t elt)(m': t elt') (x:key)(f:option elt->option elt'->option elt''), In x m \/ In x m' -> find x (map2 f m m') = f (find x m) (find x m'). @@ -988,7 +985,7 @@ Section Elt. intros elt elt' elt'' m m' x f; exact (@Raw.map2_1 elt elt' elt'' f m.(this) m.(NoDup) m'.(this) m'.(NoDup) x). Qed. - Lemma map2_2 : forall (elt elt' elt'':Set)(m: t elt)(m': t elt') + Lemma map2_2 : forall (elt elt' elt'':Type)(m: t elt)(m': t elt') (x:key)(f:option elt->option elt'->option elt''), In x (map2 f m m') -> In x m \/ In x m'. Proof. diff --git a/theories/FSets/FMaps.v b/theories/FSets/FMaps.v index 72ccad3f..75904202 100644 --- a/theories/FSets/FMaps.v +++ b/theories/FSets/FMaps.v @@ -6,13 +6,13 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: FMaps.v 8844 2006-05-22 17:22:36Z letouzey $ *) +(* $Id: FMaps.v 10699 2008-03-19 20:56:43Z letouzey $ *) -Require Export OrderedType. -Require Export OrderedTypeEx. -Require Export OrderedTypeAlt. + +Require Export OrderedType OrderedTypeEx OrderedTypeAlt. +Require Export DecidableType DecidableTypeEx. Require Export FMapInterface. -Require Export FMapList. Require Export FMapPositive. -Require Export FMapIntMap. -Require Export FMapFacts.
\ No newline at end of file +Require Export FMapFacts. +Require Export FMapWeakList. +Require Export FMapList. diff --git a/theories/FSets/FSetAVL.v b/theories/FSets/FSetAVL.v index d5ce54d9..faa705f6 100644 --- a/theories/FSets/FSetAVL.v +++ b/theories/FSets/FSetAVL.v @@ -1,4 +1,3 @@ - (***********************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) (* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) @@ -12,41 +11,555 @@ * Institution: LRI, CNRS UMR 8623 - Université Paris Sud * 91405 Orsay, France *) -(* $Id: FSetAVL.v 9862 2007-05-25 16:57:06Z letouzey $ *) +(* $Id: FSetAVL.v 10811 2008-04-17 16:29:49Z letouzey $ *) + +(** * FSetAVL *) (** This module implements sets using AVL trees. - It follows the implementation from Ocaml's standard library. *) + It follows the implementation from Ocaml's standard library, + + All operations given here expect and produce well-balanced trees + (in the ocaml sense: heigths of subtrees shouldn't differ by more + than 2), and hence has low complexities (e.g. add is logarithmic + in the size of the set). But proving these balancing preservations + is in fact not necessary for ensuring correct operational behavior + and hence fulfilling the FSet interface. As a consequence, + balancing results are not part of this file anymore, they can + now be found in [FSetFullAVL]. + + Four operations ([union], [subset], [compare] and [equal]) have + been slightly adapted in order to have only structural recursive + calls. The precise ocaml versions of these operations have also + been formalized (thanks to Function+measure), see [ocaml_union], + [ocaml_subset], [ocaml_compare] and [ocaml_equal] in + [FSetFullAVL]. The structural variants compute faster in Coq, + whereas the other variants produce nicer and/or (slightly) faster + code after extraction. +*) -Require Import FSetInterface. -Require Import FSetList. -Require Import ZArith. -Require Import Int. +Require Import FSetInterface FSetList ZArith Int. -Set Firstorder Depth 3. +Set Implicit Arguments. +Unset Strict Implicit. -Module Raw (I:Int)(X:OrderedType). -Import I. -Module II:=MoreInt(I). -Import II. -Open Local Scope Int_scope. +(** Notations and helper lemma about pairs *) + +Notation "s #1" := (fst s) (at level 9, format "s '#1'") : pair_scope. +Notation "s #2" := (snd s) (at level 9, format "s '#2'") : pair_scope. -Module E := X. -Module MX := OrderedTypeFacts X. +(** * Raw + + Functor of pure functions + a posteriori proofs of invariant + preservation *) + +Module Raw (Import I:Int)(X:OrderedType). +Open Local Scope pair_scope. +Open Local Scope lazy_bool_scope. +Open Local Scope Int_scope. Definition elt := X.t. -(** * Trees *) +(** * Trees -Inductive tree : Set := + The fourth field of [Node] is the height of the tree *) + +Inductive tree := | Leaf : tree | Node : tree -> X.t -> tree -> int -> tree. Notation t := tree. -(** The fourth field of [Node] is the height of the tree *) +(** * Basic functions on trees: height and cardinal *) + +Definition height (s : tree) : int := + match s with + | Leaf => 0 + | Node _ _ _ h => h + end. + +Fixpoint cardinal (s : tree) : nat := + match s with + | Leaf => 0%nat + | Node l _ r _ => S (cardinal l + cardinal r) + end. + +(** * Empty Set *) + +Definition empty := Leaf. + +(** * Emptyness test *) + +Definition is_empty s := + match s with Leaf => true | _ => false end. + +(** * Appartness *) + +(** The [mem] function is deciding appartness. It exploits the + binary search tree invariant to achieve logarithmic complexity. *) + +Fixpoint mem x s := + match s with + | Leaf => false + | Node l y r _ => match X.compare x y with + | LT _ => mem x l + | EQ _ => true + | GT _ => mem x r + end + end. + +(** * Singleton set *) + +Definition singleton x := Node Leaf x Leaf 1. + +(** * Helper functions *) + +(** [create l x r] creates a node, assuming [l] and [r] + to be balanced and [|height l - height r| <= 2]. *) + +Definition create l x r := + Node l x r (max (height l) (height r) + 1). + +(** [bal l x r] acts as [create], but performs one step of + rebalancing if necessary, i.e. assumes [|height l - height r| <= 3]. *) + +Definition assert_false := create. + +Definition bal l x r := + let hl := height l in + let hr := height r in + if gt_le_dec hl (hr+2) then + match l with + | Leaf => assert_false l x r + | Node ll lx lr _ => + if ge_lt_dec (height ll) (height lr) then + create ll lx (create lr x r) + else + match lr with + | Leaf => assert_false l x r + | Node lrl lrx lrr _ => + create (create ll lx lrl) lrx (create lrr x r) + end + end + else + if gt_le_dec hr (hl+2) then + match r with + | Leaf => assert_false l x r + | Node rl rx rr _ => + if ge_lt_dec (height rr) (height rl) then + create (create l x rl) rx rr + else + match rl with + | Leaf => assert_false l x r + | Node rll rlx rlr _ => + create (create l x rll) rlx (create rlr rx rr) + end + end + else + create l x r. + +(** * Insertion *) + +Fixpoint add x s := match s with + | Leaf => Node Leaf x Leaf 1 + | Node l y r h => + match X.compare x y with + | LT _ => bal (add x l) y r + | EQ _ => Node l y r h + | GT _ => bal l y (add x r) + end + end. + +(** * Join + + Same as [bal] but does not assume anything regarding heights + of [l] and [r]. +*) + +Fixpoint join l : elt -> t -> t := + match l with + | Leaf => add + | Node ll lx lr lh => fun x => + fix join_aux (r:t) : t := match r with + | Leaf => add x l + | Node rl rx rr rh => + if gt_le_dec lh (rh+2) then bal ll lx (join lr x r) + else if gt_le_dec rh (lh+2) then bal (join_aux rl) rx rr + else create l x r + end + end. + +(** * Extraction of minimum element + + Morally, [remove_min] is to be applied to a non-empty tree + [t = Node l x r h]. Since we can't deal here with [assert false] + for [t=Leaf], we pre-unpack [t] (and forget about [h]). +*) + +Fixpoint remove_min l x r : t*elt := + match l with + | Leaf => (r,x) + | Node ll lx lr lh => + let (l',m) := remove_min ll lx lr in (bal l' x r, m) + end. + +(** * Merging two trees + + [merge t1 t2] builds the union of [t1] and [t2] assuming all elements + of [t1] to be smaller than all elements of [t2], and + [|height t1 - height t2| <= 2]. +*) + +Definition merge s1 s2 := match s1,s2 with + | Leaf, _ => s2 + | _, Leaf => s1 + | _, Node l2 x2 r2 h2 => + let (s2',m) := remove_min l2 x2 r2 in bal s1 m s2' +end. + +(** * Deletion *) + +Fixpoint remove x s := match s with + | Leaf => Leaf + | Node l y r h => + match X.compare x y with + | LT _ => bal (remove x l) y r + | EQ _ => merge l r + | GT _ => bal l y (remove x r) + end + end. + +(** * Minimum element *) + +Fixpoint min_elt s := match s with + | Leaf => None + | Node Leaf y _ _ => Some y + | Node l _ _ _ => min_elt l +end. + +(** * Maximum element *) + +Fixpoint max_elt s := match s with + | Leaf => None + | Node _ y Leaf _ => Some y + | Node _ _ r _ => max_elt r +end. + +(** * Any element *) + +Definition choose := min_elt. + +(** * Concatenation + + Same as [merge] but does not assume anything about heights. +*) + +Definition concat s1 s2 := + match s1, s2 with + | Leaf, _ => s2 + | _, Leaf => s1 + | _, Node l2 x2 r2 _ => + let (s2',m) := remove_min l2 x2 r2 in + join s1 m s2' + end. + +(** * Splitting + + [split x s] returns a triple [(l, present, r)] where + - [l] is the set of elements of [s] that are [< x] + - [r] is the set of elements of [s] that are [> x] + - [present] is [true] if and only if [s] contains [x]. +*) + +Record triple := mktriple { t_left:t; t_in:bool; t_right:t }. +Notation "<< l , b , r >>" := (mktriple l b r) (at level 9). +Notation "t #l" := (t_left t) (at level 9, format "t '#l'"). +Notation "t #b" := (t_in t) (at level 9, format "t '#b'"). +Notation "t #r" := (t_right t) (at level 9, format "t '#r'"). + +Fixpoint split x s : triple := match s with + | Leaf => << Leaf, false, Leaf >> + | Node l y r h => + match X.compare x y with + | LT _ => let (ll,b,rl) := split x l in << ll, b, join rl y r >> + | EQ _ => << l, true, r >> + | GT _ => let (rl,b,rr) := split x r in << join l y rl, b, rr >> + end + end. + +(** * Intersection *) + +Fixpoint inter s1 s2 := match s1, s2 with + | Leaf, _ => Leaf + | _, Leaf => Leaf + | Node l1 x1 r1 h1, _ => + let (l2',pres,r2') := split x1 s2 in + if pres then join (inter l1 l2') x1 (inter r1 r2') + else concat (inter l1 l2') (inter r1 r2') + end. + +(** * Difference *) + +Fixpoint diff s1 s2 := match s1, s2 with + | Leaf, _ => Leaf + | _, Leaf => s1 + | Node l1 x1 r1 h1, _ => + let (l2',pres,r2') := split x1 s2 in + if pres then concat (diff l1 l2') (diff r1 r2') + else join (diff l1 l2') x1 (diff r1 r2') +end. + +(** * Union *) + +(** In ocaml, heights of [s1] and [s2] are compared each time in order + to recursively perform the split on the smaller set. + Unfortunately, this leads to a non-structural algorithm. The + following code is a simplification of the ocaml version: no + comparison of heights. It might be slightly slower, but + experimentally all the tests I've made in ocaml have shown this + potential slowdown to be non-significant. Anyway, the exact code + of ocaml has also been formalized thanks to Function+measure, see + [ocaml_union] in [FSetFullAVL]. +*) + +Fixpoint union s1 s2 := + match s1, s2 with + | Leaf, _ => s2 + | _, Leaf => s1 + | Node l1 x1 r1 h1, _ => + let (l2',_,r2') := split x1 s2 in + join (union l1 l2') x1 (union r1 r2') + end. + +(** * Elements *) + +(** [elements_tree_aux acc t] catenates the elements of [t] in infix + order to the list [acc] *) + +Fixpoint elements_aux (acc : list X.t) (t : tree) : list X.t := + match t with + | Leaf => acc + | Node l x r _ => elements_aux (x :: elements_aux acc r) l + end. + +(** then [elements] is an instanciation with an empty [acc] *) + +Definition elements := elements_aux nil. + +(** * Filter *) + +Fixpoint filter_acc (f:elt->bool) acc s := match s with + | Leaf => acc + | Node l x r h => + filter_acc f (filter_acc f (if f x then add x acc else acc) l) r + end. + +Definition filter f := filter_acc f Leaf. + + +(** * Partition *) + +Fixpoint partition_acc (f:elt->bool)(acc : t*t)(s : t) : t*t := + match s with + | Leaf => acc + | Node l x r _ => + let (acct,accf) := acc in + partition_acc f + (partition_acc f + (if f x then (add x acct, accf) else (acct, add x accf)) l) r + end. + +Definition partition f := partition_acc f (Leaf,Leaf). + +(** * [for_all] and [exists] *) + +Fixpoint for_all (f:elt->bool) s := match s with + | Leaf => true + | Node l x r _ => f x &&& for_all f l &&& for_all f r +end. + +Fixpoint exists_ (f:elt->bool) s := match s with + | Leaf => false + | Node l x r _ => f x ||| exists_ f l ||| exists_ f r +end. + +(** * Fold *) + +Fixpoint fold (A : Type) (f : elt -> A -> A)(s : tree) : A -> A := + fun a => match s with + | Leaf => a + | Node l x r _ => fold f r (f x (fold f l a)) + end. +Implicit Arguments fold [A]. + + +(** * Subset *) + +(** In ocaml, recursive calls are made on "half-trees" such as + (Node l1 x1 Leaf _) and (Node Leaf x1 r1 _). Instead of these + non-structural calls, we propose here two specialized functions for + these situations. This version should be almost as efficient as + the one of ocaml (closures as arguments may slow things a bit), + it is simply less compact. The exact ocaml version has also been + formalized (thanks to Function+measure), see [ocaml_subset] in + [FSetFullAVL]. + *) + +Fixpoint subsetl (subset_l1:t->bool) x1 s2 : bool := + match s2 with + | Leaf => false + | Node l2 x2 r2 h2 => + match X.compare x1 x2 with + | EQ _ => subset_l1 l2 + | LT _ => subsetl subset_l1 x1 l2 + | GT _ => mem x1 r2 &&& subset_l1 s2 + end + end. + +Fixpoint subsetr (subset_r1:t->bool) x1 s2 : bool := + match s2 with + | Leaf => false + | Node l2 x2 r2 h2 => + match X.compare x1 x2 with + | EQ _ => subset_r1 r2 + | LT _ => mem x1 l2 &&& subset_r1 s2 + | GT _ => subsetr subset_r1 x1 r2 + end + end. + +Fixpoint subset s1 s2 : bool := match s1, s2 with + | Leaf, _ => true + | Node _ _ _ _, Leaf => false + | Node l1 x1 r1 h1, Node l2 x2 r2 h2 => + match X.compare x1 x2 with + | EQ _ => subset l1 l2 &&& subset r1 r2 + | LT _ => subsetl (subset l1) x1 l2 &&& subset r1 s2 + | GT _ => subsetr (subset r1) x1 r2 &&& subset l1 s2 + end + end. + +(** * A new comparison algorithm suggested by Xavier Leroy + + Transformation in C.P.S. suggested by Benjamin Grégoire. + The original ocaml code (with non-structural recursive calls) + has also been formalized (thanks to Function+measure), see + [ocaml_compare] in [FSetFullAVL]. The following code with + continuations computes dramatically faster in Coq, and + should be almost as efficient after extraction. +*) + +(** Enumeration of the elements of a tree *) + +Inductive enumeration := + | End : enumeration + | More : elt -> tree -> enumeration -> enumeration. + + +(** [cons t e] adds the elements of tree [t] on the head of + enumeration [e]. *) + +Fixpoint cons s e : enumeration := + match s with + | Leaf => e + | Node l x r h => cons l (More x r e) + end. + +(** One step of comparison of elements *) + +Definition compare_more x1 (cont:enumeration->comparison) e2 := + match e2 with + | End => Gt + | More x2 r2 e2 => + match X.compare x1 x2 with + | EQ _ => cont (cons r2 e2) + | LT _ => Lt + | GT _ => Gt + end + end. + +(** Comparison of left tree, middle element, then right tree *) + +Fixpoint compare_cont s1 (cont:enumeration->comparison) e2 := + match s1 with + | Leaf => cont e2 + | Node l1 x1 r1 _ => + compare_cont l1 (compare_more x1 (compare_cont r1 cont)) e2 + end. + +(** Initial continuation *) + +Definition compare_end e2 := + match e2 with End => Eq | _ => Lt end. + +(** The complete comparison *) + +Definition compare s1 s2 := compare_cont s1 compare_end (cons s2 End). + +(** * Equality test *) + +Definition equal s1 s2 : bool := + match compare s1 s2 with + | Eq => true + | _ => false + end. + + + + +(** * Invariants *) + +(** ** Occurrence in a tree *) + +Inductive In (x : elt) : tree -> Prop := + | IsRoot : forall l r h y, X.eq x y -> In x (Node l y r h) + | InLeft : forall l r h y, In x l -> In x (Node l y r h) + | InRight : forall l r h y, In x r -> In x (Node l y r h). + +(** ** Binary search trees *) + +(** [lt_tree x s]: all elements in [s] are smaller than [x] + (resp. greater for [gt_tree]) *) + +Definition lt_tree x s := forall y, In y s -> X.lt y x. +Definition gt_tree x s := forall y, In y s -> X.lt x y. + +(** [bst t] : [t] is a binary search tree *) + +Inductive bst : tree -> Prop := + | BSLeaf : bst Leaf + | BSNode : forall x l r h, bst l -> bst r -> + lt_tree x l -> gt_tree x r -> bst (Node l x r h). + + + + +(** * Some shortcuts *) + +Definition Equal s s' := forall a : elt, In a s <-> In a s'. +Definition Subset s s' := forall a : elt, In a s -> In a s'. +Definition Empty s := forall a : elt, ~ In a s. +Definition For_all (P : elt -> Prop) s := forall x, In x s -> P x. +Definition Exists (P : elt -> Prop) s := exists x, In x s /\ P x. + + + +(** * Correctness proofs, isolated in a sub-module *) + +Module Proofs. + Module MX := OrderedTypeFacts X. + Module L := FSetList.Raw X. + +(** * Automation and dedicated tactics *) + +Hint Constructors In bst. +Hint Unfold lt_tree gt_tree. + +Tactic Notation "factornode" ident(l) ident(x) ident(r) ident(h) + "as" ident(s) := + set (s:=Node l x r h) in *; clearbody s; clear l x r h. (** A tactic to repeat [inversion_clear] on all hyps of the form [(f (Node _ _ _ _))] *) + Ltac inv f := match goal with | H:f Leaf |- _ => inversion_clear H; inv f @@ -56,30 +569,18 @@ Ltac inv f := | _ => idtac end. -(** Same, but with a backup of the original hypothesis. *) +Ltac intuition_in := repeat progress (intuition; inv In). -Ltac safe_inv f := match goal with - | H:f (Node _ _ _ _) |- _ => - generalize H; inversion_clear H; safe_inv f - | _ => intros - end. +(** Helper tactic concerning order of elements. *) -(** * Occurrence in a tree *) +Ltac order := match goal with + | U: lt_tree _ ?s, V: In _ ?s |- _ => generalize (U _ V); clear U; order + | U: gt_tree _ ?s, V: In _ ?s |- _ => generalize (U _ V); clear U; order + | _ => MX.order +end. -Inductive In (x : elt) : tree -> Prop := - | IsRoot : - forall (l r : tree) (h : int) (y : elt), - X.eq x y -> In x (Node l y r h) - | InLeft : - forall (l r : tree) (h : int) (y : elt), - In x l -> In x (Node l y r h) - | InRight : - forall (l r : tree) (h : int) (y : elt), - In x r -> In x (Node l y r h). - -Hint Constructors In. -Ltac intuition_in := repeat progress (intuition; inv In). +(** * Basic results about [In], [lt_tree], [gt_tree], [height] *) (** [In] is compatible with [X.eq] *) @@ -90,48 +591,37 @@ Proof. Qed. Hint Immediate In_1. -(** * Binary search trees *) - -(** [lt_tree x s]: all elements in [s] are smaller than [x] - (resp. greater for [gt_tree]) *) - -Definition lt_tree (x : elt) (s : tree) := - forall y:elt, In y s -> X.lt y x. -Definition gt_tree (x : elt) (s : tree) := - forall y:elt, In y s -> X.lt x y. - -Hint Unfold lt_tree gt_tree. - -Ltac order := match goal with - | H: lt_tree ?x ?s, H1: In ?y ?s |- _ => generalize (H _ H1); clear H; order - | H: gt_tree ?x ?s, H1: In ?y ?s |- _ => generalize (H _ H1); clear H; order - | _ => MX.order -end. +Lemma In_node_iff : + forall l x r h y, + In y (Node l x r h) <-> In y l \/ X.eq y x \/ In y r. +Proof. + intuition_in. +Qed. (** Results about [lt_tree] and [gt_tree] *) Lemma lt_leaf : forall x : elt, lt_tree x Leaf. Proof. - unfold lt_tree in |- *; intros; inversion H. + red; inversion 1. Qed. Lemma gt_leaf : forall x : elt, gt_tree x Leaf. Proof. - unfold gt_tree in |- *; intros; inversion H. + red; inversion 1. Qed. Lemma lt_tree_node : forall (x y : elt) (l r : tree) (h : int), lt_tree x l -> lt_tree x r -> X.lt y x -> lt_tree x (Node l y r h). Proof. - unfold lt_tree in *; intuition_in; order. + unfold lt_tree; intuition_in; order. Qed. Lemma gt_tree_node : forall (x y : elt) (l r : tree) (h : int), gt_tree x l -> gt_tree x r -> X.lt x y -> gt_tree x (Node l y r h). Proof. - unfold gt_tree in *; intuition_in; order. + unfold gt_tree; intuition_in; order. Qed. Hint Resolve lt_leaf gt_leaf lt_tree_node gt_tree_node. @@ -145,7 +635,7 @@ Qed. Lemma lt_tree_trans : forall x y, X.lt x y -> forall t, lt_tree x t -> lt_tree y t. Proof. - firstorder eauto. + eauto. Qed. Lemma gt_tree_not_in : @@ -157,120 +647,43 @@ Qed. Lemma gt_tree_trans : forall x y, X.lt y x -> forall t, gt_tree x t -> gt_tree y t. Proof. - firstorder eauto. + eauto. Qed. Hint Resolve lt_tree_not_in lt_tree_trans gt_tree_not_in gt_tree_trans. -(** [bst t] : [t] is a binary search tree *) - -Inductive bst : tree -> Prop := - | BSLeaf : bst Leaf - | BSNode : - forall (x : elt) (l r : tree) (h : int), - bst l -> bst r -> lt_tree x l -> gt_tree x r -> bst (Node l x r h). +(** * Inductions principles *) -Hint Constructors bst. +Functional Scheme mem_ind := Induction for mem Sort Prop. +Functional Scheme bal_ind := Induction for bal Sort Prop. +Functional Scheme add_ind := Induction for add Sort Prop. +Functional Scheme remove_min_ind := Induction for remove_min Sort Prop. +Functional Scheme merge_ind := Induction for merge Sort Prop. +Functional Scheme remove_ind := Induction for remove Sort Prop. +Functional Scheme min_elt_ind := Induction for min_elt Sort Prop. +Functional Scheme max_elt_ind := Induction for max_elt Sort Prop. +Functional Scheme concat_ind := Induction for concat Sort Prop. +Functional Scheme split_ind := Induction for split Sort Prop. +Functional Scheme inter_ind := Induction for inter Sort Prop. +Functional Scheme diff_ind := Induction for diff Sort Prop. +Functional Scheme union_ind := Induction for union Sort Prop. -(** * AVL trees *) -(** [avl s] : [s] is a properly balanced AVL tree, - i.e. for any node the heights of the two children - differ by at most 2 *) - -Definition height (s : tree) : int := - match s with - | Leaf => 0 - | Node _ _ _ h => h - end. - -Inductive avl : tree -> Prop := - | RBLeaf : avl Leaf - | RBNode : - forall (x : elt) (l r : tree) (h : int), - avl l -> - avl r -> - -(2) <= height l - height r <= 2 -> - h = max (height l) (height r) + 1 -> - avl (Node l x r h). - -Hint Constructors avl. - -(** Results about [avl] *) - -Lemma avl_node : - forall (x : elt) (l r : tree), - avl l -> - avl r -> - -(2) <= height l - height r <= 2 -> - avl (Node l x r (max (height l) (height r) + 1)). -Proof. - intros; auto. -Qed. -Hint Resolve avl_node. - -(** The tactics *) +(** * Empty set *) -Lemma height_non_negative : forall s : tree, avl s -> height s >= 0. +Lemma empty_1 : Empty empty. Proof. - induction s; simpl; intros; auto with zarith. - inv avl; intuition; omega_max. + intro; intro. + inversion H. Qed. -Implicit Arguments height_non_negative. - -(** When [H:avl r], typing [avl_nn H] or [avl_nn r] adds [height r>=0] *) - -Ltac avl_nn_hyp H := - let nz := fresh "nz" in assert (nz := height_non_negative H). - -Ltac avl_nn h := - let t := type of h in - match type of t with - | Prop => avl_nn_hyp h - | _ => match goal with H : avl h |- _ => avl_nn_hyp H end - end. - -(* Repeat the previous tactic. - Drawback: need to clear the [avl _] hyps ... Thank you Ltac *) - -Ltac avl_nns := - match goal with - | H:avl _ |- _ => avl_nn_hyp H; clear H; avl_nns - | _ => idtac - end. - -(** * Some shortcuts. *) - -Definition Equal s s' := forall a : elt, In a s <-> In a s'. -Definition Subset s s' := forall a : elt, In a s -> In a s'. -Definition Empty s := forall a : elt, ~ In a s. -Definition For_all (P : elt -> Prop) s := forall x, In x s -> P x. -Definition Exists (P : elt -> Prop) s := exists x, In x s /\ P x. - -(** * Empty set *) - -Definition empty := Leaf. Lemma empty_bst : bst empty. Proof. auto. Qed. -Lemma empty_avl : avl empty. -Proof. - auto. -Qed. - -Lemma empty_1 : Empty empty. -Proof. - intro; intro. - inversion H. -Qed. - (** * Emptyness test *) -Definition is_empty (s:t) := match s with Leaf => true | _ => false end. - Lemma is_empty_1 : forall s, Empty s -> is_empty s = true. Proof. destruct s as [|r x l h]; simpl; auto. @@ -282,54 +695,28 @@ Proof. destruct s; simpl; intros; try discriminate; red; auto. Qed. -(** * Appartness *) -(** The [mem] function is deciding appartness. It exploits the [bst] property - to achieve logarithmic complexity. *) -Function mem (x:elt)(s:t) { struct s } : bool := - match s with - | Leaf => false - | Node l y r _ => match X.compare x y with - | LT _ => mem x l - | EQ _ => true - | GT _ => mem x r - end - end. +(** * Appartness *) Lemma mem_1 : forall s x, bst s -> In x s -> mem x s = true. -Proof. - intros s x. - functional induction (mem x s); inversion_clear 1; auto. - inversion_clear 1. - inversion_clear 1; auto; absurd (X.lt x y); eauto. - inversion_clear 1; auto; absurd (X.lt y x); eauto. +Proof. + intros s x; functional induction mem x s; auto; intros; try clear e0; + inv bst; intuition_in; order. Qed. Lemma mem_2 : forall s x, mem x s = true -> In x s. Proof. - intros s x. - functional induction (mem x s); auto; intros; try discriminate. + intros s x; functional induction mem x s; auto; intros; discriminate. Qed. -(** * Singleton set *) -Definition singleton (x : elt) := Node Leaf x Leaf 1. - -Lemma singleton_bst : forall x : elt, bst (singleton x). -Proof. - unfold singleton; auto. -Qed. -Lemma singleton_avl : forall x : elt, avl (singleton x). -Proof. - unfold singleton; intro. - constructor; auto; try red; simpl; omega_max. -Qed. +(** * Singleton set *) Lemma singleton_1 : forall x y, In y (singleton x) -> X.eq x y. Proof. - unfold singleton; inversion_clear 1; auto; inversion_clear H0. + unfold singleton; intros; inv In; order. Qed. Lemma singleton_2 : forall x y, X.eq x y -> In y (singleton x). @@ -337,35 +724,14 @@ Proof. unfold singleton; auto. Qed. -(** * Helper functions *) - -(** [create l x r] creates a node, assuming [l] and [r] - to be balanced and [|height l - height r| <= 2]. *) - -Definition create l x r := - Node l x r (max (height l) (height r) + 1). - -Lemma create_bst : - forall l x r, bst l -> bst r -> lt_tree x l -> gt_tree x r -> - bst (create l x r). +Lemma singleton_bst : forall x : elt, bst (singleton x). Proof. - unfold create; auto. + unfold singleton; auto. Qed. -Hint Resolve create_bst. -Lemma create_avl : - forall l x r, avl l -> avl r -> -(2) <= height l - height r <= 2 -> - avl (create l x r). -Proof. - unfold create; auto. -Qed. -Lemma create_height : - forall l x r, avl l -> avl r -> -(2) <= height l - height r <= 2 -> - height (create l x r) = max (height l) (height r) + 1. -Proof. - unfold create; intros; auto. -Qed. + +(** * Helper functions *) Lemma create_in : forall l x r y, In y (create l x r) <-> X.eq y x \/ In y l \/ In y r. @@ -373,196 +739,69 @@ Proof. unfold create; split; [ inversion_clear 1 | ]; intuition. Qed. -(** trick for emulating [assert false] in Coq *) - -Definition assert_false := Leaf. - -(** [bal l x r] acts as [create], but performs one step of - rebalancing if necessary, i.e. assumes [|height l - height r| <= 3]. *) - -Definition bal l x r := - let hl := height l in - let hr := height r in - if gt_le_dec hl (hr+2) then - match l with - | Leaf => assert_false - | Node ll lx lr _ => - if ge_lt_dec (height ll) (height lr) then - create ll lx (create lr x r) - else - match lr with - | Leaf => assert_false - | Node lrl lrx lrr _ => - create (create ll lx lrl) lrx (create lrr x r) - end - end - else - if gt_le_dec hr (hl+2) then - match r with - | Leaf => assert_false - | Node rl rx rr _ => - if ge_lt_dec (height rr) (height rl) then - create (create l x rl) rx rr - else - match rl with - | Leaf => assert_false - | Node rll rlx rlr _ => - create (create l x rll) rlx (create rlr rx rr) - end - end - else - create l x r. - -Ltac bal_tac := - intros l x r; - unfold bal; - destruct (gt_le_dec (height l) (height r + 2)); - [ destruct l as [ |ll lx lr lh]; - [ | destruct (ge_lt_dec (height ll) (height lr)); - [ | destruct lr ] ] - | destruct (gt_le_dec (height r) (height l + 2)); - [ destruct r as [ |rl rx rr rh]; - [ | destruct (ge_lt_dec (height rr) (height rl)); - [ | destruct rl ] ] - | ] ]; intros. - -Lemma bal_bst : forall l x r, bst l -> bst r -> - lt_tree x l -> gt_tree x r -> bst (bal l x r). -Proof. - (* intros l x r; functional induction bal l x r. MARCHE PAS !*) - bal_tac; - inv bst; repeat apply create_bst; auto; unfold create; - apply lt_tree_node || apply gt_tree_node; auto; - eapply lt_tree_trans || eapply gt_tree_trans || eauto; eauto. -Qed. - -Lemma bal_avl : forall l x r, avl l -> avl r -> - -(3) <= height l - height r <= 3 -> avl (bal l x r). +Lemma create_bst : + forall l x r, bst l -> bst r -> lt_tree x l -> gt_tree x r -> + bst (create l x r). Proof. - bal_tac; inv avl; repeat apply create_avl; simpl in *; auto; omega_max. + unfold create; auto. Qed. +Hint Resolve create_bst. -Lemma bal_height_1 : forall l x r, avl l -> avl r -> - -(3) <= height l - height r <= 3 -> - 0 <= height (bal l x r) - max (height l) (height r) <= 1. +Lemma bal_in : forall l x r y, + In y (bal l x r) <-> X.eq y x \/ In y l \/ In y r. Proof. - bal_tac; inv avl; avl_nns; simpl in *; omega_max. + intros l x r; functional induction bal l x r; intros; try clear e0; + rewrite !create_in; intuition_in. Qed. -Lemma bal_height_2 : - forall l x r, avl l -> avl r -> -(2) <= height l - height r <= 2 -> - height (bal l x r) == max (height l) (height r) +1. +Lemma bal_bst : forall l x r, bst l -> bst r -> + lt_tree x l -> gt_tree x r -> bst (bal l x r). Proof. - bal_tac; inv avl; simpl in *; omega_max. + intros l x r; functional induction bal l x r; intros; + inv bst; repeat apply create_bst; auto; unfold create; + (apply lt_tree_node || apply gt_tree_node); auto; + (eapply lt_tree_trans || eapply gt_tree_trans); eauto. Qed. +Hint Resolve bal_bst. -Lemma bal_in : forall l x r y, avl l -> avl r -> - (In y (bal l x r) <-> X.eq y x \/ In y l \/ In y r). -Proof. - bal_tac; - solve [repeat rewrite create_in; intuition_in - |inv avl; avl_nns; simpl in *; false_omega]. -Qed. -Ltac omega_bal := match goal with - | H:avl ?l, H':avl ?r |- context [ bal ?l ?x ?r ] => - generalize (bal_height_1 l x r H H') (bal_height_2 l x r H H'); - omega_max - end. (** * Insertion *) -Function add (x:elt)(s:t) { struct s } : t := match s with - | Leaf => Node Leaf x Leaf 1 - | Node l y r h => - match X.compare x y with - | LT _ => bal (add x l) y r - | EQ _ => Node l y r h - | GT _ => bal l y (add x r) - end - end. - -Lemma add_avl_1 : forall s x, avl s -> - avl (add x s) /\ 0 <= height (add x s) - height s <= 1. -Proof. - intros s x; functional induction (add x s); subst;intros; inv avl; simpl in *. - intuition; try constructor; simpl; auto; try omega_max. - (* LT *) - destruct IHt; auto. - split. - apply bal_avl; auto; omega_max. - omega_bal. - (* EQ *) - intuition; omega_max. - (* GT *) - destruct IHt; auto. - split. - apply bal_avl; auto; omega_max. - omega_bal. -Qed. - -Lemma add_avl : forall s x, avl s -> avl (add x s). -Proof. - intros; generalize (add_avl_1 s x H); intuition. -Qed. -Hint Resolve add_avl. - -Lemma add_in : forall s x y, avl s -> - (In y (add x s) <-> X.eq y x \/ In y s). +Lemma add_in : forall s x y, + In y (add x s) <-> X.eq y x \/ In y s. Proof. - intros s x; functional induction (add x s); auto; intros. - intuition_in. - (* LT *) - inv avl. - rewrite bal_in; auto. - rewrite (IHt y0 H0); intuition_in. - (* EQ *) - inv avl. - intuition. + intros s x; functional induction (add x s); auto; intros; + try rewrite bal_in, IHt; intuition_in. eapply In_1; eauto. - (* GT *) - inv avl. - rewrite bal_in; auto. - rewrite (IHt y0 H1); intuition_in. Qed. -Lemma add_bst : forall s x, bst s -> avl s -> bst (add x s). +Lemma add_bst : forall s x, bst s -> bst (add x s). Proof. - intros s x; functional induction (add x s); auto; intros. - inv bst; inv avl; apply bal_bst; auto. + intros s x; functional induction (add x s); auto; intros; + inv bst; apply bal_bst; auto. (* lt_tree -> lt_tree (add ...) *) - red; red in H4. + red; red in H3. intros. - rewrite (add_in l x y0 H) in H0. + rewrite add_in in H. intuition. eauto. - inv bst; inv avl; apply bal_bst; auto. + inv bst; auto using bal_bst. (* gt_tree -> gt_tree (add ...) *) - red; red in H4. + red; red in H3. intros. - rewrite (add_in r x y0 H5) in H0. + rewrite add_in in H. intuition. apply MX.lt_eq with x; auto. Qed. +Hint Resolve add_bst. -(** * Join - Same as [bal] but does not assume anything regarding heights - of [l] and [r]. -*) -Fixpoint join (l:t) : elt -> t -> t := - match l with - | Leaf => add - | Node ll lx lr lh => fun x => - fix join_aux (r:t) : t := match r with - | Leaf => add x l - | Node rl rx rr rh => - if gt_le_dec lh (rh+2) then bal ll lx (join lr x r) - else if gt_le_dec rh (lh+2) then bal (join_aux rl) rx rr - else create l x r - end - end. +(** * Join *) + +(* Function/Functional Scheme can't deal with internal fix. + Let's do its job by hand: *) Ltac join_tac := intro l; induction l as [| ll _ lx lr Hlr lh]; @@ -579,437 +818,200 @@ Ltac join_tac := end | ] ] ] ]; intros. -Lemma join_avl_1 : forall l x r, avl l -> avl r -> avl (join l x r) /\ - 0<= height (join l x r) - max (height l) (height r) <= 1. -Proof. - (* intros l x r; functional induction join l x r. AUTRE PROBLEME! *) - join_tac. - - split; simpl; auto. - destruct (add_avl_1 r x H0). - avl_nns; omega_max. - split; auto. - set (l:=Node ll lx lr lh) in *. - destruct (add_avl_1 l x H). - simpl (height Leaf). - avl_nns; omega_max. - - inversion_clear H. - assert (height (Node rl rx rr rh) = rh); auto. - set (r := Node rl rx rr rh) in *; clearbody r. - destruct (Hlr x r H2 H0); clear Hrl Hlr. - set (j := join lr x r) in *; clearbody j. - simpl. - assert (-(3) <= height ll - height j <= 3) by omega_max. - split. - apply bal_avl; auto. - omega_bal. - - inversion_clear H0. - assert (height (Node ll lx lr lh) = lh); auto. - set (l := Node ll lx lr lh) in *; clearbody l. - destruct (Hrl H H1); clear Hrl Hlr. - set (j := join l x rl) in *; clearbody j. - simpl. - assert (-(3) <= height j - height rr <= 3) by omega_max. - split. - apply bal_avl; auto. - omega_bal. - - clear Hrl Hlr. - assert (height (Node ll lx lr lh) = lh); auto. - assert (height (Node rl rx rr rh) = rh); auto. - set (l := Node ll lx lr lh) in *; clearbody l. - set (r := Node rl rx rr rh) in *; clearbody r. - assert (-(2) <= height l - height r <= 2) by omega_max. - split. - apply create_avl; auto. - rewrite create_height; auto; omega_max. -Qed. - -Lemma join_avl : forall l x r, avl l -> avl r -> avl (join l x r). -Proof. - intros; generalize (join_avl_1 l x r H H0); intuition. -Qed. -Hint Resolve join_avl. - -Lemma join_in : forall l x r y, avl l -> avl r -> - (In y (join l x r) <-> X.eq y x \/ In y l \/ In y r). +Lemma join_in : forall l x r y, + In y (join l x r) <-> X.eq y x \/ In y l \/ In y r. Proof. join_tac. simpl. rewrite add_in; intuition_in. - rewrite add_in; intuition_in. - - inv avl. - rewrite bal_in; auto. - rewrite Hlr; clear Hlr Hrl; intuition_in. - - inv avl. - rewrite bal_in; auto. - rewrite Hrl; clear Hlr Hrl; intuition_in. - + rewrite bal_in, Hlr; clear Hlr Hrl; intuition_in. + rewrite bal_in, Hrl; clear Hlr Hrl; intuition_in. apply create_in. Qed. -Lemma join_bst : forall l x r, bst l -> avl l -> bst r -> avl r -> +Lemma join_bst : forall l x r, bst l -> bst r -> lt_tree x l -> gt_tree x r -> bst (join l x r). Proof. - join_tac. - apply add_bst; auto. - apply add_bst; auto. - - inv bst; safe_inv avl. - apply bal_bst; auto. - clear Hrl Hlr H13 H14 H16 H17 z; intro; intros. - set (r:=Node rl rx rr rh) in *; clearbody r. - rewrite (join_in lr x r y) in H13; auto. - intuition. - apply MX.lt_eq with x; eauto. - eauto. - - inv bst; safe_inv avl. - apply bal_bst; auto. - clear Hrl Hlr H13 H14 H16 H17 z; intro; intros. - set (l:=Node ll lx lr lh) in *; clearbody l. - rewrite (join_in l x rl y) in H13; auto. - intuition. - apply MX.eq_lt with x; eauto. - eauto. - - apply create_bst; auto. + join_tac; auto; inv bst; apply bal_bst; auto; + clear Hrl Hlr z; intro; intros; rewrite join_in in *. + intuition; [ apply MX.lt_eq with x | ]; eauto. + intuition; [ apply MX.eq_lt with x | ]; eauto. Qed. +Hint Resolve join_bst. -(** * Extraction of minimum element - morally, [remove_min] is to be applied to a non-empty tree - [t = Node l x r h]. Since we can't deal here with [assert false] - for [t=Leaf], we pre-unpack [t] (and forget about [h]). -*) - -Function remove_min (l:t)(x:elt)(r:t) { struct l } : t*elt := - match l with - | Leaf => (r,x) - | Node ll lx lr lh => let (l',m) := (remove_min ll lx lr : t*elt) in (bal l' x r, m) - end. - -Lemma remove_min_avl_1 : forall l x r h, avl (Node l x r h) -> - avl (fst (remove_min l x r)) /\ - 0 <= height (Node l x r h) - height (fst (remove_min l x r)) <= 1. -Proof. - intros l x r; functional induction (remove_min l x r); subst;simpl in *; intros. - inv avl; simpl in *; split; auto. - avl_nns; omega_max. - (* l = Node *) - inversion_clear H. - rewrite e0 in IHp;simpl in IHp;destruct (IHp lh); auto. - split; simpl in *. - apply bal_avl; auto; omega_max. - omega_bal. -Qed. -Lemma remove_min_avl : forall l x r h, avl (Node l x r h) -> - avl (fst (remove_min l x r)). -Proof. - intros; generalize (remove_min_avl_1 l x r h H); intuition. -Qed. +(** * Extraction of minimum element *) -Lemma remove_min_in : forall l x r h y, avl (Node l x r h) -> - (In y (Node l x r h) <-> - X.eq y (snd (remove_min l x r)) \/ In y (fst (remove_min l x r))). +Lemma remove_min_in : forall l x r h y, + In y (Node l x r h) <-> + X.eq y (remove_min l x r)#2 \/ In y (remove_min l x r)#1. Proof. intros l x r; functional induction (remove_min l x r); simpl in *; intros. intuition_in. - (* l = Node *) - inversion_clear H. - generalize (remove_min_avl ll lx lr lh H0). - rewrite e0; simpl; intros. - rewrite bal_in; auto. - rewrite e0 in IHp;generalize (IHp lh y H0). - intuition. - inversion_clear H7; intuition. + rewrite bal_in, In_node_iff, IHp, e0; simpl; intuition. Qed. Lemma remove_min_bst : forall l x r h, - bst (Node l x r h) -> avl (Node l x r h) -> bst (fst (remove_min l x r)). + bst (Node l x r h) -> bst (remove_min l x r)#1. Proof. - intros l x r; functional induction (remove_min l x r); subst;simpl in *; intros. + intros l x r; functional induction (remove_min l x r); simpl; intros. inv bst; auto. - inversion_clear H; inversion_clear H0. - rewrite_all e0;simpl in *. + inversion_clear H. + specialize IHp with (1:=H0); rewrite e0 in IHp; auto. apply bal_bst; auto. - firstorder. - intro; intros. - generalize (remove_min_in ll lx lr lh y H). - rewrite e0; simpl. - destruct 1. - apply H3; intuition. + intro y; specialize (H2 y). + rewrite remove_min_in, e0 in H2; simpl in H2; intuition. Qed. Lemma remove_min_gt_tree : forall l x r h, - bst (Node l x r h) -> avl (Node l x r h) -> - gt_tree (snd (remove_min l x r)) (fst (remove_min l x r)). + bst (Node l x r h) -> + gt_tree (remove_min l x r)#2 (remove_min l x r)#1. Proof. - intros l x r; functional induction (remove_min l x r); subst;simpl in *; intros. + intros l x r; functional induction (remove_min l x r); simpl; intros. inv bst; auto. - inversion_clear H; inversion_clear H0. - intro; intro. - generalize (IHp lh H1 H); clear H6 H7 IHp. - generalize (remove_min_avl ll lx lr lh H). - generalize (remove_min_in ll lx lr lh m H). - rewrite e0; simpl; intros. - rewrite (bal_in l' x r y H7 H5) in H0. - destruct H6. - firstorder. - apply MX.lt_eq with x; auto. - apply X.lt_trans with x; auto. + inversion_clear H. + specialize IHp with (1:=H0); rewrite e0 in IHp; simpl in IHp. + intro y; rewrite bal_in; intuition; + specialize (H2 m); rewrite remove_min_in, e0 in H2; simpl in H2; + [ apply MX.lt_eq with x | ]; eauto. Qed. +Hint Resolve remove_min_bst remove_min_gt_tree. -(** * Merging two trees - - [merge t1 t2] builds the union of [t1] and [t2] assuming all elements - of [t1] to be smaller than all elements of [t2], and - [|height t1 - height t2| <= 2]. -*) -Function merge (s1 s2 :t) : t:= match s1,s2 with - | Leaf, _ => s2 - | _, Leaf => s1 - | _, Node l2 x2 r2 h2 => - let (s2',m) := remove_min l2 x2 r2 in bal s1 m s2' -end. -Lemma merge_avl_1 : forall s1 s2, avl s1 -> avl s2 -> - -(2) <= height s1 - height s2 <= 2 -> - avl (merge s1 s2) /\ - 0<= height (merge s1 s2) - max (height s1) (height s2) <=1. -Proof. - intros s1 s2; functional induction (merge s1 s2); subst;simpl in *; intros. - split; auto; avl_nns; omega_max. - split; auto; avl_nns; simpl in *; omega_max. - destruct s1;try contradiction;clear y. - generalize (remove_min_avl_1 l2 x2 r2 h2 H0). - rewrite e1; simpl; destruct 1. - split. - apply bal_avl; auto. - simpl; omega_max. - omega_bal. -Qed. - -Lemma merge_avl : forall s1 s2, avl s1 -> avl s2 -> - -(2) <= height s1 - height s2 <= 2 -> avl (merge s1 s2). -Proof. - intros; generalize (merge_avl_1 s1 s2 H H0 H1); intuition. -Qed. +(** * Merging two trees *) -Lemma merge_in : forall s1 s2 y, bst s1 -> avl s1 -> bst s2 -> avl s2 -> - (In y (merge s1 s2) <-> In y s1 \/ In y s2). -Proof. - intros s1 s2; functional induction (merge s1 s2); subst; simpl in *; intros. +Lemma merge_in : forall s1 s2 y, + In y (merge s1 s2) <-> In y s1 \/ In y s2. +Proof. + intros s1 s2; functional induction (merge s1 s2); intros; + try factornode _x _x0 _x1 _x2 as s1. intuition_in. intuition_in. - destruct s1;try contradiction;clear y. - replace s2' with (fst (remove_min l2 x2 r2)); [|rewrite e1; auto]. - rewrite bal_in; auto. - generalize (remove_min_avl l2 x2 r2 h2); rewrite e1; simpl; auto. - generalize (remove_min_in l2 x2 r2 h2 y0); rewrite e1; simpl; intro. - rewrite H3 ; intuition. + rewrite bal_in, remove_min_in, e1; simpl; intuition. Qed. -Lemma merge_bst : forall s1 s2, bst s1 -> avl s1 -> bst s2 -> avl s2 -> +Lemma merge_bst : forall s1 s2, bst s1 -> bst s2 -> (forall y1 y2 : elt, In y1 s1 -> In y2 s2 -> X.lt y1 y2) -> - bst (merge s1 s2). + bst (merge s1 s2). Proof. - intros s1 s2; functional induction (merge s1 s2); subst;simpl in *; intros; auto. - destruct s1;try contradiction;clear y. + intros s1 s2; functional induction (merge s1 s2); intros; auto; + try factornode _x _x0 _x1 _x2 as s1. apply bal_bst; auto. - generalize (remove_min_bst l2 x2 r2 h2); rewrite e1; simpl in *; auto. - intro; intro. - apply H3; auto. - generalize (remove_min_in l2 x2 r2 h2 m); rewrite e1; simpl; intuition. - generalize (remove_min_gt_tree l2 x2 r2 h2); rewrite e1; simpl; auto. -Qed. + change s2' with ((s2',m)#1); rewrite <-e1; eauto. + intros y Hy. + apply H1; auto. + rewrite remove_min_in, e1; simpl; auto. + change (gt_tree (s2',m)#2 (s2',m)#1); rewrite <-e1; eauto. +Qed. +Hint Resolve merge_bst. -(** * Deletion *) -Function remove (x:elt)(s:tree) { struct s } : t := match s with - | Leaf => Leaf - | Node l y r h => - match X.compare x y with - | LT _ => bal (remove x l) y r - | EQ _ => merge l r - | GT _ => bal l y (remove x r) - end - end. -Lemma remove_avl_1 : forall s x, avl s -> - avl (remove x s) /\ 0 <= height s - height (remove x s) <= 1. -Proof. - intros s x; functional induction (remove x s); subst;simpl; intros. - intuition; omega_max. - (* LT *) - inv avl. - destruct (IHt H0). - split. - apply bal_avl; auto. - omega_max. - omega_bal. - (* EQ *) - inv avl. - generalize (merge_avl_1 l r H0 H1 H2). - intuition omega_max. - (* GT *) - inv avl. - destruct (IHt H1). - split. - apply bal_avl; auto. - omega_max. - omega_bal. -Qed. - -Lemma remove_avl : forall s x, avl s -> avl (remove x s). -Proof. - intros; generalize (remove_avl_1 s x H); intuition. -Qed. -Hint Resolve remove_avl. +(** * Deletion *) -Lemma remove_in : forall s x y, bst s -> avl s -> +Lemma remove_in : forall s x y, bst s -> (In y (remove x s) <-> ~ X.eq y x /\ In y s). Proof. - intros s x; functional induction (remove x s); subst;simpl; intros. + intros s x; functional induction (remove x s); intros; inv bst. intuition_in. - (* LT *) - inv avl; inv bst; clear e0. - rewrite bal_in; auto. - generalize (IHt y0 H0); intuition; [ order | order | intuition_in ]. - (* EQ *) - inv avl; inv bst; clear e0. - rewrite merge_in; intuition; [ order | order | intuition_in ]. - elim H9; eauto. - (* GT *) - inv avl; inv bst; clear e0. - rewrite bal_in; auto. - generalize (IHt y0 H5); intuition; [ order | order | intuition_in ]. + rewrite bal_in, IHt; clear e0 IHt; intuition; [order|order|intuition_in]. + rewrite merge_in; clear e0; intuition; [order|order|intuition_in]. + elim H4; eauto. + rewrite bal_in, IHt; clear e0 IHt; intuition; [order|order|intuition_in]. Qed. -Lemma remove_bst : forall s x, bst s -> avl s -> bst (remove x s). +Lemma remove_bst : forall s x, bst s -> bst (remove x s). Proof. - intros s x; functional induction (remove x s); simpl; intros. + intros s x; functional induction (remove x s); intros; inv bst. auto. (* LT *) - inv avl; inv bst. apply bal_bst; auto. - intro; intro. - rewrite (remove_in l x y0) in H; auto. - destruct H; eauto. + intro z; rewrite remove_in; auto; destruct 1; eauto. (* EQ *) - inv avl; inv bst. - apply merge_bst; eauto. + eauto. (* GT *) - inv avl; inv bst. apply bal_bst; auto. - intro; intro. - rewrite (remove_in r x y0) in H; auto. - destruct H; eauto. + intro z; rewrite remove_in; auto; destruct 1; eauto. Qed. +Hint Resolve remove_bst. - (** * Minimum element *) -Function min_elt (s:t) : option elt := match s with - | Leaf => None - | Node Leaf y _ _ => Some y - | Node l _ _ _ => min_elt l -end. +(** * Minimum element *) Lemma min_elt_1 : forall s x, min_elt s = Some x -> In x s. Proof. - intro s; functional induction (min_elt s); subst; simpl. - inversion 1. - inversion 1; auto. - intros. - destruct l; auto. + intro s; functional induction (min_elt s); auto; inversion 1; auto. Qed. -Lemma min_elt_2 : forall s x y, bst s -> +Lemma min_elt_2 : forall s x y, bst s -> min_elt s = Some x -> In y s -> ~ X.lt y x. Proof. - intro s; functional induction (min_elt s); subst;simpl. + intro s; functional induction (min_elt s); + try rename _x1 into l1, _x2 into x1, _x3 into r1, _x4 into h1. inversion_clear 2. inversion_clear 1. inversion 1; subst. inversion_clear 1; auto. inversion_clear H5. - destruct l;try contradiction. inversion_clear 1. simpl. destruct l1. inversion 1; subst. - assert (X.lt x _x) by (apply H2; auto). + assert (X.lt x y) by (apply H2; auto). inversion_clear 1; auto; order. - assert (X.lt t _x) by auto. + assert (X.lt x1 y) by auto. inversion_clear 2; auto; - (assert (~ X.lt t x) by auto); order. + (assert (~ X.lt x1 x) by auto); order. Qed. Lemma min_elt_3 : forall s, min_elt s = None -> Empty s. Proof. - intro s; functional induction (min_elt s); subst;simpl. - red; auto. + intro s; functional induction (min_elt s). + red; red; inversion 2. inversion 1. - destruct l;try contradiction. - clear y;intro H0. - destruct (IHo H0 t); auto. + intro H0. + destruct (IHo H0 _x2); auto. Qed. -(** * Maximum element *) -Function max_elt (s:t) : option elt := match s with - | Leaf => None - | Node _ y Leaf _ => Some y - | Node _ _ r _ => max_elt r -end. +(** * Maximum element *) Lemma max_elt_1 : forall s x, max_elt s = Some x -> In x s. Proof. - intro s; functional induction (max_elt s); subst;simpl. - inversion 1. - inversion 1; auto. - destruct r;try contradiction; auto. + intro s; functional induction (max_elt s); auto; inversion 1; auto. Qed. Lemma max_elt_2 : forall s x y, bst s -> max_elt s = Some x -> In y s -> ~ X.lt x y. Proof. - intro s; functional induction (max_elt s); subst;simpl. + intro s; functional induction (max_elt s); + try rename _x1 into l1, _x2 into x1, _x3 into r1, _x4 into h1. inversion_clear 2. inversion_clear 1. inversion 1; subst. inversion_clear 1; auto. inversion_clear H5. - destruct r;try contradiction. inversion_clear 1. -(* inversion 1; subst. *) -(* assert (X.lt y x) by (apply H4; auto). *) -(* inversion_clear 1; auto; order. *) - assert (X.lt _x0 t) by auto. + assert (X.lt y x1) by auto. inversion_clear 2; auto; - (assert (~ X.lt x t) by auto); order. + (assert (~ X.lt x x1) by auto); order. Qed. Lemma max_elt_3 : forall s, max_elt s = None -> Empty s. Proof. - intro s; functional induction (max_elt s); subst;simpl. + intro s; functional induction (max_elt s). red; auto. inversion 1. - destruct r;try contradiction. - intros H0; destruct (IHo H0 t); auto. + intros H0; destruct (IHo H0 _x2); auto. Qed. -(** * Any element *) -Definition choose := min_elt. + +(** * Any element *) Lemma choose_1 : forall s x, choose s = Some x -> In x s. Proof. @@ -1021,353 +1023,215 @@ Proof. exact min_elt_3. Qed. -(** * Concatenation +Lemma choose_3 : forall s s', bst s -> bst s' -> + forall x x', choose s = Some x -> choose s' = Some x' -> + Equal s s' -> X.eq x x'. +Proof. + unfold choose, Equal; intros s s' Hb Hb' x x' Hx Hx' H. + assert (~X.lt x x'). + apply min_elt_2 with s'; auto. + rewrite <-H; auto using min_elt_1. + assert (~X.lt x' x). + apply min_elt_2 with s; auto. + rewrite H; auto using min_elt_1. + destruct (X.compare x x'); intuition. +Qed. - Same as [merge] but does not assume anything about heights. -*) -Function concat (s1 s2 : t) : t := - match s1, s2 with - | Leaf, _ => s2 - | _, Leaf => s1 - | _, Node l2 x2 r2 h2 => - let (s2',m) := remove_min l2 x2 r2 in - join s1 m s2' - end. +(** * Concatenation *) -Lemma concat_avl : forall s1 s2, avl s1 -> avl s2 -> avl (concat s1 s2). +Lemma concat_in : forall s1 s2 y, + In y (concat s1 s2) <-> In y s1 \/ In y s2. Proof. - intros s1 s2; functional induction (concat s1 s2); subst;auto. - destruct s1;try contradiction;clear y. - intros; apply join_avl; auto. - generalize (remove_min_avl l2 x2 r2 h2 H0); rewrite e1; simpl; auto. + intros s1 s2; functional induction (concat s1 s2); intros; + try factornode _x _x0 _x1 _x2 as s1. + intuition_in. + intuition_in. + rewrite join_in, remove_min_in, e1; simpl; intuition. Qed. -Lemma concat_bst : forall s1 s2, bst s1 -> avl s1 -> bst s2 -> avl s2 -> +Lemma concat_bst : forall s1 s2, bst s1 -> bst s2 -> (forall y1 y2 : elt, In y1 s1 -> In y2 s2 -> X.lt y1 y2) -> bst (concat s1 s2). Proof. - intros s1 s2; functional induction (concat s1 s2); subst ;auto. - destruct s1;try contradiction;clear y. - intros; apply join_bst; auto. - generalize (remove_min_bst l2 x2 r2 h2 H1 H2); rewrite e1; simpl; auto. - generalize (remove_min_avl l2 x2 r2 h2 H2); rewrite e1; simpl; auto. - generalize (remove_min_in l2 x2 r2 h2 m H2); rewrite e1; simpl; auto. - destruct 1; intuition. - generalize (remove_min_gt_tree l2 x2 r2 h2 H1 H2); rewrite e1; simpl; auto. -Qed. - -Lemma concat_in : forall s1 s2 y, bst s1 -> avl s1 -> bst s2 -> avl s2 -> - (forall y1 y2 : elt, In y1 s1 -> In y2 s2 -> X.lt y1 y2) -> - (In y (concat s1 s2) <-> In y s1 \/ In y s2). -Proof. - intros s1 s2; functional induction (concat s1 s2);subst;simpl. - intuition. - inversion_clear H5. - destruct s1;try contradiction;clear y;intuition. - inversion_clear H5. - destruct s1;try contradiction;clear y; intros. - rewrite (join_in (Node s1_1 t s1_2 i) m s2' y H0). - generalize (remove_min_avl l2 x2 r2 h2 H2); rewrite e1; simpl; auto. - generalize (remove_min_in l2 x2 r2 h2 y H2); rewrite e1; simpl. - intro EQ; rewrite EQ; intuition. + intros s1 s2; functional induction (concat s1 s2); intros; auto; + try factornode _x _x0 _x1 _x2 as s1. + apply join_bst; auto. + change (bst (s2',m)#1); rewrite <-e1; eauto. + intros y Hy. + apply H1; auto. + rewrite remove_min_in, e1; simpl; auto. + change (gt_tree (s2',m)#2 (s2',m)#1); rewrite <-e1; eauto. Qed. +Hint Resolve concat_bst. -(** * Splitting - [split x s] returns a triple [(l, present, r)] where - - [l] is the set of elements of [s] that are [< x] - - [r] is the set of elements of [s] that are [> x] - - [present] is [true] if and only if [s] contains [x]. -*) +(** * Splitting *) -Function split (x:elt)(s:t) {struct s} : t * (bool * t) := match s with - | Leaf => (Leaf, (false, Leaf)) - | Node l y r h => - match X.compare x y with - | LT _ => match split x l with - | (ll,(pres,rl)) => (ll, (pres, join rl y r)) - end - | EQ _ => (l, (true, r)) - | GT _ => match split x r with - | (rl,(pres,rr)) => (join l y rl, (pres, rr)) - end - end - end. - -Lemma split_avl : forall s x, avl s -> - avl (fst (split x s)) /\ avl (snd (snd (split x s))). -Proof. - intros s x; functional induction (split x s);subst;simpl in *. - auto. - rewrite e1 in IHp;simpl in IHp;inversion_clear 1; intuition. - simpl; inversion_clear 1; auto. - rewrite e1 in IHp;simpl in IHp;inversion_clear 1; intuition. -Qed. - -Lemma split_in_1 : forall s x y, bst s -> avl s -> - (In y (fst (split x s)) <-> In y s /\ X.lt y x). -Proof. - intros s x; functional induction (split x s);subst;simpl in *. - intuition; try inversion_clear H1. - (* LT *) - rewrite e1 in IHp;simpl in *; inversion_clear 1; inversion_clear 1; clear H7 H6. - rewrite (IHp y0 H0 H4); clear IHp e0. - intuition. - inversion_clear H6; auto; order. - (* EQ *) - simpl in *; inversion_clear 1; inversion_clear 1; clear H6 H5 e0. - intuition. - order. +Lemma split_in_1 : forall s x y, bst s -> + (In y (split x s)#l <-> In y s /\ X.lt y x). +Proof. + intros s x; functional induction (split x s); simpl; intros; + inv bst; try clear e0. + intuition_in. + rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order. intuition_in; order. - (* GT *) - rewrite e1 in IHp;simpl in *; inversion_clear 1; inversion_clear 1; clear H7 H6. - rewrite join_in; auto. - generalize (split_avl r x H5); rewrite e1; simpl; intuition. - rewrite (IHp y0 H1 H5); clear e1. - intuition; [ eauto | eauto | intuition_in ]. + rewrite join_in. + rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order. Qed. -Lemma split_in_2 : forall s x y, bst s -> avl s -> - (In y (snd (snd (split x s))) <-> In y s /\ X.lt x y). +Lemma split_in_2 : forall s x y, bst s -> + (In y (split x s)#r <-> In y s /\ X.lt x y). Proof. - intros s x; functional induction (split x s);subst;simpl in *. - intuition; try inversion_clear H1. - (* LT *) - rewrite e1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1; clear H7 H6. - rewrite join_in; auto. - generalize (split_avl l x H4); rewrite e1; simpl; intuition. - rewrite (IHp y0 H0 H4); clear IHp e0. - intuition; [ order | order | intuition_in ]. - (* EQ *) - simpl in *; inversion_clear 1; inversion_clear 1; clear H6 H5 e0. - intuition; [ order | intuition_in; order ]. - (* GT *) - rewrite e1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1; clear H7 H6. - rewrite (IHp y0 H1 H5); clear IHp e0. - intuition; intuition_in; order. + intros s x; functional induction (split x s); subst; simpl; intros; + inv bst; try clear e0. + intuition_in. + rewrite join_in. + rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order. + intuition_in; order. + rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order. Qed. -Lemma split_in_3 : forall s x, bst s -> avl s -> - (fst (snd (split x s)) = true <-> In x s). +Lemma split_in_3 : forall s x, bst s -> + ((split x s)#b = true <-> In x s). Proof. - intros s x; functional induction (split x s);subst;simpl in *. - intuition; try inversion_clear H1. - (* LT *) - rewrite e1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1; clear H7 H6. - rewrite IHp; auto. - intuition_in; absurd (X.lt x y); eauto. - (* EQ *) - simpl in *; inversion_clear 1; inversion_clear 1; intuition. - (* GT *) - rewrite e1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1; clear H7 H6. - rewrite IHp; auto. - intuition_in; absurd (X.lt y x); eauto. + intros s x; functional induction (split x s); subst; simpl; intros; + inv bst; try clear e0. + intuition_in; try discriminate. + rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order. + intuition. + rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order. Qed. -Lemma split_bst : forall s x, bst s -> avl s -> - bst (fst (split x s)) /\ bst (snd (snd (split x s))). +Lemma split_bst : forall s x, bst s -> + bst (split x s)#l /\ bst (split x s)#r. Proof. - intros s x; functional induction (split x s);subst;simpl in *. - intuition. - (* LT *) - rewrite e1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1. - intuition. - apply join_bst; auto. - generalize (split_avl l x H4); rewrite e1; simpl; intuition. - intro; intro. - generalize (split_in_2 l x y0 H0 H4); rewrite e1; simpl; intuition. - (* EQ *) - simpl in *; inversion_clear 1; inversion_clear 1; intuition. - (* GT *) - rewrite e1 in IHp; simpl in *; inversion_clear 1; inversion_clear 1. - intuition. - apply join_bst; auto. - generalize (split_avl r x H5); rewrite e1; simpl; intuition. - intro; intro. - generalize (split_in_1 r x y0 H1 H5); rewrite e1; simpl; intuition. + intros s x; functional induction (split x s); subst; simpl; intros; + inv bst; try clear e0; try rewrite e1 in *; simpl in *; intuition; + apply join_bst; auto. + intros y0. + generalize (split_in_2 x y0 H0); rewrite e1; simpl; intuition. + intros y0. + generalize (split_in_1 x y0 H1); rewrite e1; simpl; intuition. Qed. -(** * Intersection *) -Fixpoint inter (s1 s2 : t) {struct s1} : t := match s1, s2 with - | Leaf,_ => Leaf - | _,Leaf => Leaf - | Node l1 x1 r1 h1, _ => - match split x1 s2 with - | (l2',(true,r2')) => join (inter l1 l2') x1 (inter r1 r2') - | (l2',(false,r2')) => concat (inter l1 l2') (inter r1 r2') - end - end. -Lemma inter_avl : forall s1 s2, avl s1 -> avl s2 -> avl (inter s1 s2). -Proof. - (* intros s1 s2; functional induction inter s1 s2; auto. BOF BOF *) - induction s1 as [ | l1 Hl1 x1 r1 Hr1 h1]; simpl; auto. - destruct s2 as [ | l2 x2 r2 h2]; intros; auto. - generalize H0; inv avl. - set (r:=Node l2 x2 r2 h2) in *; clearbody r; intros. - destruct (split_avl r x1 H8). - destruct (split x1 r) as [l2' (b,r2')]; simpl in *. - destruct b; [ apply join_avl | apply concat_avl ]; auto. -Qed. +(** * Intersection *) -Lemma inter_bst_in : forall s1 s2, bst s1 -> avl s1 -> bst s2 -> avl s2 -> +Lemma inter_bst_in : forall s1 s2, bst s1 -> bst s2 -> bst (inter s1 s2) /\ (forall y, In y (inter s1 s2) <-> In y s1 /\ In y s2). -Proof. - induction s1 as [ | l1 Hl1 x1 r1 Hr1 h1]; simpl; auto. - intuition; inversion_clear H3. - destruct s2 as [ | l2 x2 r2 h2]; intros. - simpl; intuition; inversion_clear H3. - generalize H1 H2; inv avl; inv bst. - set (r:=Node l2 x2 r2 h2) in *; clearbody r; intros. - destruct (split_avl r x1 H17). - destruct (split_bst r x1 H16 H17). - split. - (* bst *) - destruct (split x1 r) as [l2' (b,r2')]; simpl in *. - destruct (Hl1 l2'); auto. - destruct (Hr1 r2'); auto. - destruct b. +Proof. + intros s1 s2; functional induction inter s1 s2; intros B1 B2; + [intuition_in|intuition_in | | ]; + factornode _x0 _x1 _x2 _x3 as s2; + generalize (split_bst x1 B2); + rewrite e1; simpl; destruct 1; inv bst; + destruct IHt as (IHb1,IHi1); auto; + destruct IHt0 as (IHb2,IHi2); auto; + generalize (@split_in_1 s2 x1)(@split_in_2 s2 x1) + (split_in_3 x1 B2)(split_bst x1 B2); + rewrite e1; simpl; split; intros. (* bst join *) - apply join_bst; try apply inter_avl; firstorder. - (* bst concat *) - apply concat_bst; try apply inter_avl; auto. - intros; generalize (H22 y1) (H24 y2); intuition eauto. - (* in *) - intros. - destruct (split_in_1 r x1 y H16 H17). - destruct (split_in_2 r x1 y H16 H17). - destruct (split_in_3 r x1 H16 H17). - destruct (split x1 r) as [l2' (b,r2')]; simpl in *. - destruct (Hl1 l2'); auto. - destruct (Hr1 r2'); auto. - destruct b. - (* in join *) - rewrite join_in; try apply inter_avl; auto. - rewrite H30. - rewrite H28. - intuition_in. + apply join_bst; auto; intro y; [rewrite IHi1|rewrite IHi2]; intuition. (* In join *) + rewrite join_in, IHi1, IHi2, H5, H6; intuition_in. apply In_1 with x1; auto. - (* in concat *) - rewrite concat_in; try apply inter_avl; auto. - intros. - intros; generalize (H28 y1) (H30 y2); intuition eauto. - rewrite H30. - rewrite H28. + (* bst concat *) + apply concat_bst; auto; intros y1 y2; rewrite IHi1, IHi2; intuition; order. + (* In concat *) + rewrite concat_in, IHi1, IHi2, H5, H6; auto. + assert (~In x1 s2) by (rewrite <- H7; auto). intuition_in. - generalize (H26 (In_1 _ _ _ H22 H35)); intro; discriminate. + elim H9. + apply In_1 with y; auto. Qed. -Lemma inter_bst : forall s1 s2, bst s1 -> avl s1 -> bst s2 -> avl s2 -> - bst (inter s1 s2). +Lemma inter_in : forall s1 s2 y, bst s1 -> bst s2 -> + (In y (inter s1 s2) <-> In y s1 /\ In y s2). Proof. - intros; generalize (inter_bst_in s1 s2); intuition. + intros s1 s2 y B1 B2; destruct (inter_bst_in B1 B2); auto. Qed. -Lemma inter_in : forall s1 s2 y, bst s1 -> avl s1 -> bst s2 -> avl s2 -> - (In y (inter s1 s2) <-> In y s1 /\ In y s2). +Lemma inter_bst : forall s1 s2, bst s1 -> bst s2 -> bst (inter s1 s2). Proof. - intros; generalize (inter_bst_in s1 s2); firstorder. + intros s1 s2 B1 B2; destruct (inter_bst_in B1 B2); auto. Qed. -(** * Difference *) - -Fixpoint diff (s1 s2 : t) { struct s1 } : t := match s1, s2 with - | Leaf, _ => Leaf - | _, Leaf => s1 - | Node l1 x1 r1 h1, _ => - match split x1 s2 with - | (l2',(true,r2')) => concat (diff l1 l2') (diff r1 r2') - | (l2',(false,r2')) => join (diff l1 l2') x1 (diff r1 r2') - end -end. -Lemma diff_avl : forall s1 s2, avl s1 -> avl s2 -> avl (diff s1 s2). -Proof. - (* intros s1 s2; functional induction diff s1 s2; auto. BOF BOF *) - induction s1 as [ | l1 Hl1 x1 r1 Hr1 h1]; simpl; auto. - destruct s2 as [ | l2 x2 r2 h2]; intros; auto. - generalize H0; inv avl. - set (r:=Node l2 x2 r2 h2) in *; clearbody r; intros. - destruct (split_avl r x1 H8). - destruct (split x1 r) as [l2' (b,r2')]; simpl in *. - destruct b; [ apply concat_avl | apply join_avl ]; auto. -Qed. +(** * Difference *) -Lemma diff_bst_in : forall s1 s2, bst s1 -> avl s1 -> bst s2 -> avl s2 -> +Lemma diff_bst_in : forall s1 s2, bst s1 -> bst s2 -> bst (diff s1 s2) /\ (forall y, In y (diff s1 s2) <-> In y s1 /\ ~In y s2). -Proof. - induction s1 as [ | l1 Hl1 x1 r1 Hr1 h1]; simpl; auto. - intuition; inversion_clear H3. - destruct s2 as [ | l2 x2 r2 h2]; intros; auto. - intuition; inversion_clear H4. - generalize H1 H2; inv avl; inv bst. - set (r:=Node l2 x2 r2 h2) in *; clearbody r; intros. - destruct (split_avl r x1 H17). - destruct (split_bst r x1 H16 H17). - split. - (* bst *) - destruct (split x1 r) as [l2' (b,r2')]; simpl in *. - destruct (Hl1 l2'); auto. - destruct (Hr1 r2'); auto. - destruct b. +Proof. + intros s1 s2; functional induction diff s1 s2; intros B1 B2; + [intuition_in|intuition_in | | ]; + factornode _x0 _x1 _x2 _x3 as s2; + generalize (split_bst x1 B2); + rewrite e1; simpl; destruct 1; + inv avl; inv bst; + destruct IHt as (IHb1,IHi1); auto; + destruct IHt0 as (IHb2,IHi2); auto; + generalize (@split_in_1 s2 x1)(@split_in_2 s2 x1) + (split_in_3 x1 B2)(split_bst x1 B2); + rewrite e1; simpl; split; intros. (* bst concat *) - apply concat_bst; try apply diff_avl; auto. - intros; generalize (H22 y1) (H24 y2); intuition eauto. + apply concat_bst; auto; intros y1 y2; rewrite IHi1, IHi2; intuition; order. + (* In concat *) + rewrite concat_in, IHi1, IHi2, H5, H6; intuition_in. + elim H13. + apply In_1 with x1; auto. (* bst join *) - apply join_bst; try apply diff_avl; firstorder. - (* in *) - intros. - destruct (split_in_1 r x1 y H16 H17). - destruct (split_in_2 r x1 y H16 H17). - destruct (split_in_3 r x1 H16 H17). - destruct (split x1 r) as [l2' (b,r2')]; simpl in *. - destruct (Hl1 l2'); auto. - destruct (Hr1 r2'); auto. - destruct b. - (* in concat *) - rewrite concat_in; try apply diff_avl; auto. - intros. - intros; generalize (H28 y1) (H30 y2); intuition eauto. - rewrite H30. - rewrite H28. + apply join_bst; auto; intro y; [rewrite IHi1|rewrite IHi2]; intuition. (* In join *) + rewrite join_in, IHi1, IHi2, H5, H6; auto. + assert (~In x1 s2) by (rewrite <- H7; auto). intuition_in. - elim H35; apply In_1 with x1; auto. - (* in join *) - rewrite join_in; try apply diff_avl; auto. - rewrite H30. - rewrite H28. - intuition_in. - generalize (H26 (In_1 _ _ _ H34 H24)); intro; discriminate. + elim H9. + apply In_1 with y; auto. Qed. -Lemma diff_bst : forall s1 s2, bst s1 -> avl s1 -> bst s2 -> avl s2 -> - bst (diff s1 s2). +Lemma diff_in : forall s1 s2 y, bst s1 -> bst s2 -> + (In y (diff s1 s2) <-> In y s1 /\ ~In y s2). Proof. - intros; generalize (diff_bst_in s1 s2); intuition. + intros s1 s2 y B1 B2; destruct (diff_bst_in B1 B2); auto. Qed. -Lemma diff_in : forall s1 s2 y, bst s1 -> avl s1 -> bst s2 -> avl s2 -> - (In y (diff s1 s2) <-> In y s1 /\ ~In y s2). +Lemma diff_bst : forall s1 s2, bst s1 -> bst s2 -> bst (diff s1 s2). Proof. - intros; generalize (diff_bst_in s1 s2); firstorder. + intros s1 s2 B1 B2; destruct (diff_bst_in B1 B2); auto. Qed. -(** * Elements *) -(** [elements_tree_aux acc t] catenates the elements of [t] in infix - order to the list [acc] *) +(** * Union *) -Fixpoint elements_aux (acc : list X.t) (t : tree) {struct t} : list X.t := - match t with - | Leaf => acc - | Node l x r _ => elements_aux (x :: elements_aux acc r) l - end. +Lemma union_in : forall s1 s2 y, bst s1 -> bst s2 -> + (In y (union s1 s2) <-> In y s1 \/ In y s2). +Proof. + intros s1 s2; functional induction union s1 s2; intros y B1 B2. + intuition_in. + intuition_in. + factornode _x0 _x1 _x2 _x3 as s2. + generalize (split_in_1 x1 y B2)(split_in_2 x1 y B2)(split_bst x1 B2). + rewrite e1; simpl. + destruct 3; inv bst. + rewrite join_in, IHt, IHt0, H, H0; auto. + case (X.compare y x1); intuition_in. +Qed. -(** then [elements] is an instanciation with an empty [acc] *) +Lemma union_bst : forall s1 s2, bst s1 -> bst s2 -> + bst (union s1 s2). +Proof. + intros s1 s2; functional induction union s1 s2; intros B1 B2; auto. + factornode _x0 _x1 _x2 _x3 as s2. + generalize (@split_in_1 s2 x1)(@split_in_2 s2 x1)(split_bst x1 B2). + rewrite e1; simpl; destruct 3. + inv bst. + apply join_bst; auto. + intro y; rewrite union_in, H; intuition_in. + intro y; rewrite union_in, H0; intuition_in. +Qed. -Definition elements := elements_aux nil. + +(** * Elements *) Lemma elements_aux_in : forall s acc x, InA X.eq x (elements_aux acc s) <-> In x s \/ InA X.eq x acc. @@ -1411,246 +1275,190 @@ Proof. Qed. Hint Resolve elements_sort. -(** * Filter *) - -Section F. -Variable f : elt -> bool. +Lemma elements_nodup : forall s : tree, bst s -> NoDupA X.eq (elements s). +Proof. + auto. +Qed. -Fixpoint filter_acc (acc:t)(s:t) { struct s } : t := match s with - | Leaf => acc - | Node l x r h => - filter_acc (filter_acc (if f x then add x acc else acc) l) r - end. +Lemma elements_aux_cardinal : + forall s acc, (length acc + cardinal s)%nat = length (elements_aux acc s). +Proof. + simple induction s; simpl in |- *; intuition. + rewrite <- H. + simpl in |- *. + rewrite <- H0; omega. +Qed. -Definition filter := filter_acc Leaf. +Lemma elements_cardinal : forall s : tree, cardinal s = length (elements s). +Proof. + exact (fun s => elements_aux_cardinal s nil). +Qed. -Lemma filter_acc_avl : forall s acc, avl s -> avl acc -> - avl (filter_acc acc s). +Lemma elements_app : + forall s acc, elements_aux acc s = elements s ++ acc. Proof. - induction s; simpl; auto. - intros. - inv avl. - apply IHs2; auto. - apply IHs1; auto. - destruct (f t); auto. -Qed. -Hint Resolve filter_acc_avl. + induction s; simpl; intros; auto. + rewrite IHs1, IHs2. + unfold elements; simpl. + rewrite 2 IHs1, IHs2, <- !app_nil_end, !app_ass; auto. +Qed. -Lemma filter_acc_bst : forall s acc, bst s -> avl s -> bst acc -> avl acc -> - bst (filter_acc acc s). +Lemma elements_node : + forall l x r h acc, + elements l ++ x :: elements r ++ acc = + elements (Node l x r h) ++ acc. Proof. - induction s; simpl; auto. - intros. - inv avl; inv bst. - destruct (f t); auto. - apply IHs2; auto. - apply IHs1; auto. - apply add_bst; auto. -Qed. + unfold elements; simpl; intros; auto. + rewrite !elements_app, <- !app_nil_end, !app_ass; auto. +Qed. + -Lemma filter_acc_in : forall s acc, avl s -> avl acc -> +(** * Filter *) + +Section F. +Variable f : elt -> bool. + +Lemma filter_acc_in : forall s acc, compat_bool X.eq f -> forall x : elt, - In x (filter_acc acc s) <-> In x acc \/ In x s /\ f x = true. + In x (filter_acc f acc s) <-> In x acc \/ In x s /\ f x = true. Proof. induction s; simpl; intros. intuition_in. - inv bst; inv avl. - rewrite IHs2; auto. - destruct (f t); auto. - rewrite IHs1; auto. - destruct (f t); auto. + rewrite IHs2, IHs1 by (destruct (f t); auto). case_eq (f t); intros. rewrite (add_in); auto. intuition_in. - rewrite (H1 _ _ H8). + rewrite (H _ _ H2). intuition. intuition_in. - rewrite (H1 _ _ H8) in H9. - rewrite H in H9; discriminate. -Qed. - -Lemma filter_avl : forall s, avl s -> avl (filter s). -Proof. - unfold filter; intros; apply filter_acc_avl; auto. + rewrite (H _ _ H2) in H3. + rewrite H0 in H3; discriminate. Qed. -Lemma filter_bst : forall s, bst s -> avl s -> bst (filter s). +Lemma filter_acc_bst : forall s acc, bst s -> bst acc -> + bst (filter_acc f acc s). Proof. - unfold filter; intros; apply filter_acc_bst; auto. + induction s; simpl; auto. + intros. + inv bst. + destruct (f t); auto. Qed. -Lemma filter_in : forall s, avl s -> +Lemma filter_in : forall s, compat_bool X.eq f -> forall x : elt, - In x (filter s) <-> In x s /\ f x = true. + In x (filter f s) <-> In x s /\ f x = true. Proof. unfold filter; intros; rewrite filter_acc_in; intuition_in. -Qed. - -(** * Partition *) - -Fixpoint partition_acc (acc : t*t)(s : t) { struct s } : t*t := - match s with - | Leaf => acc - | Node l x r _ => - let (acct,accf) := acc in - partition_acc - (partition_acc - (if f x then (add x acct, accf) else (acct, add x accf)) l) r - end. - -Definition partition := partition_acc (Leaf,Leaf). +Qed. -Lemma partition_acc_avl_1 : forall s acc, avl s -> - avl (fst acc) -> avl (fst (partition_acc acc s)). +Lemma filter_bst : forall s, bst s -> bst (filter f s). Proof. - induction s; simpl; auto. - destruct acc as [acct accf]; simpl in *. - intros. - inv avl. - apply IHs2; auto. - apply IHs1; auto. - destruct (f t); simpl; auto. -Qed. + unfold filter; intros; apply filter_acc_bst; auto. +Qed. -Lemma partition_acc_avl_2 : forall s acc, avl s -> - avl (snd acc) -> avl (snd (partition_acc acc s)). -Proof. - induction s; simpl; auto. - destruct acc as [acct accf]; simpl in *. - intros. - inv avl. - apply IHs2; auto. - apply IHs1; auto. - destruct (f t); simpl; auto. -Qed. -Hint Resolve partition_acc_avl_1 partition_acc_avl_2. -Lemma partition_acc_bst_1 : forall s acc, bst s -> avl s -> - bst (fst acc) -> avl (fst acc) -> - bst (fst (partition_acc acc s)). -Proof. - induction s; simpl; auto. - destruct acc as [acct accf]; simpl in *. - intros. - inv avl; inv bst. - destruct (f t); auto. - apply IHs2; simpl; auto. - apply IHs1; simpl; auto. - apply add_bst; auto. - apply partition_acc_avl_1; simpl; auto. -Qed. -Lemma partition_acc_bst_2 : forall s acc, bst s -> avl s -> - bst (snd acc) -> avl (snd acc) -> - bst (snd (partition_acc acc s)). -Proof. - induction s; simpl; auto. - destruct acc as [acct accf]; simpl in *. - intros. - inv avl; inv bst. - destruct (f t); auto. - apply IHs2; simpl; auto. - apply IHs1; simpl; auto. - apply add_bst; auto. - apply partition_acc_avl_2; simpl; auto. -Qed. +(** * Partition *) -Lemma partition_acc_in_1 : forall s acc, avl s -> avl (fst acc) -> +Lemma partition_acc_in_1 : forall s acc, compat_bool X.eq f -> forall x : elt, - In x (fst (partition_acc acc s)) <-> - In x (fst acc) \/ In x s /\ f x = true. + In x (partition_acc f acc s)#1 <-> + In x acc#1 \/ In x s /\ f x = true. Proof. induction s; simpl; intros. intuition_in. destruct acc as [acct accf]; simpl in *. - inv bst; inv avl. - rewrite IHs2; auto. - destruct (f t); auto. - apply partition_acc_avl_1; simpl; auto. - rewrite IHs1; auto. - destruct (f t); simpl; auto. + rewrite IHs2 by + (destruct (f t); auto; apply partition_acc_avl_1; simpl; auto). + rewrite IHs1 by (destruct (f t); simpl; auto). case_eq (f t); simpl; intros. rewrite (add_in); auto. intuition_in. - rewrite (H1 _ _ H8). + rewrite (H _ _ H2). intuition. intuition_in. - rewrite (H1 _ _ H8) in H9. - rewrite H in H9; discriminate. -Qed. + rewrite (H _ _ H2) in H3. + rewrite H0 in H3; discriminate. +Qed. -Lemma partition_acc_in_2 : forall s acc, avl s -> avl (snd acc) -> +Lemma partition_acc_in_2 : forall s acc, compat_bool X.eq f -> forall x : elt, - In x (snd (partition_acc acc s)) <-> - In x (snd acc) \/ In x s /\ f x = false. + In x (partition_acc f acc s)#2 <-> + In x acc#2 \/ In x s /\ f x = false. Proof. induction s; simpl; intros. intuition_in. destruct acc as [acct accf]; simpl in *. - inv bst; inv avl. - rewrite IHs2; auto. - destruct (f t); auto. - apply partition_acc_avl_2; simpl; auto. - rewrite IHs1; auto. - destruct (f t); simpl; auto. + rewrite IHs2 by + (destruct (f t); auto; apply partition_acc_avl_2; simpl; auto). + rewrite IHs1 by (destruct (f t); simpl; auto). case_eq (f t); simpl; intros. intuition. intuition_in. - rewrite (H1 _ _ H8) in H9. - rewrite H in H9; discriminate. + rewrite (H _ _ H2) in H3. + rewrite H0 in H3; discriminate. rewrite (add_in); auto. intuition_in. - rewrite (H1 _ _ H8). + rewrite (H _ _ H2). intuition. +Qed. + +Lemma partition_in_1 : forall s, + compat_bool X.eq f -> forall x : elt, + In x (partition f s)#1 <-> In x s /\ f x = true. +Proof. + unfold partition; intros; rewrite partition_acc_in_1; + simpl in *; intuition_in. Qed. -Lemma partition_avl_1 : forall s, avl s -> avl (fst (partition s)). +Lemma partition_in_2 : forall s, + compat_bool X.eq f -> forall x : elt, + In x (partition f s)#2 <-> In x s /\ f x = false. Proof. - unfold partition; intros; apply partition_acc_avl_1; auto. + unfold partition; intros; rewrite partition_acc_in_2; + simpl in *; intuition_in. +Qed. + +Lemma partition_acc_bst_1 : forall s acc, bst s -> bst acc#1 -> + bst (partition_acc f acc s)#1. +Proof. + induction s; simpl; auto. + destruct acc as [acct accf]; simpl in *. + intros. + inv bst. + destruct (f t); auto. + apply IHs2; simpl; auto. + apply IHs1; simpl; auto. Qed. -Lemma partition_avl_2 : forall s, avl s -> avl (snd (partition s)). +Lemma partition_acc_bst_2 : forall s acc, bst s -> bst acc#2 -> + bst (partition_acc f acc s)#2. Proof. - unfold partition; intros; apply partition_acc_avl_2; auto. + induction s; simpl; auto. + destruct acc as [acct accf]; simpl in *. + intros. + inv bst. + destruct (f t); auto. + apply IHs2; simpl; auto. + apply IHs1; simpl; auto. Qed. -Lemma partition_bst_1 : forall s, bst s -> avl s -> - bst (fst (partition s)). +Lemma partition_bst_1 : forall s, bst s -> bst (partition f s)#1. Proof. unfold partition; intros; apply partition_acc_bst_1; auto. Qed. -Lemma partition_bst_2 : forall s, bst s -> avl s -> - bst (snd (partition s)). +Lemma partition_bst_2 : forall s, bst s -> bst (partition f s)#2. Proof. unfold partition; intros; apply partition_acc_bst_2; auto. Qed. -Lemma partition_in_1 : forall s, avl s -> - compat_bool X.eq f -> forall x : elt, - In x (fst (partition s)) <-> In x s /\ f x = true. -Proof. - unfold partition; intros; rewrite partition_acc_in_1; - simpl in *; intuition_in. -Qed. - -Lemma partition_in_2 : forall s, avl s -> - compat_bool X.eq f -> forall x : elt, - In x (snd (partition s)) <-> In x s /\ f x = false. -Proof. - unfold partition; intros; rewrite partition_acc_in_2; - simpl in *; intuition_in. -Qed. -(** [for_all] and [exists] *) -Fixpoint for_all (s:t) : bool := match s with - | Leaf => true - | Node l x r _ => f x && for_all l && for_all r -end. +(** * [for_all] and [exists] *) -Lemma for_all_1 : forall s, compat_bool E.eq f -> - For_all (fun x => f x = true) s -> for_all s = true. +Lemma for_all_1 : forall s, compat_bool X.eq f -> + For_all (fun x => f x = true) s -> for_all f s = true. Proof. induction s; simpl; auto. intros. @@ -1660,8 +1468,8 @@ Proof. destruct (f t); simpl; auto. Qed. -Lemma for_all_2 : forall s, compat_bool E.eq f -> - for_all s = true -> For_all (fun x => f x = true) s. +Lemma for_all_2 : forall s, compat_bool X.eq f -> + for_all f s = true -> For_all (fun x => f x = true) s. Proof. induction s; simpl; auto; intros; red; intros; inv In. destruct (andb_prop _ _ H0); auto. @@ -1673,52 +1481,40 @@ Proof. destruct (andb_prop _ _ H0); auto. Qed. -Fixpoint exists_ (s:t) : bool := match s with - | Leaf => false - | Node l x r _ => f x || exists_ l || exists_ r -end. - -Lemma exists_1 : forall s, compat_bool E.eq f -> - Exists (fun x => f x = true) s -> exists_ s = true. +Lemma exists_1 : forall s, compat_bool X.eq f -> + Exists (fun x => f x = true) s -> exists_ f s = true. Proof. - induction s; simpl; destruct 2 as (x,(U,V)); inv In. + induction s; simpl; destruct 2 as (x,(U,V)); inv In; rewrite <- ?orb_lazy_alt. rewrite (H _ _ (X.eq_sym H0)); rewrite V; auto. apply orb_true_intro; left. - apply orb_true_intro; right; apply IHs1; firstorder. - apply orb_true_intro; right; apply IHs2; firstorder. + apply orb_true_intro; right; apply IHs1; auto; exists x; auto. + apply orb_true_intro; right; apply IHs2; auto; exists x; auto. Qed. -Lemma exists_2 : forall s, compat_bool E.eq f -> - exists_ s = true -> Exists (fun x => f x = true) s. +Lemma exists_2 : forall s, compat_bool X.eq f -> + exists_ f s = true -> Exists (fun x => f x = true) s. Proof. - induction s; simpl; intros. + induction s; simpl; intros; rewrite <- ?orb_lazy_alt in *. discriminate. destruct (orb_true_elim _ _ H0) as [H1|H1]. destruct (orb_true_elim _ _ H1) as [H2|H2]. exists t; auto. - destruct (IHs1 H H2); firstorder. - destruct (IHs2 H H1); firstorder. -Qed. + destruct (IHs1 H H2); auto; exists x; intuition. + destruct (IHs2 H H1); auto; exists x; intuition. +Qed. End F. -(** * Fold *) -Module L := FSetList.Raw X. -Fixpoint fold (A : Set) (f : elt -> A -> A)(s : tree) {struct s} : A -> A := - fun a => match s with - | Leaf => a - | Node l x r _ => fold A f r (f x (fold A f l a)) - end. -Implicit Arguments fold [A]. +(** * Fold *) -Definition fold' (A : Set) (f : elt -> A -> A)(s : tree) := +Definition fold' (A : Type) (f : elt -> A -> A)(s : tree) := L.fold f (elements s). Implicit Arguments fold' [A]. Lemma fold_equiv_aux : - forall (A : Set) (s : tree) (f : elt -> A -> A) (a : A) (acc : list elt), + forall (A : Type) (s : tree) (f : elt -> A -> A) (a : A) (acc : list elt), L.fold f (elements_aux acc s) a = L.fold f acc (fold f s a). Proof. simple induction s. @@ -1730,7 +1526,7 @@ Proof. Qed. Lemma fold_equiv : - forall (A : Set) (s : tree) (f : elt -> A -> A) (a : A), + forall (A : Type) (s : tree) (f : elt -> A -> A) (a : A), fold f s a = fold' f s a. Proof. unfold fold', elements in |- *. @@ -1741,7 +1537,7 @@ Proof. Qed. Lemma fold_1 : - forall (s:t)(Hs:bst s)(A : Set)(f : elt -> A -> A)(i : A), + forall (s:t)(Hs:bst s)(A : Type)(f : elt -> A -> A)(i : A), fold f s i = fold_left (fun a e => f e a) (elements s) i. Proof. intros. @@ -1752,416 +1548,168 @@ Proof. apply elements_sort; auto. Qed. -(** * Cardinal *) - -Fixpoint cardinal (s : tree) : nat := - match s with - | Leaf => 0%nat - | Node l _ r _ => S (cardinal l + cardinal r) - end. +(** * Subset *) -Lemma cardinal_elements_aux_1 : - forall s acc, (length acc + cardinal s)%nat = length (elements_aux acc s). +Lemma subsetl_12 : forall subset_l1 l1 x1 h1 s2, + bst (Node l1 x1 Leaf h1) -> bst s2 -> + (forall s, bst s -> (subset_l1 s = true <-> Subset l1 s)) -> + (subsetl subset_l1 x1 s2 = true <-> Subset (Node l1 x1 Leaf h1) s2 ). Proof. - simple induction s; simpl in |- *; intuition. - rewrite <- H. - simpl in |- *. - rewrite <- H0; omega. -Qed. + induction s2 as [|l2 IHl2 x2 r2 IHr2 h2]; simpl; intros. + unfold Subset; intuition; try discriminate. + assert (H': In x1 Leaf) by auto; inversion H'. + inversion_clear H0. + specialize (IHl2 H H2 H1). + specialize (IHr2 H H3 H1). + inv bst. clear H8. + destruct X.compare. + + rewrite IHl2; clear H1 IHl2 IHr2. + unfold Subset. intuition_in. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. -Lemma cardinal_elements_1 : forall s : tree, cardinal s = length (elements s). -Proof. - exact (fun s => cardinal_elements_aux_1 s nil). -Qed. + rewrite H1 by auto; clear H1 IHl2 IHr2. + unfold Subset. intuition_in. + assert (X.eq a x2) by order; intuition_in. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. -(** NB: the remaining functions (union, subset, compare) are still defined - in a dependent style, due to the use of well-founded induction. *) + rewrite <-andb_lazy_alt, andb_true_iff, H1 by auto; clear H1 IHl2 IHr2. + unfold Subset. intuition_in. + assert (H':=mem_2 H6); apply In_1 with x1; auto. + apply mem_1; auto. + assert (In x1 (Node l2 x2 r2 h2)) by auto; intuition_in; order. +Qed. -(** Induction over cardinals *) -Lemma sorted_subset_cardinal : forall l' l : list X.t, - sort X.lt l -> sort X.lt l' -> - (forall x : elt, InA X.eq x l -> InA X.eq x l') -> (length l <= length l')%nat. +Lemma subsetr_12 : forall subset_r1 r1 x1 h1 s2, + bst (Node Leaf x1 r1 h1) -> bst s2 -> + (forall s, bst s -> (subset_r1 s = true <-> Subset r1 s)) -> + (subsetr subset_r1 x1 s2 = true <-> Subset (Node Leaf x1 r1 h1) s2). Proof. - simple induction l'; simpl in |- *; intuition. - destruct l; trivial; intros. - absurd (InA X.eq t nil); intuition. - inversion_clear H2. - inversion_clear H1. - destruct l0; simpl in |- *; intuition. + induction s2 as [|l2 IHl2 x2 r2 IHr2 h2]; simpl; intros. + unfold Subset; intuition; try discriminate. + assert (H': In x1 Leaf) by auto; inversion H'. inversion_clear H0. - apply le_n_S. - case (X.compare t a); intro. - absurd (InA X.eq t (a :: l)). - intro. - inversion_clear H0. - order. - assert (X.lt a t). - apply MX.Sort_Inf_In with l; auto. - order. - firstorder. - apply H; auto. - intros. - assert (InA X.eq x (a :: l)). - apply H2; auto. - inversion_clear H6; auto. - assert (X.lt t x). - apply MX.Sort_Inf_In with l0; auto. - order. - apply le_trans with (length (t :: l0)). - simpl in |- *; omega. - apply (H (t :: l0)); auto. - intros. - assert (InA X.eq x (a :: l)); firstorder. - inversion_clear H6; auto. - assert (X.lt a x). - apply MX.Sort_Inf_In with (t :: l0); auto. - elim (X.lt_not_eq (x:=a) (y:=x)); auto. -Qed. - -Lemma cardinal_subset : forall a b : tree, bst a -> bst b -> - (forall y : elt, In y a -> In y b) -> - (cardinal a <= cardinal b)%nat. -Proof. - intros. - do 2 rewrite cardinal_elements_1. - apply sorted_subset_cardinal; auto. - intros. - generalize (elements_in a x) (elements_in b x). - intuition. + specialize (IHl2 H H2 H1). + specialize (IHr2 H H3 H1). + inv bst. clear H7. + destruct X.compare. + + rewrite <-andb_lazy_alt, andb_true_iff, H1 by auto; clear H1 IHl2 IHr2. + unfold Subset. intuition_in. + assert (H':=mem_2 H1); apply In_1 with x1; auto. + apply mem_1; auto. + assert (In x1 (Node l2 x2 r2 h2)) by auto; intuition_in; order. + + rewrite H1 by auto; clear H1 IHl2 IHr2. + unfold Subset. intuition_in. + assert (X.eq a x2) by order; intuition_in. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. + + rewrite IHr2; clear H1 IHl2 IHr2. + unfold Subset. intuition_in. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. Qed. -Lemma cardinal_left : forall (l r : tree) (x : elt) (h : int), - (cardinal l < cardinal (Node l x r h))%nat. -Proof. - simpl in |- *; intuition. -Qed. -Lemma cardinal_right : - forall (l r : tree) (x : elt) (h : int), - (cardinal r < cardinal (Node l x r h))%nat. +Lemma subset_12 : forall s1 s2, bst s1 -> bst s2 -> + (subset s1 s2 = true <-> Subset s1 s2). Proof. - simpl in |- *; intuition. -Qed. + induction s1 as [|l1 IHl1 x1 r1 IHr1 h1]; simpl; intros. + unfold Subset; intuition_in. + destruct s2 as [|l2 x2 r2 h2]; simpl; intros. + unfold Subset; intuition_in; try discriminate. + assert (H': In x1 Leaf) by auto; inversion H'. + inv bst. + destruct X.compare. + + rewrite <-andb_lazy_alt, andb_true_iff, IHr1 by auto. + rewrite (@subsetl_12 (subset l1) l1 x1 h1) by auto. + clear IHl1 IHr1. + unfold Subset; intuition_in. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. + + rewrite <-andb_lazy_alt, andb_true_iff, IHl1, IHr1 by auto. + clear IHl1 IHr1. + unfold Subset; intuition_in. + assert (X.eq a x2) by order; intuition_in. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. + + rewrite <-andb_lazy_alt, andb_true_iff, IHl1 by auto. + rewrite (@subsetr_12 (subset r1) r1 x1 h1) by auto. + clear IHl1 IHr1. + unfold Subset; intuition_in. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. +Qed. -Lemma cardinal_rec2 : forall P : tree -> tree -> Set, - (forall s1 s2 : tree, - (forall t1 t2 : tree, - (cardinal t1 + cardinal t2 < cardinal s1 + cardinal s2)%nat -> P t1 t2) - -> P s1 s2) -> - forall s1 s2 : tree, P s1 s2. -Proof. - intros P H s1 s2. - apply well_founded_induction_type_2 - with (R := fun yy' xx' : tree * tree => - (cardinal (fst yy') + cardinal (snd yy') < - cardinal (fst xx') + cardinal (snd xx'))%nat); auto. - apply (Wf_nat.well_founded_ltof _ - (fun xx' : tree * tree => (cardinal (fst xx') + cardinal (snd xx'))%nat)). -Qed. - -Lemma height_0 : forall s, avl s -> height s = 0 -> s = Leaf. -Proof. - destruct 1; intuition; simpl in *. - avl_nns; simpl in *; false_omega_max. -Qed. - -(** * Union - - [union s1 s2] does an induction over the sum of the cardinals of - [s1] and [s2]. Code is -<< - let rec union s1 s2 = - match (s1, s2) with - (Empty, t2) -> t2 - | (t1, Empty) -> t1 - | (Node(l1, v1, r1, h1), Node(l2, v2, r2, h2)) -> - if h1 >= h2 then - if h2 = 1 then add v2 s1 else begin - let (l2', _, r2') = split v1 s2 in - join (union l1 l2') v1 (union r1 r2') - end - else - if h1 = 1 then add v1 s2 else begin - let (l1', _, r1') = split v2 s1 in - join (union l1' l2) v2 (union r1' r2) - end ->> -*) -Definition union : - forall s1 s2, bst s1 -> avl s1 -> bst s2 -> avl s2 -> - {s' : t | bst s' /\ avl s' /\ forall x : elt, In x s' <-> In x s1 \/ In x s2}. -Proof. - intros s1 s2; pattern s1, s2; apply cardinal_rec2; clear s1 s2. - destruct s1 as [| l1 x1 r1 h1]; intros. - (* s = Leaf *) - clear H. - exists s2; intuition_in. - (* s1 = Node l1 x1 r1 *) - destruct s2 as [| l2 x2 r2 h2]; simpl in |- *. - (* s2 = Leaf *) - clear H. - exists (Node l1 x1 r1 h1); simpl; intuition_in. - (* x' = Node l2 x2 r2 *) - case (ge_lt_dec h1 h2); intro. - (* h1 >= h2 *) - case (eq_dec h2 1); intro. - (* h2 = 1 *) - clear H. - exists (add x2 (Node l1 x1 r1 h1)); auto. - inv avl; inv bst. - avl_nn l2; avl_nn r2. - rewrite (height_0 _ H); [ | omega_max]. - rewrite (height_0 _ H4); [ | omega_max]. - split; [apply add_bst; auto|]. - split; [apply add_avl; auto|]. - intros. - rewrite (add_in (Node l1 x1 r1 h1) x2 x); intuition_in. - (* h2 <> 1 *) - (* split x1 s2 = l2',_,r2' *) - case_eq (split x1 (Node l2 x2 r2 h2)); intros l2' (b,r2') EqSplit. - set (s2 := Node l2 x2 r2 h2) in *; clearbody s2. - generalize (split_avl s2 x1 H3); rewrite EqSplit; simpl in *; intros (A,B). - generalize (split_bst s2 x1 H2 H3); rewrite EqSplit; simpl in *; intros (C,D). - generalize (split_in_1 s2 x1); rewrite EqSplit; simpl in *; intros. - generalize (split_in_2 s2 x1); rewrite EqSplit; simpl in *; intros. - (* union l1 l2' = l0 *) - destruct (H l1 l2') as [l0 (H7,(H8,H9))]; inv avl; inv bst; auto. - assert (cardinal l2' <= cardinal s2)%nat. - apply cardinal_subset; trivial. - intros y; rewrite (H4 y); intuition. - omega. - (* union r1 r2' = r0 *) - destruct (H r1 r2') as [r0 (H10,(H11,H12))]; inv avl; inv bst; auto. - assert (cardinal r2' <= cardinal s2)%nat. - apply cardinal_subset; trivial. - intros y; rewrite (H5 y); intuition. - omega. - exists (join l0 x1 r0). - inv avl; inv bst; clear H. - split. - apply join_bst; auto. - red; intros. - rewrite (H9 y) in H. - destruct H; auto. - rewrite (H4 y) in H; intuition. - red; intros. - rewrite (H12 y) in H. - destruct H; auto. - rewrite (H5 y) in H; intuition. - split. - apply join_avl; auto. - intros. - rewrite join_in; auto. - rewrite H9. - rewrite H12. - rewrite H4; auto. - rewrite H5; auto. - intuition_in. - case (X.compare x x1); intuition. - (* h1 < h2 *) - case (eq_dec h1 1); intro. - (* h1 = 1 *) - exists (add x1 (Node l2 x2 r2 h2)); auto. - inv avl; inv bst. - avl_nn l1; avl_nn r1. - rewrite (height_0 _ H3); [ | omega_max]. - rewrite (height_0 _ H8); [ | omega_max]. - split; [apply add_bst; auto|]. - split; [apply add_avl; auto|]. - intros. - rewrite (add_in (Node l2 x2 r2 h2) x1 x); intuition_in. - (* h1 <> 1 *) - (* split x2 s1 = l1',_,r1' *) - case_eq (split x2 (Node l1 x1 r1 h1)); intros l1' (b,r1') EqSplit. - set (s1 := Node l1 x1 r1 h1) in *; clearbody s1. - generalize (split_avl s1 x2 H1); rewrite EqSplit; simpl in *; intros (A,B). - generalize (split_bst s1 x2 H0 H1); rewrite EqSplit; simpl in *; intros (C,D). - generalize (split_in_1 s1 x2); rewrite EqSplit; simpl in *; intros. - generalize (split_in_2 s1 x2); rewrite EqSplit; simpl in *; intros. - (* union l1' l2 = l0 *) - destruct (H l1' l2) as [l0 (H7,(H8,H9))]; inv avl; inv bst; auto. - assert (cardinal l1' <= cardinal s1)%nat. - apply cardinal_subset; trivial. - intros y; rewrite (H4 y); intuition. - omega. - (* union r1' r2 = r0 *) - destruct (H r1' r2) as [r0 (H10,(H11,H12))]; inv avl; inv bst; auto. - assert (cardinal r1' <= cardinal s1)%nat. - apply cardinal_subset; trivial. - intros y; rewrite (H5 y); intuition. - omega. - exists (join l0 x2 r0). - inv avl; inv bst; clear H. - split. - apply join_bst; auto. - red; intros. - rewrite (H9 y) in H. - destruct H; auto. - rewrite (H4 y) in H; intuition. - red; intros. - rewrite (H12 y) in H. - destruct H; auto. - rewrite (H5 y) in H; intuition. - split. - apply join_avl; auto. - intros. - rewrite join_in; auto. - rewrite H9. - rewrite H12. - rewrite H4; auto. - rewrite H5; auto. - intuition_in. - case (X.compare x x2); intuition. -Qed. - - -(** * Subset -<< - let rec subset s1 s2 = - match (s1, s2) with - Empty, _ -> true - | _, Empty -> false - | Node (l1, v1, r1, _), (Node (l2, v2, r2, _) as t2) -> - let c = Ord.compare v1 v2 in - if c = 0 then - subset l1 l2 && subset r1 r2 - else if c < 0 then - subset (Node (l1, v1, Empty, 0)) l2 && subset r1 t2 - else - subset (Node (Empty, v1, r1, 0)) r2 && subset l1 t2 ->> -*) - -Definition subset : forall s1 s2 : t, bst s1 -> bst s2 -> - {Subset s1 s2} + {~ Subset s1 s2}. -Proof. - intros s1 s2; pattern s1, s2; apply cardinal_rec2; clear s1 s2. - destruct s1 as [| l1 x1 r1 h1]; intros. - (* s1 = Leaf *) - left; red; intros; inv In. - (* s1 = Node l1 x1 r1 h1 *) - destruct s2 as [| l2 x2 r2 h2]. - (* s2 = Leaf *) - right; intros; intro. - assert (In x1 Leaf); auto. - inversion_clear H3. - (* s2 = Node l2 x2 r2 h2 *) - case (X.compare x1 x2); intro. - (* x1 < x2 *) - case (H (Node l1 x1 Leaf 0) l2); inv bst; auto; intros. - simpl in |- *; omega. - case (H r1 (Node l2 x2 r2 h2)); inv bst; auto; intros. - simpl in |- *; omega. - clear H; left; red; intuition. - generalize (s a) (s0 a); clear s s0; intuition_in. - clear H; right; red; firstorder. - clear H; right; red; inv bst; intuition. - apply n; red; intros. - assert (In a (Node l2 x2 r2 h2)) by (inv In; auto). - intuition_in; order. - (* x1 = x2 *) - case (H l1 l2); inv bst; auto; intros. - simpl in |- *; omega. - case (H r1 r2); inv bst; auto; intros. - simpl in |- *; omega. - clear H; left; red; intuition_in; eauto. - clear H; right; red; inv bst; intuition. - apply n; red; intros. - assert (In a (Node l2 x2 r2 h2)) by auto. - intuition_in; order. - clear H; right; red; inv bst; intuition. - apply n; red; intros. - assert (In a (Node l2 x2 r2 h2)) by auto. - intuition_in; order. - (* x1 > x2 *) - case (H (Node Leaf x1 r1 0) r2); inv bst; auto; intros. - simpl in |- *; omega. - intros; case (H l1 (Node l2 x2 r2 h2)); inv bst; auto; intros. - simpl in |- *; omega. - clear H; left; red; intuition. - generalize (s a) (s0 a); clear s s0; intuition_in. - clear H; right; red; firstorder. - clear H; right; red; inv bst; intuition. - apply n; red; intros. - assert (In a (Node l2 x2 r2 h2)) by (inv In; auto). - intuition_in; order. -Qed. (** * Comparison *) (** ** Relations [eq] and [lt] over trees *) -Definition eq : t -> t -> Prop := Equal. +Definition eq := Equal. +Definition lt (s1 s2 : t) : Prop := L.lt (elements s1) (elements s2). -Lemma eq_refl : forall s : t, eq s s. +Lemma eq_refl : forall s : t, Equal s s. Proof. - unfold eq, Equal in |- *; intuition. + unfold Equal; intuition. Qed. -Lemma eq_sym : forall s s' : t, eq s s' -> eq s' s. +Lemma eq_sym : forall s s' : t, Equal s s' -> Equal s' s. Proof. - unfold eq, Equal in |- *; firstorder. + unfold Equal; intros s s' H x; destruct (H x); split; auto. Qed. -Lemma eq_trans : forall s s' s'' : t, eq s s' -> eq s' s'' -> eq s s''. +Lemma eq_trans : forall s s' s'' : t, + Equal s s' -> Equal s' s'' -> Equal s s''. Proof. - unfold eq, Equal in |- *; firstorder. + unfold Equal; intros s s' s'' H1 H2 x; + destruct (H1 x); destruct (H2 x); split; auto. Qed. Lemma eq_L_eq : - forall s s' : t, eq s s' -> L.eq (elements s) (elements s'). + forall s s' : t, Equal s s' -> L.eq (elements s) (elements s'). Proof. - unfold eq, Equal, L.eq, L.Equal in |- *; intros. - generalize (elements_in s a) (elements_in s' a). - firstorder. + unfold Equal, L.eq, L.Equal; intros; do 2 rewrite elements_in; auto. Qed. Lemma L_eq_eq : - forall s s' : t, L.eq (elements s) (elements s') -> eq s s'. + forall s s' : t, L.eq (elements s) (elements s') -> Equal s s'. Proof. - unfold eq, Equal, L.eq, L.Equal in |- *; intros. - generalize (elements_in s a) (elements_in s' a). - firstorder. + unfold Equal, L.eq, L.Equal; intros; do 2 rewrite <-elements_in; auto. Qed. Hint Resolve eq_L_eq L_eq_eq. -Definition lt (s1 s2 : t) : Prop := L.lt (elements s1) (elements s2). - Definition lt_trans (s s' s'' : t) (h : lt s s') (h' : lt s' s'') : lt s s'' := L.lt_trans h h'. -Lemma lt_not_eq : forall s s' : t, bst s -> bst s' -> lt s s' -> ~ eq s s'. +Lemma lt_not_eq : forall s s' : t, + bst s -> bst s' -> lt s s' -> ~ Equal s s'. Proof. unfold lt in |- *; intros; intro. apply L.lt_not_eq with (s := elements s) (s' := elements s'); auto. Qed. -(** A new comparison algorithm suggested by Xavier Leroy: - -type enumeration = End | More of elt * t * enumeration - -let rec cons s e = match s with - | Empty -> e - | Node(l, v, r, _) -> cons l (More(v, r, e)) - -let rec compare_aux e1 e2 = match (e1, e2) with - | (End, End) -> 0 - | (End, More _) -> -1 - | (More _, End) -> 1 - | (More(v1, r1, k1), More(v2, r2, k2)) -> - let c = Ord.compare v1 v2 in - if c <> 0 then c else compare_aux (cons r1 k1) (cons r2 k2) - -let compare s1 s2 = compare_aux (cons s1 End) (cons s2 End) -*) +Lemma L_eq_cons : + forall (l1 l2 : list elt) (x y : elt), + X.eq x y -> L.eq l1 l2 -> L.eq (x :: l1) (y :: l2). +Proof. + unfold L.eq, L.Equal in |- *; intuition. + inversion_clear H1; generalize (H0 a); clear H0; intuition. + apply InA_eqA with x; eauto. + inversion_clear H1; generalize (H0 a); clear H0; intuition. + apply InA_eqA with y; eauto. +Qed. +Hint Resolve L_eq_cons. -(** ** Enumeration of the elements of a tree *) -Inductive enumeration : Set := - | End : enumeration - | More : elt -> tree -> enumeration -> enumeration. +(** * A new comparison algorithm suggested by Xavier Leroy *) (** [flatten_e e] returns the list of elements of [e] i.e. the list of elements actually compared *) @@ -2171,462 +1719,166 @@ Fixpoint flatten_e (e : enumeration) : list elt := match e with | More x t r => x :: elements t ++ flatten_e r end. -(** [sorted_e e] expresses that elements in the enumeration [e] are - sorted, and that all trees in [e] are binary search trees. *) - -Inductive In_e (x:elt) : enumeration -> Prop := - | InEHd1 : - forall (y : elt) (s : tree) (e : enumeration), - X.eq x y -> In_e x (More y s e) - | InEHd2 : - forall (y : elt) (s : tree) (e : enumeration), - In x s -> In_e x (More y s e) - | InETl : - forall (y : elt) (s : tree) (e : enumeration), - In_e x e -> In_e x (More y s e). - -Hint Constructors In_e. - -Inductive sorted_e : enumeration -> Prop := - | SortedEEnd : sorted_e End - | SortedEMore : - forall (x : elt) (s : tree) (e : enumeration), - bst s -> - (gt_tree x s) -> - sorted_e e -> - (forall y : elt, In_e y e -> X.lt x y) -> - (forall y : elt, - In y s -> forall z : elt, In_e z e -> X.lt y z) -> - sorted_e (More x s e). - -Hint Constructors sorted_e. - -Lemma in_app : - forall (x : elt) (l1 l2 : list elt), - InA X.eq x (l1 ++ l2) -> InA X.eq x l1 \/ InA X.eq x l2. -Proof. - simple induction l1; simpl in |- *; intuition. - inversion_clear H0; auto. - elim (H l2 H1); auto. -Qed. - -Lemma in_flatten_e : - forall (x : elt) (e : enumeration), InA X.eq x (flatten_e e) -> In_e x e. -Proof. - simple induction e; simpl in |- *; intuition. - inversion_clear H. - inversion_clear H0; auto. - elim (in_app x _ _ H1); auto. - destruct (elements_in t x); auto. -Qed. - -Lemma sort_app : - forall l1 l2 : list elt, sort X.lt l1 -> sort X.lt l2 -> - (forall x y : elt, InA X.eq x l1 -> InA X.eq y l2 -> X.lt x y) -> - sort X.lt (l1 ++ l2). -Proof. - simple induction l1; simpl in |- *; intuition. - apply cons_sort; auto. - apply H; auto. - inversion_clear H0; trivial. - induction l as [| a0 l Hrecl]; simpl in |- *; intuition. - induction l2 as [| a0 l2 Hrecl2]; simpl in |- *; intuition. - inversion_clear H0; inversion_clear H4; auto. -Qed. - -Lemma sorted_flatten_e : - forall e : enumeration, sorted_e e -> sort X.lt (flatten_e e). -Proof. - simple induction e; simpl in |- *; intuition. - apply cons_sort. - apply sort_app; inversion H0; auto. - intros; apply H8; auto. - destruct (elements_in t x0); auto. - apply in_flatten_e; auto. - apply L.MX.ListIn_Inf. - inversion_clear H0. - intros; elim (in_app_or _ _ _ H0); intuition. - destruct (elements_in t y); auto. - apply H4; apply in_flatten_e; auto. -Qed. - -Lemma elements_app : - forall (s : tree) (acc : list elt), elements_aux acc s = elements s ++ acc. -Proof. - simple induction s; simpl in |- *; intuition. - rewrite H0. - rewrite H. - unfold elements; simpl. - do 2 rewrite H. - rewrite H0. - repeat rewrite <- app_nil_end. - repeat rewrite app_ass; auto. -Qed. - -Lemma compare_flatten_1 : - forall (t0 t2 : tree) (t1 : elt) (z : int) (l : list elt), - elements t0 ++ t1 :: elements t2 ++ l = - elements (Node t0 t1 t2 z) ++ l. +Lemma flatten_e_elements : + forall l x r h e, + elements l ++ flatten_e (More x r e) = elements (Node l x r h) ++ flatten_e e. Proof. - simpl in |- *; unfold elements in |- *; simpl in |- *; intuition. - repeat rewrite elements_app. - repeat rewrite <- app_nil_end. - repeat rewrite app_ass; auto. + intros; simpl; apply elements_node. Qed. -(** key lemma for correctness *) - -Lemma flatten_e_elements : - forall (x : elt) (l r : tree) (z : int) (e : enumeration), - elements l ++ flatten_e (More x r e) = elements (Node l x r z) ++ flatten_e e. +Lemma cons_1 : forall s e, + flatten_e (cons s e) = elements s ++ flatten_e e. Proof. - intros; simpl. - apply compare_flatten_1. + induction s; simpl; auto; intros. + rewrite IHs1; apply flatten_e_elements. Qed. -(** termination of [compare_aux] *) +(** Correctness of this comparison *) -Open Local Scope Z_scope. - -Fixpoint measure_e_t (s : tree) : Z := match s with - | Leaf => 0 - | Node l _ r _ => 1 + measure_e_t l + measure_e_t r - end. - -Fixpoint measure_e (e : enumeration) : Z := match e with - | End => 0 - | More _ s r => 1 + measure_e_t s + measure_e r +Definition Cmp c := + match c with + | Eq => L.eq + | Lt => L.lt + | Gt => (fun l1 l2 => L.lt l2 l1) end. -Ltac Measure_e_t := unfold measure_e_t in |- *; fold measure_e_t in |- *. -Ltac Measure_e := unfold measure_e in |- *; fold measure_e in |- *. - -Lemma measure_e_t_0 : forall s : tree, measure_e_t s >= 0. +Lemma cons_Cmp : forall c x1 x2 l1 l2, X.eq x1 x2 -> + Cmp c l1 l2 -> Cmp c (x1::l1) (x2::l2). Proof. - simple induction s. - simpl in |- *; omega. - intros. - Measure_e_t; omega. (* BUG Simpl! *) + destruct c; simpl; auto. Qed. +Hint Resolve cons_Cmp. -Ltac Measure_e_t_0 s := generalize (measure_e_t_0 s); intro. - -Lemma measure_e_0 : forall e : enumeration, measure_e e >= 0. +Lemma compare_end_Cmp : + forall e2, Cmp (compare_end e2) nil (flatten_e e2). Proof. - simple induction e. - simpl in |- *; omega. - intros. - Measure_e; Measure_e_t_0 t; omega. + destruct e2; simpl; auto. + apply L.eq_refl. Qed. -Ltac Measure_e_0 e := generalize (measure_e_0 e); intro. - -(** Induction principle over the sum of the measures for two lists *) - -Definition compare_rec2 : - forall P : enumeration -> enumeration -> Set, - (forall x x' : enumeration, - (forall y y' : enumeration, - measure_e y + measure_e y' < measure_e x + measure_e x' -> P y y') -> - P x x') -> - forall x x' : enumeration, P x x'. +Lemma compare_more_Cmp : forall x1 cont x2 r2 e2 l, + Cmp (cont (cons r2 e2)) l (elements r2 ++ flatten_e e2) -> + Cmp (compare_more x1 cont (More x2 r2 e2)) (x1::l) + (flatten_e (More x2 r2 e2)). Proof. - intros P H x x'. - apply well_founded_induction_type_2 - with (R := fun yy' xx' : enumeration * enumeration => - measure_e (fst yy') + measure_e (snd yy') < - measure_e (fst xx') + measure_e (snd xx')); auto. - apply Wf_nat.well_founded_lt_compat - with (f := fun xx' : enumeration * enumeration => - Zabs_nat (measure_e (fst xx') + measure_e (snd xx'))). - intros; apply Zabs.Zabs_nat_lt. - Measure_e_0 (fst x0); Measure_e_0 (snd x0); Measure_e_0 (fst y); - Measure_e_0 (snd y); intros; omega. -Qed. - -(** [cons t e] adds the elements of tree [t] on the head of - enumeration [e]. Code: - -let rec cons s e = match s with - | Empty -> e - | Node(l, v, r, _) -> cons l (More(v, r, e)) -*) - -Definition cons : forall (s : tree) (e : enumeration), bst s -> sorted_e e -> - (forall (x y : elt), In x s -> In_e y e -> X.lt x y) -> - { r : enumeration - | sorted_e r /\ - measure_e r = measure_e_t s + measure_e e /\ - flatten_e r = elements s ++ flatten_e e - }. -Proof. - simple induction s; intuition. - (* s = Leaf *) - exists e; intuition. - (* s = Node t t0 t1 z *) - clear H0. - case (H (More t0 t1 e)); clear H; intuition. - inv bst; auto. - constructor; inversion_clear H1; auto. - inversion_clear H0; inv bst; intuition; order. - exists x; intuition. - generalize H4; Measure_e; intros; Measure_e_t; omega. - rewrite H5. - apply flatten_e_elements. + simpl; intros; destruct X.compare; simpl; auto. Qed. -Lemma l_eq_cons : - forall (l1 l2 : list elt) (x y : elt), - X.eq x y -> L.eq l1 l2 -> L.eq (x :: l1) (y :: l2). +Lemma compare_cont_Cmp : forall s1 cont e2 l, + (forall e, Cmp (cont e) l (flatten_e e)) -> + Cmp (compare_cont s1 cont e2) (elements s1 ++ l) (flatten_e e2). Proof. - unfold L.eq, L.Equal in |- *; intuition. - inversion_clear H1; generalize (H0 a); clear H0; intuition. - apply InA_eqA with x; eauto. - inversion_clear H1; generalize (H0 a); clear H0; intuition. - apply InA_eqA with y; eauto. + induction s1 as [|l1 Hl1 x1 r1 Hr1 h1]; simpl; intros; auto. + rewrite <- elements_node; simpl. + apply Hl1; auto. clear e2. intros [|x2 r2 e2]. + simpl; auto. + apply compare_more_Cmp. + rewrite <- cons_1; auto. Qed. -Definition compare_aux : - forall e1 e2 : enumeration, sorted_e e1 -> sorted_e e2 -> - Compare L.lt L.eq (flatten_e e1) (flatten_e e2). -Proof. - intros e1 e2; pattern e1, e2 in |- *; apply compare_rec2. - simple destruct x; simple destruct x'; intuition. - (* x = x' = End *) - constructor 2; unfold L.eq, L.Equal in |- *; intuition. - (* x = End x' = More *) - constructor 1; simpl in |- *; auto. - (* x = More x' = End *) - constructor 3; simpl in |- *; auto. - (* x = More e t e0, x' = More e3 t0 e4 *) - case (X.compare e e3); intro. - (* e < e3 *) - constructor 1; simpl; auto. - (* e = e3 *) - destruct (cons t e0) as [c1 (H2,(H3,H4))]; try inversion_clear H0; auto. - destruct (cons t0 e4) as [c2 (H5,(H6,H7))]; try inversion_clear H1; auto. - destruct (H c1 c2); clear H; intuition. - Measure_e; omega. - constructor 1; simpl. - apply L.lt_cons_eq; auto. - rewrite H4 in l; rewrite H7 in l; auto. - constructor 2; simpl. - apply l_eq_cons; auto. - rewrite H4 in e6; rewrite H7 in e6; auto. - constructor 3; simpl. - apply L.lt_cons_eq; auto. - rewrite H4 in l; rewrite H7 in l; auto. - (* e > e3 *) - constructor 3; simpl; auto. -Qed. - -Definition compare : forall s1 s2, bst s1 -> bst s2 -> Compare lt eq s1 s2. -Proof. - intros s1 s2 s1_bst s2_bst; unfold lt, eq; simpl. - destruct (cons s1 End); intuition. - inversion_clear H0. - destruct (cons s2 End); intuition. - inversion_clear H3. - simpl in H2; rewrite <- app_nil_end in H2. - simpl in H5; rewrite <- app_nil_end in H5. - destruct (compare_aux x x0); intuition. - constructor 1; simpl in |- *. - rewrite H2 in l; rewrite H5 in l; auto. - constructor 2; apply L_eq_eq; simpl in |- *. - rewrite H2 in e; rewrite H5 in e; auto. - constructor 3; simpl in |- *. - rewrite H2 in l; rewrite H5 in l; auto. +Lemma compare_Cmp : forall s1 s2, + Cmp (compare s1 s2) (elements s1) (elements s2). +Proof. + intros; unfold compare. + rewrite (app_nil_end (elements s1)). + replace (elements s2) with (flatten_e (cons s2 End)) by + (rewrite cons_1; simpl; rewrite <- app_nil_end; auto). + apply compare_cont_Cmp; auto. + intros. + apply compare_end_Cmp; auto. Qed. (** * Equality test *) -Definition equal : forall s s' : t, bst s -> bst s' -> {Equal s s'} + {~ Equal s s'}. +Lemma equal_1 : forall s1 s2, bst s1 -> bst s2 -> + Equal s1 s2 -> equal s1 s2 = true. Proof. - intros s s' Hs Hs'; case (compare s s'); auto; intros. - right; apply lt_not_eq; auto. - right; intro; apply (lt_not_eq s' s); auto; apply eq_sym; auto. -Qed. - -(** We provide additionally a different implementation for union, subset and - equal, which is less efficient, but uses structural induction, hence computes - within Coq. *) - -(** Alternative union based on fold. - Complexity : [min(|s|,|s'|)*log(max(|s|,|s'|))] *) - -Definition union' s s' := - if ge_lt_dec (height s) (height s') then fold add s' s else fold add s s'. - -Lemma fold_add_avl : forall s s', avl s -> avl s' -> avl (fold add s s'). -Proof. - induction s; simpl; intros; inv avl; auto. -Qed. -Hint Resolve fold_add_avl. - -Lemma union'_avl : forall s s', avl s -> avl s' -> avl (union' s s'). -Proof. - unfold union'; intros; destruct (ge_lt_dec (height s) (height s')); auto. -Qed. - -Lemma fold_add_bst : forall s s', bst s -> avl s -> bst s' -> avl s' -> - bst (fold add s s'). -Proof. - induction s; simpl; intros; inv avl; inv bst; auto. - apply IHs2; auto. - apply add_bst; auto. -Qed. - -Lemma union'_bst : forall s s', bst s -> avl s -> bst s' -> avl s' -> - bst (union' s s'). -Proof. - unfold union'; intros; destruct (ge_lt_dec (height s) (height s')); - apply fold_add_bst; auto. +unfold equal; intros s1 s2 B1 B2 E. +generalize (compare_Cmp s1 s2). +destruct (compare s1 s2); simpl in *; auto; intros. +elim (lt_not_eq B1 B2 H E); auto. +elim (lt_not_eq B2 B1 H (eq_sym E)); auto. Qed. -Lemma fold_add_in : forall s s' y, bst s -> avl s -> bst s' -> avl s' -> - (In y (fold add s s') <-> In y s \/ In y s'). -Proof. - induction s; simpl; intros; inv avl; inv bst; auto. - intuition_in. - rewrite IHs2; auto. - apply add_bst; auto. - apply fold_add_bst; auto. - rewrite add_in; auto. - rewrite IHs1; auto. - intuition_in. -Qed. - -Lemma union'_in : forall s s' y, bst s -> avl s -> bst s' -> avl s' -> - (In y (union' s s') <-> In y s \/ In y s'). +Lemma equal_2 : forall s1 s2, + equal s1 s2 = true -> Equal s1 s2. Proof. - unfold union'; intros; destruct (ge_lt_dec (height s) (height s')). - rewrite fold_add_in; intuition. - apply fold_add_in; auto. -Qed. - -(** Alternative subset based on diff. *) - -Definition subset' s s' := is_empty (diff s s'). - -Lemma subset'_1 : forall s s', bst s -> avl s -> bst s' -> avl s' -> - Subset s s' -> subset' s s' = true. -Proof. - unfold subset', Subset; intros; apply is_empty_1; red; intros. - rewrite (diff_in); intuition. +unfold equal; intros s1 s2 E. +generalize (compare_Cmp s1 s2); + destruct compare; auto; discriminate. Qed. -Lemma subset'_2 : forall s s', bst s -> avl s -> bst s' -> avl s' -> - subset' s s' = true -> Subset s s'. -Proof. - unfold subset', Subset; intros; generalize (is_empty_2 _ H3 a); unfold Empty. - rewrite (diff_in); intuition. - generalize (mem_2 s' a) (mem_1 s' a); destruct (mem a s'); intuition. -Qed. +End Proofs. -(** Alternative equal based on subset *) +End Raw. -Definition equal' s s' := subset' s s' && subset' s' s. -Lemma equal'_1 : forall s s', bst s -> avl s -> bst s' -> avl s' -> - Equal s s' -> equal' s s' = true. -Proof. - unfold equal', Equal; intros. - rewrite subset'_1; firstorder; simpl. - apply subset'_1; firstorder. -Qed. - -Lemma equal'_2 : forall s s', bst s -> avl s -> bst s' -> avl s' -> - equal' s s' = true -> Equal s s'. -Proof. - unfold equal', Equal; intros; destruct (andb_prop _ _ H3); split; - apply subset'_2; auto. -Qed. - -End Raw. (** * Encapsulation Now, in order to really provide a functor implementing [S], we - need to encapsulate everything into a type of balanced binary search trees. *) + need to encapsulate everything into a type of binary search trees. + They also happen to be well-balanced, but this has no influence + on the correctness of operations, so we won't state this here, + see [FSetFullAVL] if you need more than just the FSet interface. +*) Module IntMake (I:Int)(X: OrderedType) <: S with Module E := X. Module E := X. - Module Raw := Raw I X. + Module Raw := Raw I X. + Import Raw.Proofs. - Record bbst : Set := Bbst {this :> Raw.t; is_bst : Raw.bst this; is_avl: Raw.avl this}. - Definition t := bbst. + Record bst := Bst {this :> Raw.t; is_bst : Raw.bst this}. + Definition t := bst. Definition elt := E.t. - Definition In (x : elt) (s : t) : Prop := Raw.In x s. - Definition Equal (s s':t) : Prop := forall a : elt, In a s <-> In a s'. - Definition Subset (s s':t) : Prop := forall a : elt, In a s -> In a s'. - Definition Empty (s:t) : Prop := forall a : elt, ~ In a s. - Definition For_all (P : elt -> Prop) (s:t) : Prop := forall x, In x s -> P x. - Definition Exists (P : elt -> Prop) (s:t) : Prop := exists x, In x s /\ P x. - + Definition In (x : elt) (s : t) := Raw.In x s. + Definition Equal (s s':t) := forall a : elt, In a s <-> In a s'. + Definition Subset (s s':t) := forall a : elt, In a s -> In a s'. + Definition Empty (s:t) := forall a : elt, ~ In a s. + Definition For_all (P : elt -> Prop) (s:t) := forall x, In x s -> P x. + Definition Exists (P : elt -> Prop) (s:t) := exists x, In x s /\ P x. + Lemma In_1 : forall (s:t)(x y:elt), E.eq x y -> In x s -> In y s. - Proof. intro s; exact (Raw.In_1 s). Qed. + Proof. intro s; exact (@In_1 s). Qed. Definition mem (x:elt)(s:t) : bool := Raw.mem x s. - Definition empty : t := Bbst _ Raw.empty_bst Raw.empty_avl. + Definition empty : t := Bst empty_bst. Definition is_empty (s:t) : bool := Raw.is_empty s. - Definition singleton (x:elt) : t := Bbst _ (Raw.singleton_bst x) (Raw.singleton_avl x). - Definition add (x:elt)(s:t) : t := - Bbst _ (Raw.add_bst s x (is_bst s) (is_avl s)) - (Raw.add_avl s x (is_avl s)). - Definition remove (x:elt)(s:t) : t := - Bbst _ (Raw.remove_bst s x (is_bst s) (is_avl s)) - (Raw.remove_avl s x (is_avl s)). - Definition inter (s s':t) : t := - Bbst _ (Raw.inter_bst _ _ (is_bst s) (is_avl s) (is_bst s') (is_avl s')) - (Raw.inter_avl _ _ (is_avl s) (is_avl s')). - Definition diff (s s':t) : t := - Bbst _ (Raw.diff_bst _ _ (is_bst s) (is_avl s) (is_bst s') (is_avl s')) - (Raw.diff_avl _ _ (is_avl s) (is_avl s')). + Definition singleton (x:elt) : t := Bst (singleton_bst x). + Definition add (x:elt)(s:t) : t := Bst (add_bst x (is_bst s)). + Definition remove (x:elt)(s:t) : t := Bst (remove_bst x (is_bst s)). + Definition inter (s s':t) : t := Bst (inter_bst (is_bst s) (is_bst s')). + Definition union (s s':t) : t := Bst (union_bst (is_bst s) (is_bst s')). + Definition diff (s s':t) : t := Bst (diff_bst (is_bst s) (is_bst s')). Definition elements (s:t) : list elt := Raw.elements s. Definition min_elt (s:t) : option elt := Raw.min_elt s. Definition max_elt (s:t) : option elt := Raw.max_elt s. Definition choose (s:t) : option elt := Raw.choose s. - Definition fold (B : Set) (f : elt -> B -> B) (s:t) : B -> B := Raw.fold f s. + Definition fold (B : Type) (f : elt -> B -> B) (s:t) : B -> B := Raw.fold f s. Definition cardinal (s:t) : nat := Raw.cardinal s. Definition filter (f : elt -> bool) (s:t) : t := - Bbst _ (Raw.filter_bst f _ (is_bst s) (is_avl s)) - (Raw.filter_avl f _ (is_avl s)). + Bst (filter_bst f (is_bst s)). Definition for_all (f : elt -> bool) (s:t) : bool := Raw.for_all f s. Definition exists_ (f : elt -> bool) (s:t) : bool := Raw.exists_ f s. Definition partition (f : elt -> bool) (s:t) : t * t := let p := Raw.partition f s in - (Bbst (fst p) (Raw.partition_bst_1 f _ (is_bst s) (is_avl s)) - (Raw.partition_avl_1 f _ (is_avl s)), - Bbst (snd p) (Raw.partition_bst_2 f _ (is_bst s) (is_avl s)) - (Raw.partition_avl_2 f _ (is_avl s))). - - Definition union (s s':t) : t := - let (u,p) := Raw.union _ _ (is_bst s) (is_avl s) (is_bst s') (is_avl s') in - let (b,p) := p in - let (a,_) := p in - Bbst u b a. - - Definition union' (s s' : t) : t := - Bbst _ (Raw.union'_bst _ _ (is_bst s) (is_avl s) (is_bst s') (is_avl s')) - (Raw.union'_avl _ _ (is_avl s) (is_avl s')). - - Definition equal (s s': t) : bool := if Raw.equal _ _ (is_bst s) (is_bst s') then true else false. - Definition equal' (s s':t) : bool := Raw.equal' s s'. + (@Bst (fst p) (partition_bst_1 f (is_bst s)), + @Bst (snd p) (partition_bst_2 f (is_bst s))). - Definition subset (s s':t) : bool := if Raw.subset _ _ (is_bst s) (is_bst s') then true else false. - Definition subset' (s s':t) : bool := Raw.subset' s s'. + Definition equal (s s':t) : bool := Raw.equal s s'. + Definition subset (s s':t) : bool := Raw.subset s s'. - Definition eq (s s':t) : Prop := Raw.eq s s'. - Definition lt (s s':t) : Prop := Raw.lt s s'. + Definition eq (s s':t) : Prop := Raw.Equal s s'. + Definition lt (s s':t) : Prop := Raw.Proofs.lt s s'. - Definition compare (s s':t) : Compare lt eq s s'. + Definition compare (s s':t) : Compare lt eq s s'. Proof. - intros; elim (Raw.compare _ _ (is_bst s) (is_bst s')); - [ constructor 1 | constructor 2 | constructor 3 ]; - auto. + intros (s,b) (s',b'). + generalize (compare_Cmp s s'). + destruct Raw.compare; intros; [apply EQ|apply LT|apply GT]; red; auto. Defined. (* specs *) @@ -2634,260 +1886,164 @@ Module IntMake (I:Int)(X: OrderedType) <: S with Module E := X. Variable s s' s'': t. Variable x y : elt. - Hint Resolve is_bst is_avl. + Hint Resolve is_bst. Lemma mem_1 : In x s -> mem x s = true. - Proof. exact (Raw.mem_1 s x (is_bst s)). Qed. + Proof. exact (mem_1 (is_bst s)). Qed. Lemma mem_2 : mem x s = true -> In x s. - Proof. exact (Raw.mem_2 s x). Qed. + Proof. exact (@mem_2 s x). Qed. Lemma equal_1 : Equal s s' -> equal s s' = true. - Proof. - unfold equal; destruct (Raw.equal s s'); simpl; auto. - Qed. - + Proof. exact (equal_1 (is_bst s) (is_bst s')). Qed. Lemma equal_2 : equal s s' = true -> Equal s s'. - Proof. - unfold equal; destruct (Raw.equal s s'); simpl; intuition; discriminate. - Qed. + Proof. exact (@equal_2 s s'). Qed. - Lemma equal'_1 : Equal s s' -> equal' s s' = true. - Proof. exact (Raw.equal'_1 _ _ (is_bst s) (is_avl s) (is_bst s') (is_avl s')). Qed. - Lemma equal'_2 : equal' s s' = true -> Equal s s'. - Proof. exact (Raw.equal'_2 _ _ (is_bst s) (is_avl s) (is_bst s') (is_avl s')). Qed. + Ltac wrap t H := unfold t, In; simpl; rewrite H; auto; intuition. Lemma subset_1 : Subset s s' -> subset s s' = true. - Proof. - unfold subset; destruct (Raw.subset s s'); simpl; intuition. - Qed. - + Proof. wrap subset subset_12. Qed. Lemma subset_2 : subset s s' = true -> Subset s s'. - Proof. - unfold subset; destruct (Raw.subset s s'); simpl; intuition discriminate. - Qed. - - Lemma subset'_1 : Subset s s' -> subset' s s' = true. - Proof. exact (Raw.subset'_1 _ _ (is_bst s) (is_avl s) (is_bst s') (is_avl s')). Qed. - Lemma subset'_2 : subset' s s' = true -> Subset s s'. - Proof. exact (Raw.subset'_2 _ _ (is_bst s) (is_avl s) (is_bst s') (is_avl s')). Qed. + Proof. wrap subset subset_12. Qed. Lemma empty_1 : Empty empty. - Proof. exact Raw.empty_1. Qed. + Proof. exact empty_1. Qed. Lemma is_empty_1 : Empty s -> is_empty s = true. - Proof. exact (Raw.is_empty_1 s). Qed. + Proof. exact (@is_empty_1 s). Qed. Lemma is_empty_2 : is_empty s = true -> Empty s. - Proof. exact (Raw.is_empty_2 s). Qed. + Proof. exact (@is_empty_2 s). Qed. Lemma add_1 : E.eq x y -> In y (add x s). - Proof. - unfold add, In; simpl; rewrite Raw.add_in; auto. - Qed. - + Proof. wrap add add_in. Qed. Lemma add_2 : In y s -> In y (add x s). - Proof. - unfold add, In; simpl; rewrite Raw.add_in; auto. - Qed. - + Proof. wrap add add_in. Qed. Lemma add_3 : ~ E.eq x y -> In y (add x s) -> In y s. - Proof. - unfold add, In; simpl; rewrite Raw.add_in; intuition. - elim H; auto. - Qed. + Proof. wrap add add_in. elim H; auto. Qed. Lemma remove_1 : E.eq x y -> ~ In y (remove x s). - Proof. - unfold remove, In; simpl; rewrite Raw.remove_in; intuition. - Qed. - + Proof. wrap remove remove_in. Qed. Lemma remove_2 : ~ E.eq x y -> In y s -> In y (remove x s). - Proof. - unfold remove, In; simpl; rewrite Raw.remove_in; intuition. - Qed. - + Proof. wrap remove remove_in. Qed. Lemma remove_3 : In y (remove x s) -> In y s. - Proof. - unfold remove, In; simpl; rewrite Raw.remove_in; intuition. - Qed. + Proof. wrap remove remove_in. Qed. Lemma singleton_1 : In y (singleton x) -> E.eq x y. - Proof. exact (Raw.singleton_1 x y). Qed. + Proof. exact (@singleton_1 x y). Qed. Lemma singleton_2 : E.eq x y -> In y (singleton x). - Proof. exact (Raw.singleton_2 x y). Qed. + Proof. exact (@singleton_2 x y). Qed. Lemma union_1 : In x (union s s') -> In x s \/ In x s'. - Proof. - unfold union, In; simpl. - destruct (Raw.union s s' (is_bst s) (is_avl s) (is_bst s') (is_avl s')) - as (u,(b,(a,i))). - simpl in *; rewrite i; auto. - Qed. - + Proof. wrap union union_in. Qed. Lemma union_2 : In x s -> In x (union s s'). - Proof. - unfold union, In; simpl. - destruct (Raw.union s s' (is_bst s) (is_avl s) (is_bst s') (is_avl s')) - as (u,(b,(a,i))). - simpl in *; rewrite i; auto. - Qed. - + Proof. wrap union union_in. Qed. Lemma union_3 : In x s' -> In x (union s s'). - Proof. - unfold union, In; simpl. - destruct (Raw.union s s' (is_bst s) (is_avl s) (is_bst s') (is_avl s')) - as (u,(b,(a,i))). - simpl in *; rewrite i; auto. - Qed. - - Lemma union'_1 : In x (union' s s') -> In x s \/ In x s'. - Proof. - unfold union', In; simpl; rewrite Raw.union'_in; intuition. - Qed. - - Lemma union'_2 : In x s -> In x (union' s s'). - Proof. - unfold union', In; simpl; rewrite Raw.union'_in; intuition. - Qed. - - Lemma union'_3 : In x s' -> In x (union' s s'). - Proof. - unfold union', In; simpl; rewrite Raw.union'_in; intuition. - Qed. + Proof. wrap union union_in. Qed. Lemma inter_1 : In x (inter s s') -> In x s. - Proof. - unfold inter, In; simpl; rewrite Raw.inter_in; intuition. - Qed. - + Proof. wrap inter inter_in. Qed. Lemma inter_2 : In x (inter s s') -> In x s'. - Proof. - unfold inter, In; simpl; rewrite Raw.inter_in; intuition. - Qed. - + Proof. wrap inter inter_in. Qed. Lemma inter_3 : In x s -> In x s' -> In x (inter s s'). - Proof. - unfold inter, In; simpl; rewrite Raw.inter_in; intuition. - Qed. + Proof. wrap inter inter_in. Qed. Lemma diff_1 : In x (diff s s') -> In x s. - Proof. - unfold diff, In; simpl; rewrite Raw.diff_in; intuition. - Qed. - + Proof. wrap diff diff_in. Qed. Lemma diff_2 : In x (diff s s') -> ~ In x s'. - Proof. - unfold diff, In; simpl; rewrite Raw.diff_in; intuition. - Qed. - + Proof. wrap diff diff_in. Qed. Lemma diff_3 : In x s -> ~ In x s' -> In x (diff s s'). - Proof. - unfold diff, In; simpl; rewrite Raw.diff_in; intuition. - Qed. + Proof. wrap diff diff_in. Qed. - Lemma fold_1 : forall (A : Set) (i : A) (f : elt -> A -> A), - fold A f s i = fold_left (fun a e => f e a) (elements s) i. - Proof. - unfold fold, elements; intros; apply Raw.fold_1; auto. - Qed. + Lemma fold_1 : forall (A : Type) (i : A) (f : elt -> A -> A), + fold f s i = fold_left (fun a e => f e a) (elements s) i. + Proof. unfold fold, elements; intros; apply fold_1; auto. Qed. Lemma cardinal_1 : cardinal s = length (elements s). Proof. - unfold cardinal, elements; intros; apply Raw.cardinal_elements_1; auto. + unfold cardinal, elements; intros; apply elements_cardinal; auto. Qed. Section Filter. Variable f : elt -> bool. Lemma filter_1 : compat_bool E.eq f -> In x (filter f s) -> In x s. - Proof. - intro; unfold filter, In; simpl; rewrite Raw.filter_in; intuition. - Qed. - + Proof. intro. wrap filter filter_in. Qed. Lemma filter_2 : compat_bool E.eq f -> In x (filter f s) -> f x = true. - Proof. - intro; unfold filter, In; simpl; rewrite Raw.filter_in; intuition. - Qed. - + Proof. intro. wrap filter filter_in. Qed. Lemma filter_3 : compat_bool E.eq f -> In x s -> f x = true -> In x (filter f s). - Proof. - intro; unfold filter, In; simpl; rewrite Raw.filter_in; intuition. - Qed. + Proof. intro. wrap filter filter_in. Qed. Lemma for_all_1 : compat_bool E.eq f -> For_all (fun x => f x = true) s -> for_all f s = true. - Proof. exact (Raw.for_all_1 f s). Qed. + Proof. exact (@for_all_1 f s). Qed. Lemma for_all_2 : compat_bool E.eq f -> for_all f s = true -> For_all (fun x => f x = true) s. - Proof. exact (Raw.for_all_2 f s). Qed. + Proof. exact (@for_all_2 f s). Qed. Lemma exists_1 : compat_bool E.eq f -> Exists (fun x => f x = true) s -> exists_ f s = true. - Proof. exact (Raw.exists_1 f s). Qed. + Proof. exact (@exists_1 f s). Qed. Lemma exists_2 : compat_bool E.eq f -> exists_ f s = true -> Exists (fun x => f x = true) s. - Proof. exact (Raw.exists_2 f s). Qed. + Proof. exact (@exists_2 f s). Qed. Lemma partition_1 : compat_bool E.eq f -> Equal (fst (partition f s)) (filter f s). Proof. unfold partition, filter, Equal, In; simpl ;intros H a. - rewrite Raw.partition_in_1; auto. - rewrite Raw.filter_in; intuition. + rewrite partition_in_1, filter_in; intuition. Qed. Lemma partition_2 : compat_bool E.eq f -> Equal (snd (partition f s)) (filter (fun x => negb (f x)) s). Proof. unfold partition, filter, Equal, In; simpl ;intros H a. - rewrite Raw.partition_in_2; auto. - rewrite Raw.filter_in; intuition. - red; intros. - f_equal; auto. - destruct (f a); auto. + rewrite partition_in_2, filter_in; intuition. + rewrite H2; auto. destruct (f a); auto. + red; intros; f_equal. + rewrite (H _ _ H0); auto. Qed. End Filter. Lemma elements_1 : In x s -> InA E.eq x (elements s). - Proof. - unfold elements, In; rewrite Raw.elements_in; auto. - Qed. - + Proof. wrap elements elements_in. Qed. Lemma elements_2 : InA E.eq x (elements s) -> In x s. - Proof. - unfold elements, In; rewrite Raw.elements_in; auto. - Qed. - + Proof. wrap elements elements_in. Qed. Lemma elements_3 : sort E.lt (elements s). - Proof. exact (Raw.elements_sort _ (is_bst s)). Qed. + Proof. exact (elements_sort (is_bst s)). Qed. + Lemma elements_3w : NoDupA E.eq (elements s). + Proof. exact (elements_nodup (is_bst s)). Qed. Lemma min_elt_1 : min_elt s = Some x -> In x s. - Proof. exact (Raw.min_elt_1 s x). Qed. + Proof. exact (@min_elt_1 s x). Qed. Lemma min_elt_2 : min_elt s = Some x -> In y s -> ~ E.lt y x. - Proof. exact (Raw.min_elt_2 s x y (is_bst s)). Qed. + Proof. exact (@min_elt_2 s x y (is_bst s)). Qed. Lemma min_elt_3 : min_elt s = None -> Empty s. - Proof. exact (Raw.min_elt_3 s). Qed. + Proof. exact (@min_elt_3 s). Qed. Lemma max_elt_1 : max_elt s = Some x -> In x s. - Proof. exact (Raw.max_elt_1 s x). Qed. + Proof. exact (@max_elt_1 s x). Qed. Lemma max_elt_2 : max_elt s = Some x -> In y s -> ~ E.lt x y. - Proof. exact (Raw.max_elt_2 s x y (is_bst s)). Qed. + Proof. exact (@max_elt_2 s x y (is_bst s)). Qed. Lemma max_elt_3 : max_elt s = None -> Empty s. - Proof. exact (Raw.max_elt_3 s). Qed. + Proof. exact (@max_elt_3 s). Qed. Lemma choose_1 : choose s = Some x -> In x s. - Proof. exact (Raw.choose_1 s x). Qed. + Proof. exact (@choose_1 s x). Qed. Lemma choose_2 : choose s = None -> Empty s. - Proof. exact (Raw.choose_2 s). Qed. + Proof. exact (@choose_2 s). Qed. + Lemma choose_3 : choose s = Some x -> choose s' = Some y -> + Equal s s' -> E.eq x y. + Proof. exact (@choose_3 _ _ (is_bst s) (is_bst s') x y). Qed. Lemma eq_refl : eq s s. - Proof. exact (Raw.eq_refl s). Qed. + Proof. exact (eq_refl s). Qed. Lemma eq_sym : eq s s' -> eq s' s. - Proof. exact (Raw.eq_sym s s'). Qed. + Proof. exact (@eq_sym s s'). Qed. Lemma eq_trans : eq s s' -> eq s' s'' -> eq s s''. - Proof. exact (Raw.eq_trans s s' s''). Qed. + Proof. exact (@eq_trans s s' s''). Qed. Lemma lt_trans : lt s s' -> lt s' s'' -> lt s s''. - Proof. exact (Raw.lt_trans s s' s''). Qed. + Proof. exact (@lt_trans s s' s''). Qed. Lemma lt_not_eq : lt s s' -> ~eq s s'. - Proof. exact (Raw.lt_not_eq _ _ (is_bst s) (is_bst s')). Qed. + Proof. exact (@lt_not_eq _ _ (is_bst s) (is_bst s')). Qed. End Specs. End IntMake. @@ -2897,4 +2053,3 @@ End IntMake. Module Make (X: OrderedType) <: S with Module E := X :=IntMake(Z_as_Int)(X). - diff --git a/theories/FSets/FSetBridge.v b/theories/FSets/FSetBridge.v index 08985cfc..0622451f 100644 --- a/theories/FSets/FSetBridge.v +++ b/theories/FSets/FSetBridge.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: FSetBridge.v 8834 2006-05-20 00:41:35Z letouzey $ *) +(* $Id: FSetBridge.v 10601 2008-02-28 00:20:33Z letouzey $ *) (** * Finite sets library *) @@ -27,7 +27,7 @@ Module DepOfNodep (M: S) <: Sdep with Module E := M.E. Definition empty : {s : t | Empty s}. Proof. - exists empty; auto. + exists empty; auto with set. Qed. Definition is_empty : forall s : t, {Empty s} + {~ Empty s}. @@ -66,12 +66,12 @@ Module DepOfNodep (M: S) <: Sdep with Module E := M.E. {s' : t | forall y : elt, In y s' <-> ~ E.eq x y /\ In y s}. Proof. intros; exists (remove x s); intuition. - absurd (In x (remove x s)); auto. + absurd (In x (remove x s)); auto with set. apply In_1 with y; auto. elim (ME.eq_dec x y); intros; auto. - absurd (In x (remove x s)); auto. + absurd (In x (remove x s)); auto with set. apply In_1 with y; auto. - eauto. + eauto with set. Qed. Definition union : @@ -83,14 +83,14 @@ Module DepOfNodep (M: S) <: Sdep with Module E := M.E. Definition inter : forall s s' : t, {s'' : t | forall x : elt, In x s'' <-> In x s /\ In x s'}. Proof. - intros; exists (inter s s'); intuition; eauto. + intros; exists (inter s s'); intuition; eauto with set. Qed. Definition diff : forall s s' : t, {s'' : t | forall x : elt, In x s'' <-> In x s /\ ~ In x s'}. Proof. - intros; exists (diff s s'); intuition; eauto. - absurd (In x s'); eauto. + intros; exists (diff s s'); intuition; eauto with set. + absurd (In x s'); eauto with set. Qed. Definition equal : forall s s' : t, {Equal s s'} + {~ Equal s s'}. @@ -115,7 +115,7 @@ Module DepOfNodep (M: S) <: Sdep with Module E := M.E. Defined. Definition fold : - forall (A : Set) (f : elt -> A -> A) (s : t) (i : A), + forall (A : Type) (f : elt -> A -> A) (s : t) (i : A), {r : A | let (l,_) := elements s in r = fold_left (fun a e => f e a) l i}. Proof. @@ -150,7 +150,7 @@ Module DepOfNodep (M: S) <: Sdep with Module E := M.E. exists (filter (fdec Pdec) s). intro H; assert (compat_bool E.eq (fdec Pdec)); auto. intuition. - eauto. + eauto with set. generalize (filter_2 H0 H1). unfold fdec in |- *. case (Pdec x); intuition. @@ -226,7 +226,7 @@ Module DepOfNodep (M: S) <: Sdep with Module E := M.E. generalize H4; unfold For_all, Equal in |- *; intuition. elim (H0 x); intros. assert (fdec Pdec x = true). - eauto. + eapply filter_2; eauto with set. generalize H8; unfold fdec in |- *; case (Pdec x); intuition. inversion H9. generalize H; unfold For_all, Equal in |- *; intuition. @@ -238,8 +238,8 @@ Module DepOfNodep (M: S) <: Sdep with Module E := M.E. set (b := fdec Pdec x) in *; generalize (refl_equal b); pattern b at -1 in |- *; case b; unfold b in |- *; [ left | right ]. - elim (H4 x); intros _ B; apply B; auto. - elim (H x); intros _ B; apply B; auto. + elim (H4 x); intros _ B; apply B; auto with set. + elim (H x); intros _ B; apply B; auto with set. apply filter_3; auto. rewrite H5; auto. eapply (filter_1 (s:=s) (x:=x) H2); elim (H4 x); intros B _; apply B; @@ -247,12 +247,63 @@ Module DepOfNodep (M: S) <: Sdep with Module E := M.E. eapply (filter_1 (s:=s) (x:=x) H3); elim (H x); intros B _; apply B; auto. Qed. + Definition choose_aux: forall s : t, + { x : elt | M.choose s = Some x } + { M.choose s = None }. + Proof. + intros. + destruct (M.choose s); [left | right]; auto. + exists e; auto. + Qed. + Definition choose : forall s : t, {x : elt | In x s} + {Empty s}. - Proof. - intros. - generalize (choose_1 (s:=s)) (choose_2 (s:=s)). - case (choose s); [ left | right ]; auto. - exists e; auto. + Proof. + intros; destruct (choose_aux s) as [(x,Hx)|H]. + left; exists x; apply choose_1; auto. + right; apply choose_2; auto. + Defined. + + Lemma choose_ok1 : + forall s x, M.choose s = Some x <-> exists H:In x s, + choose s = inleft _ (exist (fun x => In x s) x H). + Proof. + intros s x. + unfold choose; split; intros. + destruct (choose_aux s) as [(y,Hy)|H']; try congruence. + replace x with y in * by congruence. + exists (choose_1 Hy); auto. + destruct H. + destruct (choose_aux s) as [(y,Hy)|H']; congruence. + Qed. + + Lemma choose_ok2 : + forall s, M.choose s = None <-> exists H:Empty s, + choose s = inright _ H. + Proof. + intros s. + unfold choose; split; intros. + destruct (choose_aux s) as [(y,Hy)|H']; try congruence. + exists (choose_2 H'); auto. + destruct H. + destruct (choose_aux s) as [(y,Hy)|H']; congruence. + Qed. + + Lemma choose_equal : forall s s', Equal s s' -> + match choose s, choose s' with + | inleft (exist x _), inleft (exist x' _) => E.eq x x' + | inright _, inright _ => True + | _, _ => False + end. + Proof. + intros. + generalize (@M.choose_1 s)(@M.choose_2 s) + (@M.choose_1 s')(@M.choose_2 s')(@M.choose_3 s s') + (choose_ok1 s)(choose_ok2 s)(choose_ok1 s')(choose_ok2 s'). + destruct (choose s) as [(x,Hx)|Hx]; destruct (choose s') as [(x',Hx')|Hx']; auto; intros. + apply H4; auto. + rewrite H5; exists Hx; auto. + rewrite H7; exists Hx'; auto. + apply Hx' with x; unfold Equal in H; rewrite <-H; auto. + apply Hx with x'; unfold Equal in H; rewrite H; auto. Qed. Definition min_elt : @@ -391,6 +442,15 @@ Module NodepOfDep (M: Sdep) <: S with Module E := M.E. intro s; unfold choose in |- *; case (M.choose s); auto. simple destruct s0; intros; discriminate H. Qed. + + Lemma choose_3 : forall s s' x x', + choose s = Some x -> choose s' = Some x' -> Equal s s' -> E.eq x x'. + Proof. + unfold choose; intros. + generalize (M.choose_equal H1); clear H1. + destruct (M.choose s) as [(?,?)|?]; destruct (M.choose s') as [(?,?)|?]; + simpl; auto; congruence. + Qed. Definition elements (s : t) : list elt := let (l, _) := elements s in l. @@ -408,6 +468,10 @@ Module NodepOfDep (M: Sdep) <: S with Module E := M.E. Proof. intros; unfold elements in |- *; case (M.elements s); firstorder. Qed. + Hint Resolve elements_3. + + Lemma elements_3w : forall s : t, NoDupA E.eq (elements s). + Proof. auto. Qed. Definition min_elt (s : t) : option elt := match min_elt s with @@ -578,11 +642,11 @@ Module NodepOfDep (M: Sdep) <: S with Module E := M.E. destruct (M.elements s); auto. Qed. - Definition fold (B : Set) (f : elt -> B -> B) (i : t) + Definition fold (B : Type) (f : elt -> B -> B) (i : t) (s : B) : B := let (fold, _) := fold f i s in fold. Lemma fold_1 : - forall (s : t) (A : Set) (i : A) (f : elt -> A -> A), + forall (s : t) (A : Type) (i : A) (f : elt -> A -> A), fold f s i = fold_left (fun a e => f e a) (elements s) i. Proof. intros; unfold fold in |- *; case (M.fold f s i); unfold elements in *; diff --git a/theories/FSets/FSetDecide.v b/theories/FSets/FSetDecide.v new file mode 100644 index 00000000..0639c1f1 --- /dev/null +++ b/theories/FSets/FSetDecide.v @@ -0,0 +1,841 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id: FSetDecide.v 11064 2008-06-06 17:00:52Z letouzey $ *) + +(**************************************************************) +(* FSetDecide.v *) +(* *) +(* Author: Aaron Bohannon *) +(**************************************************************) + +(** This file implements a decision procedure for a certain + class of propositions involving finite sets. *) + +Require Import Decidable DecidableTypeEx FSetFacts. + +(** First, a version for Weak Sets *) + +Module WDecide (E : DecidableType)(Import M : WSfun E). + Module F := FSetFacts.WFacts E M. + +(** * Overview + This functor defines the tactic [fsetdec], which will + solve any valid goal of the form +<< + forall s1 ... sn, + forall x1 ... xm, + P1 -> ... -> Pk -> P +>> + where [P]'s are defined by the grammar: +<< + +P ::= +| Q +| Empty F +| Subset F F' +| Equal F F' + +Q ::= +| E.eq X X' +| In X F +| Q /\ Q' +| Q \/ Q' +| Q -> Q' +| Q <-> Q' +| ~ Q +| True +| False + +F ::= +| S +| empty +| singleton X +| add X F +| remove X F +| union F F' +| inter F F' +| diff F F' + +X ::= x1 | ... | xm +S ::= s1 | ... | sn + +>> + +The tactic will also work on some goals that vary slightly from +the above form: +- The variables and hypotheses may be mixed in any order and may + have already been introduced into the context. Moreover, + there may be additional, unrelated hypotheses mixed in (these + will be ignored). +- A conjunction of hypotheses will be handled as easily as + separate hypotheses, i.e., [P1 /\ P2 -> P] can be solved iff + [P1 -> P2 -> P] can be solved. +- [fsetdec] should solve any goal if the FSet-related hypotheses + are contradictory. +- [fsetdec] will first perform any necessary zeta and beta + reductions and will invoke [subst] to eliminate any Coq + equalities between finite sets or their elements. +- If [E.eq] is convertible with Coq's equality, it will not + matter which one is used in the hypotheses or conclusion. +- The tactic can solve goals where the finite sets or set + elements are expressed by Coq terms that are more complicated + than variables. However, non-local definitions are not + expanded, and Coq equalities between non-variable terms are + not used. For example, this goal will be solved: +<< + forall (f : t -> t), + forall (g : elt -> elt), + forall (s1 s2 : t), + forall (x1 x2 : elt), + Equal s1 (f s2) -> + E.eq x1 (g (g x2)) -> + In x1 s1 -> + In (g (g x2)) (f s2) +>> + This one will not be solved: +<< + forall (f : t -> t), + forall (g : elt -> elt), + forall (s1 s2 : t), + forall (x1 x2 : elt), + Equal s1 (f s2) -> + E.eq x1 (g x2) -> + In x1 s1 -> + g x2 = g (g x2) -> + In (g (g x2)) (f s2) +>> +*) + + (** * Facts and Tactics for Propositional Logic + These lemmas and tactics are in a module so that they do + not affect the namespace if you import the enclosing + module [Decide]. *) + Module FSetLogicalFacts. + Require Export Decidable. + Require Export Setoid. + + (** ** Lemmas and Tactics About Decidable Propositions *) + + (** ** Propositional Equivalences Involving Negation + These are all written with the unfolded form of + negation, since I am not sure if setoid rewriting will + always perform conversion. *) + + (** ** Tactics for Negations *) + + Tactic Notation "fold" "any" "not" := + repeat ( + match goal with + | H: context [?P -> False] |- _ => + fold (~ P) in H + | |- context [?P -> False] => + fold (~ P) + end). + + (** [push not using db] will pushes all negations to the + leaves of propositions in the goal, using the lemmas in + [db] to assist in checking the decidability of the + propositions involved. If [using db] is omitted, then + [core] will be used. Additional versions are provided + to manipulate the hypotheses or the hypotheses and goal + together. + + XXX: This tactic and the similar subsequent ones should + have been defined using [autorewrite]. However, dealing + with multiples rewrite sites and side-conditions is + done more cleverly with the following explicit + analysis of goals. *) + + Ltac or_not_l_iff P Q tac := + (rewrite (or_not_l_iff_1 P Q) by tac) || + (rewrite (or_not_l_iff_2 P Q) by tac). + + Ltac or_not_r_iff P Q tac := + (rewrite (or_not_r_iff_1 P Q) by tac) || + (rewrite (or_not_r_iff_2 P Q) by tac). + + Ltac or_not_l_iff_in P Q H tac := + (rewrite (or_not_l_iff_1 P Q) in H by tac) || + (rewrite (or_not_l_iff_2 P Q) in H by tac). + + Ltac or_not_r_iff_in P Q H tac := + (rewrite (or_not_r_iff_1 P Q) in H by tac) || + (rewrite (or_not_r_iff_2 P Q) in H by tac). + + Tactic Notation "push" "not" "using" ident(db) := + let dec := solve_decidable using db in + unfold not, iff; + repeat ( + match goal with + | |- context [True -> False] => rewrite not_true_iff + | |- context [False -> False] => rewrite not_false_iff + | |- context [(?P -> False) -> False] => rewrite (not_not_iff P) by dec + | |- context [(?P -> False) -> (?Q -> False)] => + rewrite (contrapositive P Q) by dec + | |- context [(?P -> False) \/ ?Q] => or_not_l_iff P Q dec + | |- context [?P \/ (?Q -> False)] => or_not_r_iff P Q dec + | |- context [(?P -> False) -> ?Q] => rewrite (imp_not_l P Q) by dec + | |- context [?P \/ ?Q -> False] => rewrite (not_or_iff P Q) + | |- context [?P /\ ?Q -> False] => rewrite (not_and_iff P Q) + | |- context [(?P -> ?Q) -> False] => rewrite (not_imp_iff P Q) by dec + end); + fold any not. + + Tactic Notation "push" "not" := + push not using core. + + Tactic Notation + "push" "not" "in" "*" "|-" "using" ident(db) := + let dec := solve_decidable using db in + unfold not, iff in * |-; + repeat ( + match goal with + | H: context [True -> False] |- _ => rewrite not_true_iff in H + | H: context [False -> False] |- _ => rewrite not_false_iff in H + | H: context [(?P -> False) -> False] |- _ => + rewrite (not_not_iff P) in H by dec + | H: context [(?P -> False) -> (?Q -> False)] |- _ => + rewrite (contrapositive P Q) in H by dec + | H: context [(?P -> False) \/ ?Q] |- _ => or_not_l_iff_in P Q H dec + | H: context [?P \/ (?Q -> False)] |- _ => or_not_r_iff_in P Q H dec + | H: context [(?P -> False) -> ?Q] |- _ => + rewrite (imp_not_l P Q) in H by dec + | H: context [?P \/ ?Q -> False] |- _ => rewrite (not_or_iff P Q) in H + | H: context [?P /\ ?Q -> False] |- _ => rewrite (not_and_iff P Q) in H + | H: context [(?P -> ?Q) -> False] |- _ => + rewrite (not_imp_iff P Q) in H by dec + end); + fold any not. + + Tactic Notation "push" "not" "in" "*" "|-" := + push not in * |- using core. + + Tactic Notation "push" "not" "in" "*" "using" ident(db) := + push not using db; push not in * |- using db. + Tactic Notation "push" "not" "in" "*" := + push not in * using core. + + (** A simple test case to see how this works. *) + Lemma test_push : forall P Q R : Prop, + decidable P -> + decidable Q -> + (~ True) -> + (~ False) -> + (~ ~ P) -> + (~ (P /\ Q) -> ~ R) -> + ((P /\ Q) \/ ~ R) -> + (~ (P /\ Q) \/ R) -> + (R \/ ~ (P /\ Q)) -> + (~ R \/ (P /\ Q)) -> + (~ P -> R) -> + (~ ((R -> P) \/ (Q -> R))) -> + (~ (P /\ R)) -> + (~ (P -> R)) -> + True. + Proof. + intros. push not in *. + (* note that ~(R->P) remains (since R isnt decidable) *) + tauto. + Qed. + + (** [pull not using db] will pull as many negations as + possible toward the top of the propositions in the goal, + using the lemmas in [db] to assist in checking the + decidability of the propositions involved. If [using + db] is omitted, then [core] will be used. Additional + versions are provided to manipulate the hypotheses or + the hypotheses and goal together. *) + + Tactic Notation "pull" "not" "using" ident(db) := + let dec := solve_decidable using db in + unfold not, iff; + repeat ( + match goal with + | |- context [True -> False] => rewrite not_true_iff + | |- context [False -> False] => rewrite not_false_iff + | |- context [(?P -> False) -> False] => rewrite (not_not_iff P) by dec + | |- context [(?P -> False) -> (?Q -> False)] => + rewrite (contrapositive P Q) by dec + | |- context [(?P -> False) \/ ?Q] => or_not_l_iff P Q dec + | |- context [?P \/ (?Q -> False)] => or_not_r_iff P Q dec + | |- context [(?P -> False) -> ?Q] => rewrite (imp_not_l P Q) by dec + | |- context [(?P -> False) /\ (?Q -> False)] => + rewrite <- (not_or_iff P Q) + | |- context [?P -> ?Q -> False] => rewrite <- (not_and_iff P Q) + | |- context [?P /\ (?Q -> False)] => rewrite <- (not_imp_iff P Q) by dec + | |- context [(?Q -> False) /\ ?P] => + rewrite <- (not_imp_rev_iff P Q) by dec + end); + fold any not. + + Tactic Notation "pull" "not" := + pull not using core. + + Tactic Notation + "pull" "not" "in" "*" "|-" "using" ident(db) := + let dec := solve_decidable using db in + unfold not, iff in * |-; + repeat ( + match goal with + | H: context [True -> False] |- _ => rewrite not_true_iff in H + | H: context [False -> False] |- _ => rewrite not_false_iff in H + | H: context [(?P -> False) -> False] |- _ => + rewrite (not_not_iff P) in H by dec + | H: context [(?P -> False) -> (?Q -> False)] |- _ => + rewrite (contrapositive P Q) in H by dec + | H: context [(?P -> False) \/ ?Q] |- _ => or_not_l_iff_in P Q H dec + | H: context [?P \/ (?Q -> False)] |- _ => or_not_r_iff_in P Q H dec + | H: context [(?P -> False) -> ?Q] |- _ => + rewrite (imp_not_l P Q) in H by dec + | H: context [(?P -> False) /\ (?Q -> False)] |- _ => + rewrite <- (not_or_iff P Q) in H + | H: context [?P -> ?Q -> False] |- _ => + rewrite <- (not_and_iff P Q) in H + | H: context [?P /\ (?Q -> False)] |- _ => + rewrite <- (not_imp_iff P Q) in H by dec + | H: context [(?Q -> False) /\ ?P] |- _ => + rewrite <- (not_imp_rev_iff P Q) in H by dec + end); + fold any not. + + Tactic Notation "pull" "not" "in" "*" "|-" := + pull not in * |- using core. + + Tactic Notation "pull" "not" "in" "*" "using" ident(db) := + pull not using db; pull not in * |- using db. + Tactic Notation "pull" "not" "in" "*" := + pull not in * using core. + + (** A simple test case to see how this works. *) + Lemma test_pull : forall P Q R : Prop, + decidable P -> + decidable Q -> + (~ True) -> + (~ False) -> + (~ ~ P) -> + (~ (P /\ Q) -> ~ R) -> + ((P /\ Q) \/ ~ R) -> + (~ (P /\ Q) \/ R) -> + (R \/ ~ (P /\ Q)) -> + (~ R \/ (P /\ Q)) -> + (~ P -> R) -> + (~ (R -> P) /\ ~ (Q -> R)) -> + (~ P \/ ~ R) -> + (P /\ ~ R) -> + (~ R /\ P) -> + True. + Proof. + intros. pull not in *. tauto. + Qed. + + End FSetLogicalFacts. + Import FSetLogicalFacts. + + (** * Auxiliary Tactics + Again, these lemmas and tactics are in a module so that + they do not affect the namespace if you import the + enclosing module [Decide]. *) + Module FSetDecideAuxiliary. + + (** ** Generic Tactics + We begin by defining a few generic, useful tactics. *) + + (** [if t then t1 else t2] executes [t] and, if it does not + fail, then [t1] will be applied to all subgoals + produced. If [t] fails, then [t2] is executed. *) + Tactic Notation + "if" tactic(t) + "then" tactic(t1) + "else" tactic(t2) := + first [ t; first [ t1 | fail 2 ] | t2 ]. + + (** [prop P holds by t] succeeds (but does not modify the + goal or context) if the proposition [P] can be proved by + [t] in the current context. Otherwise, the tactic + fails. *) + Tactic Notation "prop" constr(P) "holds" "by" tactic(t) := + let H := fresh in + assert P as H by t; + clear H. + + (** This tactic acts just like [assert ... by ...] but will + fail if the context already contains the proposition. *) + Tactic Notation "assert" "new" constr(e) "by" tactic(t) := + match goal with + | H: e |- _ => fail 1 + | _ => assert e by t + end. + + (** [subst++] is similar to [subst] except that + - it never fails (as [subst] does on recursive + equations), + - it substitutes locally defined variable for their + definitions, + - it performs beta reductions everywhere, which may + arise after substituting a locally defined function + for its definition. + *) + Tactic Notation "subst" "++" := + repeat ( + match goal with + | x : _ |- _ => subst x + end); + cbv zeta beta in *. + + (** [decompose records] calls [decompose record H] on every + relevant hypothesis [H]. *) + Tactic Notation "decompose" "records" := + repeat ( + match goal with + | H: _ |- _ => progress (decompose record H); clear H + end). + + (** ** Discarding Irrelevant Hypotheses + We will want to clear the context of any + non-FSet-related hypotheses in order to increase the + speed of the tactic. To do this, we will need to be + able to decide which are relevant. We do this by making + a simple inductive definition classifying the + propositions of interest. *) + + Inductive FSet_elt_Prop : Prop -> Prop := + | eq_Prop : forall (S : Set) (x y : S), + FSet_elt_Prop (x = y) + | eq_elt_prop : forall x y, + FSet_elt_Prop (E.eq x y) + | In_elt_prop : forall x s, + FSet_elt_Prop (In x s) + | True_elt_prop : + FSet_elt_Prop True + | False_elt_prop : + FSet_elt_Prop False + | conj_elt_prop : forall P Q, + FSet_elt_Prop P -> + FSet_elt_Prop Q -> + FSet_elt_Prop (P /\ Q) + | disj_elt_prop : forall P Q, + FSet_elt_Prop P -> + FSet_elt_Prop Q -> + FSet_elt_Prop (P \/ Q) + | impl_elt_prop : forall P Q, + FSet_elt_Prop P -> + FSet_elt_Prop Q -> + FSet_elt_Prop (P -> Q) + | not_elt_prop : forall P, + FSet_elt_Prop P -> + FSet_elt_Prop (~ P). + + Inductive FSet_Prop : Prop -> Prop := + | elt_FSet_Prop : forall P, + FSet_elt_Prop P -> + FSet_Prop P + | Empty_FSet_Prop : forall s, + FSet_Prop (Empty s) + | Subset_FSet_Prop : forall s1 s2, + FSet_Prop (Subset s1 s2) + | Equal_FSet_Prop : forall s1 s2, + FSet_Prop (Equal s1 s2). + + (** Here is the tactic that will throw away hypotheses that + are not useful (for the intended scope of the [fsetdec] + tactic). *) + Hint Constructors FSet_elt_Prop FSet_Prop : FSet_Prop. + Ltac discard_nonFSet := + decompose records; + repeat ( + match goal with + | H : ?P |- _ => + if prop (FSet_Prop P) holds by + (auto 100 with FSet_Prop) + then fail + else clear H + end). + + (** ** Turning Set Operators into Propositional Connectives + The lemmas from [FSetFacts] will be used to break down + set operations into propositional formulas built over + the predicates [In] and [E.eq] applied only to + variables. We are going to use them with [autorewrite]. + *) + + Hint Rewrite + F.empty_iff F.singleton_iff F.add_iff F.remove_iff + F.union_iff F.inter_iff F.diff_iff + : set_simpl. + + (** ** Decidability of FSet Propositions *) + + (** [In] is decidable. *) + Lemma dec_In : forall x s, + decidable (In x s). + Proof. + red; intros; generalize (F.mem_iff s x); case (mem x s); intuition. + Qed. + + (** [E.eq] is decidable. *) + Lemma dec_eq : forall (x y : E.t), + decidable (E.eq x y). + Proof. + red; intros x y; destruct (E.eq_dec x y); auto. + Qed. + + (** The hint database [FSet_decidability] will be given to + the [push_neg] tactic from the module [Negation]. *) + Hint Resolve dec_In dec_eq : FSet_decidability. + + (** ** Normalizing Propositions About Equality + We have to deal with the fact that [E.eq] may be + convertible with Coq's equality. Thus, we will find the + following tactics useful to replace one form with the + other everywhere. *) + + (** The next tactic, [Logic_eq_to_E_eq], mentions the term + [E.t]; thus, we must ensure that [E.t] is used in favor + of any other convertible but syntactically distinct + term. *) + Ltac change_to_E_t := + repeat ( + match goal with + | H : ?T |- _ => + progress (change T with E.t in H); + repeat ( + match goal with + | J : _ |- _ => progress (change T with E.t in J) + | |- _ => progress (change T with E.t) + end ) + end). + + (** These two tactics take us from Coq's built-in equality + to [E.eq] (and vice versa) when possible. *) + + Ltac Logic_eq_to_E_eq := + repeat ( + match goal with + | H: _ |- _ => + progress (change (@Logic.eq E.t) with E.eq in H) + | |- _ => + progress (change (@Logic.eq E.t) with E.eq) + end). + + Ltac E_eq_to_Logic_eq := + repeat ( + match goal with + | H: _ |- _ => + progress (change E.eq with (@Logic.eq E.t) in H) + | |- _ => + progress (change E.eq with (@Logic.eq E.t)) + end). + + (** This tactic works like the built-in tactic [subst], but + at the level of set element equality (which may not be + the convertible with Coq's equality). *) + Ltac substFSet := + repeat ( + match goal with + | H: E.eq ?x ?y |- _ => rewrite H in *; clear H + end). + + (** ** Considering Decidability of Base Propositions + This tactic adds assertions about the decidability of + [E.eq] and [In] to the context. This is necessary for + the completeness of the [fsetdec] tactic. However, in + order to minimize the cost of proof search, we should be + careful to not add more than we need. Once negations + have been pushed to the leaves of the propositions, we + only need to worry about decidability for those base + propositions that appear in a negated form. *) + Ltac assert_decidability := + (** We actually don't want these rules to fire if the + syntactic context in the patterns below is trivially + empty, but we'll just do some clean-up at the + afterward. *) + repeat ( + match goal with + | H: context [~ E.eq ?x ?y] |- _ => + assert new (E.eq x y \/ ~ E.eq x y) by (apply dec_eq) + | H: context [~ In ?x ?s] |- _ => + assert new (In x s \/ ~ In x s) by (apply dec_In) + | |- context [~ E.eq ?x ?y] => + assert new (E.eq x y \/ ~ E.eq x y) by (apply dec_eq) + | |- context [~ In ?x ?s] => + assert new (In x s \/ ~ In x s) by (apply dec_In) + end); + (** Now we eliminate the useless facts we added (because + they would likely be very harmful to performance). *) + repeat ( + match goal with + | _: ~ ?P, H : ?P \/ ~ ?P |- _ => clear H + end). + + (** ** Handling [Empty], [Subset], and [Equal] + This tactic instantiates universally quantified + hypotheses (which arise from the unfolding of [Empty], + [Subset], and [Equal]) for each of the set element + expressions that is involved in some membership or + equality fact. Then it throws away those hypotheses, + which should no longer be needed. *) + Ltac inst_FSet_hypotheses := + repeat ( + match goal with + | H : forall a : E.t, _, + _ : context [ In ?x _ ] |- _ => + let P := type of (H x) in + assert new P by (exact (H x)) + | H : forall a : E.t, _ + |- context [ In ?x _ ] => + let P := type of (H x) in + assert new P by (exact (H x)) + | H : forall a : E.t, _, + _ : context [ E.eq ?x _ ] |- _ => + let P := type of (H x) in + assert new P by (exact (H x)) + | H : forall a : E.t, _ + |- context [ E.eq ?x _ ] => + let P := type of (H x) in + assert new P by (exact (H x)) + | H : forall a : E.t, _, + _ : context [ E.eq _ ?x ] |- _ => + let P := type of (H x) in + assert new P by (exact (H x)) + | H : forall a : E.t, _ + |- context [ E.eq _ ?x ] => + let P := type of (H x) in + assert new P by (exact (H x)) + end); + repeat ( + match goal with + | H : forall a : E.t, _ |- _ => + clear H + end). + + (** ** The Core [fsetdec] Auxiliary Tactics *) + + (** Here is the crux of the proof search. Recursion through + [intuition]! (This will terminate if I correctly + understand the behavior of [intuition].) *) + Ltac fsetdec_rec := + try (match goal with + | H: E.eq ?x ?x -> False |- _ => destruct H + end); + (reflexivity || + contradiction || + (progress substFSet; intuition fsetdec_rec)). + + (** If we add [unfold Empty, Subset, Equal in *; intros;] to + the beginning of this tactic, it will satisfy the same + specification as the [fsetdec] tactic; however, it will + be much slower than necessary without the pre-processing + done by the wrapper tactic [fsetdec]. *) + Ltac fsetdec_body := + inst_FSet_hypotheses; + autorewrite with set_simpl in *; + push not in * using FSet_decidability; + substFSet; + assert_decidability; + auto using E.eq_refl; + (intuition fsetdec_rec) || + fail 1 + "because the goal is beyond the scope of this tactic". + + End FSetDecideAuxiliary. + Import FSetDecideAuxiliary. + + (** * The [fsetdec] Tactic + Here is the top-level tactic (the only one intended for + clients of this library). It's specification is given at + the top of the file. *) + Ltac fsetdec := + (** We first unfold any occurrences of [iff]. *) + unfold iff in *; + (** We fold occurrences of [not] because it is better for + [intros] to leave us with a goal of [~ P] than a goal of + [False]. *) + fold any not; intros; + (** Now we decompose conjunctions, which will allow the + [discard_nonFSet] and [assert_decidability] tactics to + do a much better job. *) + decompose records; + discard_nonFSet; + (** We unfold these defined propositions on finite sets. If + our goal was one of them, then have one more item to + introduce now. *) + unfold Empty, Subset, Equal in *; intros; + (** We now want to get rid of all uses of [=] in favor of + [E.eq]. However, the best way to eliminate a [=] is in + the context is with [subst], so we will try that first. + In fact, we may as well convert uses of [E.eq] into [=] + when possible before we do [subst] so that we can even + more mileage out of it. Then we will convert all + remaining uses of [=] back to [E.eq] when possible. We + use [change_to_E_t] to ensure that we have a canonical + name for set elements, so that [Logic_eq_to_E_eq] will + work properly. *) + change_to_E_t; E_eq_to_Logic_eq; subst++; Logic_eq_to_E_eq; + (** The next optimization is to swap a negated goal with a + negated hypothesis when possible. Any swap will improve + performance by eliminating the total number of + negations, but we will get the maximum benefit if we + swap the goal with a hypotheses mentioning the same set + element, so we try that first. If we reach the fourth + branch below, we attempt any swap. However, to maintain + completeness of this tactic, we can only perform such a + swap with a decidable proposition; hence, we first test + whether the hypothesis is an [FSet_elt_Prop], noting + that any [FSet_elt_Prop] is decidable. *) + pull not using FSet_decidability; + unfold not in *; + match goal with + | H: (In ?x ?r) -> False |- (In ?x ?s) -> False => + contradict H; fsetdec_body + | H: (In ?x ?r) -> False |- (E.eq ?x ?y) -> False => + contradict H; fsetdec_body + | H: (In ?x ?r) -> False |- (E.eq ?y ?x) -> False => + contradict H; fsetdec_body + | H: ?P -> False |- ?Q -> False => + if prop (FSet_elt_Prop P) holds by + (auto 100 with FSet_Prop) + then (contradict H; fsetdec_body) + else fsetdec_body + | |- _ => + fsetdec_body + end. + + (** * Examples *) + + Module FSetDecideTestCases. + + Lemma test_eq_trans_1 : forall x y z s, + E.eq x y -> + ~ ~ E.eq z y -> + In x s -> + In z s. + Proof. fsetdec. Qed. + + Lemma test_eq_trans_2 : forall x y z r s, + In x (singleton y) -> + ~ In z r -> + ~ ~ In z (add y r) -> + In x s -> + In z s. + Proof. fsetdec. Qed. + + Lemma test_eq_neq_trans_1 : forall w x y z s, + E.eq x w -> + ~ ~ E.eq x y -> + ~ E.eq y z -> + In w s -> + In w (remove z s). + Proof. fsetdec. Qed. + + Lemma test_eq_neq_trans_2 : forall w x y z r1 r2 s, + In x (singleton w) -> + ~ In x r1 -> + In x (add y r1) -> + In y r2 -> + In y (remove z r2) -> + In w s -> + In w (remove z s). + Proof. fsetdec. Qed. + + Lemma test_In_singleton : forall x, + In x (singleton x). + Proof. fsetdec. Qed. + + Lemma test_Subset_add_remove : forall x s, + s [<=] (add x (remove x s)). + Proof. fsetdec. Qed. + + Lemma test_eq_disjunction : forall w x y z, + In w (add x (add y (singleton z))) -> + E.eq w x \/ E.eq w y \/ E.eq w z. + Proof. fsetdec. Qed. + + Lemma test_not_In_disj : forall x y s1 s2 s3 s4, + ~ In x (union s1 (union s2 (union s3 (add y s4)))) -> + ~ (In x s1 \/ In x s4 \/ E.eq y x). + Proof. fsetdec. Qed. + + Lemma test_not_In_conj : forall x y s1 s2 s3 s4, + ~ In x (union s1 (union s2 (union s3 (add y s4)))) -> + ~ In x s1 /\ ~ In x s4 /\ ~ E.eq y x. + Proof. fsetdec. Qed. + + Lemma test_iff_conj : forall a x s s', + (In a s' <-> E.eq x a \/ In a s) -> + (In a s' <-> In a (add x s)). + Proof. fsetdec. Qed. + + Lemma test_set_ops_1 : forall x q r s, + (singleton x) [<=] s -> + Empty (union q r) -> + Empty (inter (diff s q) (diff s r)) -> + ~ In x s. + Proof. fsetdec. Qed. + + Lemma eq_chain_test : forall x1 x2 x3 x4 s1 s2 s3 s4, + Empty s1 -> + In x2 (add x1 s1) -> + In x3 s2 -> + ~ In x3 (remove x2 s2) -> + ~ In x4 s3 -> + In x4 (add x3 s3) -> + In x1 s4 -> + Subset (add x4 s4) s4. + Proof. fsetdec. Qed. + + Lemma test_too_complex : forall x y z r s, + E.eq x y -> + (In x (singleton y) -> r [<=] s) -> + In z r -> + In z s. + Proof. + (** [fsetdec] is not intended to solve this directly. *) + intros until s; intros Heq H Hr; lapply H; fsetdec. + Qed. + + Lemma function_test_1 : + forall (f : t -> t), + forall (g : elt -> elt), + forall (s1 s2 : t), + forall (x1 x2 : elt), + Equal s1 (f s2) -> + E.eq x1 (g (g x2)) -> + In x1 s1 -> + In (g (g x2)) (f s2). + Proof. fsetdec. Qed. + + Lemma function_test_2 : + forall (f : t -> t), + forall (g : elt -> elt), + forall (s1 s2 : t), + forall (x1 x2 : elt), + Equal s1 (f s2) -> + E.eq x1 (g x2) -> + In x1 s1 -> + g x2 = g (g x2) -> + In (g (g x2)) (f s2). + Proof. + (** [fsetdec] is not intended to solve this directly. *) + intros until 3. intros g_eq. rewrite <- g_eq. fsetdec. + Qed. + + End FSetDecideTestCases. + +End WDecide. + +Require Import FSetInterface. + +(** Now comes a special version dedicated to full sets. For this + one, only one argument [(M:S)] is necessary. *) + +Module Decide (M : S). + Module D:=OT_as_DT M.E. + Module WD := WDecide D M. + Ltac fsetdec := WD.fsetdec. +End Decide.
\ No newline at end of file diff --git a/theories/FSets/FSetEqProperties.v b/theories/FSets/FSetEqProperties.v index d7062d5a..a397cc28 100644 --- a/theories/FSets/FSetEqProperties.v +++ b/theories/FSets/FSetEqProperties.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: FSetEqProperties.v 8853 2006-05-23 18:17:38Z herbelin $ *) +(* $Id: FSetEqProperties.v 11064 2008-06-06 17:00:52Z letouzey $ *) (** * Finite sets library *) @@ -17,21 +17,12 @@ [mem x s=true] instead of [In x s], [equal s s'=true] instead of [Equal s s'], etc. *) +Require Import FSetProperties Zerob Sumbool Omega DecidableTypeEx. -Require Import FSetProperties. -Require Import Zerob. -Require Import Sumbool. -Require Import Omega. - -Module EqProperties (M:S). +Module WEqProperties (Import E:DecidableType)(M:WSfun E). +Module Import MP := WProperties E M. +Import FM Dec.F. Import M. -Import Logic. (* to unmask [eq] *) -Import Peano. (* to unmask [lt] *) - -Module ME := OrderedTypeFacts E. -Module MP := Properties M. -Import MP. -Import MP.FM. Definition Add := MP.Add. @@ -76,7 +67,7 @@ Qed. Lemma empty_mem: mem x empty=false. Proof. -rewrite <- not_mem_iff; auto. +rewrite <- not_mem_iff; auto with set. Qed. Lemma is_empty_equal_empty: is_empty s = equal s empty. @@ -88,17 +79,17 @@ Qed. Lemma choose_mem_1: choose s=Some x -> mem x s=true. Proof. -auto. +auto with set. Qed. Lemma choose_mem_2: choose s=None -> is_empty s=true. Proof. -auto. +auto with set. Qed. Lemma add_mem_1: mem x (add x s)=true. Proof. -auto. +auto with set. Qed. Lemma add_mem_2: ~E.eq x y -> mem y (add x s)=mem y s. @@ -108,7 +99,7 @@ Qed. Lemma remove_mem_1: mem x (remove x s)=false. Proof. -rewrite <- not_mem_iff; auto. +rewrite <- not_mem_iff; auto with set. Qed. Lemma remove_mem_2: ~E.eq x y -> mem y (remove x s)=mem y s. @@ -216,7 +207,7 @@ Proof. intros. generalize (@choose_1 s) (@choose_2 s). destruct (choose s);intros. -exists e;auto. +exists e;auto with set. generalize (H1 (refl_equal None)); clear H1. intros; rewrite (is_empty_1 H1) in H; discriminate. Qed. @@ -233,7 +224,7 @@ Qed. Lemma add_mem_3: mem y s=true -> mem y (add x s)=true. Proof. -auto. +auto with set. Qed. Lemma add_equal: @@ -260,7 +251,7 @@ Qed. Lemma add_remove: mem x s=true -> equal (add x (remove x s)) s=true. Proof. -intros; apply equal_1; apply add_remove; auto. +intros; apply equal_1; apply add_remove; auto with set. Qed. Lemma remove_add: @@ -275,9 +266,9 @@ Qed. Lemma is_empty_cardinal: is_empty s = zerob (cardinal s). Proof. intros; apply bool_1; split; intros. -rewrite cardinal_1; simpl; auto. +rewrite MP.cardinal_1; simpl; auto with set. assert (cardinal s = 0) by (apply zerob_true_elim; auto). -auto. +auto with set. Qed. (** Properties of [singleton] *) @@ -290,12 +281,12 @@ Qed. Lemma singleton_mem_2: ~E.eq x y -> mem y (singleton x)=false. Proof. intros; rewrite singleton_b. -unfold ME.eqb; destruct (ME.eq_dec x y); intuition. +unfold eqb; destruct (eq_dec x y); intuition. Qed. Lemma singleton_mem_3: mem y (singleton x)=true -> E.eq x y. Proof. -auto. +intros; apply singleton_1; auto with set. Qed. (** Properties of [union] *) @@ -358,7 +349,7 @@ Lemma union_subset_3: subset s s''=true -> subset s' s''=true -> subset (union s s') s''=true. Proof. -intros; apply subset_1; apply union_subset_3; auto. +intros; apply subset_1; apply union_subset_3; auto with set. Qed. (** Properties of [inter] *) @@ -433,7 +424,7 @@ Lemma inter_subset_3: subset s'' s=true -> subset s'' s'=true -> subset s'' (inter s s')=true. Proof. -intros; apply subset_1; apply inter_subset_3; auto. +intros; apply subset_1; apply inter_subset_3; auto with set. Qed. (** Properties of [diff] *) @@ -478,45 +469,37 @@ Hint Resolve equal_mem_1 subset_mem_1 choose_mem_1 add_mem_3 add_equal remove_mem_3 remove_equal : set. -(** General recursion principes based on [cardinal] *) +(** General recursion principle *) -Lemma cardinal_set_rec: forall (P:t->Type), +Lemma set_rec: forall (P:t->Type), (forall s s', equal s s'=true -> P s -> P s') -> (forall s x, mem x s=false -> P s -> P (add x s)) -> - P empty -> forall n s, cardinal s=n -> P s. + P empty -> forall s, P s. Proof. intros. -apply cardinal_induction with n; auto; intros. +apply set_induction; auto; intros. apply X with empty; auto with set. apply X with (add x s0); auto with set. -apply equal_1; intro a; rewrite add_iff; rewrite (H1 a); tauto. +apply equal_1; intro a; rewrite add_iff; rewrite (H0 a); tauto. apply X0; auto with set; apply mem_3; auto. Qed. -Lemma set_rec: forall (P:t->Type), - (forall s s', equal s s'=true -> P s -> P s') -> - (forall s x, mem x s=false -> P s -> P (add x s)) -> - P empty -> forall s, P s. -Proof. -intros;apply cardinal_set_rec with (cardinal s);auto. -Qed. - (** Properties of [fold] *) Lemma exclusive_set : forall s s' x, - ~In x s\/~In x s' <-> mem x s && mem x s'=false. + ~(In x s/\In x s') <-> mem x s && mem x s'=false. Proof. -intros; do 2 rewrite not_mem_iff. +intros; do 2 rewrite mem_iff. destruct (mem x s); destruct (mem x s'); intuition. Qed. Section Fold. -Variables (A:Set)(eqA:A->A->Prop)(st:Setoid_Theory _ eqA). +Variables (A:Type)(eqA:A->A->Prop)(st:Setoid_Theory _ eqA). Variables (f:elt->A->A)(Comp:compat_op E.eq eqA f)(Ass:transpose eqA f). Variables (i:A). Variables (s s':t)(x:elt). -Lemma fold_empty: eqA (fold f empty i) i. +Lemma fold_empty: (fold f empty i) = i. Proof. apply fold_empty; auto. Qed. @@ -524,7 +507,7 @@ Qed. Lemma fold_equal: equal s s'=true -> eqA (fold f s i) (fold f s' i). Proof. -intros; apply fold_equal with (eqA:=eqA); auto. +intros; apply fold_equal with (eqA:=eqA); auto with set. Qed. Lemma fold_add: @@ -537,13 +520,13 @@ Qed. Lemma add_fold: mem x s=true -> eqA (fold f (add x s) i) (fold f s i). Proof. -intros; apply add_fold with (eqA:=eqA); auto. +intros; apply add_fold with (eqA:=eqA); auto with set. Qed. Lemma remove_fold_1: mem x s=true -> eqA (f x (fold f (remove x s) i)) (fold f s i). Proof. -intros; apply remove_fold_1 with (eqA:=eqA); auto. +intros; apply remove_fold_1 with (eqA:=eqA); auto with set. Qed. Lemma remove_fold_2: @@ -581,13 +564,13 @@ Qed. Lemma remove_cardinal_1: forall s x, mem x s=true -> S (cardinal (remove x s))=cardinal s. Proof. -intros; apply remove_cardinal_1; auto. +intros; apply remove_cardinal_1; auto with set. Qed. Lemma remove_cardinal_2: forall s x, mem x s=false -> cardinal (remove x s)=cardinal s. Proof. -auto with set. +intros; apply Equal_cardinal; apply equal_2; auto with set. Qed. Lemma union_cardinal: @@ -601,7 +584,7 @@ Qed. Lemma subset_cardinal: forall s s', subset s s'=true -> cardinal s<=cardinal s'. Proof. -intros; apply subset_cardinal; auto. +intros; apply subset_cardinal; auto with set. Qed. Section Bool. @@ -644,7 +627,7 @@ Proof. intros; apply bool_1; split; intros. destruct (exists_2 Comp H) as (a,(Ha1,Ha2)). apply bool_6. -red; intros; apply (@is_empty_2 _ H0 a); auto. +red; intros; apply (@is_empty_2 _ H0 a); auto with set. generalize (@choose_1 (filter f s)) (@choose_2 (filter f s)). destruct (choose (filter f s)). intros H0 _; apply exists_1; auto. @@ -656,13 +639,30 @@ Qed. Lemma partition_filter_1: forall s, equal (fst (partition f s)) (filter f s)=true. Proof. -auto. +auto with set. Qed. Lemma partition_filter_2: forall s, equal (snd (partition f s)) (filter (fun x => negb (f x)) s)=true. Proof. -auto. +auto with set. +Qed. + +Lemma filter_add_1 : forall s x, f x = true -> + filter f (add x s) [=] add x (filter f s). +Proof. +red; intros; set_iff; do 2 (rewrite filter_iff; auto); set_iff. +intuition. +rewrite <- H; apply Comp; auto. +Qed. + +Lemma filter_add_2 : forall s x, f x = false -> + filter f (add x s) [=] filter f s. +Proof. +red; intros; do 2 (rewrite filter_iff; auto); set_iff. +intuition. +assert (f x = f a) by (apply Comp; auto). +rewrite H in H1; rewrite H2 in H1; discriminate. Qed. Lemma add_filter_1 : forall s s' x, @@ -837,6 +837,8 @@ Section Sum. (** Adding a valuation function on all elements of a set. *) Definition sum (f:elt -> nat)(s:t) := fold (fun x => plus (f x)) s 0. +Notation compat_opL := (compat_op E.eq (@Logic.eq _)). +Notation transposeL := (transpose (@Logic.eq _)). Lemma sum_plus : forall f g, compat_nat E.eq f -> compat_nat E.eq g -> @@ -844,12 +846,12 @@ Lemma sum_plus : Proof. unfold sum. intros f g Hf Hg. -assert (fc : compat_op E.eq (@eq _) (fun x:elt =>plus (f x))). auto. -assert (ft : transpose (@eq _) (fun x:elt =>plus (f x))). red; intros; omega. -assert (gc : compat_op E.eq (@eq _) (fun x:elt => plus (g x))). auto. -assert (gt : transpose (@eq _) (fun x:elt =>plus (g x))). red; intros; omega. -assert (fgc : compat_op E.eq (@eq _) (fun x:elt =>plus ((f x)+(g x)))). auto. -assert (fgt : transpose (@eq _) (fun x:elt=>plus ((f x)+(g x)))). red; intros; omega. +assert (fc : compat_opL (fun x:elt =>plus (f x))). auto. +assert (ft : transposeL (fun x:elt =>plus (f x))). red; intros; omega. +assert (gc : compat_opL (fun x:elt => plus (g x))). auto. +assert (gt : transposeL (fun x:elt =>plus (g x))). red; intros; omega. +assert (fgc : compat_opL (fun x:elt =>plus ((f x)+(g x)))). auto. +assert (fgt : transposeL (fun x:elt=>plus ((f x)+(g x)))). red; intros; omega. assert (st := gen_st nat). intros s;pattern s; apply set_rec. intros. @@ -858,7 +860,7 @@ rewrite <- (fold_equal _ _ st _ gc gt 0 _ _ H). rewrite <- (fold_equal _ _ st _ fgc fgt 0 _ _ H); auto. intros; do 3 (rewrite (fold_add _ _ st);auto). rewrite H0;simpl;omega. -intros; do 3 rewrite (fold_empty _ _ st);auto. +do 3 rewrite fold_empty;auto. Qed. Lemma sum_filter : forall f, (compat_bool E.eq f) -> @@ -866,11 +868,11 @@ Lemma sum_filter : forall f, (compat_bool E.eq f) -> Proof. unfold sum; intros f Hf. assert (st := gen_st nat). -assert (cc : compat_op E.eq (@eq _) (fun x => plus (if f x then 1 else 0))). - unfold compat_op; intros. +assert (cc : compat_opL (fun x => plus (if f x then 1 else 0))). + red; intros. rewrite (Hf x x' H); auto. -assert (ct : transpose (@eq _) (fun x => plus (if f x then 1 else 0))). - unfold transpose; intros; omega. +assert (ct : transposeL (fun x => plus (if f x then 1 else 0))). + red; intros; omega. intros s;pattern s; apply set_rec. intros. change elt with E.t. @@ -883,14 +885,14 @@ assert (~ In x (filter f s0)). case (f x); simpl; intros. rewrite (MP.cardinal_2 H1 (H2 (refl_equal true) (MP.Add_add s0 x))); auto. rewrite <- (MP.Equal_cardinal (H3 (refl_equal false) (MP.Add_add s0 x))); auto. -intros; rewrite (fold_empty _ _ st);auto. +intros; rewrite fold_empty;auto. rewrite MP.cardinal_1; auto. unfold Empty; intros. rewrite filter_iff; auto; set_iff; tauto. Qed. Lemma fold_compat : - forall (A:Set)(eqA:A->A->Prop)(st:(Setoid_Theory _ eqA)) + forall (A:Type)(eqA:A->A->Prop)(st:Setoid_Theory _ eqA) (f g:elt->A->A), (compat_op E.eq eqA f) -> (transpose eqA f) -> (compat_op E.eq eqA g) -> (transpose eqA g) -> @@ -903,26 +905,35 @@ trans_st (fold f s0 i). apply fold_equal with (eqA:=eqA); auto. rewrite equal_sym; auto. trans_st (fold g s0 i). -apply H0; intros; apply H1; auto. -elim (equal_2 H x); auto; intros. -apply fold_equal with (eqA:=eqA); auto. +apply H0; intros; apply H1; auto with set. +elim (equal_2 H x); auto with set; intros. +apply fold_equal with (eqA:=eqA); auto with set. trans_st (f x (fold f s0 i)). -apply fold_add with (eqA:=eqA); auto. -trans_st (g x (fold f s0 i)). -trans_st (g x (fold g s0 i)). +apply fold_add with (eqA:=eqA); auto with set. +trans_st (g x (fold f s0 i)); auto with set. +trans_st (g x (fold g s0 i)); auto with set. sym_st; apply fold_add with (eqA:=eqA); auto. -trans_st i; [idtac | sym_st ]; apply fold_empty; auto. +do 2 rewrite fold_empty; refl_st. Qed. Lemma sum_compat : forall f g, compat_nat E.eq f -> compat_nat E.eq g -> forall s, (forall x, In x s -> f x=g x) -> sum f s=sum g s. intros. -unfold sum; apply (fold_compat _ (@eq nat)); auto. -unfold transpose; intros; omega. -unfold transpose; intros; omega. +unfold sum; apply (fold_compat _ (@Logic.eq nat)); auto. +red; intros; omega. +red; intros; omega. Qed. End Sum. -End EqProperties. +End WEqProperties. + + +(** Now comes a special version dedicated to full sets. For this + one, only one argument [(M:S)] is necessary. *) + +Module EqProperties (M:S). + Module D := OT_as_DT M.E. + Include WEqProperties D M. +End EqProperties. diff --git a/theories/FSets/FSetFacts.v b/theories/FSets/FSetFacts.v index aa57f066..b4b834b1 100644 --- a/theories/FSets/FSetFacts.v +++ b/theories/FSets/FSetFacts.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: FSetFacts.v 8882 2006-05-31 21:55:30Z letouzey $ *) +(* $Id: FSetFacts.v 10765 2008-04-08 16:15:23Z msozeau $ *) (** * Finite sets library *) @@ -16,16 +16,19 @@ Moreover, we prove that [E.Eq] and [Equal] are setoid equalities. *) +Require Import DecidableTypeEx. Require Export FSetInterface. Set Implicit Arguments. Unset Strict Implicit. -Module Facts (M: S). -Module ME := OrderedTypeFacts M.E. -Import ME. -Import M. -Import Logic. (* to unmask [eq] *) -Import Peano. (* to unmask [lt] *) +(** First, a functor for Weak Sets. Since the signature [WS] includes + an EqualityType and not a stronger DecidableType, this functor + should take two arguments in order to compensate this. *) + +Module WFacts (Import E : DecidableType)(Import M : WSfun E). + +Notation eq_dec := E.eq_dec. +Definition eqb x y := if eq_dec x y then true else false. (** * Specifications written using equivalences *) @@ -259,6 +262,8 @@ symmetry. rewrite H0; intros. destruct H1 as (_,H1). apply H1; auto. +rewrite H2. +rewrite InA_alt; eauto. Qed. Lemma exists_b : compat_bool E.eq f -> @@ -271,7 +276,8 @@ destruct (existsb f (elements s)); destruct (exists_ f s); auto; intros. rewrite <- H1; intros. destruct H0 as (H0,_). destruct H0 as (a,(Ha1,Ha2)); auto. -exists a; auto. +exists a; split; auto. +rewrite H2; rewrite InA_alt; eauto. symmetry. rewrite H0. destruct H1 as (_,H1). @@ -289,17 +295,25 @@ End BoolSpec. Definition E_ST : Setoid_Theory elt E.eq. Proof. -constructor; [apply E.eq_refl|apply E.eq_sym|apply E.eq_trans]. +constructor ; red; [apply E.eq_refl|apply E.eq_sym|apply E.eq_trans]. Qed. -Add Setoid elt E.eq E_ST as EltSetoid. - Definition Equal_ST : Setoid_Theory t Equal. Proof. -constructor; [apply eq_refl | apply eq_sym | apply eq_trans]. +constructor ; red; [apply eq_refl | apply eq_sym | apply eq_trans]. Qed. -Add Setoid t Equal Equal_ST as EqualSetoid. +Add Relation elt E.eq + reflexivity proved by E.eq_refl + symmetry proved by E.eq_sym + transitivity proved by E.eq_trans + as EltSetoid. + +Add Relation t Equal + reflexivity proved by eq_refl + symmetry proved by eq_sym + transitivity proved by eq_trans + as EqualSetoid. Add Morphism In with signature E.eq ==> Equal ==> iff as In_m. Proof. @@ -325,7 +339,7 @@ exact (H1 (refl_equal true) _ Ha). Qed. Add Morphism Empty with signature Equal ==> iff as Empty_m. -Proof. +Proof. intros; do 2 rewrite is_empty_iff; rewrite H; intuition. Qed. @@ -340,7 +354,9 @@ Qed. Add Morphism singleton : singleton_m. Proof. unfold Equal; intros x y H a. -do 2 rewrite singleton_iff; split; order. +do 2 rewrite singleton_iff; split; intros. +apply E.eq_trans with x; auto. +apply E.eq_trans with y; auto. Qed. Add Morphism add : add_m. @@ -396,6 +412,63 @@ rewrite H in H1; rewrite H0 in H1; intuition. rewrite H in H1; rewrite H0 in H1; intuition. Qed. + +(* [Subset] is a setoid order *) + +Lemma Subset_refl : forall s, s[<=]s. +Proof. red; auto. Defined. + +Lemma Subset_trans : forall s s' s'', s[<=]s'->s'[<=]s''->s[<=]s''. +Proof. unfold Subset; eauto. Defined. + +Add Relation t Subset + reflexivity proved by Subset_refl + transitivity proved by Subset_trans + as SubsetSetoid. +(* NB: for the moment, it is important to use Defined and not Qed in + the two previous lemmas, in order to allow conversion of + SubsetSetoid coming from separate Facts modules. See bug #1738. *) + +Instance In_s_m : Morphism (E.eq ==> Subset ++> impl) In | 1. +Proof. + simpl_relation. eauto with set. +Qed. + +Add Morphism Empty with signature Subset --> impl as Empty_s_m. +Proof. +unfold Subset, Empty, impl; firstorder. +Qed. + +Add Morphism add with signature E.eq ==> Subset ++> Subset as add_s_m. +Proof. +unfold Subset; intros x y H s s' H0 a. +do 2 rewrite add_iff; rewrite H; intuition. +Qed. + +Add Morphism remove with signature E.eq ==> Subset ++> Subset as remove_s_m. +Proof. +unfold Subset; intros x y H s s' H0 a. +do 2 rewrite remove_iff; rewrite H; intuition. +Qed. + +Add Morphism union with signature Subset ++> Subset ++> Subset as union_s_m. +Proof. +unfold Equal; intros s s' H s'' s''' H0 a. +do 2 rewrite union_iff; intuition. +Qed. + +Add Morphism inter with signature Subset ++> Subset ++> Subset as inter_s_m. +Proof. +unfold Equal; intros s s' H s'' s''' H0 a. +do 2 rewrite inter_iff; intuition. +Qed. + +Add Morphism diff with signature Subset ++> Subset --> Subset as diff_s_m. +Proof. +unfold Subset; intros s s' H s'' s''' H0 a. +do 2 rewrite diff_iff; intuition. +Qed. + (* [fold], [filter], [for_all], [exists_] and [partition] cannot be proved morphism without additional hypothesis on [f]. For instance: *) @@ -405,6 +478,12 @@ Proof. unfold Equal; intros; repeat rewrite filter_iff; auto; rewrite H0; tauto. Qed. +Lemma filter_subset : forall f, compat_bool E.eq f -> + forall s s', s[<=]s' -> filter f s [<=] filter f s'. +Proof. +unfold Subset; intros; rewrite filter_iff in *; intuition. +Qed. + (* For [elements], [min_elt], [max_elt] and [choose], we would need setoid structures on [list elt] and [option elt]. *) @@ -412,4 +491,15 @@ Qed. Add Morphism cardinal ; cardinal_m. *) +End WFacts. + + +(** Now comes a special version dedicated to full sets. For this + one, only one argument [(M:S)] is necessary. *) + +Module Facts (Import M:S). + Module D:=OT_as_DT M.E. + Include WFacts D M. + End Facts. + diff --git a/theories/FSets/FSetFullAVL.v b/theories/FSets/FSetFullAVL.v new file mode 100644 index 00000000..1fc109f3 --- /dev/null +++ b/theories/FSets/FSetFullAVL.v @@ -0,0 +1,1125 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* Finite sets library. + * Authors: Pierre Letouzey and Jean-Christophe Filliâtre + * Institution: LRI, CNRS UMR 8623 - Université Paris Sud + * 91405 Orsay, France *) + +(* $Id: FSetFullAVL.v 10739 2008-04-01 14:45:20Z herbelin $ *) + +(** * FSetFullAVL + + This file contains some complements to [FSetAVL]. + + - Functor [AvlProofs] proves that trees of [FSetAVL] are not only + binary search trees, but moreover well-balanced ones. This is done + by proving that all operations preserve the balancing. + + - Functor [OcamlOps] contains variants of [union], [subset], + [compare] and [equal] that are faithful to the original ocaml codes, + while the versions in FSetAVL have been adapted to perform only + structural recursive code. + + - Finally, we pack the previous elements in a [Make] functor + similar to the one of [FSetAVL], but richer. +*) + +Require Import Recdef FSetInterface FSetList ZArith Int FSetAVL. + +Set Implicit Arguments. +Unset Strict Implicit. + +Module AvlProofs (Import I:Int)(X:OrderedType). +Module Import Raw := Raw I X. +Import Raw.Proofs. +Module Import II := MoreInt I. +Open Local Scope pair_scope. +Open Local Scope Int_scope. + +(** * AVL trees *) + +(** [avl s] : [s] is a properly balanced AVL tree, + i.e. for any node the heights of the two children + differ by at most 2 *) + +Inductive avl : tree -> Prop := + | RBLeaf : avl Leaf + | RBNode : forall x l r h, avl l -> avl r -> + -(2) <= height l - height r <= 2 -> + h = max (height l) (height r) + 1 -> + avl (Node l x r h). + +(** * Automation and dedicated tactics *) + +Hint Constructors avl. + +(** A tactic for cleaning hypothesis after use of functional induction. *) + +Ltac clearf := + match goal with + | H : (@Logic.eq (Compare _ _ _ _) _ _) |- _ => clear H; clearf + | H : (@Logic.eq (sumbool _ _) _ _) |- _ => clear H; clearf + | _ => idtac + end. + +(** Tactics about [avl] *) + +Lemma height_non_negative : forall s : tree, avl s -> height s >= 0. +Proof. + induction s; simpl; intros; auto with zarith. + inv avl; intuition; omega_max. +Qed. +Implicit Arguments height_non_negative. + +(** When [H:avl r], typing [avl_nn H] or [avl_nn r] adds [height r>=0] *) + +Ltac avl_nn_hyp H := + let nz := fresh "nz" in assert (nz := height_non_negative H). + +Ltac avl_nn h := + let t := type of h in + match type of t with + | Prop => avl_nn_hyp h + | _ => match goal with H : avl h |- _ => avl_nn_hyp H end + end. + +(* Repeat the previous tactic. + Drawback: need to clear the [avl _] hyps ... Thank you Ltac *) + +Ltac avl_nns := + match goal with + | H:avl _ |- _ => avl_nn_hyp H; clear H; avl_nns + | _ => idtac + end. + +(** Results about [height] *) + +Lemma height_0 : forall s, avl s -> height s = 0 -> s = Leaf. +Proof. + destruct 1; intuition; simpl in *. + avl_nns; simpl in *; elimtype False; omega_max. +Qed. + +(** * Results about [avl] *) + +Lemma avl_node : + forall x l r, avl l -> avl r -> + -(2) <= height l - height r <= 2 -> + avl (Node l x r (max (height l) (height r) + 1)). +Proof. + intros; auto. +Qed. +Hint Resolve avl_node. + + +(** empty *) + +Lemma empty_avl : avl empty. +Proof. + auto. +Qed. + +(** singleton *) + +Lemma singleton_avl : forall x : elt, avl (singleton x). +Proof. + unfold singleton; intro. + constructor; auto; try red; simpl; omega_max. +Qed. + +(** create *) + +Lemma create_avl : + forall l x r, avl l -> avl r -> -(2) <= height l - height r <= 2 -> + avl (create l x r). +Proof. + unfold create; auto. +Qed. + +Lemma create_height : + forall l x r, avl l -> avl r -> -(2) <= height l - height r <= 2 -> + height (create l x r) = max (height l) (height r) + 1. +Proof. + unfold create; auto. +Qed. + +(** bal *) + +Lemma bal_avl : forall l x r, avl l -> avl r -> + -(3) <= height l - height r <= 3 -> avl (bal l x r). +Proof. + intros l x r; functional induction bal l x r; intros; clearf; + inv avl; simpl in *; + match goal with |- avl (assert_false _ _ _) => avl_nns + | _ => repeat apply create_avl; simpl in *; auto + end; omega_max. +Qed. + +Lemma bal_height_1 : forall l x r, avl l -> avl r -> + -(3) <= height l - height r <= 3 -> + 0 <= height (bal l x r) - max (height l) (height r) <= 1. +Proof. + intros l x r; functional induction bal l x r; intros; clearf; + inv avl; avl_nns; simpl in *; omega_max. +Qed. + +Lemma bal_height_2 : + forall l x r, avl l -> avl r -> -(2) <= height l - height r <= 2 -> + height (bal l x r) == max (height l) (height r) +1. +Proof. + intros l x r; functional induction bal l x r; intros; clearf; + inv avl; simpl in *; omega_max. +Qed. + +Ltac omega_bal := match goal with + | H:avl ?l, H':avl ?r |- context [ bal ?l ?x ?r ] => + generalize (bal_height_1 x H H') (bal_height_2 x H H'); + omega_max + end. + +(** add *) + +Lemma add_avl_1 : forall s x, avl s -> + avl (add x s) /\ 0 <= height (add x s) - height s <= 1. +Proof. + intros s x; functional induction (add x s); subst;intros; inv avl; simpl in *. + intuition; try constructor; simpl; auto; try omega_max. + (* LT *) + destruct IHt; auto. + split. + apply bal_avl; auto; omega_max. + omega_bal. + (* EQ *) + intuition; omega_max. + (* GT *) + destruct IHt; auto. + split. + apply bal_avl; auto; omega_max. + omega_bal. +Qed. + +Lemma add_avl : forall s x, avl s -> avl (add x s). +Proof. + intros; destruct (add_avl_1 x H); auto. +Qed. +Hint Resolve add_avl. + +(** join *) + +Lemma join_avl_1 : forall l x r, avl l -> avl r -> avl (join l x r) /\ + 0<= height (join l x r) - max (height l) (height r) <= 1. +Proof. + join_tac. + + split; simpl; auto. + destruct (add_avl_1 x H0). + avl_nns; omega_max. + set (l:=Node ll lx lr lh) in *. + split; auto. + destruct (add_avl_1 x H). + simpl (height Leaf). + avl_nns; omega_max. + + inversion_clear H. + assert (height (Node rl rx rr rh) = rh); auto. + set (r := Node rl rx rr rh) in *; clearbody r. + destruct (Hlr x r H2 H0); clear Hrl Hlr. + set (j := join lr x r) in *; clearbody j. + simpl. + assert (-(3) <= height ll - height j <= 3) by omega_max. + split. + apply bal_avl; auto. + omega_bal. + + inversion_clear H0. + assert (height (Node ll lx lr lh) = lh); auto. + set (l := Node ll lx lr lh) in *; clearbody l. + destruct (Hrl H H1); clear Hrl Hlr. + set (j := join l x rl) in *; clearbody j. + simpl. + assert (-(3) <= height j - height rr <= 3) by omega_max. + split. + apply bal_avl; auto. + omega_bal. + + clear Hrl Hlr. + assert (height (Node ll lx lr lh) = lh); auto. + assert (height (Node rl rx rr rh) = rh); auto. + set (l := Node ll lx lr lh) in *; clearbody l. + set (r := Node rl rx rr rh) in *; clearbody r. + assert (-(2) <= height l - height r <= 2) by omega_max. + split. + apply create_avl; auto. + rewrite create_height; auto; omega_max. +Qed. + +Lemma join_avl : forall l x r, avl l -> avl r -> avl (join l x r). +Proof. + intros; destruct (join_avl_1 x H H0); auto. +Qed. +Hint Resolve join_avl. + +(** remove_min *) + +Lemma remove_min_avl_1 : forall l x r h, avl (Node l x r h) -> + avl (remove_min l x r)#1 /\ + 0 <= height (Node l x r h) - height (remove_min l x r)#1 <= 1. +Proof. + intros l x r; functional induction (remove_min l x r); subst;simpl in *; intros. + inv avl; simpl in *; split; auto. + avl_nns; omega_max. + inversion_clear H. + rewrite e0 in IHp;simpl in IHp;destruct (IHp _x); auto. + split; simpl in *. + apply bal_avl; auto; omega_max. + omega_bal. +Qed. + +Lemma remove_min_avl : forall l x r h, avl (Node l x r h) -> + avl (remove_min l x r)#1. +Proof. + intros; destruct (remove_min_avl_1 H); auto. +Qed. + +(** merge *) + +Lemma merge_avl_1 : forall s1 s2, avl s1 -> avl s2 -> + -(2) <= height s1 - height s2 <= 2 -> + avl (merge s1 s2) /\ + 0<= height (merge s1 s2) - max (height s1) (height s2) <=1. +Proof. + intros s1 s2; functional induction (merge s1 s2); intros; + try factornode _x _x0 _x1 _x2 as s1. + simpl; split; auto; avl_nns; omega_max. + simpl; split; auto; avl_nns; simpl in *; omega_max. + generalize (remove_min_avl_1 H0). + rewrite e1; destruct 1. + split. + apply bal_avl; auto. + simpl; omega_max. + simpl in *; omega_bal. +Qed. + +Lemma merge_avl : forall s1 s2, avl s1 -> avl s2 -> + -(2) <= height s1 - height s2 <= 2 -> avl (merge s1 s2). +Proof. + intros; destruct (merge_avl_1 H H0 H1); auto. +Qed. + + +(** remove *) + +Lemma remove_avl_1 : forall s x, avl s -> + avl (remove x s) /\ 0 <= height s - height (remove x s) <= 1. +Proof. + intros s x; functional induction (remove x s); intros. + intuition; omega_max. + (* LT *) + inv avl. + destruct (IHt H0). + split. + apply bal_avl; auto. + omega_max. + omega_bal. + (* EQ *) + inv avl. + generalize (merge_avl_1 H0 H1 H2). + intuition omega_max. + (* GT *) + inv avl. + destruct (IHt H1). + split. + apply bal_avl; auto. + omega_max. + omega_bal. +Qed. + +Lemma remove_avl : forall s x, avl s -> avl (remove x s). +Proof. + intros; destruct (remove_avl_1 x H); auto. +Qed. +Hint Resolve remove_avl. + +(** concat *) + +Lemma concat_avl : forall s1 s2, avl s1 -> avl s2 -> avl (concat s1 s2). +Proof. + intros s1 s2; functional induction (concat s1 s2); auto. + intros; apply join_avl; auto. + generalize (remove_min_avl H0); rewrite e1; simpl; auto. +Qed. +Hint Resolve concat_avl. + +(** split *) + +Lemma split_avl : forall s x, avl s -> + avl (split x s)#l /\ avl (split x s)#r. +Proof. + intros s x; functional induction (split x s); simpl; auto. + rewrite e1 in IHt;simpl in IHt;inversion_clear 1; intuition. + simpl; inversion_clear 1; auto. + rewrite e1 in IHt;simpl in IHt;inversion_clear 1; intuition. +Qed. + +(** inter *) + +Lemma inter_avl : forall s1 s2, avl s1 -> avl s2 -> avl (inter s1 s2). +Proof. + intros s1 s2; functional induction inter s1 s2; auto; intros A1 A2; + generalize (split_avl x1 A2); rewrite e1; simpl; destruct 1; + inv avl; auto. +Qed. + +(** diff *) + +Lemma diff_avl : forall s1 s2, avl s1 -> avl s2 -> avl (diff s1 s2). +Proof. + intros s1 s2; functional induction diff s1 s2; auto; intros A1 A2; + generalize (split_avl x1 A2); rewrite e1; simpl; destruct 1; + inv avl; auto. +Qed. + +(** union *) + +Lemma union_avl : forall s1 s2, avl s1 -> avl s2 -> avl (union s1 s2). +Proof. + intros s1 s2; functional induction union s1 s2; auto; intros A1 A2; + generalize (split_avl x1 A2); rewrite e1; simpl; destruct 1; + inv avl; auto. +Qed. + +(** filter *) + +Lemma filter_acc_avl : forall f s acc, avl s -> avl acc -> + avl (filter_acc f acc s). +Proof. + induction s; simpl; auto. + intros. + inv avl. + destruct (f t); auto. +Qed. +Hint Resolve filter_acc_avl. + +Lemma filter_avl : forall f s, avl s -> avl (filter f s). +Proof. + unfold filter; intros; apply filter_acc_avl; auto. +Qed. + +(** partition *) + +Lemma partition_acc_avl_1 : forall f s acc, avl s -> + avl acc#1 -> avl (partition_acc f acc s)#1. +Proof. + induction s; simpl; auto. + destruct acc as [acct accf]; simpl in *. + intros. + inv avl. + apply IHs2; auto. + apply IHs1; auto. + destruct (f t); simpl; auto. +Qed. + +Lemma partition_acc_avl_2 : forall f s acc, avl s -> + avl acc#2 -> avl (partition_acc f acc s)#2. +Proof. + induction s; simpl; auto. + destruct acc as [acct accf]; simpl in *. + intros. + inv avl. + apply IHs2; auto. + apply IHs1; auto. + destruct (f t); simpl; auto. +Qed. + +Lemma partition_avl_1 : forall f s, avl s -> avl (partition f s)#1. +Proof. + unfold partition; intros; apply partition_acc_avl_1; auto. +Qed. + +Lemma partition_avl_2 : forall f s, avl s -> avl (partition f s)#2. +Proof. + unfold partition; intros; apply partition_acc_avl_2; auto. +Qed. + +End AvlProofs. + + +Module OcamlOps (Import I:Int)(X:OrderedType). +Module Import AvlProofs := AvlProofs I X. +Import Raw. +Import Raw.Proofs. +Import II. +Open Local Scope pair_scope. +Open Local Scope nat_scope. + +(** Properties of cardinal *) + +Lemma bal_cardinal : forall l x r, + cardinal (bal l x r) = S (cardinal l + cardinal r). +Proof. + intros l x r; functional induction bal l x r; intros; clearf; + simpl; auto with arith; romega with *. +Qed. + +Lemma add_cardinal : forall x s, + cardinal (add x s) <= S (cardinal s). +Proof. + intros; functional induction add x s; simpl; auto with arith; + rewrite bal_cardinal; romega with *. +Qed. + +Lemma join_cardinal : forall l x r, + cardinal (join l x r) <= S (cardinal l + cardinal r). +Proof. + join_tac; auto with arith. + simpl; apply add_cardinal. + simpl; destruct X.compare; simpl; auto with arith. + generalize (bal_cardinal (add x ll) lx lr) (add_cardinal x ll); + romega with *. + generalize (bal_cardinal ll lx (add x lr)) (add_cardinal x lr); + romega with *. + generalize (bal_cardinal ll lx (join lr x (Node rl rx rr rh))) + (Hlr x (Node rl rx rr rh)); simpl; romega with *. + simpl S in *; generalize (bal_cardinal (join (Node ll lx lr lh) x rl) rx rr). + romega with *. +Qed. + +Lemma split_cardinal_1 : forall x s, + (cardinal (split x s)#l <= cardinal s)%nat. +Proof. + intros x s; functional induction split x s; simpl; auto. + rewrite e1 in IHt; simpl in *. + romega with *. + romega with *. + rewrite e1 in IHt; simpl in *. + generalize (@join_cardinal l y rl); romega with *. +Qed. + +Lemma split_cardinal_2 : forall x s, + (cardinal (split x s)#r <= cardinal s)%nat. +Proof. + intros x s; functional induction split x s; simpl; auto. + rewrite e1 in IHt; simpl in *. + generalize (@join_cardinal rl y r); romega with *. + romega with *. + rewrite e1 in IHt; simpl in *; romega with *. +Qed. + +(** * [ocaml_union], an union faithful to the original ocaml code *) + +Definition cardinal2 (s:t*t) := (cardinal s#1 + cardinal s#2)%nat. + +Ltac ocaml_union_tac := + intros; unfold cardinal2; simpl fst in *; simpl snd in *; + match goal with H: split ?x ?s = _ |- _ => + generalize (split_cardinal_1 x s) (split_cardinal_2 x s); + rewrite H; simpl; romega with * + end. + +Import Logic. (* Unhide eq, otherwise Function complains. *) + +Function ocaml_union (s : t * t) { measure cardinal2 s } : t := + match s with + | (Leaf, Leaf) => s#2 + | (Leaf, Node _ _ _ _) => s#2 + | (Node _ _ _ _, Leaf) => s#1 + | (Node l1 x1 r1 h1, Node l2 x2 r2 h2) => + if ge_lt_dec h1 h2 then + if eq_dec h2 1%I then add x2 s#1 else + let (l2',_,r2') := split x1 s#2 in + join (ocaml_union (l1,l2')) x1 (ocaml_union (r1,r2')) + else + if eq_dec h1 1%I then add x1 s#2 else + let (l1',_,r1') := split x2 s#1 in + join (ocaml_union (l1',l2)) x2 (ocaml_union (r1',r2)) + end. +Proof. +abstract ocaml_union_tac. +abstract ocaml_union_tac. +abstract ocaml_union_tac. +abstract ocaml_union_tac. +Defined. + +Lemma ocaml_union_in : forall s y, + bst s#1 -> avl s#1 -> bst s#2 -> avl s#2 -> + (In y (ocaml_union s) <-> In y s#1 \/ In y s#2). +Proof. + intros s; functional induction ocaml_union s; intros y B1 A1 B2 A2; + simpl fst in *; simpl snd in *; try clear e0 e1. + intuition_in. + intuition_in. + intuition_in. + (* add x2 s#1 *) + inv avl. + rewrite (height_0 H); [ | avl_nn l2; omega_max]. + rewrite (height_0 H0); [ | avl_nn r2; omega_max]. + rewrite add_in; intuition_in. + (* join (union (l1,l2')) x1 (union (r1,r2')) *) + generalize + (split_avl x1 A2) (split_bst x1 B2) + (split_in_1 x1 y B2) (split_in_2 x1 y B2). + rewrite e2; simpl. + destruct 1; destruct 1; inv avl; inv bst. + rewrite join_in, IHt, IHt0; auto. + do 2 (intro Eq; rewrite Eq; clear Eq). + case (X.compare y x1); intuition_in. + (* add x1 s#2 *) + inv avl. + rewrite (height_0 H3); [ | avl_nn l1; omega_max]. + rewrite (height_0 H4); [ | avl_nn r1; omega_max]. + rewrite add_in; auto; intuition_in. + (* join (union (l1',l2)) x1 (union (r1',r2)) *) + generalize + (split_avl x2 A1) (split_bst x2 B1) + (split_in_1 x2 y B1) (split_in_2 x2 y B1). + rewrite e2; simpl. + destruct 1; destruct 1; inv avl; inv bst. + rewrite join_in, IHt, IHt0; auto. + do 2 (intro Eq; rewrite Eq; clear Eq). + case (X.compare y x2); intuition_in. +Qed. + +Lemma ocaml_union_bst : forall s, + bst s#1 -> avl s#1 -> bst s#2 -> avl s#2 -> bst (ocaml_union s). +Proof. + intros s; functional induction ocaml_union s; intros B1 A1 B2 A2; + simpl fst in *; simpl snd in *; try clear e0 e1; + try apply add_bst; auto. + (* join (union (l1,l2')) x1 (union (r1,r2')) *) + clear _x _x0; factornode l2 x2 r2 h2 as s2. + generalize (split_avl x1 A2) (split_bst x1 B2) + (@split_in_1 s2 x1)(@split_in_2 s2 x1). + rewrite e2; simpl. + destruct 1; destruct 1; intros. + inv bst; inv avl. + apply join_bst; auto. + intro y; rewrite ocaml_union_in, H3; intuition_in. + intro y; rewrite ocaml_union_in, H4; intuition_in. + (* join (union (l1',l2)) x1 (union (r1',r2)) *) + clear _x _x0; factornode l1 x1 r1 h1 as s1. + generalize (split_avl x2 A1) (split_bst x2 B1) + (@split_in_1 s1 x2)(@split_in_2 s1 x2). + rewrite e2; simpl. + destruct 1; destruct 1; intros. + inv bst; inv avl. + apply join_bst; auto. + intro y; rewrite ocaml_union_in, H3; intuition_in. + intro y; rewrite ocaml_union_in, H4; intuition_in. +Qed. + +Lemma ocaml_union_avl : forall s, + avl s#1 -> avl s#2 -> avl (ocaml_union s). +Proof. + intros s; functional induction ocaml_union s; + simpl fst in *; simpl snd in *; auto. + intros A1 A2; generalize (split_avl x1 A2); rewrite e2; simpl. + inv avl; destruct 1; auto. + intros A1 A2; generalize (split_avl x2 A1); rewrite e2; simpl. + inv avl; destruct 1; auto. +Qed. + +Lemma ocaml_union_alt : forall s, bst s#1 -> avl s#1 -> bst s#2 -> avl s#2 -> + Equal (ocaml_union s) (union s#1 s#2). +Proof. + red; intros; rewrite ocaml_union_in, union_in; simpl; intuition. +Qed. + + +(** * [ocaml_subset], a subset faithful to the original ocaml code *) + +Function ocaml_subset (s:t*t) { measure cardinal2 s } : bool := + match s with + | (Leaf, _) => true + | (Node _ _ _ _, Leaf) => false + | (Node l1 x1 r1 h1, Node l2 x2 r2 h2) => + match X.compare x1 x2 with + | EQ _ => ocaml_subset (l1,l2) && ocaml_subset (r1,r2) + | LT _ => ocaml_subset (Node l1 x1 Leaf 0%I, l2) && ocaml_subset (r1,s#2) + | GT _ => ocaml_subset (Node Leaf x1 r1 0%I, r2) && ocaml_subset (l1,s#2) + end + end. + +Proof. + intros; unfold cardinal2; simpl; abstract romega with *. + intros; unfold cardinal2; simpl; abstract romega with *. + intros; unfold cardinal2; simpl; abstract romega with *. + intros; unfold cardinal2; simpl; abstract romega with *. + intros; unfold cardinal2; simpl; abstract romega with *. + intros; unfold cardinal2; simpl; abstract romega with *. +Defined. + +Lemma ocaml_subset_12 : forall s, + bst s#1 -> bst s#2 -> + (ocaml_subset s = true <-> Subset s#1 s#2). +Proof. + intros s; functional induction ocaml_subset s; simpl; + intros B1 B2; try clear e0. + intuition. + red; auto; inversion 1. + split; intros; try discriminate. + assert (H': In _x0 Leaf) by auto; inversion H'. + (**) + simpl in *; inv bst. + rewrite andb_true_iff, IHb, IHb0; auto; clear IHb IHb0. + unfold Subset; intuition_in. + assert (X.eq a x2) by order; intuition_in. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. + (**) + simpl in *; inv bst. + rewrite andb_true_iff, IHb, IHb0; auto; clear IHb IHb0. + unfold Subset; intuition_in. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. + (**) + simpl in *; inv bst. + rewrite andb_true_iff, IHb, IHb0; auto; clear IHb IHb0. + unfold Subset; intuition_in. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. + assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order. +Qed. + +Lemma ocaml_subset_alt : forall s, bst s#1 -> bst s#2 -> + ocaml_subset s = subset s#1 s#2. +Proof. + intros. + generalize (ocaml_subset_12 H H0); rewrite <-subset_12 by auto. + destruct ocaml_subset; destruct subset; intuition. +Qed. + + + +(** [ocaml_compare], a compare faithful to the original ocaml code *) + +(** termination of [compare_aux] *) + +Fixpoint cardinal_e e := match e with + | End => 0 + | More _ s r => S (cardinal s + cardinal_e r) + end. + +Lemma cons_cardinal_e : forall s e, + cardinal_e (cons s e) = cardinal s + cardinal_e e. +Proof. + induction s; simpl; intros; auto. + rewrite IHs1; simpl; rewrite <- plus_n_Sm; auto with arith. +Qed. + +Definition cardinal_e_2 e := cardinal_e e#1 + cardinal_e e#2. + +Function ocaml_compare_aux + (e:enumeration*enumeration) { measure cardinal_e_2 e } : comparison := + match e with + | (End,End) => Eq + | (End,More _ _ _) => Lt + | (More _ _ _, End) => Gt + | (More x1 r1 e1, More x2 r2 e2) => + match X.compare x1 x2 with + | EQ _ => ocaml_compare_aux (cons r1 e1, cons r2 e2) + | LT _ => Lt + | GT _ => Gt + end + end. + +Proof. +intros; unfold cardinal_e_2; simpl; +abstract (do 2 rewrite cons_cardinal_e; romega with *). +Defined. + +Definition ocaml_compare s1 s2 := + ocaml_compare_aux (cons s1 End, cons s2 End). + +Lemma ocaml_compare_aux_Cmp : forall e, + Cmp (ocaml_compare_aux e) (flatten_e e#1) (flatten_e e#2). +Proof. + intros e; functional induction ocaml_compare_aux e; simpl; intros; + auto; try discriminate. + apply L.eq_refl. + simpl in *. + apply cons_Cmp; auto. + rewrite <- 2 cons_1; auto. +Qed. + +Lemma ocaml_compare_Cmp : forall s1 s2, + Cmp (ocaml_compare s1 s2) (elements s1) (elements s2). +Proof. + unfold ocaml_compare; intros. + assert (H1:=cons_1 s1 End). + assert (H2:=cons_1 s2 End). + simpl in *; rewrite <- app_nil_end in *; rewrite <-H1,<-H2. + apply (@ocaml_compare_aux_Cmp (cons s1 End, cons s2 End)). +Qed. + +Lemma ocaml_compare_alt : forall s1 s2, bst s1 -> bst s2 -> + ocaml_compare s1 s2 = compare s1 s2. +Proof. + intros s1 s2 B1 B2. + generalize (ocaml_compare_Cmp s1 s2)(compare_Cmp s1 s2). + unfold Cmp. + destruct ocaml_compare; destruct compare; auto; intros; elimtype False. + elim (lt_not_eq B1 B2 H0); auto. + elim (lt_not_eq B2 B1 H0); auto. + apply eq_sym; auto. + elim (lt_not_eq B1 B2 H); auto. + elim (lt_not_eq B1 B1). + red; eapply L.lt_trans; eauto. + apply eq_refl. + elim (lt_not_eq B2 B1 H); auto. + apply eq_sym; auto. + elim (lt_not_eq B1 B2 H0); auto. + elim (lt_not_eq B1 B1). + red; eapply L.lt_trans; eauto. + apply eq_refl. +Qed. + + +(** * Equality test *) + +Definition ocaml_equal s1 s2 : bool := + match ocaml_compare s1 s2 with + | Eq => true + | _ => false + end. + +Lemma ocaml_equal_1 : forall s1 s2, bst s1 -> bst s2 -> + Equal s1 s2 -> ocaml_equal s1 s2 = true. +Proof. +unfold ocaml_equal; intros s1 s2 B1 B2 E. +generalize (ocaml_compare_Cmp s1 s2). +destruct (ocaml_compare s1 s2); auto; intros. +elim (lt_not_eq B1 B2 H E); auto. +elim (lt_not_eq B2 B1 H (eq_sym E)); auto. +Qed. + +Lemma ocaml_equal_2 : forall s1 s2, + ocaml_equal s1 s2 = true -> Equal s1 s2. +Proof. +unfold ocaml_equal; intros s1 s2 E. +generalize (ocaml_compare_Cmp s1 s2); + destruct ocaml_compare; auto; discriminate. +Qed. + +Lemma ocaml_equal_alt : forall s1 s2, bst s1 -> bst s2 -> + ocaml_equal s1 s2 = equal s1 s2. +Proof. +intros; unfold ocaml_equal, equal; rewrite ocaml_compare_alt; auto. +Qed. + +End OcamlOps. + + + +(** * Encapsulation + + We can implement [S] with balanced binary search trees. + When compared to [FSetAVL], we maintain here two invariants + (bst and avl) instead of only bst, which is enough for fulfilling + the FSet interface. + + This encapsulation propose the non-structural variants + [ocaml_union], [ocaml_subset], [ocaml_compare], [ocaml_equal]. +*) + +Module IntMake (I:Int)(X: OrderedType) <: S with Module E := X. + + Module E := X. + Module Import OcamlOps := OcamlOps I X. + Import AvlProofs. + Import Raw. + Import Raw.Proofs. + + Record bbst := Bbst {this :> Raw.t; is_bst : bst this; is_avl : avl this}. + Definition t := bbst. + Definition elt := E.t. + + Definition In (x : elt) (s : t) : Prop := In x s. + Definition Equal (s s':t) : Prop := forall a : elt, In a s <-> In a s'. + Definition Subset (s s':t) : Prop := forall a : elt, In a s -> In a s'. + Definition Empty (s:t) : Prop := forall a : elt, ~ In a s. + Definition For_all (P : elt -> Prop) (s:t) : Prop := forall x, In x s -> P x. + Definition Exists (P : elt -> Prop) (s:t) : Prop := exists x, In x s /\ P x. + + Lemma In_1 : forall (s:t)(x y:elt), E.eq x y -> In x s -> In y s. + Proof. intro s; exact (@In_1 s). Qed. + + Definition mem (x:elt)(s:t) : bool := mem x s. + + Definition empty : t := Bbst empty_bst empty_avl. + Definition is_empty (s:t) : bool := is_empty s. + Definition singleton (x:elt) : t := + Bbst (singleton_bst x) (singleton_avl x). + Definition add (x:elt)(s:t) : t := + Bbst (add_bst x (is_bst s)) (add_avl x (is_avl s)). + Definition remove (x:elt)(s:t) : t := + Bbst (remove_bst x (is_bst s)) (remove_avl x (is_avl s)). + Definition inter (s s':t) : t := + Bbst (inter_bst (is_bst s) (is_bst s')) + (inter_avl (is_avl s) (is_avl s')). + Definition union (s s':t) : t := + Bbst (union_bst (is_bst s) (is_bst s')) + (union_avl (is_avl s) (is_avl s')). + Definition ocaml_union (s s':t) : t := + Bbst (@ocaml_union_bst (s.(this),s'.(this)) + (is_bst s) (is_avl s) (is_bst s') (is_avl s')) + (@ocaml_union_avl (s.(this),s'.(this)) (is_avl s) (is_avl s')). + Definition diff (s s':t) : t := + Bbst (diff_bst (is_bst s) (is_bst s')) + (diff_avl (is_avl s) (is_avl s')). + Definition elements (s:t) : list elt := elements s. + Definition min_elt (s:t) : option elt := min_elt s. + Definition max_elt (s:t) : option elt := max_elt s. + Definition choose (s:t) : option elt := choose s. + Definition fold (B : Type) (f : elt -> B -> B) (s:t) : B -> B := fold f s. + Definition cardinal (s:t) : nat := cardinal s. + Definition filter (f : elt -> bool) (s:t) : t := + Bbst (filter_bst f (is_bst s)) (filter_avl f (is_avl s)). + Definition for_all (f : elt -> bool) (s:t) : bool := for_all f s. + Definition exists_ (f : elt -> bool) (s:t) : bool := exists_ f s. + Definition partition (f : elt -> bool) (s:t) : t * t := + let p := partition f s in + (@Bbst (fst p) (partition_bst_1 f (is_bst s)) + (partition_avl_1 f (is_avl s)), + @Bbst (snd p) (partition_bst_2 f (is_bst s)) + (partition_avl_2 f (is_avl s))). + + Definition equal (s s':t) : bool := equal s s'. + Definition ocaml_equal (s s':t) : bool := ocaml_equal s s'. + Definition subset (s s':t) : bool := subset s s'. + Definition ocaml_subset (s s':t) : bool := + ocaml_subset (s.(this),s'.(this)). + + Definition eq (s s':t) : Prop := Equal s s'. + Definition lt (s s':t) : Prop := lt s s'. + + Definition compare (s s':t) : Compare lt eq s s'. + Proof. + intros (s,b,a) (s',b',a'). + generalize (compare_Cmp s s'). + destruct Raw.compare; intros; [apply EQ|apply LT|apply GT]; red; auto. + change (Raw.Equal s s'); auto. + Defined. + + Definition ocaml_compare (s s':t) : Compare lt eq s s'. + Proof. + intros (s,b,a) (s',b',a'). + generalize (ocaml_compare_Cmp s s'). + destruct ocaml_compare; intros; [apply EQ|apply LT|apply GT]; red; auto. + change (Raw.Equal s s'); auto. + Defined. + + (* specs *) + Section Specs. + Variable s s' s'': t. + Variable x y : elt. + + Hint Resolve is_bst is_avl. + + Lemma mem_1 : In x s -> mem x s = true. + Proof. exact (mem_1 (is_bst s)). Qed. + Lemma mem_2 : mem x s = true -> In x s. + Proof. exact (@mem_2 s x). Qed. + + Lemma equal_1 : Equal s s' -> equal s s' = true. + Proof. exact (equal_1 (is_bst s) (is_bst s')). Qed. + Lemma equal_2 : equal s s' = true -> Equal s s'. + Proof. exact (@equal_2 s s'). Qed. + + Lemma ocaml_equal_alt : ocaml_equal s s' = equal s s'. + Proof. + destruct s; destruct s'; unfold ocaml_equal, equal; simpl. + apply ocaml_equal_alt; auto. + Qed. + + Lemma ocaml_equal_1 : Equal s s' -> ocaml_equal s s' = true. + Proof. exact (ocaml_equal_1 (is_bst s) (is_bst s')). Qed. + Lemma ocaml_equal_2 : ocaml_equal s s' = true -> Equal s s'. + Proof. exact (@ocaml_equal_2 s s'). Qed. + + Ltac wrap t H := unfold t, In; simpl; rewrite H; auto; intuition. + + Lemma subset_1 : Subset s s' -> subset s s' = true. + Proof. wrap subset subset_12. Qed. + Lemma subset_2 : subset s s' = true -> Subset s s'. + Proof. wrap subset subset_12. Qed. + + Lemma ocaml_subset_alt : ocaml_subset s s' = subset s s'. + Proof. + destruct s; destruct s'; unfold ocaml_subset, subset; simpl. + rewrite ocaml_subset_alt; auto. + Qed. + + Lemma ocaml_subset_1 : Subset s s' -> ocaml_subset s s' = true. + Proof. wrap ocaml_subset ocaml_subset_12; simpl; auto. Qed. + Lemma ocaml_subset_2 : ocaml_subset s s' = true -> Subset s s'. + Proof. wrap ocaml_subset ocaml_subset_12; simpl; auto. Qed. + + Lemma empty_1 : Empty empty. + Proof. exact empty_1. Qed. + + Lemma is_empty_1 : Empty s -> is_empty s = true. + Proof. exact (@is_empty_1 s). Qed. + Lemma is_empty_2 : is_empty s = true -> Empty s. + Proof. exact (@is_empty_2 s). Qed. + + Lemma add_1 : E.eq x y -> In y (add x s). + Proof. wrap add add_in. Qed. + Lemma add_2 : In y s -> In y (add x s). + Proof. wrap add add_in. Qed. + Lemma add_3 : ~ E.eq x y -> In y (add x s) -> In y s. + Proof. wrap add add_in. elim H; auto. Qed. + + Lemma remove_1 : E.eq x y -> ~ In y (remove x s). + Proof. wrap remove remove_in. Qed. + Lemma remove_2 : ~ E.eq x y -> In y s -> In y (remove x s). + Proof. wrap remove remove_in. Qed. + Lemma remove_3 : In y (remove x s) -> In y s. + Proof. wrap remove remove_in. Qed. + + Lemma singleton_1 : In y (singleton x) -> E.eq x y. + Proof. exact (@singleton_1 x y). Qed. + Lemma singleton_2 : E.eq x y -> In y (singleton x). + Proof. exact (@singleton_2 x y). Qed. + + Lemma union_1 : In x (union s s') -> In x s \/ In x s'. + Proof. wrap union union_in. Qed. + Lemma union_2 : In x s -> In x (union s s'). + Proof. wrap union union_in. Qed. + Lemma union_3 : In x s' -> In x (union s s'). + Proof. wrap union union_in. Qed. + + Lemma ocaml_union_alt : Equal (ocaml_union s s') (union s s'). + Proof. + unfold ocaml_union, union, Equal, In. + destruct s as (s0,b,a); destruct s' as (s0',b',a'); simpl. + exact (@ocaml_union_alt (s0,s0') b a b' a'). + Qed. + + Lemma ocaml_union_1 : In x (ocaml_union s s') -> In x s \/ In x s'. + Proof. wrap ocaml_union ocaml_union_in; simpl; auto. Qed. + Lemma ocaml_union_2 : In x s -> In x (ocaml_union s s'). + Proof. wrap ocaml_union ocaml_union_in; simpl; auto. Qed. + Lemma ocaml_union_3 : In x s' -> In x (ocaml_union s s'). + Proof. wrap ocaml_union ocaml_union_in; simpl; auto. Qed. + + Lemma inter_1 : In x (inter s s') -> In x s. + Proof. wrap inter inter_in. Qed. + Lemma inter_2 : In x (inter s s') -> In x s'. + Proof. wrap inter inter_in. Qed. + Lemma inter_3 : In x s -> In x s' -> In x (inter s s'). + Proof. wrap inter inter_in. Qed. + + Lemma diff_1 : In x (diff s s') -> In x s. + Proof. wrap diff diff_in. Qed. + Lemma diff_2 : In x (diff s s') -> ~ In x s'. + Proof. wrap diff diff_in. Qed. + Lemma diff_3 : In x s -> ~ In x s' -> In x (diff s s'). + Proof. wrap diff diff_in. Qed. + + Lemma fold_1 : forall (A : Type) (i : A) (f : elt -> A -> A), + fold f s i = fold_left (fun a e => f e a) (elements s) i. + Proof. + unfold fold, elements; intros; apply fold_1; auto. + Qed. + + Lemma cardinal_1 : cardinal s = length (elements s). + Proof. + unfold cardinal, elements; intros; apply elements_cardinal; auto. + Qed. + + Section Filter. + Variable f : elt -> bool. + + Lemma filter_1 : compat_bool E.eq f -> In x (filter f s) -> In x s. + Proof. intro. wrap filter filter_in. Qed. + Lemma filter_2 : compat_bool E.eq f -> In x (filter f s) -> f x = true. + Proof. intro. wrap filter filter_in. Qed. + Lemma filter_3 : compat_bool E.eq f -> In x s -> f x = true -> In x (filter f s). + Proof. intro. wrap filter filter_in. Qed. + + Lemma for_all_1 : compat_bool E.eq f -> For_all (fun x => f x = true) s -> for_all f s = true. + Proof. exact (@for_all_1 f s). Qed. + Lemma for_all_2 : compat_bool E.eq f -> for_all f s = true -> For_all (fun x => f x = true) s. + Proof. exact (@for_all_2 f s). Qed. + + Lemma exists_1 : compat_bool E.eq f -> Exists (fun x => f x = true) s -> exists_ f s = true. + Proof. exact (@exists_1 f s). Qed. + Lemma exists_2 : compat_bool E.eq f -> exists_ f s = true -> Exists (fun x => f x = true) s. + Proof. exact (@exists_2 f s). Qed. + + Lemma partition_1 : compat_bool E.eq f -> + Equal (fst (partition f s)) (filter f s). + Proof. + unfold partition, filter, Equal, In; simpl ;intros H a. + rewrite partition_in_1, filter_in; intuition. + Qed. + + Lemma partition_2 : compat_bool E.eq f -> + Equal (snd (partition f s)) (filter (fun x => negb (f x)) s). + Proof. + unfold partition, filter, Equal, In; simpl ;intros H a. + rewrite partition_in_2, filter_in; intuition. + rewrite H2; auto. + destruct (f a); auto. + red; intros; f_equal. + rewrite (H _ _ H0); auto. + Qed. + + End Filter. + + Lemma elements_1 : In x s -> InA E.eq x (elements s). + Proof. wrap elements elements_in. Qed. + Lemma elements_2 : InA E.eq x (elements s) -> In x s. + Proof. wrap elements elements_in. Qed. + Lemma elements_3 : sort E.lt (elements s). + Proof. exact (elements_sort (is_bst s)). Qed. + Lemma elements_3w : NoDupA E.eq (elements s). + Proof. exact (elements_nodup (is_bst s)). Qed. + + Lemma min_elt_1 : min_elt s = Some x -> In x s. + Proof. exact (@min_elt_1 s x). Qed. + Lemma min_elt_2 : min_elt s = Some x -> In y s -> ~ E.lt y x. + Proof. exact (@min_elt_2 s x y (is_bst s)). Qed. + Lemma min_elt_3 : min_elt s = None -> Empty s. + Proof. exact (@min_elt_3 s). Qed. + + Lemma max_elt_1 : max_elt s = Some x -> In x s. + Proof. exact (@max_elt_1 s x). Qed. + Lemma max_elt_2 : max_elt s = Some x -> In y s -> ~ E.lt x y. + Proof. exact (@max_elt_2 s x y (is_bst s)). Qed. + Lemma max_elt_3 : max_elt s = None -> Empty s. + Proof. exact (@max_elt_3 s). Qed. + + Lemma choose_1 : choose s = Some x -> In x s. + Proof. exact (@choose_1 s x). Qed. + Lemma choose_2 : choose s = None -> Empty s. + Proof. exact (@choose_2 s). Qed. + Lemma choose_3 : choose s = Some x -> choose s' = Some y -> + Equal s s' -> E.eq x y. + Proof. exact (@choose_3 _ _ (is_bst s) (is_bst s') x y). Qed. + + Lemma eq_refl : eq s s. + Proof. exact (eq_refl s). Qed. + Lemma eq_sym : eq s s' -> eq s' s. + Proof. exact (@eq_sym s s'). Qed. + Lemma eq_trans : eq s s' -> eq s' s'' -> eq s s''. + Proof. exact (@eq_trans s s' s''). Qed. + + Lemma lt_trans : lt s s' -> lt s' s'' -> lt s s''. + Proof. exact (@lt_trans s s' s''). Qed. + Lemma lt_not_eq : lt s s' -> ~eq s s'. + Proof. exact (@lt_not_eq _ _ (is_bst s) (is_bst s')). Qed. + + End Specs. +End IntMake. + +(* For concrete use inside Coq, we propose an instantiation of [Int] by [Z]. *) + +Module Make (X: OrderedType) <: S with Module E := X + :=IntMake(Z_as_Int)(X). + diff --git a/theories/FSets/FSetInterface.v b/theories/FSets/FSetInterface.v index 64ad234b..1255fcc8 100644 --- a/theories/FSets/FSetInterface.v +++ b/theories/FSets/FSetInterface.v @@ -6,40 +6,53 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: FSetInterface.v 8820 2006-05-15 11:44:05Z letouzey $ *) +(* $Id: FSetInterface.v 10616 2008-03-04 17:33:35Z letouzey $ *) (** * Finite set library *) -(** Set interfaces *) - -(* begin hide *) -Require Export Bool. -Require Export OrderedType. +(** Set interfaces, inspired by the one of Ocaml. When compared with + Ocaml, the main differences are: + - the lack of [iter] function, useless since Coq is purely functional + - the use of [option] types instead of [Not_found] exceptions + - the use of [nat] instead of [int] for the [cardinal] function + + Several variants of the set interfaces are available: + - [WSfun] : functorial signature for weak sets, non-dependent style + - [WS] : self-contained version of [WSfun] + - [Sfun] : functorial signature for ordered sets, non-dependent style + - [S] : self-contained version of [Sfun] + - [Sdep] : analog of [S] written using dependent style + + If unsure, [S] is probably what you're looking for: other signatures + are subsets of it, apart from [Sdep] which is isomorphic to [S] (see + [FSetBridge]). +*) + +Require Export Bool OrderedType DecidableType. Set Implicit Arguments. Unset Strict Implicit. -(* end hide *) -(** Compatibility of a boolean function with respect to an equality. *) -Definition compat_bool (A:Set)(eqA: A->A->Prop)(f: A-> bool) := - forall x y : A, eqA x y -> f x = f y. +(** * Non-dependent signatures -(** Compatibility of a predicate with respect to an equality. *) -Definition compat_P (A:Set)(eqA: A->A->Prop)(P : A -> Prop) := - forall x y : A, eqA x y -> P x -> P y. + The following signatures presents sets as purely informative + programs together with axioms *) -Hint Unfold compat_bool compat_P. -(** * Non-dependent signature - Signature [S] presents sets as purely informative programs - together with axioms *) +(** ** Functorial signature for weak sets -Module Type S. + Weak sets are sets without ordering on base elements, only + a decidable equality. *) + +Module Type WSfun (E : EqualityType). + + (** The module E of base objects is meant to be a [DecidableType] + (and used to be so). But requiring only an [EqualityType] here + allows subtyping between weak and ordered sets *) - Declare Module E : OrderedType. Definition elt := E.t. - Parameter t : Set. (** the abstract type of sets *) + Parameter t : Type. (** the abstract type of sets *) (** Logical predicates *) Parameter In : elt -> t -> Prop. @@ -82,10 +95,12 @@ Module Type S. (** Set difference. *) Definition eq : t -> t -> Prop := Equal. - Parameter lt : t -> t -> Prop. - Parameter compare : forall s s' : t, Compare lt eq s s'. - (** Total ordering between sets. Can be used as the ordering function - for doing sets of sets. *) + (** In order to have the subtyping WS < S between weak and ordered + sets, we do not require here an [eq_dec]. This interface is hence + not compatible with [DecidableType], but only with [EqualityType], + so in general it may not possible to form weak sets of weak sets. + Some particular implementations may allow this nonetheless, in + particular [FSetWeakList.Make]. *) Parameter equal : t -> t -> bool. (** [equal s1 s2] tests whether the sets [s1] and [s2] are @@ -95,15 +110,11 @@ Module Type S. (** [subset s1 s2] tests whether the set [s1] is a subset of the set [s2]. *) - (** Coq comment: [iter] is useless in a purely functional world *) - (** iter: (elt -> unit) -> set -> unit. i*) - (** [iter f s] applies [f] in turn to all elements of [s]. - The order in which the elements of [s] are presented to [f] - is unspecified. *) - - Parameter fold : forall A : Set, (elt -> A -> A) -> t -> A -> A. + Parameter fold : forall A : Type, (elt -> A -> A) -> t -> A -> A. (** [fold f s a] computes [(f xN ... (f x2 (f x1 a))...)], - where [x1 ... xN] are the elements of [s], in increasing order. *) + where [x1 ... xN] are the elements of [s]. + The order in which elements of [s] are presented to [f] is + unspecified. *) Parameter for_all : (elt -> bool) -> t -> bool. (** [for_all p s] checks if all elements of the set @@ -125,59 +136,39 @@ Module Type S. Parameter cardinal : t -> nat. (** Return the number of elements of a set. *) - (** Coq comment: nat instead of int ... *) Parameter elements : t -> list elt. - (** Return the list of all elements of the given set. - The returned list is sorted in increasing order with respect - to the ordering [Ord.compare], where [Ord] is the argument - given to {!Set.Make}. *) - - Parameter min_elt : t -> option elt. - (** Return the smallest element of the given set - (with respect to the [Ord.compare] ordering), or raise - [Not_found] if the set is empty. *) - (** Coq comment: [Not_found] is represented by the option type *) - - Parameter max_elt : t -> option elt. - (** Same as {!Set.S.min_elt}, but returns the largest element of the - given set. *) - (** Coq comment: [Not_found] is represented by the option type *) + (** Return the list of all elements of the given set, in any order. *) Parameter choose : t -> option elt. - (** Return one element of the given set, or raise [Not_found] if - the set is empty. Which element is chosen is unspecified, - but equal elements will be chosen for equal sets. *) - (** Coq comment: [Not_found] is represented by the option type *) + (** Return one element of the given set, or [None] if + the set is empty. Which element is chosen is unspecified. + Equal sets could return different elements. *) Section Spec. - Variable s s' s'' : t. + Variable s s' s'': t. Variable x y : elt. (** Specification of [In] *) Parameter In_1 : E.eq x y -> In x s -> In y s. - + (** Specification of [eq] *) Parameter eq_refl : eq s s. Parameter eq_sym : eq s s' -> eq s' s. Parameter eq_trans : eq s s' -> eq s' s'' -> eq s s''. - - (** Specification of [lt] *) - Parameter lt_trans : lt s s' -> lt s' s'' -> lt s s''. - Parameter lt_not_eq : lt s s' -> ~ eq s s'. (** Specification of [mem] *) Parameter mem_1 : In x s -> mem x s = true. Parameter mem_2 : mem x s = true -> In x s. (** Specification of [equal] *) - Parameter equal_1 : s[=]s' -> equal s s' = true. - Parameter equal_2 : equal s s' = true ->s[=]s'. + Parameter equal_1 : Equal s s' -> equal s s' = true. + Parameter equal_2 : equal s s' = true -> Equal s s'. (** Specification of [subset] *) - Parameter subset_1 : s[<=]s' -> subset s s' = true. - Parameter subset_2 : subset s s' = true -> s[<=]s'. + Parameter subset_1 : Subset s s' -> subset s s' = true. + Parameter subset_2 : subset s s' = true -> Subset s s'. (** Specification of [empty] *) Parameter empty_1 : Empty empty. @@ -216,7 +207,7 @@ Module Type S. Parameter diff_3 : In x s -> ~ In x s' -> In x (diff s s'). (** Specification of [fold] *) - Parameter fold_1 : forall (A : Set) (i : A) (f : elt -> A -> A), + Parameter fold_1 : forall (A : Type) (i : A) (f : elt -> A -> A), fold f s i = fold_left (fun a e => f e a) (elements s) i. (** Specification of [cardinal] *) @@ -249,18 +240,93 @@ Module Type S. exists_ f s = true -> Exists (fun x => f x = true) s. (** Specification of [partition] *) - Parameter partition_1 : compat_bool E.eq f -> - fst (partition f s) [=] filter f s. - Parameter partition_2 : compat_bool E.eq f -> - snd (partition f s) [=] filter (fun x => negb (f x)) s. + Parameter partition_1 : + compat_bool E.eq f -> Equal (fst (partition f s)) (filter f s). + Parameter partition_2 : + compat_bool E.eq f -> + Equal (snd (partition f s)) (filter (fun x => negb (f x)) s). End Filter. (** Specification of [elements] *) Parameter elements_1 : In x s -> InA E.eq x (elements s). Parameter elements_2 : InA E.eq x (elements s) -> In x s. + (** When compared with ordered sets, here comes the only + property that is really weaker: *) + Parameter elements_3w : NoDupA E.eq (elements s). + + (** Specification of [choose] *) + Parameter choose_1 : choose s = Some x -> In x s. + Parameter choose_2 : choose s = None -> Empty s. + + End Spec. + + Hint Resolve mem_1 equal_1 subset_1 empty_1 + is_empty_1 choose_1 choose_2 add_1 add_2 remove_1 + remove_2 singleton_2 union_1 union_2 union_3 + inter_3 diff_3 fold_1 filter_3 for_all_1 exists_1 + partition_1 partition_2 elements_1 elements_3w + : set. + Hint Immediate In_1 mem_2 equal_2 subset_2 is_empty_2 add_3 + remove_3 singleton_1 inter_1 inter_2 diff_1 diff_2 + filter_1 filter_2 for_all_2 exists_2 elements_2 + : set. + +End WSfun. + + + +(** ** Static signature for weak sets + + Similar to the functorial signature [SW], except that the + module [E] of base elements is incorporated in the signature. *) + +Module Type WS. + Declare Module E : EqualityType. + Include Type WSfun E. +End WS. + + + +(** ** Functorial signature for sets on ordered elements + + Based on [WSfun], plus ordering on sets and [min_elt] and [max_elt] + and some stronger specifications for other functions. *) + +Module Type Sfun (E : OrderedType). + Include Type WSfun E. + + Parameter lt : t -> t -> Prop. + Parameter compare : forall s s' : t, Compare lt eq s s'. + (** Total ordering between sets. Can be used as the ordering function + for doing sets of sets. *) + + Parameter min_elt : t -> option elt. + (** Return the smallest element of the given set + (with respect to the [E.compare] ordering), + or [None] if the set is empty. *) + + Parameter max_elt : t -> option elt. + (** Same as [min_elt], but returns the largest element of the + given set. *) + + Section Spec. + + Variable s s' s'' : t. + Variable x y : elt. + + (** Specification of [lt] *) + Parameter lt_trans : lt s s' -> lt s' s'' -> lt s s''. + Parameter lt_not_eq : lt s s' -> ~ eq s s'. + + (** Additional specification of [elements] *) Parameter elements_3 : sort E.lt (elements s). + (** Remark: since [fold] is specified via [elements], this stronger + specification of [elements] has an indirect impact on [fold], + which can now be proved to receive elements in increasing order. + *) + (** Specification of [min_elt] *) Parameter min_elt_1 : min_elt s = Some x -> In x s. Parameter min_elt_2 : min_elt s = Some x -> In y s -> ~ E.lt y x. @@ -271,37 +337,56 @@ Module Type S. Parameter max_elt_2 : max_elt s = Some x -> In y s -> ~ E.lt x y. Parameter max_elt_3 : max_elt s = None -> Empty s. - (** Specification of [choose] *) - Parameter choose_1 : choose s = Some x -> In x s. - Parameter choose_2 : choose s = None -> Empty s. -(* Parameter choose_equal: - (equal s s')=true -> E.eq (choose s) (choose s'). *) + (** Additional specification of [choose] *) + Parameter choose_3 : choose s = Some x -> choose s' = Some y -> + Equal s s' -> E.eq x y. End Spec. - (* begin hide *) - Hint Immediate In_1. - - Hint Resolve mem_1 mem_2 equal_1 equal_2 subset_1 subset_2 empty_1 - is_empty_1 is_empty_2 choose_1 choose_2 add_1 add_2 add_3 remove_1 - remove_2 remove_3 singleton_1 singleton_2 union_1 union_2 union_3 inter_1 - inter_2 inter_3 diff_1 diff_2 diff_3 filter_1 filter_2 filter_3 for_all_1 - for_all_2 exists_1 exists_2 partition_1 partition_2 elements_1 elements_2 - elements_3 min_elt_1 min_elt_2 min_elt_3 max_elt_1 max_elt_2 max_elt_3. - (* end hide *) + Hint Resolve elements_3 : set. + Hint Immediate + min_elt_1 min_elt_2 min_elt_3 max_elt_1 max_elt_2 max_elt_3 : set. + +End Sfun. + +(** ** Static signature for sets on ordered elements + + Similar to the functorial signature [Sfun], except that the + module [E] of base elements is incorporated in the signature. *) + +Module Type S. + Declare Module E : OrderedType. + Include Type Sfun E. End S. + +(** ** Some subtyping tests +<< +WSfun ---> WS + | | + | | + V V +Sfun ---> S + + +Module S_WS (M : S) <: SW := M. +Module Sfun_WSfun (E:OrderedType)(M : Sfun E) <: WSfun E := M. +Module S_Sfun (E:OrderedType)(M : S with Module E:=E) <: Sfun E := M. +Module WS_WSfun (E:EqualityType)(M : WS with Module E:=E) <: WSfun E := M. +>> +*) + (** * Dependent signature - Signature [Sdep] presents sets using dependent types *) + Signature [Sdep] presents ordered sets using dependent types *) Module Type Sdep. Declare Module E : OrderedType. Definition elt := E.t. - Parameter t : Set. + Parameter t : Type. Parameter In : elt -> t -> Prop. Definition Equal s s' := forall a : elt, In a s <-> In a s'. @@ -397,7 +482,7 @@ Module Type Sdep. Parameter fold : - forall (A : Set) (f : elt -> A -> A) (s : t) (i : A), + forall (A : Type) (f : elt -> A -> A) (s : t) (i : A), {r : A | let (l,_) := elements s in r = fold_left (fun a e => f e a) l i}. @@ -418,4 +503,14 @@ Module Type Sdep. Parameter choose : forall s : t, {x : elt | In x s} + {Empty s}. + (** The [choose_3] specification of [S] cannot be packed + in the dependent version of [choose], so we leave it separate. *) + Parameter choose_equal : forall s s', Equal s s' -> + match choose s, choose s' with + | inleft (exist x _), inleft (exist x' _) => E.eq x x' + | inright _, inright _ => True + | _, _ => False + end. + End Sdep. + diff --git a/theories/FSets/FSetList.v b/theories/FSets/FSetList.v index f6205542..a205d5b0 100644 --- a/theories/FSets/FSetList.v +++ b/theories/FSets/FSetList.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: FSetList.v 8834 2006-05-20 00:41:35Z letouzey $ *) +(* $Id: FSetList.v 10616 2008-03-04 17:33:35Z letouzey $ *) (** * Finite sets library *) @@ -25,7 +25,6 @@ Unset Strict Implicit. Module Raw (X: OrderedType). - Module E := X. Module MX := OrderedTypeFacts X. Import MX. @@ -145,7 +144,7 @@ Module Raw (X: OrderedType). | _, _ => false end. - Fixpoint fold (B : Set) (f : elt -> B -> B) (s : t) {struct s} : + Fixpoint fold (B : Type) (f : elt -> B -> B) (s : t) {struct s} : B -> B := fun i => match s with | nil => i | x :: l => fold f l (f x i) @@ -649,6 +648,11 @@ Module Raw (X: OrderedType). unfold elements; auto. Qed. + Lemma elements_3w : forall (s : t) (Hs : Sort s), NoDupA X.eq (elements s). + Proof. + unfold elements; auto. + Qed. + Lemma min_elt_1 : forall (s : t) (x : elt), min_elt s = Some x -> In x s. Proof. intro s; case s; simpl; intros; inversion H; auto. @@ -718,8 +722,21 @@ Module Raw (X: OrderedType). Definition choose_2 : forall s : t, choose s = None -> Empty s := min_elt_3. + Lemma choose_3: forall s s', Sort s -> Sort s' -> forall x x', + choose s = Some x -> choose s' = Some x' -> Equal s s' -> X.eq x x'. + Proof. + unfold choose, Equal; intros s s' Hs Hs' x x' Hx Hx' H. + assert (~X.lt x x'). + apply min_elt_2 with s'; auto. + rewrite <-H; auto using min_elt_1. + assert (~X.lt x' x). + apply min_elt_2 with s; auto. + rewrite H; auto using min_elt_1. + destruct (X.compare x x'); intuition. + Qed. + Lemma fold_1 : - forall (s : t) (Hs : Sort s) (A : Set) (i : A) (f : elt -> A -> A), + forall (s : t) (Hs : Sort s) (A : Type) (i : A) (f : elt -> A -> A), fold f s i = fold_left (fun a e => f e a) (elements s) i. Proof. induction s. @@ -1037,7 +1054,7 @@ Module Make (X: OrderedType) <: S with Module E := X. Module Raw := Raw X. Module E := X. - Record slist : Set := {this :> Raw.t; sorted : sort E.lt this}. + Record slist := {this :> Raw.t; sorted : sort E.lt this}. Definition t := slist. Definition elt := E.t. @@ -1066,7 +1083,7 @@ Module Make (X: OrderedType) <: S with Module E := X. Definition min_elt (s : t) : option elt := Raw.min_elt s. Definition max_elt (s : t) : option elt := Raw.max_elt s. Definition choose (s : t) : option elt := Raw.choose s. - Definition fold (B : Set) (f : elt -> B -> B) (s : t) : B -> B := Raw.fold (B:=B) f s. + Definition fold (B : Type) (f : elt -> B -> B) (s : t) : B -> B := Raw.fold (B:=B) f s. Definition cardinal (s : t) : nat := Raw.cardinal s. Definition filter (f : elt -> bool) (s : t) : t := Build_slist (Raw.filter_sort (sorted s) f). @@ -1149,7 +1166,7 @@ Module Make (X: OrderedType) <: S with Module E := X. Lemma diff_3 : In x s -> ~ In x s' -> In x (diff s s'). Proof. exact (fun H => Raw.diff_3 s.(sorted) s'.(sorted) H). Qed. - Lemma fold_1 : forall (A : Set) (i : A) (f : elt -> A -> A), + Lemma fold_1 : forall (A : Type) (i : A) (f : elt -> A -> A), fold f s i = fold_left (fun a e => f e a) (elements s) i. Proof. exact (Raw.fold_1 s.(sorted)). Qed. @@ -1202,6 +1219,8 @@ Module Make (X: OrderedType) <: S with Module E := X. Proof. exact (fun H => Raw.elements_2 H). Qed. Lemma elements_3 : sort E.lt (elements s). Proof. exact (Raw.elements_3 s.(sorted)). Qed. + Lemma elements_3w : NoDupA E.eq (elements s). + Proof. exact (Raw.elements_3w s.(sorted)). Qed. Lemma min_elt_1 : min_elt s = Some x -> In x s. Proof. exact (fun H => Raw.min_elt_1 H). Qed. @@ -1221,6 +1240,9 @@ Module Make (X: OrderedType) <: S with Module E := X. Proof. exact (fun H => Raw.choose_1 H). Qed. Lemma choose_2 : choose s = None -> Empty s. Proof. exact (fun H => Raw.choose_2 H). Qed. + Lemma choose_3 : choose s = Some x -> choose s' = Some y -> + Equal s s' -> E.eq x y. + Proof. exact (@Raw.choose_3 _ _ s.(sorted) s'.(sorted) x y). Qed. Lemma eq_refl : eq s s. Proof. exact (Raw.eq_refl s). Qed. diff --git a/theories/FSets/FSetProperties.v b/theories/FSets/FSetProperties.v index 6e93a546..7413b06b 100644 --- a/theories/FSets/FSetProperties.v +++ b/theories/FSets/FSetProperties.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: FSetProperties.v 8853 2006-05-23 18:17:38Z herbelin $ *) +(* $Id: FSetProperties.v 11064 2008-06-06 17:00:52Z letouzey $ *) (** * Finite sets library *) @@ -16,414 +16,259 @@ [In x s] instead of [mem x s=true], [Equal s s'] instead of [equal s s'=true], etc. *) -Require Export FSetInterface. -Require Import FSetFacts. +Require Export FSetInterface. +Require Import DecidableTypeEx FSetFacts FSetDecide. Set Implicit Arguments. Unset Strict Implicit. -Hint Unfold transpose compat_op compat_nat. +Hint Unfold transpose compat_op. Hint Extern 1 (Setoid_Theory _ _) => constructor; congruence. -Module Properties (M: S). - Module ME:=OrderedTypeFacts(M.E). - Import ME. (* for ME.eq_dec *) - Import M.E. - Import M. - Import Logic. (* to unmask [eq] *) - Import Peano. (* to unmask [lt] *) - - (** Results about lists without duplicates *) +(** First, a functor for Weak Sets. Since the signature [WS] includes + an EqualityType and not a stronger DecidableType, this functor + should take two arguments in order to compensate this. *) - Module FM := Facts M. - Import FM. - - Definition Add (x : elt) (s s' : t) := - forall y : elt, In y s' <-> E.eq x y \/ In y s. +Module WProperties (Import E : DecidableType)(M : WSfun E). + Module Import Dec := WDecide E M. + Module Import FM := Dec.F (* FSetFacts.WFacts E M *). + Import M. Lemma In_dec : forall x s, {In x s} + {~ In x s}. Proof. intros; generalize (mem_iff s x); case (mem x s); intuition. Qed. - Section BasicProperties. - - (** properties of [Equal] *) + Definition Add x s s' := forall y, In y s' <-> E.eq x y \/ In y s. - Lemma equal_refl : forall s, s[=]s. + Lemma Add_Equal : forall x s s', Add x s s' <-> s' [=] add x s. Proof. - unfold Equal; intuition. - Qed. - - Lemma equal_sym : forall s s', s[=]s' -> s'[=]s. - Proof. - unfold Equal; intros. - rewrite H; intuition. + unfold Add. + split; intros. + red; intros. + rewrite H; clear H. + fsetdec. + fsetdec. Qed. + + Ltac expAdd := repeat rewrite Add_Equal. - Lemma equal_trans : forall s1 s2 s3, s1[=]s2 -> s2[=]s3 -> s1[=]s3. - Proof. - unfold Equal; intros. - rewrite H; exact (H0 a). - Qed. + Section BasicProperties. Variable s s' s'' s1 s2 s3 : t. Variable x x' : elt. - (** properties of [Subset] *) - - Lemma subset_refl : s[<=]s. - Proof. - unfold Subset; intuition. - Qed. + Lemma equal_refl : s[=]s. + Proof. fsetdec. Qed. - Lemma subset_antisym : s[<=]s' -> s'[<=]s -> s[=]s'. - Proof. - unfold Subset, Equal; intuition. - Qed. + Lemma equal_sym : s[=]s' -> s'[=]s. + Proof. fsetdec. Qed. + + Lemma equal_trans : s1[=]s2 -> s2[=]s3 -> s1[=]s3. + Proof. fsetdec. Qed. + + Lemma subset_refl : s[<=]s. + Proof. fsetdec. Qed. Lemma subset_trans : s1[<=]s2 -> s2[<=]s3 -> s1[<=]s3. - Proof. - unfold Subset; intuition. - Qed. + Proof. fsetdec. Qed. + + Lemma subset_antisym : s[<=]s' -> s'[<=]s -> s[=]s'. + Proof. fsetdec. Qed. Lemma subset_equal : s[=]s' -> s[<=]s'. - Proof. - unfold Subset, Equal; firstorder. - Qed. + Proof. fsetdec. Qed. Lemma subset_empty : empty[<=]s. - Proof. - unfold Subset; intros a; set_iff; intuition. - Qed. + Proof. fsetdec. Qed. Lemma subset_remove_3 : s1[<=]s2 -> remove x s1 [<=] s2. - Proof. - unfold Subset; intros H a; set_iff; intuition. - Qed. + Proof. fsetdec. Qed. Lemma subset_diff : s1[<=]s3 -> diff s1 s2 [<=] s3. - Proof. - unfold Subset; intros H a; set_iff; intuition. - Qed. - + Proof. fsetdec. Qed. + Lemma subset_add_3 : In x s2 -> s1[<=]s2 -> add x s1 [<=] s2. - Proof. - unfold Subset; intros H H0 a; set_iff; intuition. - rewrite <- H2; auto. - Qed. + Proof. fsetdec. Qed. Lemma subset_add_2 : s1[<=]s2 -> s1[<=] add x s2. - Proof. - unfold Subset; intuition. - Qed. + Proof. fsetdec. Qed. Lemma in_subset : In x s1 -> s1[<=]s2 -> In x s2. - Proof. - unfold Subset; intuition. - Qed. + Proof. fsetdec. Qed. Lemma double_inclusion : s1[=]s2 <-> s1[<=]s2 /\ s2[<=]s1. - Proof. - unfold Subset, Equal; split; intros; intuition; generalize (H a); intuition. - Qed. - - (** properties of [empty] *) + Proof. intuition fsetdec. Qed. Lemma empty_is_empty_1 : Empty s -> s[=]empty. - Proof. - unfold Empty, Equal; intros; generalize (H a); set_iff; tauto. - Qed. + Proof. fsetdec. Qed. Lemma empty_is_empty_2 : s[=]empty -> Empty s. - Proof. - unfold Empty, Equal; intros; generalize (H a); set_iff; tauto. - Qed. - - (** properties of [add] *) + Proof. fsetdec. Qed. Lemma add_equal : In x s -> add x s [=] s. - Proof. - unfold Equal; intros; set_iff; intuition. - rewrite <- H1; auto. - Qed. + Proof. fsetdec. Qed. Lemma add_add : add x (add x' s) [=] add x' (add x s). - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. - - (** properties of [remove] *) + Proof. fsetdec. Qed. Lemma remove_equal : ~ In x s -> remove x s [=] s. - Proof. - unfold Equal; intros; set_iff; intuition. - rewrite H1 in H; auto. - Qed. + Proof. fsetdec. Qed. Lemma Equal_remove : s[=]s' -> remove x s [=] remove x s'. - Proof. - intros; rewrite H; apply equal_refl. - Qed. - - (** properties of [add] and [remove] *) + Proof. fsetdec. Qed. Lemma add_remove : In x s -> add x (remove x s) [=] s. - Proof. - unfold Equal; intros; set_iff; elim (eq_dec x a); intuition. - rewrite <- H1; auto. - Qed. + Proof. fsetdec. Qed. Lemma remove_add : ~In x s -> remove x (add x s) [=] s. - Proof. - unfold Equal; intros; set_iff; elim (eq_dec x a); intuition. - rewrite H1 in H; auto. - Qed. - - (** properties of [singleton] *) + Proof. fsetdec. Qed. Lemma singleton_equal_add : singleton x [=] add x empty. - Proof. - unfold Equal; intros; set_iff; intuition. - Qed. - - (** properties of [union] *) + Proof. fsetdec. Qed. Lemma union_sym : union s s' [=] union s' s. - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. + Proof. fsetdec. Qed. Lemma union_subset_equal : s[<=]s' -> union s s' [=] s'. - Proof. - unfold Subset, Equal; intros; set_iff; intuition. - Qed. + Proof. fsetdec. Qed. Lemma union_equal_1 : s[=]s' -> union s s'' [=] union s' s''. - Proof. - intros; rewrite H; apply equal_refl. - Qed. + Proof. fsetdec. Qed. Lemma union_equal_2 : s'[=]s'' -> union s s' [=] union s s''. - Proof. - intros; rewrite H; apply equal_refl. - Qed. + Proof. fsetdec. Qed. Lemma union_assoc : union (union s s') s'' [=] union s (union s' s''). - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. + Proof. fsetdec. Qed. Lemma add_union_singleton : add x s [=] union (singleton x) s. - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. + Proof. fsetdec. Qed. Lemma union_add : union (add x s) s' [=] add x (union s s'). - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. + Proof. fsetdec. Qed. + + Lemma union_remove_add_1 : + union (remove x s) (add x s') [=] union (add x s) (remove x s'). + Proof. fsetdec. Qed. + + Lemma union_remove_add_2 : In x s -> + union (remove x s) (add x s') [=] union s s'. + Proof. fsetdec. Qed. Lemma union_subset_1 : s [<=] union s s'. - Proof. - unfold Subset; intuition. - Qed. + Proof. fsetdec. Qed. Lemma union_subset_2 : s' [<=] union s s'. - Proof. - unfold Subset; intuition. - Qed. + Proof. fsetdec. Qed. Lemma union_subset_3 : s[<=]s'' -> s'[<=]s'' -> union s s' [<=] s''. - Proof. - unfold Subset; intros H H0 a; set_iff; intuition. - Qed. + Proof. fsetdec. Qed. Lemma union_subset_4 : s[<=]s' -> union s s'' [<=] union s' s''. - Proof. - unfold Subset; intros H a; set_iff; intuition. - Qed. + Proof. fsetdec. Qed. Lemma union_subset_5 : s[<=]s' -> union s'' s [<=] union s'' s'. - Proof. - unfold Subset; intros H a; set_iff; intuition. - Qed. + Proof. fsetdec. Qed. Lemma empty_union_1 : Empty s -> union s s' [=] s'. - Proof. - unfold Equal, Empty; intros; set_iff; firstorder. - Qed. + Proof. fsetdec. Qed. Lemma empty_union_2 : Empty s -> union s' s [=] s'. - Proof. - unfold Equal, Empty; intros; set_iff; firstorder. - Qed. + Proof. fsetdec. Qed. Lemma not_in_union : ~In x s -> ~In x s' -> ~In x (union s s'). - Proof. - intros; set_iff; intuition. - Qed. - - (** properties of [inter] *) + Proof. fsetdec. Qed. Lemma inter_sym : inter s s' [=] inter s' s. - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. + Proof. fsetdec. Qed. Lemma inter_subset_equal : s[<=]s' -> inter s s' [=] s. - Proof. - unfold Equal; intros; set_iff; intuition. - Qed. + Proof. fsetdec. Qed. Lemma inter_equal_1 : s[=]s' -> inter s s'' [=] inter s' s''. - Proof. - intros; rewrite H; apply equal_refl. - Qed. + Proof. fsetdec. Qed. Lemma inter_equal_2 : s'[=]s'' -> inter s s' [=] inter s s''. - Proof. - intros; rewrite H; apply equal_refl. - Qed. + Proof. fsetdec. Qed. Lemma inter_assoc : inter (inter s s') s'' [=] inter s (inter s' s''). - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. + Proof. fsetdec. Qed. Lemma union_inter_1 : inter (union s s') s'' [=] union (inter s s'') (inter s' s''). - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. + Proof. fsetdec. Qed. Lemma union_inter_2 : union (inter s s') s'' [=] inter (union s s'') (union s' s''). - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. + Proof. fsetdec. Qed. Lemma inter_add_1 : In x s' -> inter (add x s) s' [=] add x (inter s s'). - Proof. - unfold Equal; intros; set_iff; intuition. - rewrite <- H1; auto. - Qed. + Proof. fsetdec. Qed. Lemma inter_add_2 : ~ In x s' -> inter (add x s) s' [=] inter s s'. - Proof. - unfold Equal; intros; set_iff; intuition. - destruct H; rewrite H0; auto. - Qed. + Proof. fsetdec. Qed. Lemma empty_inter_1 : Empty s -> Empty (inter s s'). - Proof. - unfold Empty; intros; set_iff; firstorder. - Qed. + Proof. fsetdec. Qed. Lemma empty_inter_2 : Empty s' -> Empty (inter s s'). - Proof. - unfold Empty; intros; set_iff; firstorder. - Qed. + Proof. fsetdec. Qed. Lemma inter_subset_1 : inter s s' [<=] s. - Proof. - unfold Subset; intro a; set_iff; tauto. - Qed. + Proof. fsetdec. Qed. Lemma inter_subset_2 : inter s s' [<=] s'. - Proof. - unfold Subset; intro a; set_iff; tauto. - Qed. + Proof. fsetdec. Qed. Lemma inter_subset_3 : s''[<=]s -> s''[<=]s' -> s''[<=] inter s s'. - Proof. - unfold Subset; intros H H' a; set_iff; intuition. - Qed. - - (** properties of [diff] *) + Proof. fsetdec. Qed. Lemma empty_diff_1 : Empty s -> Empty (diff s s'). - Proof. - unfold Empty, Equal; intros; set_iff; firstorder. - Qed. + Proof. fsetdec. Qed. Lemma empty_diff_2 : Empty s -> diff s' s [=] s'. - Proof. - unfold Empty, Equal; intros; set_iff; firstorder. - Qed. + Proof. fsetdec. Qed. Lemma diff_subset : diff s s' [<=] s. - Proof. - unfold Subset; intros a; set_iff; tauto. - Qed. + Proof. fsetdec. Qed. Lemma diff_subset_equal : s[<=]s' -> diff s s' [=] empty. - Proof. - unfold Subset, Equal; intros; set_iff; intuition; absurd (In a empty); auto. - Qed. + Proof. fsetdec. Qed. Lemma remove_diff_singleton : remove x s [=] diff s (singleton x). - Proof. - unfold Equal; intros; set_iff; intuition. - Qed. + Proof. fsetdec. Qed. Lemma diff_inter_empty : inter (diff s s') (inter s s') [=] empty. - Proof. - unfold Equal; intros; set_iff; intuition; absurd (In a empty); auto. - Qed. + Proof. fsetdec. Qed. Lemma diff_inter_all : union (diff s s') (inter s s') [=] s. - Proof. - unfold Equal; intros; set_iff; intuition. - elim (In_dec a s'); auto. - Qed. - - (** properties of [Add] *) + Proof. fsetdec. Qed. Lemma Add_add : Add x s (add x s). - Proof. - unfold Add; intros; set_iff; intuition. - Qed. + Proof. expAdd; fsetdec. Qed. Lemma Add_remove : In x s -> Add x (remove x s) s. - Proof. - unfold Add; intros; set_iff; intuition. - elim (eq_dec x y); auto. - rewrite <- H1; auto. - Qed. + Proof. expAdd; fsetdec. Qed. Lemma union_Add : Add x s s' -> Add x (union s s'') (union s' s''). - Proof. - unfold Add; intros; set_iff; rewrite H; tauto. - Qed. + Proof. expAdd; fsetdec. Qed. Lemma inter_Add : In x s'' -> Add x s s' -> Add x (inter s s'') (inter s' s''). - Proof. - unfold Add; intros; set_iff; rewrite H0; intuition. - rewrite <- H2; auto. - Qed. + Proof. expAdd; fsetdec. Qed. Lemma union_Equal : In x s'' -> Add x s s' -> union s s'' [=] union s' s''. - Proof. - unfold Add, Equal; intros; set_iff; rewrite H0; intuition. - rewrite <- H1; auto. - Qed. + Proof. expAdd; fsetdec. Qed. Lemma inter_Add_2 : ~In x s'' -> Add x s s' -> inter s s'' [=] inter s' s''. - Proof. - unfold Add, Equal; intros; set_iff; rewrite H0; intuition. - destruct H; rewrite H1; auto. - Qed. + Proof. expAdd; fsetdec. Qed. End BasicProperties. - Hint Immediate equal_sym: set. - Hint Resolve equal_refl equal_trans : set. - - Hint Immediate add_remove remove_add union_sym inter_sym: set. - Hint Resolve subset_refl subset_equal subset_antisym + Hint Immediate equal_sym add_remove remove_add union_sym inter_sym: set. + Hint Resolve equal_refl equal_trans subset_refl subset_equal subset_antisym subset_trans subset_empty subset_remove_3 subset_diff subset_add_3 subset_add_2 in_subset empty_is_empty_1 empty_is_empty_2 add_equal remove_equal singleton_equal_add union_subset_equal union_equal_1 @@ -436,6 +281,31 @@ Module Properties (M: S). remove_diff_singleton diff_inter_empty diff_inter_all Add_add Add_remove Equal_remove add_add : set. + (** * Properties of elements *) + + Lemma elements_Empty : forall s, Empty s <-> elements s = nil. + Proof. + intros. + unfold Empty. + split; intros. + assert (forall a, ~ List.In a (elements s)). + red; intros. + apply (H a). + rewrite elements_iff. + rewrite InA_alt; exists a; auto. + destruct (elements s); auto. + elim (H0 e); simpl; auto. + red; intros. + rewrite elements_iff in H0. + rewrite InA_alt in H0; destruct H0. + rewrite H in H0; destruct H0 as (_,H0); inversion H0. + Qed. + + Lemma elements_empty : elements empty = nil. + Proof. + rewrite <-elements_Empty; auto with set. + Qed. + (** * Alternative (weaker) specifications for [fold] *) Section Old_Spec_Now_Properties. @@ -447,14 +317,14 @@ Module Properties (M: S). *) Lemma fold_0 : - forall s (A : Set) (i : A) (f : elt -> A -> A), + forall s (A : Type) (i : A) (f : elt -> A -> A), exists l : list elt, NoDup l /\ (forall x : elt, In x s <-> InA E.eq x l) /\ fold f s i = fold_right f i l. Proof. intros; exists (rev (elements s)); split. - apply NoDupA_rev; auto. + apply NoDupA_rev; auto with set. exact E.eq_trans. split; intros. rewrite elements_iff; do 2 rewrite InA_alt. @@ -468,7 +338,7 @@ Module Properties (M: S). [fold_2]. *) Lemma fold_1 : - forall s (A : Set) (eqA : A -> A -> Prop) + forall s (A : Type) (eqA : A -> A -> Prop) (st : Setoid_Theory A eqA) (i : A) (f : elt -> A -> A), Empty s -> eqA (fold f s i) i. Proof. @@ -481,7 +351,7 @@ Module Properties (M: S). Qed. Lemma fold_2 : - forall s s' x (A : Set) (eqA : A -> A -> Prop) + forall s s' x (A : Type) (eqA : A -> A -> Prop) (st : Setoid_Theory A eqA) (i : A) (f : elt -> A -> A), compat_op E.eq eqA f -> transpose eqA f -> @@ -492,9 +362,21 @@ Module Properties (M: S). rewrite Hl2; rewrite Hl'2; clear Hl2 Hl'2. apply fold_right_add with (eqA:=E.eq)(eqB:=eqA); auto. eauto. - exact eq_dec. rewrite <- Hl1; auto. - intros; rewrite <- Hl1; rewrite <- Hl'1; auto. + intros a; rewrite InA_cons; rewrite <- Hl1; rewrite <- Hl'1; + rewrite (H2 a); intuition. + Qed. + + (** In fact, [fold] on empty sets is more than equivalent to + the initial element, it is Leibniz-equal to it. *) + + Lemma fold_1b : + forall s (A : Type)(i : A) (f : elt -> A -> A), + Empty s -> (fold f s i) = i. + Proof. + intros. + rewrite M.fold_1. + rewrite elements_Empty in H; rewrite H; simpl; auto. Qed. (** Similar specifications for [cardinal]. *) @@ -531,41 +413,46 @@ Module Properties (M: S). (** * Induction principle over sets *) + Lemma cardinal_Empty : forall s, Empty s <-> cardinal s = 0. + Proof. + intros. + rewrite elements_Empty, M.cardinal_1. + destruct (elements s); intuition; discriminate. + Qed. + Lemma cardinal_inv_1 : forall s, cardinal s = 0 -> Empty s. - Proof. - intros s; rewrite M.cardinal_1; intros H a; red. - rewrite elements_iff. - destruct (elements s); simpl in *; discriminate || inversion 1. + Proof. + intros; rewrite cardinal_Empty; auto. Qed. Hint Resolve cardinal_inv_1. Lemma cardinal_inv_2 : forall s n, cardinal s = S n -> { x : elt | In x s }. Proof. - intros; rewrite M.cardinal_1 in H. - generalize (elements_2 (s:=s)). - destruct (elements s); try discriminate. - exists e; auto. + intros; rewrite M.cardinal_1 in H. + generalize (elements_2 (s:=s)). + destruct (elements s); try discriminate. + exists e; auto. Qed. - Lemma Equal_cardinal_aux : - forall n s s', cardinal s = n -> s[=]s' -> cardinal s = cardinal s'. + Lemma cardinal_inv_2b : + forall s, cardinal s <> 0 -> { x : elt | In x s }. Proof. - simple induction n; intros. - rewrite H; symmetry . - apply cardinal_1. - rewrite <- H0; auto. - destruct (cardinal_inv_2 H0) as (x,H2). - revert H0. - rewrite (cardinal_2 (s:=remove x s) (s':=s) (x:=x)); auto with set. - rewrite (cardinal_2 (s:=remove x s') (s':=s') (x:=x)); auto with set. - rewrite H1 in H2; auto with set. + intro; generalize (@cardinal_inv_2 s); destruct cardinal; + [intuition|eauto]. Qed. Lemma Equal_cardinal : forall s s', s[=]s' -> cardinal s = cardinal s'. Proof. - intros; apply Equal_cardinal_aux with (cardinal s); auto. - Qed. + symmetry. + remember (cardinal s) as n; symmetry in Heqn; revert s s' Heqn H. + induction n; intros. + apply cardinal_1; rewrite <- H; auto. + destruct (cardinal_inv_2 Heqn) as (x,H2). + revert Heqn. + rewrite (cardinal_2 (s:=remove x s) (s':=s) (x:=x)); auto with set. + rewrite (cardinal_2 (s:=remove x s') (s':=s') (x:=x)); eauto with set. + Qed. Add Morphism cardinal : cardinal_m. Proof. @@ -574,40 +461,33 @@ Module Properties (M: S). Hint Resolve Add_add Add_remove Equal_remove cardinal_inv_1 Equal_cardinal. - Lemma cardinal_induction : - forall P : t -> Type, - (forall s, Empty s -> P s) -> - (forall s s', P s -> forall x, ~In x s -> Add x s s' -> P s') -> - forall n s, cardinal s = n -> P s. - Proof. - simple induction n; intros; auto. - destruct (cardinal_inv_2 H) as (x,H0). - apply X0 with (remove x s) x; auto. - apply X1; auto. - rewrite (cardinal_2 (x:=x)(s:=remove x s)(s':=s)) in H; auto. - Qed. - Lemma set_induction : forall P : t -> Type, (forall s : t, Empty s -> P s) -> (forall s s' : t, P s -> forall x : elt, ~In x s -> Add x s s' -> P s') -> forall s : t, P s. Proof. - intros; apply cardinal_induction with (cardinal s); auto. - Qed. + intros; remember (cardinal s) as n; revert s Heqn; induction n; intros; auto. + destruct (cardinal_inv_2 (sym_eq Heqn)) as (x,H0). + apply X0 with (remove x s) x; auto with set. + apply IHn; auto. + assert (S n = S (cardinal (remove x s))). + rewrite Heqn; apply cardinal_2 with x; auto with set. + inversion H; auto. + Qed. (** Other properties of [fold]. *) Section Fold. - Variables (A:Set)(eqA:A->A->Prop)(st:Setoid_Theory _ eqA). + Variables (A:Type)(eqA:A->A->Prop)(st:Setoid_Theory _ eqA). Variables (f:elt->A->A)(Comp:compat_op E.eq eqA f)(Ass:transpose eqA f). Section Fold_1. Variable i i':A. - Lemma fold_empty : eqA (fold f empty i) i. + Lemma fold_empty : (fold f empty i) = i. Proof. - apply fold_1; auto. + apply fold_1b; auto with set. Qed. Lemma fold_equal : @@ -642,7 +522,7 @@ Module Properties (M: S). Proof. intros. sym_st. - apply fold_2 with (eqA:=eqA); auto. + apply fold_2 with (eqA:=eqA); auto with set. Qed. Lemma remove_fold_2: forall s x, ~In x s -> @@ -742,7 +622,8 @@ Module Properties (M: S). apply fold_1; auto with set. Qed. - Lemma fold_union: forall s s', (forall x, ~In x s\/~In x s') -> + Lemma fold_union: forall s s', + (forall x, ~(In x s/\In x s')) -> eqA (fold f (union s s') i) (fold f s (fold f s' i)). Proof. intros. @@ -760,8 +641,8 @@ Module Properties (M: S). forall s p, fold (fun _ => S) s p = fold (fun _ => S) s 0 + p. Proof. assert (st := gen_st nat). - assert (fe : compat_op E.eq (@eq _) (fun _ => S)) by (unfold compat_op; auto). - assert (fp : transpose (@eq _) (fun _:elt => S)) by (unfold transpose; auto). + assert (fe : compat_op E.eq (@Logic.eq _) (fun _ => S)) by (unfold compat_op; auto). + assert (fp : transpose (@Logic.eq _) (fun _:elt => S)) by (unfold transpose; auto). intros s p; pattern s; apply set_induction; clear s; intros. rewrite (fold_1 st p (fun _ => S) H). rewrite (fold_1 st 0 (fun _ => S) H); trivial. @@ -774,11 +655,11 @@ Module Properties (M: S). simpl; auto. Qed. - (** properties of [cardinal] *) + (** more properties of [cardinal] *) Lemma empty_cardinal : cardinal empty = 0. Proof. - rewrite cardinal_fold; apply fold_1; auto. + rewrite cardinal_fold; apply fold_1; auto with set. Qed. Hint Immediate empty_cardinal cardinal_1 : set. @@ -798,11 +679,11 @@ Module Properties (M: S). Proof. intros; do 3 rewrite cardinal_fold. rewrite <- fold_plus. - apply fold_diff_inter with (eqA:=@eq nat); auto. + apply fold_diff_inter with (eqA:=@Logic.eq nat); auto. Qed. Lemma union_cardinal: - forall s s', (forall x, ~In x s\/~In x s') -> + forall s s', (forall x, ~(In x s/\In x s')) -> cardinal (union s s')=cardinal s+cardinal s'. Proof. intros; do 3 rewrite cardinal_fold. @@ -841,7 +722,7 @@ Module Properties (M: S). intros. do 4 rewrite cardinal_fold. do 2 rewrite <- fold_plus. - apply fold_union_inter with (eqA:=@eq nat); auto. + apply fold_union_inter with (eqA:=@Logic.eq nat); auto. Qed. Lemma union_cardinal_inter : @@ -872,7 +753,7 @@ Module Properties (M: S). intros. do 2 rewrite cardinal_fold. change S with ((fun _ => S) x); - apply fold_add with (eqA:=@eq nat); auto. + apply fold_add with (eqA:=@Logic.eq nat); auto. Qed. Lemma remove_cardinal_1 : @@ -881,7 +762,7 @@ Module Properties (M: S). intros. do 2 rewrite cardinal_fold. change S with ((fun _ =>S) x). - apply remove_fold_1 with (eqA:=@eq nat); auto. + apply remove_fold_1 with (eqA:=@Logic.eq nat); auto. Qed. Lemma remove_cardinal_2 : @@ -892,4 +773,295 @@ Module Properties (M: S). Hint Resolve subset_cardinal union_cardinal add_cardinal_1 add_cardinal_2. +End WProperties. + + +(** A clone of [WProperties] working on full sets. *) + +Module Properties (M:S). + Module D := OT_as_DT M.E. + Include WProperties D M. End Properties. + + +(** Now comes some properties specific to the element ordering, + invalid for Weak Sets. *) + +Module OrdProperties (M:S). + Module ME:=OrderedTypeFacts(M.E). + Module Import P := Properties M. + Import FM. + Import M.E. + Import M. + + (** First, a specialized version of SortA_equivlistA_eqlistA: *) + Lemma sort_equivlistA_eqlistA : forall l l' : list elt, + sort E.lt l -> sort E.lt l' -> equivlistA E.eq l l' -> eqlistA E.eq l l'. + Proof. + apply SortA_equivlistA_eqlistA; eauto. + Qed. + + Definition gtb x y := match E.compare x y with GT _ => true | _ => false end. + Definition leb x := fun y => negb (gtb x y). + + Definition elements_lt x s := List.filter (gtb x) (elements s). + Definition elements_ge x s := List.filter (leb x) (elements s). + + Lemma gtb_1 : forall x y, gtb x y = true <-> E.lt y x. + Proof. + intros; unfold gtb; destruct (E.compare x y); intuition; try discriminate; ME.order. + Qed. + + Lemma leb_1 : forall x y, leb x y = true <-> ~E.lt y x. + Proof. + intros; unfold leb, gtb; destruct (E.compare x y); intuition; try discriminate; ME.order. + Qed. + + Lemma gtb_compat : forall x, compat_bool E.eq (gtb x). + Proof. + red; intros x a b H. + generalize (gtb_1 x a)(gtb_1 x b); destruct (gtb x a); destruct (gtb x b); auto. + intros. + symmetry; rewrite H1. + apply ME.eq_lt with a; auto. + rewrite <- H0; auto. + intros. + rewrite H0. + apply ME.eq_lt with b; auto. + rewrite <- H1; auto. + Qed. + + Lemma leb_compat : forall x, compat_bool E.eq (leb x). + Proof. + red; intros x a b H; unfold leb. + f_equal; apply gtb_compat; auto. + Qed. + Hint Resolve gtb_compat leb_compat. + + Lemma elements_split : forall x s, + elements s = elements_lt x s ++ elements_ge x s. + Proof. + unfold elements_lt, elements_ge, leb; intros. + eapply (@filter_split _ E.eq); eauto with set. ME.order. ME.order. ME.order. + intros. + rewrite gtb_1 in H. + assert (~E.lt y x). + unfold gtb in *; destruct (E.compare x y); intuition; try discriminate; ME.order. + ME.order. + Qed. + + Lemma elements_Add : forall s s' x, ~In x s -> Add x s s' -> + eqlistA E.eq (elements s') (elements_lt x s ++ x :: elements_ge x s). + Proof. + intros; unfold elements_ge, elements_lt. + apply sort_equivlistA_eqlistA; auto with set. + apply (@SortA_app _ E.eq); auto. + apply (@filter_sort _ E.eq); auto with set; eauto with set. + constructor; auto. + apply (@filter_sort _ E.eq); auto with set; eauto with set. + rewrite ME.Inf_alt by (apply (@filter_sort _ E.eq); eauto with set). + intros. + rewrite filter_InA in H1; auto; destruct H1. + rewrite leb_1 in H2. + rewrite <- elements_iff in H1. + assert (~E.eq x y). + contradict H; rewrite H; auto. + ME.order. + intros. + rewrite filter_InA in H1; auto; destruct H1. + rewrite gtb_1 in H3. + inversion_clear H2. + ME.order. + rewrite filter_InA in H4; auto; destruct H4. + rewrite leb_1 in H4. + ME.order. + red; intros a. + rewrite InA_app_iff; rewrite InA_cons. + do 2 (rewrite filter_InA; auto). + do 2 rewrite <- elements_iff. + rewrite leb_1; rewrite gtb_1. + rewrite (H0 a); intuition. + destruct (E.compare a x); intuition. + right; right; split; auto. + ME.order. + Qed. + + Definition Above x s := forall y, In y s -> E.lt y x. + Definition Below x s := forall y, In y s -> E.lt x y. + + Lemma elements_Add_Above : forall s s' x, + Above x s -> Add x s s' -> + eqlistA E.eq (elements s') (elements s ++ x::nil). + Proof. + intros. + apply sort_equivlistA_eqlistA; auto with set. + apply (@SortA_app _ E.eq); auto with set. + intros. + inversion_clear H2. + rewrite <- elements_iff in H1. + apply ME.lt_eq with x; auto. + inversion H3. + red; intros a. + rewrite InA_app_iff; rewrite InA_cons; rewrite InA_nil. + do 2 rewrite <- elements_iff; rewrite (H0 a); intuition. + Qed. + + Lemma elements_Add_Below : forall s s' x, + Below x s -> Add x s s' -> + eqlistA E.eq (elements s') (x::elements s). + Proof. + intros. + apply sort_equivlistA_eqlistA; auto with set. + change (sort E.lt ((x::nil) ++ elements s)). + apply (@SortA_app _ E.eq); auto with set. + intros. + inversion_clear H1. + rewrite <- elements_iff in H2. + apply ME.eq_lt with x; auto. + inversion H3. + red; intros a. + rewrite InA_cons. + do 2 rewrite <- elements_iff; rewrite (H0 a); intuition. + Qed. + + (** Two other induction principles on sets: we can be more restrictive + on the element we add at each step. *) + + Lemma set_induction_max : + forall P : t -> Type, + (forall s : t, Empty s -> P s) -> + (forall s s', P s -> forall x, Above x s -> Add x s s' -> P s') -> + forall s : t, P s. + Proof. + intros; remember (cardinal s) as n; revert s Heqn; induction n; intros; auto. + case_eq (max_elt s); intros. + apply X0 with (remove e s) e; auto with set. + apply IHn. + assert (S n = S (cardinal (remove e s))). + rewrite Heqn; apply cardinal_2 with e; auto with set. + inversion H0; auto. + red; intros. + rewrite remove_iff in H0; destruct H0. + generalize (@max_elt_2 s e y H H0); ME.order. + + assert (H0:=max_elt_3 H). + rewrite cardinal_Empty in H0; rewrite H0 in Heqn; inversion Heqn. + Qed. + + Lemma set_induction_min : + forall P : t -> Type, + (forall s : t, Empty s -> P s) -> + (forall s s', P s -> forall x, Below x s -> Add x s s' -> P s') -> + forall s : t, P s. + Proof. + intros; remember (cardinal s) as n; revert s Heqn; induction n; intros; auto. + case_eq (min_elt s); intros. + apply X0 with (remove e s) e; auto with set. + apply IHn. + assert (S n = S (cardinal (remove e s))). + rewrite Heqn; apply cardinal_2 with e; auto with set. + inversion H0; auto. + red; intros. + rewrite remove_iff in H0; destruct H0. + generalize (@min_elt_2 s e y H H0); ME.order. + + assert (H0:=min_elt_3 H). + rewrite cardinal_Empty in H0; auto; rewrite H0 in Heqn; inversion Heqn. + Qed. + + (** More properties of [fold] : behavior with respect to Above/Below *) + + Lemma fold_3 : + forall s s' x (A : Type) (eqA : A -> A -> Prop) + (st : Setoid_Theory A eqA) (i : A) (f : elt -> A -> A), + compat_op E.eq eqA f -> + Above x s -> Add x s s' -> eqA (fold f s' i) (f x (fold f s i)). + Proof. + intros. + do 2 rewrite M.fold_1. + do 2 rewrite <- fold_left_rev_right. + change (f x (fold_right f i (rev (elements s)))) with + (fold_right f i (rev (x::nil)++rev (elements s))). + apply (@fold_right_eqlistA E.t E.eq A eqA st); auto. + rewrite <- distr_rev. + apply eqlistA_rev. + apply elements_Add_Above; auto. + Qed. + + Lemma fold_4 : + forall s s' x (A : Type) (eqA : A -> A -> Prop) + (st : Setoid_Theory A eqA) (i : A) (f : elt -> A -> A), + compat_op E.eq eqA f -> + Below x s -> Add x s s' -> eqA (fold f s' i) (fold f s (f x i)). + Proof. + intros. + do 2 rewrite M.fold_1. + set (g:=fun (a : A) (e : elt) => f e a). + change (eqA (fold_left g (elements s') i) (fold_left g (x::elements s) i)). + unfold g. + do 2 rewrite <- fold_left_rev_right. + apply (@fold_right_eqlistA E.t E.eq A eqA st); auto. + apply eqlistA_rev. + apply elements_Add_Below; auto. + Qed. + + (** The following results have already been proved earlier, + but we can now prove them with one hypothesis less: + no need for [(transpose eqA f)]. *) + + Section FoldOpt. + Variables (A:Type)(eqA:A->A->Prop)(st:Setoid_Theory _ eqA). + Variables (f:elt->A->A)(Comp:compat_op E.eq eqA f). + + Lemma fold_equal : + forall i s s', s[=]s' -> eqA (fold f s i) (fold f s' i). + Proof. + intros; do 2 rewrite M.fold_1. + do 2 rewrite <- fold_left_rev_right. + apply (@fold_right_eqlistA E.t E.eq A eqA st); auto. + apply eqlistA_rev. + apply sort_equivlistA_eqlistA; auto with set. + red; intro a; do 2 rewrite <- elements_iff; auto. + Qed. + + Lemma fold_init : forall i i' s, eqA i i' -> + eqA (fold f s i) (fold f s i'). + Proof. + intros; do 2 rewrite M.fold_1. + do 2 rewrite <- fold_left_rev_right. + induction (rev (elements s)); simpl; auto. + Qed. + + Lemma add_fold : forall i s x, In x s -> + eqA (fold f (add x s) i) (fold f s i). + Proof. + intros; apply fold_equal; auto with set. + Qed. + + Lemma remove_fold_2: forall i s x, ~In x s -> + eqA (fold f (remove x s) i) (fold f s i). + Proof. + intros. + apply fold_equal; auto with set. + Qed. + + End FoldOpt. + + (** An alternative version of [choose_3] *) + + Lemma choose_equal : forall s s', Equal s s' -> + match choose s, choose s' with + | Some x, Some x' => E.eq x x' + | None, None => True + | _, _ => False + end. + Proof. + intros s s' H; + generalize (@choose_1 s)(@choose_2 s) + (@choose_1 s')(@choose_2 s')(@choose_3 s s'); + destruct (choose s); destruct (choose s'); simpl; intuition. + apply H5 with e; rewrite <-H; auto. + apply H5 with e; rewrite H; auto. + Qed. + +End OrdProperties. diff --git a/theories/FSets/FSetToFiniteSet.v b/theories/FSets/FSetToFiniteSet.v index 8cf85efe..ae51d905 100644 --- a/theories/FSets/FSetToFiniteSet.v +++ b/theories/FSets/FSetToFiniteSet.v @@ -11,16 +11,16 @@ * Institution: LRI, CNRS UMR 8623 - Université Paris Sud * 91405 Orsay, France *) -(* $Id: FSetToFiniteSet.v 8876 2006-05-30 13:43:15Z letouzey $ *) +(* $Id: FSetToFiniteSet.v 10739 2008-04-01 14:45:20Z herbelin $ *) Require Import Ensembles Finite_sets. -Require Import FSetInterface FSetProperties OrderedTypeEx. +Require Import FSetInterface FSetProperties OrderedTypeEx DecidableTypeEx. -(** * Going from [FSets] with usual equality - to the old [Ensembles] and [Finite_sets] theory. *) +(** * Going from [FSets] with usual Leibniz equality + to the good old [Ensembles] and [Finite_sets] theory. *) -Module S_to_Finite_set (U:UsualOrderedType)(M:S with Module E := U). - Module MP:= Properties(M). +Module WS_to_Finite_set (U:UsualDecidableType)(M: WSfun U). + Module MP:= WProperties U M. Import M MP FM Ensembles Finite_sets. Definition mkEns : M.t -> Ensemble M.elt := @@ -82,7 +82,7 @@ Module S_to_Finite_set (U:UsualOrderedType)(M:S with Module E := U). Lemma add_Add : forall x s, !!(add x s) === Add _ (!!s) x. Proof. unfold Same_set, Included, mkEns, In. - split; intro; set_iff; inversion 1; unfold E.eq; auto with sets. + split; intro; set_iff; inversion 1; auto with sets. inversion H0. constructor 2; constructor. constructor 1; auto. @@ -97,7 +97,7 @@ Module S_to_Finite_set (U:UsualOrderedType)(M:S with Module E := U). inversion H0. constructor 2; constructor. constructor 1; auto. - red in H; rewrite H; unfold E.eq in *. + red in H; rewrite H. inversion H0; auto. inversion H1; auto. Qed. @@ -105,10 +105,10 @@ Module S_to_Finite_set (U:UsualOrderedType)(M:S with Module E := U). Lemma remove_Subtract : forall x s, !!(remove x s) === Subtract _ (!!s) x. Proof. unfold Same_set, Included, mkEns, In. - split; intro; set_iff; inversion 1; unfold E.eq in *; auto with sets. + split; intro; set_iff; inversion 1; auto with sets. split; auto. - swap H1. - inversion H2; auto. + contradict H1. + inversion H1; auto. Qed. Lemma mkEns_Finite : forall s, Finite _ (!!s). @@ -136,4 +136,28 @@ Module S_to_Finite_set (U:UsualOrderedType)(M:S with Module E := U). apply Add_Add; auto. Qed. + (** we can even build a function from Finite Ensemble to FSet + ... at least in Prop. *) + + Lemma Ens_to_FSet : forall e : Ensemble M.elt, Finite _ e -> + exists s:M.t, !!s === e. + Proof. + induction 1. + exists M.empty. + apply empty_Empty_Set. + destruct IHFinite as (s,Hs). + exists (M.add x s). + apply Extensionality_Ensembles in Hs. + rewrite <- Hs. + apply add_Add. + Qed. + +End WS_to_Finite_set. + + +Module S_to_Finite_set (U:UsualOrderedType)(M: Sfun U). + Module D := OT_as_DT U. + Include WS_to_Finite_set D M. End S_to_Finite_set. + + diff --git a/theories/FSets/FSetWeak.v b/theories/FSets/FSetWeak.v deleted file mode 100644 index c88a7869..00000000 --- a/theories/FSets/FSetWeak.v +++ /dev/null @@ -1,16 +0,0 @@ -(***********************************************************************) -(* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) -(* \VV/ *************************************************************) -(* // * This file is distributed under the terms of the *) -(* * GNU Lesser General Public License Version 2.1 *) -(***********************************************************************) - -(* $Id: FSetWeak.v 9278 2006-10-25 13:43:17Z letouzey $ *) - -Require Export DecidableType. -Require Export DecidableTypeEx. -Require Export FSetWeakInterface. -Require Export FSetWeakFacts. -Require Export FSetWeakProperties. -Require Export FSetWeakList. diff --git a/theories/FSets/FSetWeakFacts.v b/theories/FSets/FSetWeakFacts.v deleted file mode 100644 index 61797a95..00000000 --- a/theories/FSets/FSetWeakFacts.v +++ /dev/null @@ -1,421 +0,0 @@ -(***********************************************************************) -(* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) -(* \VV/ *************************************************************) -(* // * This file is distributed under the terms of the *) -(* * GNU Lesser General Public License Version 2.1 *) -(***********************************************************************) - -(* $Id: FSetWeakFacts.v 8882 2006-05-31 21:55:30Z letouzey $ *) - -(** * Finite sets library *) - -(** This functor derives additional facts from [FSetInterface.S]. These - facts are mainly the specifications of [FSetInterface.S] written using - different styles: equivalence and boolean equalities. - Moreover, we prove that [E.Eq] and [Equal] are setoid equalities. -*) - -Require Export FSetWeakInterface. -Set Implicit Arguments. -Unset Strict Implicit. - -Module Facts (M: S). -Import M.E. -Import M. -Import Logic. (* to unmask [eq] *) - -(** * Specifications written using equivalences *) - -Section IffSpec. -Variable s s' s'' : t. -Variable x y z : elt. - -Lemma In_eq_iff : E.eq x y -> (In x s <-> In y s). -Proof. -split; apply In_1; auto. -Qed. - -Lemma mem_iff : In x s <-> mem x s = true. -Proof. -split; [apply mem_1|apply mem_2]. -Qed. - -Lemma not_mem_iff : ~In x s <-> mem x s = false. -Proof. -rewrite mem_iff; destruct (mem x s); intuition. -Qed. - -Lemma equal_iff : s[=]s' <-> equal s s' = true. -Proof. -split; [apply equal_1|apply equal_2]. -Qed. - -Lemma subset_iff : s[<=]s' <-> subset s s' = true. -Proof. -split; [apply subset_1|apply subset_2]. -Qed. - -Lemma empty_iff : In x empty <-> False. -Proof. -intuition; apply (empty_1 H). -Qed. - -Lemma is_empty_iff : Empty s <-> is_empty s = true. -Proof. -split; [apply is_empty_1|apply is_empty_2]. -Qed. - -Lemma singleton_iff : In y (singleton x) <-> E.eq x y. -Proof. -split; [apply singleton_1|apply singleton_2]. -Qed. - -Lemma add_iff : In y (add x s) <-> E.eq x y \/ In y s. -Proof. -split; [ | destruct 1; [apply add_1|apply add_2]]; auto. -destruct (eq_dec x y) as [E|E]; auto. -intro H; right; exact (add_3 E H). -Qed. - -Lemma add_neq_iff : ~ E.eq x y -> (In y (add x s) <-> In y s). -Proof. -split; [apply add_3|apply add_2]; auto. -Qed. - -Lemma remove_iff : In y (remove x s) <-> In y s /\ ~E.eq x y. -Proof. -split; [split; [apply remove_3 with x |] | destruct 1; apply remove_2]; auto. -intro. -apply (remove_1 H0 H). -Qed. - -Lemma remove_neq_iff : ~ E.eq x y -> (In y (remove x s) <-> In y s). -Proof. -split; [apply remove_3|apply remove_2]; auto. -Qed. - -Lemma union_iff : In x (union s s') <-> In x s \/ In x s'. -Proof. -split; [apply union_1 | destruct 1; [apply union_2|apply union_3]]; auto. -Qed. - -Lemma inter_iff : In x (inter s s') <-> In x s /\ In x s'. -Proof. -split; [split; [apply inter_1 with s' | apply inter_2 with s] | destruct 1; apply inter_3]; auto. -Qed. - -Lemma diff_iff : In x (diff s s') <-> In x s /\ ~ In x s'. -Proof. -split; [split; [apply diff_1 with s' | apply diff_2 with s] | destruct 1; apply diff_3]; auto. -Qed. - -Variable f : elt->bool. - -Lemma filter_iff : compat_bool E.eq f -> (In x (filter f s) <-> In x s /\ f x = true). -Proof. -split; [split; [apply filter_1 with f | apply filter_2 with s] | destruct 1; apply filter_3]; auto. -Qed. - -Lemma for_all_iff : compat_bool E.eq f -> - (For_all (fun x => f x = true) s <-> for_all f s = true). -Proof. -split; [apply for_all_1 | apply for_all_2]; auto. -Qed. - -Lemma exists_iff : compat_bool E.eq f -> - (Exists (fun x => f x = true) s <-> exists_ f s = true). -Proof. -split; [apply exists_1 | apply exists_2]; auto. -Qed. - -Lemma elements_iff : In x s <-> InA E.eq x (elements s). -Proof. -split; [apply elements_1 | apply elements_2]. -Qed. - -End IffSpec. - -(** Useful tactic for simplifying expressions like [In y (add x (union s s'))] *) - -Ltac set_iff := - repeat (progress ( - rewrite add_iff || rewrite remove_iff || rewrite singleton_iff - || rewrite union_iff || rewrite inter_iff || rewrite diff_iff - || rewrite empty_iff)). - -(** * Specifications written using boolean predicates *) - -Definition eqb x y := if eq_dec x y then true else false. - -Section BoolSpec. -Variable s s' s'' : t. -Variable x y z : elt. - -Lemma mem_b : E.eq x y -> mem x s = mem y s. -Proof. -intros. -generalize (mem_iff s x) (mem_iff s y)(In_eq_iff s H). -destruct (mem x s); destruct (mem y s); intuition. -Qed. - -Lemma empty_b : mem y empty = false. -Proof. -generalize (empty_iff y)(mem_iff empty y). -destruct (mem y empty); intuition. -Qed. - -Lemma add_b : mem y (add x s) = eqb x y || mem y s. -Proof. -generalize (mem_iff (add x s) y)(mem_iff s y)(add_iff s x y); unfold eqb. -destruct (eq_dec x y); destruct (mem y s); destruct (mem y (add x s)); intuition. -Qed. - -Lemma add_neq_b : ~ E.eq x y -> mem y (add x s) = mem y s. -Proof. -intros; generalize (mem_iff (add x s) y)(mem_iff s y)(add_neq_iff s H). -destruct (mem y s); destruct (mem y (add x s)); intuition. -Qed. - -Lemma remove_b : mem y (remove x s) = mem y s && negb (eqb x y). -Proof. -generalize (mem_iff (remove x s) y)(mem_iff s y)(remove_iff s x y); unfold eqb. -destruct (eq_dec x y); destruct (mem y s); destruct (mem y (remove x s)); simpl; intuition. -Qed. - -Lemma remove_neq_b : ~ E.eq x y -> mem y (remove x s) = mem y s. -Proof. -intros; generalize (mem_iff (remove x s) y)(mem_iff s y)(remove_neq_iff s H). -destruct (mem y s); destruct (mem y (remove x s)); intuition. -Qed. - -Lemma singleton_b : mem y (singleton x) = eqb x y. -Proof. -generalize (mem_iff (singleton x) y)(singleton_iff x y); unfold eqb. -destruct (eq_dec x y); destruct (mem y (singleton x)); intuition. -Qed. - -Lemma union_b : mem x (union s s') = mem x s || mem x s'. -Proof. -generalize (mem_iff (union s s') x)(mem_iff s x)(mem_iff s' x)(union_iff s s' x). -destruct (mem x s); destruct (mem x s'); destruct (mem x (union s s')); intuition. -Qed. - -Lemma inter_b : mem x (inter s s') = mem x s && mem x s'. -Proof. -generalize (mem_iff (inter s s') x)(mem_iff s x)(mem_iff s' x)(inter_iff s s' x). -destruct (mem x s); destruct (mem x s'); destruct (mem x (inter s s')); intuition. -Qed. - -Lemma diff_b : mem x (diff s s') = mem x s && negb (mem x s'). -Proof. -generalize (mem_iff (diff s s') x)(mem_iff s x)(mem_iff s' x)(diff_iff s s' x). -destruct (mem x s); destruct (mem x s'); destruct (mem x (diff s s')); simpl; intuition. -Qed. - -Lemma elements_b : mem x s = existsb (eqb x) (elements s). -Proof. -generalize (mem_iff s x)(elements_iff s x)(existsb_exists (eqb x) (elements s)). -rewrite InA_alt. -destruct (mem x s); destruct (existsb (eqb x) (elements s)); auto; intros. -symmetry. -rewrite H1. -destruct H0 as (H0,_). -destruct H0 as (a,(Ha1,Ha2)); [ intuition |]. -exists a; intuition. -unfold eqb; destruct (eq_dec x a); auto. -rewrite <- H. -rewrite H0. -destruct H1 as (H1,_). -destruct H1 as (a,(Ha1,Ha2)); [intuition|]. -exists a; intuition. -unfold eqb in *; destruct (eq_dec x a); auto; discriminate. -Qed. - -Variable f : elt->bool. - -Lemma filter_b : compat_bool E.eq f -> mem x (filter f s) = mem x s && f x. -Proof. -intros. -generalize (mem_iff (filter f s) x)(mem_iff s x)(filter_iff s x H). -destruct (mem x s); destruct (mem x (filter f s)); destruct (f x); simpl; intuition. -Qed. - -Lemma for_all_b : compat_bool E.eq f -> - for_all f s = forallb f (elements s). -Proof. -intros. -generalize (forallb_forall f (elements s))(for_all_iff s H)(elements_iff s). -unfold For_all. -destruct (forallb f (elements s)); destruct (for_all f s); auto; intros. -rewrite <- H1; intros. -destruct H0 as (H0,_). -rewrite (H2 x0) in H3. -rewrite (InA_alt E.eq x0 (elements s)) in H3. -destruct H3 as (a,(Ha1,Ha2)). -rewrite (H _ _ Ha1). -apply H0; auto. -symmetry. -rewrite H0; intros. -destruct H1 as (_,H1). -apply H1; auto. -rewrite H2. -rewrite InA_alt; eauto. -Qed. - -Lemma exists_b : compat_bool E.eq f -> - exists_ f s = existsb f (elements s). -Proof. -intros. -generalize (existsb_exists f (elements s))(exists_iff s H)(elements_iff s). -unfold Exists. -destruct (existsb f (elements s)); destruct (exists_ f s); auto; intros. -rewrite <- H1; intros. -destruct H0 as (H0,_). -destruct H0 as (a,(Ha1,Ha2)); auto. -exists a; auto. -split; auto. -rewrite H2; rewrite InA_alt; eauto. -symmetry. -rewrite H0. -destruct H1 as (_,H1). -destruct H1 as (a,(Ha1,Ha2)); auto. -rewrite (H2 a) in Ha1. -rewrite (InA_alt E.eq a (elements s)) in Ha1. -destruct Ha1 as (b,(Hb1,Hb2)). -exists b; auto. -rewrite <- (H _ _ Hb1); auto. -Qed. - -End BoolSpec. - -(** * [E.eq] and [Equal] are setoid equalities *) - -Definition E_ST : Setoid_Theory elt E.eq. -Proof. -constructor; [apply E.eq_refl|apply E.eq_sym|apply E.eq_trans]. -Qed. - -Add Setoid elt E.eq E_ST as EltSetoid. - -Definition Equal_ST : Setoid_Theory t Equal. -Proof. -constructor; unfold Equal; firstorder. -Qed. - -Add Setoid t Equal Equal_ST as EqualSetoid. - -Add Morphism In with signature E.eq ==> Equal ==> iff as In_m. -Proof. -unfold Equal; intros x y H s s' H0. -rewrite (In_eq_iff s H); auto. -Qed. - -Add Morphism is_empty : is_empty_m. -Proof. -unfold Equal; intros s s' H. -generalize (is_empty_iff s)(is_empty_iff s'). -destruct (is_empty s); destruct (is_empty s'); - unfold Empty; auto; intros. -symmetry. -rewrite <- H1; intros a Ha. -rewrite <- (H a) in Ha. -destruct H0 as (_,H0). -exact (H0 (refl_equal true) _ Ha). -rewrite <- H0; intros a Ha. -rewrite (H a) in Ha. -destruct H1 as (_,H1). -exact (H1 (refl_equal true) _ Ha). -Qed. - -Add Morphism Empty with signature Equal ==> iff as Empty_m. -Proof. -intros; do 2 rewrite is_empty_iff; rewrite H; intuition. -Qed. - -Add Morphism mem : mem_m. -Proof. -unfold Equal; intros x y H s s' H0. -generalize (H0 x); clear H0; rewrite (In_eq_iff s' H). -generalize (mem_iff s x)(mem_iff s' y). -destruct (mem x s); destruct (mem y s'); intuition. -Qed. - -Add Morphism singleton : singleton_m. -Proof. -unfold Equal; intros x y H a. -do 2 rewrite singleton_iff; split. -intros; apply E.eq_trans with x; auto. -intros; apply E.eq_trans with y; auto. -Qed. - -Add Morphism add : add_m. -Proof. -unfold Equal; intros x y H s s' H0 a. -do 2 rewrite add_iff; rewrite H; rewrite H0; intuition. -Qed. - -Add Morphism remove : remove_m. -Proof. -unfold Equal; intros x y H s s' H0 a. -do 2 rewrite remove_iff; rewrite H; rewrite H0; intuition. -Qed. - -Add Morphism union : union_m. -Proof. -unfold Equal; intros s s' H s'' s''' H0 a. -do 2 rewrite union_iff; rewrite H; rewrite H0; intuition. -Qed. - -Add Morphism inter : inter_m. -Proof. -unfold Equal; intros s s' H s'' s''' H0 a. -do 2 rewrite inter_iff; rewrite H; rewrite H0; intuition. -Qed. - -Add Morphism diff : diff_m. -Proof. -unfold Equal; intros s s' H s'' s''' H0 a. -do 2 rewrite diff_iff; rewrite H; rewrite H0; intuition. -Qed. - -Add Morphism Subset with signature Equal ==> Equal ==> iff as Subset_m. -Proof. -unfold Equal, Subset; firstorder. -Qed. - -Add Morphism subset : subset_m. -Proof. -intros s s' H s'' s''' H0. -generalize (subset_iff s s'') (subset_iff s' s'''). -destruct (subset s s''); destruct (subset s' s'''); auto; intros. -rewrite H in H1; rewrite H0 in H1; intuition. -rewrite H in H1; rewrite H0 in H1; intuition. -Qed. - -Add Morphism equal : equal_m. -Proof. -intros s s' H s'' s''' H0. -generalize (equal_iff s s'') (equal_iff s' s'''). -destruct (equal s s''); destruct (equal s' s'''); auto; intros. -rewrite H in H1; rewrite H0 in H1; intuition. -rewrite H in H1; rewrite H0 in H1; intuition. -Qed. - -(* [fold], [filter], [for_all], [exists_] and [partition] cannot be proved morphism - without additional hypothesis on [f]. For instance: *) - -Lemma filter_equal : forall f, compat_bool E.eq f -> - forall s s', s[=]s' -> filter f s [=] filter f s'. -Proof. -unfold Equal; intros; repeat rewrite filter_iff; auto; rewrite H0; tauto. -Qed. - -(* For [elements], [min_elt], [max_elt] and [choose], we would need setoid - structures on [list elt] and [option elt]. *) - -(* Later: -Add Morphism cardinal ; cardinal_m. -*) - -End Facts. diff --git a/theories/FSets/FSetWeakInterface.v b/theories/FSets/FSetWeakInterface.v deleted file mode 100644 index a281ce22..00000000 --- a/theories/FSets/FSetWeakInterface.v +++ /dev/null @@ -1,251 +0,0 @@ -(***********************************************************************) -(* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) -(* \VV/ *************************************************************) -(* // * This file is distributed under the terms of the *) -(* * GNU Lesser General Public License Version 2.1 *) -(***********************************************************************) - -(* $Id: FSetWeakInterface.v 8820 2006-05-15 11:44:05Z letouzey $ *) - -(** * Finite sets library *) - -(** Set interfaces for types with only a decidable equality, but no ordering *) - -Require Export Bool. -Require Export DecidableType. -Set Implicit Arguments. -Unset Strict Implicit. - -(** Compatibility of a boolean function with respect to an equality. *) -Definition compat_bool (A:Set)(eqA: A->A->Prop)(f: A-> bool) := - forall x y : A, eqA x y -> f x = f y. - -(** Compatibility of a predicate with respect to an equality. *) -Definition compat_P (A:Set)(eqA: A->A->Prop)(P : A -> Prop) := - forall x y : A, eqA x y -> P x -> P y. - -Hint Unfold compat_bool compat_P. - -(** * Non-dependent signature - - Signature [S] presents sets as purely informative programs - together with axioms *) - -Module Type S. - - Declare Module E : DecidableType. - Definition elt := E.t. - - Parameter t : Set. (** the abstract type of sets *) - - (** Logical predicates *) - Parameter In : elt -> t -> Prop. - Definition Equal s s' := forall a : elt, In a s <-> In a s'. - Definition Subset s s' := forall a : elt, In a s -> In a s'. - Definition Empty s := forall a : elt, ~ In a s. - Definition For_all (P : elt -> Prop) s := forall x, In x s -> P x. - Definition Exists (P : elt -> Prop) s := exists x, In x s /\ P x. - - Notation "s [=] t" := (Equal s t) (at level 70, no associativity). - Notation "s [<=] t" := (Subset s t) (at level 70, no associativity). - - Parameter empty : t. - (** The empty set. *) - - Parameter is_empty : t -> bool. - (** Test whether a set is empty or not. *) - - Parameter mem : elt -> t -> bool. - (** [mem x s] tests whether [x] belongs to the set [s]. *) - - Parameter add : elt -> t -> t. - (** [add x s] returns a set containing all elements of [s], - plus [x]. If [x] was already in [s], [s] is returned unchanged. *) - - Parameter singleton : elt -> t. - (** [singleton x] returns the one-element set containing only [x]. *) - - Parameter remove : elt -> t -> t. - (** [remove x s] returns a set containing all elements of [s], - except [x]. If [x] was not in [s], [s] is returned unchanged. *) - - Parameter union : t -> t -> t. - (** Set union. *) - - Parameter inter : t -> t -> t. - (** Set intersection. *) - - Parameter diff : t -> t -> t. - (** Set difference. *) - - Parameter equal : t -> t -> bool. - (** [equal s1 s2] tests whether the sets [s1] and [s2] are - equal, that is, contain equal elements. *) - - Parameter subset : t -> t -> bool. - (** [subset s1 s2] tests whether the set [s1] is a subset of - the set [s2]. *) - - (** Coq comment: [iter] is useless in a purely functional world *) - (** iter: (elt -> unit) -> set -> unit. i*) - (** [iter f s] applies [f] in turn to all elements of [s]. - The order in which the elements of [s] are presented to [f] - is unspecified. *) - - Parameter fold : forall A : Set, (elt -> A -> A) -> t -> A -> A. - (** [fold f s a] computes [(f xN ... (f x2 (f x1 a))...)], - where [x1 ... xN] are the elements of [s]. - The order in which elements of [s] are presented to [f] is - unspecified. *) - - Parameter for_all : (elt -> bool) -> t -> bool. - (** [for_all p s] checks if all elements of the set - satisfy the predicate [p]. *) - - Parameter exists_ : (elt -> bool) -> t -> bool. - (** [exists p s] checks if at least one element of - the set satisfies the predicate [p]. *) - - Parameter filter : (elt -> bool) -> t -> t. - (** [filter p s] returns the set of all elements in [s] - that satisfy predicate [p]. *) - - Parameter partition : (elt -> bool) -> t -> t * t. - (** [partition p s] returns a pair of sets [(s1, s2)], where - [s1] is the set of all the elements of [s] that satisfy the - predicate [p], and [s2] is the set of all the elements of - [s] that do not satisfy [p]. *) - - Parameter cardinal : t -> nat. - (** Return the number of elements of a set. *) - (** Coq comment: nat instead of int ... *) - - Parameter elements : t -> list elt. - (** Return the list of all elements of the given set, in any order. *) - - Parameter choose : t -> option elt. - (** Return one element of the given set, or raise [Not_found] if - the set is empty. Which element is chosen is unspecified. - Equal sets could return different elements. *) - (** Coq comment: [Not_found] is represented by the option type *) - - Section Spec. - - Variable s s' : t. - Variable x y : elt. - - (** Specification of [In] *) - Parameter In_1 : E.eq x y -> In x s -> In y s. - - (** Specification of [mem] *) - Parameter mem_1 : In x s -> mem x s = true. - Parameter mem_2 : mem x s = true -> In x s. - - (** Specification of [equal] *) - Parameter equal_1 : Equal s s' -> equal s s' = true. - Parameter equal_2 : equal s s' = true -> Equal s s'. - - (** Specification of [subset] *) - Parameter subset_1 : Subset s s' -> subset s s' = true. - Parameter subset_2 : subset s s' = true -> Subset s s'. - - (** Specification of [empty] *) - Parameter empty_1 : Empty empty. - - (** Specification of [is_empty] *) - Parameter is_empty_1 : Empty s -> is_empty s = true. - Parameter is_empty_2 : is_empty s = true -> Empty s. - - (** Specification of [add] *) - Parameter add_1 : E.eq x y -> In y (add x s). - Parameter add_2 : In y s -> In y (add x s). - Parameter add_3 : ~ E.eq x y -> In y (add x s) -> In y s. - - (** Specification of [remove] *) - Parameter remove_1 : E.eq x y -> ~ In y (remove x s). - Parameter remove_2 : ~ E.eq x y -> In y s -> In y (remove x s). - Parameter remove_3 : In y (remove x s) -> In y s. - - (** Specification of [singleton] *) - Parameter singleton_1 : In y (singleton x) -> E.eq x y. - Parameter singleton_2 : E.eq x y -> In y (singleton x). - - (** Specification of [union] *) - Parameter union_1 : In x (union s s') -> In x s \/ In x s'. - Parameter union_2 : In x s -> In x (union s s'). - Parameter union_3 : In x s' -> In x (union s s'). - - (** Specification of [inter] *) - Parameter inter_1 : In x (inter s s') -> In x s. - Parameter inter_2 : In x (inter s s') -> In x s'. - Parameter inter_3 : In x s -> In x s' -> In x (inter s s'). - - (** Specification of [diff] *) - Parameter diff_1 : In x (diff s s') -> In x s. - Parameter diff_2 : In x (diff s s') -> ~ In x s'. - Parameter diff_3 : In x s -> ~ In x s' -> In x (diff s s'). - - (** Specification of [fold] *) - Parameter fold_1 : forall (A : Set) (i : A) (f : elt -> A -> A), - fold f s i = fold_left (fun a e => f e a) (elements s) i. - - (** Specification of [cardinal] *) - Parameter cardinal_1 : cardinal s = length (elements s). - - Section Filter. - - Variable f : elt -> bool. - - (** Specification of [filter] *) - Parameter filter_1 : compat_bool E.eq f -> In x (filter f s) -> In x s. - Parameter filter_2 : compat_bool E.eq f -> In x (filter f s) -> f x = true. - Parameter filter_3 : - compat_bool E.eq f -> In x s -> f x = true -> In x (filter f s). - - (** Specification of [for_all] *) - Parameter for_all_1 : - compat_bool E.eq f -> - For_all (fun x => f x = true) s -> for_all f s = true. - Parameter for_all_2 : - compat_bool E.eq f -> - for_all f s = true -> For_all (fun x => f x = true) s. - - (** Specification of [exists] *) - Parameter exists_1 : - compat_bool E.eq f -> - Exists (fun x => f x = true) s -> exists_ f s = true. - Parameter exists_2 : - compat_bool E.eq f -> - exists_ f s = true -> Exists (fun x => f x = true) s. - - (** Specification of [partition] *) - Parameter partition_1 : - compat_bool E.eq f -> Equal (fst (partition f s)) (filter f s). - Parameter partition_2 : - compat_bool E.eq f -> - Equal (snd (partition f s)) (filter (fun x => negb (f x)) s). - - End Filter. - - (** Specification of [elements] *) - Parameter elements_1 : In x s -> InA E.eq x (elements s). - Parameter elements_2 : InA E.eq x (elements s) -> In x s. - Parameter elements_3 : NoDupA E.eq (elements s). - - (** Specification of [choose] *) - Parameter choose_1 : choose s = Some x -> In x s. - Parameter choose_2 : choose s = None -> Empty s. - - End Spec. - - Hint Immediate In_1. - - Hint Resolve mem_1 mem_2 equal_1 equal_2 subset_1 subset_2 empty_1 - is_empty_1 is_empty_2 choose_1 choose_2 add_1 add_2 add_3 remove_1 - remove_2 remove_3 singleton_1 singleton_2 union_1 union_2 union_3 inter_1 - inter_2 inter_3 diff_1 diff_2 diff_3 filter_1 filter_2 filter_3 for_all_1 - for_all_2 exists_1 exists_2 partition_1 partition_2 elements_1 elements_2 - elements_3. - -End S. diff --git a/theories/FSets/FSetWeakList.v b/theories/FSets/FSetWeakList.v index 97080b7a..71a0d584 100644 --- a/theories/FSets/FSetWeakList.v +++ b/theories/FSets/FSetWeakList.v @@ -6,14 +6,14 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: FSetWeakList.v 8834 2006-05-20 00:41:35Z letouzey $ *) +(* $Id: FSetWeakList.v 10631 2008-03-06 18:17:24Z msozeau $ *) (** * Finite sets library *) (** This file proposes an implementation of the non-dependant interface [FSetWeakInterface.S] using lists without redundancy. *) -Require Import FSetWeakInterface. +Require Import FSetInterface. Set Implicit Arguments. Unset Strict Implicit. @@ -24,8 +24,6 @@ Unset Strict Implicit. And the functions returning sets are proved to preserve this invariant. *) Module Raw (X: DecidableType). - - Module E := X. Definition elt := X.t. Definition t := list elt. @@ -59,7 +57,7 @@ Module Raw (X: DecidableType). if X.eq_dec x y then l else y :: remove x l end. - Fixpoint fold (B : Set) (f : elt -> B -> B) (s : t) {struct s} : + Fixpoint fold (B : Type) (f : elt -> B -> B) (s : t) {struct s} : B -> B := fun i => match s with | nil => i | x :: l => fold f l (f x i) @@ -127,7 +125,7 @@ Module Raw (X: DecidableType). Lemma In_eq : forall (s : t) (x y : elt), X.eq x y -> In x s -> In y s. Proof. - intros s x y; do 2 setoid_rewrite InA_alt; firstorder eauto. + intros s x y; setoid_rewrite InA_alt; firstorder eauto. Qed. Hint Immediate In_eq. @@ -287,13 +285,13 @@ Module Raw (X: DecidableType). unfold elements; auto. Qed. - Lemma elements_3 : forall (s : t) (Hs : NoDup s), NoDup (elements s). + Lemma elements_3w : forall (s : t) (Hs : NoDup s), NoDup (elements s). Proof. unfold elements; auto. Qed. Lemma fold_1 : - forall (s : t) (Hs : NoDup s) (A : Set) (i : A) (f : elt -> A -> A), + forall (s : t) (Hs : NoDup s) (A : Type) (i : A) (f : elt -> A -> A), fold f s i = fold_left (fun a e => f e a) (elements s) i. Proof. induction s; simpl; auto; intros. @@ -732,22 +730,68 @@ Module Raw (X: DecidableType). generalize (Hrec H0 f). case (f x); case (partition f l); simpl; auto. Qed. - + Definition eq : t -> t -> Prop := Equal. - Lemma eq_refl : forall s : t, eq s s. - Proof. - unfold eq, Equal; intuition. - Qed. + Lemma eq_refl : forall s, eq s s. + Proof. firstorder. Qed. - Lemma eq_sym : forall s s' : t, eq s s' -> eq s' s. - Proof. - unfold eq, Equal; firstorder. - Qed. + Lemma eq_sym : forall s s', eq s s' -> eq s' s. + Proof. firstorder. Qed. - Lemma eq_trans : forall s s' s'' : t, eq s s' -> eq s' s'' -> eq s s''. - Proof. - unfold eq, Equal; firstorder. + Lemma eq_trans : + forall s s' s'', eq s s' -> eq s' s'' -> eq s s''. + Proof. firstorder. Qed. + + Definition eq_dec : forall (s s':t)(Hs:NoDup s)(Hs':NoDup s'), + { eq s s' }+{ ~eq s s' }. + Proof. + unfold eq. + induction s; intros s'. + (* nil *) + destruct s'; [left|right]. + firstorder. + unfold not, Equal. + intros H; generalize (H e); clear H. + rewrite InA_nil, InA_cons; intuition. + (* cons *) + intros. + case_eq (mem a s'); intros H; + [ destruct (IHs (remove a s')) as [H'|H']; + [ | | left|right]|right]; + clear IHs. + inversion_clear Hs; auto. + apply remove_unique; auto. + (* In a s' /\ s [=] remove a s' *) + generalize (mem_2 H); clear H; intro H. + unfold Equal in *; intros b. + rewrite InA_cons; split. + destruct 1. + apply In_eq with a; auto. + rewrite H' in H0. + apply remove_3 with a; auto. + destruct (X.eq_dec b a); [left|right]; auto. + rewrite H'. + apply remove_2; auto. + (* In a s' /\ ~ s [=] remove a s' *) + generalize (mem_2 H); clear H; intro H. + contradict H'. + unfold Equal in *; intros b. + split; intros. + apply remove_2; auto. + inversion_clear Hs. + contradict H1; apply In_eq with b; auto. + rewrite <- H'; rewrite InA_cons; auto. + assert (In b s') by (apply remove_3 with a; auto). + rewrite <- H', InA_cons in H1; destruct H1; auto. + elim (remove_1 Hs' (X.eq_sym H1) H0). + (* ~ In a s' *) + assert (~In a s'). + red; intro H'; rewrite (mem_1 H') in H; discriminate. + contradict H0. + unfold Equal in *. + rewrite <- H0. + rewrite InA_cons; auto. Qed. End ForNotations. @@ -758,12 +802,12 @@ End Raw. Now, in order to really provide a functor implementing [S], we need to encapsulate everything into a type of lists without redundancy. *) -Module Make (X: DecidableType) <: S with Module E := X. +Module Make (X: DecidableType) <: WS with Module E := X. Module Raw := Raw X. Module E := X. - Record slist : Set := {this :> Raw.t; unique : NoDupA E.eq this}. + Record slist := {this :> Raw.t; unique : NoDupA E.eq this}. Definition t := slist. Definition elt := E.t. @@ -791,7 +835,7 @@ Module Make (X: DecidableType) <: S with Module E := X. Definition is_empty (s : t) : bool := Raw.is_empty s. Definition elements (s : t) : list elt := Raw.elements s. Definition choose (s:t) : option elt := Raw.choose s. - Definition fold (B : Set) (f : elt -> B -> B) (s : t) : B -> B := Raw.fold (B:=B) f s. + Definition fold (B : Type) (f : elt -> B -> B) (s : t) : B -> B := Raw.fold (B:=B) f s. Definition cardinal (s : t) : nat := Raw.cardinal s. Definition filter (f : elt -> bool) (s : t) : t := Build_slist (Raw.filter_unique (unique s) f). @@ -872,7 +916,7 @@ Module Make (X: DecidableType) <: S with Module E := X. Lemma diff_3 : In x s -> ~ In x s' -> In x (diff s s'). Proof. exact (fun H => Raw.diff_3 s.(unique) s'.(unique) H). Qed. - Lemma fold_1 : forall (A : Set) (i : A) (f : elt -> A -> A), + Lemma fold_1 : forall (A : Type) (i : A) (f : elt -> A -> A), fold f s i = fold_left (fun a e => f e a) (elements s) i. Proof. exact (Raw.fold_1 s.(unique)). Qed. @@ -923,8 +967,8 @@ Module Make (X: DecidableType) <: S with Module E := X. Proof. exact (fun H => Raw.elements_1 H). Qed. Lemma elements_2 : InA E.eq x (elements s) -> In x s. Proof. exact (fun H => Raw.elements_2 H). Qed. - Lemma elements_3 : NoDupA E.eq (elements s). - Proof. exact (Raw.elements_3 s.(unique)). Qed. + Lemma elements_3w : NoDupA E.eq (elements s). + Proof. exact (Raw.elements_3w s.(unique)). Qed. Lemma choose_1 : choose s = Some x -> In x s. Proof. exact (fun H => Raw.choose_1 H). Qed. @@ -933,4 +977,22 @@ Module Make (X: DecidableType) <: S with Module E := X. End Spec. + Definition eq : t -> t -> Prop := Equal. + + Lemma eq_refl : forall s, eq s s. + Proof. firstorder. Qed. + + Lemma eq_sym : forall s s', eq s s' -> eq s' s. + Proof. firstorder. Qed. + + Lemma eq_trans : + forall s s' s'', eq s s' -> eq s' s'' -> eq s s''. + Proof. firstorder. Qed. + + Definition eq_dec : forall (s s':t), + { eq s s' }+{ ~eq s s' }. + Proof. + intros s s'; exact (Raw.eq_dec s.(unique) s'.(unique)). + Qed. + End Make. diff --git a/theories/FSets/FSetWeakProperties.v b/theories/FSets/FSetWeakProperties.v deleted file mode 100644 index a0054d36..00000000 --- a/theories/FSets/FSetWeakProperties.v +++ /dev/null @@ -1,896 +0,0 @@ -(***********************************************************************) -(* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) -(* \VV/ *************************************************************) -(* // * This file is distributed under the terms of the *) -(* * GNU Lesser General Public License Version 2.1 *) -(***********************************************************************) - -(* $Id: FSetWeakProperties.v 8853 2006-05-23 18:17:38Z herbelin $ *) - -(** * Finite sets library *) - -(** NB: this file is a clone of [FSetProperties] for weak sets - and should remain so until we find a way to share the two. *) - -(** This functor derives additional properties from [FSetWeakInterface.S]. - Contrary to the functor in [FSetWeakEqProperties] it uses - predicates over sets instead of sets operations, i.e. - [In x s] instead of [mem x s=true], - [Equal s s'] instead of [equal s s'=true], etc. *) - -Require Export FSetWeakInterface. -Require Import FSetWeakFacts. -Set Implicit Arguments. -Unset Strict Implicit. - -Hint Unfold transpose compat_op. -Hint Extern 1 (Setoid_Theory _ _) => constructor; congruence. - -Module Properties (M: S). - Import M.E. - Import M. - Import Logic. (* to unmask [eq] *) - Import Peano. (* to unmask [lt] *) - - (** Results about lists without duplicates *) - - Module FM := Facts M. - Import FM. - - Definition Add (x : elt) (s s' : t) := - forall y : elt, In y s' <-> E.eq x y \/ In y s. - - Lemma In_dec : forall x s, {In x s} + {~ In x s}. - Proof. - intros; generalize (mem_iff s x); case (mem x s); intuition. - Qed. - - Section BasicProperties. - - (** properties of [Equal] *) - - Lemma equal_refl : forall s, s[=]s. - Proof. - unfold Equal; intuition. - Qed. - - Lemma equal_sym : forall s s', s[=]s' -> s'[=]s. - Proof. - unfold Equal; intros. - rewrite H; intuition. - Qed. - - Lemma equal_trans : forall s1 s2 s3, s1[=]s2 -> s2[=]s3 -> s1[=]s3. - Proof. - unfold Equal; intros. - rewrite H; exact (H0 a). - Qed. - - Variable s s' s'' s1 s2 s3 : t. - Variable x x' : elt. - - (** properties of [Subset] *) - - Lemma subset_refl : s[<=]s. - Proof. - unfold Subset; intuition. - Qed. - - Lemma subset_antisym : s[<=]s' -> s'[<=]s -> s[=]s'. - Proof. - unfold Subset, Equal; intuition. - Qed. - - Lemma subset_trans : s1[<=]s2 -> s2[<=]s3 -> s1[<=]s3. - Proof. - unfold Subset; intuition. - Qed. - - Lemma subset_equal : s[=]s' -> s[<=]s'. - Proof. - unfold Subset, Equal; firstorder. - Qed. - - Lemma subset_empty : empty[<=]s. - Proof. - unfold Subset; intros a; set_iff; intuition. - Qed. - - Lemma subset_remove_3 : s1[<=]s2 -> remove x s1 [<=] s2. - Proof. - unfold Subset; intros H a; set_iff; intuition. - Qed. - - Lemma subset_diff : s1[<=]s3 -> diff s1 s2 [<=] s3. - Proof. - unfold Subset; intros H a; set_iff; intuition. - Qed. - - Lemma subset_add_3 : In x s2 -> s1[<=]s2 -> add x s1 [<=] s2. - Proof. - unfold Subset; intros H H0 a; set_iff; intuition. - rewrite <- H2; auto. - Qed. - - Lemma subset_add_2 : s1[<=]s2 -> s1[<=] add x s2. - Proof. - unfold Subset; intuition. - Qed. - - Lemma in_subset : In x s1 -> s1[<=]s2 -> In x s2. - Proof. - unfold Subset; intuition. - Qed. - - Lemma double_inclusion : s1[=]s2 <-> s1[<=]s2 /\ s2[<=]s1. - Proof. - unfold Subset, Equal; split; intros; intuition; generalize (H a); intuition. - Qed. - - (** properties of [empty] *) - - Lemma empty_is_empty_1 : Empty s -> s[=]empty. - Proof. - unfold Empty, Equal; intros; generalize (H a); set_iff; tauto. - Qed. - - Lemma empty_is_empty_2 : s[=]empty -> Empty s. - Proof. - unfold Empty, Equal; intros; generalize (H a); set_iff; tauto. - Qed. - - (** properties of [add] *) - - Lemma add_equal : In x s -> add x s [=] s. - Proof. - unfold Equal; intros; set_iff; intuition. - rewrite <- H1; auto. - Qed. - - Lemma add_add : add x (add x' s) [=] add x' (add x s). - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. - - (** properties of [remove] *) - - Lemma remove_equal : ~ In x s -> remove x s [=] s. - Proof. - unfold Equal; intros; set_iff; intuition. - rewrite H1 in H; auto. - Qed. - - Lemma Equal_remove : s[=]s' -> remove x s [=] remove x s'. - Proof. - intros; rewrite H; apply equal_refl. - Qed. - - (** properties of [add] and [remove] *) - - Lemma add_remove : In x s -> add x (remove x s) [=] s. - Proof. - unfold Equal; intros; set_iff; elim (eq_dec x a); intuition. - rewrite <- H1; auto. - Qed. - - Lemma remove_add : ~In x s -> remove x (add x s) [=] s. - Proof. - unfold Equal; intros; set_iff; elim (eq_dec x a); intuition. - rewrite H1 in H; auto. - Qed. - - (** properties of [singleton] *) - - Lemma singleton_equal_add : singleton x [=] add x empty. - Proof. - unfold Equal; intros; set_iff; intuition. - Qed. - - (** properties of [union] *) - - Lemma union_sym : union s s' [=] union s' s. - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. - - Lemma union_subset_equal : s[<=]s' -> union s s' [=] s'. - Proof. - unfold Subset, Equal; intros; set_iff; intuition. - Qed. - - Lemma union_equal_1 : s[=]s' -> union s s'' [=] union s' s''. - Proof. - intros; rewrite H; apply equal_refl. - Qed. - - Lemma union_equal_2 : s'[=]s'' -> union s s' [=] union s s''. - Proof. - intros; rewrite H; apply equal_refl. - Qed. - - Lemma union_assoc : union (union s s') s'' [=] union s (union s' s''). - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. - - Lemma add_union_singleton : add x s [=] union (singleton x) s. - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. - - Lemma union_add : union (add x s) s' [=] add x (union s s'). - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. - - Lemma union_subset_1 : s [<=] union s s'. - Proof. - unfold Subset; intuition. - Qed. - - Lemma union_subset_2 : s' [<=] union s s'. - Proof. - unfold Subset; intuition. - Qed. - - Lemma union_subset_3 : s[<=]s'' -> s'[<=]s'' -> union s s' [<=] s''. - Proof. - unfold Subset; intros H H0 a; set_iff; intuition. - Qed. - - Lemma union_subset_4 : s[<=]s' -> union s s'' [<=] union s' s''. - Proof. - unfold Subset; intros H a; set_iff; intuition. - Qed. - - Lemma union_subset_5 : s[<=]s' -> union s'' s [<=] union s'' s'. - Proof. - unfold Subset; intros H a; set_iff; intuition. - Qed. - - Lemma empty_union_1 : Empty s -> union s s' [=] s'. - Proof. - unfold Equal, Empty; intros; set_iff; firstorder. - Qed. - - Lemma empty_union_2 : Empty s -> union s' s [=] s'. - Proof. - unfold Equal, Empty; intros; set_iff; firstorder. - Qed. - - Lemma not_in_union : ~In x s -> ~In x s' -> ~In x (union s s'). - Proof. - intros; set_iff; intuition. - Qed. - - (** properties of [inter] *) - - Lemma inter_sym : inter s s' [=] inter s' s. - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. - - Lemma inter_subset_equal : s[<=]s' -> inter s s' [=] s. - Proof. - unfold Equal; intros; set_iff; intuition. - Qed. - - Lemma inter_equal_1 : s[=]s' -> inter s s'' [=] inter s' s''. - Proof. - intros; rewrite H; apply equal_refl. - Qed. - - Lemma inter_equal_2 : s'[=]s'' -> inter s s' [=] inter s s''. - Proof. - intros; rewrite H; apply equal_refl. - Qed. - - Lemma inter_assoc : inter (inter s s') s'' [=] inter s (inter s' s''). - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. - - Lemma union_inter_1 : inter (union s s') s'' [=] union (inter s s'') (inter s' s''). - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. - - Lemma union_inter_2 : union (inter s s') s'' [=] inter (union s s'') (union s' s''). - Proof. - unfold Equal; intros; set_iff; tauto. - Qed. - - Lemma inter_add_1 : In x s' -> inter (add x s) s' [=] add x (inter s s'). - Proof. - unfold Equal; intros; set_iff; intuition. - rewrite <- H1; auto. - Qed. - - Lemma inter_add_2 : ~ In x s' -> inter (add x s) s' [=] inter s s'. - Proof. - unfold Equal; intros; set_iff; intuition. - destruct H; rewrite H0; auto. - Qed. - - Lemma empty_inter_1 : Empty s -> Empty (inter s s'). - Proof. - unfold Empty; intros; set_iff; firstorder. - Qed. - - Lemma empty_inter_2 : Empty s' -> Empty (inter s s'). - Proof. - unfold Empty; intros; set_iff; firstorder. - Qed. - - Lemma inter_subset_1 : inter s s' [<=] s. - Proof. - unfold Subset; intro a; set_iff; tauto. - Qed. - - Lemma inter_subset_2 : inter s s' [<=] s'. - Proof. - unfold Subset; intro a; set_iff; tauto. - Qed. - - Lemma inter_subset_3 : - s''[<=]s -> s''[<=]s' -> s''[<=] inter s s'. - Proof. - unfold Subset; intros H H' a; set_iff; intuition. - Qed. - - (** properties of [diff] *) - - Lemma empty_diff_1 : Empty s -> Empty (diff s s'). - Proof. - unfold Empty, Equal; intros; set_iff; firstorder. - Qed. - - Lemma empty_diff_2 : Empty s -> diff s' s [=] s'. - Proof. - unfold Empty, Equal; intros; set_iff; firstorder. - Qed. - - Lemma diff_subset : diff s s' [<=] s. - Proof. - unfold Subset; intros a; set_iff; tauto. - Qed. - - Lemma diff_subset_equal : s[<=]s' -> diff s s' [=] empty. - Proof. - unfold Subset, Equal; intros; set_iff; intuition; absurd (In a empty); auto. - Qed. - - Lemma remove_diff_singleton : - remove x s [=] diff s (singleton x). - Proof. - unfold Equal; intros; set_iff; intuition. - Qed. - - Lemma diff_inter_empty : inter (diff s s') (inter s s') [=] empty. - Proof. - unfold Equal; intros; set_iff; intuition; absurd (In a empty); auto. - Qed. - - Lemma diff_inter_all : union (diff s s') (inter s s') [=] s. - Proof. - unfold Equal; intros; set_iff; intuition. - elim (In_dec a s'); auto. - Qed. - - (** properties of [Add] *) - - Lemma Add_add : Add x s (add x s). - Proof. - unfold Add; intros; set_iff; intuition. - Qed. - - Lemma Add_remove : In x s -> Add x (remove x s) s. - Proof. - unfold Add; intros; set_iff; intuition. - elim (eq_dec x y); auto. - rewrite <- H1; auto. - Qed. - - Lemma union_Add : Add x s s' -> Add x (union s s'') (union s' s''). - Proof. - unfold Add; intros; set_iff; rewrite H; tauto. - Qed. - - Lemma inter_Add : - In x s'' -> Add x s s' -> Add x (inter s s'') (inter s' s''). - Proof. - unfold Add; intros; set_iff; rewrite H0; intuition. - rewrite <- H2; auto. - Qed. - - Lemma union_Equal : - In x s'' -> Add x s s' -> union s s'' [=] union s' s''. - Proof. - unfold Add, Equal; intros; set_iff; rewrite H0; intuition. - rewrite <- H1; auto. - Qed. - - Lemma inter_Add_2 : - ~In x s'' -> Add x s s' -> inter s s'' [=] inter s' s''. - Proof. - unfold Add, Equal; intros; set_iff; rewrite H0; intuition. - destruct H; rewrite H1; auto. - Qed. - - End BasicProperties. - - Hint Immediate equal_sym: set. - Hint Resolve equal_refl equal_trans : set. - - Hint Immediate add_remove remove_add union_sym inter_sym: set. - Hint Resolve subset_refl subset_equal subset_antisym - subset_trans subset_empty subset_remove_3 subset_diff subset_add_3 - subset_add_2 in_subset empty_is_empty_1 empty_is_empty_2 add_equal - remove_equal singleton_equal_add union_subset_equal union_equal_1 - union_equal_2 union_assoc add_union_singleton union_add union_subset_1 - union_subset_2 union_subset_3 inter_subset_equal inter_equal_1 inter_equal_2 - inter_assoc union_inter_1 union_inter_2 inter_add_1 inter_add_2 - empty_inter_1 empty_inter_2 empty_union_1 empty_union_2 empty_diff_1 - empty_diff_2 union_Add inter_Add union_Equal inter_Add_2 not_in_union - inter_subset_1 inter_subset_2 inter_subset_3 diff_subset diff_subset_equal - remove_diff_singleton diff_inter_empty diff_inter_all Add_add Add_remove - Equal_remove add_add : set. - - (** * Alternative (weaker) specifications for [fold] *) - - Section Old_Spec_Now_Properties. - - Notation NoDup := (NoDupA E.eq). - - (** When [FSets] was first designed, the order in which Ocaml's [Set.fold] - takes the set elements was unspecified. This specification reflects this fact: - *) - - Lemma fold_0 : - forall s (A : Set) (i : A) (f : elt -> A -> A), - exists l : list elt, - NoDup l /\ - (forall x : elt, In x s <-> InA E.eq x l) /\ - fold f s i = fold_right f i l. - Proof. - intros; exists (rev (elements s)); split. - apply NoDupA_rev; auto. - exact E.eq_trans. - split; intros. - rewrite elements_iff; do 2 rewrite InA_alt. - split; destruct 1; generalize (In_rev (elements s) x0); exists x0; intuition. - rewrite fold_left_rev_right. - apply fold_1. - Qed. - - (** An alternate (and previous) specification for [fold] was based on - the recursive structure of a set. It is now lemmas [fold_1] and - [fold_2]. *) - - Lemma fold_1 : - forall s (A : Set) (eqA : A -> A -> Prop) - (st : Setoid_Theory A eqA) (i : A) (f : elt -> A -> A), - Empty s -> eqA (fold f s i) i. - Proof. - unfold Empty; intros; destruct (fold_0 s i f) as (l,(H1, (H2, H3))). - rewrite H3; clear H3. - generalize H H2; clear H H2; case l; simpl; intros. - refl_st. - elim (H e). - elim (H2 e); intuition. - Qed. - - Lemma fold_2 : - forall s s' x (A : Set) (eqA : A -> A -> Prop) - (st : Setoid_Theory A eqA) (i : A) (f : elt -> A -> A), - compat_op E.eq eqA f -> - transpose eqA f -> - ~ In x s -> Add x s s' -> eqA (fold f s' i) (f x (fold f s i)). - Proof. - intros; destruct (fold_0 s i f) as (l,(Hl, (Hl1, Hl2))); - destruct (fold_0 s' i f) as (l',(Hl', (Hl'1, Hl'2))). - rewrite Hl2; rewrite Hl'2; clear Hl2 Hl'2. - apply fold_right_add with (eqA:=E.eq)(eqB:=eqA); auto. - eauto. - exact eq_dec. - rewrite <- Hl1; auto. - intros; rewrite <- Hl1; rewrite <- Hl'1; auto. - Qed. - - (** Similar specifications for [cardinal]. *) - - Lemma cardinal_fold : forall s, cardinal s = fold (fun _ => S) s 0. - Proof. - intros; rewrite cardinal_1; rewrite M.fold_1. - symmetry; apply fold_left_length; auto. - Qed. - - Lemma cardinal_0 : - forall s, exists l : list elt, - NoDupA E.eq l /\ - (forall x : elt, In x s <-> InA E.eq x l) /\ - cardinal s = length l. - Proof. - intros; exists (elements s); intuition; apply cardinal_1. - Qed. - - Lemma cardinal_1 : forall s, Empty s -> cardinal s = 0. - Proof. - intros; rewrite cardinal_fold; apply fold_1; auto. - Qed. - - Lemma cardinal_2 : - forall s s' x, ~ In x s -> Add x s s' -> cardinal s' = S (cardinal s). - Proof. - intros; do 2 rewrite cardinal_fold. - change S with ((fun _ => S) x). - apply fold_2; auto. - Qed. - - End Old_Spec_Now_Properties. - - (** * Induction principle over sets *) - - Lemma cardinal_inv_1 : forall s, cardinal s = 0 -> Empty s. - Proof. - intros s; rewrite M.cardinal_1; intros H a; red. - rewrite elements_iff. - destruct (elements s); simpl in *; discriminate || inversion 1. - Qed. - Hint Resolve cardinal_inv_1. - - Lemma cardinal_inv_2 : - forall s n, cardinal s = S n -> { x : elt | In x s }. - Proof. - intros; rewrite M.cardinal_1 in H. - generalize (elements_2 (s:=s)). - destruct (elements s); try discriminate. - exists e; auto. - Qed. - - Lemma Equal_cardinal_aux : - forall n s s', cardinal s = n -> s[=]s' -> cardinal s = cardinal s'. - Proof. - simple induction n; intros. - rewrite H; symmetry . - apply cardinal_1. - rewrite <- H0; auto. - destruct (cardinal_inv_2 H0) as (x,H2). - revert H0. - rewrite (cardinal_2 (s:=remove x s) (s':=s) (x:=x)); auto with set. - rewrite (cardinal_2 (s:=remove x s') (s':=s') (x:=x)); auto with set. - rewrite H1 in H2; auto with set. - Qed. - - Lemma Equal_cardinal : forall s s', s[=]s' -> cardinal s = cardinal s'. - Proof. - intros; apply Equal_cardinal_aux with (cardinal s); auto. - Qed. - - Add Morphism cardinal : cardinal_m. - Proof. - exact Equal_cardinal. - Qed. - - Hint Resolve Add_add Add_remove Equal_remove cardinal_inv_1 Equal_cardinal. - - Lemma cardinal_induction : - forall P : t -> Type, - (forall s, Empty s -> P s) -> - (forall s s', P s -> forall x, ~In x s -> Add x s s' -> P s') -> - forall n s, cardinal s = n -> P s. - Proof. - simple induction n; intros; auto. - destruct (cardinal_inv_2 H) as (x,H0). - apply X0 with (remove x s) x; auto. - apply X1; auto. - rewrite (cardinal_2 (x:=x)(s:=remove x s)(s':=s)) in H; auto. - Qed. - - Lemma set_induction : - forall P : t -> Type, - (forall s : t, Empty s -> P s) -> - (forall s s' : t, P s -> forall x : elt, ~In x s -> Add x s s' -> P s') -> - forall s : t, P s. - Proof. - intros; apply cardinal_induction with (cardinal s); auto. - Qed. - - (** Other properties of [fold]. *) - - Section Fold. - Variables (A:Set)(eqA:A->A->Prop)(st:Setoid_Theory _ eqA). - Variables (f:elt->A->A)(Comp:compat_op E.eq eqA f)(Ass:transpose eqA f). - - Section Fold_1. - Variable i i':A. - - Lemma fold_empty : eqA (fold f empty i) i. - Proof. - apply fold_1; auto. - Qed. - - Lemma fold_equal : - forall s s', s[=]s' -> eqA (fold f s i) (fold f s' i). - Proof. - intros s; pattern s; apply set_induction; clear s; intros. - trans_st i. - apply fold_1; auto. - sym_st; apply fold_1; auto. - rewrite <- H0; auto. - trans_st (f x (fold f s i)). - apply fold_2 with (eqA := eqA); auto. - sym_st; apply fold_2 with (eqA := eqA); auto. - unfold Add in *; intros. - rewrite <- H2; auto. - Qed. - - Lemma fold_add : forall s x, ~In x s -> - eqA (fold f (add x s) i) (f x (fold f s i)). - Proof. - intros; apply fold_2 with (eqA := eqA); auto. - Qed. - - Lemma add_fold : forall s x, In x s -> - eqA (fold f (add x s) i) (fold f s i). - Proof. - intros; apply fold_equal; auto with set. - Qed. - - Lemma remove_fold_1: forall s x, In x s -> - eqA (f x (fold f (remove x s) i)) (fold f s i). - Proof. - intros. - sym_st. - apply fold_2 with (eqA:=eqA); auto. - Qed. - - Lemma remove_fold_2: forall s x, ~In x s -> - eqA (fold f (remove x s) i) (fold f s i). - Proof. - intros. - apply fold_equal; auto with set. - Qed. - - Lemma fold_commutes : forall s x, - eqA (fold f s (f x i)) (f x (fold f s i)). - Proof. - intros; pattern s; apply set_induction; clear s; intros. - trans_st (f x i). - apply fold_1; auto. - sym_st. - apply Comp; auto. - apply fold_1; auto. - trans_st (f x0 (fold f s (f x i))). - apply fold_2 with (eqA:=eqA); auto. - trans_st (f x0 (f x (fold f s i))). - trans_st (f x (f x0 (fold f s i))). - apply Comp; auto. - sym_st. - apply fold_2 with (eqA:=eqA); auto. - Qed. - - Lemma fold_init : forall s, eqA i i' -> - eqA (fold f s i) (fold f s i'). - Proof. - intros; pattern s; apply set_induction; clear s; intros. - trans_st i. - apply fold_1; auto. - trans_st i'. - sym_st; apply fold_1; auto. - trans_st (f x (fold f s i)). - apply fold_2 with (eqA:=eqA); auto. - trans_st (f x (fold f s i')). - sym_st; apply fold_2 with (eqA:=eqA); auto. - Qed. - - End Fold_1. - Section Fold_2. - Variable i:A. - - Lemma fold_union_inter : forall s s', - eqA (fold f (union s s') (fold f (inter s s') i)) - (fold f s (fold f s' i)). - Proof. - intros; pattern s; apply set_induction; clear s; intros. - trans_st (fold f s' (fold f (inter s s') i)). - apply fold_equal; auto with set. - trans_st (fold f s' i). - apply fold_init; auto. - apply fold_1; auto with set. - sym_st; apply fold_1; auto. - rename s'0 into s''. - destruct (In_dec x s'). - (* In x s' *) - trans_st (fold f (union s'' s') (f x (fold f (inter s s') i))); auto with set. - apply fold_init; auto. - apply fold_2 with (eqA:=eqA); auto with set. - rewrite inter_iff; intuition. - trans_st (f x (fold f s (fold f s' i))). - trans_st (fold f (union s s') (f x (fold f (inter s s') i))). - apply fold_equal; auto. - apply equal_sym; apply union_Equal with x; auto with set. - trans_st (f x (fold f (union s s') (fold f (inter s s') i))). - apply fold_commutes; auto. - sym_st; apply fold_2 with (eqA:=eqA); auto. - (* ~(In x s') *) - trans_st (f x (fold f (union s s') (fold f (inter s'' s') i))). - apply fold_2 with (eqA:=eqA); auto with set. - trans_st (f x (fold f (union s s') (fold f (inter s s') i))). - apply Comp;auto. - apply fold_init;auto. - apply fold_equal;auto. - apply equal_sym; apply inter_Add_2 with x; auto with set. - trans_st (f x (fold f s (fold f s' i))). - sym_st; apply fold_2 with (eqA:=eqA); auto. - Qed. - - End Fold_2. - Section Fold_3. - Variable i:A. - - Lemma fold_diff_inter : forall s s', - eqA (fold f (diff s s') (fold f (inter s s') i)) (fold f s i). - Proof. - intros. - trans_st (fold f (union (diff s s') (inter s s')) - (fold f (inter (diff s s') (inter s s')) i)). - sym_st; apply fold_union_inter; auto. - trans_st (fold f s (fold f (inter (diff s s') (inter s s')) i)). - apply fold_equal; auto with set. - apply fold_init; auto. - apply fold_1; auto with set. - Qed. - - Lemma fold_union: forall s s', (forall x, ~In x s\/~In x s') -> - eqA (fold f (union s s') i) (fold f s (fold f s' i)). - Proof. - intros. - trans_st (fold f (union s s') (fold f (inter s s') i)). - apply fold_init; auto. - sym_st; apply fold_1; auto with set. - unfold Empty; intro a; generalize (H a); set_iff; tauto. - apply fold_union_inter; auto. - Qed. - - End Fold_3. - End Fold. - - Lemma fold_plus : - forall s p, fold (fun _ => S) s p = fold (fun _ => S) s 0 + p. - Proof. - assert (st := gen_st nat). - assert (fe : compat_op E.eq (@eq _) (fun _ => S)) by (unfold compat_op; auto). - assert (fp : transpose (@eq _) (fun _:elt => S)) by (unfold transpose; auto). - intros s p; pattern s; apply set_induction; clear s; intros. - rewrite (fold_1 st p (fun _ => S) H). - rewrite (fold_1 st 0 (fun _ => S) H); trivial. - assert (forall p s', Add x s s' -> fold (fun _ => S) s' p = S (fold (fun _ => S) s p)). - change S with ((fun _ => S) x). - intros; apply fold_2; auto. - rewrite H2; auto. - rewrite (H2 0); auto. - rewrite H. - simpl; auto. - Qed. - - (** properties of [cardinal] *) - - Lemma empty_cardinal : cardinal empty = 0. - Proof. - rewrite cardinal_fold; apply fold_1; auto. - Qed. - - Hint Immediate empty_cardinal cardinal_1 : set. - - Lemma singleton_cardinal : forall x, cardinal (singleton x) = 1. - Proof. - intros. - rewrite (singleton_equal_add x). - replace 0 with (cardinal empty); auto with set. - apply cardinal_2 with x; auto with set. - Qed. - - Hint Resolve singleton_cardinal: set. - - Lemma diff_inter_cardinal : - forall s s', cardinal (diff s s') + cardinal (inter s s') = cardinal s . - Proof. - intros; do 3 rewrite cardinal_fold. - rewrite <- fold_plus. - apply fold_diff_inter with (eqA:=@eq nat); auto. - Qed. - - Lemma union_cardinal: - forall s s', (forall x, ~In x s\/~In x s') -> - cardinal (union s s')=cardinal s+cardinal s'. - Proof. - intros; do 3 rewrite cardinal_fold. - rewrite <- fold_plus. - apply fold_union; auto. - Qed. - - Lemma subset_cardinal : - forall s s', s[<=]s' -> cardinal s <= cardinal s' . - Proof. - intros. - rewrite <- (diff_inter_cardinal s' s). - rewrite (inter_sym s' s). - rewrite (inter_subset_equal H); auto with arith. - Qed. - - Lemma subset_cardinal_lt : - forall s s' x, s[<=]s' -> In x s' -> ~In x s -> cardinal s < cardinal s'. - Proof. - intros. - rewrite <- (diff_inter_cardinal s' s). - rewrite (inter_sym s' s). - rewrite (inter_subset_equal H). - generalize (@cardinal_inv_1 (diff s' s)). - destruct (cardinal (diff s' s)). - intro H2; destruct (H2 (refl_equal _) x). - set_iff; auto. - intros _. - change (0 + cardinal s < S n + cardinal s). - apply Plus.plus_lt_le_compat; auto with arith. - Qed. - - Theorem union_inter_cardinal : - forall s s', cardinal (union s s') + cardinal (inter s s') = cardinal s + cardinal s' . - Proof. - intros. - do 4 rewrite cardinal_fold. - do 2 rewrite <- fold_plus. - apply fold_union_inter with (eqA:=@eq nat); auto. - Qed. - - Lemma union_cardinal_inter : - forall s s', cardinal (union s s') = cardinal s + cardinal s' - cardinal (inter s s'). - Proof. - intros. - rewrite <- union_inter_cardinal. - rewrite Plus.plus_comm. - auto with arith. - Qed. - - Lemma union_cardinal_le : - forall s s', cardinal (union s s') <= cardinal s + cardinal s'. - Proof. - intros; generalize (union_inter_cardinal s s'). - intros; rewrite <- H; auto with arith. - Qed. - - Lemma add_cardinal_1 : - forall s x, In x s -> cardinal (add x s) = cardinal s. - Proof. - auto with set. - Qed. - - Lemma add_cardinal_2 : - forall s x, ~In x s -> cardinal (add x s) = S (cardinal s). - Proof. - intros. - do 2 rewrite cardinal_fold. - change S with ((fun _ => S) x); - apply fold_add with (eqA:=@eq nat); auto. - Qed. - - Lemma remove_cardinal_1 : - forall s x, In x s -> S (cardinal (remove x s)) = cardinal s. - Proof. - intros. - do 2 rewrite cardinal_fold. - change S with ((fun _ =>S) x). - apply remove_fold_1 with (eqA:=@eq nat); auto. - Qed. - - Lemma remove_cardinal_2 : - forall s x, ~In x s -> cardinal (remove x s) = cardinal s. - Proof. - auto with set. - Qed. - - Hint Resolve subset_cardinal union_cardinal add_cardinal_1 add_cardinal_2. - -End Properties. diff --git a/theories/FSets/FSets.v b/theories/FSets/FSets.v index b0402db6..a73c1da7 100644 --- a/theories/FSets/FSets.v +++ b/theories/FSets/FSets.v @@ -6,13 +6,19 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: FSets.v 8897 2006-06-05 21:04:10Z letouzey $ *) +(* $Id: FSets.v 10699 2008-03-19 20:56:43Z letouzey $ *) Require Export OrderedType. Require Export OrderedTypeEx. Require Export OrderedTypeAlt. +Require Export DecidableType. +Require Export DecidableTypeEx. Require Export FSetInterface. Require Export FSetBridge. +Require Export FSetFacts. +Require Export FSetDecide. Require Export FSetProperties. Require Export FSetEqProperties. +Require Export FSetWeakList. Require Export FSetList. +Require Export FSetAVL.
\ No newline at end of file diff --git a/theories/FSets/OrderedType.v b/theories/FSets/OrderedType.v index f966cd4d..c56a24cf 100644 --- a/theories/FSets/OrderedType.v +++ b/theories/FSets/OrderedType.v @@ -6,32 +6,25 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: OrderedType.v 8834 2006-05-20 00:41:35Z letouzey $ *) +(* $Id: OrderedType.v 10616 2008-03-04 17:33:35Z letouzey $ *) Require Export SetoidList. Set Implicit Arguments. Unset Strict Implicit. -(* TODO concernant la tactique order: - * propagate_lt n'est sans doute pas complet - * un propagate_le - * exploiter les hypotheses negatives restant a la fin - * faire que ca marche meme quand une hypothese depend d'un eq ou lt. -*) - (** * Ordered types *) -Inductive Compare (X : Set) (lt eq : X -> X -> Prop) (x y : X) : Set := +Inductive Compare (X : Type) (lt eq : X -> X -> Prop) (x y : X) : Type := | LT : lt x y -> Compare lt eq x y | EQ : eq x y -> Compare lt eq x y | GT : lt y x -> Compare lt eq x y. Module Type OrderedType. - Parameter t : Set. + Parameter Inline t : Type. - Parameter eq : t -> t -> Prop. - Parameter lt : t -> t -> Prop. + Parameter Inline eq : t -> t -> Prop. + Parameter Inline lt : t -> t -> Prop. Axiom eq_refl : forall x : t, eq x x. Axiom eq_sym : forall x y : t, eq x y -> eq y x. @@ -122,6 +115,13 @@ Module OrderedTypeFacts (O: OrderedType). intuition. Qed. +(* TODO concernant la tactique order: + * propagate_lt n'est sans doute pas complet + * un propagate_le + * exploiter les hypotheses negatives restant a la fin + * faire que ca marche meme quand une hypothese depend d'un eq ou lt. +*) + Ltac abstraction := match goal with (* First, some obvious simplifications *) | H : False |- _ => elim H @@ -137,9 +137,9 @@ Ltac abstraction := match goal with | H1: ~lt ?x ?y, H2: ~eq ?y ?x |- _ => generalize (le_neq H1 (neq_sym H2)); clear H1 H2; intro; abstraction (* Then, we generalize all interesting facts *) - | H : lt ?x ?y |- _ => revert H; abstraction - | H : ~lt ?x ?y |- _ => revert H; abstraction | H : ~eq ?x ?y |- _ => revert H; abstraction + | H : ~lt ?x ?y |- _ => revert H; abstraction + | H : lt ?x ?y |- _ => revert H; abstraction | H : eq ?x ?y |- _ => revert H; abstraction | _ => idtac end. @@ -192,7 +192,7 @@ Ltac do_lt x y LT := match goal with | |- lt ?z x -> _ => let H := fresh "H" in (intro H; generalize (lt_trans H LT); intro); do_lt x y LT | |- lt _ _ -> _ => intro; do_lt x y LT - (* Ge *) + (* GE *) | |- ~lt y x -> _ => intros _; do_lt x y LT | |- ~lt x ?z -> _ => let H := fresh "H" in (intro H; generalize (le_lt_trans H LT); intro); do_lt x y LT @@ -296,12 +296,12 @@ Ltac false_order := elimtype False; order. Lemma eq_dec : forall x y : t, {eq x y} + {~ eq x y}. Proof. intros; elim (compare x y); [ right | left | right ]; auto. - Qed. + Defined. Lemma lt_dec : forall x y : t, {lt x y} + {~ lt x y}. Proof. intros; elim (compare x y); [ left | right | right ]; auto. - Qed. + Defined. Definition eqb x y : bool := if eq_dec x y then true else false. @@ -361,7 +361,7 @@ Module KeyOrderedType(O:OrderedType). Import MO. Section Elt. - Variable elt : Set. + Variable elt : Type. Notation key:=t. Definition eqk (p p':key*elt) := eq (fst p) (fst p'). diff --git a/theories/FSets/OrderedTypeAlt.v b/theories/FSets/OrderedTypeAlt.v index 9bcfbfc7..516df0f0 100644 --- a/theories/FSets/OrderedTypeAlt.v +++ b/theories/FSets/OrderedTypeAlt.v @@ -11,19 +11,19 @@ * Institution: LRI, CNRS UMR 8623 - Université Paris Sud * 91405 Orsay, France *) -(* $Id: OrderedTypeAlt.v 8773 2006-04-29 14:31:32Z letouzey $ *) +(* $Id: OrderedTypeAlt.v 10739 2008-04-01 14:45:20Z herbelin $ *) Require Import OrderedType. (** * An alternative (but equivalent) presentation for an Ordered Type inferface. *) -(** NB: [comparison], defined in [theories/Init/datatypes.v] is [Eq|Lt|Gt] -whereas [compare], defined in [theories/FSets/OrderedType.v] is [EQ _ | LT _ | GT _ ] +(** NB: [comparison], defined in [Datatypes.v] is [Eq|Lt|Gt] +whereas [compare], defined in [OrderedType.v] is [EQ _ | LT _ | GT _ ] *) Module Type OrderedTypeAlt. - Parameter t : Set. + Parameter t : Type. Parameter compare : t -> t -> comparison. @@ -103,24 +103,16 @@ Module OrderedType_to_Alt (O:OrderedType) <: OrderedTypeAlt. Lemma compare_sym : forall x y, (y?=x) = CompOpp (x?=y). Proof. - intros x y. - unfold compare. - destruct (O.compare y x); elim_comp; simpl; auto. + intros x y; unfold compare. + destruct O.compare; elim_comp; simpl; auto. Qed. Lemma compare_trans : forall c x y z, (x?=y) = c -> (y?=z) = c -> (x?=z) = c. Proof. intros c x y z. - destruct c; unfold compare. - destruct (O.compare x y); intros; try discriminate. - destruct (O.compare y z); intros; try discriminate. - elim_comp; auto. - destruct (O.compare x y); intros; try discriminate. - destruct (O.compare y z); intros; try discriminate. - elim_comp; auto. - destruct (O.compare x y); intros; try discriminate. - destruct (O.compare y z); intros; try discriminate. + destruct c; unfold compare; + do 2 (destruct O.compare; intros; try discriminate); elim_comp; auto. Qed. diff --git a/theories/FSets/OrderedTypeEx.v b/theories/FSets/OrderedTypeEx.v index 28a5705d..03171396 100644 --- a/theories/FSets/OrderedTypeEx.v +++ b/theories/FSets/OrderedTypeEx.v @@ -11,7 +11,7 @@ * Institution: LRI, CNRS UMR 8623 - Université Paris Sud * 91405 Orsay, France *) -(* $Id: OrderedTypeEx.v 9940 2007-07-05 12:32:47Z letouzey $ *) +(* $Id: OrderedTypeEx.v 10739 2008-04-01 14:45:20Z herbelin $ *) Require Import OrderedType. Require Import ZArith. @@ -25,9 +25,9 @@ Require Import Compare_dec. the equality is the usual one of Coq. *) Module Type UsualOrderedType. - Parameter t : Set. + Parameter Inline t : Type. Definition eq := @eq t. - Parameter lt : t -> t -> Prop. + Parameter Inline lt : t -> t -> Prop. Definition eq_refl := @refl_equal t. Definition eq_sym := @sym_eq t. Definition eq_trans := @trans_eq t. @@ -154,16 +154,16 @@ Module N_as_OT <: UsualOrderedType. Definition eq_sym := @sym_eq t. Definition eq_trans := @trans_eq t. - Definition lt p q:= Nle q p = false. + Definition lt p q:= Nleb q p = false. - Definition lt_trans := Nlt_trans. + Definition lt_trans := Nltb_trans. Lemma lt_not_eq : forall x y : t, lt x y -> ~ eq x y. Proof. intros; intro. rewrite H0 in H. unfold lt in H. - rewrite Nle_refl in H; discriminate. + rewrite Nleb_refl in H; discriminate. Qed. Definition compare : forall x y : t, Compare lt eq x y. @@ -172,16 +172,15 @@ Module N_as_OT <: UsualOrderedType. case_eq ((x ?= y)%N); intros. apply EQ; apply Ncompare_Eq_eq; auto. apply LT; unfold lt; auto. - generalize (Nle_Ncompare y x). - destruct (Nle y x); auto. - rewrite <- Ncompare_antisym. + generalize (Nleb_Nle y x). + unfold Nle; rewrite <- Ncompare_antisym. destruct (x ?= y)%N; simpl; try discriminate. - intros (H0,_); elim H0; auto. + clear H; intros H. + destruct (Nleb y x); intuition. apply GT; unfold lt. - generalize (Nle_Ncompare x y). - destruct (Nle x y); auto. - destruct (x ?= y)%N; simpl; try discriminate. - intros (H0,_); elim H0; auto. + generalize (Nleb_Nle x y). + unfold Nle; destruct (x ?= y)%N; simpl; try discriminate. + destruct (Nleb x y); intuition. Defined. End N_as_OT. diff --git a/theories/Init/Datatypes.v b/theories/Init/Datatypes.v index 56dc7e95..e5e6fd23 100644 --- a/theories/Init/Datatypes.v +++ b/theories/Init/Datatypes.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Datatypes.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Datatypes.v 11073 2008-06-08 20:24:51Z herbelin $ i*) Set Implicit Arguments. @@ -26,6 +26,52 @@ Inductive bool : Set := Add Printing If bool. +Delimit Scope bool_scope with bool. + +Bind Scope bool_scope with bool. + +(** Basic boolean operators *) + +Definition andb (b1 b2:bool) : bool := if b1 then b2 else false. + +Definition orb (b1 b2:bool) : bool := if b1 then true else b2. + +Definition implb (b1 b2:bool) : bool := if b1 then b2 else true. + +Definition xorb (b1 b2:bool) : bool := + match b1, b2 with + | true, true => false + | true, false => true + | false, true => true + | false, false => false + end. + +Definition negb (b:bool) := if b then false else true. + +Infix "||" := orb : bool_scope. +Infix "&&" := andb : bool_scope. + +(*******************************) +(** * Properties of [andb] *) +(*******************************) + +Lemma andb_prop : forall a b:bool, andb a b = true -> a = true /\ b = true. +Proof. + destruct a; destruct b; intros; split; try (reflexivity || discriminate). +Qed. +Hint Resolve andb_prop: bool v62. + +Lemma andb_true_intro : + forall b1 b2:bool, b1 = true /\ b2 = true -> andb b1 b2 = true. +Proof. + destruct b1; destruct b2; simpl in |- *; tauto || auto with bool. +Qed. +Hint Resolve andb_true_intro: bool v62. + +(** Interpretation of booleans as propositions *) + +Inductive eq_true : bool -> Prop := is_eq_true : eq_true true. + (** [nat] is the datatype of natural numbers built from [O] and successor [S]; note that the constructor name is the letter O. Numbers in [nat] can be denoted using a decimal notation; @@ -70,7 +116,7 @@ Definition option_map (A B:Type) (f:A->B) o := end. (** [sum A B], written [A + B], is the disjoint sum of [A] and [B] *) -(* Syntax defined in Specif.v *) + Inductive sum (A B:Type) : Type := | inl : A -> sum A B | inr : B -> sum A B. @@ -82,6 +128,7 @@ Notation "x + y" := (sum x y) : type_scope. Inductive prod (A B:Type) : Type := pair : A -> B -> prod A B. + Add Printing Let prod. Notation "x * y" := (prod x y) : type_scope. @@ -135,6 +182,13 @@ Definition CompOpp (r:comparison) := | Gt => Lt end. +(** Identity *) + +Definition ID := forall A:Type, A -> A. +Definition id : ID := fun A x => x. + +(* begin hide *) + (* Compatibility *) Notation prodT := prod (only parsing). @@ -146,3 +200,5 @@ Notation fstT := fst (only parsing). Notation sndT := snd (only parsing). Notation prodT_uncurry := prod_uncurry (only parsing). Notation prodT_curry := prod_curry (only parsing). + +(* end hide *) diff --git a/theories/Init/Logic.v b/theories/Init/Logic.v index 8b487432..6a636ccc 100644 --- a/theories/Init/Logic.v +++ b/theories/Init/Logic.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Logic.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Logic.v 10304 2007-11-08 17:06:32Z emakarov $ i*) Set Implicit Arguments. @@ -16,10 +16,10 @@ Require Import Notations. (** [True] is the always true proposition *) Inductive True : Prop := - I : True. + I : True. (** [False] is the always false proposition *) -Inductive False : Prop :=. +Inductive False : Prop :=. (** [not A], written [~A], is the negation of [A] *) Definition not (A:Prop) := A -> False. @@ -30,14 +30,14 @@ Hint Unfold not: core. (** [and A B], written [A /\ B], is the conjunction of [A] and [B] - [conj p q] is a proof of [A /\ B] as soon as + [conj p q] is a proof of [A /\ B] as soon as [p] is a proof of [A] and [q] a proof of [B] [proj1] and [proj2] are first and second projections of a conjunction *) Inductive and (A B:Prop) : Prop := - conj : A -> B -> A /\ B - + conj : A -> B -> A /\ B + where "A /\ B" := (and A B) : type_scope. Section Conjunction. @@ -60,7 +60,7 @@ End Conjunction. Inductive or (A B:Prop) : Prop := | or_introl : A -> A \/ B - | or_intror : B -> A \/ B + | or_intror : B -> A \/ B where "A \/ B" := (or A B) : type_scope. @@ -89,6 +89,67 @@ Theorem iff_sym : forall A B:Prop, (A <-> B) -> (B <-> A). End Equivalence. +Hint Unfold iff: extcore. + +(** Some equivalences *) + +Theorem neg_false : forall A : Prop, ~ A <-> (A <-> False). +Proof. +intro A; unfold not; split. +intro H; split; [exact H | intro H1; elim H1]. +intros [H _]; exact H. +Qed. + +Theorem and_cancel_l : forall A B C : Prop, + (B -> A) -> (C -> A) -> ((A /\ B <-> A /\ C) <-> (B <-> C)). +Proof. +intros; tauto. +Qed. + +Theorem and_cancel_r : forall A B C : Prop, + (B -> A) -> (C -> A) -> ((B /\ A <-> C /\ A) <-> (B <-> C)). +Proof. +intros; tauto. +Qed. + +Theorem or_cancel_l : forall A B C : Prop, + (B -> ~ A) -> (C -> ~ A) -> ((A \/ B <-> A \/ C) <-> (B <-> C)). +Proof. +intros; tauto. +Qed. + +Theorem or_cancel_r : forall A B C : Prop, + (B -> ~ A) -> (C -> ~ A) -> ((B \/ A <-> C \/ A) <-> (B <-> C)). +Proof. +intros; tauto. +Qed. + +(** Backward direction of the equivalences above does not need assumptions *) + +Theorem and_iff_compat_l : forall A B C : Prop, + (B <-> C) -> (A /\ B <-> A /\ C). +Proof. +intros; tauto. +Qed. + +Theorem and_iff_compat_r : forall A B C : Prop, + (B <-> C) -> (B /\ A <-> C /\ A). +Proof. +intros; tauto. +Qed. + +Theorem or_iff_compat_l : forall A B C : Prop, + (B <-> C) -> (A \/ B <-> A \/ C). +Proof. +intros; tauto. +Qed. + +Theorem or_iff_compat_r : forall A B C : Prop, + (B <-> C) -> (B \/ A <-> C \/ A). +Proof. +intros; tauto. +Qed. + (** [(IF_then_else P Q R)], written [IF P then Q else R] denotes either [P] and [Q], or [~P] and [Q] *) @@ -103,7 +164,7 @@ Notation "'IF' c1 'then' c2 'else' c3" := (IF_then_else c1 c2 c3) expresses the existence of an [x] of some type [A] in [Set] which satisfies the predicate [P]. This is existential quantification. - [ex2 P Q], or simply [exists2 x, P x & Q x], or also + [ex2 P Q], or simply [exists2 x, P x & Q x], or also [exists2 x:A, P x & Q x], expresses the existence of an [x] of type [A] which satisfies both predicates [P] and [Q]. @@ -123,14 +184,14 @@ Inductive ex (A:Type) (P:A -> Prop) : Prop := Inductive ex2 (A:Type) (P Q:A -> Prop) : Prop := ex_intro2 : forall x:A, P x -> Q x -> ex2 (A:=A) P Q. -Definition all (A:Type) (P:A -> Prop) := forall x:A, P x. +Definition all (A:Type) (P:A -> Prop) := forall x:A, P x. (* Rule order is important to give printing priority to fully typed exists *) Notation "'exists' x , p" := (ex (fun x => p)) (at level 200, x ident, right associativity) : type_scope. Notation "'exists' x : t , p" := (ex (fun x:t => p)) - (at level 200, x ident, right associativity, + (at level 200, x ident, right associativity, format "'[' 'exists' '/ ' x : t , '/ ' p ']'") : type_scope. @@ -165,14 +226,14 @@ End universal_quantification. (** [eq x y], or simply [x=y] expresses the equality of [x] and [y]. Both [x] and [y] must belong to the same type [A]. The definition is inductive and states the reflexivity of the equality. - The others properties (symmetry, transitivity, replacement of + The others properties (symmetry, transitivity, replacement of equals by equals) are proved below. The type of [x] and [y] can be made explicit using the notation [x = y :> A]. This is Leibniz equality as it expresses that [x] and [y] are equal iff every property on [A] which is true of [x] is also true of [y] *) Inductive eq (A:Type) (x:A) : A -> Prop := - refl_equal : x = x :>A + refl_equal : x = x :>A where "x = y :> A" := (@eq A x y) : type_scope. @@ -222,7 +283,7 @@ Section Logic_lemmas. Proof. red in |- *; intros h1 h2; apply h1; destruct h2; trivial. Qed. - + Definition sym_equal := sym_eq. Definition sym_not_equal := sym_not_eq. Definition trans_equal := trans_eq. @@ -233,12 +294,12 @@ Section Logic_lemmas. forall (A:Type) (x:A) (P:A -> Prop), P x -> forall y:A, y = x -> P y. intros A x P H y H0; elim sym_eq with (1 := H0); assumption. Defined. - + Definition eq_rec_r : forall (A:Type) (x:A) (P:A -> Set), P x -> forall y:A, y = x -> P y. intros A x P H y H0; elim sym_eq with (1 := H0); assumption. Defined. - + Definition eq_rect_r : forall (A:Type) (x:A) (P:A -> Type), P x -> forall y:A, y = x -> P y. intros A x P H y H0; elim sym_eq with (1 := H0); assumption. @@ -246,14 +307,14 @@ Section Logic_lemmas. End Logic_lemmas. Theorem f_equal2 : - forall (A1 A2 B:Type) (f:A1 -> A2 -> B) (x1 y1:A1) + forall (A1 A2 B:Type) (f:A1 -> A2 -> B) (x1 y1:A1) (x2 y2:A2), x1 = y1 -> x2 = y2 -> f x1 x2 = f y1 y2. Proof. destruct 1; destruct 1; reflexivity. Qed. Theorem f_equal3 : - forall (A1 A2 A3 B:Type) (f:A1 -> A2 -> A3 -> B) (x1 y1:A1) + forall (A1 A2 A3 B:Type) (f:A1 -> A2 -> A3 -> B) (x1 y1:A1) (x2 y2:A2) (x3 y3:A3), x1 = y1 -> x2 = y2 -> x3 = y3 -> f x1 x2 x3 = f y1 y2 y3. Proof. @@ -261,7 +322,7 @@ Proof. Qed. Theorem f_equal4 : - forall (A1 A2 A3 A4 B:Type) (f:A1 -> A2 -> A3 -> A4 -> B) + forall (A1 A2 A3 A4 B:Type) (f:A1 -> A2 -> A3 -> A4 -> B) (x1 y1:A1) (x2 y2:A2) (x3 y3:A3) (x4 y4:A4), x1 = y1 -> x2 = y2 -> x3 = y3 -> x4 = y4 -> f x1 x2 x3 x4 = f y1 y2 y3 y4. Proof. @@ -295,7 +356,7 @@ Definition uniqueness (A:Type) (P:A->Prop) := forall x y, P x -> P y -> x = y. Notation "'exists' ! x , P" := (ex (unique (fun x => P))) (at level 200, x ident, right associativity, format "'[' 'exists' ! '/ ' x , '/ ' P ']'") : type_scope. -Notation "'exists' ! x : A , P" := +Notation "'exists' ! x : A , P" := (ex (unique (fun x:A => P))) (at level 200, x ident, right associativity, format "'[' 'exists' ! '/ ' x : A , '/ ' P ']'") : type_scope. @@ -305,15 +366,47 @@ Lemma unique_existence : forall (A:Type) (P:A->Prop), Proof. intros A P; split. intros ((x,Hx),Huni); exists x; red; auto. - intros (x,(Hx,Huni)); split. + intros (x,(Hx,Huni)); split. exists x; assumption. intros x' x'' Hx' Hx''; transitivity x. symmetry; auto. auto. Qed. -(** Being inhabited *) +(** * Being inhabited *) + +(** The predicate [inhabited] can be used in different contexts. If [A] is + thought as a type, [inhabited A] states that [A] is inhabited. If [A] is + thought as a computationally relevant proposition, then + [inhabited A] weakens [A] so as to hide its computational meaning. + The so-weakened proof remains computationally relevant but only in + a propositional context. +*) Inductive inhabited (A:Type) : Prop := inhabits : A -> inhabited A. Hint Resolve inhabits: core. + +Lemma exists_inhabited : forall (A:Type) (P:A->Prop), + (exists x, P x) -> inhabited A. +Proof. + destruct 1; auto. +Qed. + +(** Declaration of stepl and stepr for eq and iff *) + +Lemma eq_stepl : forall (A : Type) (x y z : A), x = y -> x = z -> z = y. +Proof. +intros A x y z H1 H2. rewrite <- H2; exact H1. +Qed. + +Declare Left Step eq_stepl. +Declare Right Step trans_eq. + +Lemma iff_stepl : forall A B C : Prop, (A <-> B) -> (A <-> C) -> (C <-> B). +Proof. +intros; tauto. +Qed. + +Declare Left Step iff_stepl. +Declare Right Step iff_trans. diff --git a/theories/Init/Logic_Type.v b/theories/Init/Logic_Type.v index dbe944b0..c4e5f6c7 100644 --- a/theories/Init/Logic_Type.v +++ b/theories/Init/Logic_Type.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Logic_Type.v 8866 2006-05-28 16:21:04Z herbelin $ i*) +(*i $Id: Logic_Type.v 10840 2008-04-23 21:29:34Z herbelin $ i*) (** This module defines type constructors for types in [Type] ([Datatypes.v] and [Logic.v] defined them for types in [Set]) *) @@ -32,17 +32,17 @@ Section identity_is_a_congruence. Lemma sym_id : identity x y -> identity y x. Proof. destruct 1; trivial. - Qed. + Defined. Lemma trans_id : identity x y -> identity y z -> identity x z. Proof. destruct 2; trivial. - Qed. + Defined. Lemma congr_id : identity x y -> identity (f x) (f y). Proof. destruct 1; trivial. - Qed. + Defined. Lemma sym_not_id : notT (identity x y) -> notT (identity y x). Proof. diff --git a/theories/Init/Notations.v b/theories/Init/Notations.v index 416647b4..3dc6385d 100644 --- a/theories/Init/Notations.v +++ b/theories/Init/Notations.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Notations.v 8866 2006-05-28 16:21:04Z herbelin $ i*) +(*i $Id: Notations.v 11073 2008-06-08 20:24:51Z herbelin $ i*) (** These are the notations whose level and associativity are imposed by Coq *) @@ -19,13 +19,13 @@ Reserved Notation "~ x" (at level 75, right associativity). (** Notations for equality and inequalities *) -Reserved Notation "x = y :> T" +Reserved Notation "x = y :> T" (at level 70, y at next level, no associativity). Reserved Notation "x = y" (at level 70, no associativity). Reserved Notation "x = y = z" (at level 70, no associativity, y at next level). -Reserved Notation "x <> y :> T" +Reserved Notation "x <> y :> T" (at level 70, y at next level, no associativity). Reserved Notation "x <> y" (at level 70, no associativity). @@ -49,6 +49,11 @@ Reserved Notation "- x" (at level 35, right associativity). Reserved Notation "/ x" (at level 35, right associativity). Reserved Notation "x ^ y" (at level 30, right associativity). +(** Notations for booleans *) + +Reserved Notation "x || y" (at level 50, left associativity). +Reserved Notation "x && y" (at level 40, left associativity). + (** Notations for pairs *) Reserved Notation "( x , y , .. , z )" (at level 0). diff --git a/theories/Init/Peano.v b/theories/Init/Peano.v index 3df2b566..9ef63cc8 100644 --- a/theories/Init/Peano.v +++ b/theories/Init/Peano.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Peano.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Peano.v 11115 2008-06-12 16:03:32Z werner $ i*) (** The type [nat] of Peano natural numbers (built from [O] and [S]) is defined in [Datatypes.v] *) @@ -40,7 +40,7 @@ Hint Resolve (f_equal (A:=nat)): core. (** The predecessor function *) Definition pred (n:nat) : nat := match n with - | O => 0 + | O => n | S u => u end. Hint Resolve (f_equal pred): v62. @@ -123,6 +123,11 @@ Proof. auto. Qed. +(** Standard associated names *) + +Notation plus_0_r_reverse := plus_n_O (only parsing). +Notation plus_succ_r_reverse := plus_n_Sm (only parsing). + (** Multiplication *) Fixpoint mult (n m:nat) {struct n} : nat := @@ -149,12 +154,21 @@ Proof. Qed. Hint Resolve mult_n_Sm: core v62. +(** Standard associated names *) + +Notation mult_0_r_reverse := mult_n_O (only parsing). +Notation mult_succ_r_reverse := mult_n_Sm (only parsing). + (** Truncated subtraction: [m-n] is [0] if [n>=m] *) Fixpoint minus (n m:nat) {struct n} : nat := match n, m with - | O, _ => 0 - | S k, O => S k + | O, _ => n + | S k, O => n +(*======= + + | O, _ => n + | S k, O => S k *) | S k, S l => k - l end @@ -211,5 +225,3 @@ Proof. induction n; auto. destruct m as [| n0]; auto. Qed. - -(** Notations *) diff --git a/theories/Init/Prelude.v b/theories/Init/Prelude.v index 5f6f1eab..6492c948 100644 --- a/theories/Init/Prelude.v +++ b/theories/Init/Prelude.v @@ -6,12 +6,12 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Prelude.v 8642 2006-03-17 10:09:02Z notin $ i*) +(*i $Id: Prelude.v 10064 2007-08-08 15:32:36Z msozeau $ i*) Require Export Notations. Require Export Logic. Require Export Datatypes. Require Export Specif. Require Export Peano. -Require Export Wf. -Require Export Tactics. +Require Export Coq.Init.Wf. +Require Export Coq.Init.Tactics. diff --git a/theories/Init/Specif.v b/theories/Init/Specif.v index dd2f7697..c0f5c42a 100644 --- a/theories/Init/Specif.v +++ b/theories/Init/Specif.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Specif.v 8866 2006-05-28 16:21:04Z herbelin $ i*) +(*i $Id: Specif.v 10923 2008-05-12 18:25:06Z herbelin $ i*) (** Basic specifications : sets that may contain logical information *) @@ -46,12 +46,12 @@ Arguments Scope sigT [type_scope type_scope]. Arguments Scope sigT2 [type_scope type_scope type_scope]. Notation "{ x | P }" := (sig (fun x => P)) : type_scope. -Notation "{ x | P & Q }" := (sig2 (fun x => P) (fun x => Q)) : type_scope. +Notation "{ x | P & Q }" := (sig2 (fun x => P) (fun x => Q)) : type_scope. Notation "{ x : A | P }" := (sig (fun x:A => P)) : type_scope. -Notation "{ x : A | P & Q }" := (sig2 (fun x:A => P) (fun x:A => Q)) : +Notation "{ x : A | P & Q }" := (sig2 (fun x:A => P) (fun x:A => Q)) : type_scope. -Notation "{ x : A & P }" := (sigT (fun x:A => P)) : type_scope. -Notation "{ x : A & P & Q }" := (sigT2 (fun x:A => P) (fun x:A => Q)) : +Notation "{ x : A & P }" := (sigT (fun x:A => P)) : type_scope. +Notation "{ x : A & P & Q }" := (sigT2 (fun x:A => P) (fun x:A => Q)) : type_scope. Add Printing Let sig. @@ -107,6 +107,16 @@ Section Projections. End Projections. +(** [sigT] of a predicate is equivalent to [sig] *) + +Lemma sig_of_sigT : forall (A:Type) (P:A->Prop), sigT P -> sig P. +Proof. destruct 1 as (x,H); exists x; trivial. Defined. + +Lemma sigT_of_sig : forall (A:Type) (P:A->Prop), sig P -> sigT P. +Proof. destruct 1 as (x,H); exists x; trivial. Defined. + +Coercion sigT_of_sig : sig >-> sigT. +Coercion sig_of_sigT : sigT >-> sig. (** [sumbool] is a boolean type equipped with the justification of their value *) @@ -201,6 +211,7 @@ Proof. Qed. Hint Resolve left right inleft inright: core v62. +Hint Resolve exist exist2 existT existT2: core. (* Compatibility *) diff --git a/theories/Init/Tactics.v b/theories/Init/Tactics.v index ba210dd6..afe8297e 100644 --- a/theories/Init/Tactics.v +++ b/theories/Init/Tactics.v @@ -6,59 +6,143 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Tactics.v 9268 2006-10-24 12:56:16Z herbelin $ i*) +(*i $Id: Tactics.v 11072 2008-06-08 16:13:37Z herbelin $ i*) Require Import Notations. Require Import Logic. -(** Useful tactics *) +(** * Useful tactics *) + +(** A tactic for proof by contradiction. With contradict H, + - H:~A |- B gives |- A + - H:~A |- ~B gives H: B |- A + - H: A |- B gives |- ~A + - H: A |- ~B gives H: B |- ~A + - H:False leads to a resolved subgoal. + Moreover, negations may be in unfolded forms, + and A or B may live in Type *) + +Ltac contradict H := + let save tac H := let x:=fresh in intro x; tac H; rename x into H + in + let negpos H := case H; clear H + in + let negneg H := save negpos H + in + let pospos H := + let A := type of H in (elimtype False; revert H; try fold (~A)) + in + let posneg H := save pospos H + in + let neg H := match goal with + | |- (~_) => negneg H + | |- (_->False) => negneg H + | |- _ => negpos H + end in + let pos H := match goal with + | |- (~_) => posneg H + | |- (_->False) => posneg H + | |- _ => pospos H + end in + match type of H with + | (~_) => neg H + | (_->False) => neg H + | _ => (elim H;fail) || pos H + end. -(* A shorter name for generalize + clear, can be seen as an anti-intro *) +(* Transforming a negative goal [ H:~A |- ~B ] into a positive one [ B |- A ]*) -Tactic Notation "revert" ne_hyp_list(l) := generalize l; clear l. +Ltac swap H := + idtac "swap is OBSOLETE: use contradict instead."; + intro; apply H; clear H. -(* to contradict an hypothesis without copying its type. *) +(* To contradict an hypothesis without copying its type. *) -Ltac absurd_hyp h := - let T := type of h in +Ltac absurd_hyp H := + idtac "absurd_hyp is OBSOLETE: use contradict instead."; + let T := type of H in absurd T. -(* Transforming a negative goal [ H:~A |- ~B ] into a positive one [ B |- A ]*) +(* A useful complement to contradict. Here H:A while G allows to conclude ~A *) -Ltac swap H := intro; apply H; clear H. +Ltac false_hyp H G := + let T := type of H in absurd T; [ apply G | assumption ]. (* A case with no loss of information. *) Ltac case_eq x := generalize (refl_equal x); pattern x at -1; case x. -(* A tactic for easing the use of lemmas f_equal, f_equal2, ... *) - -Ltac f_equal := - let cg := try congruence in - let r := try reflexivity in - match goal with - | |- ?f ?a = ?f' ?a' => cut (a=a'); [cg|r] - | |- ?f ?a ?b = ?f' ?a' ?b' => - cut (b=b');[cut (a=a');[cg|r]|r] - | |- ?f ?a ?b ?c = ?f' ?a' ?b' ?c'=> - cut (c=c');[cut (b=b');[cut (a=a');[cg|r]|r]|r] - | |- ?f ?a ?b ?c ?d= ?f' ?a' ?b' ?c' ?d'=> - cut (d=d');[cut (c=c');[cut (b=b');[cut (a=a');[cg|r]|r]|r]|r] - | |- ?f ?a ?b ?c ?d ?e= ?f' ?a' ?b' ?c' ?d' ?e'=> - cut (e=e');[cut (d=d');[cut (c=c');[cut (b=b');[cut (a=a');[cg|r]|r]|r]|r]|r] - | _ => idtac - end. - (* Rewriting in all hypothesis several times everywhere *) Tactic Notation "rewrite_all" constr(eq) := repeat rewrite eq in *. Tactic Notation "rewrite_all" "<-" constr(eq) := repeat rewrite <- eq in *. -(* Keeping a copy of an expression *) - -Ltac remembertac x a := - let x := fresh x in - let H := fresh "Heq" x in - (set (x:=a) in *; assert (H: x=a) by reflexivity; clearbody x). - -Tactic Notation "remember" constr(c) "as" ident(x) := remembertac x c. +(** Tactics for applying equivalences. + +The following code provides tactics "apply -> t", "apply <- t", +"apply -> t in H" and "apply <- t in H". Here t is a term whose type +consists of nested dependent and nondependent products with an +equivalence A <-> B as the conclusion. The tactics with "->" in their +names apply A -> B while those with "<-" in the name apply B -> A. *) + +(* The idea of the tactics is to first provide a term in the context +whose type is the implication (in one of the directions), and then +apply it. The first idea is to produce a statement "forall ..., A -> +B" (call this type T) and then do "assert (H : T)" for a fresh H. +Thus, T can be proved from the original equivalence and then used to +perform the application. However, currently in Ltac it is difficult +to produce such T from the original formula. + +Therefore, we first pose the original equivalence as H. If the type of +H is a dependent product, we create an existential variable and apply +H to this variable. If the type of H has the form C -> D, then we do a +cut on C. Once we eliminate all products, we split (i.e., destruct) +the conjunction into two parts and apply the relevant one. *) + +Ltac find_equiv H := +let T := type of H in +lazymatch T with +| ?A -> ?B => + let H1 := fresh in + let H2 := fresh in + cut A; + [intro H1; pose proof (H H1) as H2; clear H H1; + rename H2 into H; find_equiv H | + clear H] +| forall x : ?t, _ => + let a := fresh "a" with + H1 := fresh "H" in + evar (a : t); pose proof (H a) as H1; unfold a in H1; + clear a; clear H; rename H1 into H; find_equiv H +| ?A <-> ?B => idtac +| _ => fail "The given statement does not seem to end with an equivalence" +end. + +Ltac bapply lemma todo := +let H := fresh in + pose proof lemma as H; + find_equiv H; [todo H; clear H | .. ]. + +Tactic Notation "apply" "->" constr(lemma) := +bapply lemma ltac:(fun H => destruct H as [H _]; apply H). + +Tactic Notation "apply" "<-" constr(lemma) := +bapply lemma ltac:(fun H => destruct H as [_ H]; apply H). + +Tactic Notation "apply" "->" constr(lemma) "in" ident(J) := +bapply lemma ltac:(fun H => destruct H as [H _]; apply H in J). + +Tactic Notation "apply" "<-" constr(lemma) "in" ident(J) := +bapply lemma ltac:(fun H => destruct H as [_ H]; apply H in J). + +(** A tactic simpler than auto that is useful for ending proofs "in one step" *) +Tactic Notation "now" tactic(t) := +t; +match goal with +| H : _ |- _ => solve [inversion H] +| _ => solve [trivial | reflexivity | symmetry; trivial | discriminate | split] +| _ => fail 1 "Cannot solve this goal" +end. + +(** A tactic to document or check what is proved at some point of a script *) +Ltac now_show c := change c. diff --git a/theories/Init/Wf.v b/theories/Init/Wf.v index 4e0f3745..f46b2b11 100644 --- a/theories/Init/Wf.v +++ b/theories/Init/Wf.v @@ -6,12 +6,11 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Wf.v 8988 2006-06-25 22:15:32Z letouzey $ i*) +(*i $Id: Wf.v 10712 2008-03-23 11:38:38Z herbelin $ i*) -(** This module proves the validity of - - well-founded recursion (also called course of values) +(** * This module proves the validity of + - well-founded recursion (also known as course of values) - well-founded induction - from a well-founded ordering on a given set *) Set Implicit Arguments. @@ -40,6 +39,7 @@ Section Well_founded. [let Acc_rec F = let rec wf x = F x wf in wf] *) Section AccRecType. + Variable P : A -> Type. Variable F : forall x:A, (forall y:A, R y x -> Acc y) -> (forall y:A, R y x -> P y) -> P x. @@ -51,17 +51,6 @@ Section Well_founded. Definition Acc_rec (P:A -> Set) := Acc_rect P. - (** A simplified version of [Acc_rect] *) - - Section AccIter. - Variable P : A -> Type. - Variable F : forall x:A, (forall y:A, R y x -> P y) -> P x. - - Fixpoint Acc_iter (x:A) (a:Acc x) {struct a} : P x := - F (fun (y:A) (h:R y x) => Acc_iter (Acc_inv a h)). - - End AccIter. - (** A relation is well-founded if every element is accessible *) Definition well_founded := forall a:A, Acc a. @@ -74,7 +63,7 @@ Section Well_founded. forall P:A -> Type, (forall x:A, (forall y:A, R y x -> P y) -> P x) -> forall a:A, P a. Proof. - intros; apply (Acc_iter P); auto. + intros; apply Acc_rect; auto. Defined. Theorem well_founded_induction : @@ -91,16 +80,26 @@ Section Well_founded. exact (fun P:A -> Prop => well_founded_induction_type P). Defined. -(** Building fixpoints *) +(** Well-founded fixpoints *) Section FixPoint. Variable P : A -> Type. Variable F : forall x:A, (forall y:A, R y x -> P y) -> P x. - Notation Fix_F := (Acc_iter P F) (only parsing). (* alias *) + Fixpoint Fix_F (x:A) (a:Acc x) {struct a} : P x := + F (fun (y:A) (h:R y x) => Fix_F (Acc_inv a h)). + + Scheme Acc_inv_dep := Induction for Acc Sort Prop. + + Lemma Fix_F_eq : + forall (x:A) (r:Acc x), + F (fun (y:A) (p:R y x) => Fix_F (x:=y) (Acc_inv r p)) = Fix_F (x:=x) r. + Proof. + destruct r using Acc_inv_dep; auto. + Qed. - Definition Fix (x:A) := Acc_iter P F (Rwf x). + Definition Fix (x:A) := Fix_F (Rwf x). (** Proof that [well_founded_induction] satisfies the fixpoint equation. It requires an extra property of the functional *) @@ -110,16 +109,7 @@ Section Well_founded. forall (x:A) (f g:forall y:A, R y x -> P y), (forall (y:A) (p:R y x), f y p = g y p) -> F f = F g. - Scheme Acc_inv_dep := Induction for Acc Sort Prop. - - Lemma Fix_F_eq : - forall (x:A) (r:Acc x), - F (fun (y:A) (p:R y x) => Fix_F y (Acc_inv r p)) = Fix_F x r. - Proof. - destruct r using Acc_inv_dep; auto. - Qed. - - Lemma Fix_F_inv : forall (x:A) (r s:Acc x), Fix_F x r = Fix_F x s. + Lemma Fix_F_inv : forall (x:A) (r s:Acc x), Fix_F r = Fix_F s. Proof. intro x; induction (Rwf x); intros. rewrite <- (Fix_F_eq r); rewrite <- (Fix_F_eq s); intros. @@ -129,7 +119,7 @@ Section Well_founded. Lemma Fix_eq : forall x:A, Fix x = F (fun (y:A) (p:R y x) => Fix y). Proof. intro x; unfold Fix in |- *. - rewrite <- (Fix_F_eq (x:=x)). + rewrite <- Fix_F_eq. apply F_ext; intros. apply Fix_F_inv. Qed. @@ -138,27 +128,29 @@ Section Well_founded. End Well_founded. -(** A recursor over pairs *) +(** Well-founded fixpoints over pairs *) Section Well_founded_2. - Variables A B : Set. + Variables A B : Type. Variable R : A * B -> A * B -> Prop. Variable P : A -> B -> Type. - Section Acc_iter_2. + Section FixPoint_2. + Variable F : forall (x:A) (x':B), (forall (y:A) (y':B), R (y, y') (x, x') -> P y y') -> P x x'. - Fixpoint Acc_iter_2 (x:A) (x':B) (a:Acc R (x, x')) {struct a} : + Fixpoint Fix_F_2 (x:A) (x':B) (a:Acc R (x, x')) {struct a} : P x x' := F (fun (y:A) (y':B) (h:R (y, y') (x, x')) => - Acc_iter_2 (x:=y) (x':=y') (Acc_inv a (y, y') h)). - End Acc_iter_2. + Fix_F_2 (x:=y) (x':=y') (Acc_inv a (y,y') h)). + + End FixPoint_2. Hypothesis Rwf : well_founded R. @@ -167,9 +159,10 @@ Section Well_founded_2. (forall (y:A) (y':B), R (y, y') (x, x') -> P y y') -> P x x') -> forall (a:A) (b:B), P a b. Proof. - intros; apply Acc_iter_2; auto. + intros; apply Fix_F_2; auto. Defined. End Well_founded_2. -Notation Fix_F := Acc_iter (only parsing). (* compatibility *) +Notation Acc_iter := Fix_F (only parsing). (* compatibility *) +Notation Acc_iter_2 := Fix_F_2 (only parsing). (* compatibility *) diff --git a/theories/IntMap/.depend b/theories/IntMap/.depend deleted file mode 100644 index 8c90ac99..00000000 --- a/theories/IntMap/.depend +++ /dev/null @@ -1,48 +0,0 @@ -Mapsubset.vo: Mapsubset.v Addr.vo Adist.vo Addec.vo Map.vo Fset.vo Mapaxioms.vo Mapiter.vo -Mapsubset.vi: Mapsubset.v Addr.vo Adist.vo Addec.vo Map.vo Fset.vo Mapaxioms.vo Mapiter.vo -Maplists.vo: Maplists.v Addr.vo Addec.vo Map.vo Fset.vo Mapaxioms.vo Mapsubset.vo Mapcard.vo Mapcanon.vo Mapc.vo Mapiter.vo Mapfold.vo -Maplists.vi: Maplists.v Addr.vo Addec.vo Map.vo Fset.vo Mapaxioms.vo Mapsubset.vo Mapcard.vo Mapcanon.vo Mapc.vo Mapiter.vo Mapfold.vo -Mapiter.vo: Mapiter.v Addr.vo Adist.vo Addec.vo Map.vo Mapaxioms.vo Fset.vo -Mapiter.vi: Mapiter.v Addr.vo Adist.vo Addec.vo Map.vo Mapaxioms.vo Fset.vo -Mapfold.vo: Mapfold.v Addr.vo Adist.vo Addec.vo Map.vo Fset.vo Mapaxioms.vo Mapiter.vo Lsort.vo Mapsubset.vo -Mapfold.vi: Mapfold.v Addr.vo Adist.vo Addec.vo Map.vo Fset.vo Mapaxioms.vo Mapiter.vo Lsort.vo Mapsubset.vo -Mapcard.vo: Mapcard.v Addr.vo Adist.vo Addec.vo Map.vo Mapaxioms.vo Mapiter.vo Fset.vo Mapsubset.vo Lsort.vo -Mapcard.vi: Mapcard.v Addr.vo Adist.vo Addec.vo Map.vo Mapaxioms.vo Mapiter.vo Fset.vo Mapsubset.vo Lsort.vo -Mapcanon.vo: Mapcanon.v Addr.vo Adist.vo Addec.vo Map.vo Mapaxioms.vo Mapiter.vo Fset.vo Lsort.vo Mapsubset.vo Mapcard.vo -Mapcanon.vi: Mapcanon.v Addr.vo Adist.vo Addec.vo Map.vo Mapaxioms.vo Mapiter.vo Fset.vo Lsort.vo Mapsubset.vo Mapcard.vo -Mapc.vo: Mapc.v Addr.vo Adist.vo Addec.vo Map.vo Mapaxioms.vo Fset.vo Mapiter.vo Mapsubset.vo Lsort.vo Mapcard.vo Mapcanon.vo -Mapc.vi: Mapc.v Addr.vo Adist.vo Addec.vo Map.vo Mapaxioms.vo Fset.vo Mapiter.vo Mapsubset.vo Lsort.vo Mapcard.vo Mapcanon.vo -Mapaxioms.vo: Mapaxioms.v Addr.vo Adist.vo Addec.vo Map.vo Fset.vo -Mapaxioms.vi: Mapaxioms.v Addr.vo Adist.vo Addec.vo Map.vo Fset.vo -Map.vo: Map.v Addr.vo Adist.vo Addec.vo -Map.vi: Map.v Addr.vo Adist.vo Addec.vo -Lsort.vo: Lsort.v Addr.vo Adist.vo Addec.vo Map.vo Mapiter.vo -Lsort.vi: Lsort.v Addr.vo Adist.vo Addec.vo Map.vo Mapiter.vo -Fset.vo: Fset.v Addr.vo Adist.vo Addec.vo Map.vo -Fset.vi: Fset.v Addr.vo Adist.vo Addec.vo Map.vo -Allmaps.vo: Allmaps.v Addr.vo Adist.vo Addec.vo Map.vo Fset.vo Mapaxioms.vo Mapiter.vo Mapsubset.vo Lsort.vo Mapfold.vo Mapcard.vo Mapcanon.vo Mapc.vo Maplists.vo Adalloc.vo -Allmaps.vi: Allmaps.v Addr.vo Adist.vo Addec.vo Map.vo Fset.vo Mapaxioms.vo Mapiter.vo Mapsubset.vo Lsort.vo Mapfold.vo Mapcard.vo Mapcanon.vo Mapc.vo Maplists.vo Adalloc.vo -Adist.vo: Adist.v Addr.vo -Adist.vi: Adist.v Addr.vo -Addr.vo: Addr.v -Addr.vi: Addr.v -Addec.vo: Addec.v Addr.vo -Addec.vi: Addec.v Addr.vo -Adalloc.vo: Adalloc.v Addr.vo Adist.vo Addec.vo Map.vo Fset.vo -Adalloc.vi: Adalloc.v Addr.vo Adist.vo Addec.vo Map.vo Fset.vo -Mapsubset.html: Mapsubset.v Addr.html Adist.html Addec.html Map.html Fset.html Mapaxioms.html Mapiter.html -Maplists.html: Maplists.v Addr.html Addec.html Map.html Fset.html Mapaxioms.html Mapsubset.html Mapcard.html Mapcanon.html Mapc.html Mapiter.html Mapfold.html -Mapiter.html: Mapiter.v Addr.html Adist.html Addec.html Map.html Mapaxioms.html Fset.html -Mapfold.html: Mapfold.v Addr.html Adist.html Addec.html Map.html Fset.html Mapaxioms.html Mapiter.html Lsort.html Mapsubset.html -Mapcard.html: Mapcard.v Addr.html Adist.html Addec.html Map.html Mapaxioms.html Mapiter.html Fset.html Mapsubset.html Lsort.html -Mapcanon.html: Mapcanon.v Addr.html Adist.html Addec.html Map.html Mapaxioms.html Mapiter.html Fset.html Lsort.html Mapsubset.html Mapcard.html -Mapc.html: Mapc.v Addr.html Adist.html Addec.html Map.html Mapaxioms.html Fset.html Mapiter.html Mapsubset.html Lsort.html Mapcard.html Mapcanon.html -Mapaxioms.html: Mapaxioms.v Addr.html Adist.html Addec.html Map.html Fset.html -Map.html: Map.v Addr.html Adist.html Addec.html -Lsort.html: Lsort.v Addr.html Adist.html Addec.html Map.html Mapiter.html -Fset.html: Fset.v Addr.html Adist.html Addec.html Map.html -Allmaps.html: Allmaps.v Addr.html Adist.html Addec.html Map.html Fset.html Mapaxioms.html Mapiter.html Mapsubset.html Lsort.html Mapfold.html Mapcard.html Mapcanon.html Mapc.html Maplists.html Adalloc.html -Adist.html: Adist.v Addr.html -Addr.html: Addr.v -Addec.html: Addec.v Addr.html -Adalloc.html: Adalloc.v Addr.html Adist.html Addec.html Map.html Fset.html diff --git a/theories/IntMap/Adalloc.v b/theories/IntMap/Adalloc.v deleted file mode 100644 index ca8e7eeb..00000000 --- a/theories/IntMap/Adalloc.v +++ /dev/null @@ -1,94 +0,0 @@ -(************************************************************************) -(* 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: Adalloc.v 8733 2006-04-25 22:52:18Z letouzey $ i*) - -Require Import Bool. -Require Import Sumbool. -Require Import Arith. -Require Import NArith. -Require Import Ndigits. -Require Import Ndec. -Require Import Nnat. -Require Import Map. -Require Import Fset. - -Section AdAlloc. - - Variable A : Set. - - (** Allocator: returns an address not in the domain of [m]. - This allocator is optimal in that it returns the lowest possible address, - in the usual ordering on integers. It is not the most efficient, however. *) - Fixpoint ad_alloc_opt (m:Map A) : ad := - match m with - | M0 => N0 - | M1 a _ => if Neqb a N0 then Npos 1 else N0 - | M2 m1 m2 => - Nmin (Ndouble (ad_alloc_opt m1)) - (Ndouble_plus_one (ad_alloc_opt m2)) - end. - - Lemma ad_alloc_opt_allocates_1 : - forall m:Map A, MapGet A m (ad_alloc_opt m) = None. - Proof. - induction m as [| a| m0 H m1 H0]. reflexivity. - simpl in |- *. elim (sumbool_of_bool (Neqb a N0)). intro H. rewrite H. - rewrite (Neqb_complete _ _ H). reflexivity. - intro H. rewrite H. rewrite H. reflexivity. - intros. change - (ad_alloc_opt (M2 A m0 m1)) with (Nmin (Ndouble (ad_alloc_opt m0)) - (Ndouble_plus_one (ad_alloc_opt m1))) - in |- *. - elim - (Nmin_choice (Ndouble (ad_alloc_opt m0)) - (Ndouble_plus_one (ad_alloc_opt m1))). - intro H1. rewrite H1. rewrite MapGet_M2_bit_0_0. rewrite Ndouble_div2. assumption. - apply Ndouble_bit0. - intro H1. rewrite H1. rewrite MapGet_M2_bit_0_1. rewrite Ndouble_plus_one_div2. assumption. - apply Ndouble_plus_one_bit0. - Qed. - - Lemma ad_alloc_opt_allocates : - forall m:Map A, in_dom A (ad_alloc_opt m) m = false. - Proof. - unfold in_dom in |- *. intro. rewrite (ad_alloc_opt_allocates_1 m). reflexivity. - Qed. - - (** Moreover, this is optimal: all addresses below [(ad_alloc_opt m)] - are in [dom m]: *) - - Lemma ad_alloc_opt_optimal_1 : - forall (m:Map A) (a:ad), - Nle (ad_alloc_opt m) a = false -> {y : A | MapGet A m a = Some y}. - Proof. - induction m as [| a y| m0 H m1 H0]. simpl in |- *. unfold Nle in |- *. simpl in |- *. intros. discriminate H. - simpl in |- *. intros b H. elim (sumbool_of_bool (Neqb a N0)). intro H0. rewrite H0 in H. - unfold Nle in H. cut (N0 = b). intro. split with y. rewrite <- H1. rewrite H0. reflexivity. - rewrite <- (N_of_nat_of_N b). - rewrite <- (le_n_O_eq _ (le_S_n _ _ (leb_complete_conv _ _ H))). reflexivity. - intro H0. rewrite H0 in H. discriminate H. - intros. simpl in H1. elim (Ndouble_or_double_plus_un a). intro H2. elim H2. intros a0 H3. - rewrite H3 in H1. elim (H _ (Nlt_double_mono_conv _ _ (Nmin_lt_3 _ _ _ H1))). intros y H4. - split with y. rewrite H3. rewrite MapGet_M2_bit_0_0. rewrite Ndouble_div2. assumption. - apply Ndouble_bit0. - intro H2. elim H2. intros a0 H3. rewrite H3 in H1. - elim (H0 _ (Nlt_double_plus_one_mono_conv _ _ (Nmin_lt_4 _ _ _ H1))). intros y H4. - split with y. rewrite H3. rewrite MapGet_M2_bit_0_1. rewrite Ndouble_plus_one_div2. - assumption. - apply Ndouble_plus_one_bit0. - Qed. - - Lemma ad_alloc_opt_optimal : - forall (m:Map A) (a:ad), - Nle (ad_alloc_opt m) a = false -> in_dom A a m = true. - Proof. - intros. unfold in_dom in |- *. elim (ad_alloc_opt_optimal_1 m a H). intros y H0. rewrite H0. - reflexivity. - Qed. - -End AdAlloc. diff --git a/theories/IntMap/Fset.v b/theories/IntMap/Fset.v deleted file mode 100644 index 5b46c969..00000000 --- a/theories/IntMap/Fset.v +++ /dev/null @@ -1,371 +0,0 @@ -(************************************************************************) -(* 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: Fset.v 8733 2006-04-25 22:52:18Z letouzey $ i*) - -(*s Sets operations on maps *) - -Require Import Bool. -Require Import Sumbool. -Require Import NArith. -Require Import Ndigits. -Require Import Ndec. -Require Import Map. - -Section Dom. - - Variables A B : Set. - - Fixpoint MapDomRestrTo (m:Map A) : Map B -> Map A := - match m with - | M0 => fun _:Map B => M0 A - | M1 a y => - fun m':Map B => match MapGet B m' a with - | None => M0 A - | _ => m - end - | M2 m1 m2 => - fun m':Map B => - match m' with - | M0 => M0 A - | M1 a' y' => - match MapGet A m a' with - | None => M0 A - | Some y => M1 A a' y - end - | M2 m'1 m'2 => - makeM2 A (MapDomRestrTo m1 m'1) (MapDomRestrTo m2 m'2) - end - end. - - Lemma MapDomRestrTo_semantics : - forall (m:Map A) (m':Map B), - eqm A (MapGet A (MapDomRestrTo m m')) - (fun a0:ad => - match MapGet B m' a0 with - | None => None - | _ => MapGet A m a0 - end). - Proof. - unfold eqm in |- *. simple induction m. simpl in |- *. intros. case (MapGet B m' a); trivial. - intros. simpl in |- *. elim (sumbool_of_bool (Neqb a a1)). intro H. rewrite H. - rewrite <- (Neqb_complete _ _ H). case (MapGet B m' a); try reflexivity. - intro. apply M1_semantics_1. - intro H. rewrite H. case (MapGet B m' a). - case (MapGet B m' a1); intros; exact (M1_semantics_2 A a a1 a0 H). - case (MapGet B m' a1); reflexivity. - simple induction m'. trivial. - unfold MapDomRestrTo in |- *. intros. elim (sumbool_of_bool (Neqb a a1)). - intro H1. - rewrite (Neqb_complete _ _ H1). rewrite (M1_semantics_1 B a1 a0). - case (MapGet A (M2 A m0 m1) a1); try reflexivity. - intro. apply M1_semantics_1. - intro H1. rewrite (M1_semantics_2 B a a1 a0 H1). case (MapGet A (M2 A m0 m1) a); try reflexivity. - intro. exact (M1_semantics_2 A a a1 a2 H1). - intros. change - (MapGet A (makeM2 A (MapDomRestrTo m0 m2) (MapDomRestrTo m1 m3)) a = - match MapGet B (M2 B m2 m3) a with - | None => None - | Some _ => MapGet A (M2 A m0 m1) a - end) in |- *. - rewrite (makeM2_M2 A (MapDomRestrTo m0 m2) (MapDomRestrTo m1 m3) a). - rewrite MapGet_M2_bit_0_if. rewrite (H0 m3 (Ndiv2 a)). rewrite (H m2 (Ndiv2 a)). - rewrite (MapGet_M2_bit_0_if B m2 m3 a). rewrite (MapGet_M2_bit_0_if A m0 m1 a). - case (Nbit0 a); reflexivity. - Qed. - - Fixpoint MapDomRestrBy (m:Map A) : Map B -> Map A := - match m with - | M0 => fun _:Map B => M0 A - | M1 a y => - fun m':Map B => match MapGet B m' a with - | None => m - | _ => M0 A - end - | M2 m1 m2 => - fun m':Map B => - match m' with - | M0 => m - | M1 a' y' => MapRemove A m a' - | M2 m'1 m'2 => - makeM2 A (MapDomRestrBy m1 m'1) (MapDomRestrBy m2 m'2) - end - end. - - Lemma MapDomRestrBy_semantics : - forall (m:Map A) (m':Map B), - eqm A (MapGet A (MapDomRestrBy m m')) - (fun a0:ad => - match MapGet B m' a0 with - | None => MapGet A m a0 - | _ => None - end). - Proof. - unfold eqm in |- *. simple induction m. simpl in |- *. intros. case (MapGet B m' a); trivial. - intros. simpl in |- *. elim (sumbool_of_bool (Neqb a a1)). intro H. rewrite H. - rewrite (Neqb_complete _ _ H). case (MapGet B m' a1). trivial. - apply M1_semantics_1. - intro H. rewrite H. case (MapGet B m' a). - case (MapGet B m' a1); trivial. - rewrite (M1_semantics_2 A a a1 a0 H). - case (MapGet B m' a1); trivial. - simple induction m'. trivial. - unfold MapDomRestrBy in |- *. intros. rewrite (MapRemove_semantics A (M2 A m0 m1) a a1). - elim (sumbool_of_bool (Neqb a a1)). intro H1. rewrite H1. rewrite (Neqb_complete _ _ H1). - rewrite (M1_semantics_1 B a1 a0). reflexivity. - intro H1. rewrite H1. rewrite (M1_semantics_2 B a a1 a0 H1). reflexivity. - intros. change - (MapGet A (makeM2 A (MapDomRestrBy m0 m2) (MapDomRestrBy m1 m3)) a = - match MapGet B (M2 B m2 m3) a with - | None => MapGet A (M2 A m0 m1) a - | Some _ => None - end) in |- *. - rewrite (makeM2_M2 A (MapDomRestrBy m0 m2) (MapDomRestrBy m1 m3) a). - rewrite MapGet_M2_bit_0_if. rewrite (H0 m3 (Ndiv2 a)). rewrite (H m2 (Ndiv2 a)). - rewrite (MapGet_M2_bit_0_if B m2 m3 a). rewrite (MapGet_M2_bit_0_if A m0 m1 a). - case (Nbit0 a); reflexivity. - Qed. - - Definition in_dom (a:ad) (m:Map A) := - match MapGet A m a with - | None => false - | _ => true - end. - - Lemma in_dom_M0 : forall a:ad, in_dom a (M0 A) = false. - Proof. - trivial. - Qed. - - Lemma in_dom_M1 : forall (a a0:ad) (y:A), in_dom a0 (M1 A a y) = Neqb a a0. - Proof. - unfold in_dom in |- *. intros. simpl in |- *. case (Neqb a a0); reflexivity. - Qed. - - Lemma in_dom_M1_1 : forall (a:ad) (y:A), in_dom a (M1 A a y) = true. - Proof. - intros. rewrite in_dom_M1. apply Neqb_correct. - Qed. - - Lemma in_dom_M1_2 : - forall (a a0:ad) (y:A), in_dom a0 (M1 A a y) = true -> a = a0. - Proof. - intros. apply (Neqb_complete a a0). rewrite (in_dom_M1 a a0 y) in H. assumption. - Qed. - - Lemma in_dom_some : - forall (m:Map A) (a:ad), - in_dom a m = true -> {y : A | MapGet A m a = Some y}. - Proof. - unfold in_dom in |- *. intros. elim (option_sum _ (MapGet A m a)). trivial. - intro H0. rewrite H0 in H. discriminate H. - Qed. - - Lemma in_dom_none : - forall (m:Map A) (a:ad), in_dom a m = false -> MapGet A m a = None. - Proof. - unfold in_dom in |- *. intros. elim (option_sum _ (MapGet A m a)). intro H0. elim H0. - intros y H1. rewrite H1 in H. discriminate H. - trivial. - Qed. - - Lemma in_dom_put : - forall (m:Map A) (a0:ad) (y0:A) (a:ad), - in_dom a (MapPut A m a0 y0) = orb (Neqb a a0) (in_dom a m). - Proof. - unfold in_dom in |- *. intros. rewrite (MapPut_semantics A m a0 y0 a). - elim (sumbool_of_bool (Neqb a a0)). intro H. rewrite H. rewrite (Neqb_comm a a0) in H. - rewrite H. rewrite orb_true_b. reflexivity. - intro H. rewrite H. rewrite (Neqb_comm a a0) in H. rewrite H. rewrite orb_false_b. - reflexivity. - Qed. - - Lemma in_dom_put_behind : - forall (m:Map A) (a0:ad) (y0:A) (a:ad), - in_dom a (MapPut_behind A m a0 y0) = orb (Neqb a a0) (in_dom a m). - Proof. - unfold in_dom in |- *. intros. rewrite (MapPut_behind_semantics A m a0 y0 a). - elim (sumbool_of_bool (Neqb a a0)). intro H. rewrite H. rewrite (Neqb_comm a a0) in H. - rewrite H. case (MapGet A m a); reflexivity. - intro H. rewrite H. rewrite (Neqb_comm a a0) in H. rewrite H. case (MapGet A m a); trivial. - Qed. - - Lemma in_dom_remove : - forall (m:Map A) (a0 a:ad), - in_dom a (MapRemove A m a0) = andb (negb (Neqb a a0)) (in_dom a m). - Proof. - unfold in_dom in |- *. intros. rewrite (MapRemove_semantics A m a0 a). - elim (sumbool_of_bool (Neqb a a0)). intro H. rewrite H. rewrite (Neqb_comm a a0) in H. - rewrite H. reflexivity. - intro H. rewrite H. rewrite (Neqb_comm a a0) in H. rewrite H. - case (MapGet A m a); reflexivity. - Qed. - - Lemma in_dom_merge : - forall (m m':Map A) (a:ad), - in_dom a (MapMerge A m m') = orb (in_dom a m) (in_dom a m'). - Proof. - unfold in_dom in |- *. intros. rewrite (MapMerge_semantics A m m' a). - elim (option_sum A (MapGet A m' a)). intro H. elim H. intros y H0. rewrite H0. - case (MapGet A m a); reflexivity. - intro H. rewrite H. rewrite orb_b_false. reflexivity. - Qed. - - Lemma in_dom_delta : - forall (m m':Map A) (a:ad), - in_dom a (MapDelta A m m') = xorb (in_dom a m) (in_dom a m'). - Proof. - unfold in_dom in |- *. intros. rewrite (MapDelta_semantics A m m' a). - elim (option_sum A (MapGet A m' a)). intro H. elim H. intros y H0. rewrite H0. - case (MapGet A m a); reflexivity. - intro H. rewrite H. case (MapGet A m a); reflexivity. - Qed. - -End Dom. - -Section InDom. - - Variables A B : Set. - - Lemma in_dom_restrto : - forall (m:Map A) (m':Map B) (a:ad), - in_dom A a (MapDomRestrTo A B m m') = - andb (in_dom A a m) (in_dom B a m'). - Proof. - unfold in_dom in |- *. intros. rewrite (MapDomRestrTo_semantics A B m m' a). - elim (option_sum B (MapGet B m' a)). intro H. elim H. intros y H0. rewrite H0. - rewrite andb_b_true. reflexivity. - intro H. rewrite H. rewrite andb_b_false. reflexivity. - Qed. - - Lemma in_dom_restrby : - forall (m:Map A) (m':Map B) (a:ad), - in_dom A a (MapDomRestrBy A B m m') = - andb (in_dom A a m) (negb (in_dom B a m')). - Proof. - unfold in_dom in |- *. intros. rewrite (MapDomRestrBy_semantics A B m m' a). - elim (option_sum B (MapGet B m' a)). intro H. elim H. intros y H0. rewrite H0. - unfold negb in |- *. rewrite andb_b_false. reflexivity. - intro H. rewrite H. unfold negb in |- *. rewrite andb_b_true. reflexivity. - Qed. - -End InDom. - -Definition FSet := Map unit. - -Section FSetDefs. - - Variable A : Set. - - Definition in_FSet : ad -> FSet -> bool := in_dom unit. - - Fixpoint MapDom (m:Map A) : FSet := - match m with - | M0 => M0 unit - | M1 a _ => M1 unit a tt - | M2 m m' => M2 unit (MapDom m) (MapDom m') - end. - - Lemma MapDom_semantics_1 : - forall (m:Map A) (a:ad) (y:A), - MapGet A m a = Some y -> in_FSet a (MapDom m) = true. - Proof. - simple induction m. intros. discriminate H. - unfold MapDom in |- *. unfold in_FSet in |- *. unfold in_dom in |- *. unfold MapGet in |- *. intros a y a0 y0. - case (Neqb a a0). trivial. - intro. discriminate H. - intros m0 H m1 H0 a y. rewrite (MapGet_M2_bit_0_if A m0 m1 a). simpl in |- *. unfold in_FSet in |- *. - unfold in_dom in |- *. rewrite (MapGet_M2_bit_0_if unit (MapDom m0) (MapDom m1) a). - case (Nbit0 a). unfold in_FSet, in_dom in H0. intro. apply H0 with (y := y). assumption. - unfold in_FSet, in_dom in H. intro. apply H with (y := y). assumption. - Qed. - - Lemma MapDom_semantics_2 : - forall (m:Map A) (a:ad), - in_FSet a (MapDom m) = true -> {y : A | MapGet A m a = Some y}. - Proof. - simple induction m. intros. discriminate H. - unfold MapDom in |- *. unfold in_FSet in |- *. unfold in_dom in |- *. unfold MapGet in |- *. intros a y a0. case (Neqb a a0). - intro. split with y. reflexivity. - intro. discriminate H. - intros m0 H m1 H0 a. rewrite (MapGet_M2_bit_0_if A m0 m1 a). simpl in |- *. unfold in_FSet in |- *. - unfold in_dom in |- *. rewrite (MapGet_M2_bit_0_if unit (MapDom m0) (MapDom m1) a). - case (Nbit0 a). unfold in_FSet, in_dom in H0. intro. apply H0. assumption. - unfold in_FSet, in_dom in H. intro. apply H. assumption. - Qed. - - Lemma MapDom_semantics_3 : - forall (m:Map A) (a:ad), - MapGet A m a = None -> in_FSet a (MapDom m) = false. - Proof. - intros. elim (sumbool_of_bool (in_FSet a (MapDom m))). intro H0. - elim (MapDom_semantics_2 m a H0). intros y H1. rewrite H in H1. discriminate H1. - trivial. - Qed. - - Lemma MapDom_semantics_4 : - forall (m:Map A) (a:ad), - in_FSet a (MapDom m) = false -> MapGet A m a = None. - Proof. - intros. elim (option_sum A (MapGet A m a)). intro H0. elim H0. intros y H1. - rewrite (MapDom_semantics_1 m a y H1) in H. discriminate H. - trivial. - Qed. - - Lemma MapDom_Dom : - forall (m:Map A) (a:ad), in_dom A a m = in_FSet a (MapDom m). - Proof. - intros. elim (sumbool_of_bool (in_FSet a (MapDom m))). intro H. - elim (MapDom_semantics_2 m a H). intros y H0. rewrite H. unfold in_dom in |- *. rewrite H0. - reflexivity. - intro H. rewrite H. unfold in_dom in |- *. rewrite (MapDom_semantics_4 m a H). reflexivity. - Qed. - - Definition FSetUnion (s s':FSet) : FSet := MapMerge unit s s'. - - Lemma in_FSet_union : - forall (s s':FSet) (a:ad), - in_FSet a (FSetUnion s s') = orb (in_FSet a s) (in_FSet a s'). - Proof. - exact (in_dom_merge unit). - Qed. - - Definition FSetInter (s s':FSet) : FSet := MapDomRestrTo unit unit s s'. - - Lemma in_FSet_inter : - forall (s s':FSet) (a:ad), - in_FSet a (FSetInter s s') = andb (in_FSet a s) (in_FSet a s'). - Proof. - exact (in_dom_restrto unit unit). - Qed. - - Definition FSetDiff (s s':FSet) : FSet := MapDomRestrBy unit unit s s'. - - Lemma in_FSet_diff : - forall (s s':FSet) (a:ad), - in_FSet a (FSetDiff s s') = andb (in_FSet a s) (negb (in_FSet a s')). - Proof. - exact (in_dom_restrby unit unit). - Qed. - - Definition FSetDelta (s s':FSet) : FSet := MapDelta unit s s'. - - Lemma in_FSet_delta : - forall (s s':FSet) (a:ad), - in_FSet a (FSetDelta s s') = xorb (in_FSet a s) (in_FSet a s'). - Proof. - exact (in_dom_delta unit). - Qed. - -End FSetDefs. - -Lemma FSet_Dom : forall s:FSet, MapDom unit s = s. -Proof. - simple induction s. trivial. - simpl in |- *. intros a t. elim t. reflexivity. - intros. simpl in |- *. rewrite H. rewrite H0. reflexivity. -Qed.
\ No newline at end of file diff --git a/theories/IntMap/Lsort.v b/theories/IntMap/Lsort.v deleted file mode 100644 index c8d793a1..00000000 --- a/theories/IntMap/Lsort.v +++ /dev/null @@ -1,413 +0,0 @@ -(************************************************************************) -(* 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: Lsort.v 8733 2006-04-25 22:52:18Z letouzey $ i*) - -Require Import Bool. -Require Import Sumbool. -Require Import Arith. -Require Import NArith. -Require Import Ndigits. -Require Import Ndec. -Require Import Map. -Require Import List. -Require Import Mapiter. - -Section LSort. - - Variable A : Set. - - Fixpoint alist_sorted (l:alist A) : bool := - match l with - | nil => true - | (a, _) :: l' => - match l' with - | nil => true - | (a', y') :: l'' => andb (Nless a a') (alist_sorted l') - end - end. - - Fixpoint alist_nth_ad (n:nat) (l:alist A) {struct l} : ad := - match l with - | nil => N0 (* dummy *) - | (a, y) :: l' => match n with - | O => a - | S n' => alist_nth_ad n' l' - end - end. - - Definition alist_sorted_1 (l:alist A) := - forall n:nat, - S (S n) <= length l -> - Nless (alist_nth_ad n l) (alist_nth_ad (S n) l) = true. - - Lemma alist_sorted_imp_1 : - forall l:alist A, alist_sorted l = true -> alist_sorted_1 l. - Proof. - unfold alist_sorted_1 in |- *. simple induction l. intros. elim (le_Sn_O (S n) H0). - intro r. elim r. intros a y. simple induction l0. intros. simpl in H1. - elim (le_Sn_O n (le_S_n (S n) 0 H1)). - intro r0. elim r0. intros a0 y0. simple induction n. intros. simpl in |- *. simpl in H1. - exact (proj1 (andb_prop _ _ H1)). - intros. change - (Nless (alist_nth_ad n0 ((a0, y0) :: l1)) - (alist_nth_ad (S n0) ((a0, y0) :: l1)) = true) - in |- *. - apply H0. exact (proj2 (andb_prop _ _ H1)). - apply le_S_n. exact H3. - Qed. - - Definition alist_sorted_2 (l:alist A) := - forall m n:nat, - m < n -> - S n <= length l -> Nless (alist_nth_ad m l) (alist_nth_ad n l) = true. - - Lemma alist_sorted_1_imp_2 : - forall l:alist A, alist_sorted_1 l -> alist_sorted_2 l. - Proof. - unfold alist_sorted_1, alist_sorted_2, lt in |- *. intros l H m n H0. elim H0. exact (H m). - intros. apply Nless_trans with (a' := alist_nth_ad m0 l). apply H2. apply le_Sn_le. - assumption. - apply H. assumption. - Qed. - - Lemma alist_sorted_2_imp : - forall l:alist A, alist_sorted_2 l -> alist_sorted l = true. - Proof. - unfold alist_sorted_2, lt in |- *. simple induction l. trivial. - intro r. elim r. intros a y. simple induction l0. trivial. - intro r0. elim r0. intros a0 y0. intros. - change (andb (Nless a a0) (alist_sorted ((a0, y0) :: l1)) = true) - in |- *. - apply andb_true_intro. split. apply (H1 0 1). apply le_n. - simpl in |- *. apply le_n_S. apply le_n_S. apply le_O_n. - apply H0. intros. apply (H1 (S m) (S n)). apply le_n_S. assumption. - exact (le_n_S _ _ H3). - Qed. - - Lemma app_length : - forall (C:Set) (l l':list C), length (l ++ l') = length l + length l'. - Proof. - simple induction l. trivial. - intros. simpl in |- *. rewrite (H l'). reflexivity. - Qed. - - Lemma aapp_length : - forall l l':alist A, length (aapp A l l') = length l + length l'. - Proof. - exact (app_length (ad * A)). - Qed. - - Lemma alist_nth_ad_aapp_1 : - forall (l l':alist A) (n:nat), - S n <= length l -> alist_nth_ad n (aapp A l l') = alist_nth_ad n l. - Proof. - simple induction l. intros. elim (le_Sn_O n H). - intro r. elim r. intros a y l' H l''. simple induction n. trivial. - intros. simpl in |- *. apply H. apply le_S_n. exact H1. - Qed. - - Lemma alist_nth_ad_aapp_2 : - forall (l l':alist A) (n:nat), - S n <= length l' -> - alist_nth_ad (length l + n) (aapp A l l') = alist_nth_ad n l'. - Proof. - simple induction l. trivial. - intro r. elim r. intros a y l' H l'' n H0. simpl in |- *. apply H. exact H0. - Qed. - - Lemma interval_split : - forall p q n:nat, - S n <= p + q -> {n' : nat | S n' <= q /\ n = p + n'} + {S n <= p}. - Proof. - simple induction p. simpl in |- *. intros. left. split with n. split; [ assumption | reflexivity ]. - intros p' H q. simple induction n. intros. right. apply le_n_S. apply le_O_n. - intros. elim (H _ _ (le_S_n _ _ H1)). intro H2. left. elim H2. intros n' H3. - elim H3. intros H4 H5. split with n'. split; [ assumption | rewrite H5; reflexivity ]. - intro H2. right. apply le_n_S. assumption. - Qed. - - Lemma alist_conc_sorted : - forall l l':alist A, - alist_sorted_2 l -> - alist_sorted_2 l' -> - (forall n n':nat, - S n <= length l -> - S n' <= length l' -> - Nless (alist_nth_ad n l) (alist_nth_ad n' l') = true) -> - alist_sorted_2 (aapp A l l'). - Proof. - unfold alist_sorted_2, lt in |- *. intros. rewrite (aapp_length l l') in H3. - elim - (interval_split (length l) (length l') m - (le_trans _ _ _ (le_n_S _ _ (lt_le_weak m n H2)) H3)). - intro H4. elim H4. intros m' H5. elim H5. intros. rewrite H7. - rewrite (alist_nth_ad_aapp_2 l l' m' H6). elim (interval_split (length l) (length l') n H3). - intro H8. elim H8. intros n' H9. elim H9. intros. rewrite H11. - rewrite (alist_nth_ad_aapp_2 l l' n' H10). apply H0. rewrite H7 in H2. rewrite H11 in H2. - change (S (length l) + m' <= length l + n') in H2. - rewrite (plus_Snm_nSm (length l) m') in H2. exact ((fun p n m:nat => plus_le_reg_l n m p) (length l) (S m') n' H2). - exact H10. - intro H8. rewrite H7 in H2. cut (S (length l) <= length l). intros. elim (le_Sn_n _ H9). - apply le_trans with (m := S n). apply le_n_S. apply le_trans with (m := S (length l + m')). - apply le_trans with (m := length l + m'). apply le_plus_l. - apply le_n_Sn. - exact H2. - exact H8. - intro H4. rewrite (alist_nth_ad_aapp_1 l l' m H4). - elim (interval_split (length l) (length l') n H3). intro H5. elim H5. intros n' H6. elim H6. - intros. rewrite H8. rewrite (alist_nth_ad_aapp_2 l l' n' H7). exact (H1 m n' H4 H7). - intro H5. rewrite (alist_nth_ad_aapp_1 l l' n H5). exact (H m n H2 H5). - Qed. - - Lemma alist_nth_ad_semantics : - forall (l:alist A) (n:nat), - S n <= length l -> - {y : A | alist_semantics A l (alist_nth_ad n l) = Some y}. - Proof. - simple induction l. intros. elim (le_Sn_O _ H). - intro r. elim r. intros a y l0 H. simple induction n. simpl in |- *. intro. split with y. - rewrite (Neqb_correct a). reflexivity. - intros. elim (H _ (le_S_n _ _ H1)). intros y0 H2. - elim (sumbool_of_bool (Neqb a (alist_nth_ad n0 l0))). intro H3. split with y. - rewrite (Neqb_complete _ _ H3). simpl in |- *. rewrite (Neqb_correct (alist_nth_ad n0 l0)). - reflexivity. - intro H3. split with y0. simpl in |- *. rewrite H3. assumption. - Qed. - - Lemma alist_of_Map_nth_ad : - forall (m:Map A) (pf:ad -> ad) (l:alist A), - l = - MapFold1 A (alist A) (anil A) (aapp A) - (fun (a0:ad) (y:A) => acons A (a0, y) (anil A)) pf m -> - forall n:nat, S n <= length l -> {a' : ad | alist_nth_ad n l = pf a'}. - Proof. - intros. elim (alist_nth_ad_semantics l n H0). intros y H1. - apply (alist_of_Map_semantics_1_1 A m pf (alist_nth_ad n l) y). - rewrite <- H. assumption. - Qed. - - Definition ad_monotonic (pf:ad -> ad) := - forall a a':ad, Nless a a' = true -> Nless (pf a) (pf a') = true. - - Lemma Ndouble_monotonic : ad_monotonic Ndouble. - Proof. - unfold ad_monotonic in |- *. intros. rewrite Nless_def_1. assumption. - Qed. - - Lemma Ndouble_plus_one_monotonic : ad_monotonic Ndouble_plus_one. - Proof. - unfold ad_monotonic in |- *. intros. rewrite Nless_def_2. assumption. - Qed. - - Lemma ad_comp_monotonic : - forall pf pf':ad -> ad, - ad_monotonic pf -> - ad_monotonic pf' -> ad_monotonic (fun a0:ad => pf (pf' a0)). - Proof. - unfold ad_monotonic in |- *. intros. apply H. apply H0. exact H1. - Qed. - - Lemma ad_comp_double_monotonic : - forall pf:ad -> ad, - ad_monotonic pf -> ad_monotonic (fun a0:ad => pf (Ndouble a0)). - Proof. - intros. apply ad_comp_monotonic. assumption. - exact Ndouble_monotonic. - Qed. - - Lemma ad_comp_double_plus_un_monotonic : - forall pf:ad -> ad, - ad_monotonic pf -> ad_monotonic (fun a0:ad => pf (Ndouble_plus_one a0)). - Proof. - intros. apply ad_comp_monotonic. assumption. - exact Ndouble_plus_one_monotonic. - Qed. - - Lemma alist_of_Map_sorts_1 : - forall (m:Map A) (pf:ad -> ad), - ad_monotonic pf -> - alist_sorted_2 - (MapFold1 A (alist A) (anil A) (aapp A) - (fun (a:ad) (y:A) => acons A (a, y) (anil A)) pf m). - Proof. - simple induction m. simpl in |- *. intros. apply alist_sorted_1_imp_2. apply alist_sorted_imp_1. reflexivity. - intros. simpl in |- *. apply alist_sorted_1_imp_2. apply alist_sorted_imp_1. reflexivity. - intros. simpl in |- *. apply alist_conc_sorted. - exact - (H (fun a0:ad => pf (Ndouble a0)) (ad_comp_double_monotonic pf H1)). - exact - (H0 (fun a0:ad => pf (Ndouble_plus_one a0)) - (ad_comp_double_plus_un_monotonic pf H1)). - intros. elim - (alist_of_Map_nth_ad m0 (fun a0:ad => pf (Ndouble a0)) - (MapFold1 A (alist A) (anil A) (aapp A) - (fun (a0:ad) (y:A) => acons A (a0, y) (anil A)) - (fun a0:ad => pf (Ndouble a0)) m0) (refl_equal _) n H2). - intros a H4. rewrite H4. elim - (alist_of_Map_nth_ad m1 (fun a0:ad => pf (Ndouble_plus_one a0)) - (MapFold1 A (alist A) (anil A) (aapp A) - (fun (a0:ad) (y:A) => acons A (a0, y) (anil A)) - (fun a0:ad => pf (Ndouble_plus_one a0)) m1) ( - refl_equal _) n' H3). - intros a' H5. rewrite H5. unfold ad_monotonic in H1. apply H1. apply Nless_def_3. - Qed. - - Lemma alist_of_Map_sorts : - forall m:Map A, alist_sorted (alist_of_Map A m) = true. - Proof. - intro. apply alist_sorted_2_imp. - exact - (alist_of_Map_sorts_1 m (fun a0:ad => a0) - (fun (a a':ad) (p:Nless a a' = true) => p)). - Qed. - - Lemma alist_of_Map_sorts1 : - forall m:Map A, alist_sorted_1 (alist_of_Map A m). - Proof. - intro. apply alist_sorted_imp_1. apply alist_of_Map_sorts. - Qed. - - Lemma alist_of_Map_sorts2 : - forall m:Map A, alist_sorted_2 (alist_of_Map A m). - Proof. - intro. apply alist_sorted_1_imp_2. apply alist_of_Map_sorts1. - Qed. - - Lemma alist_too_low : - forall (l:alist A) (a a':ad) (y:A), - Nless a a' = true -> - alist_sorted_2 ((a', y) :: l) -> - alist_semantics A ((a', y) :: l) a = None. - Proof. - simple induction l. intros. simpl in |- *. elim (sumbool_of_bool (Neqb a' a)). intro H1. - rewrite (Neqb_complete _ _ H1) in H. rewrite (Nless_not_refl a) in H. discriminate H. - intro H1. rewrite H1. reflexivity. - intro r. elim r. intros a y l0 H a0 a1 y0 H0 H1. - change - (match Neqb a1 a0 with - | true => Some y0 - | false => alist_semantics A ((a, y) :: l0) a0 - end = None) in |- *. - elim (sumbool_of_bool (Neqb a1 a0)). intro H2. rewrite (Neqb_complete _ _ H2) in H0. - rewrite (Nless_not_refl a0) in H0. discriminate H0. - intro H2. rewrite H2. apply H. apply Nless_trans with (a' := a1). assumption. - unfold alist_sorted_2 in H1. apply (H1 0 1). apply lt_n_Sn. - simpl in |- *. apply le_n_S. apply le_n_S. apply le_O_n. - apply alist_sorted_1_imp_2. apply alist_sorted_imp_1. - cut (alist_sorted ((a1, y0) :: (a, y) :: l0) = true). intro H3. - exact (proj2 (andb_prop _ _ H3)). - apply alist_sorted_2_imp. assumption. - Qed. - - Lemma alist_semantics_nth_ad : - forall (l:alist A) (a:ad) (y:A), - alist_semantics A l a = Some y -> - {n : nat | S n <= length l /\ alist_nth_ad n l = a}. - Proof. - simple induction l. intros. discriminate H. - intro r. elim r. intros a y l0 H a0 y0 H0. simpl in H0. elim (sumbool_of_bool (Neqb a a0)). - intro H1. rewrite H1 in H0. split with 0. split. simpl in |- *. apply le_n_S. apply le_O_n. - simpl in |- *. exact (Neqb_complete _ _ H1). - intro H1. rewrite H1 in H0. elim (H a0 y0 H0). intros n' H2. split with (S n'). split. - simpl in |- *. apply le_n_S. exact (proj1 H2). - exact (proj2 H2). - Qed. - - Lemma alist_semantics_tail : - forall (l:alist A) (a:ad) (y:A), - alist_sorted_2 ((a, y) :: l) -> - eqm A (alist_semantics A l) - (fun a0:ad => - if Neqb a a0 then None else alist_semantics A ((a, y) :: l) a0). - Proof. - unfold eqm in |- *. intros. elim (sumbool_of_bool (Neqb a a0)). intro H0. rewrite H0. - rewrite <- (Neqb_complete _ _ H0). unfold alist_sorted_2 in H. - elim (option_sum A (alist_semantics A l a)). intro H1. elim H1. intros y0 H2. - elim (alist_semantics_nth_ad l a y0 H2). intros n H3. elim H3. intros. - cut - (Nless (alist_nth_ad 0 ((a, y) :: l)) - (alist_nth_ad (S n) ((a, y) :: l)) = true). - intro. simpl in H6. rewrite H5 in H6. rewrite (Nless_not_refl a) in H6. discriminate H6. - apply H. apply lt_O_Sn. - simpl in |- *. apply le_n_S. assumption. - trivial. - intro H0. simpl in |- *. rewrite H0. reflexivity. - Qed. - - Lemma alist_semantics_same_tail : - forall (l l':alist A) (a:ad) (y:A), - alist_sorted_2 ((a, y) :: l) -> - alist_sorted_2 ((a, y) :: l') -> - eqm A (alist_semantics A ((a, y) :: l)) - (alist_semantics A ((a, y) :: l')) -> - eqm A (alist_semantics A l) (alist_semantics A l'). - Proof. - unfold eqm in |- *. intros. rewrite (alist_semantics_tail _ _ _ H a0). - rewrite (alist_semantics_tail _ _ _ H0 a0). case (Neqb a a0). reflexivity. - exact (H1 a0). - Qed. - - Lemma alist_sorted_tail : - forall (l:alist A) (a:ad) (y:A), - alist_sorted_2 ((a, y) :: l) -> alist_sorted_2 l. - Proof. - unfold alist_sorted_2 in |- *. intros. apply (H (S m) (S n)). apply lt_n_S. assumption. - simpl in |- *. apply le_n_S. assumption. - Qed. - - Lemma alist_canonical : - forall l l':alist A, - eqm A (alist_semantics A l) (alist_semantics A l') -> - alist_sorted_2 l -> alist_sorted_2 l' -> l = l'. - Proof. - unfold eqm in |- *. simple induction l. simple induction l'. trivial. - intro r. elim r. intros a y l0 H H0 H1 H2. simpl in H0. - cut - (None = - match Neqb a a with - | true => Some y - | false => alist_semantics A l0 a - end). - rewrite (Neqb_correct a). intro. discriminate H3. - exact (H0 a). - intro r. elim r. intros a y l0 H. simple induction l'. intros. simpl in H0. - cut - (match Neqb a a with - | true => Some y - | false => alist_semantics A l0 a - end = None). - rewrite (Neqb_correct a). intro. discriminate H3. - exact (H0 a). - intro r'. elim r'. intros a' y' l'0 H0 H1 H2 H3. elim (Nless_total a a'). intro H4. - elim H4. intro H5. - cut - (alist_semantics A ((a, y) :: l0) a = - alist_semantics A ((a', y') :: l'0) a). - intro. rewrite (alist_too_low l'0 a a' y' H5 H3) in H6. simpl in H6. - rewrite (Neqb_correct a) in H6. discriminate H6. - exact (H1 a). - intro H5. cut - (alist_semantics A ((a, y) :: l0) a' = - alist_semantics A ((a', y') :: l'0) a'). - intro. rewrite (alist_too_low l0 a' a y H5 H2) in H6. simpl in H6. - rewrite (Neqb_correct a') in H6. discriminate H6. - exact (H1 a'). - intro H4. rewrite H4. - cut - (alist_semantics A ((a, y) :: l0) a = - alist_semantics A ((a', y') :: l'0) a). - intro. simpl in H5. rewrite H4 in H5. rewrite (Neqb_correct a') in H5. inversion H5. - rewrite H4 in H1. rewrite H7 in H1. cut (l0 = l'0). intro. rewrite H6. reflexivity. - apply H. rewrite H4 in H2. rewrite H7 in H2. - exact (alist_semantics_same_tail l0 l'0 a' y' H2 H3 H1). - exact (alist_sorted_tail _ _ _ H2). - exact (alist_sorted_tail _ _ _ H3). - exact (H1 a). - Qed. - -End LSort.
\ No newline at end of file diff --git a/theories/IntMap/Map.v b/theories/IntMap/Map.v deleted file mode 100644 index 2be6de04..00000000 --- a/theories/IntMap/Map.v +++ /dev/null @@ -1,869 +0,0 @@ -(************************************************************************) -(* 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: Map.v 8733 2006-04-25 22:52:18Z letouzey $ i*) - -(** Definition of finite sets as trees indexed by adresses *) - -Require Import Bool. -Require Import Sumbool. -Require Import NArith. -Require Import Ndigits. -Require Import Ndec. - -(* The type [ad] of addresses is now [N] in [BinNat]. *) - -Definition ad := N. - -(* a Notation or complete replacement would be nice, - but that would changes hyps names *) - -Section MapDefs. - -(** We now define maps from ad to A. *) - Variable A : Set. - - Inductive Map : Set := - | M0 : Map - | M1 : ad -> A -> Map - | M2 : Map -> Map -> Map. - - Lemma option_sum : forall o:option A, {y : A | o = Some y} + {o = None}. - Proof. - simple induction o. - left. split with a. reflexivity. - right. reflexivity. - Qed. - - (** The semantics of maps is given by the function [MapGet]. - The semantics of a map [m] is a partial, finite function from - [ad] to [A]: *) - - Fixpoint MapGet (m:Map) : ad -> option A := - match m with - | M0 => fun a:ad => None - | M1 x y => fun a:ad => if Neqb x a then Some y else None - | M2 m1 m2 => - fun a:ad => - match a with - | N0 => MapGet m1 N0 - | Npos xH => MapGet m2 N0 - | Npos (xO p) => MapGet m1 (Npos p) - | Npos (xI p) => MapGet m2 (Npos p) - end - end. - - Definition newMap := M0. - - Definition MapSingleton := M1. - - Definition eqm (g g':ad -> option A) := forall a:ad, g a = g' a. - - Lemma newMap_semantics : eqm (MapGet newMap) (fun a:ad => None). - Proof. - simpl in |- *. unfold eqm in |- *. trivial. - Qed. - - Lemma MapSingleton_semantics : - forall (a:ad) (y:A), - eqm (MapGet (MapSingleton a y)) - (fun a':ad => if Neqb a a' then Some y else None). - Proof. - simpl in |- *. unfold eqm in |- *. trivial. - Qed. - - Lemma M1_semantics_1 : forall (a:ad) (y:A), MapGet (M1 a y) a = Some y. - Proof. - unfold MapGet in |- *. intros. rewrite (Neqb_correct a). reflexivity. - Qed. - - Lemma M1_semantics_2 : - forall (a a':ad) (y:A), Neqb a a' = false -> MapGet (M1 a y) a' = None. - Proof. - intros. simpl in |- *. rewrite H. reflexivity. - Qed. - - Lemma Map2_semantics_1 : - forall m m':Map, - eqm (MapGet m) (fun a:ad => MapGet (M2 m m') (Ndouble a)). - Proof. - unfold eqm in |- *. simple induction a; trivial. - Qed. - - Lemma Map2_semantics_1_eq : - forall (m m':Map) (f:ad -> option A), - eqm (MapGet (M2 m m')) f -> eqm (MapGet m) (fun a:ad => f (Ndouble a)). - Proof. - unfold eqm in |- *. - intros. - rewrite <- (H (Ndouble a)). - exact (Map2_semantics_1 m m' a). - Qed. - - Lemma Map2_semantics_2 : - forall m m':Map, - eqm (MapGet m') (fun a:ad => MapGet (M2 m m') (Ndouble_plus_one a)). - Proof. - unfold eqm in |- *. simple induction a; trivial. - Qed. - - Lemma Map2_semantics_2_eq : - forall (m m':Map) (f:ad -> option A), - eqm (MapGet (M2 m m')) f -> - eqm (MapGet m') (fun a:ad => f (Ndouble_plus_one a)). - Proof. - unfold eqm in |- *. - intros. - rewrite <- (H (Ndouble_plus_one a)). - exact (Map2_semantics_2 m m' a). - Qed. - - Lemma MapGet_M2_bit_0_0 : - forall a:ad, - Nbit0 a = false -> - forall m m':Map, MapGet (M2 m m') a = MapGet m (Ndiv2 a). - Proof. - simple induction a; trivial. simple induction p. intros. discriminate H0. - trivial. - intros. discriminate H. - Qed. - - Lemma MapGet_M2_bit_0_1 : - forall a:ad, - Nbit0 a = true -> - forall m m':Map, MapGet (M2 m m') a = MapGet m' (Ndiv2 a). - Proof. - simple induction a. intros. discriminate H. - simple induction p. trivial. - intros. discriminate H0. - trivial. - Qed. - - Lemma MapGet_M2_bit_0_if : - forall (m m':Map) (a:ad), - MapGet (M2 m m') a = - (if Nbit0 a then MapGet m' (Ndiv2 a) else MapGet m (Ndiv2 a)). - Proof. - intros. elim (sumbool_of_bool (Nbit0 a)). intro H. rewrite H. - apply MapGet_M2_bit_0_1; assumption. - intro H. rewrite H. apply MapGet_M2_bit_0_0; assumption. - Qed. - - Lemma MapGet_M2_bit_0 : - forall (m m' m'':Map) (a:ad), - (if Nbit0 a then MapGet (M2 m' m) a else MapGet (M2 m m'') a) = - MapGet m (Ndiv2 a). - Proof. - intros. elim (sumbool_of_bool (Nbit0 a)). intro H. rewrite H. - apply MapGet_M2_bit_0_1; assumption. - intro H. rewrite H. apply MapGet_M2_bit_0_0; assumption. - Qed. - - Lemma Map2_semantics_3 : - forall m m':Map, - eqm (MapGet (M2 m m')) - (fun a:ad => - match Nbit0 a with - | false => MapGet m (Ndiv2 a) - | true => MapGet m' (Ndiv2 a) - end). - Proof. - unfold eqm in |- *. - simple induction a; trivial. - simple induction p; trivial. - Qed. - - Lemma Map2_semantics_3_eq : - forall (m m':Map) (f f':ad -> option A), - eqm (MapGet m) f -> - eqm (MapGet m') f' -> - eqm (MapGet (M2 m m')) - (fun a:ad => - match Nbit0 a with - | false => f (Ndiv2 a) - | true => f' (Ndiv2 a) - end). - Proof. - unfold eqm in |- *. - intros. - rewrite <- (H (Ndiv2 a)). - rewrite <- (H0 (Ndiv2 a)). - exact (Map2_semantics_3 m m' a). - Qed. - - Fixpoint MapPut1 (a:ad) (y:A) (a':ad) (y':A) (p:positive) {struct p} : - Map := - match p with - | xO p' => - let m := MapPut1 (Ndiv2 a) y (Ndiv2 a') y' p' in - match Nbit0 a with - | false => M2 m M0 - | true => M2 M0 m - end - | _ => - match Nbit0 a with - | false => M2 (M1 (Ndiv2 a) y) (M1 (Ndiv2 a') y') - | true => M2 (M1 (Ndiv2 a') y') (M1 (Ndiv2 a) y) - end - end. - - Lemma MapGet_if_commute : - forall (b:bool) (m m':Map) (a:ad), - MapGet (if b then m else m') a = (if b then MapGet m a else MapGet m' a). - Proof. - intros. case b; trivial. - Qed. - - (*i - Lemma MapGet_M2_bit_0_1' : (m,m',m'',m''':Map) - (a:ad) (MapGet (if (Nbit0 a) then (M2 m m') else (M2 m'' m''')) a)= - (MapGet (if (Nbit0 a) then m' else m'') (Ndiv2 a)). - Proof. - Intros. Rewrite (MapGet_if_commute (Nbit0 a)). Rewrite (MapGet_if_commute (Nbit0 a)). - Cut (Nbit0 a)=false\/(Nbit0 a)=true. Intros. Elim H. Intros. Rewrite H0. - Apply MapGet_M2_bit_0_0. Assumption. - Intros. Rewrite H0. Apply MapGet_M2_bit_0_1. Assumption. - Case (Nbit0 a); Auto. - Qed. - i*) - - Lemma MapGet_if_same : - forall (m:Map) (b:bool) (a:ad), MapGet (if b then m else m) a = MapGet m a. - Proof. - simple induction b; trivial. - Qed. - - Lemma MapGet_M2_bit_0_2 : - forall (m m' m'':Map) (a:ad), - MapGet (if Nbit0 a then M2 m m' else M2 m' m'') a = - MapGet m' (Ndiv2 a). - Proof. - intros. rewrite MapGet_if_commute. apply MapGet_M2_bit_0. - Qed. - - Lemma MapPut1_semantics_1 : - forall (p:positive) (a a':ad) (y y':A), - Nxor a a' = Npos p -> MapGet (MapPut1 a y a' y' p) a = Some y. - Proof. - simple induction p. intros. unfold MapPut1 in |- *. rewrite MapGet_M2_bit_0_2. apply M1_semantics_1. - intros. simpl in |- *. rewrite MapGet_M2_bit_0_2. apply H. rewrite <- Nxor_div2. rewrite H0. - reflexivity. - intros. unfold MapPut1 in |- *. rewrite MapGet_M2_bit_0_2. apply M1_semantics_1. - Qed. - - Lemma MapPut1_semantics_2 : - forall (p:positive) (a a':ad) (y y':A), - Nxor a a' = Npos p -> MapGet (MapPut1 a y a' y' p) a' = Some y'. - Proof. - simple induction p. intros. unfold MapPut1 in |- *. rewrite (Nneg_bit0_2 a a' p0 H0). - rewrite if_negb. rewrite MapGet_M2_bit_0_2. apply M1_semantics_1. - intros. simpl in |- *. rewrite (Nsame_bit0 a a' p0 H0). rewrite MapGet_M2_bit_0_2. - apply H. rewrite <- Nxor_div2. rewrite H0. reflexivity. - intros. unfold MapPut1 in |- *. rewrite (Nneg_bit0_1 a a' H). rewrite if_negb. - rewrite MapGet_M2_bit_0_2. apply M1_semantics_1. - Qed. - - Lemma MapGet_M2_both_None : - forall (m m':Map) (a:ad), - MapGet m (Ndiv2 a) = None -> - MapGet m' (Ndiv2 a) = None -> MapGet (M2 m m') a = None. - Proof. - intros. rewrite (Map2_semantics_3 m m' a). - case (Nbit0 a); assumption. - Qed. - - Lemma MapPut1_semantics_3 : - forall (p:positive) (a a' a0:ad) (y y':A), - Nxor a a' = Npos p -> - Neqb a a0 = false -> - Neqb a' a0 = false -> MapGet (MapPut1 a y a' y' p) a0 = None. - Proof. - simple induction p. intros. unfold MapPut1 in |- *. elim (Nneq_elim a a0 H1). intro. rewrite H3. rewrite if_negb. - rewrite MapGet_M2_bit_0_2. apply M1_semantics_2. apply Ndiv2_bit_neq. assumption. - rewrite (Nneg_bit0_2 a a' p0 H0) in H3. rewrite (negb_intro (Nbit0 a')). - rewrite (negb_intro (Nbit0 a0)). rewrite H3. reflexivity. - intro. elim (Nneq_elim a' a0 H2). intro. rewrite (Nneg_bit0_2 a a' p0 H0). rewrite H4. - rewrite (negb_elim (Nbit0 a0)). rewrite MapGet_M2_bit_0_2. - apply M1_semantics_2; assumption. - intro; case (Nbit0 a); apply MapGet_M2_both_None; apply M1_semantics_2; - assumption. - intros. simpl in |- *. elim (Nneq_elim a a0 H1). intro. rewrite H3. rewrite if_negb. - rewrite MapGet_M2_bit_0_2. reflexivity. - intro. elim (Nneq_elim a' a0 H2). intro. rewrite (Nsame_bit0 a a' p0 H0). rewrite H4. - rewrite if_negb. rewrite MapGet_M2_bit_0_2. reflexivity. - intro. cut (Nxor (Ndiv2 a) (Ndiv2 a') = Npos p0). intro. - case (Nbit0 a); apply MapGet_M2_both_None; trivial; apply H; - assumption. - rewrite <- Nxor_div2. rewrite H0. reflexivity. - intros. simpl in |- *. elim (Nneq_elim a a0 H0). intro. rewrite H2. rewrite if_negb. - rewrite MapGet_M2_bit_0_2. apply M1_semantics_2. apply Ndiv2_bit_neq. assumption. - rewrite (Nneg_bit0_1 a a' H) in H2. rewrite (negb_intro (Nbit0 a')). - rewrite (negb_intro (Nbit0 a0)). rewrite H2. reflexivity. - intro. elim (Nneq_elim a' a0 H1). intro. rewrite (Nneg_bit0_1 a a' H). rewrite H3. - rewrite (negb_elim (Nbit0 a0)). rewrite MapGet_M2_bit_0_2. - apply M1_semantics_2; assumption. - intro. case (Nbit0 a); apply MapGet_M2_both_None; apply M1_semantics_2; - assumption. - Qed. - - Lemma MapPut1_semantics : - forall (p:positive) (a a':ad) (y y':A), - Nxor a a' = Npos p -> - eqm (MapGet (MapPut1 a y a' y' p)) - (fun a0:ad => - if Neqb a a0 - then Some y - else if Neqb a' a0 then Some y' else None). - Proof. - unfold eqm in |- *. intros. elim (sumbool_of_bool (Neqb a a0)). intro H0. rewrite H0. - rewrite <- (Neqb_complete _ _ H0). exact (MapPut1_semantics_1 p a a' y y' H). - intro H0. rewrite H0. elim (sumbool_of_bool (Neqb a' a0)). intro H1. - rewrite <- (Neqb_complete _ _ H1). rewrite (Neqb_correct a'). - exact (MapPut1_semantics_2 p a a' y y' H). - intro H1. rewrite H1. exact (MapPut1_semantics_3 p a a' a0 y y' H H0 H1). - Qed. - - Lemma MapPut1_semantics' : - forall (p:positive) (a a':ad) (y y':A), - Nxor a a' = Npos p -> - eqm (MapGet (MapPut1 a y a' y' p)) - (fun a0:ad => - if Neqb a' a0 - then Some y' - else if Neqb a a0 then Some y else None). - Proof. - unfold eqm in |- *. intros. rewrite (MapPut1_semantics p a a' y y' H a0). - elim (sumbool_of_bool (Neqb a a0)). intro H0. rewrite H0. - rewrite <- (Neqb_complete a a0 H0). rewrite (Neqb_comm a' a). - rewrite (Nxor_eq_false a a' p H). reflexivity. - intro H0. rewrite H0. reflexivity. - Qed. - - Fixpoint MapPut (m:Map) : ad -> A -> Map := - match m with - | M0 => M1 - | M1 a y => - fun (a':ad) (y':A) => - match Nxor a a' with - | N0 => M1 a' y' - | Npos p => MapPut1 a y a' y' p - end - | M2 m1 m2 => - fun (a:ad) (y:A) => - match a with - | N0 => M2 (MapPut m1 N0 y) m2 - | Npos xH => M2 m1 (MapPut m2 N0 y) - | Npos (xO p) => M2 (MapPut m1 (Npos p) y) m2 - | Npos (xI p) => M2 m1 (MapPut m2 (Npos p) y) - end - end. - - Lemma MapPut_semantics_1 : - forall (a:ad) (y:A) (a0:ad), - MapGet (MapPut M0 a y) a0 = MapGet (M1 a y) a0. - Proof. - trivial. - Qed. - - Lemma MapPut_semantics_2_1 : - forall (a:ad) (y y':A) (a0:ad), - MapGet (MapPut (M1 a y) a y') a0 = - (if Neqb a a0 then Some y' else None). - Proof. - simpl in |- *. intros. rewrite (Nxor_nilpotent a). trivial. - Qed. - - Lemma MapPut_semantics_2_2 : - forall (a a':ad) (y y':A) (a0 a'':ad), - Nxor a a' = a'' -> - MapGet (MapPut (M1 a y) a' y') a0 = - (if Neqb a' a0 then Some y' else if Neqb a a0 then Some y else None). - Proof. - simple induction a''. intro. rewrite (Nxor_eq _ _ H). rewrite MapPut_semantics_2_1. - case (Neqb a' a0); trivial. - intros. simpl in |- *. rewrite H. rewrite (MapPut1_semantics p a a' y y' H a0). - elim (sumbool_of_bool (Neqb a a0)). intro H0. rewrite H0. rewrite <- (Neqb_complete _ _ H0). - rewrite (Neqb_comm a' a). rewrite (Nxor_eq_false _ _ _ H). reflexivity. - intro H0. rewrite H0. reflexivity. - Qed. - - Lemma MapPut_semantics_2 : - forall (a a':ad) (y y':A) (a0:ad), - MapGet (MapPut (M1 a y) a' y') a0 = - (if Neqb a' a0 then Some y' else if Neqb a a0 then Some y else None). - Proof. - intros. apply MapPut_semantics_2_2 with (a'' := Nxor a a'); trivial. - Qed. - - Lemma MapPut_semantics_3_1 : - forall (m m':Map) (a:ad) (y:A), - MapPut (M2 m m') a y = - (if Nbit0 a - then M2 m (MapPut m' (Ndiv2 a) y) - else M2 (MapPut m (Ndiv2 a) y) m'). - Proof. - simple induction a. trivial. - simple induction p; trivial. - Qed. - - Lemma MapPut_semantics : - forall (m:Map) (a:ad) (y:A), - eqm (MapGet (MapPut m a y)) - (fun a':ad => if Neqb a a' then Some y else MapGet m a'). - Proof. - unfold eqm in |- *. simple induction m. exact MapPut_semantics_1. - intros. unfold MapGet at 2 in |- *. apply MapPut_semantics_2; assumption. - intros. rewrite MapPut_semantics_3_1. rewrite (MapGet_M2_bit_0_if m0 m1 a0). - elim (sumbool_of_bool (Nbit0 a)). intro H1. rewrite H1. rewrite MapGet_M2_bit_0_if. - elim (sumbool_of_bool (Nbit0 a0)). intro H2. rewrite H2. - rewrite (H0 (Ndiv2 a) y (Ndiv2 a0)). elim (sumbool_of_bool (Neqb a a0)). - intro H3. rewrite H3. rewrite (Ndiv2_eq _ _ H3). reflexivity. - intro H3. rewrite H3. rewrite <- H2 in H1. rewrite (Ndiv2_bit_neq _ _ H3 H1). reflexivity. - intro H2. rewrite H2. rewrite (Neqb_comm a a0). rewrite (Nbit0_neq a0 a H2 H1). - reflexivity. - intro H1. rewrite H1. rewrite MapGet_M2_bit_0_if. elim (sumbool_of_bool (Nbit0 a0)). - intro H2. rewrite H2. rewrite (Nbit0_neq a a0 H1 H2). reflexivity. - intro H2. rewrite H2. rewrite (H (Ndiv2 a) y (Ndiv2 a0)). - elim (sumbool_of_bool (Neqb a a0)). intro H3. rewrite H3. - rewrite (Ndiv2_eq a a0 H3). reflexivity. - intro H3. rewrite H3. rewrite <- H2 in H1. rewrite (Ndiv2_bit_neq a a0 H3 H1). reflexivity. - Qed. - - Fixpoint MapPut_behind (m:Map) : ad -> A -> Map := - match m with - | M0 => M1 - | M1 a y => - fun (a':ad) (y':A) => - match Nxor a a' with - | N0 => m - | Npos p => MapPut1 a y a' y' p - end - | M2 m1 m2 => - fun (a:ad) (y:A) => - match a with - | N0 => M2 (MapPut_behind m1 N0 y) m2 - | Npos xH => M2 m1 (MapPut_behind m2 N0 y) - | Npos (xO p) => M2 (MapPut_behind m1 (Npos p) y) m2 - | Npos (xI p) => M2 m1 (MapPut_behind m2 (Npos p) y) - end - end. - - Lemma MapPut_behind_semantics_3_1 : - forall (m m':Map) (a:ad) (y:A), - MapPut_behind (M2 m m') a y = - (if Nbit0 a - then M2 m (MapPut_behind m' (Ndiv2 a) y) - else M2 (MapPut_behind m (Ndiv2 a) y) m'). - Proof. - simple induction a. trivial. - simple induction p; trivial. - Qed. - - Lemma MapPut_behind_as_before_1 : - forall a a' a0:ad, - Neqb a' a0 = false -> - forall y y':A, - MapGet (MapPut (M1 a y) a' y') a0 = - MapGet (MapPut_behind (M1 a y) a' y') a0. - Proof. - intros a a' a0. simpl in |- *. intros H y y'. elim (Ndiscr (Nxor a a')). intro H0. elim H0. - intros p H1. rewrite H1. reflexivity. - intro H0. rewrite H0. rewrite (Nxor_eq _ _ H0). rewrite (M1_semantics_2 a' a0 y H). - exact (M1_semantics_2 a' a0 y' H). - Qed. - - Lemma MapPut_behind_as_before : - forall (m:Map) (a:ad) (y:A) (a0:ad), - Neqb a a0 = false -> - MapGet (MapPut m a y) a0 = MapGet (MapPut_behind m a y) a0. - Proof. - simple induction m. trivial. - intros a y a' y' a0 H. exact (MapPut_behind_as_before_1 a a' a0 H y y'). - intros. rewrite MapPut_semantics_3_1. rewrite MapPut_behind_semantics_3_1. - elim (sumbool_of_bool (Nbit0 a)). intro H2. rewrite H2. rewrite MapGet_M2_bit_0_if. - rewrite MapGet_M2_bit_0_if. elim (sumbool_of_bool (Nbit0 a0)). intro H3. - rewrite H3. apply H0. rewrite <- H3 in H2. exact (Ndiv2_bit_neq a a0 H1 H2). - intro H3. rewrite H3. reflexivity. - intro H2. rewrite H2. rewrite MapGet_M2_bit_0_if. rewrite MapGet_M2_bit_0_if. - elim (sumbool_of_bool (Nbit0 a0)). intro H3. rewrite H3. reflexivity. - intro H3. rewrite H3. apply H. rewrite <- H3 in H2. exact (Ndiv2_bit_neq a a0 H1 H2). - Qed. - - Lemma MapPut_behind_new : - forall (m:Map) (a:ad) (y:A), - MapGet (MapPut_behind m a y) a = - match MapGet m a with - | Some y' => Some y' - | _ => Some y - end. - Proof. - simple induction m. simpl in |- *. intros. rewrite (Neqb_correct a). reflexivity. - intros. elim (Ndiscr (Nxor a a1)). intro H. elim H. intros p H0. simpl in |- *. - rewrite H0. rewrite (Nxor_eq_false a a1 p). exact (MapPut1_semantics_2 p a a1 a0 y H0). - assumption. - intro H. simpl in |- *. rewrite H. rewrite <- (Nxor_eq _ _ H). rewrite (Neqb_correct a). - exact (M1_semantics_1 a a0). - intros. rewrite MapPut_behind_semantics_3_1. rewrite (MapGet_M2_bit_0_if m0 m1 a). - elim (sumbool_of_bool (Nbit0 a)). intro H1. rewrite H1. rewrite (MapGet_M2_bit_0_1 a H1). - exact (H0 (Ndiv2 a) y). - intro H1. rewrite H1. rewrite (MapGet_M2_bit_0_0 a H1). exact (H (Ndiv2 a) y). - Qed. - - Lemma MapPut_behind_semantics : - forall (m:Map) (a:ad) (y:A), - eqm (MapGet (MapPut_behind m a y)) - (fun a':ad => - match MapGet m a' with - | Some y' => Some y' - | _ => if Neqb a a' then Some y else None - end). - Proof. - unfold eqm in |- *. intros. elim (sumbool_of_bool (Neqb a a0)). intro H. rewrite H. - rewrite (Neqb_complete _ _ H). apply MapPut_behind_new. - intro H. rewrite H. rewrite <- (MapPut_behind_as_before m a y a0 H). - rewrite (MapPut_semantics m a y a0). rewrite H. case (MapGet m a0); trivial. - Qed. - - Definition makeM2 (m m':Map) := - match m, m' with - | M0, M0 => M0 - | M0, M1 a y => M1 (Ndouble_plus_one a) y - | M1 a y, M0 => M1 (Ndouble a) y - | _, _ => M2 m m' - end. - - Lemma makeM2_M2 : - forall m m':Map, eqm (MapGet (makeM2 m m')) (MapGet (M2 m m')). - Proof. - unfold eqm in |- *. intros. elim (sumbool_of_bool (Nbit0 a)). intro H. - rewrite (MapGet_M2_bit_0_1 a H m m'). case m'. case m. reflexivity. - intros a0 y. simpl in |- *. rewrite (Nodd_not_double a H a0). reflexivity. - intros m1 m2. unfold makeM2 in |- *. rewrite MapGet_M2_bit_0_1. reflexivity. - assumption. - case m. intros a0 y. simpl in |- *. elim (sumbool_of_bool (Neqb a0 (Ndiv2 a))). - intro H0. rewrite H0. rewrite (Neqb_complete _ _ H0). rewrite (Ndiv2_double_plus_one a H). - rewrite (Neqb_correct a). reflexivity. - intro H0. rewrite H0. rewrite (Neqb_comm a0 (Ndiv2 a)) in H0. - rewrite (Nnot_div2_not_double_plus_one a a0 H0). reflexivity. - intros a0 y0 a1 y1. unfold makeM2 in |- *. rewrite MapGet_M2_bit_0_1. reflexivity. - assumption. - intros m1 m2 a0 y. unfold makeM2 in |- *. rewrite MapGet_M2_bit_0_1. reflexivity. - assumption. - intros m1 m2. unfold makeM2 in |- *. - cut (MapGet (M2 m (M2 m1 m2)) a = MapGet (M2 m1 m2) (Ndiv2 a)). - case m; trivial. - exact (MapGet_M2_bit_0_1 a H m (M2 m1 m2)). - intro H. rewrite (MapGet_M2_bit_0_0 a H m m'). case m. case m'. reflexivity. - intros a0 y. simpl in |- *. rewrite (Neven_not_double_plus_one a H a0). reflexivity. - intros m1 m2. unfold makeM2 in |- *. rewrite MapGet_M2_bit_0_0. reflexivity. - assumption. - case m'. intros a0 y. simpl in |- *. elim (sumbool_of_bool (Neqb a0 (Ndiv2 a))). intro H0. - rewrite H0. rewrite (Neqb_complete _ _ H0). rewrite (Ndiv2_double a H). - rewrite (Neqb_correct a). reflexivity. - intro H0. rewrite H0. rewrite (Neqb_comm (Ndouble a0) a). - rewrite (Neqb_comm a0 (Ndiv2 a)) in H0. rewrite (Nnot_div2_not_double a a0 H0). - reflexivity. - intros a0 y0 a1 y1. unfold makeM2 in |- *. rewrite MapGet_M2_bit_0_0. reflexivity. - assumption. - intros m1 m2 a0 y. unfold makeM2 in |- *. rewrite MapGet_M2_bit_0_0. reflexivity. - assumption. - intros m1 m2. unfold makeM2 in |- *. exact (MapGet_M2_bit_0_0 a H (M2 m1 m2) m'). - Qed. - - Fixpoint MapRemove (m:Map) : ad -> Map := - match m with - | M0 => fun _:ad => M0 - | M1 a y => - fun a':ad => match Neqb a a' with - | true => M0 - | false => m - end - | M2 m1 m2 => - fun a:ad => - if Nbit0 a - then makeM2 m1 (MapRemove m2 (Ndiv2 a)) - else makeM2 (MapRemove m1 (Ndiv2 a)) m2 - end. - - Lemma MapRemove_semantics : - forall (m:Map) (a:ad), - eqm (MapGet (MapRemove m a)) - (fun a':ad => if Neqb a a' then None else MapGet m a'). - Proof. - unfold eqm in |- *. simple induction m. simpl in |- *. intros. case (Neqb a a0); trivial. - intros. simpl in |- *. elim (sumbool_of_bool (Neqb a1 a2)). intro H. rewrite H. - elim (sumbool_of_bool (Neqb a a1)). intro H0. rewrite H0. reflexivity. - intro H0. rewrite H0. rewrite (Neqb_complete _ _ H) in H0. exact (M1_semantics_2 a a2 a0 H0). - intro H. elim (sumbool_of_bool (Neqb a a1)). intro H0. rewrite H0. rewrite H. - rewrite <- (Neqb_complete _ _ H0) in H. rewrite H. reflexivity. - intro H0. rewrite H0. rewrite H. reflexivity. - intros. change - (MapGet - (if Nbit0 a - then makeM2 m0 (MapRemove m1 (Ndiv2 a)) - else makeM2 (MapRemove m0 (Ndiv2 a)) m1) a0 = - (if Neqb a a0 then None else MapGet (M2 m0 m1) a0)) - in |- *. - elim (sumbool_of_bool (Nbit0 a)). intro H1. rewrite H1. - rewrite (makeM2_M2 m0 (MapRemove m1 (Ndiv2 a)) a0). elim (sumbool_of_bool (Nbit0 a0)). - intro H2. rewrite MapGet_M2_bit_0_1. rewrite (H0 (Ndiv2 a) (Ndiv2 a0)). - elim (sumbool_of_bool (Neqb a a0)). intro H3. rewrite H3. rewrite (Ndiv2_eq _ _ H3). - reflexivity. - intro H3. rewrite H3. rewrite <- H2 in H1. rewrite (Ndiv2_bit_neq _ _ H3 H1). - rewrite (MapGet_M2_bit_0_1 a0 H2 m0 m1). reflexivity. - assumption. - intro H2. rewrite (MapGet_M2_bit_0_0 a0 H2 m0 (MapRemove m1 (Ndiv2 a))). - rewrite (Neqb_comm a a0). rewrite (Nbit0_neq _ _ H2 H1). - rewrite (MapGet_M2_bit_0_0 a0 H2 m0 m1). reflexivity. - intro H1. rewrite H1. rewrite (makeM2_M2 (MapRemove m0 (Ndiv2 a)) m1 a0). - elim (sumbool_of_bool (Nbit0 a0)). intro H2. rewrite MapGet_M2_bit_0_1. - rewrite (MapGet_M2_bit_0_1 a0 H2 m0 m1). rewrite (Nbit0_neq a a0 H1 H2). reflexivity. - assumption. - intro H2. rewrite MapGet_M2_bit_0_0. rewrite (H (Ndiv2 a) (Ndiv2 a0)). - rewrite (MapGet_M2_bit_0_0 a0 H2 m0 m1). elim (sumbool_of_bool (Neqb a a0)). intro H3. - rewrite H3. rewrite (Ndiv2_eq _ _ H3). reflexivity. - intro H3. rewrite H3. rewrite <- H2 in H1. rewrite (Ndiv2_bit_neq _ _ H3 H1). reflexivity. - assumption. - Qed. - - Fixpoint MapCard (m:Map) : nat := - match m with - | M0 => 0 - | M1 _ _ => 1 - | M2 m m' => MapCard m + MapCard m' - end. - - Fixpoint MapMerge (m:Map) : Map -> Map := - match m with - | M0 => fun m':Map => m' - | M1 a y => fun m':Map => MapPut_behind m' a y - | M2 m1 m2 => - fun m':Map => - match m' with - | M0 => m - | M1 a' y' => MapPut m a' y' - | M2 m'1 m'2 => M2 (MapMerge m1 m'1) (MapMerge m2 m'2) - end - end. - - Lemma MapMerge_semantics : - forall m m':Map, - eqm (MapGet (MapMerge m m')) - (fun a0:ad => - match MapGet m' a0 with - | Some y' => Some y' - | None => MapGet m a0 - end). - Proof. - unfold eqm in |- *. simple induction m. intros. simpl in |- *. case (MapGet m' a); trivial. - intros. simpl in |- *. rewrite (MapPut_behind_semantics m' a a0 a1). reflexivity. - simple induction m'. trivial. - intros. unfold MapMerge in |- *. rewrite (MapPut_semantics (M2 m0 m1) a a0 a1). - elim (sumbool_of_bool (Neqb a a1)). intro H1. rewrite H1. rewrite (Neqb_complete _ _ H1). - rewrite (M1_semantics_1 a1 a0). reflexivity. - intro H1. rewrite H1. rewrite (M1_semantics_2 a a1 a0 H1). reflexivity. - intros. cut (MapMerge (M2 m0 m1) (M2 m2 m3) = M2 (MapMerge m0 m2) (MapMerge m1 m3)). - intro. rewrite H3. rewrite MapGet_M2_bit_0_if. rewrite (H0 m3 (Ndiv2 a)). - rewrite (H m2 (Ndiv2 a)). rewrite (MapGet_M2_bit_0_if m2 m3 a). - rewrite (MapGet_M2_bit_0_if m0 m1 a). case (Nbit0 a); trivial. - reflexivity. - Qed. - - (** [MapInter], [MapRngRestrTo], [MapRngRestrBy], [MapInverse] - not implemented: need a decidable equality on [A]. *) - - Fixpoint MapDelta (m:Map) : Map -> Map := - match m with - | M0 => fun m':Map => m' - | M1 a y => - fun m':Map => - match MapGet m' a with - | None => MapPut m' a y - | _ => MapRemove m' a - end - | M2 m1 m2 => - fun m':Map => - match m' with - | M0 => m - | M1 a' y' => - match MapGet m a' with - | None => MapPut m a' y' - | _ => MapRemove m a' - end - | M2 m'1 m'2 => makeM2 (MapDelta m1 m'1) (MapDelta m2 m'2) - end - end. - - Lemma MapDelta_semantics_comm : - forall m m':Map, eqm (MapGet (MapDelta m m')) (MapGet (MapDelta m' m)). - Proof. - unfold eqm in |- *. simple induction m. simple induction m'; reflexivity. - simple induction m'. reflexivity. - unfold MapDelta in |- *. intros. elim (sumbool_of_bool (Neqb a a1)). intro H. - rewrite <- (Neqb_complete _ _ H). rewrite (M1_semantics_1 a a2). - rewrite (M1_semantics_1 a a0). simpl in |- *. rewrite (Neqb_correct a). reflexivity. - intro H. rewrite (M1_semantics_2 a a1 a0 H). rewrite (Neqb_comm a a1) in H. - rewrite (M1_semantics_2 a1 a a2 H). rewrite (MapPut_semantics (M1 a a0) a1 a2 a3). - rewrite (MapPut_semantics (M1 a1 a2) a a0 a3). elim (sumbool_of_bool (Neqb a a3)). - intro H0. rewrite H0. rewrite (Neqb_complete _ _ H0) in H. rewrite H. - rewrite (Neqb_complete _ _ H0). rewrite (M1_semantics_1 a3 a0). reflexivity. - intro H0. rewrite H0. rewrite (M1_semantics_2 a a3 a0 H0). - elim (sumbool_of_bool (Neqb a1 a3)). intro H1. rewrite H1. - rewrite (Neqb_complete _ _ H1). exact (M1_semantics_1 a3 a2). - intro H1. rewrite H1. exact (M1_semantics_2 a1 a3 a2 H1). - intros. reflexivity. - simple induction m'. reflexivity. - reflexivity. - intros. simpl in |- *. rewrite (makeM2_M2 (MapDelta m0 m2) (MapDelta m1 m3) a). - rewrite (makeM2_M2 (MapDelta m2 m0) (MapDelta m3 m1) a). - rewrite (MapGet_M2_bit_0_if (MapDelta m0 m2) (MapDelta m1 m3) a). - rewrite (MapGet_M2_bit_0_if (MapDelta m2 m0) (MapDelta m3 m1) a). - rewrite (H0 m3 (Ndiv2 a)). rewrite (H m2 (Ndiv2 a)). reflexivity. - Qed. - - Lemma MapDelta_semantics_1_1 : - forall (a:ad) (y:A) (m':Map) (a0:ad), - MapGet (M1 a y) a0 = None -> - MapGet m' a0 = None -> MapGet (MapDelta (M1 a y) m') a0 = None. - Proof. - intros. unfold MapDelta in |- *. elim (sumbool_of_bool (Neqb a a0)). intro H1. - rewrite (Neqb_complete _ _ H1) in H. rewrite (M1_semantics_1 a0 y) in H. discriminate H. - intro H1. case (MapGet m' a). - rewrite (MapRemove_semantics m' a a0). rewrite H1. trivial. - rewrite (MapPut_semantics m' a y a0). rewrite H1. assumption. - Qed. - - Lemma MapDelta_semantics_1 : - forall (m m':Map) (a:ad), - MapGet m a = None -> - MapGet m' a = None -> MapGet (MapDelta m m') a = None. - Proof. - simple induction m. trivial. - exact MapDelta_semantics_1_1. - simple induction m'. trivial. - intros. rewrite (MapDelta_semantics_comm (M2 m0 m1) (M1 a a0) a1). - apply MapDelta_semantics_1_1; trivial. - intros. simpl in |- *. rewrite (makeM2_M2 (MapDelta m0 m2) (MapDelta m1 m3) a). - rewrite MapGet_M2_bit_0_if. elim (sumbool_of_bool (Nbit0 a)). intro H5. rewrite H5. - apply H0. rewrite (MapGet_M2_bit_0_1 a H5 m0 m1) in H3. exact H3. - rewrite (MapGet_M2_bit_0_1 a H5 m2 m3) in H4. exact H4. - intro H5. rewrite H5. apply H. rewrite (MapGet_M2_bit_0_0 a H5 m0 m1) in H3. exact H3. - rewrite (MapGet_M2_bit_0_0 a H5 m2 m3) in H4. exact H4. - Qed. - - Lemma MapDelta_semantics_2_1 : - forall (a:ad) (y:A) (m':Map) (a0:ad) (y0:A), - MapGet (M1 a y) a0 = None -> - MapGet m' a0 = Some y0 -> MapGet (MapDelta (M1 a y) m') a0 = Some y0. - Proof. - intros. unfold MapDelta in |- *. elim (sumbool_of_bool (Neqb a a0)). intro H1. - rewrite (Neqb_complete _ _ H1) in H. rewrite (M1_semantics_1 a0 y) in H. discriminate H. - intro H1. case (MapGet m' a). - rewrite (MapRemove_semantics m' a a0). rewrite H1. trivial. - rewrite (MapPut_semantics m' a y a0). rewrite H1. assumption. - Qed. - - Lemma MapDelta_semantics_2_2 : - forall (a:ad) (y:A) (m':Map) (a0:ad) (y0:A), - MapGet (M1 a y) a0 = Some y0 -> - MapGet m' a0 = None -> MapGet (MapDelta (M1 a y) m') a0 = Some y0. - Proof. - intros. unfold MapDelta in |- *. elim (sumbool_of_bool (Neqb a a0)). intro H1. - rewrite (Neqb_complete _ _ H1) in H. rewrite (Neqb_complete _ _ H1). - rewrite H0. rewrite (MapPut_semantics m' a0 y a0). rewrite (Neqb_correct a0). - rewrite (M1_semantics_1 a0 y) in H. simple inversion H. assumption. - intro H1. rewrite (M1_semantics_2 a a0 y H1) in H. discriminate H. - Qed. - - Lemma MapDelta_semantics_2 : - forall (m m':Map) (a:ad) (y:A), - MapGet m a = None -> - MapGet m' a = Some y -> MapGet (MapDelta m m') a = Some y. - Proof. - simple induction m. trivial. - exact MapDelta_semantics_2_1. - simple induction m'. intros. discriminate H2. - intros. rewrite (MapDelta_semantics_comm (M2 m0 m1) (M1 a a0) a1). - apply MapDelta_semantics_2_2; assumption. - intros. simpl in |- *. rewrite (makeM2_M2 (MapDelta m0 m2) (MapDelta m1 m3) a). - rewrite MapGet_M2_bit_0_if. elim (sumbool_of_bool (Nbit0 a)). intro H5. rewrite H5. - apply H0. rewrite <- (MapGet_M2_bit_0_1 a H5 m0 m1). assumption. - rewrite <- (MapGet_M2_bit_0_1 a H5 m2 m3). assumption. - intro H5. rewrite H5. apply H. rewrite <- (MapGet_M2_bit_0_0 a H5 m0 m1). assumption. - rewrite <- (MapGet_M2_bit_0_0 a H5 m2 m3). assumption. - Qed. - - Lemma MapDelta_semantics_3_1 : - forall (a0:ad) (y0:A) (m':Map) (a:ad) (y y':A), - MapGet (M1 a0 y0) a = Some y -> - MapGet m' a = Some y' -> MapGet (MapDelta (M1 a0 y0) m') a = None. - Proof. - intros. unfold MapDelta in |- *. elim (sumbool_of_bool (Neqb a0 a)). intro H1. - rewrite (Neqb_complete a0 a H1). rewrite H0. rewrite (MapRemove_semantics m' a a). - rewrite (Neqb_correct a). reflexivity. - intro H1. rewrite (M1_semantics_2 a0 a y0 H1) in H. discriminate H. - Qed. - - Lemma MapDelta_semantics_3 : - forall (m m':Map) (a:ad) (y y':A), - MapGet m a = Some y -> - MapGet m' a = Some y' -> MapGet (MapDelta m m') a = None. - Proof. - simple induction m. intros. discriminate H. - exact MapDelta_semantics_3_1. - simple induction m'. intros. discriminate H2. - intros. rewrite (MapDelta_semantics_comm (M2 m0 m1) (M1 a a0) a1). - exact (MapDelta_semantics_3_1 a a0 (M2 m0 m1) a1 y' y H2 H1). - intros. simpl in |- *. rewrite (makeM2_M2 (MapDelta m0 m2) (MapDelta m1 m3) a). - rewrite MapGet_M2_bit_0_if. elim (sumbool_of_bool (Nbit0 a)). intro H5. rewrite H5. - apply (H0 m3 (Ndiv2 a) y y'). rewrite <- (MapGet_M2_bit_0_1 a H5 m0 m1). assumption. - rewrite <- (MapGet_M2_bit_0_1 a H5 m2 m3). assumption. - intro H5. rewrite H5. apply (H m2 (Ndiv2 a) y y'). - rewrite <- (MapGet_M2_bit_0_0 a H5 m0 m1). assumption. - rewrite <- (MapGet_M2_bit_0_0 a H5 m2 m3). assumption. - Qed. - - Lemma MapDelta_semantics : - forall m m':Map, - eqm (MapGet (MapDelta m m')) - (fun a0:ad => - match MapGet m a0, MapGet m' a0 with - | None, Some y' => Some y' - | Some y, None => Some y - | _, _ => None - end). - Proof. - unfold eqm in |- *. intros. elim (option_sum (MapGet m' a)). intro H. elim H. intros a0 H0. - rewrite H0. elim (option_sum (MapGet m a)). intro H1. elim H1. intros a1 H2. rewrite H2. - exact (MapDelta_semantics_3 m m' a a1 a0 H2 H0). - intro H1. rewrite H1. exact (MapDelta_semantics_2 m m' a a0 H1 H0). - intro H. rewrite H. elim (option_sum (MapGet m a)). intro H0. elim H0. intros a0 H1. - rewrite H1. rewrite (MapDelta_semantics_comm m m' a). - exact (MapDelta_semantics_2 m' m a a0 H H1). - intro H0. rewrite H0. exact (MapDelta_semantics_1 m m' a H0 H). - Qed. - - Definition MapEmptyp (m:Map) := match m with - | M0 => true - | _ => false - end. - - Lemma MapEmptyp_correct : MapEmptyp M0 = true. - Proof. - reflexivity. - Qed. - - Lemma MapEmptyp_complete : forall m:Map, MapEmptyp m = true -> m = M0. - Proof. - simple induction m; trivial. intros. discriminate H. - intros. discriminate H1. - Qed. - - (** [MapSplit] not implemented: not the preferred way of recursing over Maps - (use [MapSweep], [MapCollect], or [MapFold] in Mapiter.v. *) - -End MapDefs.
\ No newline at end of file diff --git a/theories/IntMap/Mapaxioms.v b/theories/IntMap/Mapaxioms.v deleted file mode 100644 index 0722bcfa..00000000 --- a/theories/IntMap/Mapaxioms.v +++ /dev/null @@ -1,761 +0,0 @@ -(************************************************************************) -(* 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: Mapaxioms.v 8733 2006-04-25 22:52:18Z letouzey $ i*) - -Require Import Bool. -Require Import Sumbool. -Require Import NArith. -Require Import Ndigits. -Require Import Ndec. -Require Import Map. -Require Import Fset. - -Section MapAxioms. - - Variables A B C : Set. - - Lemma eqm_sym : forall f f':ad -> option A, eqm A f f' -> eqm A f' f. - Proof. - unfold eqm in |- *. intros. rewrite H. reflexivity. - Qed. - - Lemma eqm_refl : forall f:ad -> option A, eqm A f f. - Proof. - unfold eqm in |- *. trivial. - Qed. - - Lemma eqm_trans : - forall f f' f'':ad -> option A, eqm A f f' -> eqm A f' f'' -> eqm A f f''. - Proof. - unfold eqm in |- *. intros. rewrite H. exact (H0 a). - Qed. - - Definition eqmap (m m':Map A) := eqm A (MapGet A m) (MapGet A m'). - - Lemma eqmap_sym : forall m m':Map A, eqmap m m' -> eqmap m' m. - Proof. - intros. unfold eqmap in |- *. apply eqm_sym. assumption. - Qed. - - Lemma eqmap_refl : forall m:Map A, eqmap m m. - Proof. - intros. unfold eqmap in |- *. apply eqm_refl. - Qed. - - Lemma eqmap_trans : - forall m m' m'':Map A, eqmap m m' -> eqmap m' m'' -> eqmap m m''. - Proof. - intros. exact (eqm_trans (MapGet A m) (MapGet A m') (MapGet A m'') H H0). - Qed. - - Lemma MapPut_as_Merge : - forall (m:Map A) (a:ad) (y:A), - eqmap (MapPut A m a y) (MapMerge A m (M1 A a y)). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapPut_semantics A m a y a0). - rewrite (MapMerge_semantics A m (M1 A a y) a0). unfold MapGet at 2. - elim (sumbool_of_bool (Neqb a a0)); intro H; rewrite H; reflexivity. - Qed. - - Lemma MapPut_ext : - forall m m':Map A, - eqmap m m' -> - forall (a:ad) (y:A), eqmap (MapPut A m a y) (MapPut A m' a y). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapPut_semantics A m' a y a0). - rewrite (MapPut_semantics A m a y a0). - case (Neqb a a0); [ reflexivity | apply H ]. - Qed. - - Lemma MapPut_behind_as_Merge : - forall (m:Map A) (a:ad) (y:A), - eqmap (MapPut_behind A m a y) (MapMerge A (M1 A a y) m). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapPut_behind_semantics A m a y a0). - rewrite (MapMerge_semantics A (M1 A a y) m a0). reflexivity. - Qed. - - Lemma MapPut_behind_ext : - forall m m':Map A, - eqmap m m' -> - forall (a:ad) (y:A), - eqmap (MapPut_behind A m a y) (MapPut_behind A m' a y). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapPut_behind_semantics A m' a y a0). - rewrite (MapPut_behind_semantics A m a y a0). rewrite (H a0). reflexivity. - Qed. - - Lemma MapMerge_empty_m_1 : forall m:Map A, MapMerge A (M0 A) m = m. - Proof. - trivial. - Qed. - - Lemma MapMerge_empty_m : forall m:Map A, eqmap (MapMerge A (M0 A) m) m. - Proof. - unfold eqmap, eqm in |- *. trivial. - Qed. - - Lemma MapMerge_m_empty_1 : forall m:Map A, MapMerge A m (M0 A) = m. - Proof. - simple induction m; trivial. - Qed. - - Lemma MapMerge_m_empty : forall m:Map A, eqmap (MapMerge A m (M0 A)) m. - Proof. - unfold eqmap, eqm in |- *. intros. rewrite MapMerge_m_empty_1. reflexivity. - Qed. - - Lemma MapMerge_empty_l : - forall m m':Map A, eqmap (MapMerge A m m') (M0 A) -> eqmap m (M0 A). - Proof. - unfold eqmap, eqm in |- *. intros. cut (MapGet A (MapMerge A m m') a = MapGet A (M0 A) a). - rewrite (MapMerge_semantics A m m' a). case (MapGet A m' a); trivial. - intros. discriminate H0. - exact (H a). - Qed. - - Lemma MapMerge_empty_r : - forall m m':Map A, eqmap (MapMerge A m m') (M0 A) -> eqmap m' (M0 A). - Proof. - unfold eqmap, eqm in |- *. intros. cut (MapGet A (MapMerge A m m') a = MapGet A (M0 A) a). - rewrite (MapMerge_semantics A m m' a). case (MapGet A m' a); trivial. - exact (H a). - Qed. - - Lemma MapMerge_assoc : - forall m m' m'':Map A, - eqmap (MapMerge A (MapMerge A m m') m'') - (MapMerge A m (MapMerge A m' m'')). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapMerge_semantics A (MapMerge A m m') m'' a). - rewrite (MapMerge_semantics A m (MapMerge A m' m'') a). rewrite (MapMerge_semantics A m m' a). - rewrite (MapMerge_semantics A m' m'' a). - case (MapGet A m'' a); case (MapGet A m' a); trivial. - Qed. - - Lemma MapMerge_idempotent : forall m:Map A, eqmap (MapMerge A m m) m. - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapMerge_semantics A m m a). - case (MapGet A m a); trivial. - Qed. - - Lemma MapMerge_ext : - forall m1 m2 m'1 m'2:Map A, - eqmap m1 m'1 -> - eqmap m2 m'2 -> eqmap (MapMerge A m1 m2) (MapMerge A m'1 m'2). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapMerge_semantics A m1 m2 a). - rewrite (MapMerge_semantics A m'1 m'2 a). rewrite (H a). rewrite (H0 a). reflexivity. - Qed. - - Lemma MapMerge_ext_l : - forall m1 m'1 m2:Map A, - eqmap m1 m'1 -> eqmap (MapMerge A m1 m2) (MapMerge A m'1 m2). - Proof. - intros. apply MapMerge_ext. assumption. - apply eqmap_refl. - Qed. - - Lemma MapMerge_ext_r : - forall m1 m2 m'2:Map A, - eqmap m2 m'2 -> eqmap (MapMerge A m1 m2) (MapMerge A m1 m'2). - Proof. - intros. apply MapMerge_ext. apply eqmap_refl. - assumption. - Qed. - - Lemma MapMerge_RestrTo_l : - forall m m' m'':Map A, - eqmap (MapMerge A (MapDomRestrTo A A m m') m'') - (MapDomRestrTo A A (MapMerge A m m'') (MapMerge A m' m'')). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapMerge_semantics A (MapDomRestrTo A A m m') m'' a). - rewrite (MapDomRestrTo_semantics A A m m' a). - rewrite - (MapDomRestrTo_semantics A A (MapMerge A m m'') (MapMerge A m' m'') a) - . - rewrite (MapMerge_semantics A m' m'' a). rewrite (MapMerge_semantics A m m'' a). - case (MapGet A m'' a); case (MapGet A m' a); reflexivity. - Qed. - - Lemma MapRemove_as_RestrBy : - forall (m:Map A) (a:ad) (y:B), - eqmap (MapRemove A m a) (MapDomRestrBy A B m (M1 B a y)). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapRemove_semantics A m a a0). - rewrite (MapDomRestrBy_semantics A B m (M1 B a y) a0). elim (sumbool_of_bool (Neqb a a0)). - intro H. rewrite H. rewrite (Neqb_complete a a0 H). rewrite (M1_semantics_1 B a0 y). - reflexivity. - intro H. rewrite H. rewrite (M1_semantics_2 B a a0 y H). reflexivity. - Qed. - - Lemma MapRemove_ext : - forall m m':Map A, - eqmap m m' -> forall a:ad, eqmap (MapRemove A m a) (MapRemove A m' a). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapRemove_semantics A m' a a0). - rewrite (MapRemove_semantics A m a a0). - case (Neqb a a0); [ reflexivity | apply H ]. - Qed. - - Lemma MapDomRestrTo_empty_m_1 : - forall m:Map B, MapDomRestrTo A B (M0 A) m = M0 A. - Proof. - trivial. - Qed. - - Lemma MapDomRestrTo_empty_m : - forall m:Map B, eqmap (MapDomRestrTo A B (M0 A) m) (M0 A). - Proof. - unfold eqmap, eqm in |- *. trivial. - Qed. - - Lemma MapDomRestrTo_m_empty_1 : - forall m:Map A, MapDomRestrTo A B m (M0 B) = M0 A. - Proof. - simple induction m; trivial. - Qed. - - Lemma MapDomRestrTo_m_empty : - forall m:Map A, eqmap (MapDomRestrTo A B m (M0 B)) (M0 A). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDomRestrTo_m_empty_1 m). reflexivity. - Qed. - - Lemma MapDomRestrTo_assoc : - forall (m:Map A) (m':Map B) (m'':Map C), - eqmap (MapDomRestrTo A C (MapDomRestrTo A B m m') m'') - (MapDomRestrTo A B m (MapDomRestrTo B C m' m'')). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite (MapDomRestrTo_semantics A C (MapDomRestrTo A B m m') m'' a). - rewrite (MapDomRestrTo_semantics A B m m' a). - rewrite (MapDomRestrTo_semantics A B m (MapDomRestrTo B C m' m'') a). - rewrite (MapDomRestrTo_semantics B C m' m'' a). - case (MapGet C m'' a); case (MapGet B m' a); trivial. - Qed. - - Lemma MapDomRestrTo_idempotent : - forall m:Map A, eqmap (MapDomRestrTo A A m m) m. - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDomRestrTo_semantics A A m m a). - case (MapGet A m a); trivial. - Qed. - - Lemma MapDomRestrTo_Dom : - forall (m:Map A) (m':Map B), - eqmap (MapDomRestrTo A B m m') (MapDomRestrTo A unit m (MapDom B m')). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDomRestrTo_semantics A B m m' a). - rewrite (MapDomRestrTo_semantics A unit m (MapDom B m') a). - elim (sumbool_of_bool (in_FSet a (MapDom B m'))). intro H. - elim (MapDom_semantics_2 B m' a H). intros y H0. rewrite H0. unfold in_FSet, in_dom in H. - generalize H. case (MapGet unit (MapDom B m') a); trivial. intro H1. discriminate H1. - intro H. rewrite (MapDom_semantics_4 B m' a H). unfold in_FSet, in_dom in H. - generalize H. case (MapGet unit (MapDom B m') a); trivial. - intros H0 H1. discriminate H1. - Qed. - - Lemma MapDomRestrBy_empty_m_1 : - forall m:Map B, MapDomRestrBy A B (M0 A) m = M0 A. - Proof. - trivial. - Qed. - - Lemma MapDomRestrBy_empty_m : - forall m:Map B, eqmap (MapDomRestrBy A B (M0 A) m) (M0 A). - Proof. - unfold eqmap, eqm in |- *. trivial. - Qed. - - Lemma MapDomRestrBy_m_empty_1 : - forall m:Map A, MapDomRestrBy A B m (M0 B) = m. - Proof. - simple induction m; trivial. - Qed. - - Lemma MapDomRestrBy_m_empty : - forall m:Map A, eqmap (MapDomRestrBy A B m (M0 B)) m. - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDomRestrBy_m_empty_1 m). reflexivity. - Qed. - - Lemma MapDomRestrBy_Dom : - forall (m:Map A) (m':Map B), - eqmap (MapDomRestrBy A B m m') (MapDomRestrBy A unit m (MapDom B m')). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDomRestrBy_semantics A B m m' a). - rewrite (MapDomRestrBy_semantics A unit m (MapDom B m') a). - elim (sumbool_of_bool (in_FSet a (MapDom B m'))). intro H. - elim (MapDom_semantics_2 B m' a H). intros y H0. rewrite H0. - unfold in_FSet, in_dom in H. generalize H. case (MapGet unit (MapDom B m') a); trivial. - intro H1. discriminate H1. - intro H. rewrite (MapDom_semantics_4 B m' a H). unfold in_FSet, in_dom in H. - generalize H. case (MapGet unit (MapDom B m') a); trivial. - intros H0 H1. discriminate H1. - Qed. - - Lemma MapDomRestrBy_m_m_1 : - forall m:Map A, eqmap (MapDomRestrBy A A m m) (M0 A). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDomRestrBy_semantics A A m m a). - case (MapGet A m a); trivial. - Qed. - - Lemma MapDomRestrBy_By : - forall (m:Map A) (m' m'':Map B), - eqmap (MapDomRestrBy A B (MapDomRestrBy A B m m') m'') - (MapDomRestrBy A B m (MapMerge B m' m'')). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite (MapDomRestrBy_semantics A B (MapDomRestrBy A B m m') m'' a). - rewrite (MapDomRestrBy_semantics A B m m' a). - rewrite (MapDomRestrBy_semantics A B m (MapMerge B m' m'') a). - rewrite (MapMerge_semantics B m' m'' a). - case (MapGet B m'' a); case (MapGet B m' a); trivial. - Qed. - - Lemma MapDomRestrBy_By_comm : - forall (m:Map A) (m':Map B) (m'':Map C), - eqmap (MapDomRestrBy A C (MapDomRestrBy A B m m') m'') - (MapDomRestrBy A B (MapDomRestrBy A C m m'') m'). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite (MapDomRestrBy_semantics A C (MapDomRestrBy A B m m') m'' a). - rewrite (MapDomRestrBy_semantics A B m m' a). - rewrite (MapDomRestrBy_semantics A B (MapDomRestrBy A C m m'') m' a). - rewrite (MapDomRestrBy_semantics A C m m'' a). - case (MapGet C m'' a); case (MapGet B m' a); trivial. - Qed. - - Lemma MapDomRestrBy_To : - forall (m:Map A) (m':Map B) (m'':Map C), - eqmap (MapDomRestrBy A C (MapDomRestrTo A B m m') m'') - (MapDomRestrTo A B m (MapDomRestrBy B C m' m'')). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite (MapDomRestrBy_semantics A C (MapDomRestrTo A B m m') m'' a). - rewrite (MapDomRestrTo_semantics A B m m' a). - rewrite (MapDomRestrTo_semantics A B m (MapDomRestrBy B C m' m'') a). - rewrite (MapDomRestrBy_semantics B C m' m'' a). - case (MapGet C m'' a); case (MapGet B m' a); trivial. - Qed. - - Lemma MapDomRestrBy_To_comm : - forall (m:Map A) (m':Map B) (m'':Map C), - eqmap (MapDomRestrBy A C (MapDomRestrTo A B m m') m'') - (MapDomRestrTo A B (MapDomRestrBy A C m m'') m'). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite (MapDomRestrBy_semantics A C (MapDomRestrTo A B m m') m'' a). - rewrite (MapDomRestrTo_semantics A B m m' a). - rewrite (MapDomRestrTo_semantics A B (MapDomRestrBy A C m m'') m' a). - rewrite (MapDomRestrBy_semantics A C m m'' a). - case (MapGet C m'' a); case (MapGet B m' a); trivial. - Qed. - - Lemma MapDomRestrTo_By : - forall (m:Map A) (m':Map B) (m'':Map C), - eqmap (MapDomRestrTo A C (MapDomRestrBy A B m m') m'') - (MapDomRestrTo A C m (MapDomRestrBy C B m'' m')). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite (MapDomRestrTo_semantics A C (MapDomRestrBy A B m m') m'' a). - rewrite (MapDomRestrBy_semantics A B m m' a). - rewrite (MapDomRestrTo_semantics A C m (MapDomRestrBy C B m'' m') a). - rewrite (MapDomRestrBy_semantics C B m'' m' a). - case (MapGet C m'' a); case (MapGet B m' a); trivial. - Qed. - - Lemma MapDomRestrTo_By_comm : - forall (m:Map A) (m':Map B) (m'':Map C), - eqmap (MapDomRestrTo A C (MapDomRestrBy A B m m') m'') - (MapDomRestrBy A B (MapDomRestrTo A C m m'') m'). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite (MapDomRestrTo_semantics A C (MapDomRestrBy A B m m') m'' a). - rewrite (MapDomRestrBy_semantics A B m m' a). - rewrite (MapDomRestrBy_semantics A B (MapDomRestrTo A C m m'') m' a). - rewrite (MapDomRestrTo_semantics A C m m'' a). - case (MapGet C m'' a); case (MapGet B m' a); trivial. - Qed. - - Lemma MapDomRestrTo_To_comm : - forall (m:Map A) (m':Map B) (m'':Map C), - eqmap (MapDomRestrTo A C (MapDomRestrTo A B m m') m'') - (MapDomRestrTo A B (MapDomRestrTo A C m m'') m'). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite (MapDomRestrTo_semantics A C (MapDomRestrTo A B m m') m'' a). - rewrite (MapDomRestrTo_semantics A B m m' a). - rewrite (MapDomRestrTo_semantics A B (MapDomRestrTo A C m m'') m' a). - rewrite (MapDomRestrTo_semantics A C m m'' a). - case (MapGet C m'' a); case (MapGet B m' a); trivial. - Qed. - - Lemma MapMerge_DomRestrTo : - forall (m m':Map A) (m'':Map B), - eqmap (MapDomRestrTo A B (MapMerge A m m') m'') - (MapMerge A (MapDomRestrTo A B m m'') (MapDomRestrTo A B m' m'')). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite (MapDomRestrTo_semantics A B (MapMerge A m m') m'' a). - rewrite (MapMerge_semantics A m m' a). - rewrite - (MapMerge_semantics A (MapDomRestrTo A B m m'') - (MapDomRestrTo A B m' m'') a). - rewrite (MapDomRestrTo_semantics A B m' m'' a). - rewrite (MapDomRestrTo_semantics A B m m'' a). - case (MapGet B m'' a); case (MapGet A m' a); trivial. - Qed. - - Lemma MapMerge_DomRestrBy : - forall (m m':Map A) (m'':Map B), - eqmap (MapDomRestrBy A B (MapMerge A m m') m'') - (MapMerge A (MapDomRestrBy A B m m'') (MapDomRestrBy A B m' m'')). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite (MapDomRestrBy_semantics A B (MapMerge A m m') m'' a). - rewrite (MapMerge_semantics A m m' a). - rewrite - (MapMerge_semantics A (MapDomRestrBy A B m m'') - (MapDomRestrBy A B m' m'') a). - rewrite (MapDomRestrBy_semantics A B m' m'' a). - rewrite (MapDomRestrBy_semantics A B m m'' a). - case (MapGet B m'' a); case (MapGet A m' a); trivial. - Qed. - - Lemma MapDelta_empty_m_1 : forall m:Map A, MapDelta A (M0 A) m = m. - Proof. - trivial. - Qed. - - Lemma MapDelta_empty_m : forall m:Map A, eqmap (MapDelta A (M0 A) m) m. - Proof. - unfold eqmap, eqm in |- *. trivial. - Qed. - - Lemma MapDelta_m_empty_1 : forall m:Map A, MapDelta A m (M0 A) = m. - Proof. - simple induction m; trivial. - Qed. - - Lemma MapDelta_m_empty : forall m:Map A, eqmap (MapDelta A m (M0 A)) m. - Proof. - unfold eqmap, eqm in |- *. intros. rewrite MapDelta_m_empty_1. reflexivity. - Qed. - - Lemma MapDelta_nilpotent : forall m:Map A, eqmap (MapDelta A m m) (M0 A). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDelta_semantics A m m a). - case (MapGet A m a); trivial. - Qed. - - Lemma MapDelta_as_Merge : - forall m m':Map A, - eqmap (MapDelta A m m') - (MapMerge A (MapDomRestrBy A A m m') (MapDomRestrBy A A m' m)). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite (MapDelta_semantics A m m' a). - rewrite - (MapMerge_semantics A (MapDomRestrBy A A m m') ( - MapDomRestrBy A A m' m) a). - rewrite (MapDomRestrBy_semantics A A m' m a). - rewrite (MapDomRestrBy_semantics A A m m' a). - case (MapGet A m a); case (MapGet A m' a); trivial. - Qed. - - Lemma MapDelta_as_DomRestrBy : - forall m m':Map A, - eqmap (MapDelta A m m') - (MapDomRestrBy A A (MapMerge A m m') (MapDomRestrTo A A m m')). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDelta_semantics A m m' a). - rewrite - (MapDomRestrBy_semantics A A (MapMerge A m m') ( - MapDomRestrTo A A m m') a). - rewrite (MapDomRestrTo_semantics A A m m' a). rewrite (MapMerge_semantics A m m' a). - case (MapGet A m a); case (MapGet A m' a); trivial. - Qed. - - Lemma MapDelta_as_DomRestrBy_2 : - forall m m':Map A, - eqmap (MapDelta A m m') - (MapDomRestrBy A A (MapMerge A m m') (MapDomRestrTo A A m' m)). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDelta_semantics A m m' a). - rewrite - (MapDomRestrBy_semantics A A (MapMerge A m m') ( - MapDomRestrTo A A m' m) a). - rewrite (MapDomRestrTo_semantics A A m' m a). rewrite (MapMerge_semantics A m m' a). - case (MapGet A m a); case (MapGet A m' a); trivial. - Qed. - - Lemma MapDelta_sym : - forall m m':Map A, eqmap (MapDelta A m m') (MapDelta A m' m). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDelta_semantics A m m' a). - rewrite (MapDelta_semantics A m' m a). - case (MapGet A m a); case (MapGet A m' a); trivial. - Qed. - - Lemma MapDelta_ext : - forall m1 m2 m'1 m'2:Map A, - eqmap m1 m'1 -> - eqmap m2 m'2 -> eqmap (MapDelta A m1 m2) (MapDelta A m'1 m'2). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDelta_semantics A m1 m2 a). - rewrite (MapDelta_semantics A m'1 m'2 a). rewrite (H a). rewrite (H0 a). reflexivity. - Qed. - - Lemma MapDelta_ext_l : - forall m1 m'1 m2:Map A, - eqmap m1 m'1 -> eqmap (MapDelta A m1 m2) (MapDelta A m'1 m2). - Proof. - intros. apply MapDelta_ext. assumption. - apply eqmap_refl. - Qed. - - Lemma MapDelta_ext_r : - forall m1 m2 m'2:Map A, - eqmap m2 m'2 -> eqmap (MapDelta A m1 m2) (MapDelta A m1 m'2). - Proof. - intros. apply MapDelta_ext. apply eqmap_refl. - assumption. - Qed. - - Lemma MapDom_Split_1 : - forall (m:Map A) (m':Map B), - eqmap m (MapMerge A (MapDomRestrTo A B m m') (MapDomRestrBy A B m m')). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite - (MapMerge_semantics A (MapDomRestrTo A B m m') ( - MapDomRestrBy A B m m') a). - rewrite (MapDomRestrBy_semantics A B m m' a). - rewrite (MapDomRestrTo_semantics A B m m' a). - case (MapGet B m' a); case (MapGet A m a); trivial. - Qed. - - Lemma MapDom_Split_2 : - forall (m:Map A) (m':Map B), - eqmap m (MapMerge A (MapDomRestrBy A B m m') (MapDomRestrTo A B m m')). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite - (MapMerge_semantics A (MapDomRestrBy A B m m') ( - MapDomRestrTo A B m m') a). - rewrite (MapDomRestrBy_semantics A B m m' a). - rewrite (MapDomRestrTo_semantics A B m m' a). - case (MapGet B m' a); case (MapGet A m a); trivial. - Qed. - - Lemma MapDom_Split_3 : - forall (m:Map A) (m':Map B), - eqmap - (MapDomRestrTo A A (MapDomRestrTo A B m m') (MapDomRestrBy A B m m')) - (M0 A). - Proof. - unfold eqmap, eqm in |- *. intros. - rewrite - (MapDomRestrTo_semantics A A (MapDomRestrTo A B m m') - (MapDomRestrBy A B m m') a). - rewrite (MapDomRestrBy_semantics A B m m' a). - rewrite (MapDomRestrTo_semantics A B m m' a). - case (MapGet B m' a); case (MapGet A m a); trivial. - Qed. - -End MapAxioms. - -Lemma MapDomRestrTo_ext : - forall (A B:Set) (m1:Map A) (m2:Map B) (m'1:Map A) - (m'2:Map B), - eqmap A m1 m'1 -> - eqmap B m2 m'2 -> - eqmap A (MapDomRestrTo A B m1 m2) (MapDomRestrTo A B m'1 m'2). -Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDomRestrTo_semantics A B m1 m2 a). - rewrite (MapDomRestrTo_semantics A B m'1 m'2 a). rewrite (H a). rewrite (H0 a). reflexivity. -Qed. - -Lemma MapDomRestrTo_ext_l : - forall (A B:Set) (m1:Map A) (m2:Map B) (m'1:Map A), - eqmap A m1 m'1 -> - eqmap A (MapDomRestrTo A B m1 m2) (MapDomRestrTo A B m'1 m2). -Proof. - intros. apply MapDomRestrTo_ext; [ assumption | apply eqmap_refl ]. -Qed. - -Lemma MapDomRestrTo_ext_r : - forall (A B:Set) (m1:Map A) (m2 m'2:Map B), - eqmap B m2 m'2 -> - eqmap A (MapDomRestrTo A B m1 m2) (MapDomRestrTo A B m1 m'2). -Proof. - intros. apply MapDomRestrTo_ext; [ apply eqmap_refl | assumption ]. -Qed. - -Lemma MapDomRestrBy_ext : - forall (A B:Set) (m1:Map A) (m2:Map B) (m'1:Map A) - (m'2:Map B), - eqmap A m1 m'1 -> - eqmap B m2 m'2 -> - eqmap A (MapDomRestrBy A B m1 m2) (MapDomRestrBy A B m'1 m'2). -Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDomRestrBy_semantics A B m1 m2 a). - rewrite (MapDomRestrBy_semantics A B m'1 m'2 a). rewrite (H a). rewrite (H0 a). reflexivity. -Qed. - -Lemma MapDomRestrBy_ext_l : - forall (A B:Set) (m1:Map A) (m2:Map B) (m'1:Map A), - eqmap A m1 m'1 -> - eqmap A (MapDomRestrBy A B m1 m2) (MapDomRestrBy A B m'1 m2). -Proof. - intros. apply MapDomRestrBy_ext; [ assumption | apply eqmap_refl ]. -Qed. - -Lemma MapDomRestrBy_ext_r : - forall (A B:Set) (m1:Map A) (m2 m'2:Map B), - eqmap B m2 m'2 -> - eqmap A (MapDomRestrBy A B m1 m2) (MapDomRestrBy A B m1 m'2). -Proof. - intros. apply MapDomRestrBy_ext; [ apply eqmap_refl | assumption ]. -Qed. - -Lemma MapDomRestrBy_m_m : - forall (A:Set) (m:Map A), - eqmap A (MapDomRestrBy A unit m (MapDom A m)) (M0 A). -Proof. - intros. apply eqmap_trans with (m' := MapDomRestrBy A A m m). apply eqmap_sym. - apply MapDomRestrBy_Dom. - apply MapDomRestrBy_m_m_1. -Qed. - -Lemma FSetDelta_assoc : - forall s s' s'':FSet, - eqmap unit (MapDelta _ (MapDelta _ s s') s'') - (MapDelta _ s (MapDelta _ s' s'')). -Proof. - unfold eqmap, eqm in |- *. intros. rewrite (MapDelta_semantics unit (MapDelta unit s s') s'' a). - rewrite (MapDelta_semantics unit s s' a). - rewrite (MapDelta_semantics unit s (MapDelta unit s' s'') a). - rewrite (MapDelta_semantics unit s' s'' a). - case (MapGet _ s a); case (MapGet _ s' a); case (MapGet _ s'' a); trivial. - intros. elim u. elim u1. reflexivity. -Qed. - -Lemma FSet_ext : - forall s s':FSet, - (forall a:ad, in_FSet a s = in_FSet a s') -> eqmap unit s s'. -Proof. - unfold in_FSet, eqmap, eqm in |- *. intros. elim (sumbool_of_bool (in_dom _ a s)). intro H0. - elim (in_dom_some _ s a H0). intros y H1. rewrite (H a) in H0. elim (in_dom_some _ s' a H0). - intros y' H2. rewrite H1. rewrite H2. elim y. elim y'. reflexivity. - intro H0. rewrite (in_dom_none _ s a H0). rewrite (H a) in H0. rewrite (in_dom_none _ s' a H0). - reflexivity. -Qed. - -Lemma FSetUnion_comm : - forall s s':FSet, eqmap unit (FSetUnion s s') (FSetUnion s' s). -Proof. - intros. apply FSet_ext. intro. rewrite in_FSet_union. rewrite in_FSet_union. apply orb_comm. -Qed. - -Lemma FSetUnion_assoc : - forall s s' s'':FSet, - eqmap unit (FSetUnion (FSetUnion s s') s'') - (FSetUnion s (FSetUnion s' s'')). -Proof. - exact (MapMerge_assoc unit). -Qed. - -Lemma FSetUnion_M0_s : forall s:FSet, eqmap unit (FSetUnion (M0 unit) s) s. -Proof. - exact (MapMerge_empty_m unit). -Qed. - -Lemma FSetUnion_s_M0 : forall s:FSet, eqmap unit (FSetUnion s (M0 unit)) s. -Proof. - exact (MapMerge_m_empty unit). -Qed. - -Lemma FSetUnion_idempotent : forall s:FSet, eqmap unit (FSetUnion s s) s. -Proof. - exact (MapMerge_idempotent unit). -Qed. - -Lemma FSetInter_comm : - forall s s':FSet, eqmap unit (FSetInter s s') (FSetInter s' s). -Proof. - intros. apply FSet_ext. intro. rewrite in_FSet_inter. rewrite in_FSet_inter. apply andb_comm. -Qed. - -Lemma FSetInter_assoc : - forall s s' s'':FSet, - eqmap unit (FSetInter (FSetInter s s') s'') - (FSetInter s (FSetInter s' s'')). -Proof. - exact (MapDomRestrTo_assoc unit unit unit). -Qed. - -Lemma FSetInter_M0_s : - forall s:FSet, eqmap unit (FSetInter (M0 unit) s) (M0 unit). -Proof. - exact (MapDomRestrTo_empty_m unit unit). -Qed. - -Lemma FSetInter_s_M0 : - forall s:FSet, eqmap unit (FSetInter s (M0 unit)) (M0 unit). -Proof. - exact (MapDomRestrTo_m_empty unit unit). -Qed. - -Lemma FSetInter_idempotent : forall s:FSet, eqmap unit (FSetInter s s) s. -Proof. - exact (MapDomRestrTo_idempotent unit). -Qed. - -Lemma FSetUnion_Inter_l : - forall s s' s'':FSet, - eqmap unit (FSetUnion (FSetInter s s') s'') - (FSetInter (FSetUnion s s'') (FSetUnion s' s'')). -Proof. - intros. apply FSet_ext. intro. rewrite in_FSet_union. rewrite in_FSet_inter. - rewrite in_FSet_inter. rewrite in_FSet_union. rewrite in_FSet_union. - case (in_FSet a s); case (in_FSet a s'); case (in_FSet a s''); reflexivity. -Qed. - -Lemma FSetUnion_Inter_r : - forall s s' s'':FSet, - eqmap unit (FSetUnion s (FSetInter s' s'')) - (FSetInter (FSetUnion s s') (FSetUnion s s'')). -Proof. - intros. apply FSet_ext. intro. rewrite in_FSet_union. rewrite in_FSet_inter. - rewrite in_FSet_inter. rewrite in_FSet_union. rewrite in_FSet_union. - case (in_FSet a s); case (in_FSet a s'); case (in_FSet a s''); reflexivity. -Qed. - -Lemma FSetInter_Union_l : - forall s s' s'':FSet, - eqmap unit (FSetInter (FSetUnion s s') s'') - (FSetUnion (FSetInter s s'') (FSetInter s' s'')). -Proof. - intros. apply FSet_ext. intro. rewrite in_FSet_inter. rewrite in_FSet_union. - rewrite in_FSet_union. rewrite in_FSet_inter. rewrite in_FSet_inter. - case (in_FSet a s); case (in_FSet a s'); case (in_FSet a s''); reflexivity. -Qed. - -Lemma FSetInter_Union_r : - forall s s' s'':FSet, - eqmap unit (FSetInter s (FSetUnion s' s'')) - (FSetUnion (FSetInter s s') (FSetInter s s'')). -Proof. - intros. apply FSet_ext. intro. rewrite in_FSet_inter. rewrite in_FSet_union. - rewrite in_FSet_union. rewrite in_FSet_inter. rewrite in_FSet_inter. - case (in_FSet a s); case (in_FSet a s'); case (in_FSet a s''); reflexivity. -Qed.
\ No newline at end of file diff --git a/theories/IntMap/Mapc.v b/theories/IntMap/Mapc.v deleted file mode 100644 index 163373bf..00000000 --- a/theories/IntMap/Mapc.v +++ /dev/null @@ -1,539 +0,0 @@ -(************************************************************************) -(* 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: Mapc.v 8733 2006-04-25 22:52:18Z letouzey $ i*) - -Require Import Bool. -Require Import Sumbool. -Require Import Arith. -Require Import NArith. -Require Import Map. -Require Import Mapaxioms. -Require Import Fset. -Require Import Mapiter. -Require Import Mapsubset. -Require Import List. -Require Import Lsort. -Require Import Mapcard. -Require Import Mapcanon. - -Section MapC. - - Variables A B C : Set. - - Lemma MapPut_as_Merge_c : - forall m:Map A, - mapcanon A m -> - forall (a:ad) (y:A), MapPut A m a y = MapMerge A m (M1 A a y). - Proof. - intros. apply mapcanon_unique. exact (MapPut_canon A m H a y). - apply MapMerge_canon. assumption. - apply M1_canon. - apply MapPut_as_Merge. - Qed. - - Lemma MapPut_behind_as_Merge_c : - forall m:Map A, - mapcanon A m -> - forall (a:ad) (y:A), MapPut_behind A m a y = MapMerge A (M1 A a y) m. - Proof. - intros. apply mapcanon_unique. exact (MapPut_behind_canon A m H a y). - apply MapMerge_canon. apply M1_canon. - assumption. - apply MapPut_behind_as_Merge. - Qed. - - Lemma MapMerge_empty_m_c : forall m:Map A, MapMerge A (M0 A) m = m. - Proof. - trivial. - Qed. - - Lemma MapMerge_assoc_c : - forall m m' m'':Map A, - mapcanon A m -> - mapcanon A m' -> - mapcanon A m'' -> - MapMerge A (MapMerge A m m') m'' = MapMerge A m (MapMerge A m' m''). - Proof. - intros. apply mapcanon_unique. - apply MapMerge_canon; try assumption. apply MapMerge_canon; try assumption. - apply MapMerge_canon; try assumption. apply MapMerge_canon; try assumption. - apply MapMerge_assoc. - Qed. - - Lemma MapMerge_idempotent_c : - forall m:Map A, mapcanon A m -> MapMerge A m m = m. - Proof. - intros. apply mapcanon_unique. apply MapMerge_canon; assumption. - assumption. - apply MapMerge_idempotent. - Qed. - - Lemma MapMerge_RestrTo_l_c : - forall m m' m'':Map A, - mapcanon A m -> - mapcanon A m'' -> - MapMerge A (MapDomRestrTo A A m m') m'' = - MapDomRestrTo A A (MapMerge A m m'') (MapMerge A m' m''). - Proof. - intros. apply mapcanon_unique. apply MapMerge_canon. apply MapDomRestrTo_canon; assumption. - assumption. - apply MapDomRestrTo_canon; apply MapMerge_canon; assumption. - apply MapMerge_RestrTo_l. - Qed. - - Lemma MapRemove_as_RestrBy_c : - forall m:Map A, - mapcanon A m -> - forall (a:ad) (y:B), MapRemove A m a = MapDomRestrBy A B m (M1 B a y). - Proof. - intros. apply mapcanon_unique. apply MapRemove_canon; assumption. - apply MapDomRestrBy_canon; assumption. - apply MapRemove_as_RestrBy. - Qed. - - Lemma MapDomRestrTo_assoc_c : - forall (m:Map A) (m':Map B) (m'':Map C), - mapcanon A m -> - MapDomRestrTo A C (MapDomRestrTo A B m m') m'' = - MapDomRestrTo A B m (MapDomRestrTo B C m' m''). - Proof. - intros. apply mapcanon_unique. apply MapDomRestrTo_canon; try assumption. - apply MapDomRestrTo_canon; try assumption. - apply MapDomRestrTo_canon; try assumption. - apply MapDomRestrTo_assoc. - Qed. - - Lemma MapDomRestrTo_idempotent_c : - forall m:Map A, mapcanon A m -> MapDomRestrTo A A m m = m. - Proof. - intros. apply mapcanon_unique. apply MapDomRestrTo_canon; assumption. - assumption. - apply MapDomRestrTo_idempotent. - Qed. - - Lemma MapDomRestrTo_Dom_c : - forall (m:Map A) (m':Map B), - mapcanon A m -> - MapDomRestrTo A B m m' = MapDomRestrTo A unit m (MapDom B m'). - Proof. - intros. apply mapcanon_unique. apply MapDomRestrTo_canon; assumption. - apply MapDomRestrTo_canon; assumption. - apply MapDomRestrTo_Dom. - Qed. - - Lemma MapDomRestrBy_Dom_c : - forall (m:Map A) (m':Map B), - mapcanon A m -> - MapDomRestrBy A B m m' = MapDomRestrBy A unit m (MapDom B m'). - Proof. - intros. apply mapcanon_unique. apply MapDomRestrBy_canon; assumption. - apply MapDomRestrBy_canon; assumption. - apply MapDomRestrBy_Dom. - Qed. - - Lemma MapDomRestrBy_By_c : - forall (m:Map A) (m' m'':Map B), - mapcanon A m -> - MapDomRestrBy A B (MapDomRestrBy A B m m') m'' = - MapDomRestrBy A B m (MapMerge B m' m''). - Proof. - intros. apply mapcanon_unique. apply MapDomRestrBy_canon; try assumption. - apply MapDomRestrBy_canon; try assumption. - apply MapDomRestrBy_canon; try assumption. - apply MapDomRestrBy_By. - Qed. - - Lemma MapDomRestrBy_By_comm_c : - forall (m:Map A) (m':Map B) (m'':Map C), - mapcanon A m -> - MapDomRestrBy A C (MapDomRestrBy A B m m') m'' = - MapDomRestrBy A B (MapDomRestrBy A C m m'') m'. - Proof. - intros. apply mapcanon_unique. apply MapDomRestrBy_canon. - apply MapDomRestrBy_canon; assumption. - apply MapDomRestrBy_canon. apply MapDomRestrBy_canon; assumption. - apply MapDomRestrBy_By_comm. - Qed. - - Lemma MapDomRestrBy_To_c : - forall (m:Map A) (m':Map B) (m'':Map C), - mapcanon A m -> - MapDomRestrBy A C (MapDomRestrTo A B m m') m'' = - MapDomRestrTo A B m (MapDomRestrBy B C m' m''). - Proof. - intros. apply mapcanon_unique. apply MapDomRestrBy_canon. - apply MapDomRestrTo_canon; assumption. - apply MapDomRestrTo_canon; assumption. - apply MapDomRestrBy_To. - Qed. - - Lemma MapDomRestrBy_To_comm_c : - forall (m:Map A) (m':Map B) (m'':Map C), - mapcanon A m -> - MapDomRestrBy A C (MapDomRestrTo A B m m') m'' = - MapDomRestrTo A B (MapDomRestrBy A C m m'') m'. - Proof. - intros. apply mapcanon_unique. apply MapDomRestrBy_canon. - apply MapDomRestrTo_canon; assumption. - apply MapDomRestrTo_canon. apply MapDomRestrBy_canon; assumption. - apply MapDomRestrBy_To_comm. - Qed. - - Lemma MapDomRestrTo_By_c : - forall (m:Map A) (m':Map B) (m'':Map C), - mapcanon A m -> - MapDomRestrTo A C (MapDomRestrBy A B m m') m'' = - MapDomRestrTo A C m (MapDomRestrBy C B m'' m'). - Proof. - intros. apply mapcanon_unique. apply MapDomRestrTo_canon. - apply MapDomRestrBy_canon; assumption. - apply MapDomRestrTo_canon; assumption. - apply MapDomRestrTo_By. - Qed. - - Lemma MapDomRestrTo_By_comm_c : - forall (m:Map A) (m':Map B) (m'':Map C), - mapcanon A m -> - MapDomRestrTo A C (MapDomRestrBy A B m m') m'' = - MapDomRestrBy A B (MapDomRestrTo A C m m'') m'. - Proof. - intros. apply mapcanon_unique. apply MapDomRestrTo_canon. - apply MapDomRestrBy_canon; assumption. - apply MapDomRestrBy_canon. apply MapDomRestrTo_canon; assumption. - apply MapDomRestrTo_By_comm. - Qed. - - Lemma MapDomRestrTo_To_comm_c : - forall (m:Map A) (m':Map B) (m'':Map C), - mapcanon A m -> - MapDomRestrTo A C (MapDomRestrTo A B m m') m'' = - MapDomRestrTo A B (MapDomRestrTo A C m m'') m'. - Proof. - intros. apply mapcanon_unique. apply MapDomRestrTo_canon. - apply MapDomRestrTo_canon; assumption. - apply MapDomRestrTo_canon. apply MapDomRestrTo_canon; assumption. - apply MapDomRestrTo_To_comm. - Qed. - - Lemma MapMerge_DomRestrTo_c : - forall (m m':Map A) (m'':Map B), - mapcanon A m -> - mapcanon A m' -> - MapDomRestrTo A B (MapMerge A m m') m'' = - MapMerge A (MapDomRestrTo A B m m'') (MapDomRestrTo A B m' m''). - Proof. - intros. apply mapcanon_unique. apply MapDomRestrTo_canon. - apply MapMerge_canon; assumption. - apply MapMerge_canon. apply MapDomRestrTo_canon; assumption. - apply MapDomRestrTo_canon; assumption. - apply MapMerge_DomRestrTo. - Qed. - - Lemma MapMerge_DomRestrBy_c : - forall (m m':Map A) (m'':Map B), - mapcanon A m -> - mapcanon A m' -> - MapDomRestrBy A B (MapMerge A m m') m'' = - MapMerge A (MapDomRestrBy A B m m'') (MapDomRestrBy A B m' m''). - Proof. - intros. apply mapcanon_unique. apply MapDomRestrBy_canon. apply MapMerge_canon; assumption. - apply MapMerge_canon. apply MapDomRestrBy_canon; assumption. - apply MapDomRestrBy_canon; assumption. - apply MapMerge_DomRestrBy. - Qed. - - Lemma MapDelta_nilpotent_c : - forall m:Map A, mapcanon A m -> MapDelta A m m = M0 A. - Proof. - intros. apply mapcanon_unique. apply MapDelta_canon; assumption. - apply M0_canon. - apply MapDelta_nilpotent. - Qed. - - Lemma MapDelta_as_Merge_c : - forall m m':Map A, - mapcanon A m -> - mapcanon A m' -> - MapDelta A m m' = - MapMerge A (MapDomRestrBy A A m m') (MapDomRestrBy A A m' m). - Proof. - intros. apply mapcanon_unique. apply MapDelta_canon; assumption. - apply MapMerge_canon; apply MapDomRestrBy_canon; assumption. - apply MapDelta_as_Merge. - Qed. - - Lemma MapDelta_as_DomRestrBy_c : - forall m m':Map A, - mapcanon A m -> - mapcanon A m' -> - MapDelta A m m' = - MapDomRestrBy A A (MapMerge A m m') (MapDomRestrTo A A m m'). - Proof. - intros. apply mapcanon_unique. apply MapDelta_canon; assumption. - apply MapDomRestrBy_canon. apply MapMerge_canon; assumption. - apply MapDelta_as_DomRestrBy. - Qed. - - Lemma MapDelta_as_DomRestrBy_2_c : - forall m m':Map A, - mapcanon A m -> - mapcanon A m' -> - MapDelta A m m' = - MapDomRestrBy A A (MapMerge A m m') (MapDomRestrTo A A m' m). - Proof. - intros. apply mapcanon_unique. apply MapDelta_canon; assumption. - apply MapDomRestrBy_canon. apply MapMerge_canon; assumption. - apply MapDelta_as_DomRestrBy_2. - Qed. - - Lemma MapDelta_sym_c : - forall m m':Map A, - mapcanon A m -> mapcanon A m' -> MapDelta A m m' = MapDelta A m' m. - Proof. - intros. apply mapcanon_unique. apply MapDelta_canon; assumption. - apply MapDelta_canon; assumption. apply MapDelta_sym. - Qed. - - Lemma MapDom_Split_1_c : - forall (m:Map A) (m':Map B), - mapcanon A m -> - m = MapMerge A (MapDomRestrTo A B m m') (MapDomRestrBy A B m m'). - Proof. - intros. apply mapcanon_unique. assumption. - apply MapMerge_canon. apply MapDomRestrTo_canon; assumption. - apply MapDomRestrBy_canon; assumption. - apply MapDom_Split_1. - Qed. - - Lemma MapDom_Split_2_c : - forall (m:Map A) (m':Map B), - mapcanon A m -> - m = MapMerge A (MapDomRestrBy A B m m') (MapDomRestrTo A B m m'). - Proof. - intros. apply mapcanon_unique. assumption. - apply MapMerge_canon. apply MapDomRestrBy_canon; assumption. - apply MapDomRestrTo_canon; assumption. - apply MapDom_Split_2. - Qed. - - Lemma MapDom_Split_3_c : - forall (m:Map A) (m':Map B), - mapcanon A m -> - MapDomRestrTo A A (MapDomRestrTo A B m m') (MapDomRestrBy A B m m') = - M0 A. - Proof. - intros. apply mapcanon_unique. apply MapDomRestrTo_canon. - apply MapDomRestrTo_canon; assumption. - apply M0_canon. - apply MapDom_Split_3. - Qed. - - Lemma Map_of_alist_of_Map_c : - forall m:Map A, mapcanon A m -> Map_of_alist A (alist_of_Map A m) = m. - Proof. - intros. apply mapcanon_unique; try assumption. apply Map_of_alist_canon. - apply Map_of_alist_of_Map. - Qed. - - Lemma alist_of_Map_of_alist_c : - forall l:alist A, - alist_sorted_2 A l -> alist_of_Map A (Map_of_alist A l) = l. - Proof. - intros. apply alist_canonical. apply alist_of_Map_of_alist. - apply alist_of_Map_sorts2. - assumption. - Qed. - - Lemma MapSubset_antisym_c : - forall (m:Map A) (m':Map B), - mapcanon A m -> - mapcanon B m' -> - MapSubset A B m m' -> MapSubset B A m' m -> MapDom A m = MapDom B m'. - Proof. - intros. apply (mapcanon_unique unit). apply MapDom_canon; assumption. - apply MapDom_canon; assumption. - apply MapSubset_antisym; assumption. - Qed. - - Lemma FSubset_antisym_c : - forall s s':FSet, - mapcanon unit s -> - mapcanon unit s' -> MapSubset _ _ s s' -> MapSubset _ _ s' s -> s = s'. - Proof. - intros. apply (mapcanon_unique unit); try assumption. apply FSubset_antisym; assumption. - Qed. - - Lemma MapDisjoint_empty_c : - forall m:Map A, mapcanon A m -> MapDisjoint A A m m -> m = M0 A. - Proof. - intros. apply mapcanon_unique; try assumption; try apply M0_canon. - apply MapDisjoint_empty; assumption. - Qed. - - Lemma MapDelta_disjoint_c : - forall m m':Map A, - mapcanon A m -> - mapcanon A m' -> - MapDisjoint A A m m' -> MapDelta A m m' = MapMerge A m m'. - Proof. - intros. apply mapcanon_unique. apply MapDelta_canon; assumption. - apply MapMerge_canon; assumption. apply MapDelta_disjoint; assumption. - Qed. - -End MapC. - -Lemma FSetDelta_assoc_c : - forall s s' s'':FSet, - mapcanon unit s -> - mapcanon unit s' -> - mapcanon unit s'' -> - MapDelta _ (MapDelta _ s s') s'' = MapDelta _ s (MapDelta _ s' s''). -Proof. - intros. apply (mapcanon_unique unit). apply MapDelta_canon. apply MapDelta_canon; assumption. - assumption. - apply MapDelta_canon. assumption. - apply MapDelta_canon; assumption. - apply FSetDelta_assoc; assumption. -Qed. - -Lemma FSet_ext_c : - forall s s':FSet, - mapcanon unit s -> - mapcanon unit s' -> (forall a:ad, in_FSet a s = in_FSet a s') -> s = s'. -Proof. - intros. apply (mapcanon_unique unit); try assumption. apply FSet_ext. assumption. -Qed. - -Lemma FSetUnion_comm_c : - forall s s':FSet, - mapcanon unit s -> mapcanon unit s' -> FSetUnion s s' = FSetUnion s' s. -Proof. - intros. - apply (mapcanon_unique unit); - try (unfold FSetUnion in |- *; apply MapMerge_canon; assumption). - apply FSetUnion_comm. -Qed. - -Lemma FSetUnion_assoc_c : - forall s s' s'':FSet, - mapcanon unit s -> - mapcanon unit s' -> - mapcanon unit s'' -> - FSetUnion (FSetUnion s s') s'' = FSetUnion s (FSetUnion s' s''). -Proof. - exact (MapMerge_assoc_c unit). -Qed. - -Lemma FSetUnion_M0_s_c : forall s:FSet, FSetUnion (M0 unit) s = s. -Proof. - exact (MapMerge_empty_m_c unit). -Qed. - -Lemma FSetUnion_s_M0_c : forall s:FSet, FSetUnion s (M0 unit) = s. -Proof. - exact (MapMerge_m_empty_1 unit). -Qed. - -Lemma FSetUnion_idempotent : - forall s:FSet, mapcanon unit s -> FSetUnion s s = s. -Proof. - exact (MapMerge_idempotent_c unit). -Qed. - -Lemma FSetInter_comm_c : - forall s s':FSet, - mapcanon unit s -> mapcanon unit s' -> FSetInter s s' = FSetInter s' s. -Proof. - intros. - apply (mapcanon_unique unit); - try (unfold FSetInter in |- *; apply MapDomRestrTo_canon; assumption). - apply FSetInter_comm. -Qed. - -Lemma FSetInter_assoc_c : - forall s s' s'':FSet, - mapcanon unit s -> - FSetInter (FSetInter s s') s'' = FSetInter s (FSetInter s' s''). -Proof. - exact (MapDomRestrTo_assoc_c unit unit unit). -Qed. - -Lemma FSetInter_M0_s_c : forall s:FSet, FSetInter (M0 unit) s = M0 unit. -Proof. - trivial. -Qed. - -Lemma FSetInter_s_M0_c : forall s:FSet, FSetInter s (M0 unit) = M0 unit. -Proof. - exact (MapDomRestrTo_m_empty_1 unit unit). -Qed. - -Lemma FSetInter_idempotent : - forall s:FSet, mapcanon unit s -> FSetInter s s = s. -Proof. - exact (MapDomRestrTo_idempotent_c unit). -Qed. - -Lemma FSetUnion_Inter_l_c : - forall s s' s'':FSet, - mapcanon unit s -> - mapcanon unit s'' -> - FSetUnion (FSetInter s s') s'' = - FSetInter (FSetUnion s s'') (FSetUnion s' s''). -Proof. - intros. apply (mapcanon_unique unit). unfold FSetUnion in |- *. apply MapMerge_canon; try assumption. - unfold FSetInter in |- *. apply MapDomRestrTo_canon; assumption. - unfold FSetInter in |- *; unfold FSetUnion in |- *; - apply MapDomRestrTo_canon; apply MapMerge_canon; - assumption. - apply FSetUnion_Inter_l. -Qed. - -Lemma FSetUnion_Inter_r : - forall s s' s'':FSet, - mapcanon unit s -> - mapcanon unit s' -> - FSetUnion s (FSetInter s' s'') = - FSetInter (FSetUnion s s') (FSetUnion s s''). -Proof. - intros. apply (mapcanon_unique unit). unfold FSetUnion in |- *. apply MapMerge_canon; try assumption. - unfold FSetInter in |- *. apply MapDomRestrTo_canon; assumption. - unfold FSetInter in |- *; unfold FSetUnion in |- *; - apply MapDomRestrTo_canon; apply MapMerge_canon; - assumption. - apply FSetUnion_Inter_r. -Qed. - -Lemma FSetInter_Union_l_c : - forall s s' s'':FSet, - mapcanon unit s -> - mapcanon unit s' -> - FSetInter (FSetUnion s s') s'' = - FSetUnion (FSetInter s s'') (FSetInter s' s''). -Proof. - intros. apply (mapcanon_unique unit). unfold FSetInter in |- *. - apply MapDomRestrTo_canon; try assumption. unfold FSetUnion in |- *. - apply MapMerge_canon; assumption. - unfold FSetUnion in |- *; unfold FSetInter in |- *; apply MapMerge_canon; - apply MapDomRestrTo_canon; assumption. - apply FSetInter_Union_l. -Qed. - -Lemma FSetInter_Union_r : - forall s s' s'':FSet, - mapcanon unit s -> - mapcanon unit s' -> - FSetInter s (FSetUnion s' s'') = - FSetUnion (FSetInter s s') (FSetInter s s''). -Proof. - intros. apply (mapcanon_unique unit). unfold FSetInter in |- *. - apply MapDomRestrTo_canon; try assumption. - unfold FSetUnion in |- *. apply MapMerge_canon; unfold FSetInter in |- *; apply MapDomRestrTo_canon; - assumption. - apply FSetInter_Union_r. -Qed.
\ No newline at end of file diff --git a/theories/IntMap/Mapcanon.v b/theories/IntMap/Mapcanon.v deleted file mode 100644 index 33741b98..00000000 --- a/theories/IntMap/Mapcanon.v +++ /dev/null @@ -1,401 +0,0 @@ -(************************************************************************) -(* 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: Mapcanon.v 8733 2006-04-25 22:52:18Z letouzey $ i*) - -Require Import Bool. -Require Import Sumbool. -Require Import Arith. -Require Import NArith. -Require Import Ndigits. -Require Import Ndec. -Require Import Map. -Require Import Mapaxioms. -Require Import Mapiter. -Require Import Fset. -Require Import List. -Require Import Lsort. -Require Import Mapsubset. -Require Import Mapcard. - -Section MapCanon. - - Variable A : Set. - - Inductive mapcanon : Map A -> Prop := - | M0_canon : mapcanon (M0 A) - | M1_canon : forall (a:ad) (y:A), mapcanon (M1 A a y) - | M2_canon : - forall m1 m2:Map A, - mapcanon m1 -> - mapcanon m2 -> 2 <= MapCard A (M2 A m1 m2) -> mapcanon (M2 A m1 m2). - - Lemma mapcanon_M2 : - forall m1 m2:Map A, mapcanon (M2 A m1 m2) -> 2 <= MapCard A (M2 A m1 m2). - Proof. - intros. inversion H. assumption. - Qed. - - Lemma mapcanon_M2_1 : - forall m1 m2:Map A, mapcanon (M2 A m1 m2) -> mapcanon m1. - Proof. - intros. inversion H. assumption. - Qed. - - Lemma mapcanon_M2_2 : - forall m1 m2:Map A, mapcanon (M2 A m1 m2) -> mapcanon m2. - Proof. - intros. inversion H. assumption. - Qed. - - Lemma M2_eqmap_1 : - forall m0 m1 m2 m3:Map A, - eqmap A (M2 A m0 m1) (M2 A m2 m3) -> eqmap A m0 m2. - Proof. - unfold eqmap, eqm in |- *. intros. rewrite <- (Ndouble_div2 a). - rewrite <- (MapGet_M2_bit_0_0 A _ (Ndouble_bit0 a) m0 m1). - rewrite <- (MapGet_M2_bit_0_0 A _ (Ndouble_bit0 a) m2 m3). - exact (H (Ndouble a)). - Qed. - - Lemma M2_eqmap_2 : - forall m0 m1 m2 m3:Map A, - eqmap A (M2 A m0 m1) (M2 A m2 m3) -> eqmap A m1 m3. - Proof. - unfold eqmap, eqm in |- *. intros. rewrite <- (Ndouble_plus_one_div2 a). - rewrite <- (MapGet_M2_bit_0_1 A _ (Ndouble_plus_one_bit0 a) m0 m1). - rewrite <- (MapGet_M2_bit_0_1 A _ (Ndouble_plus_one_bit0 a) m2 m3). - exact (H (Ndouble_plus_one a)). - Qed. - - Lemma mapcanon_unique : - forall m m':Map A, mapcanon m -> mapcanon m' -> eqmap A m m' -> m = m'. - Proof. - simple induction m. simple induction m'. trivial. - intros a y H H0 H1. cut (None = MapGet A (M1 A a y) a). simpl in |- *. rewrite (Neqb_correct a). - intro. discriminate H2. - exact (H1 a). - intros. cut (2 <= MapCard A (M0 A)). intro. elim (le_Sn_O _ H4). - rewrite (MapCard_ext A _ _ H3). exact (mapcanon_M2 _ _ H2). - intros a y. simple induction m'. intros. cut (MapGet A (M1 A a y) a = None). simpl in |- *. - rewrite (Neqb_correct a). intro. discriminate H2. - exact (H1 a). - intros a0 y0 H H0 H1. cut (MapGet A (M1 A a y) a = MapGet A (M1 A a0 y0) a). simpl in |- *. - rewrite (Neqb_correct a). intro. elim (sumbool_of_bool (Neqb a0 a)). intro H3. - rewrite H3 in H2. inversion H2. rewrite (Neqb_complete _ _ H3). reflexivity. - intro H3. rewrite H3 in H2. discriminate H2. - exact (H1 a). - intros. cut (2 <= MapCard A (M1 A a y)). intro. elim (le_Sn_O _ (le_S_n _ _ H4)). - rewrite (MapCard_ext A _ _ H3). exact (mapcanon_M2 _ _ H2). - simple induction m'. intros. cut (2 <= MapCard A (M0 A)). intro. elim (le_Sn_O _ H4). - rewrite <- (MapCard_ext A _ _ H3). exact (mapcanon_M2 _ _ H1). - intros a y H1 H2 H3. cut (2 <= MapCard A (M1 A a y)). intro. - elim (le_Sn_O _ (le_S_n _ _ H4)). - rewrite <- (MapCard_ext A _ _ H3). exact (mapcanon_M2 _ _ H1). - intros. rewrite (H m2). rewrite (H0 m3). reflexivity. - exact (mapcanon_M2_2 _ _ H3). - exact (mapcanon_M2_2 _ _ H4). - exact (M2_eqmap_2 _ _ _ _ H5). - exact (mapcanon_M2_1 _ _ H3). - exact (mapcanon_M2_1 _ _ H4). - exact (M2_eqmap_1 _ _ _ _ H5). - Qed. - - Lemma MapPut1_canon : - forall (p:positive) (a a':ad) (y y':A), mapcanon (MapPut1 A a y a' y' p). - Proof. - simple induction p. simpl in |- *. intros. case (Nbit0 a). apply M2_canon. apply M1_canon. - apply M1_canon. - apply le_n. - apply M2_canon. apply M1_canon. - apply M1_canon. - apply le_n. - simpl in |- *. intros. case (Nbit0 a). apply M2_canon. apply M0_canon. - apply H. - simpl in |- *. rewrite MapCard_Put1_equals_2. apply le_n. - apply M2_canon. apply H. - apply M0_canon. - simpl in |- *. rewrite MapCard_Put1_equals_2. apply le_n. - simpl in |- *. simpl in |- *. intros. case (Nbit0 a). apply M2_canon. apply M1_canon. - apply M1_canon. - simpl in |- *. apply le_n. - apply M2_canon. apply M1_canon. - apply M1_canon. - simpl in |- *. apply le_n. - Qed. - - Lemma MapPut_canon : - forall m:Map A, - mapcanon m -> forall (a:ad) (y:A), mapcanon (MapPut A m a y). - Proof. - simple induction m. intros. simpl in |- *. apply M1_canon. - intros a0 y0 H a y. simpl in |- *. case (Nxor a0 a). apply M1_canon. - intro. apply MapPut1_canon. - intros. simpl in |- *. elim a. apply M2_canon. apply H. exact (mapcanon_M2_1 m0 m1 H1). - exact (mapcanon_M2_2 m0 m1 H1). - simpl in |- *. apply le_trans with (m := MapCard A m0 + MapCard A m1). exact (mapcanon_M2 _ _ H1). - apply plus_le_compat. exact (MapCard_Put_lb A m0 N0 y). - apply le_n. - intro. case p. intro. apply M2_canon. exact (mapcanon_M2_1 m0 m1 H1). - apply H0. exact (mapcanon_M2_2 m0 m1 H1). - simpl in |- *. apply le_trans with (m := MapCard A m0 + MapCard A m1). - exact (mapcanon_M2 m0 m1 H1). - apply plus_le_compat_l. exact (MapCard_Put_lb A m1 (Npos p0) y). - intro. apply M2_canon. apply H. exact (mapcanon_M2_1 m0 m1 H1). - exact (mapcanon_M2_2 m0 m1 H1). - simpl in |- *. apply le_trans with (m := MapCard A m0 + MapCard A m1). - exact (mapcanon_M2 m0 m1 H1). - apply plus_le_compat_r. exact (MapCard_Put_lb A m0 (Npos p0) y). - apply M2_canon. apply (mapcanon_M2_1 m0 m1 H1). - apply H0. apply (mapcanon_M2_2 m0 m1 H1). - simpl in |- *. apply le_trans with (m := MapCard A m0 + MapCard A m1). - exact (mapcanon_M2 m0 m1 H1). - apply plus_le_compat_l. exact (MapCard_Put_lb A m1 N0 y). - Qed. - - Lemma MapPut_behind_canon : - forall m:Map A, - mapcanon m -> forall (a:ad) (y:A), mapcanon (MapPut_behind A m a y). - Proof. - simple induction m. intros. simpl in |- *. apply M1_canon. - intros a0 y0 H a y. simpl in |- *. case (Nxor a0 a). apply M1_canon. - intro. apply MapPut1_canon. - intros. simpl in |- *. elim a. apply M2_canon. apply H. exact (mapcanon_M2_1 m0 m1 H1). - exact (mapcanon_M2_2 m0 m1 H1). - simpl in |- *. apply le_trans with (m := MapCard A m0 + MapCard A m1). exact (mapcanon_M2 _ _ H1). - apply plus_le_compat. rewrite MapCard_Put_behind_Put. exact (MapCard_Put_lb A m0 N0 y). - apply le_n. - intro. case p. intro. apply M2_canon. exact (mapcanon_M2_1 m0 m1 H1). - apply H0. exact (mapcanon_M2_2 m0 m1 H1). - simpl in |- *. apply le_trans with (m := MapCard A m0 + MapCard A m1). - exact (mapcanon_M2 m0 m1 H1). - apply plus_le_compat_l. rewrite MapCard_Put_behind_Put. exact (MapCard_Put_lb A m1 (Npos p0) y). - intro. apply M2_canon. apply H. exact (mapcanon_M2_1 m0 m1 H1). - exact (mapcanon_M2_2 m0 m1 H1). - simpl in |- *. apply le_trans with (m := MapCard A m0 + MapCard A m1). - exact (mapcanon_M2 m0 m1 H1). - apply plus_le_compat_r. rewrite MapCard_Put_behind_Put. exact (MapCard_Put_lb A m0 (Npos p0) y). - apply M2_canon. apply (mapcanon_M2_1 m0 m1 H1). - apply H0. apply (mapcanon_M2_2 m0 m1 H1). - simpl in |- *. apply le_trans with (m := MapCard A m0 + MapCard A m1). - exact (mapcanon_M2 m0 m1 H1). - apply plus_le_compat_l. rewrite MapCard_Put_behind_Put. exact (MapCard_Put_lb A m1 N0 y). - Qed. - - Lemma makeM2_canon : - forall m m':Map A, mapcanon m -> mapcanon m' -> mapcanon (makeM2 A m m'). - Proof. - intro. case m. intro. case m'. intros. exact M0_canon. - intros a y H H0. exact (M1_canon (Ndouble_plus_one a) y). - intros. simpl in |- *. apply M2_canon; try assumption. exact (mapcanon_M2 m0 m1 H0). - intros a y m'. case m'. intros. exact (M1_canon (Ndouble a) y). - intros a0 y0 H H0. simpl in |- *. apply M2_canon; try assumption. apply le_n. - intros. simpl in |- *. apply M2_canon; try assumption. - apply le_trans with (m := MapCard A (M2 A m0 m1)). exact (mapcanon_M2 _ _ H0). - exact (le_plus_r (MapCard A (M1 A a y)) (MapCard A (M2 A m0 m1))). - simpl in |- *. intros. apply M2_canon; try assumption. - apply le_trans with (m := MapCard A (M2 A m0 m1)). exact (mapcanon_M2 _ _ H). - exact (le_plus_l (MapCard A (M2 A m0 m1)) (MapCard A m')). - Qed. - - Fixpoint MapCanonicalize (m:Map A) : Map A := - match m with - | M2 m0 m1 => makeM2 A (MapCanonicalize m0) (MapCanonicalize m1) - | _ => m - end. - - Lemma mapcanon_exists_1 : forall m:Map A, eqmap A m (MapCanonicalize m). - Proof. - simple induction m. apply eqmap_refl. - intros. apply eqmap_refl. - intros. simpl in |- *. unfold eqmap, eqm in |- *. intro. - rewrite (makeM2_M2 A (MapCanonicalize m0) (MapCanonicalize m1) a). - rewrite MapGet_M2_bit_0_if. rewrite MapGet_M2_bit_0_if. - rewrite <- (H (Ndiv2 a)). rewrite <- (H0 (Ndiv2 a)). reflexivity. - Qed. - - Lemma mapcanon_exists_2 : forall m:Map A, mapcanon (MapCanonicalize m). - Proof. - simple induction m. apply M0_canon. - intros. simpl in |- *. apply M1_canon. - intros. simpl in |- *. apply makeM2_canon; assumption. - Qed. - - Lemma mapcanon_exists : - forall m:Map A, {m' : Map A | eqmap A m m' /\ mapcanon m'}. - Proof. - intro. split with (MapCanonicalize m). split. apply mapcanon_exists_1. - apply mapcanon_exists_2. - Qed. - - Lemma MapRemove_canon : - forall m:Map A, mapcanon m -> forall a:ad, mapcanon (MapRemove A m a). - Proof. - simple induction m. intros. exact M0_canon. - intros a y H a0. simpl in |- *. case (Neqb a a0). exact M0_canon. - assumption. - intros. simpl in |- *. case (Nbit0 a). apply makeM2_canon. exact (mapcanon_M2_1 _ _ H1). - apply H0. exact (mapcanon_M2_2 _ _ H1). - apply makeM2_canon. apply H. exact (mapcanon_M2_1 _ _ H1). - exact (mapcanon_M2_2 _ _ H1). - Qed. - - Lemma MapMerge_canon : - forall m m':Map A, mapcanon m -> mapcanon m' -> mapcanon (MapMerge A m m'). - Proof. - simple induction m. intros. exact H0. - simpl in |- *. intros a y m' H H0. exact (MapPut_behind_canon m' H0 a y). - simple induction m'. intros. exact H1. - intros a y H1 H2. unfold MapMerge in |- *. exact (MapPut_canon _ H1 a y). - intros. simpl in |- *. apply M2_canon. apply H. exact (mapcanon_M2_1 _ _ H3). - exact (mapcanon_M2_1 _ _ H4). - apply H0. exact (mapcanon_M2_2 _ _ H3). - exact (mapcanon_M2_2 _ _ H4). - change (2 <= MapCard A (MapMerge A (M2 A m0 m1) (M2 A m2 m3))) in |- *. - apply le_trans with (m := MapCard A (M2 A m0 m1)). exact (mapcanon_M2 _ _ H3). - exact (MapMerge_Card_lb_l A (M2 A m0 m1) (M2 A m2 m3)). - Qed. - - Lemma MapDelta_canon : - forall m m':Map A, mapcanon m -> mapcanon m' -> mapcanon (MapDelta A m m'). - Proof. - simple induction m. intros. exact H0. - simpl in |- *. intros a y m' H H0. case (MapGet A m' a). - intro. exact (MapRemove_canon m' H0 a). - exact (MapPut_canon m' H0 a y). - simple induction m'. intros. exact H1. - unfold MapDelta in |- *. intros a y H1 H2. case (MapGet A (M2 A m0 m1) a). - intro. exact (MapRemove_canon _ H1 a). - exact (MapPut_canon _ H1 a y). - intros. simpl in |- *. apply makeM2_canon. apply H. exact (mapcanon_M2_1 _ _ H3). - exact (mapcanon_M2_1 _ _ H4). - apply H0. exact (mapcanon_M2_2 _ _ H3). - exact (mapcanon_M2_2 _ _ H4). - Qed. - - Variable B : Set. - - Lemma MapDomRestrTo_canon : - forall m:Map A, - mapcanon m -> forall m':Map B, mapcanon (MapDomRestrTo A B m m'). - Proof. - simple induction m. intros. exact M0_canon. - simpl in |- *. intros a y H m'. case (MapGet B m' a). - intro. apply M1_canon. - exact M0_canon. - simple induction m'. exact M0_canon. - unfold MapDomRestrTo in |- *. intros a y. case (MapGet A (M2 A m0 m1) a). - intro. apply M1_canon. - exact M0_canon. - intros. simpl in |- *. apply makeM2_canon. apply H. exact (mapcanon_M2_1 m0 m1 H1). - apply H0. exact (mapcanon_M2_2 m0 m1 H1). - Qed. - - Lemma MapDomRestrBy_canon : - forall m:Map A, - mapcanon m -> forall m':Map B, mapcanon (MapDomRestrBy A B m m'). - Proof. - simple induction m. intros. exact M0_canon. - simpl in |- *. intros a y H m'. case (MapGet B m' a); try assumption. - intro. exact M0_canon. - simple induction m'. exact H1. - intros a y. simpl in |- *. case (Nbit0 a). apply makeM2_canon. exact (mapcanon_M2_1 _ _ H1). - apply MapRemove_canon. exact (mapcanon_M2_2 _ _ H1). - apply makeM2_canon. apply MapRemove_canon. exact (mapcanon_M2_1 _ _ H1). - exact (mapcanon_M2_2 _ _ H1). - intros. simpl in |- *. apply makeM2_canon. apply H. exact (mapcanon_M2_1 _ _ H1). - apply H0. exact (mapcanon_M2_2 _ _ H1). - Qed. - - Lemma Map_of_alist_canon : forall l:alist A, mapcanon (Map_of_alist A l). - Proof. - simple induction l. exact M0_canon. - intro r. elim r. intros a y l0 H. simpl in |- *. apply MapPut_canon. assumption. - Qed. - - Lemma MapSubset_c_1 : - forall (m:Map A) (m':Map B), - mapcanon m -> MapSubset A B m m' -> MapDomRestrBy A B m m' = M0 A. - Proof. - intros. apply mapcanon_unique. apply MapDomRestrBy_canon. assumption. - apply M0_canon. - exact (MapSubset_imp_2 _ _ m m' H0). - Qed. - - Lemma MapSubset_c_2 : - forall (m:Map A) (m':Map B), - MapDomRestrBy A B m m' = M0 A -> MapSubset A B m m'. - Proof. - intros. apply MapSubset_2_imp. unfold MapSubset_2 in |- *. rewrite H. apply eqmap_refl. - Qed. - -End MapCanon. - -Section FSetCanon. - - Variable A : Set. - - Lemma MapDom_canon : - forall m:Map A, mapcanon A m -> mapcanon unit (MapDom A m). - Proof. - simple induction m. intro. exact (M0_canon unit). - intros a y H. exact (M1_canon unit a _). - intros. simpl in |- *. apply M2_canon. apply H. exact (mapcanon_M2_1 A _ _ H1). - apply H0. exact (mapcanon_M2_2 A _ _ H1). - change (2 <= MapCard unit (MapDom A (M2 A m0 m1))) in |- *. rewrite <- MapCard_Dom. - exact (mapcanon_M2 A _ _ H1). - Qed. - -End FSetCanon. - -Section MapFoldCanon. - - Variables A B : Set. - - Lemma MapFold_canon_1 : - forall m0:Map B, - mapcanon B m0 -> - forall op:Map B -> Map B -> Map B, - (forall m1:Map B, - mapcanon B m1 -> - forall m2:Map B, mapcanon B m2 -> mapcanon B (op m1 m2)) -> - forall f:ad -> A -> Map B, - (forall (a:ad) (y:A), mapcanon B (f a y)) -> - forall (m:Map A) (pf:ad -> ad), - mapcanon B (MapFold1 A (Map B) m0 op f pf m). - Proof. - simple induction m. intro. exact H. - intros a y pf. simpl in |- *. apply H1. - intros. simpl in |- *. apply H0. apply H2. - apply H3. - Qed. - - Lemma MapFold_canon : - forall m0:Map B, - mapcanon B m0 -> - forall op:Map B -> Map B -> Map B, - (forall m1:Map B, - mapcanon B m1 -> - forall m2:Map B, mapcanon B m2 -> mapcanon B (op m1 m2)) -> - forall f:ad -> A -> Map B, - (forall (a:ad) (y:A), mapcanon B (f a y)) -> - forall m:Map A, mapcanon B (MapFold A (Map B) m0 op f m). - Proof. - intros. exact (MapFold_canon_1 m0 H op H0 f H1 m (fun a:ad => a)). - Qed. - - Lemma MapCollect_canon : - forall f:ad -> A -> Map B, - (forall (a:ad) (y:A), mapcanon B (f a y)) -> - forall m:Map A, mapcanon B (MapCollect A B f m). - Proof. - intros. rewrite MapCollect_as_Fold. apply MapFold_canon. apply M0_canon. - intros. exact (MapMerge_canon B m1 m2 H0 H1). - assumption. - Qed. - -End MapFoldCanon.
\ No newline at end of file diff --git a/theories/IntMap/Mapcard.v b/theories/IntMap/Mapcard.v deleted file mode 100644 index 36be9bf9..00000000 --- a/theories/IntMap/Mapcard.v +++ /dev/null @@ -1,764 +0,0 @@ -(************************************************************************) -(* 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: Mapcard.v 8733 2006-04-25 22:52:18Z letouzey $ i*) - -Require Import Bool. -Require Import Sumbool. -Require Import Arith. -Require Import NArith. -Require Import Ndigits. -Require Import Ndec. -Require Import Map. -Require Import Mapaxioms. -Require Import Mapiter. -Require Import Fset. -Require Import Mapsubset. -Require Import List. -Require Import Lsort. -Require Import Peano_dec. - -Section MapCard. - - Variables A B : Set. - - Lemma MapCard_M0 : MapCard A (M0 A) = 0. - Proof. - trivial. - Qed. - - Lemma MapCard_M1 : forall (a:ad) (y:A), MapCard A (M1 A a y) = 1. - Proof. - trivial. - Qed. - - Lemma MapCard_is_O : - forall m:Map A, MapCard A m = 0 -> forall a:ad, MapGet A m a = None. - Proof. - simple induction m. trivial. - intros a y H. discriminate H. - intros. simpl in H1. elim (plus_is_O _ _ H1). intros. rewrite (MapGet_M2_bit_0_if A m0 m1 a). - case (Nbit0 a). apply H0. assumption. - apply H. assumption. - Qed. - - Lemma MapCard_is_not_O : - forall (m:Map A) (a:ad) (y:A), - MapGet A m a = Some y -> {n : nat | MapCard A m = S n}. - Proof. - simple induction m. intros. discriminate H. - intros a y a0 y0 H. simpl in H. elim (sumbool_of_bool (Neqb a a0)). intro H0. split with 0. - reflexivity. - intro H0. rewrite H0 in H. discriminate H. - intros. elim (sumbool_of_bool (Nbit0 a)). intro H2. - rewrite (MapGet_M2_bit_0_1 A a H2 m0 m1) in H1. elim (H0 (Ndiv2 a) y H1). intros n H3. - simpl in |- *. rewrite H3. split with (MapCard A m0 + n). - rewrite <- (plus_Snm_nSm (MapCard A m0) n). reflexivity. - intro H2. rewrite (MapGet_M2_bit_0_0 A a H2 m0 m1) in H1. elim (H (Ndiv2 a) y H1). - intros n H3. simpl in |- *. rewrite H3. split with (n + MapCard A m1). reflexivity. - Qed. - - Lemma MapCard_is_one : - forall m:Map A, - MapCard A m = 1 -> {a : ad & {y : A | MapGet A m a = Some y}}. - Proof. - simple induction m. intro. discriminate H. - intros a y H. split with a. split with y. apply M1_semantics_1. - intros. simpl in H1. elim (plus_is_one (MapCard A m0) (MapCard A m1) H1). - intro H2. elim H2. intros. elim (H0 H4). intros a H5. split with (Ndouble_plus_one a). - rewrite (MapGet_M2_bit_0_1 A _ (Ndouble_plus_one_bit0 a) m0 m1). - rewrite Ndouble_plus_one_div2. exact H5. - intro H2. elim H2. intros. elim (H H3). intros a H5. split with (Ndouble a). - rewrite (MapGet_M2_bit_0_0 A _ (Ndouble_bit0 a) m0 m1). - rewrite Ndouble_div2. exact H5. - Qed. - - Lemma MapCard_is_one_unique : - forall m:Map A, - MapCard A m = 1 -> - forall (a a':ad) (y y':A), - MapGet A m a = Some y -> - MapGet A m a' = Some y' -> a = a' /\ y = y'. - Proof. - simple induction m. intro. discriminate H. - intros. elim (sumbool_of_bool (Neqb a a1)). intro H2. rewrite (Neqb_complete _ _ H2) in H0. - rewrite (M1_semantics_1 A a1 a0) in H0. inversion H0. elim (sumbool_of_bool (Neqb a a')). - intro H5. rewrite (Neqb_complete _ _ H5) in H1. rewrite (M1_semantics_1 A a' a0) in H1. - inversion H1. rewrite <- (Neqb_complete _ _ H2). rewrite <- (Neqb_complete _ _ H5). - rewrite <- H4. rewrite <- H6. split; reflexivity. - intro H5. rewrite (M1_semantics_2 A a a' a0 H5) in H1. discriminate H1. - intro H2. rewrite (M1_semantics_2 A a a1 a0 H2) in H0. discriminate H0. - intros. simpl in H1. elim (plus_is_one _ _ H1). intro H4. elim H4. intros. - rewrite (MapGet_M2_bit_0_if A m0 m1 a) in H2. elim (sumbool_of_bool (Nbit0 a)). - intro H7. rewrite H7 in H2. rewrite (MapGet_M2_bit_0_if A m0 m1 a') in H3. - elim (sumbool_of_bool (Nbit0 a')). intro H8. rewrite H8 in H3. elim (H0 H6 _ _ _ _ H2 H3). - intros. split. rewrite <- (Ndiv2_double_plus_one a H7). - rewrite <- (Ndiv2_double_plus_one a' H8). rewrite H9. reflexivity. - assumption. - intro H8. rewrite H8 in H3. rewrite (MapCard_is_O m0 H5 (Ndiv2 a')) in H3. - discriminate H3. - intro H7. rewrite H7 in H2. rewrite (MapCard_is_O m0 H5 (Ndiv2 a)) in H2. - discriminate H2. - intro H4. elim H4. intros. rewrite (MapGet_M2_bit_0_if A m0 m1 a) in H2. - elim (sumbool_of_bool (Nbit0 a)). intro H7. rewrite H7 in H2. - rewrite (MapCard_is_O m1 H6 (Ndiv2 a)) in H2. discriminate H2. - intro H7. rewrite H7 in H2. rewrite (MapGet_M2_bit_0_if A m0 m1 a') in H3. - elim (sumbool_of_bool (Nbit0 a')). intro H8. rewrite H8 in H3. - rewrite (MapCard_is_O m1 H6 (Ndiv2 a')) in H3. discriminate H3. - intro H8. rewrite H8 in H3. elim (H H5 _ _ _ _ H2 H3). intros. split. - rewrite <- (Ndiv2_double a H7). rewrite <- (Ndiv2_double a' H8). - rewrite H9. reflexivity. - assumption. - Qed. - - Lemma length_as_fold : - forall (C:Set) (l:list C), - length l = fold_right (fun (_:C) (n:nat) => S n) 0 l. - Proof. - simple induction l. reflexivity. - intros. simpl in |- *. rewrite H. reflexivity. - Qed. - - Lemma length_as_fold_2 : - forall l:alist A, - length l = - fold_right (fun (r:ad * A) (n:nat) => let (a, y) := r in 1 + n) 0 l. - Proof. - simple induction l. reflexivity. - intros. simpl in |- *. rewrite H. elim a; reflexivity. - Qed. - - Lemma MapCard_as_Fold_1 : - forall (m:Map A) (pf:ad -> ad), - MapCard A m = MapFold1 A nat 0 plus (fun (_:ad) (_:A) => 1) pf m. - Proof. - simple induction m. trivial. - trivial. - intros. simpl in |- *. rewrite <- (H (fun a0:ad => pf (Ndouble a0))). - rewrite <- (H0 (fun a0:ad => pf (Ndouble_plus_one a0))). reflexivity. - Qed. - - Lemma MapCard_as_Fold : - forall m:Map A, - MapCard A m = MapFold A nat 0 plus (fun (_:ad) (_:A) => 1) m. - Proof. - intro. exact (MapCard_as_Fold_1 m (fun a0:ad => a0)). - Qed. - - Lemma MapCard_as_length : - forall m:Map A, MapCard A m = length (alist_of_Map A m). - Proof. - intro. rewrite MapCard_as_Fold. rewrite length_as_fold_2. - apply MapFold_as_fold with - (op := plus) (neutral := 0) (f := fun (_:ad) (_:A) => 1). exact plus_assoc_reverse. - trivial. - intro. rewrite <- plus_n_O. reflexivity. - Qed. - - Lemma MapCard_Put1_equals_2 : - forall (p:positive) (a a':ad) (y y':A), - MapCard A (MapPut1 A a y a' y' p) = 2. - Proof. - simple induction p. intros. simpl in |- *. case (Nbit0 a); reflexivity. - intros. simpl in |- *. case (Nbit0 a). exact (H (Ndiv2 a) (Ndiv2 a') y y'). - simpl in |- *. rewrite <- plus_n_O. exact (H (Ndiv2 a) (Ndiv2 a') y y'). - intros. simpl in |- *. case (Nbit0 a); reflexivity. - Qed. - - Lemma MapCard_Put_sum : - forall (m m':Map A) (a:ad) (y:A) (n n':nat), - m' = MapPut A m a y -> - n = MapCard A m -> n' = MapCard A m' -> {n' = n} + {n' = S n}. - Proof. - simple induction m. simpl in |- *. intros. rewrite H in H1. simpl in H1. right. - rewrite H0. rewrite H1. reflexivity. - intros a y m' a0 y0 n n' H H0 H1. simpl in H. elim (Ndiscr (Nxor a a0)). intro H2. - elim H2. intros p H3. rewrite H3 in H. rewrite H in H1. - rewrite (MapCard_Put1_equals_2 p a a0 y y0) in H1. simpl in H0. right. - rewrite H0. rewrite H1. reflexivity. - intro H2. rewrite H2 in H. rewrite H in H1. simpl in H1. simpl in H0. left. - rewrite H0. rewrite H1. reflexivity. - intros. simpl in H2. rewrite (MapPut_semantics_3_1 A m0 m1 a y) in H1. - elim (sumbool_of_bool (Nbit0 a)). intro H4. rewrite H4 in H1. - elim - (H0 (MapPut A m1 (Ndiv2 a) y) (Ndiv2 a) y ( - MapCard A m1) (MapCard A (MapPut A m1 (Ndiv2 a) y)) ( - refl_equal _) (refl_equal _) (refl_equal _)). - intro H5. rewrite H1 in H3. simpl in H3. rewrite H5 in H3. rewrite <- H2 in H3. left. - assumption. - intro H5. rewrite H1 in H3. simpl in H3. rewrite H5 in H3. - rewrite <- (plus_Snm_nSm (MapCard A m0) (MapCard A m1)) in H3. - simpl in H3. rewrite <- H2 in H3. right. assumption. - intro H4. rewrite H4 in H1. - elim - (H (MapPut A m0 (Ndiv2 a) y) (Ndiv2 a) y ( - MapCard A m0) (MapCard A (MapPut A m0 (Ndiv2 a) y)) ( - refl_equal _) (refl_equal _) (refl_equal _)). - intro H5. rewrite H1 in H3. simpl in H3. rewrite H5 in H3. rewrite <- H2 in H3. - left. assumption. - intro H5. rewrite H1 in H3. simpl in H3. rewrite H5 in H3. simpl in H3. rewrite <- H2 in H3. - right. assumption. - Qed. - - Lemma MapCard_Put_lb : - forall (m:Map A) (a:ad) (y:A), MapCard A (MapPut A m a y) >= MapCard A m. - Proof. - unfold ge in |- *. intros. - elim - (MapCard_Put_sum m (MapPut A m a y) a y (MapCard A m) - (MapCard A (MapPut A m a y)) (refl_equal _) ( - refl_equal _) (refl_equal _)). - intro H. rewrite H. apply le_n. - intro H. rewrite H. apply le_n_Sn. - Qed. - - Lemma MapCard_Put_ub : - forall (m:Map A) (a:ad) (y:A), - MapCard A (MapPut A m a y) <= S (MapCard A m). - Proof. - intros. - elim - (MapCard_Put_sum m (MapPut A m a y) a y (MapCard A m) - (MapCard A (MapPut A m a y)) (refl_equal _) ( - refl_equal _) (refl_equal _)). - intro H. rewrite H. apply le_n_Sn. - intro H. rewrite H. apply le_n. - Qed. - - Lemma MapCard_Put_1 : - forall (m:Map A) (a:ad) (y:A), - MapCard A (MapPut A m a y) = MapCard A m -> - {y : A | MapGet A m a = Some y}. - Proof. - simple induction m. intros. discriminate H. - intros a y a0 y0 H. simpl in H. elim (Ndiscr (Nxor a a0)). intro H0. elim H0. - intros p H1. rewrite H1 in H. rewrite (MapCard_Put1_equals_2 p a a0 y y0) in H. - discriminate H. - intro H0. rewrite H0 in H. rewrite (Nxor_eq _ _ H0). split with y. apply M1_semantics_1. - intros. rewrite (MapPut_semantics_3_1 A m0 m1 a y) in H1. elim (sumbool_of_bool (Nbit0 a)). - intro H2. rewrite H2 in H1. simpl in H1. elim (H0 (Ndiv2 a) y ((fun n m p:nat => plus_reg_l m p n) _ _ _ H1)). - intros y0 H3. split with y0. rewrite <- H3. exact (MapGet_M2_bit_0_1 A a H2 m0 m1). - intro H2. rewrite H2 in H1. simpl in H1. - rewrite - (plus_comm (MapCard A (MapPut A m0 (Ndiv2 a) y)) (MapCard A m1)) - in H1. - rewrite (plus_comm (MapCard A m0) (MapCard A m1)) in H1. - elim (H (Ndiv2 a) y ((fun n m p:nat => plus_reg_l m p n) _ _ _ H1)). intros y0 H3. split with y0. - rewrite <- H3. exact (MapGet_M2_bit_0_0 A a H2 m0 m1). - Qed. - - Lemma MapCard_Put_2 : - forall (m:Map A) (a:ad) (y:A), - MapCard A (MapPut A m a y) = S (MapCard A m) -> MapGet A m a = None. - Proof. - simple induction m. trivial. - intros. simpl in H. elim (sumbool_of_bool (Neqb a a1)). intro H0. - rewrite (Neqb_complete _ _ H0) in H. rewrite (Nxor_nilpotent a1) in H. discriminate H. - intro H0. exact (M1_semantics_2 A a a1 a0 H0). - intros. elim (sumbool_of_bool (Nbit0 a)). intro H2. - rewrite (MapGet_M2_bit_0_1 A a H2 m0 m1). apply (H0 (Ndiv2 a) y). - apply (fun n m p:nat => plus_reg_l m p n) with (n := MapCard A m0). - rewrite <- (plus_Snm_nSm (MapCard A m0) (MapCard A m1)). simpl in H1. simpl in |- *. rewrite <- H1. - clear H1. - induction a. discriminate H2. - induction p. reflexivity. - discriminate H2. - reflexivity. - intro H2. rewrite (MapGet_M2_bit_0_0 A a H2 m0 m1). apply (H (Ndiv2 a) y). - cut - (MapCard A (MapPut A m0 (Ndiv2 a) y) + MapCard A m1 = - S (MapCard A m0) + MapCard A m1). - intro. rewrite (plus_comm (MapCard A (MapPut A m0 (Ndiv2 a) y)) (MapCard A m1)) - in H3. - rewrite (plus_comm (S (MapCard A m0)) (MapCard A m1)) in H3. exact ((fun n m p:nat => plus_reg_l m p n) _ _ _ H3). - simpl in |- *. simpl in H1. rewrite <- H1. induction a. trivial. - induction p. discriminate H2. - reflexivity. - discriminate H2. - Qed. - - Lemma MapCard_Put_1_conv : - forall (m:Map A) (a:ad) (y y':A), - MapGet A m a = Some y -> MapCard A (MapPut A m a y') = MapCard A m. - Proof. - intros. - elim - (MapCard_Put_sum m (MapPut A m a y') a y' (MapCard A m) - (MapCard A (MapPut A m a y')) (refl_equal _) ( - refl_equal _) (refl_equal _)). - trivial. - intro H0. rewrite (MapCard_Put_2 m a y' H0) in H. discriminate H. - Qed. - - Lemma MapCard_Put_2_conv : - forall (m:Map A) (a:ad) (y:A), - MapGet A m a = None -> MapCard A (MapPut A m a y) = S (MapCard A m). - Proof. - intros. - elim - (MapCard_Put_sum m (MapPut A m a y) a y (MapCard A m) - (MapCard A (MapPut A m a y)) (refl_equal _) ( - refl_equal _) (refl_equal _)). - intro H0. elim (MapCard_Put_1 m a y H0). intros y' H1. rewrite H1 in H. discriminate H. - trivial. - Qed. - - Lemma MapCard_ext : - forall m m':Map A, - eqm A (MapGet A m) (MapGet A m') -> MapCard A m = MapCard A m'. - Proof. - unfold eqm in |- *. intros. rewrite (MapCard_as_length m). rewrite (MapCard_as_length m'). - rewrite (alist_canonical A (alist_of_Map A m) (alist_of_Map A m')). reflexivity. - unfold eqm in |- *. intro. rewrite (Map_of_alist_semantics A (alist_of_Map A m) a). - rewrite (Map_of_alist_semantics A (alist_of_Map A m') a). rewrite (Map_of_alist_of_Map A m' a). - rewrite (Map_of_alist_of_Map A m a). exact (H a). - apply alist_of_Map_sorts2. - apply alist_of_Map_sorts2. - Qed. - - Lemma MapCard_Dom : forall m:Map A, MapCard A m = MapCard unit (MapDom A m). - Proof. - simple induction m; trivial. intros. simpl in |- *. rewrite H. rewrite H0. reflexivity. - Qed. - - Lemma MapCard_Dom_Put_behind : - forall (m:Map A) (a:ad) (y:A), - MapDom A (MapPut_behind A m a y) = MapDom A (MapPut A m a y). - Proof. - simple induction m. trivial. - intros a y a0 y0. simpl in |- *. elim (Ndiscr (Nxor a a0)). intro H. elim H. - intros p H0. rewrite H0. reflexivity. - intro H. rewrite H. rewrite (Nxor_eq _ _ H). reflexivity. - intros. simpl in |- *. elim (Ndiscr a). intro H1. elim H1. intros p H2. rewrite H2. case p. - intro p0. simpl in |- *. rewrite H0. reflexivity. - intro p0. simpl in |- *. rewrite H. reflexivity. - simpl in |- *. rewrite H0. reflexivity. - intro H1. rewrite H1. simpl in |- *. rewrite H. reflexivity. - Qed. - - Lemma MapCard_Put_behind_Put : - forall (m:Map A) (a:ad) (y:A), - MapCard A (MapPut_behind A m a y) = MapCard A (MapPut A m a y). - Proof. - intros. rewrite MapCard_Dom. rewrite MapCard_Dom. rewrite MapCard_Dom_Put_behind. - reflexivity. - Qed. - - Lemma MapCard_Put_behind_sum : - forall (m m':Map A) (a:ad) (y:A) (n n':nat), - m' = MapPut_behind A m a y -> - n = MapCard A m -> n' = MapCard A m' -> {n' = n} + {n' = S n}. - Proof. - intros. apply (MapCard_Put_sum m (MapPut A m a y) a y n n'); trivial. - rewrite <- MapCard_Put_behind_Put. rewrite <- H. assumption. - Qed. - - Lemma MapCard_makeM2 : - forall m m':Map A, MapCard A (makeM2 A m m') = MapCard A m + MapCard A m'. - Proof. - intros. rewrite (MapCard_ext _ _ (makeM2_M2 A m m')). reflexivity. - Qed. - - Lemma MapCard_Remove_sum : - forall (m m':Map A) (a:ad) (n n':nat), - m' = MapRemove A m a -> - n = MapCard A m -> n' = MapCard A m' -> {n = n'} + {n = S n'}. - Proof. - simple induction m. simpl in |- *. intros. rewrite H in H1. simpl in H1. left. rewrite H1. assumption. - simpl in |- *. intros. elim (sumbool_of_bool (Neqb a a1)). intro H2. rewrite H2 in H. - rewrite H in H1. simpl in H1. right. rewrite H1. assumption. - intro H2. rewrite H2 in H. rewrite H in H1. simpl in H1. left. rewrite H1. assumption. - intros. simpl in H1. simpl in H2. elim (sumbool_of_bool (Nbit0 a)). intro H4. - rewrite H4 in H1. rewrite H1 in H3. - rewrite (MapCard_makeM2 m0 (MapRemove A m1 (Ndiv2 a))) in H3. - elim - (H0 (MapRemove A m1 (Ndiv2 a)) (Ndiv2 a) ( - MapCard A m1) (MapCard A (MapRemove A m1 (Ndiv2 a))) - (refl_equal _) (refl_equal _) (refl_equal _)). - intro H5. rewrite H5 in H2. left. rewrite H3. exact H2. - intro H5. rewrite H5 in H2. - rewrite <- - (plus_Snm_nSm (MapCard A m0) (MapCard A (MapRemove A m1 (Ndiv2 a)))) - in H2. - right. rewrite H3. exact H2. - intro H4. rewrite H4 in H1. rewrite H1 in H3. - rewrite (MapCard_makeM2 (MapRemove A m0 (Ndiv2 a)) m1) in H3. - elim - (H (MapRemove A m0 (Ndiv2 a)) (Ndiv2 a) ( - MapCard A m0) (MapCard A (MapRemove A m0 (Ndiv2 a))) - (refl_equal _) (refl_equal _) (refl_equal _)). - intro H5. rewrite H5 in H2. left. rewrite H3. exact H2. - intro H5. rewrite H5 in H2. right. rewrite H3. exact H2. - Qed. - - Lemma MapCard_Remove_ub : - forall (m:Map A) (a:ad), MapCard A (MapRemove A m a) <= MapCard A m. - Proof. - intros. - elim - (MapCard_Remove_sum m (MapRemove A m a) a (MapCard A m) - (MapCard A (MapRemove A m a)) (refl_equal _) ( - refl_equal _) (refl_equal _)). - intro H. rewrite H. apply le_n. - intro H. rewrite H. apply le_n_Sn. - Qed. - - Lemma MapCard_Remove_lb : - forall (m:Map A) (a:ad), S (MapCard A (MapRemove A m a)) >= MapCard A m. - Proof. - unfold ge in |- *. intros. - elim - (MapCard_Remove_sum m (MapRemove A m a) a (MapCard A m) - (MapCard A (MapRemove A m a)) (refl_equal _) ( - refl_equal _) (refl_equal _)). - intro H. rewrite H. apply le_n_Sn. - intro H. rewrite H. apply le_n. - Qed. - - Lemma MapCard_Remove_1 : - forall (m:Map A) (a:ad), - MapCard A (MapRemove A m a) = MapCard A m -> MapGet A m a = None. - Proof. - simple induction m. trivial. - simpl in |- *. intros a y a0 H. elim (sumbool_of_bool (Neqb a a0)). intro H0. - rewrite H0 in H. discriminate H. - intro H0. rewrite H0. reflexivity. - intros. simpl in H1. elim (sumbool_of_bool (Nbit0 a)). intro H2. rewrite H2 in H1. - rewrite (MapCard_makeM2 m0 (MapRemove A m1 (Ndiv2 a))) in H1. - rewrite (MapGet_M2_bit_0_1 A a H2 m0 m1). apply H0. exact ((fun n m p:nat => plus_reg_l m p n) _ _ _ H1). - intro H2. rewrite H2 in H1. - rewrite (MapCard_makeM2 (MapRemove A m0 (Ndiv2 a)) m1) in H1. - rewrite (MapGet_M2_bit_0_0 A a H2 m0 m1). apply H. - rewrite - (plus_comm (MapCard A (MapRemove A m0 (Ndiv2 a))) (MapCard A m1)) - in H1. - rewrite (plus_comm (MapCard A m0) (MapCard A m1)) in H1. exact ((fun n m p:nat => plus_reg_l m p n) _ _ _ H1). - Qed. - - Lemma MapCard_Remove_2 : - forall (m:Map A) (a:ad), - S (MapCard A (MapRemove A m a)) = MapCard A m -> - {y : A | MapGet A m a = Some y}. - Proof. - simple induction m. intros. discriminate H. - intros a y a0 H. simpl in H. elim (sumbool_of_bool (Neqb a a0)). intro H0. - rewrite (Neqb_complete _ _ H0). split with y. exact (M1_semantics_1 A a0 y). - intro H0. rewrite H0 in H. discriminate H. - intros. simpl in H1. elim (sumbool_of_bool (Nbit0 a)). intro H2. rewrite H2 in H1. - rewrite (MapCard_makeM2 m0 (MapRemove A m1 (Ndiv2 a))) in H1. - rewrite (MapGet_M2_bit_0_1 A a H2 m0 m1). apply H0. - change - (S (MapCard A m0) + MapCard A (MapRemove A m1 (Ndiv2 a)) = - MapCard A m0 + MapCard A m1) in H1. - rewrite - (plus_Snm_nSm (MapCard A m0) (MapCard A (MapRemove A m1 (Ndiv2 a)))) - in H1. - exact ((fun n m p:nat => plus_reg_l m p n) _ _ _ H1). - intro H2. rewrite H2 in H1. rewrite (MapGet_M2_bit_0_0 A a H2 m0 m1). apply H. - rewrite (MapCard_makeM2 (MapRemove A m0 (Ndiv2 a)) m1) in H1. - change - (S (MapCard A (MapRemove A m0 (Ndiv2 a))) + MapCard A m1 = - MapCard A m0 + MapCard A m1) in H1. - rewrite - (plus_comm (S (MapCard A (MapRemove A m0 (Ndiv2 a)))) (MapCard A m1)) - in H1. - rewrite (plus_comm (MapCard A m0) (MapCard A m1)) in H1. exact ((fun n m p:nat => plus_reg_l m p n) _ _ _ H1). - Qed. - - Lemma MapCard_Remove_1_conv : - forall (m:Map A) (a:ad), - MapGet A m a = None -> MapCard A (MapRemove A m a) = MapCard A m. - Proof. - intros. - elim - (MapCard_Remove_sum m (MapRemove A m a) a (MapCard A m) - (MapCard A (MapRemove A m a)) (refl_equal _) ( - refl_equal _) (refl_equal _)). - intro H0. rewrite H0. reflexivity. - intro H0. elim (MapCard_Remove_2 m a (sym_eq H0)). intros y H1. rewrite H1 in H. - discriminate H. - Qed. - - Lemma MapCard_Remove_2_conv : - forall (m:Map A) (a:ad) (y:A), - MapGet A m a = Some y -> S (MapCard A (MapRemove A m a)) = MapCard A m. - Proof. - intros. - elim - (MapCard_Remove_sum m (MapRemove A m a) a (MapCard A m) - (MapCard A (MapRemove A m a)) (refl_equal _) ( - refl_equal _) (refl_equal _)). - intro H0. rewrite (MapCard_Remove_1 m a (sym_eq H0)) in H. discriminate H. - intro H0. rewrite H0. reflexivity. - Qed. - - Lemma MapMerge_Restr_Card : - forall m m':Map A, - MapCard A m + MapCard A m' = - MapCard A (MapMerge A m m') + MapCard A (MapDomRestrTo A A m m'). - Proof. - simple induction m. simpl in |- *. intro. apply plus_n_O. - simpl in |- *. intros a y m'. elim (option_sum A (MapGet A m' a)). intro H. elim H. intros y0 H0. - rewrite H0. rewrite MapCard_Put_behind_Put. rewrite (MapCard_Put_1_conv m' a y0 y H0). - simpl in |- *. rewrite <- plus_Snm_nSm. apply plus_n_O. - intro H. rewrite H. rewrite MapCard_Put_behind_Put. rewrite (MapCard_Put_2_conv m' a y H). - apply plus_n_O. - intros. - change - (MapCard A m0 + MapCard A m1 + MapCard A m' = - MapCard A (MapMerge A (M2 A m0 m1) m') + - MapCard A (MapDomRestrTo A A (M2 A m0 m1) m')) - in |- *. - elim m'. reflexivity. - intros a y. unfold MapMerge in |- *. unfold MapDomRestrTo in |- *. - elim (option_sum A (MapGet A (M2 A m0 m1) a)). intro H1. elim H1. intros y0 H2. rewrite H2. - rewrite (MapCard_Put_1_conv (M2 A m0 m1) a y0 y H2). reflexivity. - intro H1. rewrite H1. rewrite (MapCard_Put_2_conv (M2 A m0 m1) a y H1). simpl in |- *. - rewrite <- (plus_Snm_nSm (MapCard A m0 + MapCard A m1) 0). reflexivity. - intros. simpl in |- *. - rewrite - (plus_permute_2_in_4 (MapCard A m0) (MapCard A m1) ( - MapCard A m2) (MapCard A m3)). - rewrite (H m2). rewrite (H0 m3). - rewrite - (MapCard_makeM2 (MapDomRestrTo A A m0 m2) (MapDomRestrTo A A m1 m3)) - . - apply plus_permute_2_in_4. - Qed. - - Lemma MapMerge_disjoint_Card : - forall m m':Map A, - MapDisjoint A A m m' -> - MapCard A (MapMerge A m m') = MapCard A m + MapCard A m'. - Proof. - intros. rewrite (MapMerge_Restr_Card m m'). - rewrite (MapCard_ext _ _ (MapDisjoint_imp_2 _ _ _ _ H)). apply plus_n_O. - Qed. - - Lemma MapSplit_Card : - forall (m:Map A) (m':Map B), - MapCard A m = - MapCard A (MapDomRestrTo A B m m') + MapCard A (MapDomRestrBy A B m m'). - Proof. - intros. rewrite (MapCard_ext _ _ (MapDom_Split_1 A B m m')). apply MapMerge_disjoint_Card. - apply MapDisjoint_2_imp. unfold MapDisjoint_2 in |- *. apply MapDom_Split_3. - Qed. - - Lemma MapMerge_Card_ub : - forall m m':Map A, - MapCard A (MapMerge A m m') <= MapCard A m + MapCard A m'. - Proof. - intros. rewrite MapMerge_Restr_Card. apply le_plus_l. - Qed. - - Lemma MapDomRestrTo_Card_ub_l : - forall (m:Map A) (m':Map B), - MapCard A (MapDomRestrTo A B m m') <= MapCard A m. - Proof. - intros. rewrite (MapSplit_Card m m'). apply le_plus_l. - Qed. - - Lemma MapDomRestrBy_Card_ub_l : - forall (m:Map A) (m':Map B), - MapCard A (MapDomRestrBy A B m m') <= MapCard A m. - Proof. - intros. rewrite (MapSplit_Card m m'). apply le_plus_r. - Qed. - - Lemma MapMerge_Card_disjoint : - forall m m':Map A, - MapCard A (MapMerge A m m') = MapCard A m + MapCard A m' -> - MapDisjoint A A m m'. - Proof. - simple induction m. intros. apply Map_M0_disjoint. - simpl in |- *. intros. rewrite (MapCard_Put_behind_Put m' a a0) in H. unfold MapDisjoint, in_dom in |- *. - simpl in |- *. intros. elim (sumbool_of_bool (Neqb a a1)). intro H2. - rewrite (Neqb_complete _ _ H2) in H. rewrite (MapCard_Put_2 m' a1 a0 H) in H1. - discriminate H1. - intro H2. rewrite H2 in H0. discriminate H0. - simple induction m'. intros. apply Map_disjoint_M0. - intros a y H1. rewrite <- (MapCard_ext _ _ (MapPut_as_Merge A (M2 A m0 m1) a y)) in H1. - unfold MapCard at 3 in H1. rewrite <- (plus_Snm_nSm (MapCard A (M2 A m0 m1)) 0) in H1. - rewrite <- (plus_n_O (S (MapCard A (M2 A m0 m1)))) in H1. unfold MapDisjoint, in_dom in |- *. - unfold MapGet at 2 in |- *. intros. elim (sumbool_of_bool (Neqb a a0)). intro H4. - rewrite <- (Neqb_complete _ _ H4) in H2. rewrite (MapCard_Put_2 _ _ _ H1) in H2. - discriminate H2. - intro H4. rewrite H4 in H3. discriminate H3. - intros. unfold MapDisjoint in |- *. intros. elim (sumbool_of_bool (Nbit0 a)). intro H6. - unfold MapDisjoint in H0. apply H0 with (m' := m3) (a := Ndiv2 a). apply le_antisym. - apply MapMerge_Card_ub. - apply (fun p n m:nat => plus_le_reg_l n m p) with - (p := MapCard A m0 + MapCard A m2). - rewrite - (plus_permute_2_in_4 (MapCard A m0) (MapCard A m2) ( - MapCard A m1) (MapCard A m3)). - change - (MapCard A (M2 A (MapMerge A m0 m2) (MapMerge A m1 m3)) = - MapCard A m0 + MapCard A m1 + (MapCard A m2 + MapCard A m3)) - in H3. - rewrite <- H3. simpl in |- *. apply plus_le_compat_r. apply MapMerge_Card_ub. - elim (in_dom_some _ _ _ H4). intros y H7. rewrite (MapGet_M2_bit_0_1 _ a H6 m0 m1) in H7. - unfold in_dom in |- *. rewrite H7. reflexivity. - elim (in_dom_some _ _ _ H5). intros y H7. rewrite (MapGet_M2_bit_0_1 _ a H6 m2 m3) in H7. - unfold in_dom in |- *. rewrite H7. reflexivity. - intro H6. unfold MapDisjoint in H. apply H with (m' := m2) (a := Ndiv2 a). apply le_antisym. - apply MapMerge_Card_ub. - apply (fun p n m:nat => plus_le_reg_l n m p) with - (p := MapCard A m1 + MapCard A m3). - rewrite - (plus_comm (MapCard A m1 + MapCard A m3) (MapCard A m0 + MapCard A m2)) - . - rewrite - (plus_permute_2_in_4 (MapCard A m0) (MapCard A m2) ( - MapCard A m1) (MapCard A m3)). - rewrite - (plus_comm (MapCard A m1 + MapCard A m3) (MapCard A (MapMerge A m0 m2))) - . - change - (MapCard A (MapMerge A m0 m2) + MapCard A (MapMerge A m1 m3) = - MapCard A m0 + MapCard A m1 + (MapCard A m2 + MapCard A m3)) - in H3. - rewrite <- H3. apply plus_le_compat_l. apply MapMerge_Card_ub. - elim (in_dom_some _ _ _ H4). intros y H7. rewrite (MapGet_M2_bit_0_0 _ a H6 m0 m1) in H7. - unfold in_dom in |- *. rewrite H7. reflexivity. - elim (in_dom_some _ _ _ H5). intros y H7. rewrite (MapGet_M2_bit_0_0 _ a H6 m2 m3) in H7. - unfold in_dom in |- *. rewrite H7. reflexivity. - Qed. - - Lemma MapCard_is_Sn : - forall (m:Map A) (n:nat), - MapCard _ m = S n -> {a : ad | in_dom _ a m = true}. - Proof. - simple induction m. intros. discriminate H. - intros a y n H. split with a. unfold in_dom in |- *. rewrite (M1_semantics_1 _ a y). reflexivity. - intros. simpl in H1. elim (O_or_S (MapCard _ m0)). intro H2. elim H2. intros m2 H3. - elim (H _ (sym_eq H3)). intros a H4. split with (Ndouble a). unfold in_dom in |- *. - rewrite (MapGet_M2_bit_0_0 A (Ndouble a) (Ndouble_bit0 a) m0 m1). - rewrite (Ndouble_div2 a). elim (in_dom_some _ _ _ H4). intros y H5. rewrite H5. reflexivity. - intro H2. rewrite <- H2 in H1. simpl in H1. elim (H0 _ H1). intros a H3. - split with (Ndouble_plus_one a). unfold in_dom in |- *. - rewrite - (MapGet_M2_bit_0_1 A (Ndouble_plus_one a) (Ndouble_plus_one_bit0 a) - m0 m1). - rewrite (Ndouble_plus_one_div2 a). elim (in_dom_some _ _ _ H3). intros y H4. rewrite H4. - reflexivity. - Qed. - -End MapCard. - -Section MapCard2. - - Variables A B : Set. - - Lemma MapSubset_card_eq_1 : - forall (n:nat) (m:Map A) (m':Map B), - MapSubset _ _ m m' -> - MapCard _ m = n -> MapCard _ m' = n -> MapSubset _ _ m' m. - Proof. - simple induction n. intros. unfold MapSubset, in_dom in |- *. intro. rewrite (MapCard_is_O _ m H0 a). - rewrite (MapCard_is_O _ m' H1 a). intro H2. discriminate H2. - intros. elim (MapCard_is_Sn A m n0 H1). intros a H3. elim (in_dom_some _ _ _ H3). - intros y H4. elim (in_dom_some _ _ _ (H0 _ H3)). intros y' H6. - cut (eqmap _ (MapPut _ (MapRemove _ m a) a y) m). intro. - cut (eqmap _ (MapPut _ (MapRemove _ m' a) a y') m'). intro. - apply MapSubset_ext with - (m0 := MapPut _ (MapRemove _ m' a) a y') - (m2 := MapPut _ (MapRemove _ m a) a y). - assumption. - assumption. - apply MapSubset_Put_mono. apply H. apply MapSubset_Remove_mono. assumption. - rewrite <- (MapCard_Remove_2_conv _ m a y H4) in H1. inversion_clear H1. reflexivity. - rewrite <- (MapCard_Remove_2_conv _ m' a y' H6) in H2. inversion_clear H2. reflexivity. - unfold eqmap, eqm in |- *. intro. rewrite (MapPut_semantics _ (MapRemove B m' a) a y' a0). - elim (sumbool_of_bool (Neqb a a0)). intro H7. rewrite H7. rewrite <- (Neqb_complete _ _ H7). - apply sym_eq. assumption. - intro H7. rewrite H7. rewrite (MapRemove_semantics _ m' a a0). rewrite H7. reflexivity. - unfold eqmap, eqm in |- *. intro. rewrite (MapPut_semantics _ (MapRemove A m a) a y a0). - elim (sumbool_of_bool (Neqb a a0)). intro H7. rewrite H7. rewrite <- (Neqb_complete _ _ H7). - apply sym_eq. assumption. - intro H7. rewrite H7. rewrite (MapRemove_semantics A m a a0). rewrite H7. reflexivity. - Qed. - - Lemma MapDomRestrTo_Card_ub_r : - forall (m:Map A) (m':Map B), - MapCard A (MapDomRestrTo A B m m') <= MapCard B m'. - Proof. - simple induction m. intro. simpl in |- *. apply le_O_n. - intros a y m'. simpl in |- *. elim (option_sum B (MapGet B m' a)). intro H. elim H. intros y0 H0. - rewrite H0. elim (MapCard_is_not_O B m' a y0 H0). intros n H1. rewrite H1. simpl in |- *. - apply le_n_S. apply le_O_n. - intro H. rewrite H. simpl in |- *. apply le_O_n. - simple induction m'. simpl in |- *. apply le_O_n. - - intros a y. unfold MapDomRestrTo in |- *. case (MapGet A (M2 A m0 m1) a). simpl in |- *. - intro. simpl in |- *. apply le_n. - apply le_O_n. - intros. simpl in |- *. rewrite - (MapCard_makeM2 A (MapDomRestrTo A B m0 m2) (MapDomRestrTo A B m1 m3)) - . - apply plus_le_compat. apply H. - apply H0. - Qed. - -End MapCard2. - -Section MapCard3. - - Variables A B : Set. - - Lemma MapMerge_Card_lb_l : - forall m m':Map A, MapCard A (MapMerge A m m') >= MapCard A m. - Proof. - unfold ge in |- *. intros. apply ((fun p n m:nat => plus_le_reg_l n m p) (MapCard A m')). - rewrite (plus_comm (MapCard A m') (MapCard A m)). - rewrite (plus_comm (MapCard A m') (MapCard A (MapMerge A m m'))). - rewrite (MapMerge_Restr_Card A m m'). apply plus_le_compat_l. apply MapDomRestrTo_Card_ub_r. - Qed. - - Lemma MapMerge_Card_lb_r : - forall m m':Map A, MapCard A (MapMerge A m m') >= MapCard A m'. - Proof. - unfold ge in |- *. intros. apply ((fun p n m:nat => plus_le_reg_l n m p) (MapCard A m)). rewrite (MapMerge_Restr_Card A m m'). - rewrite - (plus_comm (MapCard A (MapMerge A m m')) - (MapCard A (MapDomRestrTo A A m m'))). - apply plus_le_compat_r. apply MapDomRestrTo_Card_ub_l. - Qed. - - Lemma MapDomRestrBy_Card_lb : - forall (m:Map A) (m':Map B), - MapCard B m' + MapCard A (MapDomRestrBy A B m m') >= MapCard A m. - Proof. - unfold ge in |- *. intros. rewrite (MapSplit_Card A B m m'). apply plus_le_compat_r. - apply MapDomRestrTo_Card_ub_r. - Qed. - - Lemma MapSubset_Card_le : - forall (m:Map A) (m':Map B), - MapSubset A B m m' -> MapCard A m <= MapCard B m'. - Proof. - intros. apply le_trans with (m := MapCard B m' + MapCard A (MapDomRestrBy A B m m')). - exact (MapDomRestrBy_Card_lb m m'). - rewrite (MapCard_ext _ _ _ (MapSubset_imp_2 _ _ _ _ H)). simpl in |- *. rewrite <- plus_n_O. - apply le_n. - Qed. - - Lemma MapSubset_card_eq : - forall (m:Map A) (m':Map B), - MapSubset _ _ m m' -> - MapCard _ m' <= MapCard _ m -> eqmap _ (MapDom _ m) (MapDom _ m'). - Proof. - intros. apply MapSubset_antisym. assumption. - cut (MapCard B m' = MapCard A m). intro. apply (MapSubset_card_eq_1 A B (MapCard A m)). - assumption. - reflexivity. - assumption. - apply le_antisym. assumption. - apply MapSubset_Card_le. assumption. - Qed. - -End MapCard3.
\ No newline at end of file diff --git a/theories/IntMap/Mapfold.v b/theories/IntMap/Mapfold.v deleted file mode 100644 index eb58cb64..00000000 --- a/theories/IntMap/Mapfold.v +++ /dev/null @@ -1,425 +0,0 @@ -(************************************************************************) -(* 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: Mapfold.v 8733 2006-04-25 22:52:18Z letouzey $ i*) - -Require Import Bool. -Require Import Sumbool. -Require Import NArith. -Require Import Ndigits. -Require Import Ndec. -Require Import Map. -Require Import Fset. -Require Import Mapaxioms. -Require Import Mapiter. -Require Import Lsort. -Require Import Mapsubset. -Require Import List. - -Section MapFoldResults. - - Variable A : Set. - - Variable M : Set. - Variable neutral : M. - Variable op : M -> M -> M. - - Variable nleft : forall a:M, op neutral a = a. - Variable nright : forall a:M, op a neutral = a. - Variable assoc : forall a b c:M, op (op a b) c = op a (op b c). - - Lemma MapFold_ext : - forall (f:ad -> A -> M) (m m':Map A), - eqmap A m m' -> MapFold _ _ neutral op f m = MapFold _ _ neutral op f m'. - Proof. - intros. rewrite (MapFold_as_fold A M neutral op assoc nleft nright f m). - rewrite (MapFold_as_fold A M neutral op assoc nleft nright f m'). - cut (alist_of_Map A m = alist_of_Map A m'). intro. rewrite H0. reflexivity. - apply alist_canonical. unfold eqmap in H. apply eqm_trans with (f' := MapGet A m). - apply eqm_sym. apply alist_of_Map_semantics. - apply eqm_trans with (f' := MapGet A m'). assumption. - apply alist_of_Map_semantics. - apply alist_of_Map_sorts2. - apply alist_of_Map_sorts2. - Qed. - - Lemma MapFold_ext_f_1 : - forall (m:Map A) (f g:ad -> A -> M) (pf:ad -> ad), - (forall (a:ad) (y:A), MapGet _ m a = Some y -> f (pf a) y = g (pf a) y) -> - MapFold1 _ _ neutral op f pf m = MapFold1 _ _ neutral op g pf m. - Proof. - simple induction m. trivial. - simpl in |- *. intros. apply H. rewrite (Neqb_correct a). reflexivity. - intros. simpl in |- *. rewrite (H f g (fun a0:ad => pf (Ndouble a0))). - rewrite (H0 f g (fun a0:ad => pf (Ndouble_plus_one a0))). reflexivity. - intros. apply H1. rewrite MapGet_M2_bit_0_1. rewrite Ndouble_plus_one_div2. assumption. - apply Ndouble_plus_one_bit0. - intros. apply H1. rewrite MapGet_M2_bit_0_0. rewrite Ndouble_div2. assumption. - apply Ndouble_bit0. - Qed. - - Lemma MapFold_ext_f : - forall (f g:ad -> A -> M) (m:Map A), - (forall (a:ad) (y:A), MapGet _ m a = Some y -> f a y = g a y) -> - MapFold _ _ neutral op f m = MapFold _ _ neutral op g m. - Proof. - intros. exact (MapFold_ext_f_1 m f g (fun a0:ad => a0) H). - Qed. - - Lemma MapFold1_as_Fold_1 : - forall (m:Map A) (f f':ad -> A -> M) (pf pf':ad -> ad), - (forall (a:ad) (y:A), f (pf a) y = f' (pf' a) y) -> - MapFold1 _ _ neutral op f pf m = MapFold1 _ _ neutral op f' pf' m. - Proof. - simple induction m. trivial. - intros. simpl in |- *. apply H. - intros. simpl in |- *. - rewrite - (H f f' (fun a0:ad => pf (Ndouble a0)) - (fun a0:ad => pf' (Ndouble a0))). - rewrite - (H0 f f' (fun a0:ad => pf (Ndouble_plus_one a0)) - (fun a0:ad => pf' (Ndouble_plus_one a0))). - reflexivity. - intros. apply H1. - intros. apply H1. - Qed. - - Lemma MapFold1_as_Fold : - forall (f:ad -> A -> M) (pf:ad -> ad) (m:Map A), - MapFold1 _ _ neutral op f pf m = - MapFold _ _ neutral op (fun (a:ad) (y:A) => f (pf a) y) m. - Proof. - intros. unfold MapFold in |- *. apply MapFold1_as_Fold_1. trivial. - Qed. - - Lemma MapFold1_ext : - forall (f:ad -> A -> M) (m m':Map A), - eqmap A m m' -> - forall pf:ad -> ad, - MapFold1 _ _ neutral op f pf m = MapFold1 _ _ neutral op f pf m'. - Proof. - intros. rewrite MapFold1_as_Fold. rewrite MapFold1_as_Fold. apply MapFold_ext. assumption. - Qed. - - Variable comm : forall a b:M, op a b = op b a. - - Lemma MapFold_Put_disjoint_1 : - forall (p:positive) (f:ad -> A -> M) (pf:ad -> ad) - (a1 a2:ad) (y1 y2:A), - Nxor a1 a2 = Npos p -> - MapFold1 A M neutral op f pf (MapPut1 A a1 y1 a2 y2 p) = - op (f (pf a1) y1) (f (pf a2) y2). - Proof. - simple induction p. intros. simpl in |- *. elim (sumbool_of_bool (Nbit0 a1)). intro H1. rewrite H1. - simpl in |- *. rewrite Ndiv2_double_plus_one. rewrite Ndiv2_double. apply comm. - change (Nbit0 a2 = negb true) in |- *. rewrite <- H1. rewrite (Nneg_bit0_2 _ _ _ H0). - rewrite negb_elim. reflexivity. - assumption. - intro H1. rewrite H1. simpl in |- *. rewrite Ndiv2_double. rewrite Ndiv2_double_plus_one. - reflexivity. - change (Nbit0 a2 = negb false) in |- *. rewrite <- H1. rewrite (Nneg_bit0_2 _ _ _ H0). - rewrite negb_elim. reflexivity. - assumption. - simpl in |- *. intros. elim (sumbool_of_bool (Nbit0 a1)). intro H1. rewrite H1. simpl in |- *. - rewrite nleft. - rewrite - (H f (fun a0:ad => pf (Ndouble_plus_one a0)) ( - Ndiv2 a1) (Ndiv2 a2) y1 y2). - rewrite Ndiv2_double_plus_one. rewrite Ndiv2_double_plus_one. reflexivity. - unfold Nodd. - rewrite <- (Nsame_bit0 _ _ _ H0). assumption. - assumption. - rewrite <- Nxor_div2. rewrite H0. reflexivity. - intro H1. rewrite H1. simpl in |- *. rewrite nright. - rewrite - (H f (fun a0:ad => pf (Ndouble a0)) (Ndiv2 a1) (Ndiv2 a2) y1 y2) - . - rewrite Ndiv2_double. rewrite Ndiv2_double. reflexivity. - unfold Neven. - rewrite <- (Nsame_bit0 _ _ _ H0). assumption. - assumption. - rewrite <- Nxor_div2. rewrite H0. reflexivity. - intros. simpl in |- *. elim (sumbool_of_bool (Nbit0 a1)). intro H0. rewrite H0. simpl in |- *. - rewrite Ndiv2_double. rewrite Ndiv2_double_plus_one. apply comm. - assumption. - change (Nbit0 a2 = negb true) in |- *. rewrite <- H0. rewrite (Nneg_bit0_1 _ _ H). - rewrite negb_elim. reflexivity. - intro H0. rewrite H0. simpl in |- *. rewrite Ndiv2_double. rewrite Ndiv2_double_plus_one. - reflexivity. - change (Nbit0 a2 = negb false) in |- *. rewrite <- H0. rewrite (Nneg_bit0_1 _ _ H). - rewrite negb_elim. reflexivity. - assumption. - Qed. - - Lemma MapFold_Put_disjoint_2 : - forall (f:ad -> A -> M) (m:Map A) (a:ad) (y:A) (pf:ad -> ad), - MapGet A m a = None -> - MapFold1 A M neutral op f pf (MapPut A m a y) = - op (f (pf a) y) (MapFold1 A M neutral op f pf m). - Proof. - simple induction m. intros. simpl in |- *. rewrite (nright (f (pf a) y)). reflexivity. - intros a1 y1 a2 y2 pf H. simpl in |- *. elim (Ndiscr (Nxor a1 a2)). intro H0. elim H0. - intros p H1. rewrite H1. rewrite comm. exact (MapFold_Put_disjoint_1 p f pf a1 a2 y1 y2 H1). - intro H0. rewrite (Neqb_complete _ _ (Nxor_eq_true _ _ H0)) in H. - rewrite (M1_semantics_1 A a2 y1) in H. discriminate H. - intros. elim (sumbool_of_bool (Nbit0 a)). intro H2. - cut (MapPut A (M2 A m0 m1) a y = M2 A m0 (MapPut A m1 (Ndiv2 a) y)). intro. - rewrite H3. simpl in |- *. rewrite (H0 (Ndiv2 a) y (fun a0:ad => pf (Ndouble_plus_one a0))). - rewrite Ndiv2_double_plus_one. rewrite <- assoc. - rewrite - (comm (MapFold1 A M neutral op f (fun a0:ad => pf (Ndouble a0)) m0) - (f (pf a) y)). - rewrite assoc. reflexivity. - assumption. - rewrite (MapGet_M2_bit_0_1 A a H2 m0 m1) in H1. assumption. - simpl in |- *. elim (Ndiscr a). intro H3. elim H3. intro p. elim p. intros p0 H4 H5. rewrite H5. - reflexivity. - intros p0 H4 H5. rewrite H5 in H2. discriminate H2. - intro H4. rewrite H4. reflexivity. - intro H3. rewrite H3 in H2. discriminate H2. - intro H2. cut (MapPut A (M2 A m0 m1) a y = M2 A (MapPut A m0 (Ndiv2 a) y) m1). - intro. rewrite H3. simpl in |- *. rewrite (H (Ndiv2 a) y (fun a0:ad => pf (Ndouble a0))). - rewrite Ndiv2_double. rewrite <- assoc. reflexivity. - assumption. - rewrite (MapGet_M2_bit_0_0 A a H2 m0 m1) in H1. assumption. - simpl in |- *. elim (Ndiscr a). intro H3. elim H3. intro p. elim p. intros p0 H4 H5. rewrite H5 in H2. - discriminate H2. - intros p0 H4 H5. rewrite H5. reflexivity. - intro H4. rewrite H4 in H2. discriminate H2. - intro H3. rewrite H3. reflexivity. - Qed. - - Lemma MapFold_Put_disjoint : - forall (f:ad -> A -> M) (m:Map A) (a:ad) (y:A), - MapGet A m a = None -> - MapFold A M neutral op f (MapPut A m a y) = - op (f a y) (MapFold A M neutral op f m). - Proof. - intros. exact (MapFold_Put_disjoint_2 f m a y (fun a0:ad => a0) H). - Qed. - - Lemma MapFold_Put_behind_disjoint_2 : - forall (f:ad -> A -> M) (m:Map A) (a:ad) (y:A) (pf:ad -> ad), - MapGet A m a = None -> - MapFold1 A M neutral op f pf (MapPut_behind A m a y) = - op (f (pf a) y) (MapFold1 A M neutral op f pf m). - Proof. - intros. cut (eqmap A (MapPut_behind A m a y) (MapPut A m a y)). intro. - rewrite (MapFold1_ext f _ _ H0 pf). apply MapFold_Put_disjoint_2. assumption. - apply eqmap_trans with (m' := MapMerge A (M1 A a y) m). apply MapPut_behind_as_Merge. - apply eqmap_trans with (m' := MapMerge A m (M1 A a y)). - apply eqmap_trans with (m' := MapDelta A (M1 A a y) m). apply eqmap_sym. apply MapDelta_disjoint. - unfold MapDisjoint in |- *. unfold in_dom in |- *. simpl in |- *. intros. elim (sumbool_of_bool (Neqb a a0)). - intro H2. rewrite (Neqb_complete _ _ H2) in H. rewrite H in H1. discriminate H1. - intro H2. rewrite H2 in H0. discriminate H0. - apply eqmap_trans with (m' := MapDelta A m (M1 A a y)). apply MapDelta_sym. - apply MapDelta_disjoint. unfold MapDisjoint in |- *. unfold in_dom in |- *. simpl in |- *. intros. - elim (sumbool_of_bool (Neqb a a0)). intro H2. rewrite (Neqb_complete _ _ H2) in H. - rewrite H in H0. discriminate H0. - intro H2. rewrite H2 in H1. discriminate H1. - apply eqmap_sym. apply MapPut_as_Merge. - Qed. - - Lemma MapFold_Put_behind_disjoint : - forall (f:ad -> A -> M) (m:Map A) (a:ad) (y:A), - MapGet A m a = None -> - MapFold A M neutral op f (MapPut_behind A m a y) = - op (f a y) (MapFold A M neutral op f m). - Proof. - intros. exact (MapFold_Put_behind_disjoint_2 f m a y (fun a0:ad => a0) H). - Qed. - - Lemma MapFold_Merge_disjoint_1 : - forall (f:ad -> A -> M) (m1 m2:Map A) (pf:ad -> ad), - MapDisjoint A A m1 m2 -> - MapFold1 A M neutral op f pf (MapMerge A m1 m2) = - op (MapFold1 A M neutral op f pf m1) (MapFold1 A M neutral op f pf m2). - Proof. - simple induction m1. simpl in |- *. intros. rewrite nleft. reflexivity. - intros. unfold MapMerge in |- *. apply (MapFold_Put_behind_disjoint_2 f m2 a a0 pf). - apply in_dom_none. exact (MapDisjoint_M1_l _ _ m2 a a0 H). - simple induction m2. intros. simpl in |- *. rewrite nright. reflexivity. - intros. unfold MapMerge in |- *. rewrite (MapFold_Put_disjoint_2 f (M2 A m m0) a a0 pf). apply comm. - apply in_dom_none. exact (MapDisjoint_M1_r _ _ (M2 A m m0) a a0 H1). - intros. simpl in |- *. rewrite (H m3 (fun a0:ad => pf (Ndouble a0))). - rewrite (H0 m4 (fun a0:ad => pf (Ndouble_plus_one a0))). - cut (forall a b c d:M, op (op a b) (op c d) = op (op a c) (op b d)). intro. apply H4. - intros. rewrite assoc. rewrite <- (assoc b c d). rewrite (comm b c). rewrite (assoc c b d). - rewrite assoc. reflexivity. - exact (MapDisjoint_M2_r _ _ _ _ _ _ H3). - exact (MapDisjoint_M2_l _ _ _ _ _ _ H3). - Qed. - - Lemma MapFold_Merge_disjoint : - forall (f:ad -> A -> M) (m1 m2:Map A), - MapDisjoint A A m1 m2 -> - MapFold A M neutral op f (MapMerge A m1 m2) = - op (MapFold A M neutral op f m1) (MapFold A M neutral op f m2). - Proof. - intros. exact (MapFold_Merge_disjoint_1 f m1 m2 (fun a0:ad => a0) H). - Qed. - -End MapFoldResults. - -Section MapFoldDistr. - - Variable A : Set. - - Variable M : Set. - Variable neutral : M. - Variable op : M -> M -> M. - - Variable M' : Set. - Variable neutral' : M'. - Variable op' : M' -> M' -> M'. - - Variable N : Set. - - Variable times : M -> N -> M'. - - Variable absorb : forall c:N, times neutral c = neutral'. - Variable - distr : - forall (a b:M) (c:N), times (op a b) c = op' (times a c) (times b c). - - Lemma MapFold_distr_r_1 : - forall (f:ad -> A -> M) (m:Map A) (c:N) (pf:ad -> ad), - times (MapFold1 A M neutral op f pf m) c = - MapFold1 A M' neutral' op' (fun (a:ad) (y:A) => times (f a y) c) pf m. - Proof. - simple induction m. intros. exact (absorb c). - trivial. - intros. simpl in |- *. rewrite distr. rewrite H. rewrite H0. reflexivity. - Qed. - - Lemma MapFold_distr_r : - forall (f:ad -> A -> M) (m:Map A) (c:N), - times (MapFold A M neutral op f m) c = - MapFold A M' neutral' op' (fun (a:ad) (y:A) => times (f a y) c) m. - Proof. - intros. exact (MapFold_distr_r_1 f m c (fun a:ad => a)). - Qed. - -End MapFoldDistr. - -Section MapFoldDistrL. - - Variable A : Set. - - Variable M : Set. - Variable neutral : M. - Variable op : M -> M -> M. - - Variable M' : Set. - Variable neutral' : M'. - Variable op' : M' -> M' -> M'. - - Variable N : Set. - - Variable times : N -> M -> M'. - - Variable absorb : forall c:N, times c neutral = neutral'. - Variable - distr : - forall (a b:M) (c:N), times c (op a b) = op' (times c a) (times c b). - - Lemma MapFold_distr_l : - forall (f:ad -> A -> M) (m:Map A) (c:N), - times c (MapFold A M neutral op f m) = - MapFold A M' neutral' op' (fun (a:ad) (y:A) => times c (f a y)) m. - Proof. - intros. apply MapFold_distr_r with (times := fun (a:M) (b:N) => times b a); - assumption. - Qed. - -End MapFoldDistrL. - -Section MapFoldExists. - - Variable A : Set. - - Lemma MapFold_orb_1 : - forall (f:ad -> A -> bool) (m:Map A) (pf:ad -> ad), - MapFold1 A bool false orb f pf m = - match MapSweep1 A f pf m with - | Some _ => true - | _ => false - end. - Proof. - simple induction m. trivial. - intros a y pf. simpl in |- *. unfold MapSweep2 in |- *. case (f (pf a) y); reflexivity. - intros. simpl in |- *. rewrite (H (fun a0:ad => pf (Ndouble a0))). - rewrite (H0 (fun a0:ad => pf (Ndouble_plus_one a0))). - case (MapSweep1 A f (fun a0:ad => pf (Ndouble a0)) m0); reflexivity. - Qed. - - Lemma MapFold_orb : - forall (f:ad -> A -> bool) (m:Map A), - MapFold A bool false orb f m = - match MapSweep A f m with - | Some _ => true - | _ => false - end. - Proof. - intros. exact (MapFold_orb_1 f m (fun a:ad => a)). - Qed. - -End MapFoldExists. - -Section DMergeDef. - - Variable A : Set. - - Definition DMerge := - MapFold (Map A) (Map A) (M0 A) (MapMerge A) (fun (_:ad) (m:Map A) => m). - - Lemma in_dom_DMerge_1 : - forall (m:Map (Map A)) (a:ad), - in_dom A a (DMerge m) = - match MapSweep _ (fun (_:ad) (m0:Map A) => in_dom A a m0) m with - | Some _ => true - | _ => false - end. - Proof. - unfold DMerge in |- *. intros. - rewrite - (MapFold_distr_l (Map A) (Map A) (M0 A) (MapMerge A) bool false orb ad - (in_dom A) (fun c:ad => refl_equal _) (in_dom_merge A)) - . - apply MapFold_orb. - Qed. - - Lemma in_dom_DMerge_2 : - forall (m:Map (Map A)) (a:ad), - in_dom A a (DMerge m) = true -> - {b : ad & - {m0 : Map A | MapGet _ m b = Some m0 /\ in_dom A a m0 = true}}. - Proof. - intros m a. rewrite in_dom_DMerge_1. - elim - (option_sum _ - (MapSweep (Map A) (fun (_:ad) (m0:Map A) => in_dom A a m0) m)). - intro H. elim H. intro r. elim r. intros b m0 H0. intro. split with b. split with m0. - split. exact (MapSweep_semantics_2 _ _ _ _ _ H0). - exact (MapSweep_semantics_1 _ _ _ _ _ H0). - intro H. rewrite H. intro. discriminate H0. - Qed. - - Lemma in_dom_DMerge_3 : - forall (m:Map (Map A)) (a b:ad) (m0:Map A), - MapGet _ m a = Some m0 -> - in_dom A b m0 = true -> in_dom A b (DMerge m) = true. - Proof. - intros m a b m0 H H0. rewrite in_dom_DMerge_1. - elim - (MapSweep_semantics_4 _ (fun (_:ad) (m'0:Map A) => in_dom A b m'0) _ _ _ - H H0). - intros a' H1. elim H1. intros m'0 H2. rewrite H2. reflexivity. - Qed. - -End DMergeDef.
\ No newline at end of file diff --git a/theories/IntMap/Mapiter.v b/theories/IntMap/Mapiter.v deleted file mode 100644 index a8ba7e39..00000000 --- a/theories/IntMap/Mapiter.v +++ /dev/null @@ -1,618 +0,0 @@ -(************************************************************************) -(* 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: Mapiter.v 8733 2006-04-25 22:52:18Z letouzey $ i*) - -Require Import Bool. -Require Import Sumbool. -Require Import NArith. -Require Import Ndigits. -Require Import Ndec. -Require Import Map. -Require Import Mapaxioms. -Require Import Fset. -Require Import List. - -Section MapIter. - - Variable A : Set. - - Section MapSweepDef. - - Variable f : ad -> A -> bool. - - Definition MapSweep2 (a0:ad) (y:A) := - if f a0 y then Some (a0, y) else None. - - Fixpoint MapSweep1 (pf:ad -> ad) (m:Map A) {struct m} : - option (ad * A) := - match m with - | M0 => None - | M1 a y => MapSweep2 (pf a) y - | M2 m m' => - match MapSweep1 (fun a:ad => pf (Ndouble a)) m with - | Some r => Some r - | None => MapSweep1 (fun a:ad => pf (Ndouble_plus_one a)) m' - end - end. - - Definition MapSweep (m:Map A) := MapSweep1 (fun a:ad => a) m. - - Lemma MapSweep_semantics_1_1 : - forall (m:Map A) (pf:ad -> ad) (a:ad) (y:A), - MapSweep1 pf m = Some (a, y) -> f a y = true. - Proof. - simple induction m. intros. discriminate H. - simpl in |- *. intros a y pf a0 y0. elim (sumbool_of_bool (f (pf a) y)). intro H. unfold MapSweep2 in |- *. - rewrite H. intro H0. inversion H0. rewrite <- H3. assumption. - intro H. unfold MapSweep2 in |- *. rewrite H. intro H0. discriminate H0. - simpl in |- *. intros. elim (option_sum (ad * A) (MapSweep1 (fun a0:ad => pf (Ndouble a0)) m0)). - intro H2. elim H2. intros r H3. rewrite H3 in H1. inversion H1. rewrite H5 in H3. - exact (H (fun a0:ad => pf (Ndouble a0)) a y H3). - intro H2. rewrite H2 in H1. exact (H0 (fun a0:ad => pf (Ndouble_plus_one a0)) a y H1). - Qed. - - Lemma MapSweep_semantics_1 : - forall (m:Map A) (a:ad) (y:A), MapSweep m = Some (a, y) -> f a y = true. - Proof. - intros. exact (MapSweep_semantics_1_1 m (fun a:ad => a) a y H). - Qed. - - Lemma MapSweep_semantics_2_1 : - forall (m:Map A) (pf:ad -> ad) (a:ad) (y:A), - MapSweep1 pf m = Some (a, y) -> {a' : ad | a = pf a'}. - Proof. - simple induction m. intros. discriminate H. - simpl in |- *. unfold MapSweep2 in |- *. intros a y pf a0 y0. case (f (pf a) y). intros. split with a. - inversion H. reflexivity. - intro. discriminate H. - intros m0 H m1 H0 pf a y. simpl in |- *. - elim - (option_sum (ad * A) (MapSweep1 (fun a0:ad => pf (Ndouble a0)) m0)). intro H1. elim H1. - intros r H2. rewrite H2. intro H3. inversion H3. rewrite H5 in H2. - elim (H (fun a0:ad => pf (Ndouble a0)) a y H2). intros a0 H6. split with (Ndouble a0). - assumption. - intro H1. rewrite H1. intro H2. elim (H0 (fun a0:ad => pf (Ndouble_plus_one a0)) a y H2). - intros a0 H3. split with (Ndouble_plus_one a0). assumption. - Qed. - - Lemma MapSweep_semantics_2_2 : - forall (m:Map A) (pf fp:ad -> ad), - (forall a0:ad, fp (pf a0) = a0) -> - forall (a:ad) (y:A), - MapSweep1 pf m = Some (a, y) -> MapGet A m (fp a) = Some y. - Proof. - simple induction m. intros. discriminate H0. - simpl in |- *. intros a y pf fp H a0 y0. unfold MapSweep2 in |- *. elim (sumbool_of_bool (f (pf a) y)). - intro H0. rewrite H0. intro H1. inversion H1. rewrite (H a). rewrite (Neqb_correct a). - reflexivity. - intro H0. rewrite H0. intro H1. discriminate H1. - intros. rewrite (MapGet_M2_bit_0_if A m0 m1 (fp a)). elim (sumbool_of_bool (Nbit0 (fp a))). - intro H3. rewrite H3. elim (option_sum (ad * A) (MapSweep1 (fun a0:ad => pf (Ndouble a0)) m0)). - intro H4. simpl in H2. apply - (H0 (fun a0:ad => pf (Ndouble_plus_one a0)) - (fun a0:ad => Ndiv2 (fp a0))). - intro. rewrite H1. apply Ndouble_plus_one_div2. - elim - (option_sum (ad * A) (MapSweep1 (fun a0:ad => pf (Ndouble a0)) m0)). intro H5. elim H5. - intros r H6. rewrite H6 in H2. inversion H2. rewrite H8 in H6. - elim (MapSweep_semantics_2_1 m0 (fun a0:ad => pf (Ndouble a0)) a y H6). intros a0 H9. - rewrite H9 in H3. rewrite (H1 (Ndouble a0)) in H3. rewrite (Ndouble_bit0 a0) in H3. - discriminate H3. - intro H5. rewrite H5 in H2. assumption. - intro H4. simpl in H2. rewrite H4 in H2. - apply - (H0 (fun a0:ad => pf (Ndouble_plus_one a0)) - (fun a0:ad => Ndiv2 (fp a0))). intro. - rewrite H1. apply Ndouble_plus_one_div2. - assumption. - intro H3. rewrite H3. simpl in H2. - elim - (option_sum (ad * A) (MapSweep1 (fun a0:ad => pf (Ndouble a0)) m0)). intro H4. elim H4. - intros r H5. rewrite H5 in H2. inversion H2. rewrite H7 in H5. - apply - (H (fun a0:ad => pf (Ndouble a0)) (fun a0:ad => Ndiv2 (fp a0))). intro. rewrite H1. - apply Ndouble_div2. - assumption. - intro H4. rewrite H4 in H2. - elim - (MapSweep_semantics_2_1 m1 (fun a0:ad => pf (Ndouble_plus_one a0)) a y - H2). - intros a0 H5. rewrite H5 in H3. rewrite (H1 (Ndouble_plus_one a0)) in H3. - rewrite (Ndouble_plus_one_bit0 a0) in H3. discriminate H3. - Qed. - - Lemma MapSweep_semantics_2 : - forall (m:Map A) (a:ad) (y:A), - MapSweep m = Some (a, y) -> MapGet A m a = Some y. - Proof. - intros. - exact - (MapSweep_semantics_2_2 m (fun a0:ad => a0) (fun a0:ad => a0) - (fun a0:ad => refl_equal a0) a y H). - Qed. - - Lemma MapSweep_semantics_3_1 : - forall (m:Map A) (pf:ad -> ad), - MapSweep1 pf m = None -> - forall (a:ad) (y:A), MapGet A m a = Some y -> f (pf a) y = false. - Proof. - simple induction m. intros. discriminate H0. - simpl in |- *. unfold MapSweep2 in |- *. intros a y pf. elim (sumbool_of_bool (f (pf a) y)). intro H. - rewrite H. intro. discriminate H0. - intro H. rewrite H. intros H0 a0 y0. elim (sumbool_of_bool (Neqb a a0)). intro H1. rewrite H1. - intro H2. inversion H2. rewrite <- H4. rewrite <- (Neqb_complete _ _ H1). assumption. - intro H1. rewrite H1. intro. discriminate H2. - intros. simpl in H1. elim (option_sum (ad * A) (MapSweep1 (fun a:ad => pf (Ndouble a)) m0)). - intro H3. elim H3. intros r H4. rewrite H4 in H1. discriminate H1. - intro H3. rewrite H3 in H1. elim (sumbool_of_bool (Nbit0 a)). intro H4. - rewrite (MapGet_M2_bit_0_1 A a H4 m0 m1) in H2. rewrite <- (Ndiv2_double_plus_one a H4). - exact (H0 (fun a:ad => pf (Ndouble_plus_one a)) H1 (Ndiv2 a) y H2). - intro H4. rewrite (MapGet_M2_bit_0_0 A a H4 m0 m1) in H2. rewrite <- (Ndiv2_double a H4). - exact (H (fun a:ad => pf (Ndouble a)) H3 (Ndiv2 a) y H2). - Qed. - - Lemma MapSweep_semantics_3 : - forall m:Map A, - MapSweep m = None -> - forall (a:ad) (y:A), MapGet A m a = Some y -> f a y = false. - Proof. - intros. - exact (MapSweep_semantics_3_1 m (fun a0:ad => a0) H a y H0). - Qed. - - Lemma MapSweep_semantics_4_1 : - forall (m:Map A) (pf:ad -> ad) (a:ad) (y:A), - MapGet A m a = Some y -> - f (pf a) y = true -> - {a' : ad & {y' : A | MapSweep1 pf m = Some (a', y')}}. - Proof. - simple induction m. intros. discriminate H. - intros. elim (sumbool_of_bool (Neqb a a1)). intro H1. split with (pf a1). split with y. - rewrite (Neqb_complete _ _ H1). unfold MapSweep1, MapSweep2 in |- *. - rewrite (Neqb_complete _ _ H1) in H. rewrite (M1_semantics_1 _ a1 a0) in H. - inversion H. rewrite H0. reflexivity. - - intro H1. rewrite (M1_semantics_2 _ a a1 a0 H1) in H. discriminate H. - - intros. elim (sumbool_of_bool (Nbit0 a)). intro H3. - rewrite (MapGet_M2_bit_0_1 _ _ H3 m0 m1) in H1. - rewrite <- (Ndiv2_double_plus_one a H3) in H2. - elim (H0 (fun a0:ad => pf (Ndouble_plus_one a0)) (Ndiv2 a) y H1 H2). intros a'' H4. elim H4. - intros y'' H5. simpl in |- *. elim (option_sum _ (MapSweep1 (fun a:ad => pf (Ndouble a)) m0)). - intro H6. elim H6. intro r. elim r. intros a''' y''' H7. rewrite H7. split with a'''. - split with y'''. reflexivity. - intro H6. rewrite H6. split with a''. split with y''. assumption. - intro H3. rewrite (MapGet_M2_bit_0_0 _ _ H3 m0 m1) in H1. - rewrite <- (Ndiv2_double a H3) in H2. - elim (H (fun a0:ad => pf (Ndouble a0)) (Ndiv2 a) y H1 H2). intros a'' H4. elim H4. - intros y'' H5. split with a''. split with y''. simpl in |- *. rewrite H5. reflexivity. - Qed. - - Lemma MapSweep_semantics_4 : - forall (m:Map A) (a:ad) (y:A), - MapGet A m a = Some y -> - f a y = true -> {a' : ad & {y' : A | MapSweep m = Some (a', y')}}. - Proof. - intros. exact (MapSweep_semantics_4_1 m (fun a0:ad => a0) a y H H0). - Qed. - - End MapSweepDef. - - Variable B : Set. - - Fixpoint MapCollect1 (f:ad -> A -> Map B) (pf:ad -> ad) - (m:Map A) {struct m} : Map B := - match m with - | M0 => M0 B - | M1 a y => f (pf a) y - | M2 m1 m2 => - MapMerge B (MapCollect1 f (fun a0:ad => pf (Ndouble a0)) m1) - (MapCollect1 f (fun a0:ad => pf (Ndouble_plus_one a0)) m2) - end. - - Definition MapCollect (f:ad -> A -> Map B) (m:Map A) := - MapCollect1 f (fun a:ad => a) m. - - Section MapFoldDef. - - Variable M : Set. - Variable neutral : M. - Variable op : M -> M -> M. - - Fixpoint MapFold1 (f:ad -> A -> M) (pf:ad -> ad) - (m:Map A) {struct m} : M := - match m with - | M0 => neutral - | M1 a y => f (pf a) y - | M2 m1 m2 => - op (MapFold1 f (fun a0:ad => pf (Ndouble a0)) m1) - (MapFold1 f (fun a0:ad => pf (Ndouble_plus_one a0)) m2) - end. - - Definition MapFold (f:ad -> A -> M) (m:Map A) := - MapFold1 f (fun a:ad => a) m. - - Lemma MapFold_empty : forall f:ad -> A -> M, MapFold f (M0 A) = neutral. - Proof. - trivial. - Qed. - - Lemma MapFold_M1 : - forall (f:ad -> A -> M) (a:ad) (y:A), MapFold f (M1 A a y) = f a y. - Proof. - trivial. - Qed. - - Variable State : Set. - Variable f : State -> ad -> A -> State * M. - - Fixpoint MapFold1_state (state:State) (pf:ad -> ad) - (m:Map A) {struct m} : State * M := - match m with - | M0 => (state, neutral) - | M1 a y => f state (pf a) y - | M2 m1 m2 => - match MapFold1_state state (fun a0:ad => pf (Ndouble a0)) m1 with - | (state1, x1) => - match - MapFold1_state state1 - (fun a0:ad => pf (Ndouble_plus_one a0)) m2 - with - | (state2, x2) => (state2, op x1 x2) - end - end - end. - - Definition MapFold_state (state:State) := - MapFold1_state state (fun a:ad => a). - - Lemma pair_sp : forall (B C:Set) (x:B * C), x = (fst x, snd x). - Proof. - simple induction x. trivial. - Qed. - - Lemma MapFold_state_stateless_1 : - forall (m:Map A) (g:ad -> A -> M) (pf:ad -> ad), - (forall (state:State) (a:ad) (y:A), snd (f state a y) = g a y) -> - forall state:State, snd (MapFold1_state state pf m) = MapFold1 g pf m. - Proof. - simple induction m. trivial. - intros. simpl in |- *. apply H. - intros. simpl in |- *. rewrite - (pair_sp _ _ (MapFold1_state state (fun a0:ad => pf (Ndouble a0)) m0)) - . - rewrite (H g (fun a0:ad => pf (Ndouble a0)) H1 state). - rewrite - (pair_sp _ _ - (MapFold1_state - (fst (MapFold1_state state (fun a0:ad => pf (Ndouble a0)) m0)) - (fun a0:ad => pf (Ndouble_plus_one a0)) m1)) - . - simpl in |- *. - rewrite - (H0 g (fun a0:ad => pf (Ndouble_plus_one a0)) H1 - (fst (MapFold1_state state (fun a0:ad => pf (Ndouble a0)) m0))) - . - reflexivity. - Qed. - - Lemma MapFold_state_stateless : - forall g:ad -> A -> M, - (forall (state:State) (a:ad) (y:A), snd (f state a y) = g a y) -> - forall (state:State) (m:Map A), - snd (MapFold_state state m) = MapFold g m. - Proof. - intros. exact (MapFold_state_stateless_1 m g (fun a0:ad => a0) H state). - Qed. - - End MapFoldDef. - - Lemma MapCollect_as_Fold : - forall (f:ad -> A -> Map B) (m:Map A), - MapCollect f m = MapFold (Map B) (M0 B) (MapMerge B) f m. - Proof. - simple induction m; trivial. - Qed. - - Definition alist := list (ad * A). - Definition anil := nil (A:=(ad * A)). - Definition acons := cons (A:=(ad * A)). - Definition aapp := app (A:=(ad * A)). - - Definition alist_of_Map := - MapFold alist anil aapp (fun (a:ad) (y:A) => acons (a, y) anil). - - Fixpoint alist_semantics (l:alist) : ad -> option A := - match l with - | nil => fun _:ad => None - | (a, y) :: l' => - fun a0:ad => if Neqb a a0 then Some y else alist_semantics l' a0 - end. - - Lemma alist_semantics_app : - forall (l l':alist) (a:ad), - alist_semantics (aapp l l') a = - match alist_semantics l a with - | None => alist_semantics l' a - | Some y => Some y - end. - Proof. - unfold aapp in |- *. simple induction l. trivial. - intros. elim a. intros a1 y1. simpl in |- *. case (Neqb a1 a0). reflexivity. - apply H. - Qed. - - Lemma alist_of_Map_semantics_1_1 : - forall (m:Map A) (pf:ad -> ad) (a:ad) (y:A), - alist_semantics - (MapFold1 alist anil aapp (fun (a0:ad) (y:A) => acons (a0, y) anil) pf - m) a = Some y -> {a' : ad | a = pf a'}. - Proof. - simple induction m. simpl in |- *. intros. discriminate H. - simpl in |- *. intros a y pf a0 y0. elim (sumbool_of_bool (Neqb (pf a) a0)). intro H. rewrite H. - intro H0. split with a. rewrite (Neqb_complete _ _ H). reflexivity. - intro H. rewrite H. intro H0. discriminate H0. - intros. change - (alist_semantics - (aapp - (MapFold1 alist anil aapp (fun (a0:ad) (y:A) => acons (a0, y) anil) - (fun a0:ad => pf (Ndouble a0)) m0) - (MapFold1 alist anil aapp (fun (a0:ad) (y:A) => acons (a0, y) anil) - (fun a0:ad => pf (Ndouble_plus_one a0)) m1)) a = - Some y) in H1. - rewrite - (alist_semantics_app - (MapFold1 alist anil aapp (fun (a0:ad) (y0:A) => acons (a0, y0) anil) - (fun a0:ad => pf (Ndouble a0)) m0) - (MapFold1 alist anil aapp (fun (a0:ad) (y0:A) => acons (a0, y0) anil) - (fun a0:ad => pf (Ndouble_plus_one a0)) m1) a) - in H1. - elim - (option_sum A - (alist_semantics - (MapFold1 alist anil aapp - (fun (a0:ad) (y0:A) => acons (a0, y0) anil) - (fun a0:ad => pf (Ndouble a0)) m0) a)). - intro H2. elim H2. intros y0 H3. elim (H (fun a0:ad => pf (Ndouble a0)) a y0 H3). intros a0 H4. - split with (Ndouble a0). assumption. - intro H2. rewrite H2 in H1. elim (H0 (fun a0:ad => pf (Ndouble_plus_one a0)) a y H1). - intros a0 H3. split with (Ndouble_plus_one a0). assumption. - Qed. - - Definition ad_inj (pf:ad -> ad) := - forall a0 a1:ad, pf a0 = pf a1 -> a0 = a1. - - Lemma ad_comp_double_inj : - forall pf:ad -> ad, ad_inj pf -> ad_inj (fun a0:ad => pf (Ndouble a0)). - Proof. - unfold ad_inj in |- *. intros. apply Ndouble_inj. exact (H _ _ H0). - Qed. - - Lemma ad_comp_double_plus_un_inj : - forall pf:ad -> ad, - ad_inj pf -> ad_inj (fun a0:ad => pf (Ndouble_plus_one a0)). - Proof. - unfold ad_inj in |- *. intros. apply Ndouble_plus_one_inj. exact (H _ _ H0). - Qed. - - Lemma alist_of_Map_semantics_1 : - forall (m:Map A) (pf:ad -> ad), - ad_inj pf -> - forall a:ad, - MapGet A m a = - alist_semantics - (MapFold1 alist anil aapp (fun (a0:ad) (y:A) => acons (a0, y) anil) - pf m) (pf a). - Proof. - simple induction m. trivial. - simpl in |- *. intros. elim (sumbool_of_bool (Neqb a a1)). intro H0. rewrite H0. - rewrite (Neqb_complete _ _ H0). rewrite (Neqb_correct (pf a1)). reflexivity. - intro H0. rewrite H0. elim (sumbool_of_bool (Neqb (pf a) (pf a1))). intro H1. - rewrite (H a a1 (Neqb_complete _ _ H1)) in H0. rewrite (Neqb_correct a1) in H0. - discriminate H0. - intro H1. rewrite H1. reflexivity. - intros. change - (MapGet A (M2 A m0 m1) a = - alist_semantics - (aapp - (MapFold1 alist anil aapp (fun (a0:ad) (y:A) => acons (a0, y) anil) - (fun a0:ad => pf (Ndouble a0)) m0) - (MapFold1 alist anil aapp (fun (a0:ad) (y:A) => acons (a0, y) anil) - (fun a0:ad => pf (Ndouble_plus_one a0)) m1)) ( - pf a)) in |- *. - rewrite alist_semantics_app. rewrite (MapGet_M2_bit_0_if A m0 m1 a). - elim (Ndouble_or_double_plus_un a). intro H2. elim H2. intros a0 H3. rewrite H3. - rewrite (Ndouble_bit0 a0). - rewrite <- - (H (fun a1:ad => pf (Ndouble a1)) (ad_comp_double_inj pf H1) a0) - . - rewrite Ndouble_div2. case (MapGet A m0 a0); trivial. - elim - (option_sum A - (alist_semantics - (MapFold1 alist anil aapp - (fun (a1:ad) (y:A) => acons (a1, y) anil) - (fun a1:ad => pf (Ndouble_plus_one a1)) m1) - (pf (Ndouble a0)))). - intro H4. elim H4. intros y H5. - elim - (alist_of_Map_semantics_1_1 m1 (fun a1:ad => pf (Ndouble_plus_one a1)) - (pf (Ndouble a0)) y H5). - intros a1 H6. cut (Nbit0 (Ndouble a0) = Nbit0 (Ndouble_plus_one a1)). - intro. rewrite (Ndouble_bit0 a0) in H7. rewrite (Ndouble_plus_one_bit0 a1) in H7. - discriminate H7. - rewrite (H1 (Ndouble a0) (Ndouble_plus_one a1) H6). reflexivity. - intro H4. rewrite H4. reflexivity. - intro H2. elim H2. intros a0 H3. rewrite H3. rewrite (Ndouble_plus_one_bit0 a0). - rewrite <- - (H0 (fun a1:ad => pf (Ndouble_plus_one a1)) - (ad_comp_double_plus_un_inj pf H1) a0). - rewrite Ndouble_plus_one_div2. - elim - (option_sum A - (alist_semantics - (MapFold1 alist anil aapp - (fun (a1:ad) (y:A) => acons (a1, y) anil) - (fun a1:ad => pf (Ndouble a1)) m0) - (pf (Ndouble_plus_one a0)))). - intro H4. elim H4. intros y H5. - elim - (alist_of_Map_semantics_1_1 m0 (fun a1:ad => pf (Ndouble a1)) - (pf (Ndouble_plus_one a0)) y H5). - intros a1 H6. cut (Nbit0 (Ndouble_plus_one a0) = Nbit0 (Ndouble a1)). - intro H7. rewrite (Ndouble_plus_one_bit0 a0) in H7. rewrite (Ndouble_bit0 a1) in H7. - discriminate H7. - rewrite (H1 (Ndouble_plus_one a0) (Ndouble a1) H6). reflexivity. - intro H4. rewrite H4. reflexivity. - Qed. - - Lemma alist_of_Map_semantics : - forall m:Map A, eqm A (MapGet A m) (alist_semantics (alist_of_Map m)). - Proof. - unfold eqm in |- *. intros. exact - (alist_of_Map_semantics_1 m (fun a0:ad => a0) - (fun (a0 a1:ad) (p:a0 = a1) => p) a). - Qed. - - Fixpoint Map_of_alist (l:alist) : Map A := - match l with - | nil => M0 A - | (a, y) :: l' => MapPut A (Map_of_alist l') a y - end. - - Lemma Map_of_alist_semantics : - forall l:alist, eqm A (alist_semantics l) (MapGet A (Map_of_alist l)). - Proof. - unfold eqm in |- *. simple induction l. trivial. - intros r l0 H a. elim r. intros a0 y0. simpl in |- *. elim (sumbool_of_bool (Neqb a0 a)). - intro H0. rewrite H0. rewrite (Neqb_complete _ _ H0). - rewrite (MapPut_semantics A (Map_of_alist l0) a y0 a). rewrite (Neqb_correct a). - reflexivity. - intro H0. rewrite H0. rewrite (MapPut_semantics A (Map_of_alist l0) a0 y0 a). - rewrite H0. apply H. - Qed. - - Lemma Map_of_alist_of_Map : - forall m:Map A, eqmap A (Map_of_alist (alist_of_Map m)) m. - Proof. - unfold eqmap in |- *. intro. apply eqm_trans with (f' := alist_semantics (alist_of_Map m)). - apply eqm_sym. apply Map_of_alist_semantics. - apply eqm_sym. apply alist_of_Map_semantics. - Qed. - - Lemma alist_of_Map_of_alist : - forall l:alist, - eqm A (alist_semantics (alist_of_Map (Map_of_alist l))) - (alist_semantics l). - Proof. - intro. apply eqm_trans with (f' := MapGet A (Map_of_alist l)). - apply eqm_sym. apply alist_of_Map_semantics. - apply eqm_sym. apply Map_of_alist_semantics. - Qed. - - Lemma fold_right_aapp : - forall (M:Set) (neutral:M) (op:M -> M -> M), - (forall a b c:M, op (op a b) c = op a (op b c)) -> - (forall a:M, op neutral a = a) -> - forall (f:ad -> A -> M) (l l':alist), - fold_right (fun (r:ad * A) (m:M) => let (a, y) := r in op (f a y) m) - neutral (aapp l l') = - op - (fold_right - (fun (r:ad * A) (m:M) => let (a, y) := r in op (f a y) m) neutral - l) - (fold_right - (fun (r:ad * A) (m:M) => let (a, y) := r in op (f a y) m) neutral - l'). - Proof. - simple induction l. simpl in |- *. intro. rewrite H0. reflexivity. - intros r l0 H1 l'. elim r. intros a y. simpl in |- *. rewrite H. rewrite (H1 l'). reflexivity. - Qed. - - Lemma MapFold_as_fold_1 : - forall (M:Set) (neutral:M) (op:M -> M -> M), - (forall a b c:M, op (op a b) c = op a (op b c)) -> - (forall a:M, op neutral a = a) -> - (forall a:M, op a neutral = a) -> - forall (f:ad -> A -> M) (m:Map A) (pf:ad -> ad), - MapFold1 M neutral op f pf m = - fold_right (fun (r:ad * A) (m:M) => let (a, y) := r in op (f a y) m) - neutral - (MapFold1 alist anil aapp (fun (a:ad) (y:A) => acons (a, y) anil) pf - m). - Proof. - simple induction m. trivial. - intros. simpl in |- *. rewrite H1. reflexivity. - intros. simpl in |- *. rewrite (fold_right_aapp M neutral op H H0 f). - rewrite (H2 (fun a0:ad => pf (Ndouble a0))). rewrite (H3 (fun a0:ad => pf (Ndouble_plus_one a0))). - reflexivity. - Qed. - - Lemma MapFold_as_fold : - forall (M:Set) (neutral:M) (op:M -> M -> M), - (forall a b c:M, op (op a b) c = op a (op b c)) -> - (forall a:M, op neutral a = a) -> - (forall a:M, op a neutral = a) -> - forall (f:ad -> A -> M) (m:Map A), - MapFold M neutral op f m = - fold_right (fun (r:ad * A) (m:M) => let (a, y) := r in op (f a y) m) - neutral (alist_of_Map m). - Proof. - intros. exact (MapFold_as_fold_1 M neutral op H H0 H1 f m (fun a0:ad => a0)). - Qed. - - Lemma alist_MapMerge_semantics : - forall m m':Map A, - eqm A (alist_semantics (aapp (alist_of_Map m') (alist_of_Map m))) - (alist_semantics (alist_of_Map (MapMerge A m m'))). - Proof. - unfold eqm in |- *. intros. rewrite alist_semantics_app. rewrite <- (alist_of_Map_semantics m a). - rewrite <- (alist_of_Map_semantics m' a). - rewrite <- (alist_of_Map_semantics (MapMerge A m m') a). - rewrite (MapMerge_semantics A m m' a). reflexivity. - Qed. - - Lemma alist_MapMerge_semantics_disjoint : - forall m m':Map A, - eqmap A (MapDomRestrTo A A m m') (M0 A) -> - eqm A (alist_semantics (aapp (alist_of_Map m) (alist_of_Map m'))) - (alist_semantics (alist_of_Map (MapMerge A m m'))). - Proof. - unfold eqm in |- *. intros. rewrite alist_semantics_app. rewrite <- (alist_of_Map_semantics m a). - rewrite <- (alist_of_Map_semantics m' a). - rewrite <- (alist_of_Map_semantics (MapMerge A m m') a). rewrite (MapMerge_semantics A m m' a). - elim (option_sum _ (MapGet A m a)). intro H0. elim H0. intros y H1. rewrite H1. - elim (option_sum _ (MapGet A m' a)). intro H2. elim H2. intros y' H3. - cut (MapGet A (MapDomRestrTo A A m m') a = None). - rewrite (MapDomRestrTo_semantics A A m m' a). rewrite H3. rewrite H1. intro. discriminate H4. - exact (H a). - intro H2. rewrite H2. reflexivity. - intro H0. rewrite H0. case (MapGet A m' a); trivial. - Qed. - - Lemma alist_semantics_disjoint_comm : - forall l l':alist, - eqmap A (MapDomRestrTo A A (Map_of_alist l) (Map_of_alist l')) (M0 A) -> - eqm A (alist_semantics (aapp l l')) (alist_semantics (aapp l' l)). - Proof. - unfold eqm in |- *. intros. rewrite (alist_semantics_app l l' a). rewrite (alist_semantics_app l' l a). - rewrite <- (alist_of_Map_of_alist l a). rewrite <- (alist_of_Map_of_alist l' a). - rewrite <- - (alist_semantics_app (alist_of_Map (Map_of_alist l)) - (alist_of_Map (Map_of_alist l')) a). - rewrite <- - (alist_semantics_app (alist_of_Map (Map_of_alist l')) - (alist_of_Map (Map_of_alist l)) a). - rewrite (alist_MapMerge_semantics (Map_of_alist l) (Map_of_alist l') a). - rewrite - (alist_MapMerge_semantics_disjoint (Map_of_alist l) ( - Map_of_alist l') H a). - reflexivity. - Qed. - -End MapIter. diff --git a/theories/IntMap/Maplists.v b/theories/IntMap/Maplists.v deleted file mode 100644 index 56a3c160..00000000 --- a/theories/IntMap/Maplists.v +++ /dev/null @@ -1,438 +0,0 @@ -(************************************************************************) -(* 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: Maplists.v 8733 2006-04-25 22:52:18Z letouzey $ i*) - -Require Import BinNat. -Require Import Ndigits. -Require Import Ndec. -Require Import Map. -Require Import Fset. -Require Import Mapaxioms. -Require Import Mapsubset. -Require Import Mapcard. -Require Import Mapcanon. -Require Import Mapc. -Require Import Bool. -Require Import Sumbool. -Require Import List. -Require Import Arith. -Require Import Mapiter. -Require Import Mapfold. - -Section MapLists. - - Fixpoint ad_in_list (a:ad) (l:list ad) {struct l} : bool := - match l with - | nil => false - | a' :: l' => orb (Neqb a a') (ad_in_list a l') - end. - - Fixpoint ad_list_stutters (l:list ad) : bool := - match l with - | nil => false - | a :: l' => orb (ad_in_list a l') (ad_list_stutters l') - end. - - Lemma ad_in_list_forms_circuit : - forall (x:ad) (l:list ad), - ad_in_list x l = true -> - {l1 : list ad & {l2 : list ad | l = l1 ++ x :: l2}}. - Proof. - simple induction l. intro. discriminate H. - intros. elim (sumbool_of_bool (Neqb x a)). intro H1. simpl in H0. split with (nil (A:=ad)). - split with l0. rewrite (Neqb_complete _ _ H1). reflexivity. - intro H2. simpl in H0. rewrite H2 in H0. simpl in H0. elim (H H0). intros l'1 H3. - split with (a :: l'1). elim H3. intros l2 H4. split with l2. rewrite H4. reflexivity. - Qed. - - Lemma ad_list_stutters_has_circuit : - forall l:list ad, - ad_list_stutters l = true -> - {x : ad & - {l0 : list ad & - {l1 : list ad & {l2 : list ad | l = l0 ++ x :: l1 ++ x :: l2}}}}. - Proof. - simple induction l. intro. discriminate H. - intros. simpl in H0. elim (orb_true_elim _ _ H0). intro H1. split with a. - split with (nil (A:=ad)). simpl in |- *. elim (ad_in_list_forms_circuit a l0 H1). intros l1 H2. - split with l1. elim H2. intros l2 H3. split with l2. rewrite H3. reflexivity. - intro H1. elim (H H1). intros x H2. split with x. elim H2. intros l1 H3. - split with (a :: l1). elim H3. intros l2 H4. split with l2. elim H4. intros l3 H5. - split with l3. rewrite H5. reflexivity. - Qed. - - Fixpoint Elems (l:list ad) : FSet := - match l with - | nil => M0 unit - | a :: l' => MapPut _ (Elems l') a tt - end. - - Lemma Elems_canon : forall l:list ad, mapcanon _ (Elems l). - Proof. - simple induction l. exact (M0_canon unit). - intros. simpl in |- *. apply MapPut_canon. assumption. - Qed. - - Lemma Elems_app : - forall l l':list ad, Elems (l ++ l') = FSetUnion (Elems l) (Elems l'). - Proof. - simple induction l. trivial. - intros. simpl in |- *. rewrite (MapPut_as_Merge_c unit (Elems l0)). - rewrite (MapPut_as_Merge_c unit (Elems (l0 ++ l'))). - change - (FSetUnion (Elems (l0 ++ l')) (M1 unit a tt) = - FSetUnion (FSetUnion (Elems l0) (M1 unit a tt)) (Elems l')) - in |- *. - rewrite FSetUnion_comm_c. rewrite (FSetUnion_comm_c (Elems l0) (M1 unit a tt)). - rewrite FSetUnion_assoc_c. rewrite (H l'). reflexivity. - apply M1_canon. - apply Elems_canon. - apply Elems_canon. - apply Elems_canon. - apply M1_canon. - apply Elems_canon. - apply M1_canon. - apply Elems_canon. - apply Elems_canon. - Qed. - - Lemma Elems_rev : forall l:list ad, Elems (rev l) = Elems l. - Proof. - simple induction l. trivial. - intros. simpl in |- *. rewrite Elems_app. simpl in |- *. rewrite (MapPut_as_Merge_c unit (Elems l0)). - rewrite H. reflexivity. - apply Elems_canon. - Qed. - - Lemma ad_in_elems_in_list : - forall (l:list ad) (a:ad), in_FSet a (Elems l) = ad_in_list a l. - Proof. - simple induction l. trivial. - simpl in |- *. unfold in_FSet in |- *. intros. rewrite (in_dom_put _ (Elems l0) a tt a0). - rewrite (H a0). reflexivity. - Qed. - - Lemma ad_list_not_stutters_card : - forall l:list ad, - ad_list_stutters l = false -> length l = MapCard _ (Elems l). - Proof. - simple induction l. trivial. - simpl in |- *. intros. rewrite MapCard_Put_2_conv. rewrite H. reflexivity. - elim (orb_false_elim _ _ H0). trivial. - elim (sumbool_of_bool (in_FSet a (Elems l0))). rewrite ad_in_elems_in_list. - intro H1. rewrite H1 in H0. discriminate H0. - exact (in_dom_none unit (Elems l0) a). - Qed. - - Lemma ad_list_card : forall l:list ad, MapCard _ (Elems l) <= length l. - Proof. - simple induction l. trivial. - intros. simpl in |- *. apply le_trans with (m := S (MapCard _ (Elems l0))). apply MapCard_Put_ub. - apply le_n_S. assumption. - Qed. - - Lemma ad_list_stutters_card : - forall l:list ad, - ad_list_stutters l = true -> MapCard _ (Elems l) < length l. - Proof. - simple induction l. intro. discriminate H. - intros. simpl in |- *. simpl in H0. elim (orb_true_elim _ _ H0). intro H1. - rewrite <- (ad_in_elems_in_list l0 a) in H1. elim (in_dom_some _ _ _ H1). intros y H2. - rewrite (MapCard_Put_1_conv _ _ _ _ tt H2). apply le_lt_trans with (m := length l0). - apply ad_list_card. - apply lt_n_Sn. - intro H1. apply le_lt_trans with (m := S (MapCard _ (Elems l0))). apply MapCard_Put_ub. - apply lt_n_S. apply H. assumption. - Qed. - - Lemma ad_list_not_stutters_card_conv : - forall l:list ad, - length l = MapCard _ (Elems l) -> ad_list_stutters l = false. - Proof. - intros. elim (sumbool_of_bool (ad_list_stutters l)). intro H0. - cut (MapCard _ (Elems l) < length l). intro. rewrite H in H1. elim (lt_irrefl _ H1). - exact (ad_list_stutters_card _ H0). - trivial. - Qed. - - Lemma ad_list_stutters_card_conv : - forall l:list ad, - MapCard _ (Elems l) < length l -> ad_list_stutters l = true. - Proof. - intros. elim (sumbool_of_bool (ad_list_stutters l)). trivial. - intro H0. rewrite (ad_list_not_stutters_card _ H0) in H. elim (lt_irrefl _ H). - Qed. - - Lemma ad_in_list_l : - forall (l l':list ad) (a:ad), - ad_in_list a l = true -> ad_in_list a (l ++ l') = true. - Proof. - simple induction l. intros. discriminate H. - intros. simpl in |- *. simpl in H0. elim (orb_true_elim _ _ H0). intro H1. rewrite H1. reflexivity. - intro H1. rewrite (H l' a0 H1). apply orb_b_true. - Qed. - - Lemma ad_list_stutters_app_l : - forall l l':list ad, - ad_list_stutters l = true -> ad_list_stutters (l ++ l') = true. - Proof. - simple induction l. intros. discriminate H. - intros. simpl in |- *. simpl in H0. elim (orb_true_elim _ _ H0). intro H1. - rewrite (ad_in_list_l l0 l' a H1). reflexivity. - intro H1. rewrite (H l' H1). apply orb_b_true. - Qed. - - Lemma ad_in_list_r : - forall (l l':list ad) (a:ad), - ad_in_list a l' = true -> ad_in_list a (l ++ l') = true. - Proof. - simple induction l. trivial. - intros. simpl in |- *. rewrite (H l' a0 H0). apply orb_b_true. - Qed. - - Lemma ad_list_stutters_app_r : - forall l l':list ad, - ad_list_stutters l' = true -> ad_list_stutters (l ++ l') = true. - Proof. - simple induction l. trivial. - intros. simpl in |- *. rewrite (H l' H0). apply orb_b_true. - Qed. - - Lemma ad_list_stutters_app_conv_l : - forall l l':list ad, - ad_list_stutters (l ++ l') = false -> ad_list_stutters l = false. - Proof. - intros. elim (sumbool_of_bool (ad_list_stutters l)). intro H0. - rewrite (ad_list_stutters_app_l l l' H0) in H. discriminate H. - trivial. - Qed. - - Lemma ad_list_stutters_app_conv_r : - forall l l':list ad, - ad_list_stutters (l ++ l') = false -> ad_list_stutters l' = false. - Proof. - intros. elim (sumbool_of_bool (ad_list_stutters l')). intro H0. - rewrite (ad_list_stutters_app_r l l' H0) in H. discriminate H. - trivial. - Qed. - - Lemma ad_in_list_app_1 : - forall (l l':list ad) (x:ad), ad_in_list x (l ++ x :: l') = true. - Proof. - simple induction l. simpl in |- *. intros. rewrite (Neqb_correct x). reflexivity. - intros. simpl in |- *. rewrite (H l' x). apply orb_b_true. - Qed. - - Lemma ad_in_list_app : - forall (l l':list ad) (x:ad), - ad_in_list x (l ++ l') = orb (ad_in_list x l) (ad_in_list x l'). - Proof. - simple induction l. trivial. - intros. simpl in |- *. rewrite <- orb_assoc. rewrite (H l' x). reflexivity. - Qed. - - Lemma ad_in_list_rev : - forall (l:list ad) (x:ad), ad_in_list x (rev l) = ad_in_list x l. - Proof. - simple induction l. trivial. - intros. simpl in |- *. rewrite ad_in_list_app. rewrite (H x). simpl in |- *. rewrite orb_b_false. - apply orb_comm. - Qed. - - Lemma ad_list_has_circuit_stutters : - forall (l0 l1 l2:list ad) (x:ad), - ad_list_stutters (l0 ++ x :: l1 ++ x :: l2) = true. - Proof. - simple induction l0. simpl in |- *. intros. rewrite (ad_in_list_app_1 l1 l2 x). reflexivity. - intros. simpl in |- *. rewrite (H l1 l2 x). apply orb_b_true. - Qed. - - Lemma ad_list_stutters_prev_l : - forall (l l':list ad) (x:ad), - ad_in_list x l = true -> ad_list_stutters (l ++ x :: l') = true. - Proof. - intros. elim (ad_in_list_forms_circuit _ _ H). intros l0 H0. elim H0. intros l1 H1. - rewrite H1. rewrite app_ass. simpl in |- *. apply ad_list_has_circuit_stutters. - Qed. - - Lemma ad_list_stutters_prev_conv_l : - forall (l l':list ad) (x:ad), - ad_list_stutters (l ++ x :: l') = false -> ad_in_list x l = false. - Proof. - intros. elim (sumbool_of_bool (ad_in_list x l)). intro H0. - rewrite (ad_list_stutters_prev_l l l' x H0) in H. discriminate H. - trivial. - Qed. - - Lemma ad_list_stutters_prev_r : - forall (l l':list ad) (x:ad), - ad_in_list x l' = true -> ad_list_stutters (l ++ x :: l') = true. - Proof. - intros. elim (ad_in_list_forms_circuit _ _ H). intros l0 H0. elim H0. intros l1 H1. - rewrite H1. apply ad_list_has_circuit_stutters. - Qed. - - Lemma ad_list_stutters_prev_conv_r : - forall (l l':list ad) (x:ad), - ad_list_stutters (l ++ x :: l') = false -> ad_in_list x l' = false. - Proof. - intros. elim (sumbool_of_bool (ad_in_list x l')). intro H0. - rewrite (ad_list_stutters_prev_r l l' x H0) in H. discriminate H. - trivial. - Qed. - - Lemma ad_list_Elems : - forall l l':list ad, - MapCard _ (Elems l) = MapCard _ (Elems l') -> - length l = length l' -> ad_list_stutters l = ad_list_stutters l'. - Proof. - intros. elim (sumbool_of_bool (ad_list_stutters l)). intro H1. rewrite H1. apply sym_eq. - apply ad_list_stutters_card_conv. rewrite <- H. rewrite <- H0. apply ad_list_stutters_card. - assumption. - intro H1. rewrite H1. apply sym_eq. apply ad_list_not_stutters_card_conv. rewrite <- H. - rewrite <- H0. apply ad_list_not_stutters_card. assumption. - Qed. - - Lemma ad_list_app_length : - forall l l':list ad, length (l ++ l') = length l + length l'. - Proof. - simple induction l. trivial. - intros. simpl in |- *. rewrite (H l'). reflexivity. - Qed. - - Lemma ad_list_stutters_permute : - forall l l':list ad, - ad_list_stutters (l ++ l') = ad_list_stutters (l' ++ l). - Proof. - intros. apply ad_list_Elems. rewrite Elems_app. rewrite Elems_app. - rewrite (FSetUnion_comm_c _ _ (Elems_canon l) (Elems_canon l')). reflexivity. - rewrite ad_list_app_length. rewrite ad_list_app_length. apply plus_comm. - Qed. - - Lemma ad_list_rev_length : forall l:list ad, length (rev l) = length l. - Proof. - simple induction l. trivial. - intros. simpl in |- *. rewrite ad_list_app_length. simpl in |- *. rewrite H. rewrite <- plus_Snm_nSm. - rewrite <- plus_n_O. reflexivity. - Qed. - - Lemma ad_list_stutters_rev : - forall l:list ad, ad_list_stutters (rev l) = ad_list_stutters l. - Proof. - intros. apply ad_list_Elems. rewrite Elems_rev. reflexivity. - apply ad_list_rev_length. - Qed. - - Lemma ad_list_app_rev : - forall (l l':list ad) (x:ad), rev l ++ x :: l' = rev (x :: l) ++ l'. - Proof. - simple induction l. trivial. - intros. simpl in |- *. rewrite (app_ass (rev l0) (a :: nil) (x :: l')). simpl in |- *. - rewrite (H (x :: l') a). simpl in |- *. - rewrite (app_ass (rev l0) (a :: nil) (x :: nil)). simpl in |- *. - rewrite app_ass. simpl in |- *. rewrite app_ass. reflexivity. - Qed. - - Section ListOfDomDef. - - Variable A : Set. - - Definition ad_list_of_dom := - MapFold A (list ad) nil (app (A:=ad)) (fun (a:ad) (_:A) => a :: nil). - - Lemma ad_in_list_of_dom_in_dom : - forall (m:Map A) (a:ad), ad_in_list a (ad_list_of_dom m) = in_dom A a m. - Proof. - unfold ad_list_of_dom in |- *. intros. - rewrite - (MapFold_distr_l A (list ad) nil (app (A:=ad)) bool false orb ad - (fun (a:ad) (l:list ad) => ad_in_list a l) ( - fun c:ad => refl_equal _) ad_in_list_app - (fun (a0:ad) (_:A) => a0 :: nil) m a). - simpl in |- *. rewrite (MapFold_orb A (fun (a0:ad) (_:A) => orb (Neqb a a0) false) m). - elim - (option_sum _ - (MapSweep A (fun (a0:ad) (_:A) => orb (Neqb a a0) false) m)). intro H. elim H. - intro r. elim r. intros a0 y H0. rewrite H0. unfold in_dom in |- *. - elim (orb_prop _ _ (MapSweep_semantics_1 _ _ _ _ _ H0)). intro H1. - rewrite (Neqb_complete _ _ H1). rewrite (MapSweep_semantics_2 A _ _ _ _ H0). reflexivity. - intro H1. discriminate H1. - intro H. rewrite H. elim (sumbool_of_bool (in_dom A a m)). intro H0. - elim (in_dom_some A m a H0). intros y H1. - elim (orb_false_elim _ _ (MapSweep_semantics_3 _ _ _ H _ _ H1)). intro H2. - rewrite (Neqb_correct a) in H2. discriminate H2. - exact (sym_eq (y:=_)). - Qed. - - Lemma Elems_of_list_of_dom : - forall m:Map A, eqmap unit (Elems (ad_list_of_dom m)) (MapDom A m). - Proof. - unfold eqmap, eqm in |- *. intros. elim (sumbool_of_bool (in_FSet a (Elems (ad_list_of_dom m)))). - intro H. elim (in_dom_some _ _ _ H). intro t. elim t. intro H0. - rewrite (ad_in_elems_in_list (ad_list_of_dom m) a) in H. - rewrite (ad_in_list_of_dom_in_dom m a) in H. rewrite (MapDom_Dom A m a) in H. - elim (in_dom_some _ _ _ H). intro t'. elim t'. intro H1. rewrite H1. assumption. - intro H. rewrite (in_dom_none _ _ _ H). - rewrite (ad_in_elems_in_list (ad_list_of_dom m) a) in H. - rewrite (ad_in_list_of_dom_in_dom m a) in H. rewrite (MapDom_Dom A m a) in H. - rewrite (in_dom_none _ _ _ H). reflexivity. - Qed. - - Lemma Elems_of_list_of_dom_c : - forall m:Map A, mapcanon A m -> Elems (ad_list_of_dom m) = MapDom A m. - Proof. - intros. apply (mapcanon_unique unit). apply Elems_canon. - apply MapDom_canon. assumption. - apply Elems_of_list_of_dom. - Qed. - - Lemma ad_list_of_dom_card_1 : - forall (m:Map A) (pf:ad -> ad), - length - (MapFold1 A (list ad) nil (app (A:=ad)) (fun (a:ad) (_:A) => a :: nil) - pf m) = MapCard A m. - Proof. - simple induction m; try trivial. simpl in |- *. intros. rewrite ad_list_app_length. - rewrite (H (fun a0:ad => pf (Ndouble a0))). rewrite (H0 (fun a0:ad => pf (Ndouble_plus_one a0))). - reflexivity. - Qed. - - Lemma ad_list_of_dom_card : - forall m:Map A, length (ad_list_of_dom m) = MapCard A m. - Proof. - exact (fun m:Map A => ad_list_of_dom_card_1 m (fun a:ad => a)). - Qed. - - Lemma ad_list_of_dom_not_stutters : - forall m:Map A, ad_list_stutters (ad_list_of_dom m) = false. - Proof. - intro. apply ad_list_not_stutters_card_conv. rewrite ad_list_of_dom_card. apply sym_eq. - rewrite (MapCard_Dom A m). apply MapCard_ext. exact (Elems_of_list_of_dom m). - Qed. - - End ListOfDomDef. - - Lemma ad_list_of_dom_Dom_1 : - forall (A:Set) (m:Map A) (pf:ad -> ad), - MapFold1 A (list ad) nil (app (A:=ad)) (fun (a:ad) (_:A) => a :: nil) pf - m = - MapFold1 unit (list ad) nil (app (A:=ad)) - (fun (a:ad) (_:unit) => a :: nil) pf (MapDom A m). - Proof. - simple induction m; try trivial. simpl in |- *. intros. rewrite (H (fun a0:ad => pf (Ndouble a0))). - rewrite (H0 (fun a0:ad => pf (Ndouble_plus_one a0))). reflexivity. - Qed. - - Lemma ad_list_of_dom_Dom : - forall (A:Set) (m:Map A), - ad_list_of_dom A m = ad_list_of_dom unit (MapDom A m). - Proof. - intros. exact (ad_list_of_dom_Dom_1 A m (fun a0:ad => a0)). - Qed. - -End MapLists.
\ No newline at end of file diff --git a/theories/IntMap/Mapsubset.v b/theories/IntMap/Mapsubset.v deleted file mode 100644 index 6771c03e..00000000 --- a/theories/IntMap/Mapsubset.v +++ /dev/null @@ -1,605 +0,0 @@ -(************************************************************************) -(* 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: Mapsubset.v 8733 2006-04-25 22:52:18Z letouzey $ i*) - -Require Import Bool. -Require Import Sumbool. -Require Import Arith. -Require Import NArith. -Require Import Ndigits. -Require Import Ndec. -Require Import Map. -Require Import Fset. -Require Import Mapaxioms. -Require Import Mapiter. - -Section MapSubsetDef. - - Variables A B : Set. - - Definition MapSubset (m:Map A) (m':Map B) := - forall a:ad, in_dom A a m = true -> in_dom B a m' = true. - - Definition MapSubset_1 (m:Map A) (m':Map B) := - match MapSweep A (fun (a:ad) (_:A) => negb (in_dom B a m')) m with - | None => true - | _ => false - end. - - Definition MapSubset_2 (m:Map A) (m':Map B) := - eqmap A (MapDomRestrBy A B m m') (M0 A). - - Lemma MapSubset_imp_1 : - forall (m:Map A) (m':Map B), MapSubset m m' -> MapSubset_1 m m' = true. - Proof. - unfold MapSubset, MapSubset_1 in |- *. intros. - elim - (option_sum _ (MapSweep A (fun (a:ad) (_:A) => negb (in_dom B a m')) m)). - intro H0. elim H0. intro r. elim r. intros a y H1. cut (negb (in_dom B a m') = true). - intro. cut (in_dom A a m = false). intro. unfold in_dom in H3. - rewrite (MapSweep_semantics_2 _ _ m a y H1) in H3. discriminate H3. - elim (sumbool_of_bool (in_dom A a m)). intro H3. rewrite (H a H3) in H2. discriminate H2. - trivial. - exact (MapSweep_semantics_1 _ _ m a y H1). - intro H0. rewrite H0. reflexivity. - Qed. - - Lemma MapSubset_1_imp : - forall (m:Map A) (m':Map B), MapSubset_1 m m' = true -> MapSubset m m'. - Proof. - unfold MapSubset, MapSubset_1 in |- *. unfold in_dom at 2 in |- *. intros. elim (option_sum _ (MapGet A m a)). - intro H1. elim H1. intros y H2. - elim - (option_sum _ (MapSweep A (fun (a:ad) (_:A) => negb (in_dom B a m')) m)). intro H3. - elim H3. intro r. elim r. intros a' y' H4. rewrite H4 in H. discriminate H. - intro H3. cut (negb (in_dom B a m') = false). intro. rewrite (negb_intro (in_dom B a m')). - rewrite H4. reflexivity. - exact (MapSweep_semantics_3 _ _ m H3 a y H2). - intro H1. rewrite H1 in H0. discriminate H0. - Qed. - - Lemma map_dom_empty_1 : - forall m:Map A, eqmap A m (M0 A) -> forall a:ad, in_dom _ a m = false. - Proof. - unfold eqmap, eqm, in_dom in |- *. intros. rewrite (H a). reflexivity. - Qed. - - Lemma map_dom_empty_2 : - forall m:Map A, (forall a:ad, in_dom _ a m = false) -> eqmap A m (M0 A). - Proof. - unfold eqmap, eqm, in_dom in |- *. intros. - cut - (match MapGet A m a with - | None => false - | Some _ => true - end = false). - case (MapGet A m a); trivial. - intros. discriminate H0. - exact (H a). - Qed. - - Lemma MapSubset_imp_2 : - forall (m:Map A) (m':Map B), MapSubset m m' -> MapSubset_2 m m'. - Proof. - unfold MapSubset, MapSubset_2 in |- *. intros. apply map_dom_empty_2. intro. rewrite in_dom_restrby. - elim (sumbool_of_bool (in_dom A a m)). intro H0. rewrite H0. rewrite (H a H0). reflexivity. - intro H0. rewrite H0. reflexivity. - Qed. - - Lemma MapSubset_2_imp : - forall (m:Map A) (m':Map B), MapSubset_2 m m' -> MapSubset m m'. - Proof. - unfold MapSubset, MapSubset_2 in |- *. intros. cut (in_dom _ a (MapDomRestrBy A B m m') = false). - rewrite in_dom_restrby. intro. elim (andb_false_elim _ _ H1). rewrite H0. - intro H2. discriminate H2. - intro H2. rewrite (negb_intro (in_dom B a m')). rewrite H2. reflexivity. - exact (map_dom_empty_1 _ H a). - Qed. - -End MapSubsetDef. - -Section MapSubsetOrder. - - Variables A B C : Set. - - Lemma MapSubset_refl : forall m:Map A, MapSubset A A m m. - Proof. - unfold MapSubset in |- *. trivial. - Qed. - - Lemma MapSubset_antisym : - forall (m:Map A) (m':Map B), - MapSubset A B m m' -> - MapSubset B A m' m -> eqmap unit (MapDom A m) (MapDom B m'). - Proof. - unfold MapSubset, eqmap, eqm in |- *. intros. elim (option_sum _ (MapGet _ (MapDom A m) a)). - intro H1. elim H1. intro t. elim t. intro H2. elim (option_sum _ (MapGet _ (MapDom B m') a)). - intro H3. elim H3. intro t'. elim t'. intro H4. rewrite H4. exact H2. - intro H3. cut (in_dom B a m' = true). intro. rewrite (MapDom_Dom B m' a) in H4. - unfold in_FSet, in_dom in H4. rewrite H3 in H4. discriminate H4. - apply H. rewrite (MapDom_Dom A m a). unfold in_FSet, in_dom in |- *. rewrite H2. reflexivity. - intro H1. elim (option_sum _ (MapGet _ (MapDom B m') a)). intro H2. elim H2. intros t H3. - cut (in_dom A a m = true). intro. rewrite (MapDom_Dom A m a) in H4. unfold in_FSet, in_dom in H4. - rewrite H1 in H4. discriminate H4. - apply H0. rewrite (MapDom_Dom B m' a). unfold in_FSet, in_dom in |- *. rewrite H3. reflexivity. - intro H2. rewrite H2. exact H1. - Qed. - - Lemma MapSubset_trans : - forall (m:Map A) (m':Map B) (m'':Map C), - MapSubset A B m m' -> MapSubset B C m' m'' -> MapSubset A C m m''. - Proof. - unfold MapSubset in |- *. intros. apply H0. apply H. assumption. - Qed. - -End MapSubsetOrder. - -Section FSubsetOrder. - - Lemma FSubset_refl : forall s:FSet, MapSubset _ _ s s. - Proof. - exact (MapSubset_refl unit). - Qed. - - Lemma FSubset_antisym : - forall s s':FSet, - MapSubset _ _ s s' -> MapSubset _ _ s' s -> eqmap unit s s'. - Proof. - intros. rewrite <- (FSet_Dom s). rewrite <- (FSet_Dom s'). - exact (MapSubset_antisym _ _ s s' H H0). - Qed. - - Lemma FSubset_trans : - forall s s' s'':FSet, - MapSubset _ _ s s' -> MapSubset _ _ s' s'' -> MapSubset _ _ s s''. - Proof. - exact (MapSubset_trans unit unit unit). - Qed. - -End FSubsetOrder. - -Section MapSubsetExtra. - - Variables A B : Set. - - Lemma MapSubset_Dom_1 : - forall (m:Map A) (m':Map B), - MapSubset A B m m' -> MapSubset unit unit (MapDom A m) (MapDom B m'). - Proof. - unfold MapSubset in |- *. intros. elim (MapDom_semantics_2 _ m a H0). intros y H1. - cut (in_dom A a m = true -> in_dom B a m' = true). intro. unfold in_dom in H2. - rewrite H1 in H2. elim (option_sum _ (MapGet B m' a)). intro H3. elim H3. - intros y' H4. exact (MapDom_semantics_1 _ m' a y' H4). - intro H3. rewrite H3 in H2. cut (false = true). intro. discriminate H4. - apply H2. reflexivity. - exact (H a). - Qed. - - Lemma MapSubset_Dom_2 : - forall (m:Map A) (m':Map B), - MapSubset unit unit (MapDom A m) (MapDom B m') -> MapSubset A B m m'. - Proof. - unfold MapSubset in |- *. intros. unfold in_dom in H0. elim (option_sum _ (MapGet A m a)). - intro H1. elim H1. intros y H2. - elim (MapDom_semantics_2 _ _ _ (H a (MapDom_semantics_1 _ _ _ _ H2))). intros y' H3. - unfold in_dom in |- *. rewrite H3. reflexivity. - intro H1. rewrite H1 in H0. discriminate H0. - Qed. - - Lemma MapSubset_1_Dom : - forall (m:Map A) (m':Map B), - MapSubset_1 A B m m' = MapSubset_1 unit unit (MapDom A m) (MapDom B m'). - Proof. - intros. elim (sumbool_of_bool (MapSubset_1 A B m m')). intro H. rewrite H. - apply sym_eq. apply MapSubset_imp_1. apply MapSubset_Dom_1. exact (MapSubset_1_imp _ _ _ _ H). - intro H. rewrite H. elim (sumbool_of_bool (MapSubset_1 unit unit (MapDom A m) (MapDom B m'))). - intro H0. - rewrite - (MapSubset_imp_1 _ _ _ _ - (MapSubset_Dom_2 _ _ (MapSubset_1_imp _ _ _ _ H0))) - in H. - discriminate H. - intro. apply sym_eq. assumption. - Qed. - - Lemma MapSubset_Put : - forall (m:Map A) (a:ad) (y:A), MapSubset A A m (MapPut A m a y). - Proof. - unfold MapSubset in |- *. intros. rewrite in_dom_put. rewrite H. apply orb_b_true. - Qed. - - Lemma MapSubset_Put_mono : - forall (m:Map A) (m':Map B) (a:ad) (y:A) (y':B), - MapSubset A B m m' -> MapSubset A B (MapPut A m a y) (MapPut B m' a y'). - Proof. - unfold MapSubset in |- *. intros. rewrite in_dom_put. rewrite (in_dom_put A m a y a0) in H0. - elim (orb_true_elim _ _ H0). intro H1. rewrite H1. reflexivity. - intro H1. rewrite (H _ H1). apply orb_b_true. - Qed. - - Lemma MapSubset_Put_behind : - forall (m:Map A) (a:ad) (y:A), MapSubset A A m (MapPut_behind A m a y). - Proof. - unfold MapSubset in |- *. intros. rewrite in_dom_put_behind. rewrite H. apply orb_b_true. - Qed. - - Lemma MapSubset_Put_behind_mono : - forall (m:Map A) (m':Map B) (a:ad) (y:A) (y':B), - MapSubset A B m m' -> - MapSubset A B (MapPut_behind A m a y) (MapPut_behind B m' a y'). - Proof. - unfold MapSubset in |- *. intros. rewrite in_dom_put_behind. - rewrite (in_dom_put_behind A m a y a0) in H0. - elim (orb_true_elim _ _ H0). intro H1. rewrite H1. reflexivity. - intro H1. rewrite (H _ H1). apply orb_b_true. - Qed. - - Lemma MapSubset_Remove : - forall (m:Map A) (a:ad), MapSubset A A (MapRemove A m a) m. - Proof. - unfold MapSubset in |- *. intros. unfold MapSubset in |- *. intros. rewrite (in_dom_remove _ m a a0) in H. - elim (andb_prop _ _ H). trivial. - Qed. - - Lemma MapSubset_Remove_mono : - forall (m:Map A) (m':Map B) (a:ad), - MapSubset A B m m' -> MapSubset A B (MapRemove A m a) (MapRemove B m' a). - Proof. - unfold MapSubset in |- *. intros. rewrite in_dom_remove. rewrite (in_dom_remove A m a a0) in H0. - elim (andb_prop _ _ H0). intros. rewrite H1. rewrite (H _ H2). reflexivity. - Qed. - - Lemma MapSubset_Merge_l : - forall m m':Map A, MapSubset A A m (MapMerge A m m'). - Proof. - unfold MapSubset in |- *. intros. rewrite in_dom_merge. rewrite H. reflexivity. - Qed. - - Lemma MapSubset_Merge_r : - forall m m':Map A, MapSubset A A m' (MapMerge A m m'). - Proof. - unfold MapSubset in |- *. intros. rewrite in_dom_merge. rewrite H. apply orb_b_true. - Qed. - - Lemma MapSubset_Merge_mono : - forall (m m':Map A) (m'' m''':Map B), - MapSubset A B m m'' -> - MapSubset A B m' m''' -> - MapSubset A B (MapMerge A m m') (MapMerge B m'' m'''). - Proof. - unfold MapSubset in |- *. intros. rewrite in_dom_merge. rewrite (in_dom_merge A m m' a) in H1. - elim (orb_true_elim _ _ H1). intro H2. rewrite (H _ H2). reflexivity. - intro H2. rewrite (H0 _ H2). apply orb_b_true. - Qed. - - Lemma MapSubset_DomRestrTo_l : - forall (m:Map A) (m':Map B), MapSubset A A (MapDomRestrTo A B m m') m. - Proof. - unfold MapSubset in |- *. intros. rewrite (in_dom_restrto _ _ m m' a) in H. elim (andb_prop _ _ H). - trivial. - Qed. - - Lemma MapSubset_DomRestrTo_r : - forall (m:Map A) (m':Map B), MapSubset A B (MapDomRestrTo A B m m') m'. - Proof. - unfold MapSubset in |- *. intros. rewrite (in_dom_restrto _ _ m m' a) in H. elim (andb_prop _ _ H). - trivial. - Qed. - - Lemma MapSubset_ext : - forall (m0 m1:Map A) (m2 m3:Map B), - eqmap A m0 m1 -> - eqmap B m2 m3 -> MapSubset A B m0 m2 -> MapSubset A B m1 m3. - Proof. - intros. apply MapSubset_2_imp. unfold MapSubset_2 in |- *. - apply eqmap_trans with (m' := MapDomRestrBy A B m0 m2). apply MapDomRestrBy_ext. apply eqmap_sym. - assumption. - apply eqmap_sym. assumption. - exact (MapSubset_imp_2 _ _ _ _ H1). - Qed. - - Variables C D : Set. - - Lemma MapSubset_DomRestrTo_mono : - forall (m:Map A) (m':Map B) (m'':Map C) (m''':Map D), - MapSubset _ _ m m'' -> - MapSubset _ _ m' m''' -> - MapSubset _ _ (MapDomRestrTo _ _ m m') (MapDomRestrTo _ _ m'' m'''). - Proof. - unfold MapSubset in |- *. intros. rewrite in_dom_restrto. rewrite (in_dom_restrto A B m m' a) in H1. - elim (andb_prop _ _ H1). intros. rewrite (H _ H2). rewrite (H0 _ H3). reflexivity. - Qed. - - Lemma MapSubset_DomRestrBy_l : - forall (m:Map A) (m':Map B), MapSubset A A (MapDomRestrBy A B m m') m. - Proof. - unfold MapSubset in |- *. intros. rewrite (in_dom_restrby _ _ m m' a) in H. elim (andb_prop _ _ H). - trivial. - Qed. - - Lemma MapSubset_DomRestrBy_mono : - forall (m:Map A) (m':Map B) (m'':Map C) (m''':Map D), - MapSubset _ _ m m'' -> - MapSubset _ _ m''' m' -> - MapSubset _ _ (MapDomRestrBy _ _ m m') (MapDomRestrBy _ _ m'' m'''). - Proof. - unfold MapSubset in |- *. intros. rewrite in_dom_restrby. rewrite (in_dom_restrby A B m m' a) in H1. - elim (andb_prop _ _ H1). intros. rewrite (H _ H2). elim (sumbool_of_bool (in_dom D a m''')). - intro H4. rewrite (H0 _ H4) in H3. discriminate H3. - intro H4. rewrite H4. reflexivity. - Qed. - -End MapSubsetExtra. - -Section MapDisjointDef. - - Variables A B : Set. - - Definition MapDisjoint (m:Map A) (m':Map B) := - forall a:ad, in_dom A a m = true -> in_dom B a m' = true -> False. - - Definition MapDisjoint_1 (m:Map A) (m':Map B) := - match MapSweep A (fun (a:ad) (_:A) => in_dom B a m') m with - | None => true - | _ => false - end. - - Definition MapDisjoint_2 (m:Map A) (m':Map B) := - eqmap A (MapDomRestrTo A B m m') (M0 A). - - Lemma MapDisjoint_imp_1 : - forall (m:Map A) (m':Map B), MapDisjoint m m' -> MapDisjoint_1 m m' = true. - Proof. - unfold MapDisjoint, MapDisjoint_1 in |- *. intros. - elim (option_sum _ (MapSweep A (fun (a:ad) (_:A) => in_dom B a m') m)). intro H0. elim H0. - intro r. elim r. intros a y H1. cut (in_dom A a m = true -> in_dom B a m' = true -> False). - intro. unfold in_dom at 1 in H2. rewrite (MapSweep_semantics_2 _ _ _ _ _ H1) in H2. - rewrite (MapSweep_semantics_1 _ _ _ _ _ H1) in H2. elim (H2 (refl_equal _) (refl_equal _)). - exact (H a). - intro H0. rewrite H0. reflexivity. - Qed. - - Lemma MapDisjoint_1_imp : - forall (m:Map A) (m':Map B), MapDisjoint_1 m m' = true -> MapDisjoint m m'. - Proof. - unfold MapDisjoint, MapDisjoint_1 in |- *. intros. - elim (option_sum _ (MapSweep A (fun (a:ad) (_:A) => in_dom B a m') m)). intro H2. elim H2. - intro r. elim r. intros a' y' H3. rewrite H3 in H. discriminate H. - intro H2. unfold in_dom in H0. elim (option_sum _ (MapGet A m a)). intro H3. elim H3. - intros y H4. rewrite (MapSweep_semantics_3 _ _ _ H2 a y H4) in H1. discriminate H1. - intro H3. rewrite H3 in H0. discriminate H0. - Qed. - - Lemma MapDisjoint_imp_2 : - forall (m:Map A) (m':Map B), MapDisjoint m m' -> MapDisjoint_2 m m'. - Proof. - unfold MapDisjoint, MapDisjoint_2 in |- *. unfold eqmap, eqm in |- *. intros. - rewrite (MapDomRestrTo_semantics A B m m' a). - cut (in_dom A a m = true -> in_dom B a m' = true -> False). intro. - elim (option_sum _ (MapGet A m a)). intro H1. elim H1. intros y H2. unfold in_dom at 1 in H0. - elim (option_sum _ (MapGet B m' a)). intro H3. elim H3. intros y' H4. unfold in_dom at 1 in H0. - rewrite H4 in H0. rewrite H2 in H0. elim (H0 (refl_equal _) (refl_equal _)). - intro H3. rewrite H3. reflexivity. - intro H1. rewrite H1. case (MapGet B m' a); reflexivity. - exact (H a). - Qed. - - Lemma MapDisjoint_2_imp : - forall (m:Map A) (m':Map B), MapDisjoint_2 m m' -> MapDisjoint m m'. - Proof. - unfold MapDisjoint, MapDisjoint_2 in |- *. unfold eqmap, eqm in |- *. intros. elim (in_dom_some _ _ _ H0). - intros y H2. elim (in_dom_some _ _ _ H1). intros y' H3. - cut (MapGet A (MapDomRestrTo A B m m') a = None). intro. - rewrite (MapDomRestrTo_semantics _ _ m m' a) in H4. rewrite H3 in H4. rewrite H2 in H4. - discriminate H4. - exact (H a). - Qed. - - Lemma Map_M0_disjoint : forall m:Map B, MapDisjoint (M0 A) m. - Proof. - unfold MapDisjoint, in_dom in |- *. intros. discriminate H. - Qed. - - Lemma Map_disjoint_M0 : forall m:Map A, MapDisjoint m (M0 B). - Proof. - unfold MapDisjoint, in_dom in |- *. intros. discriminate H0. - Qed. - -End MapDisjointDef. - -Section MapDisjointExtra. - - Variables A B : Set. - - Lemma MapDisjoint_ext : - forall (m0 m1:Map A) (m2 m3:Map B), - eqmap A m0 m1 -> - eqmap B m2 m3 -> MapDisjoint A B m0 m2 -> MapDisjoint A B m1 m3. - Proof. - intros. apply MapDisjoint_2_imp. unfold MapDisjoint_2 in |- *. - apply eqmap_trans with (m' := MapDomRestrTo A B m0 m2). apply eqmap_sym. apply MapDomRestrTo_ext. - assumption. - assumption. - exact (MapDisjoint_imp_2 _ _ _ _ H1). - Qed. - - Lemma MapMerge_disjoint : - forall m m':Map A, - MapDisjoint A A m m' -> - forall a:ad, - in_dom A a (MapMerge A m m') = - orb (andb (in_dom A a m) (negb (in_dom A a m'))) - (andb (in_dom A a m') (negb (in_dom A a m))). - Proof. - unfold MapDisjoint in |- *. intros. rewrite in_dom_merge. elim (sumbool_of_bool (in_dom A a m)). - intro H0. rewrite H0. elim (sumbool_of_bool (in_dom A a m')). intro H1. elim (H a H0 H1). - intro H1. rewrite H1. reflexivity. - intro H0. rewrite H0. simpl in |- *. rewrite andb_b_true. reflexivity. - Qed. - - Lemma MapDisjoint_M2_l : - forall (m0 m1:Map A) (m2 m3:Map B), - MapDisjoint A B (M2 A m0 m1) (M2 B m2 m3) -> MapDisjoint A B m0 m2. - Proof. - unfold MapDisjoint, in_dom in |- *. intros. elim (option_sum _ (MapGet A m0 a)). intro H2. - elim H2. intros y H3. elim (option_sum _ (MapGet B m2 a)). intro H4. elim H4. - intros y' H5. apply (H (Ndouble a)). - rewrite (MapGet_M2_bit_0_0 _ (Ndouble a) (Ndouble_bit0 a) m0 m1). - rewrite (Ndouble_div2 a). rewrite H3. reflexivity. - rewrite (MapGet_M2_bit_0_0 _ (Ndouble a) (Ndouble_bit0 a) m2 m3). - rewrite (Ndouble_div2 a). rewrite H5. reflexivity. - intro H4. rewrite H4 in H1. discriminate H1. - intro H2. rewrite H2 in H0. discriminate H0. - Qed. - - Lemma MapDisjoint_M2_r : - forall (m0 m1:Map A) (m2 m3:Map B), - MapDisjoint A B (M2 A m0 m1) (M2 B m2 m3) -> MapDisjoint A B m1 m3. - Proof. - unfold MapDisjoint, in_dom in |- *. intros. elim (option_sum _ (MapGet A m1 a)). intro H2. - elim H2. intros y H3. elim (option_sum _ (MapGet B m3 a)). intro H4. elim H4. - intros y' H5. apply (H (Ndouble_plus_one a)). - rewrite - (MapGet_M2_bit_0_1 _ (Ndouble_plus_one a) (Ndouble_plus_one_bit0 a) - m0 m1). - rewrite (Ndouble_plus_one_div2 a). rewrite H3. reflexivity. - rewrite - (MapGet_M2_bit_0_1 _ (Ndouble_plus_one a) (Ndouble_plus_one_bit0 a) - m2 m3). - rewrite (Ndouble_plus_one_div2 a). rewrite H5. reflexivity. - intro H4. rewrite H4 in H1. discriminate H1. - intro H2. rewrite H2 in H0. discriminate H0. - Qed. - - Lemma MapDisjoint_M2 : - forall (m0 m1:Map A) (m2 m3:Map B), - MapDisjoint A B m0 m2 -> - MapDisjoint A B m1 m3 -> MapDisjoint A B (M2 A m0 m1) (M2 B m2 m3). - Proof. - unfold MapDisjoint, in_dom in |- *. intros. elim (sumbool_of_bool (Nbit0 a)). intro H3. - rewrite (MapGet_M2_bit_0_1 A a H3 m0 m1) in H1. - rewrite (MapGet_M2_bit_0_1 B a H3 m2 m3) in H2. exact (H0 (Ndiv2 a) H1 H2). - intro H3. rewrite (MapGet_M2_bit_0_0 A a H3 m0 m1) in H1. - rewrite (MapGet_M2_bit_0_0 B a H3 m2 m3) in H2. exact (H (Ndiv2 a) H1 H2). - Qed. - - Lemma MapDisjoint_M1_l : - forall (m:Map A) (a:ad) (y:B), - MapDisjoint B A (M1 B a y) m -> in_dom A a m = false. - Proof. - unfold MapDisjoint in |- *. intros. elim (sumbool_of_bool (in_dom A a m)). intro H0. - elim (H a (in_dom_M1_1 B a y) H0). - trivial. - Qed. - - Lemma MapDisjoint_M1_r : - forall (m:Map A) (a:ad) (y:B), - MapDisjoint A B m (M1 B a y) -> in_dom A a m = false. - Proof. - unfold MapDisjoint in |- *. intros. elim (sumbool_of_bool (in_dom A a m)). intro H0. - elim (H a H0 (in_dom_M1_1 B a y)). - trivial. - Qed. - - Lemma MapDisjoint_M1_conv_l : - forall (m:Map A) (a:ad) (y:B), - in_dom A a m = false -> MapDisjoint B A (M1 B a y) m. - Proof. - unfold MapDisjoint in |- *. intros. rewrite (in_dom_M1_2 B a a0 y H0) in H. rewrite H1 in H. - discriminate H. - Qed. - - Lemma MapDisjoint_M1_conv_r : - forall (m:Map A) (a:ad) (y:B), - in_dom A a m = false -> MapDisjoint A B m (M1 B a y). - Proof. - unfold MapDisjoint in |- *. intros. rewrite (in_dom_M1_2 B a a0 y H1) in H. rewrite H0 in H. - discriminate H. - Qed. - - Lemma MapDisjoint_sym : - forall (m:Map A) (m':Map B), MapDisjoint A B m m' -> MapDisjoint B A m' m. - Proof. - unfold MapDisjoint in |- *. intros. exact (H _ H1 H0). - Qed. - - Lemma MapDisjoint_empty : - forall m:Map A, MapDisjoint A A m m -> eqmap A m (M0 A). - Proof. - unfold eqmap, eqm in |- *. intros. rewrite <- (MapDomRestrTo_idempotent A m a). - exact (MapDisjoint_imp_2 A A m m H a). - Qed. - - Lemma MapDelta_disjoint : - forall m m':Map A, - MapDisjoint A A m m' -> eqmap A (MapDelta A m m') (MapMerge A m m'). - Proof. - intros. - apply eqmap_trans with - (m' := MapDomRestrBy A A (MapMerge A m m') (MapDomRestrTo A A m m')). - apply MapDelta_as_DomRestrBy. - apply eqmap_trans with (m' := MapDomRestrBy A A (MapMerge A m m') (M0 A)). - apply MapDomRestrBy_ext. apply eqmap_refl. - exact (MapDisjoint_imp_2 A A m m' H). - apply MapDomRestrBy_m_empty. - Qed. - - Variable C : Set. - - Lemma MapDomRestr_disjoint : - forall (m:Map A) (m':Map B) (m'':Map C), - MapDisjoint A B (MapDomRestrTo A C m m'') (MapDomRestrBy B C m' m''). - Proof. - unfold MapDisjoint in |- *. intros m m' m'' a. rewrite in_dom_restrto. rewrite in_dom_restrby. - intros. elim (andb_prop _ _ H). elim (andb_prop _ _ H0). intros. rewrite H4 in H2. - discriminate H2. - Qed. - - Lemma MapDelta_RestrTo_disjoint : - forall m m':Map A, - MapDisjoint A A (MapDelta A m m') (MapDomRestrTo A A m m'). - Proof. - unfold MapDisjoint in |- *. intros m m' a. rewrite in_dom_delta. rewrite in_dom_restrto. - intros. elim (andb_prop _ _ H0). intros. rewrite H1 in H. rewrite H2 in H. discriminate H. - Qed. - - Lemma MapDelta_RestrTo_disjoint_2 : - forall m m':Map A, - MapDisjoint A A (MapDelta A m m') (MapDomRestrTo A A m' m). - Proof. - unfold MapDisjoint in |- *. intros m m' a. rewrite in_dom_delta. rewrite in_dom_restrto. - intros. elim (andb_prop _ _ H0). intros. rewrite H1 in H. rewrite H2 in H. discriminate H. - Qed. - - Variable D : Set. - - Lemma MapSubset_Disjoint : - forall (m:Map A) (m':Map B) (m'':Map C) (m''':Map D), - MapSubset _ _ m m' -> - MapSubset _ _ m'' m''' -> - MapDisjoint _ _ m' m''' -> MapDisjoint _ _ m m''. - Proof. - unfold MapSubset, MapDisjoint in |- *. intros. exact (H1 _ (H _ H2) (H0 _ H3)). - Qed. - - Lemma MapSubset_Disjoint_l : - forall (m:Map A) (m':Map B) (m'':Map C), - MapSubset _ _ m m' -> MapDisjoint _ _ m' m'' -> MapDisjoint _ _ m m''. - Proof. - unfold MapSubset, MapDisjoint in |- *. intros. exact (H0 _ (H _ H1) H2). - Qed. - - Lemma MapSubset_Disjoint_r : - forall (m:Map A) (m'':Map C) (m''':Map D), - MapSubset _ _ m'' m''' -> - MapDisjoint _ _ m m''' -> MapDisjoint _ _ m m''. - Proof. - unfold MapSubset, MapDisjoint in |- *. intros. exact (H0 _ H1 (H _ H2)). - Qed. - -End MapDisjointExtra.
\ No newline at end of file diff --git a/theories/IntMap/intro.tex b/theories/IntMap/intro.tex deleted file mode 100644 index 9ad93050..00000000 --- a/theories/IntMap/intro.tex +++ /dev/null @@ -1,6 +0,0 @@ -\section{Maps indexed by binary integers : IntMap}\label{IntMap} - -This library contains a data structure for finite sets implemented by -an efficient structure of map (trees indexed by binary integers). -It was initially developed by Jean Goubault. - diff --git a/theories/Lists/List.v b/theories/Lists/List.v index c80d0b15..a72283d9 100644 --- a/theories/Lists/List.v +++ b/theories/Lists/List.v @@ -1,15 +1,14 @@ - (************************************************************************) - (* 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 *) - (************************************************************************) +(************************************************************************) +(* 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: List.v 9290 2006-10-26 19:20:42Z herbelin $ i*) +(*i $Id: List.v 10999 2008-05-27 15:55:22Z letouzey $ i*) Require Import Le Gt Minus Min Bool. -Require Import Setoid. Set Implicit Arguments. @@ -82,8 +81,6 @@ End Lists. Implicit Arguments nil [A]. Infix "::" := cons (at level 60, right associativity) : list_scope. Infix "++" := app (right associativity, at level 60) : list_scope. - -Ltac now_show c := change c in |- *. Open Scope list_scope. @@ -314,7 +311,27 @@ Section Facts. now_show (H = a \/ In a (y ++ m)). elim H2; auto. Qed. - + + Lemma app_inv_head: + forall l l1 l2 : list A, l ++ l1 = l ++ l2 -> l1 = l2. + Proof. + induction l; simpl; auto; injection 1; auto. + Qed. + + Lemma app_inv_tail: + forall l l1 l2 : list A, l1 ++ l = l2 ++ l -> l1 = l2. + Proof. + intros l l1 l2; revert l1 l2 l. + induction l1 as [ | x1 l1]; destruct l2 as [ | x2 l2]; + simpl; auto; intros l H. + absurd (length (x2 :: l2 ++ l) <= length l). + simpl; rewrite app_length; auto with arith. + rewrite <- H; auto with arith. + absurd (length (x1 :: l1 ++ l) <= length l). + simpl; rewrite app_length; auto with arith. + rewrite H; auto with arith. + injection H; clear H; intros; f_equal; eauto. + Qed. End Facts. @@ -512,6 +529,20 @@ Section Elts. exists (a::l'); exists a'; auto. Qed. + Lemma removelast_app : + forall l l', l' <> nil -> removelast (l++l') = l ++ removelast l'. + Proof. + induction l. + simpl; auto. + simpl; intros. + assert (l++l' <> nil). + destruct l. + simpl; auto. + simpl; discriminate. + specialize (IHl l' H). + destruct (l++l'); [elim H0; auto|f_equal; auto]. + Qed. + (****************************************) (** ** Counting occurences of a element *) @@ -534,8 +565,7 @@ Section Elts. simpl; intros; split; [destruct 1 | apply gt_irrefl]. simpl. intro x; destruct (eqA_dec y x) as [Heq|Hneq]. rewrite Heq; intuition. - rewrite <- (IHl x). - tauto. + pose (IHl x). intuition. Qed. Theorem count_occ_inv_nil : forall (l : list A), (forall x:A, count_occ l x = 0) <-> l = nil. @@ -668,8 +698,8 @@ Section ListOps. rewrite app_nth1; auto. rewrite (minus_plus_simpl_l_reverse (length l) n 1). replace (1 + length l) with (S (length l)); auto with arith. - rewrite <- minus_Sn_m; auto with arith; simpl. - apply IHl; auto. + rewrite <- minus_Sn_m; auto with arith. + apply IHl ; auto with arith. rewrite rev_length; auto. Qed. @@ -899,7 +929,7 @@ Section ListOps. apply perm_trans with (l1'++a::l2); auto using Permutation_cons_app. apply perm_skip. apply (IH a l1' l2 l3' l4); auto. - (* swap *) + (* contradict *) intros x y l l' Hp IH; intros. break_list l1 b l1' H; break_list l3 c l3' H0. auto. @@ -1345,7 +1375,7 @@ End Fold_Right_Recursor. destruct n; destruct d; simpl; auto. destruct a; destruct (split l); simpl; auto. destruct a; destruct (split l); simpl in *; auto. - rewrite IHl; simpl; auto. + apply IHl. Qed. Lemma split_length_l : forall (l:list (A*B)), @@ -1618,7 +1648,7 @@ Hint Resolve incl_refl incl_tl incl_tran incl_appl incl_appr incl_cons (**************************************) -(* ** Cutting a list at some position *) +(** * Cutting a list at some position *) (**************************************) Section Cutting. @@ -1651,6 +1681,45 @@ Section Cutting. f_equal; auto. Qed. + Lemma firstn_length : forall n l, length (firstn n l) = min n (length l). + Proof. + induction n; destruct l; simpl; auto. + Qed. + + Lemma removelast_firstn : forall n l, n < length l -> + removelast (firstn (S n) l) = firstn n l. + Proof. + induction n; destruct l. + simpl; auto. + simpl; auto. + simpl; auto. + intros. + simpl in H. + change (firstn (S (S n)) (a::l)) with ((a::nil)++firstn (S n) l). + change (firstn (S n) (a::l)) with (a::firstn n l). + rewrite removelast_app. + rewrite IHn; auto with arith. + + clear IHn; destruct l; simpl in *; try discriminate. + inversion_clear H. + inversion_clear H0. + Qed. + + Lemma firstn_removelast : forall n l, n < length l -> + firstn n (removelast l) = firstn n l. + Proof. + induction n; destruct l. + simpl; auto. + simpl; auto. + simpl; auto. + intros. + simpl in H. + change (removelast (a :: l)) with (removelast ((a::nil)++l)). + rewrite removelast_app. + simpl; f_equal; auto with arith. + intro H0; rewrite H0 in H; inversion_clear H; inversion_clear H1. + Qed. + End Cutting. @@ -1672,8 +1741,8 @@ Section ReDun. inversion_clear 1; auto. inversion_clear 1. constructor. - swap H0. - apply in_or_app; destruct (in_app_or _ _ _ H); simpl; tauto. + contradict H0. + apply in_or_app; destruct (in_app_or _ _ _ H0); simpl; tauto. apply IHl with a0; auto. Qed. @@ -1682,8 +1751,8 @@ Section ReDun. induction l; simpl. inversion_clear 1; auto. inversion_clear 1. - swap H0. - destruct H. + contradict H0. + destruct H0. subst a0. apply in_or_app; right; red; auto. destruct (IHl _ _ H1); auto. diff --git a/theories/Lists/ListSet.v b/theories/Lists/ListSet.v index 4e009ed5..021a64c1 100644 --- a/theories/Lists/ListSet.v +++ b/theories/Lists/ListSet.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: ListSet.v 6844 2005-03-16 13:09:55Z herbelin $ i*) +(*i $Id: ListSet.v 10616 2008-03-04 17:33:35Z letouzey $ i*) (** A Library for finite sets, implemented as lists *) @@ -20,7 +20,7 @@ Set Implicit Arguments. Section first_definitions. - Variable A : Set. + Variable A : Type. Hypothesis Aeq_dec : forall x y:A, {x = y} + {x <> y}. Definition set := list A. @@ -100,7 +100,7 @@ Section first_definitions. Qed. Lemma set_mem_ind : - forall (B:Set) (P:B -> Prop) (y z:B) (a:A) (x:set), + forall (B:Type) (P:B -> Prop) (y z:B) (a:A) (x:set), (set_In a x -> P y) -> P z -> P (if set_mem a x then y else z). Proof. @@ -110,7 +110,7 @@ Section first_definitions. Qed. Lemma set_mem_ind2 : - forall (B:Set) (P:B -> Prop) (y z:B) (a:A) (x:set), + forall (B:Type) (P:B -> Prop) (y z:B) (a:A) (x:set), (set_In a x -> P y) -> (~ set_In a x -> P z) -> P (if set_mem a x then y else z). @@ -373,7 +373,7 @@ End first_definitions. Section other_definitions. - Variables A B : Set. + Variables A B : Type. Definition set_prod : set A -> set B -> set (A * B) := list_prod (A:=A) (B:=B). diff --git a/theories/Lists/ListTactics.v b/theories/Lists/ListTactics.v index e46f1279..515ed138 100644 --- a/theories/Lists/ListTactics.v +++ b/theories/Lists/ListTactics.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: ListTactics.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: ListTactics.v 9427 2006-12-11 18:46:35Z bgregoir $ i*) Require Import BinPos. Require Import List. diff --git a/theories/Lists/SetoidList.v b/theories/Lists/SetoidList.v index eb40594b..4edc1581 100644 --- a/theories/Lists/SetoidList.v +++ b/theories/Lists/SetoidList.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: SetoidList.v 8853 2006-05-23 18:17:38Z herbelin $ *) +(* $Id: SetoidList.v 10616 2008-03-04 17:33:35Z letouzey $ *) Require Export List. Require Export Sorting. @@ -21,7 +21,7 @@ Unset Strict Implicit. found in [Sorting]. *) Section Type_with_equality. -Variable A : Set. +Variable A : Type. Variable eqA : A -> A -> Prop. (** Being in a list modulo an equality relation over type [A]. *) @@ -32,6 +32,18 @@ Inductive InA (x : A) : list A -> Prop := Hint Constructors InA. +Lemma InA_cons : forall x y l, InA x (y::l) <-> eqA x y \/ InA x l. +Proof. + intuition. + inversion H; auto. +Qed. + +Lemma InA_nil : forall x, InA x nil <-> False. +Proof. + intuition. + inversion H. +Qed. + (** An alternative definition of [InA]. *) Lemma InA_alt : forall x l, InA x l <-> exists y, eqA x y /\ In y l. @@ -53,7 +65,28 @@ Hint Constructors NoDupA. (** lists with same elements modulo [eqA] *) -Definition eqlistA l l' := forall x, InA x l <-> InA x l'. +Definition equivlistA l l' := forall x, InA x l <-> InA x l'. + +(** lists with same elements modulo [eqA] at the same place *) + +Inductive eqlistA : list A -> list A -> Prop := + | eqlistA_nil : eqlistA nil nil + | eqlistA_cons : forall x x' l l', + eqA x x' -> eqlistA l l' -> eqlistA (x::l) (x'::l'). + +Hint Constructors eqlistA. + +(** Compatibility of a boolean function with respect to an equality. *) + +Definition compat_bool (f : A->bool) := forall x y, eqA x y -> f x = f y. + +(** Compatibility of a function upon natural numbers. *) + +Definition compat_nat (f : A->nat) := forall x y, eqA x y -> f x = f y. + +(** Compatibility of a predicate with respect to an equality. *) + +Definition compat_P (P : A->Prop) := forall x y, eqA x y -> P x -> P y. (** Results concerning lists modulo [eqA] *) @@ -91,6 +124,35 @@ exists (a::l1); exists y; exists l2; auto. split; simpl; f_equal; auto. Qed. +Lemma InA_app : forall l1 l2 x, + InA x (l1 ++ l2) -> InA x l1 \/ InA x l2. +Proof. + induction l1; simpl in *; intuition. + inversion_clear H; auto. + elim (IHl1 l2 x H0); auto. +Qed. + +Lemma InA_app_iff : forall l1 l2 x, + InA x (l1 ++ l2) <-> InA x l1 \/ InA x l2. +Proof. + split. + apply InA_app. + destruct 1; generalize H; do 2 rewrite InA_alt. + destruct 1 as (y,(H1,H2)); exists y; split; auto. + apply in_or_app; auto. + destruct 1 as (y,(H1,H2)); exists y; split; auto. + apply in_or_app; auto. +Qed. + +Lemma InA_rev : forall p m, + InA p (rev m) <-> InA p m. +Proof. + intros; do 2 rewrite InA_alt. + split; intros (y,H); exists y; intuition. + rewrite In_rev; auto. + rewrite <- In_rev; auto. +Qed. + (** Results concerning lists modulo [eqA] and [ltA] *) Variable ltA : A -> A -> Prop. @@ -106,10 +168,12 @@ Hint Immediate ltA_eqA eqA_ltA. Notation InfA:=(lelistA ltA). Notation SortA:=(sort ltA). +Hint Constructors lelistA sort. + Lemma InfA_ltA : forall l x y, ltA x y -> InfA y l -> InfA x l. Proof. - intro s; case s; constructor; inversion_clear H0. + destruct l; constructor; inversion_clear H0; eapply ltA_trans; eauto. Qed. @@ -153,6 +217,26 @@ intros; eapply SortA_InfA_InA; eauto. apply InA_InfA. Qed. +Lemma InfA_app : forall l1 l2 a, InfA a l1 -> InfA a l2 -> InfA a (l1++l2). +Proof. + induction l1; simpl; auto. + inversion_clear 1; auto. +Qed. + +Lemma SortA_app : + forall l1 l2, SortA l1 -> SortA l2 -> + (forall x y, InA x l1 -> InA y l2 -> ltA x y) -> + SortA (l1 ++ l2). +Proof. + induction l1; simpl in *; intuition. + inversion_clear H. + constructor; auto. + apply InfA_app; auto. + destruct l2; auto. +Qed. + +Section NoDupA. + Lemma SortA_NoDupA : forall l, SortA l -> NoDupA l. Proof. simple induction l; auto. @@ -185,7 +269,6 @@ intros. apply (H1 x); auto. Qed. - Lemma NoDupA_rev : forall l, NoDupA l -> NoDupA (rev l). Proof. induction l. @@ -206,33 +289,240 @@ rewrite In_rev; auto. inversion H4. Qed. +Lemma NoDupA_split : forall l l' x, NoDupA (l++x::l') -> NoDupA (l++l'). +Proof. + induction l; simpl in *; inversion_clear 1; auto. + constructor; eauto. + contradict H0. + rewrite InA_app_iff in *; rewrite InA_cons; intuition. +Qed. -Lemma InA_app : forall l1 l2 x, - InA x (l1 ++ l2) -> InA x l1 \/ InA x l2. +Lemma NoDupA_swap : forall l l' x, NoDupA (l++x::l') -> NoDupA (x::l++l'). Proof. - induction l1; simpl in *; intuition. - inversion_clear H; auto. - elim (IHl1 l2 x H0); auto. + induction l; simpl in *; inversion_clear 1; auto. + constructor; eauto. + assert (H2:=IHl _ _ H1). + inversion_clear H2. + rewrite InA_cons. + red; destruct 1. + apply H0. + rewrite InA_app_iff in *; rewrite InA_cons; auto. + apply H; auto. + constructor. + contradict H0. + rewrite InA_app_iff in *; rewrite InA_cons; intuition. + eapply NoDupA_split; eauto. Qed. - Hint Constructors lelistA sort. +End NoDupA. -Lemma InfA_app : forall l1 l2 a, InfA a l1 -> InfA a l2 -> InfA a (l1++l2). +(** Some results about [eqlistA] *) + +Section EqlistA. + +Lemma eqlistA_length : forall l l', eqlistA l l' -> length l = length l'. Proof. - induction l1; simpl; auto. - inversion_clear 1; auto. +induction 1; auto; simpl; congruence. Qed. -Lemma SortA_app : - forall l1 l2, SortA l1 -> SortA l2 -> - (forall x y, InA x l1 -> InA y l2 -> ltA x y) -> - SortA (l1 ++ l2). +Lemma eqlistA_app : forall l1 l1' l2 l2', + eqlistA l1 l1' -> eqlistA l2 l2' -> eqlistA (l1++l2) (l1'++l2'). Proof. - induction l1; simpl in *; intuition. - inversion_clear H. - constructor; auto. - apply InfA_app; auto. - destruct l2; auto. +intros l1 l1' l2 l2' H; revert l2 l2'; induction H; simpl; auto. +Qed. + +Lemma eqlistA_rev_app : forall l1 l1', + eqlistA l1 l1' -> forall l2 l2', eqlistA l2 l2' -> + eqlistA ((rev l1)++l2) ((rev l1')++l2'). +Proof. +induction 1; auto. +simpl; intros. +do 2 rewrite app_ass; simpl; auto. +Qed. + +Lemma eqlistA_rev : forall l1 l1', + eqlistA l1 l1' -> eqlistA (rev l1) (rev l1'). +Proof. +intros. +rewrite (app_nil_end (rev l1)). +rewrite (app_nil_end (rev l1')). +apply eqlistA_rev_app; auto. +Qed. + +Lemma SortA_equivlistA_eqlistA : forall l l', + SortA l -> SortA l' -> equivlistA l l' -> eqlistA l l'. +Proof. +induction l; destruct l'; simpl; intros; auto. +destruct (H1 a); assert (H4 : InA a nil) by auto; inversion H4. +destruct (H1 a); assert (H4 : InA a nil) by auto; inversion H4. +inversion_clear H; inversion_clear H0. +assert (forall y, InA y l -> ltA a y). +intros; eapply SortA_InfA_InA with (l:=l); eauto. +assert (forall y, InA y l' -> ltA a0 y). +intros; eapply SortA_InfA_InA with (l:=l'); eauto. +clear H3 H4. +assert (eqA a a0). + destruct (H1 a). + destruct (H1 a0). + assert (InA a (a0::l')) by auto. + inversion_clear H8; auto. + assert (InA a0 (a::l)) by auto. + inversion_clear H8; auto. + elim (@ltA_not_eqA a a); auto. + apply ltA_trans with a0; auto. +constructor; auto. +apply IHl; auto. +split; intros. +destruct (H1 x). +assert (H8 : InA x (a0::l')) by auto; inversion_clear H8; auto. +elim (@ltA_not_eqA a x); eauto. +destruct (H1 x). +assert (H8 : InA x (a::l)) by auto; inversion_clear H8; auto. +elim (@ltA_not_eqA a0 x); eauto. +Qed. + +End EqlistA. + +(** A few things about [filter] *) + +Section Filter. + +Lemma filter_sort : forall f l, SortA l -> SortA (List.filter f l). +Proof. +induction l; simpl; auto. +inversion_clear 1; auto. +destruct (f a); auto. +constructor; auto. +apply In_InfA; auto. +intros. +rewrite filter_In in H; destruct H. +eapply SortA_InfA_InA; eauto. +Qed. + +Lemma filter_InA : forall f, (compat_bool f) -> + forall l x, InA x (List.filter f l) <-> InA x l /\ f x = true. +Proof. +intros; do 2 rewrite InA_alt; intuition. +destruct H0 as (y,(H0,H1)); rewrite filter_In in H1; exists y; intuition. +destruct H0 as (y,(H0,H1)); rewrite filter_In in H1; intuition. + rewrite (H _ _ H0); auto. +destruct H1 as (y,(H0,H1)); exists y; rewrite filter_In; intuition. + rewrite <- (H _ _ H0); auto. +Qed. + +Lemma filter_split : + forall f, (forall x y, f x = true -> f y = false -> ltA x y) -> + forall l, SortA l -> l = filter f l ++ filter (fun x=>negb (f x)) l. +Proof. +induction l; simpl; intros; auto. +inversion_clear H0. +pattern l at 1; rewrite IHl; auto. +case_eq (f a); simpl; intros; auto. +assert (forall e, In e l -> f e = false). + intros. + assert (H4:=SortA_InfA_InA H1 H2 (In_InA H3)). + case_eq (f e); simpl; intros; auto. + elim (@ltA_not_eqA e e); auto. + apply ltA_trans with a; eauto. +replace (List.filter f l) with (@nil A); auto. +generalize H3; clear; induction l; simpl; auto. +case_eq (f a); auto; intros. +rewrite H3 in H; auto; try discriminate. +Qed. + +End Filter. + +Section Fold. + +Variable B:Type. +Variable eqB:B->B->Prop. + +(** Compatibility of a two-argument function with respect to two equalities. *) +Definition compat_op (f : A -> B -> B) := + forall (x x' : A) (y y' : B), eqA x x' -> eqB y y' -> eqB (f x y) (f x' y'). + +(** Two-argument functions that allow to reorder their arguments. *) +Definition transpose (f : A -> B -> B) := + forall (x y : A) (z : B), eqB (f x (f y z)) (f y (f x z)). + +Variable st:Setoid_Theory _ eqB. +Variable f:A->B->B. +Variable i:B. +Variable Comp:compat_op f. + +Lemma fold_right_eqlistA : + forall s s', eqlistA s s' -> + eqB (fold_right f i s) (fold_right f i s'). +Proof. +induction 1; simpl; auto. +refl_st. +Qed. + +Variable Ass:transpose f. + +Lemma fold_right_commutes : forall s1 s2 x, + eqB (fold_right f i (s1++x::s2)) (f x (fold_right f i (s1++s2))). +Proof. +induction s1; simpl; auto; intros. +refl_st. +trans_st (f a (f x (fold_right f i (s1++s2)))). +Qed. + +Lemma equivlistA_NoDupA_split : forall l l1 l2 x y, eqA x y -> + NoDupA (x::l) -> NoDupA (l1++y::l2) -> + equivlistA (x::l) (l1++y::l2) -> equivlistA l (l1++l2). +Proof. + intros; intro a. + generalize (H2 a). + repeat rewrite InA_app_iff. + do 2 rewrite InA_cons. + inversion_clear H0. + assert (SW:=NoDupA_swap H1). + inversion_clear SW. + rewrite InA_app_iff in H0. + split; intros. + assert (~eqA a x). + contradict H3; apply InA_eqA with a; auto. + assert (~eqA a y). + contradict H8; eauto. + intuition. + assert (eqA a x \/ InA a l) by intuition. + destruct H8; auto. + elim H0. + destruct H7; [left|right]; eapply InA_eqA; eauto. +Qed. + +Lemma fold_right_equivlistA : + forall s s', NoDupA s -> NoDupA s' -> + equivlistA s s' -> eqB (fold_right f i s) (fold_right f i s'). +Proof. + simple induction s. + destruct s'; simpl. + intros; refl_st; auto. + unfold equivlistA; intros. + destruct (H1 a). + assert (X : InA a nil); auto; inversion X. + intros x l Hrec s' N N' E; simpl in *. + assert (InA x s'). + rewrite <- (E x); auto. + destruct (InA_split H) as (s1,(y,(s2,(H1,H2)))). + subst s'. + trans_st (f x (fold_right f i (s1++s2))). + apply Comp; auto. + apply Hrec; auto. + inversion_clear N; auto. + eapply NoDupA_split; eauto. + eapply equivlistA_NoDupA_split; eauto. + trans_st (f y (fold_right f i (s1++s2))). + apply Comp; auto; refl_st. + sym_st; apply fold_right_commutes. +Qed. + +Lemma fold_right_add : + forall s' s x, NoDupA s -> NoDupA s' -> ~ InA x s -> + equivlistA s' (x::s) -> eqB (fold_right f i s') (f x (fold_right f i s)). +Proof. + intros; apply (@fold_right_equivlistA s' (x::s)); auto. Qed. Section Remove. @@ -279,7 +569,7 @@ destruct H0; apply eqA_trans with a; auto. split. inversion_clear 1. split; auto. -swap n. +contradict n. apply eqA_trans with y; auto. rewrite (IHl x y) in H0; destruct H0; auto. destruct 1; inversion_clear H; auto. @@ -298,14 +588,14 @@ rewrite removeA_InA. intuition. Qed. -Lemma removeA_eqlistA : forall l l' x, - ~InA x l -> eqlistA (x :: l) l' -> eqlistA l (removeA x l'). +Lemma removeA_equivlistA : forall l l' x, + ~InA x l -> equivlistA (x :: l) l' -> equivlistA l (removeA x l'). Proof. -unfold eqlistA; intros. +unfold equivlistA; intros. rewrite removeA_InA. split; intros. rewrite <- H0; split; auto. -swap H. +contradict H. apply InA_eqA with x0; auto. rewrite <- (H0 x0) in H1. destruct H1. @@ -313,160 +603,17 @@ inversion_clear H1; auto. elim H2; auto. Qed. -Let addlistA x l l' := forall y, InA y l' <-> eqA x y \/ InA y l. - -Lemma removeA_add : - forall s s' x x', NoDupA s -> NoDupA (x' :: s') -> - ~ eqA x x' -> ~ InA x s -> - addlistA x s (x' :: s') -> addlistA x (removeA x' s) s'. -Proof. -unfold addlistA; intros. -inversion_clear H0. -rewrite removeA_InA; auto. -split; intros. -destruct (eqA_dec x y); auto; intros. -right; split; auto. -destruct (H3 y); clear H3. -destruct H6; intuition. -swap H4; apply InA_eqA with y; auto. -destruct H0. -assert (InA y (x' :: s')) by (rewrite H3; auto). -inversion_clear H6; auto. -elim H1; apply eqA_trans with y; auto. -destruct H0. -assert (InA y (x' :: s')) by (rewrite H3; auto). -inversion_clear H7; auto. -elim H6; auto. -Qed. - -Section Fold. - -Variable B:Set. -Variable eqB:B->B->Prop. - -(** Two-argument functions that allow to reorder its arguments. *) -Definition transpose (f : A -> B -> B) := - forall (x y : A) (z : B), eqB (f x (f y z)) (f y (f x z)). - -(** Compatibility of a two-argument function with respect to two equalities. *) -Definition compat_op (f : A -> B -> B) := - forall (x x' : A) (y y' : B), eqA x x' -> eqB y y' -> eqB (f x y) (f x' y'). - -(** Compatibility of a function upon natural numbers. *) -Definition compat_nat (f : A -> nat) := - forall x x' : A, eqA x x' -> f x = f x'. - -Variable st:Setoid_Theory _ eqB. -Variable f:A->B->B. -Variable Comp:compat_op f. -Variable Ass:transpose f. -Variable i:B. - -Lemma removeA_fold_right_0 : - forall s x, ~InA x s -> - eqB (fold_right f i s) (fold_right f i (removeA x s)). -Proof. - simple induction s; simpl; intros. - refl_st. - destruct (eqA_dec x a); simpl; intros. - absurd_hyp e; auto. - apply Comp; auto. -Qed. - -Lemma removeA_fold_right : - forall s x, NoDupA s -> InA x s -> - eqB (fold_right f i s) (f x (fold_right f i (removeA x s))). -Proof. - simple induction s; simpl. - inversion_clear 2. - intros. - inversion_clear H0. - destruct (eqA_dec x a); simpl; intros. - apply Comp; auto. - apply removeA_fold_right_0; auto. - swap H2; apply InA_eqA with x; auto. - inversion_clear H1. - destruct n; auto. - trans_st (f a (f x (fold_right f i (removeA x l)))). -Qed. - -Lemma fold_right_equal : - forall s s', NoDupA s -> NoDupA s' -> - eqlistA s s' -> eqB (fold_right f i s) (fold_right f i s'). -Proof. - simple induction s. - destruct s'; simpl. - intros; refl_st; auto. - unfold eqlistA; intros. - destruct (H1 a). - assert (X : InA a nil); auto; inversion X. - intros x l Hrec s' N N' E; simpl in *. - trans_st (f x (fold_right f i (removeA x s'))). - apply Comp; auto. - apply Hrec; auto. - inversion N; auto. - apply removeA_NoDupA; auto; apply eqA_trans. - apply removeA_eqlistA; auto. - inversion_clear N; auto. - sym_st. - apply removeA_fold_right; auto. - unfold eqlistA in E. - rewrite <- E; auto. -Qed. - -Lemma fold_right_add : - forall s' s x, NoDupA s -> NoDupA s' -> ~ InA x s -> - addlistA x s s' -> eqB (fold_right f i s') (f x (fold_right f i s)). -Proof. - simple induction s'. - unfold addlistA; intros. - destruct (H2 x); clear H2. - assert (X : InA x nil); auto; inversion X. - intros x' l' Hrec s x N N' IN EQ; simpl. - (* if x=x' *) - destruct (eqA_dec x x'). - apply Comp; auto. - apply fold_right_equal; auto. - inversion_clear N'; trivial. - unfold eqlistA; unfold addlistA in EQ; intros. - destruct (EQ x0); clear EQ. - split; intros. - destruct H; auto. - inversion_clear N'. - destruct H2; apply InA_eqA with x0; auto. - apply eqA_trans with x; auto. - assert (X:InA x0 (x' :: l')); auto; inversion_clear X; auto. - destruct IN; apply InA_eqA with x0; auto. - apply eqA_trans with x'; auto. - (* else x<>x' *) - trans_st (f x' (f x (fold_right f i (removeA x' s)))). - apply Comp; auto. - apply Hrec; auto. - apply removeA_NoDupA; auto; apply eqA_trans. - inversion_clear N'; auto. - rewrite removeA_InA; intuition. - apply removeA_add; auto. - trans_st (f x (f x' (fold_right f i (removeA x' s)))). - apply Comp; auto. - sym_st. - apply removeA_fold_right; auto. - destruct (EQ x'). - destruct H; auto; destruct n; auto. -Qed. +End Remove. End Fold. -End Remove. - End Type_with_equality. -Hint Constructors InA. -Hint Constructors NoDupA. -Hint Constructors sort. -Hint Constructors lelistA. +Hint Unfold compat_bool compat_nat compat_P. +Hint Constructors InA NoDupA sort lelistA eqlistA. Section Find. -Variable A B : Set. +Variable A B : Type. Variable eqA : A -> A -> Prop. Hypothesis eqA_sym : forall x y, eqA x y -> eqA y x. Hypothesis eqA_trans : forall x y z, eqA x y -> eqA y z -> eqA x z. diff --git a/theories/Lists/StreamMemo.v b/theories/Lists/StreamMemo.v new file mode 100644 index 00000000..bdbe0ecc --- /dev/null +++ b/theories/Lists/StreamMemo.v @@ -0,0 +1,205 @@ +(************************************************************************) +(* 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 Eqdep_dec. +Require Import Streams. + +(** * Memoization *) + +(** Successive outputs of a given function [f] are stored in + a stream in order to avoid duplicated computations. *) + +Section MemoFunction. + +Variable A: Type. +Variable f: nat -> A. + +CoFixpoint memo_make (n:nat) : Stream A := Cons (f n) (memo_make (S n)). + +Definition memo_list := memo_make 0. + +Fixpoint memo_get (n:nat) (l:Stream A) : A := + match n with + | O => hd l + | S n1 => memo_get n1 (tl l) + end. + +Theorem memo_get_correct: forall n, memo_get n memo_list = f n. +Proof. +assert (F1: forall n m, memo_get n (memo_make m) = f (n + m)). + induction n as [| n Hrec]; try (intros m; refine (refl_equal _)). + intros m; simpl; rewrite Hrec. + rewrite plus_n_Sm; auto. +intros n; apply trans_equal with (f (n + 0)); try exact (F1 n 0). +rewrite <- plus_n_O; auto. +Qed. + +(** Building with possible sharing using a iterator [g] : + We now suppose in addition that [f n] is in fact the [n]-th + iterate of a function [g]. +*) + +Variable g: A -> A. + +Hypothesis Hg_correct: forall n, f (S n) = g (f n). + +CoFixpoint imemo_make (fn:A) : Stream A := + let fn1 := g fn in + Cons fn1 (imemo_make fn1). + +Definition imemo_list := let f0 := f 0 in + Cons f0 (imemo_make f0). + +Theorem imemo_get_correct: forall n, memo_get n imemo_list = f n. +Proof. +assert (F1: forall n m, + memo_get n (imemo_make (f m)) = f (S (n + m))). + induction n as [| n Hrec]; try (intros m; exact (sym_equal (Hg_correct m))). + simpl; intros m; rewrite <- Hg_correct; rewrite Hrec; rewrite <- plus_n_Sm; auto. +destruct n as [| n]; try apply refl_equal. +unfold imemo_list; simpl; rewrite F1. +rewrite <- plus_n_O; auto. +Qed. + +End MemoFunction. + +(** For a dependent function, the previous solution is + reused thanks to a temporarly hiding of the dependency + in a "container" [memo_val]. *) + +Section DependentMemoFunction. + +Variable A: nat -> Type. +Variable f: forall n, A n. + +Inductive memo_val: Type := + memo_mval: forall n, A n -> memo_val. + +Fixpoint is_eq (n m : nat) {struct n}: {n = m} + {True} := + match n, m return {n = m} + {True} with + | 0, 0 =>left True (refl_equal 0) + | 0, S m1 => right (0 = S m1) I + | S n1, 0 => right (S n1 = 0) I + | S n1, S m1 => + match is_eq n1 m1 with + | left H => left True (f_equal S H) + | right _ => right (S n1 = S m1) I + end + end. + +Definition memo_get_val n (v: memo_val): A n := +match v with +| memo_mval m x => + match is_eq n m with + | left H => + match H in (@eq _ _ y) return (A y -> A n) with + | refl_equal => fun v1 : A n => v1 + end + | right _ => fun _ : A m => f n + end x +end. + +Let mf n := memo_mval n (f n). + +Definition dmemo_list := memo_list _ mf. + +Definition dmemo_get n l := memo_get_val n (memo_get _ n l). + +Theorem dmemo_get_correct: forall n, dmemo_get n dmemo_list = f n. +Proof. +intros n; unfold dmemo_get, dmemo_list. +rewrite (memo_get_correct memo_val mf n); simpl. +case (is_eq n n); simpl; auto; intros e. +assert (e = refl_equal n). + apply eq_proofs_unicity. + induction x as [| x Hx]; destruct y as [| y]. + left; auto. + right; intros HH; discriminate HH. + right; intros HH; discriminate HH. + case (Hx y). + intros HH; left; case HH; auto. + intros HH; right; intros HH1; case HH. + injection HH1; auto. +rewrite H; auto. +Qed. + +(** Finally, a version with both dependency and iterator *) + +Variable g: forall n, A n -> A (S n). + +Hypothesis Hg_correct: forall n, f (S n) = g n (f n). + +Let mg v := match v with + memo_mval n1 v1 => memo_mval (S n1) (g n1 v1) end. + +Definition dimemo_list := imemo_list _ mf mg. + +Theorem dimemo_get_correct: forall n, dmemo_get n dimemo_list = f n. +Proof. +intros n; unfold dmemo_get, dimemo_list. +rewrite (imemo_get_correct memo_val mf mg); simpl. +case (is_eq n n); simpl; auto; intros e. +assert (e = refl_equal n). + apply eq_proofs_unicity. + induction x as [| x Hx]; destruct y as [| y]. + left; auto. + right; intros HH; discriminate HH. + right; intros HH; discriminate HH. + case (Hx y). + intros HH; left; case HH; auto. + intros HH; right; intros HH1; case HH. + injection HH1; auto. +rewrite H; auto. +intros n1; unfold mf; rewrite Hg_correct; auto. +Qed. + +End DependentMemoFunction. + +(** An example with the memo function on factorial *) + +(* +Require Import ZArith. +Open Scope Z_scope. + +Fixpoint tfact (n: nat) := + match n with + | O => 1 + | S n1 => Z_of_nat n * tfact n1 + end. + +Definition lfact_list := + dimemo_list _ tfact (fun n z => (Z_of_nat (S n) * z)). + +Definition lfact n := dmemo_get _ tfact n lfact_list. + +Theorem lfact_correct n: lfact n = tfact n. +Proof. +intros n; unfold lfact, lfact_list. +rewrite dimemo_get_correct; auto. +Qed. + +Fixpoint nop p := + match p with + | xH => 0 + | xI p1 => nop p1 + | xO p1 => nop p1 + end. + +Fixpoint test z := + match z with + | Z0 => 0 + | Zpos p1 => nop p1 + | Zneg p1 => nop p1 + end. + +Time Eval vm_compute in test (lfact 2000). +Time Eval vm_compute in test (lfact 2000). +Time Eval vm_compute in test (lfact 1500). +Time Eval vm_compute in (lfact 1500). +*) + diff --git a/theories/Lists/Streams.v b/theories/Lists/Streams.v index 7bc6a09d..49990502 100644 --- a/theories/Lists/Streams.v +++ b/theories/Lists/Streams.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Streams.v 8642 2006-03-17 10:09:02Z notin $ i*) +(*i $Id: Streams.v 9967 2007-07-11 15:25:03Z roconnor $ i*) Set Implicit Arguments. @@ -14,9 +14,9 @@ Set Implicit Arguments. Section Streams. -Variable A : Set. +Variable A : Type. -CoInductive Stream : Set := +CoInductive Stream : Type := Cons : A -> Stream -> Stream. @@ -146,6 +146,15 @@ Inductive Exists ( x: Stream ) : Prop := CoInductive ForAll (x: Stream) : Prop := HereAndFurther : P x -> ForAll (tl x) -> ForAll x. +Lemma ForAll_Str_nth_tl : forall m x, ForAll x -> ForAll (Str_nth_tl m x). +Proof. +induction m. + tauto. +intros x [_ H]. +simpl. +apply IHm. +assumption. +Qed. Section Co_Induction_ForAll. Variable Inv : Stream -> Prop. @@ -162,15 +171,78 @@ End Stream_Properties. End Streams. Section Map. -Variables A B : Set. +Variables A B : Type. Variable f : A -> B. CoFixpoint map (s:Stream A) : Stream B := Cons (f (hd s)) (map (tl s)). + +Lemma Str_nth_tl_map : forall n s, Str_nth_tl n (map s)= map (Str_nth_tl n s). +Proof. +induction n. +reflexivity. +simpl. +intros s. +apply IHn. +Qed. + +Lemma Str_nth_map : forall n s, Str_nth n (map s)= f (Str_nth n s). +Proof. +intros n s. +unfold Str_nth. +rewrite Str_nth_tl_map. +reflexivity. +Qed. + +Lemma ForAll_map : forall (P:Stream B -> Prop) (S:Stream A), ForAll (fun s => P +(map s)) S <-> ForAll P (map S). +Proof. +intros P S. +split; generalize S; clear S; cofix; intros S; constructor; +destruct H as [H0 H]; firstorder. +Qed. + +Lemma Exists_map : forall (P:Stream B -> Prop) (S:Stream A), Exists (fun s => P +(map s)) S -> Exists P (map S). +Proof. +intros P S H. +(induction H;[left|right]); firstorder. +Defined. + End Map. Section Constant_Stream. -Variable A : Set. +Variable A : Type. Variable a : A. CoFixpoint const : Stream A := Cons a const. End Constant_Stream. -Unset Implicit Arguments.
\ No newline at end of file +Section Zip. + +Variable A B C : Type. +Variable f: A -> B -> C. + +CoFixpoint zipWith (a:Stream A) (b:Stream B) : Stream C := +Cons (f (hd a) (hd b)) (zipWith (tl a) (tl b)). + +Lemma Str_nth_tl_zipWith : forall n (a:Stream A) (b:Stream B), + Str_nth_tl n (zipWith a b)= zipWith (Str_nth_tl n a) (Str_nth_tl n b). +Proof. +induction n. +reflexivity. +intros [x xs] [y ys]. +unfold Str_nth in *. +simpl in *. +apply IHn. +Qed. + +Lemma Str_nth_zipWith : forall n (a:Stream A) (b:Stream B), Str_nth n (zipWith a + b)= f (Str_nth n a) (Str_nth n b). +Proof. +intros. +unfold Str_nth. +rewrite Str_nth_tl_zipWith. +reflexivity. +Qed. + +End Zip. + +Unset Implicit Arguments. diff --git a/theories/Logic/ChoiceFacts.v b/theories/Logic/ChoiceFacts.v index 3b066cfc..3d434b37 100644 --- a/theories/Logic/ChoiceFacts.v +++ b/theories/Logic/ChoiceFacts.v @@ -1,4 +1,3 @@ -(* -*- coding: utf-8 -*- *) (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) (* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *) @@ -7,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: ChoiceFacts.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: ChoiceFacts.v 10756 2008-04-04 17:10:45Z herbelin $ i*) (** Some facts and definitions concerning choice and description in intuitionistic logic. @@ -30,7 +29,7 @@ description principles - OAC_rel = "omniscient" relational form of the (non extensional) axiom of choice - OAC_fun = "omniscient" functional form of the (non extensional) axiom of choice - (called AC* in Bell [Bell]) + (called AC* in Bell [[Bell]]) - OAC! - ID_iota = intuitionistic definite description @@ -44,13 +43,15 @@ description principles (an unconstrained generalisation of the constructive principle of independence of premises) - Drinker = drinker's paradox (small form) - (called Ex in Bell [Bell]) + (called Ex in Bell [[Bell]]) We let also -IPL_2^2 = 2nd-order impredicative, 2nd-order functional minimal predicate logic -IPL_2 = 2nd-order impredicative minimal predicate logic +IPL_2 = 2nd-order impredicative minimal predicate logic (with ex. quant.) IPL^2 = 2nd-order functional minimal predicate logic (with ex. quant.) +IPL_2^2 = 2nd-order impredicative, 2nd-order functional minimal pred. logic (with ex. quant.) + +with no prerequisite on the non-emptyness of domains Table of contents @@ -58,24 +59,26 @@ Table of contents 2. IPL_2^2 |- AC_rel + AC! = AC_fun -3. 1. AC_rel + PI -> GAC_rel and PL_2 |- AC_rel + IGP -> GAC_rel and GAC_rel = OAC_rel +3.1. typed IPL_2 + Sigma-types + PI |- AC_rel = GAC_rel and IPL_2 |- AC_rel + IGP -> GAC_rel and IPL_2 |- GAC_rel = OAC_rel + +3.2. IPL^2 |- AC_fun + IGP = GAC_fun = OAC_fun = AC_fun + Drinker -4. 2. IPL^2 |- AC_fun + IGP = GAC_fun = OAC_fun = AC_fun + Drinker +3.3. D_iota -> ID_iota and D_epsilon <-> ID_epsilon + Drinker -5. Derivability of choice for decidable relations with well-ordered codomain +4. Derivability of choice for decidable relations with well-ordered codomain -6. Equivalence of choices on dependent or non dependent functional types +5. Equivalence of choices on dependent or non dependent functional types -7. Non contradiction of constructive descriptions wrt functional choices +6. Non contradiction of constructive descriptions wrt functional choices -8. Definite description transports classical logic to the computational world +7. Definite description transports classical logic to the computational world References: -[Bell] John L. Bell, Choice principles in intuitionistic set theory, +[[Bell]] John L. Bell, Choice principles in intuitionistic set theory, unpublished. -[Bell93] John L. Bell, Hilbert's Epsilon Operator in Intuitionistic +[[Bell93]] John L. Bell, Hilbert's Epsilon Operator in Intuitionistic Type Theories, Mathematical Logic Quarterly, volume 39, 1993. [Carlstrøm05] Jesper Carlstrøm, Interpreting descriptions in @@ -84,8 +87,6 @@ intentional type theory, Journal of Symbolic Logic 70(2):488-514, 2005. Set Implicit Arguments. -Notation Local "'inhabited' A" := A (at level 10, only parsing). - (**********************************************************************) (** * Definitions *) @@ -95,9 +96,9 @@ Section ChoiceSchemes. Variables A B :Type. -Variables P:A->Prop. +Variable P:A->Prop. -Variables R:A->B->Prop. +Variable R:A->B->Prop. (** ** Constructive choice and description *) @@ -183,15 +184,15 @@ Definition OmniscientFunctionalChoice_on := (** D_epsilon *) -Definition ClassicalIndefiniteDescription := +Definition EpsilonStatement_on := forall P:A->Prop, - A -> { x:A | (exists x, P x) -> P x }. + inhabited A -> { x:A | (exists x, P x) -> P x }. (** D_iota *) -Definition ClassicalDefiniteDescription := +Definition IotaStatement_on := forall P:A->Prop, - A -> { x:A | (exists! x, P x) -> P x }. + inhabited A -> { x:A | (exists! x, P x) -> P x }. End ChoiceSchemes. @@ -223,6 +224,11 @@ Notation ConstructiveDefiniteDescription := Notation ConstructiveIndefiniteDescription := (forall A, ConstructiveIndefiniteDescription_on A). +Notation IotaStatement := + (forall A, IotaStatement_on A). +Notation EpsilonStatement := + (forall A, EpsilonStatement_on A). + (** Subclassical schemes *) Definition ProofIrrelevance := @@ -238,16 +244,17 @@ Definition SmallDrinker'sParadox := exists x, (exists x, P x) -> P x. (**********************************************************************) -(** * AC_rel + PDP = AC_fun +(** * AC_rel + AC! = AC_fun We show that the functional formulation of the axiom of Choice (usual formulation in type theory) is equivalent to its relational - formulation (only formulation of set theory) + the axiom of - (parametric) definite description (aka axiom of unique choice) *) + formulation (only formulation of set theory) + functional relation + reification (aka axiom of unique choice, or, principle of (parametric) + definite descriptions) *) (** This shows that the axiom of choice can be assumed (under its relational formulation) without known inconsistency with classical logic, - though definite description conflicts with classical logic *) + though functional relation reification conflicts with classical logic *) Lemma description_rel_choice_imp_funct_choice : forall A B : Type, @@ -289,7 +296,7 @@ Proof. exists f; exact H0. Qed. -Theorem FunChoice_Equiv_RelChoice_and_ParamDefinDescr : +Corollary FunChoice_Equiv_RelChoice_and_ParamDefinDescr : forall A B, FunctionalChoice_on A B <-> RelationalChoice_on A B /\ FunctionalRelReification_on A B. Proof. @@ -301,11 +308,13 @@ Proof. Qed. (**********************************************************************) -(** * Connection between the guarded, non guarded and descriptive choices and *) +(** * Connection between the guarded, non guarded and omniscient choices *) -(** We show that the guarded relational formulation of the axiom of Choice - comes from the non guarded formulation in presence either of the - independance of premises or proof-irrelevance *) +(** We show that the guarded formulations of the axiom of choice + are equivalent to their "omniscient" variant and comes from the non guarded + formulation in presence either of the independance of general premises + or subset types (themselves derivable from subtypes thanks to proof- + irrelevance) *) (**********************************************************************) (** ** AC_rel + PI -> GAC_rel and AC_rel + IGP -> GAC_rel and GAC_rel = OAC_rel *) @@ -352,9 +361,17 @@ Proof. exists R'; firstorder. Qed. +Lemma subset_types_imp_guarded_rel_choice_iff_rel_choice : + ProofIrrelevance -> (GuardedRelationalChoice <-> RelationalChoice). +Proof. + auto decomp using + guarded_rel_choice_imp_rel_choice, + rel_choice_and_proof_irrel_imp_guarded_rel_choice. +Qed. + (** OAC_rel = GAC_rel *) -Lemma guarded_iff_omniscient_rel_choice : +Corollary guarded_iff_omniscient_rel_choice : GuardedRelationalChoice <-> OmniscientRelationalChoice. Proof. split. @@ -378,6 +395,7 @@ Proof. exists (f tt); auto. Qed. + Lemma guarded_fun_choice_imp_fun_choice : GuardedFunctionalChoice -> FunctionalChoiceOnInhabitedSet. Proof. @@ -396,9 +414,19 @@ Proof. intro x; apply IndPrem; eauto. Qed. +Corollary fun_choice_and_indep_general_prem_iff_guarded_fun_choice : + FunctionalChoiceOnInhabitedSet /\ IndependenceOfGeneralPremises + <-> GuardedFunctionalChoice. +Proof. + auto decomp using + guarded_fun_choice_imp_indep_of_general_premises, + guarded_fun_choice_imp_fun_choice, + fun_choice_and_indep_general_prem_imp_guarded_fun_choice. +Qed. + (** AC_fun + Drinker = OAC_fun *) -(** This was already observed by Bell [Bell] *) +(** This was already observed by Bell [[Bell]] *) Lemma omniscient_fun_choice_imp_small_drinker : OmniscientFunctionalChoice -> SmallDrinker'sParadox. @@ -427,12 +455,22 @@ Proof. exists f; assumption. Qed. +Corollary fun_choice_and_small_drinker_iff_omniscient_fun_choice : + FunctionalChoiceOnInhabitedSet /\ SmallDrinker'sParadox + <-> OmniscientFunctionalChoice. +Proof. + auto decomp using + omniscient_fun_choice_imp_small_drinker, + omniscient_fun_choice_imp_fun_choice, + fun_choice_and_small_drinker_imp_omniscient_fun_choice. +Qed. + (** OAC_fun = GAC_fun *) (** This is derivable from the intuitionistic equivalence between IGP and Drinker but we give a direct proof *) -Lemma guarded_iff_omniscient_fun_choice : +Theorem guarded_iff_omniscient_fun_choice : GuardedFunctionalChoice <-> OmniscientFunctionalChoice. Proof. split. @@ -444,6 +482,57 @@ Proof. Qed. (**********************************************************************) +(** ** D_iota -> ID_iota and D_epsilon <-> ID_epsilon + Drinker *) + +(** D_iota -> ID_iota *) + +Lemma iota_imp_constructive_definite_description : + IotaStatement -> ConstructiveDefiniteDescription. +Proof. + intros D_iota A P H. + destruct D_iota with (P:=P) as (x,H1). + destruct H; red in H; auto. + exists x; apply H1; assumption. +Qed. + +(** ID_epsilon + Drinker <-> D_epsilon *) + +Lemma epsilon_imp_constructive_indefinite_description: + EpsilonStatement -> ConstructiveIndefiniteDescription. +Proof. + intros D_epsilon A P H. + destruct D_epsilon with (P:=P) as (x,H1). + destruct H; auto. + exists x; apply H1; assumption. +Qed. + +Lemma constructive_indefinite_description_and_small_drinker_imp_epsilon : + SmallDrinker'sParadox -> ConstructiveIndefiniteDescription -> + EpsilonStatement. +Proof. + intros Drinkers D_epsilon A P Inh; + apply D_epsilon; apply Drinkers; assumption. +Qed. + +Lemma epsilon_imp_small_drinker : + EpsilonStatement -> SmallDrinker'sParadox. +Proof. + intros D_epsilon A P Inh; edestruct D_epsilon; eauto. +Qed. + +Theorem constructive_indefinite_description_and_small_drinker_iff_epsilon : + (SmallDrinker'sParadox * ConstructiveIndefiniteDescription -> + EpsilonStatement) * + (EpsilonStatement -> + SmallDrinker'sParadox * ConstructiveIndefiniteDescription). +Proof. + auto decomp using + epsilon_imp_constructive_indefinite_description, + constructive_indefinite_description_and_small_drinker_imp_epsilon, + epsilon_imp_small_drinker. +Qed. + +(**********************************************************************) (** * Derivability of choice for decidable relations with well-ordered codomain *) (** Countable codomains, such as [nat], can be equipped with a @@ -457,45 +546,7 @@ Qed. *) Require Import Wf_nat. -Require Import Compare_dec. Require Import Decidable. -Require Import Arith. - -Definition has_unique_least_element (A:Type) (R:A->A->Prop) (P:A->Prop) := - exists! x, P x /\ forall x', P x' -> R x x'. - -Lemma dec_inh_nat_subset_has_unique_least_element : - forall P:nat->Prop, (forall n, P n \/ ~ P n) -> - (exists n, P n) -> has_unique_least_element le P. -Proof. - intros P Pdec (n0,HPn0). - assert - (forall n, (exists n', n'<n /\ P n' /\ forall n'', P n'' -> n'<=n'') - \/(forall n', P n' -> n<=n')). - induction n. - right. - intros n' Hn'. - apply le_O_n. - destruct IHn. - left; destruct H as (n', (Hlt', HPn')). - exists n'; split. - apply lt_S; assumption. - assumption. - destruct (Pdec n). - left; exists n; split. - apply lt_n_Sn. - split; assumption. - right. - intros n' Hltn'. - destruct (le_lt_eq_dec n n') as [Hltn|Heqn]. - apply H; assumption. - assumption. - destruct H0. - rewrite Heqn; assumption. - destruct (H n0) as [(n,(Hltn,(Hmin,Huniqn)))|]; [exists n | exists n0]; - repeat split; - assumption || intros n' (HPn',Hminn'); apply le_antisym; auto. -Qed. Definition FunctionalChoice_on_rel (A B:Type) (R:A->B->Prop) := (forall x:A, exists y : B, R x y) -> @@ -614,16 +665,24 @@ Proof. destruct Heq using eq_indd; trivial. Qed. +Corollary dep_iff_non_dep_functional_rel_reification : + FunctionalRelReification <-> DependentFunctionalRelReification. +Proof. + auto decomp using + non_dep_dep_functional_rel_reification, + dep_non_dep_functional_rel_reification. +Qed. + (**********************************************************************) (** * Non contradiction of constructive descriptions wrt functional axioms of choice *) (** ** Non contradiction of indefinite description *) -Lemma relative_non_contradiction_of_indefinite_desc : - (ConstructiveIndefiniteDescription -> False) - -> (FunctionalChoice -> False). +Lemma relative_non_contradiction_of_indefinite_descr : + forall C:Prop, (ConstructiveIndefiniteDescription -> C) + -> (FunctionalChoice -> C). Proof. - intros H AC_fun. + intros C H AC_fun. assert (AC_depfun := non_dep_dep_functional_choice AC_fun). pose (A0 := { A:Type & { P:A->Prop & exists x, P x }}). pose (B0 := fun x:A0 => projT1 x). @@ -632,11 +691,8 @@ Proof. destruct (AC_depfun A0 B0 R0 H0) as (f, Hf). apply H. intros A P H'. - exists (f (existT (fun _ => sigT _) A - (existT (fun P => exists x, P x) P H'))). - pose (Hf' := - Hf (existT (fun _ => sigT _) A - (existT (fun P => exists x, P x) P H'))). + exists (f (existT _ A (existT _ P H'))). + pose (Hf' := Hf (existT _ A (existT _ P H'))). assumption. Qed. @@ -652,10 +708,10 @@ Qed. (** ** Non contradiction of definite description *) Lemma relative_non_contradiction_of_definite_descr : - (ConstructiveDefiniteDescription -> False) - -> (FunctionalRelReification -> False). + forall C:Prop, (ConstructiveDefiniteDescription -> C) + -> (FunctionalRelReification -> C). Proof. - intros H FunReify. + intros C H FunReify. assert (DepFunReify := non_dep_dep_functional_rel_reification FunReify). pose (A0 := { A:Type & { P:A->Prop & exists! x, P x }}). pose (B0 := fun x:A0 => projT1 x). @@ -664,11 +720,8 @@ Proof. destruct (DepFunReify A0 B0 R0 H0) as (f, Hf). apply H. intros A P H'. - exists (f (existT (fun _ => sigT _) A - (existT (fun P => exists! x, P x) P H'))). - pose (Hf' := - Hf (existT (fun _ => sigT _) A - (existT (fun P => exists! x, P x) P H'))). + exists (f (existT _ A (existT _ P H'))). + pose (Hf' := Hf (existT _ A (existT _ P H'))). assumption. Qed. @@ -681,20 +734,37 @@ Proof. apply (proj2_sig (DefDescr B (R x) (H x))). Qed. +(** Remark, the following corollaries morally hold: + +Definition In_propositional_context (A:Type) := forall C:Prop, (A -> C) -> C. + +Corollary constructive_definite_descr_in_prop_context_iff_fun_reification : + In_propositional_context ConstructiveIndefiniteDescription + <-> FunctionalChoice. + +Corollary constructive_definite_descr_in_prop_context_iff_fun_reification : + In_propositional_context ConstructiveDefiniteDescription + <-> FunctionalRelReification. + +but expecting [FunctionalChoice] (resp. [FunctionalRelReification]) to +be applied on the same Type universes on both sides of the first +(resp. second) equivalence breaks the stratification of universes. +*) + (**********************************************************************) (** * Excluded-middle + definite description => computational excluded-middle *) -(** The idea for the following proof comes from [ChicliPottierSimpson02] *) +(** The idea for the following proof comes from [[ChicliPottierSimpson02]] *) (** Classical logic and axiom of unique choice (i.e. functional - relation reification), as shown in [ChicliPottierSimpson02], + relation reification), as shown in [[ChicliPottierSimpson02]], implies the double-negation of excluded-middle in [Set] (which is incompatible with the impredicativity of [Set]). We adapt the proof to show that constructive definite description transports excluded-middle from [Prop] to [Set]. - [ChicliPottierSimpson02] Laurent Chicli, Loïc Pottier, Carlos + [[ChicliPottierSimpson02]] Laurent Chicli, Loïc Pottier, Carlos Simpson, Mathematical Quotients and Quotient Types in Coq, Proceedings of TYPES 2002, Lecture Notes in Computer Science 2646, Springer Verlag. *) @@ -717,3 +787,13 @@ Proof. left; trivial. right; trivial. Qed. + +Corollary fun_reification_descr_computational_excluded_middle_in_prop_context : + FunctionalRelReification -> + (forall P:Prop, P \/ ~ P) -> + forall C:Prop, ((forall P:Prop, {P} + {~ P}) -> C) -> C. +Proof. + intros FunReify EM C; auto decomp using + constructive_definite_descr_excluded_middle, + (relative_non_contradiction_of_definite_descr (C:=C)). +Qed. diff --git a/theories/Logic/ClassicalChoice.v b/theories/Logic/ClassicalChoice.v index bb8186ae..f9b59a6a 100644 --- a/theories/Logic/ClassicalChoice.v +++ b/theories/Logic/ClassicalChoice.v @@ -6,11 +6,17 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: ClassicalChoice.v 8892 2006-06-04 17:59:53Z herbelin $ i*) +(*i $Id: ClassicalChoice.v 10170 2007-10-03 14:41:25Z herbelin $ i*) -(** This file provides classical logic, and functional choice *) +(** This file provides classical logic and functional choice; this + especially provides both indefinite descriptions and choice functions + but this is weaker than providing epsilon operator and classical logic + as the indefinite descriptions provided by the axiom of choice can + be used only in a propositional context (especially, they cannot + be used to build choice functions outside the scope of a theorem + proof) *) -(** This file extends ClassicalUniqueChoice.v with the axiom of choice. +(** This file extends ClassicalUniqueChoice.v with full choice. As ClassicalUniqueChoice.v, it implies the double-negation of excluded-middle in [Set] and leads to a classical world populated with non computable functions. Especially it conflicts with the diff --git a/theories/Logic/ClassicalDescription.v b/theories/Logic/ClassicalDescription.v index 1f1c34bf..3737abf6 100644 --- a/theories/Logic/ClassicalDescription.v +++ b/theories/Logic/ClassicalDescription.v @@ -6,14 +6,15 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: ClassicalDescription.v 9514 2007-01-22 14:58:50Z herbelin $ i*) +(*i $Id: ClassicalDescription.v 10170 2007-10-03 14:41:25Z herbelin $ i*) -(** This file provides classical logic and definite description *) +(** This file provides classical logic and definite description, which is + equivalent to providing classical logic and Church's iota operator *) -(** Classical definite description operator (i.e. iota) implies - excluded-middle in [Set] and leads to a classical world populated - with non computable functions. It conflicts with the - impredicativity of [Set] *) +(** Classical logic and definite descriptions implies excluded-middle + in [Set] and leads to a classical world populated with non + computable functions. It conflicts with the impredicativity of + [Set] *) Set Implicit Arguments. diff --git a/theories/Logic/ClassicalEpsilon.v b/theories/Logic/ClassicalEpsilon.v index 6d0a9c77..2a4de511 100644 --- a/theories/Logic/ClassicalEpsilon.v +++ b/theories/Logic/ClassicalEpsilon.v @@ -6,12 +6,12 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: ClassicalEpsilon.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: ClassicalEpsilon.v 10170 2007-10-03 14:41:25Z herbelin $ i*) -(** This file provides classical logic and indefinite description - (Hilbert's epsilon operator) *) +(** This file provides classical logic and indefinite description under + the form of Hilbert's epsilon operator *) -(** Classical epsilon's operator (i.e. indefinite description) implies +(** Hilbert's epsilon operator and classical logic implies excluded-middle in [Set] and leads to a classical world populated with non computable functions. It conflicts with the impredicativity of [Set] *) diff --git a/theories/Logic/ClassicalFacts.v b/theories/Logic/ClassicalFacts.v index dd911db6..734de52d 100644 --- a/theories/Logic/ClassicalFacts.v +++ b/theories/Logic/ClassicalFacts.v @@ -7,7 +7,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: ClassicalFacts.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: ClassicalFacts.v 10156 2007-09-30 19:02:14Z herbelin $ i*) (** Some facts and definitions about classical logic @@ -31,8 +31,8 @@ Table of contents: 3.1. Weak excluded middle -3.2. Gödel-Dummet axiom and right distributivity of implication over - disjunction +3.2. Gödel-Dummett axiom and right distributivity of implication over + disjunction 3 3. Independence of general premises and drinker's paradox @@ -91,6 +91,17 @@ Proof. right; apply (Ext A False); split; [ exact H | apply False_ind ]. Qed. +(** A weakest form of propositional extensionality: extensionality for + provable propositions only *) + +Definition provable_prop_extensionality := forall A:Prop, A -> A = True. + +Lemma provable_prop_ext : + prop_extensionality -> provable_prop_extensionality. +Proof. + intros Ext A Ha; apply Ext; split; trivial. +Qed. + (************************************************************************) (** * Classical logic and proof-irrelevance *) @@ -105,6 +116,7 @@ Qed. (just take the identity), which implies the existence of a fixpoint operator in [A] (e.g. take the Y combinator of lambda-calculus) + *) Definition inhabited (A:Prop) := A. @@ -143,6 +155,10 @@ Proof. reflexivity. Qed. +(** Remark: [prop_extensionality] can be replaced in lemma [ext_prop_fixpoint] + by the weakest property [provable_prop_extensionality]. +*) + (************************************************************************) (** ** CC |- prop_ext /\ dep elim on bool -> proof-irrelevance *) @@ -230,6 +246,11 @@ Section Proof_irrelevance_Prop_Ext_CC. End Proof_irrelevance_Prop_Ext_CC. +(** Remark: [prop_extensionality] can be replaced in lemma + [ext_prop_dep_proof_irrel_gen] by the weakest property + [provable_prop_extensionality]. +*) + (************************************************************************) (** ** CIC |- prop. ext. -> proof-irrelevance *) @@ -396,7 +417,7 @@ End Proof_irrelevance_CCI. (** We show the following increasing in the strength of axioms: - weak excluded-middle - - right distributivity of implication over disjunction and Gödel-Dummet axiom + - right distributivity of implication over disjunction and Gödel-Dummett axiom - independence of general premises and drinker's paradox - excluded-middle *) @@ -533,7 +554,11 @@ Proof. Qed. (** Independence of general premises is weaker than (generalized) - excluded middle *) + excluded middle + +Remark: generalized excluded middle is preferred here to avoid relying on +the "ex falso quodlibet" property (i.e. [False -> forall A, A]) +*) Definition generalized_excluded_middle := forall A B:Prop, A \/ (A -> B). diff --git a/theories/Logic/ClassicalUniqueChoice.v b/theories/Logic/ClassicalUniqueChoice.v index 28d32fcc..bb846aa6 100644 --- a/theories/Logic/ClassicalUniqueChoice.v +++ b/theories/Logic/ClassicalUniqueChoice.v @@ -6,9 +6,13 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: ClassicalUniqueChoice.v 9026 2006-07-06 15:16:20Z herbelin $ i*) +(*i $Id: ClassicalUniqueChoice.v 10170 2007-10-03 14:41:25Z herbelin $ i*) -(** This file provides classical logic and unique choice *) +(** This file provides classical logic and unique choice; this is + weaker than providing iota operator and classical logic as the + definite descriptions provided by the axiom of unique choice can + be used only in a propositional context (especially, they cannot + be used to build functions outside the scope of a theorem proof) *) (** Classical logic and unique choice, as shown in [ChicliPottierSimpson02], implies the double-negation of diff --git a/theories/Logic/ConstructiveEpsilon.v b/theories/Logic/ConstructiveEpsilon.v index 61e377ea..f1503d24 100644 --- a/theories/Logic/ConstructiveEpsilon.v +++ b/theories/Logic/ConstructiveEpsilon.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id:$ i*) +(*i $Id: ConstructiveEpsilon.v 10739 2008-04-01 14:45:20Z herbelin $ i*) (** This module proves the constructive description schema, which infers the sigma-existence (i.e., [Set]-existence) of a witness to a @@ -20,17 +20,19 @@ show [{n : nat | P n}]. However, one can perform a recursion on an inductive predicate in sort [Prop] so that the returning type of the recursion is in [Set]. This trick is described in Coq'Art book, Sect. 14.2.3 and 15.4. In particular, this trick is used in the proof of -[Acc_iter] in the module Coq.Init.Wf. There, recursion is done on an +[Fix_F] in the module Coq.Init.Wf. There, recursion is done on an inductive predicate [Acc] and the resulting type is in [Type]. The predicate [Acc] delineates elements that are accessible via a given relation [R]. An element is accessible if there are no infinite [R]-descending chains starting from it. -To use [Acc_iter], we define a relation R and prove that if [exists n, +To use [Fix_F], we define a relation R and prove that if [exists n, P n] then 0 is accessible with respect to R. Then, by induction on the definition of [Acc R 0], we show [{n : nat | P n}]. *) +(** Based on ideas from Benjamin Werner and Jean-François Monin *) + (** Contributed by Yevgeniy Makarov *) Require Import Arith. @@ -49,7 +51,8 @@ numbers we try. Namely, [y] is [R]-less then [x] if we try [y] after infinite [R]-descending chain from 0 is equivalent to the termination of our searching algorithm. *) -Let R (x y : nat) := (x = S y /\ ~ P y). +Let R (x y : nat) : Prop := x = S y /\ ~ P y. + Notation Local "'acc' x" := (Acc R x) (at level 10). Lemma P_implies_acc : forall x : nat, P x -> acc x. @@ -78,7 +81,7 @@ Defined. Theorem acc_implies_P_eventually : acc 0 -> {n : nat | P n}. Proof. -intros Acc_0. pattern 0. apply Acc_iter with (R := R); [| assumption]. +intros Acc_0. pattern 0. apply Fix_F with (R := R); [| assumption]. clear Acc_0; intros x IH. destruct (P_decidable x) as [Px | not_Px]. exists x; simpl; assumption. @@ -102,7 +105,7 @@ Section ConstructiveEpsilon. there are functions [f : A -> nat] and [g : nat -> A] such that [g] is a left inverse of [f]. *) -Variable A : Type. +Variable A : Set. Variable f : A -> nat. Variable g : nat -> A. @@ -132,24 +135,11 @@ Proof. intros; apply constructive_indefinite_description; firstorder. Defined. -Definition epsilon (E : exists x : A, P x) : A +Definition constructive_epsilon (E : exists x : A, P x) : A := proj1_sig (constructive_indefinite_description E). -Definition epsilon_spec (E : (exists x, P x)) : P (epsilon E) +Definition constructive_epsilon_spec (E : (exists x, P x)) : P (constructive_epsilon E) := proj2_sig (constructive_indefinite_description E). End ConstructiveEpsilon. -Theorem choice : - forall (A B : Type) (f : B -> nat) (g : nat -> B), - (forall x : B, g (f x) = x) -> - forall (R : A -> B -> Prop), - (forall (x : A) (y : B), {R x y} + {~ R x y}) -> - (forall x : A, exists y : B, R x y) -> - (exists f : A -> B, forall x : A, R x (f x)). -Proof. -intros A B f g gof_eq_id R R_dec H. -exists (fun x : A => epsilon B f g gof_eq_id (R x) (R_dec x) (H x)). -intro x. -apply (epsilon_spec B f g gof_eq_id (R x) (R_dec x) (H x)). -Qed. diff --git a/theories/Logic/Decidable.v b/theories/Logic/Decidable.v index 8317f6bb..a7c098e8 100644 --- a/theories/Logic/Decidable.v +++ b/theories/Logic/Decidable.v @@ -5,56 +5,191 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Decidable.v 5920 2004-07-16 20:01:26Z herbelin $ i*) +(*i $Id: Decidable.v 10500 2008-02-02 15:51:00Z letouzey $ i*) (** Properties of decidable propositions *) Definition decidable (P:Prop) := P \/ ~ P. Theorem dec_not_not : forall P:Prop, decidable P -> (~ P -> False) -> P. -unfold decidable in |- *; tauto. +Proof. +unfold decidable; tauto. Qed. Theorem dec_True : decidable True. -unfold decidable in |- *; auto. +Proof. +unfold decidable; auto. Qed. Theorem dec_False : decidable False. -unfold decidable, not in |- *; auto. +Proof. +unfold decidable, not; auto. Qed. Theorem dec_or : forall A B:Prop, decidable A -> decidable B -> decidable (A \/ B). -unfold decidable in |- *; tauto. +Proof. +unfold decidable; tauto. Qed. Theorem dec_and : forall A B:Prop, decidable A -> decidable B -> decidable (A /\ B). -unfold decidable in |- *; tauto. +Proof. +unfold decidable; tauto. Qed. Theorem dec_not : forall A:Prop, decidable A -> decidable (~ A). -unfold decidable in |- *; tauto. +Proof. +unfold decidable; tauto. Qed. Theorem dec_imp : forall A B:Prop, decidable A -> decidable B -> decidable (A -> B). -unfold decidable in |- *; tauto. +Proof. +unfold decidable; tauto. +Qed. + +Theorem dec_iff : + forall A B:Prop, decidable A -> decidable B -> decidable (A<->B). +Proof. +unfold decidable; tauto. Qed. Theorem not_not : forall P:Prop, decidable P -> ~ ~ P -> P. -unfold decidable in |- *; tauto. Qed. +Proof. +unfold decidable; tauto. +Qed. Theorem not_or : forall A B:Prop, ~ (A \/ B) -> ~ A /\ ~ B. -tauto. Qed. +Proof. +tauto. +Qed. Theorem not_and : forall A B:Prop, decidable A -> ~ (A /\ B) -> ~ A \/ ~ B. -unfold decidable in |- *; tauto. Qed. +Proof. +unfold decidable; tauto. +Qed. Theorem not_imp : forall A B:Prop, decidable A -> ~ (A -> B) -> A /\ ~ B. -unfold decidable in |- *; tauto. +Proof. +unfold decidable; tauto. Qed. Theorem imp_simp : forall A B:Prop, decidable A -> (A -> B) -> ~ A \/ B. -unfold decidable in |- *; tauto. +Proof. +unfold decidable; tauto. +Qed. + +(** Results formulated with iff, used in FSetDecide. + Negation are expanded since it is unclear whether setoid rewrite + will always perform conversion. *) + +(** We begin with lemmas that, when read from left to right, + can be understood as ways to eliminate uses of [not]. *) + +Theorem not_true_iff : (True -> False) <-> False. +Proof. +tauto. +Qed. + +Theorem not_false_iff : (False -> False) <-> True. +Proof. +tauto. +Qed. + +Theorem not_not_iff : forall A:Prop, decidable A -> + (((A -> False) -> False) <-> A). +Proof. +unfold decidable; tauto. +Qed. + +Theorem contrapositive : forall A B:Prop, decidable A -> + (((A -> False) -> (B -> False)) <-> (B -> A)). +Proof. +unfold decidable; tauto. +Qed. + +Lemma or_not_l_iff_1 : forall A B: Prop, decidable A -> + ((A -> False) \/ B <-> (A -> B)). +Proof. +unfold decidable. tauto. +Qed. + +Lemma or_not_l_iff_2 : forall A B: Prop, decidable B -> + ((A -> False) \/ B <-> (A -> B)). +Proof. +unfold decidable. tauto. +Qed. + +Lemma or_not_r_iff_1 : forall A B: Prop, decidable A -> + (A \/ (B -> False) <-> (B -> A)). +Proof. +unfold decidable. tauto. Qed. + +Lemma or_not_r_iff_2 : forall A B: Prop, decidable B -> + (A \/ (B -> False) <-> (B -> A)). +Proof. +unfold decidable. tauto. +Qed. + +Lemma imp_not_l : forall A B: Prop, decidable A -> + (((A -> False) -> B) <-> (A \/ B)). +Proof. +unfold decidable. tauto. +Qed. + + +(** Moving Negations Around: + We have four lemmas that, when read from left to right, + describe how to push negations toward the leaves of a + proposition and, when read from right to left, describe + how to pull negations toward the top of a proposition. *) + +Theorem not_or_iff : forall A B:Prop, + (A \/ B -> False) <-> (A -> False) /\ (B -> False). +Proof. +tauto. +Qed. + +Lemma not_and_iff : forall A B:Prop, + (A /\ B -> False) <-> (A -> B -> False). +Proof. +tauto. +Qed. + +Lemma not_imp_iff : forall A B:Prop, decidable A -> + (((A -> B) -> False) <-> A /\ (B -> False)). +Proof. +unfold decidable. tauto. +Qed. + +Lemma not_imp_rev_iff : forall A B : Prop, decidable A -> + (((A -> B) -> False) <-> (B -> False) /\ A). +Proof. +unfold decidable. tauto. +Qed. + + + +(** With the following hint database, we can leverage [auto] to check + decidability of propositions. *) + +Hint Resolve dec_True dec_False dec_or dec_and dec_imp dec_not dec_iff + : decidable_prop. + +(** [solve_decidable using lib] will solve goals about the + decidability of a proposition, assisted by an auxiliary + database of lemmas. The database is intended to contain + lemmas stating the decidability of base propositions, + (e.g., the decidability of equality on a particular + inductive type). *) + +Tactic Notation "solve_decidable" "using" ident(db) := + match goal with + | |- decidable _ => + solve [ auto 100 with decidable_prop db ] + end. + +Tactic Notation "solve_decidable" := + solve_decidable using core. diff --git a/theories/Logic/DecidableType.v b/theories/Logic/DecidableType.v index a38b111f..a65e2c52 100644 --- a/theories/Logic/DecidableType.v +++ b/theories/Logic/DecidableType.v @@ -6,19 +6,36 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: DecidableType.v 8933 2006-06-09 14:08:38Z herbelin $ *) +(* $Id: DecidableType.v 10616 2008-03-04 17:33:35Z letouzey $ *) Require Export SetoidList. Set Implicit Arguments. Unset Strict Implicit. +(** * Types with Equalities, and nothing more (for subtyping purpose) *) + +Module Type EqualityType. + + Parameter Inline t : Type. + + Parameter Inline eq : t -> t -> Prop. + + Axiom eq_refl : forall x : t, eq x x. + Axiom eq_sym : forall x y : t, eq x y -> eq y x. + Axiom eq_trans : forall x y z : t, eq x y -> eq y z -> eq x z. + + Hint Immediate eq_sym. + Hint Resolve eq_refl eq_trans. + +End EqualityType. + (** * Types with decidable Equalities (but no ordering) *) Module Type DecidableType. - Parameter t : Set. + Parameter Inline t : Type. - Parameter eq : t -> t -> Prop. + Parameter Inline eq : t -> t -> Prop. Axiom eq_refl : forall x : t, eq x x. Axiom eq_sym : forall x y : t, eq x y -> eq y x. @@ -37,7 +54,7 @@ Module KeyDecidableType(D:DecidableType). Import D. Section Elt. - Variable elt : Set. + Variable elt : Type. Notation key:=t. Definition eqk (p p':key*elt) := eq (fst p) (fst p'). diff --git a/theories/Logic/DecidableTypeEx.v b/theories/Logic/DecidableTypeEx.v index a4f99de2..9c928598 100644 --- a/theories/Logic/DecidableTypeEx.v +++ b/theories/Logic/DecidableTypeEx.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: DecidableTypeEx.v 8933 2006-06-09 14:08:38Z herbelin $ *) +(* $Id: DecidableTypeEx.v 10739 2008-04-01 14:45:20Z herbelin $ *) Require Import DecidableType OrderedType OrderedTypeEx. Set Implicit Arguments. @@ -18,7 +18,7 @@ Unset Strict Implicit. the equality is the usual one of Coq. *) Module Type UsualDecidableType. - Parameter t : Set. + Parameter Inline t : Type. Definition eq := @eq t. Definition eq_refl := @refl_equal t. Definition eq_sym := @sym_eq t. @@ -30,6 +30,22 @@ End UsualDecidableType. Module UDT_to_DT (U:UsualDecidableType) <: DecidableType := U. +(** an shortcut for easily building a UsualDecidableType *) + +Module Type MiniDecidableType. + Parameter Inline t : Type. + Parameter eq_dec : forall x y:t, { x=y }+{ x<>y }. +End MiniDecidableType. + +Module Make_UDT (M:MiniDecidableType) <: UsualDecidableType. + Definition t:=M.t. + Definition eq := @eq t. + Definition eq_refl := @refl_equal t. + Definition eq_sym := @sym_eq t. + Definition eq_trans := @trans_eq t. + Definition eq_dec := M.eq_dec. +End Make_UDT. + (** An OrderedType can be seen as a DecidableType *) Module OT_as_DT (O:OrderedType) <: DecidableType. @@ -48,3 +64,54 @@ Module Nat_as_DT <: UsualDecidableType := OT_as_DT (Nat_as_OT). Module Positive_as_DT <: UsualDecidableType := OT_as_DT (Positive_as_OT). Module N_as_DT <: UsualDecidableType := OT_as_DT (N_as_OT). Module Z_as_DT <: UsualDecidableType := OT_as_DT (Z_as_OT). + +(** From two decidable types, we can build a new DecidableType + over their cartesian product. *) + +Module PairDecidableType(D1 D2:DecidableType) <: DecidableType. + + Definition t := prod D1.t D2.t. + + Definition eq x y := D1.eq (fst x) (fst y) /\ D2.eq (snd x) (snd y). + + Lemma eq_refl : forall x : t, eq x x. + Proof. + intros (x1,x2); red; simpl; auto. + Qed. + + Lemma eq_sym : forall x y : t, eq x y -> eq y x. + Proof. + intros (x1,x2) (y1,y2); unfold eq; simpl; intuition. + Qed. + + Lemma eq_trans : forall x y z : t, eq x y -> eq y z -> eq x z. + Proof. + intros (x1,x2) (y1,y2) (z1,z2); unfold eq; simpl; intuition eauto. + Qed. + + Definition eq_dec : forall x y, { eq x y }+{ ~eq x y }. + Proof. + intros (x1,x2) (y1,y2); unfold eq; simpl. + destruct (D1.eq_dec x1 y1); destruct (D2.eq_dec x2 y2); intuition. + Defined. + +End PairDecidableType. + +(** Similarly for pairs of UsualDecidableType *) + +Module PairUsualDecidableType(D1 D2:UsualDecidableType) <: DecidableType. + Definition t := prod D1.t D2.t. + Definition eq := @eq t. + Definition eq_refl := @refl_equal t. + Definition eq_sym := @sym_eq t. + Definition eq_trans := @trans_eq t. + Definition eq_dec : forall x y, { eq x y }+{ ~eq x y }. + Proof. + intros (x1,x2) (y1,y2); + destruct (D1.eq_dec x1 y1); destruct (D2.eq_dec x2 y2); + unfold eq, D1.eq, D2.eq in *; simpl; + (left; f_equal; auto; fail) || + (right; intro H; injection H; auto). + Defined. + +End PairUsualDecidableType. diff --git a/theories/Logic/Description.v b/theories/Logic/Description.v new file mode 100644 index 00000000..962f2a2a --- /dev/null +++ b/theories/Logic/Description.v @@ -0,0 +1,21 @@ +(************************************************************************) +(* 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: Description.v 10170 2007-10-03 14:41:25Z herbelin $ i*) + +(** This file provides a constructive form of definite description; it + allows to build functions from the proof of their existence in any + context; this is weaker than Church's iota operator *) + +Require Import ChoiceFacts. + +Set Implicit Arguments. + +Axiom constructive_definite_description : + forall (A : Type) (P : A->Prop), + (exists! x, P x) -> { x : A | P x }. diff --git a/theories/Logic/Epsilon.v b/theories/Logic/Epsilon.v new file mode 100644 index 00000000..65d4d853 --- /dev/null +++ b/theories/Logic/Epsilon.v @@ -0,0 +1,72 @@ +(************************************************************************) +(* 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: Epsilon.v 10170 2007-10-03 14:41:25Z herbelin $ i*) + +(** This file provides indefinite description under the form of + Hilbert's epsilon operator; it does not assume classical logic. *) + +Require Import ChoiceFacts. + +Set Implicit Arguments. + +(** Hilbert's epsilon: operator and specification in one statement *) + +Axiom epsilon_statement : + forall (A : Type) (P : A->Prop), inhabited A -> + { x : A | (exists x, P x) -> P x }. + +Lemma constructive_indefinite_description : + forall (A : Type) (P : A->Prop), + (exists x, P x) -> { x : A | P x }. +Proof. + apply epsilon_imp_constructive_indefinite_description. + exact epsilon_statement. +Qed. + +Lemma small_drinkers'_paradox : + forall (A:Type) (P:A -> Prop), inhabited A -> + exists x, (exists x, P x) -> P x. +Proof. + apply epsilon_imp_small_drinker. + exact epsilon_statement. +Qed. + +Theorem iota_statement : + forall (A : Type) (P : A->Prop), inhabited A -> + { x : A | (exists! x : A, P x) -> P x }. +Proof. + intros; destruct epsilon_statement with (P:=P); firstorder. +Qed. + +Lemma constructive_definite_description : + forall (A : Type) (P : A->Prop), + (exists! x, P x) -> { x : A | P x }. +Proof. + apply iota_imp_constructive_definite_description. + exact iota_statement. +Qed. + +(** Hilbert's epsilon operator and its specification *) + +Definition epsilon (A : Type) (i:inhabited A) (P : A->Prop) : A + := proj1_sig (epsilon_statement P i). + +Definition epsilon_spec (A : Type) (i:inhabited A) (P : A->Prop) : + (exists x, P x) -> P (epsilon i P) + := proj2_sig (epsilon_statement P i). + +(** Church's iota operator and its specification *) + +Definition iota (A : Type) (i:inhabited A) (P : A->Prop) : A + := proj1_sig (iota_statement P i). + +Definition iota_spec (A : Type) (i:inhabited A) (P : A->Prop) : + (exists! x:A, P x) -> P (iota i P) + := proj2_sig (iota_statement P i). + diff --git a/theories/Logic/EqdepFacts.v b/theories/Logic/EqdepFacts.v index 94a577ca..844bff88 100644 --- a/theories/Logic/EqdepFacts.v +++ b/theories/Logic/EqdepFacts.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: EqdepFacts.v 9597 2007-02-06 19:44:05Z herbelin $ i*) +(*i $Id: EqdepFacts.v 11095 2008-06-10 19:36:10Z herbelin $ i*) (** This file defines dependent equality and shows its equivalence with equality on dependent pairs (inhabiting sigma-types). It derives @@ -104,7 +104,7 @@ Implicit Arguments eq_dep1 [U P]. (** Dependent equality is equivalent to equality on dependent pairs *) -Lemma eq_sigS_eq_dep : +Lemma eq_sigT_eq_dep : forall (U:Type) (P:U -> Type) (p q:U) (x:P p) (y:P q), existT P p x = existT P q y -> eq_dep p x q y. Proof. @@ -113,26 +113,19 @@ Proof. apply eq_dep_intro. Qed. +Notation eq_sigS_eq_dep := eq_sigT_eq_dep (only parsing). (* Compatibility *) + Lemma equiv_eqex_eqdep : forall (U:Type) (P:U -> Type) (p q:U) (x:P p) (y:P q), - existS P p x = existS P q y <-> eq_dep p x q y. + existT P p x = existT P q y <-> eq_dep p x q y. Proof. split. (* -> *) - apply eq_sigS_eq_dep. + apply eq_sigT_eq_dep. (* <- *) destruct 1; reflexivity. Qed. -Lemma eq_sigT_eq_dep : - forall (U:Type) (P:U -> Type) (p q:U) (x:P p) (y:P q), - existT P p x = existT P q y -> eq_dep p x q y. -Proof. - intros. - dependent rewrite H. - apply eq_dep_intro. -Qed. - Lemma eq_dep_eq_sigT : forall (U:Type) (P:U -> Type) (p q:U) (x:P p) (y:P q), eq_dep p x q y -> existT P p x = existT P q y. @@ -258,7 +251,7 @@ Section Corollaries. Proof. intro eq_dep_eq; red; intros. apply eq_dep_eq. - apply eq_sigS_eq_dep. + apply eq_sigT_eq_dep. assumption. Qed. @@ -270,7 +263,7 @@ Notation eq_dep_eq__inj_pairT2 := eq_dep_eq__inj_pair2. (************************************************************************) -(** *** C. Definition of the functor that builds properties of dependent equalities assuming axiom eq_rect_eq *) +(** * Definition of the functor that builds properties of dependent equalities assuming axiom eq_rect_eq *) Module Type EqdepElimination. diff --git a/theories/Logic/Eqdep_dec.v b/theories/Logic/Eqdep_dec.v index 103efd22..0281916e 100644 --- a/theories/Logic/Eqdep_dec.v +++ b/theories/Logic/Eqdep_dec.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Eqdep_dec.v 9597 2007-02-06 19:44:05Z herbelin $ i*) +(*i $Id: Eqdep_dec.v 10144 2007-09-26 15:12:17Z vsiles $ i*) (** We prove that there is only one proof of [x=x], i.e [refl_equal x]. This holds if the equality upon the set of [x] is decidable. @@ -158,6 +158,13 @@ Proof. apply (Streicher_K__eq_rect_eq A (K_dec_type eq_dec)). Qed. +(** We deduce the injectivity of dependent equality for decidable types *) +Theorem eq_dep_eq_dec : + forall A:Type, + (forall x y:A, {x = y} + {x <> y}) -> + forall (P:A->Type) (p:A) (x y:P p), eq_dep A P p x p y -> x = y. +Proof (fun A eq_dec => eq_rect_eq__eq_dep_eq A (eq_rect_eq_dec eq_dec)). + Unset Implicit Arguments. (************************************************************************) @@ -229,7 +236,7 @@ Module DecidableEqDep (M:DecidableType). End DecidableEqDep. (************************************************************************) -(** ** B Definition of the functor that builds properties of dependent equalities on decidable sets in Set *) +(** ** Definition of the functor that builds properties of dependent equalities on decidable sets in Set *) (** The signature of decidable sets in [Set] *) @@ -296,3 +303,15 @@ Module DecidableEqDepSet (M:DecidableSet). Notation inj_pairT2 := inj_pair2. End DecidableEqDepSet. + + (** From decidability to inj_pair2 **) +Lemma inj_pair2_eq_dec : forall A:Type, (forall x y:A, {x=y}+{x<>y}) -> + ( forall (P:A -> Type) (p:A) (x y:P p), existT P p x = existT P p y -> x = y ). +Proof. + intros A eq_dec. + apply eq_dep_eq__inj_pair2. + apply eq_rect_eq__eq_dep_eq. + unfold Eq_rect_eq. + apply eq_rect_eq_dec. + apply eq_dec. +Qed. diff --git a/theories/Logic/IndefiniteDescription.v b/theories/Logic/IndefiniteDescription.v new file mode 100644 index 00000000..740b889a --- /dev/null +++ b/theories/Logic/IndefiniteDescription.v @@ -0,0 +1,39 @@ +(************************************************************************) +(* 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: IndefiniteDescription.v 10170 2007-10-03 14:41:25Z herbelin $ i*) + +(** This file provides a constructive form of indefinite description that + allows to build choice functions; this is weaker than Hilbert's + epsilon operator (which implies weakly classical properties) but + stronger than the axiom of choice (which cannot be used outside + the context of a theorem proof). *) + +Require Import ChoiceFacts. + +Set Implicit Arguments. + +Axiom constructive_indefinite_description : + forall (A : Type) (P : A->Prop), + (exists x, P x) -> { x : A | P x }. + +Lemma constructive_definite_description : + forall (A : Type) (P : A->Prop), + (exists! x, P x) -> { x : A | P x }. +Proof. + intros; apply constructive_indefinite_description; firstorder. +Qed. + +Lemma functional_choice : + forall (A B : Type) (R:A->B->Prop), + (forall x : A, exists y : B, R x y) -> + (exists f : A->B, forall x : A, R x (f x)). +Proof. + apply constructive_indefinite_descr_fun_choice. + exact constructive_indefinite_description. +Qed. diff --git a/theories/Logic/JMeq.v b/theories/Logic/JMeq.v index 6a723e43..c3573ac3 100644 --- a/theories/Logic/JMeq.v +++ b/theories/Logic/JMeq.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: JMeq.v 9077 2006-08-24 08:44:32Z herbelin $ i*) +(*i $Id: JMeq.v 9849 2007-05-22 20:40:04Z herbelin $ i*) (** John Major's Equality as proposed by Conor McBride @@ -19,9 +19,12 @@ Set Implicit Arguments. +Unset Elimination Schemes. + Inductive JMeq (A:Type) (x:A) : forall B:Type, B -> Prop := JMeq_refl : JMeq x x. -Reset JMeq_rect. + +Set Elimination Schemes. Hint Resolve JMeq_refl. @@ -65,20 +68,42 @@ Lemma JMeq_rect_r : intros A x y P H H'; case JMeq_eq with (1 := sym_JMeq H'); trivial. Qed. -(** [JMeq] is equivalent to [(eq_dep Type [X]X)] *) +(** [JMeq] is equivalent to [eq_dep Type (fun X => X)] *) Require Import Eqdep. -Lemma JMeq_eq_dep : +Lemma JMeq_eq_dep_id : forall (A B:Type) (x:A) (y:B), JMeq x y -> eq_dep Type (fun X => X) A x B y. Proof. destruct 1. apply eq_dep_intro. Qed. -Lemma eq_dep_JMeq : +Lemma eq_dep_id_JMeq : forall (A B:Type) (x:A) (y:B), eq_dep Type (fun X => X) A x B y -> JMeq x y. Proof. destruct 1. -apply JMeq_refl. +apply JMeq_refl. +Qed. + +(** [eq_dep U P p x q y] is strictly finer than [JMeq (P p) x (P q) y] *) + +Lemma eq_dep_JMeq : + forall U P p x q y, eq_dep U P p x q y -> JMeq x y. +Proof. +destruct 1. +apply JMeq_refl. +Qed. + +Lemma eq_dep_strictly_stronger_JMeq : + exists U, exists P, exists p, exists q, exists x, exists y, + JMeq x y /\ ~ eq_dep U P p x q y. +Proof. +exists bool. exists (fun _ => True). exists true. exists false. +exists I. exists I. +split. +trivial. +intro H. +assert (true=false) by (destruct H; reflexivity). +discriminate. Qed. diff --git a/theories/Logic/SetIsType.v b/theories/Logic/SetIsType.v new file mode 100644 index 00000000..3286beb4 --- /dev/null +++ b/theories/Logic/SetIsType.v @@ -0,0 +1,17 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) + +(** * The Set universe seen as a synonym for Type *) + +(** After loading this file, Set becomes just another name for Type. + This allows to easily perform a Set-to-Type migration, or at least + test whether a development relies or not on specific features of + Set: simply insert some Require Export of this file at starting + points of the development and try to recompile... *) + +Notation "'Set'" := Type (only parsing).
\ No newline at end of file diff --git a/theories/NArith/BinNat.v b/theories/NArith/BinNat.v index 78353145..20dabed2 100644 --- a/theories/NArith/BinNat.v +++ b/theories/NArith/BinNat.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: BinNat.v 8771 2006-04-29 11:55:57Z letouzey $ i*) +(*i $Id: BinNat.v 10806 2008-04-16 23:51:06Z letouzey $ i*) Require Import BinPos. Unset Boxed Definitions. @@ -59,6 +59,16 @@ Definition Nsucc n := | Npos p => Npos (Psucc p) end. +(** Predecessor *) + +Definition Npred (n : N) := match n with +| N0 => N0 +| Npos p => match p with + | xH => N0 + | _ => Npos (Ppred p) + end +end. + (** Addition *) Definition Nplus n m := @@ -70,6 +80,21 @@ Definition Nplus n m := Infix "+" := Nplus : N_scope. +(** Subtraction *) + +Definition Nminus (n m : N) := +match n, m with +| N0, _ => N0 +| n, N0 => n +| Npos n', Npos m' => + match Pminus_mask n' m' with + | IsPos p => Npos p + | _ => N0 + end +end. + +Infix "-" := Nminus : N_scope. + (** Multiplication *) Definition Nmult n m := @@ -93,6 +118,28 @@ Definition Ncompare n m := Infix "?=" := Ncompare (at level 70, no associativity) : N_scope. +Definition Nlt (x y:N) := (x ?= y) = Lt. +Definition Ngt (x y:N) := (x ?= y) = Gt. +Definition Nle (x y:N) := (x ?= y) <> Gt. +Definition Nge (x y:N) := (x ?= y) <> Lt. + +Infix "<=" := Nle : N_scope. +Infix "<" := Nlt : N_scope. +Infix ">=" := Nge : N_scope. +Infix ">" := Ngt : N_scope. + +(** Min and max *) + +Definition Nmin (n n' : N) := match Ncompare n n' with + | Lt | Eq => n + | Gt => n' + end. + +Definition Nmax (n n' : N) := match Ncompare n n' with + | Lt | Eq => n' + | Gt => n + end. + (** convenient induction principles *) Lemma N_ind_double : @@ -123,15 +170,48 @@ Qed. (** Peano induction on binary natural numbers *) -Theorem Nind : - forall P:N -> Prop, - P N0 -> (forall n:N, P n -> P (Nsucc n)) -> forall n:N, P n. +Definition Nrect + (P : N -> Type) (a : P N0) + (f : forall n : N, P n -> P (Nsucc n)) (n : N) : P n := +let f' (p : positive) (x : P (Npos p)) := f (Npos p) x in +let P' (p : positive) := P (Npos p) in +match n return (P n) with +| N0 => a +| Npos p => Prect P' (f N0 a) f' p +end. + +Theorem Nrect_base : forall P a f, Nrect P a f N0 = a. +Proof. +intros P a f; simpl; reflexivity. +Qed. + +Theorem Nrect_step : forall P a f n, Nrect P a f (Nsucc n) = f n (Nrect P a f n). +Proof. +intros P a f; destruct n as [| p]; simpl; +[rewrite Prect_base | rewrite Prect_succ]; reflexivity. +Qed. + +Definition Nind (P : N -> Prop) := Nrect P. + +Definition Nrec (P : N -> Set) := Nrect P. + +Theorem Nrec_base : forall P a f, Nrec P a f N0 = a. Proof. -destruct n. - assumption. - apply Pind with (P := fun p => P (Npos p)). -exact (H0 N0 H). -intro p'; exact (H0 (Npos p')). +intros P a f; unfold Nrec; apply Nrect_base. +Qed. + +Theorem Nrec_step : forall P a f n, Nrec P a f (Nsucc n) = f n (Nrec P a f n). +Proof. +intros P a f; unfold Nrec; apply Nrect_step. +Qed. + +(** Properties of successor and predecessor *) + +Theorem Npred_succ : forall n : N, Npred (Nsucc n) = n. +Proof. +destruct n as [| p]; simpl. reflexivity. +case_eq (Psucc p); try (intros q H; rewrite <- H; now rewrite Ppred_succ). +intro H; false_hyp H Psucc_not_one. Qed. (** Properties of addition *) @@ -171,6 +251,11 @@ destruct n; destruct m. simpl in |- *; rewrite Pplus_succ_permute_l; reflexivity. Qed. +Theorem Nsucc_0 : forall n : N, Nsucc n <> N0. +Proof. +intro n; elim n; simpl Nsucc; intros; discriminate. +Qed. + Theorem Nsucc_inj : forall n m:N, Nsucc n = Nsucc m -> n = m. Proof. destruct n; destruct m; simpl in |- *; intro H; reflexivity || injection H; @@ -188,13 +273,51 @@ intro n; pattern n in |- *; apply Nind; clear n; simpl in |- *. apply IHn; apply Nsucc_inj; assumption. Qed. +(** Properties of subtraction. *) + +Lemma Nminus_N0_Nle : forall n n' : N, n - n' = N0 <-> n <= n'. +Proof. +destruct n as [| p]; destruct n' as [| q]; unfold Nle; simpl; +split; intro H; try discriminate; try reflexivity. +now elim H. +intro H1; apply Pminus_mask_Gt in H1. destruct H1 as [h [H1 _]]. +rewrite H1 in H; discriminate. +case_eq (Pcompare p q Eq); intro H1; rewrite H1 in H; try now elim H. +assert (H2 : p = q); [now apply Pcompare_Eq_eq |]. now rewrite H2, Pminus_mask_diag. +now rewrite Pminus_mask_Lt. +Qed. + +Theorem Nminus_0_r : forall n : N, n - N0 = n. +Proof. +now destruct n. +Qed. + +Theorem Nminus_succ_r : forall n m : N, n - (Nsucc m) = Npred (n - m). +Proof. +destruct n as [| p]; destruct m as [| q]; try reflexivity. +now destruct p. +simpl. rewrite Pminus_mask_succ_r, Pminus_mask_carry_spec. +now destruct (Pminus_mask p q) as [| r |]; [| destruct r |]. +Qed. + (** Properties of multiplication *) +Theorem Nmult_0_l : forall n:N, N0 * n = N0. +Proof. +reflexivity. +Qed. + Theorem Nmult_1_l : forall n:N, Npos 1 * n = n. Proof. destruct n; reflexivity. Qed. +Theorem Nmult_Sn_m : forall n m : N, (Nsucc n) * m = m + n * m. +Proof. +destruct n as [| n]; destruct m as [| m]; simpl; auto. +rewrite Pmult_Sn_m; reflexivity. +Qed. + Theorem Nmult_1_r : forall n:N, n * Npos 1%positive = n. Proof. destruct n; simpl in |- *; try reflexivity. @@ -233,13 +356,14 @@ destruct n; destruct m; reflexivity || (try discriminate H). injection H; clear H; intro H; rewrite Pmult_reg_r with (1 := H); reflexivity. Qed. -Theorem Nmult_0_l : forall n:N, N0 * n = N0. +(** Properties of comparison *) + +Lemma Ncompare_refl : forall n, (n ?= n) = Eq. Proof. -reflexivity. +destruct n; simpl; auto. +apply Pcompare_refl. Qed. -(** Properties of comparison *) - Theorem Ncompare_Eq_eq : forall n m:N, (n ?= m) = Eq -> n = m. Proof. destruct n as [| n]; destruct m as [| m]; simpl in |- *; intro H; @@ -247,10 +371,10 @@ destruct n as [| n]; destruct m as [| m]; simpl in |- *; intro H; rewrite (Pcompare_Eq_eq n m H); reflexivity. Qed. -Lemma Ncompare_refl : forall n, (n ?= n) = Eq. +Theorem Ncompare_eq_correct : forall n m:N, (n ?= m) = Eq <-> n = m. Proof. -destruct n; simpl; auto. -apply Pcompare_refl. +split; intros; + [ apply Ncompare_Eq_eq; auto | subst; apply Ncompare_refl ]. Qed. Lemma Ncompare_antisym : forall n m, CompOpp (n ?= m) = (m ?= n). @@ -259,6 +383,30 @@ destruct n; destruct m; simpl; auto. exact (Pcompare_antisym p p0 Eq). Qed. +Theorem Nlt_irrefl : forall n : N, ~ n < n. +Proof. +intro n; unfold Nlt; now rewrite Ncompare_refl. +Qed. + +Theorem Ncompare_n_Sm : + forall n m : N, Ncompare n (Nsucc m) = Lt <-> Ncompare n m = Lt \/ n = m. +Proof. +intros n m; split; destruct n as [| p]; destruct m as [| q]; simpl; auto. +destruct p; simpl; intros; discriminate. +pose proof (proj1 (Pcompare_p_Sq p q)); +assert (p = q <-> Npos p = Npos q); [split; congruence | tauto]. +intros H; destruct H; discriminate. +pose proof (proj2 (Pcompare_p_Sq p q)); +assert (p = q <-> Npos p = Npos q); [split; congruence | tauto]. +Qed. + +(** 0 is the least natural number *) + +Theorem Ncompare_0 : forall n : N, Ncompare n N0 <> Lt. +Proof. +destruct n; discriminate. +Qed. + (** Dividing by 2 *) Definition Ndiv2 (n:N) := diff --git a/theories/NArith/BinPos.v b/theories/NArith/BinPos.v index 513a67c2..e3293e70 100644 --- a/theories/NArith/BinPos.v +++ b/theories/NArith/BinPos.v @@ -6,19 +6,19 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: BinPos.v 6699 2005-02-07 14:30:08Z coq $ i*) +(*i $Id: BinPos.v 11033 2008-06-01 22:56:50Z letouzey $ i*) Unset Boxed Definitions. (**********************************************************************) (** Binary positive numbers *) -(** Original development by Pierre Crégut, CNET, Lannion, France *) +(** Original development by Pierre Crégut, CNET, Lannion, France *) Inductive positive : Set := - | xI : positive -> positive - | xO : positive -> positive - | xH : positive. +| xI : positive -> positive +| xO : positive -> positive +| xH : positive. (** Declare binding key for scope positive_scope *) @@ -30,164 +30,181 @@ Bind Scope positive_scope with positive. Arguments Scope xO [positive_scope]. Arguments Scope xI [positive_scope]. +(** Postfix notation for positive numbers, allowing to mimic + the position of bits in a big-endian representation. + For instance, we can write 1~1~0 instead of (xO (xI xH)) + for the number 6 (which is 110 in binary notation). +*) + +Notation "p ~ 1" := (xI p) + (at level 7, left associativity, format "p '~' '1'") : positive_scope. +Notation "p ~ 0" := (xO p) + (at level 7, left associativity, format "p '~' '0'") : positive_scope. + +Open Local Scope positive_scope. + +(* In the current file, [xH] cannot yet be written as [1], since the + interpretation of positive numerical constants is not available + yet. We fix this here with an ad-hoc temporary notation. *) + +Notation Local "1" := xH (at level 7). + (** Successor *) Fixpoint Psucc (x:positive) : positive := match x with - | xI x' => xO (Psucc x') - | xO x' => xI x' - | xH => xO xH + | p~1 => (Psucc p)~0 + | p~0 => p~1 + | 1 => 1~0 end. (** Addition *) Set Boxed Definitions. -Fixpoint Pplus (x y:positive) {struct x} : positive := +Fixpoint Pplus (x y:positive) : positive := match x, y with - | xI x', xI y' => xO (Pplus_carry x' y') - | xI x', xO y' => xI (Pplus x' y') - | xI x', xH => xO (Psucc x') - | xO x', xI y' => xI (Pplus x' y') - | xO x', xO y' => xO (Pplus x' y') - | xO x', xH => xI x' - | xH, xI y' => xO (Psucc y') - | xH, xO y' => xI y' - | xH, xH => xO xH + | p~1, q~1 => (Pplus_carry p q)~0 + | p~1, q~0 => (Pplus p q)~1 + | p~1, 1 => (Psucc p)~0 + | p~0, q~1 => (Pplus p q)~1 + | p~0, q~0 => (Pplus p q)~0 + | p~0, 1 => p~1 + | 1, q~1 => (Psucc q)~0 + | 1, q~0 => q~1 + | 1, 1 => 1~0 end - - with Pplus_carry (x y:positive) {struct x} : positive := + +with Pplus_carry (x y:positive) : positive := match x, y with - | xI x', xI y' => xI (Pplus_carry x' y') - | xI x', xO y' => xO (Pplus_carry x' y') - | xI x', xH => xI (Psucc x') - | xO x', xI y' => xO (Pplus_carry x' y') - | xO x', xO y' => xI (Pplus x' y') - | xO x', xH => xO (Psucc x') - | xH, xI y' => xI (Psucc y') - | xH, xO y' => xO (Psucc y') - | xH, xH => xI xH + | p~1, q~1 => (Pplus_carry p q)~1 + | p~1, q~0 => (Pplus_carry p q)~0 + | p~1, 1 => (Psucc p)~1 + | p~0, q~1 => (Pplus_carry p q)~0 + | p~0, q~0 => (Pplus p q)~1 + | p~0, 1 => (Psucc p)~0 + | 1, q~1 => (Psucc q)~1 + | 1, q~0 => (Psucc q)~0 + | 1, 1 => 1~1 end. Unset Boxed Definitions. Infix "+" := Pplus : positive_scope. -Open Local Scope positive_scope. - (** From binary positive numbers to Peano natural numbers *) -Fixpoint Pmult_nat (x:positive) (pow2:nat) {struct x} : nat := +Fixpoint Pmult_nat (x:positive) (pow2:nat) : nat := match x with - | xI x' => (pow2 + Pmult_nat x' (pow2 + pow2))%nat - | xO x' => Pmult_nat x' (pow2 + pow2)%nat - | xH => pow2 + | p~1 => (pow2 + Pmult_nat p (pow2 + pow2))%nat + | p~0 => Pmult_nat p (pow2 + pow2)%nat + | 1 => pow2 end. -Definition nat_of_P (x:positive) := Pmult_nat x 1. +Definition nat_of_P (x:positive) := Pmult_nat x (S O). (** From Peano natural numbers to binary positive numbers *) Fixpoint P_of_succ_nat (n:nat) : positive := match n with - | O => xH - | S x' => Psucc (P_of_succ_nat x') + | O => 1 + | S x => Psucc (P_of_succ_nat x) end. (** Operation x -> 2*x-1 *) Fixpoint Pdouble_minus_one (x:positive) : positive := match x with - | xI x' => xI (xO x') - | xO x' => xI (Pdouble_minus_one x') - | xH => xH + | p~1 => p~0~1 + | p~0 => (Pdouble_minus_one p)~1 + | 1 => 1 end. (** Predecessor *) Definition Ppred (x:positive) := match x with - | xI x' => xO x' - | xO x' => Pdouble_minus_one x' - | xH => xH + | p~1 => p~0 + | p~0 => Pdouble_minus_one p + | 1 => 1 end. (** An auxiliary type for subtraction *) Inductive positive_mask : Set := - | IsNul : positive_mask - | IsPos : positive -> positive_mask - | IsNeg : positive_mask. +| IsNul : positive_mask +| IsPos : positive -> positive_mask +| IsNeg : positive_mask. (** Operation x -> 2*x+1 *) Definition Pdouble_plus_one_mask (x:positive_mask) := match x with - | IsNul => IsPos xH - | IsNeg => IsNeg - | IsPos p => IsPos (xI p) + | IsNul => IsPos 1 + | IsNeg => IsNeg + | IsPos p => IsPos p~1 end. (** Operation x -> 2*x *) Definition Pdouble_mask (x:positive_mask) := match x with - | IsNul => IsNul - | IsNeg => IsNeg - | IsPos p => IsPos (xO p) + | IsNul => IsNul + | IsNeg => IsNeg + | IsPos p => IsPos p~0 end. (** Operation x -> 2*x-2 *) Definition Pdouble_minus_two (x:positive) := match x with - | xI x' => IsPos (xO (xO x')) - | xO x' => IsPos (xO (Pdouble_minus_one x')) - | xH => IsNul + | p~1 => IsPos p~0~0 + | p~0 => IsPos (Pdouble_minus_one p)~0 + | 1 => IsNul end. (** Subtraction of binary positive numbers into a positive numbers mask *) Fixpoint Pminus_mask (x y:positive) {struct y} : positive_mask := match x, y with - | xI x', xI y' => Pdouble_mask (Pminus_mask x' y') - | xI x', xO y' => Pdouble_plus_one_mask (Pminus_mask x' y') - | xI x', xH => IsPos (xO x') - | xO x', xI y' => Pdouble_plus_one_mask (Pminus_mask_carry x' y') - | xO x', xO y' => Pdouble_mask (Pminus_mask x' y') - | xO x', xH => IsPos (Pdouble_minus_one x') - | xH, xH => IsNul - | xH, _ => IsNeg + | p~1, q~1 => Pdouble_mask (Pminus_mask p q) + | p~1, q~0 => Pdouble_plus_one_mask (Pminus_mask p q) + | p~1, 1 => IsPos p~0 + | p~0, q~1 => Pdouble_plus_one_mask (Pminus_mask_carry p q) + | p~0, q~0 => Pdouble_mask (Pminus_mask p q) + | p~0, 1 => IsPos (Pdouble_minus_one p) + | 1, 1 => IsNul + | 1, _ => IsNeg end - - with Pminus_mask_carry (x y:positive) {struct y} : positive_mask := + +with Pminus_mask_carry (x y:positive) {struct y} : positive_mask := match x, y with - | xI x', xI y' => Pdouble_plus_one_mask (Pminus_mask_carry x' y') - | xI x', xO y' => Pdouble_mask (Pminus_mask x' y') - | xI x', xH => IsPos (Pdouble_minus_one x') - | xO x', xI y' => Pdouble_mask (Pminus_mask_carry x' y') - | xO x', xO y' => Pdouble_plus_one_mask (Pminus_mask_carry x' y') - | xO x', xH => Pdouble_minus_two x' - | xH, _ => IsNeg + | p~1, q~1 => Pdouble_plus_one_mask (Pminus_mask_carry p q) + | p~1, q~0 => Pdouble_mask (Pminus_mask p q) + | p~1, 1 => IsPos (Pdouble_minus_one p) + | p~0, q~1 => Pdouble_mask (Pminus_mask_carry p q) + | p~0, q~0 => Pdouble_plus_one_mask (Pminus_mask_carry p q) + | p~0, 1 => Pdouble_minus_two p + | 1, _ => IsNeg end. (** Subtraction of binary positive numbers x and y, returns 1 if x<=y *) Definition Pminus (x y:positive) := match Pminus_mask x y with - | IsPos z => z - | _ => xH + | IsPos z => z + | _ => 1 end. Infix "-" := Pminus : positive_scope. (** Multiplication on binary positive numbers *) -Fixpoint Pmult (x y:positive) {struct x} : positive := +Fixpoint Pmult (x y:positive) : positive := match x with - | xI x' => y + xO (Pmult x' y) - | xO x' => xO (Pmult x' y) - | xH => y + | p~1 => y + (Pmult p y)~0 + | p~0 => (Pmult p y)~0 + | 1 => y end. Infix "*" := Pmult : positive_scope. @@ -196,9 +213,9 @@ Infix "*" := Pmult : positive_scope. Definition Pdiv2 (z:positive) := match z with - | xH => xH - | xO p => p - | xI p => p + | 1 => 1 + | p~0 => p + | p~1 => p end. Infix "/" := Pdiv2 : positive_scope. @@ -207,25 +224,51 @@ Infix "/" := Pdiv2 : positive_scope. Fixpoint Pcompare (x y:positive) (r:comparison) {struct y} : comparison := match x, y with - | xI x', xI y' => Pcompare x' y' r - | xI x', xO y' => Pcompare x' y' Gt - | xI x', xH => Gt - | xO x', xI y' => Pcompare x' y' Lt - | xO x', xO y' => Pcompare x' y' r - | xO x', xH => Gt - | xH, xI y' => Lt - | xH, xO y' => Lt - | xH, xH => r + | p~1, q~1 => Pcompare p q r + | p~1, q~0 => Pcompare p q Gt + | p~1, 1 => Gt + | p~0, q~1 => Pcompare p q Lt + | p~0, q~0 => Pcompare p q r + | p~0, 1 => Gt + | 1, q~1 => Lt + | 1, q~0 => Lt + | 1, 1 => r end. Infix "?=" := Pcompare (at level 70, no associativity) : positive_scope. +Definition Plt (x y:positive) := (Pcompare x y Eq) = Lt. +Definition Pgt (x y:positive) := (Pcompare x y Eq) = Gt. +Definition Ple (x y:positive) := (Pcompare x y Eq) <> Gt. +Definition Pge (x y:positive) := (Pcompare x y Eq) <> Lt. + +Infix "<=" := Ple : positive_scope. +Infix "<" := Plt : positive_scope. +Infix ">=" := Pge : positive_scope. +Infix ">" := Pgt : positive_scope. + +Notation "x <= y <= z" := (x <= y /\ y <= z) : positive_scope. +Notation "x <= y < z" := (x <= y /\ y < z) : positive_scope. +Notation "x < y < z" := (x < y /\ y < z) : positive_scope. +Notation "x < y <= z" := (x < y /\ y <= z) : positive_scope. + + +Definition Pmin (p p' : positive) := match Pcompare p p' Eq with + | Lt | Eq => p + | Gt => p' + end. + +Definition Pmax (p p' : positive) := match Pcompare p p' Eq with + | Lt | Eq => p' + | Gt => p + end. + (**********************************************************************) (** Miscellaneous properties of binary positive numbers *) -Lemma ZL11 : forall p:positive, p = xH \/ p <> xH. +Lemma ZL11 : forall p:positive, p = 1 \/ p <> 1. Proof. -intros x; case x; intros; (left; reflexivity) || (right; discriminate). + intros x; case x; intros; (left; reflexivity) || (right; discriminate). Qed. (**********************************************************************) @@ -233,78 +276,70 @@ Qed. (** Specification of [xI] in term of [Psucc] and [xO] *) -Lemma xI_succ_xO : forall p:positive, xI p = Psucc (xO p). +Lemma xI_succ_xO : forall p:positive, p~1 = Psucc p~0. Proof. -reflexivity. + reflexivity. Qed. Lemma Psucc_discr : forall p:positive, p <> Psucc p. Proof. -intro x; destruct x as [p| p| ]; discriminate. + destruct p; discriminate. Qed. (** Successor and double *) Lemma Psucc_o_double_minus_one_eq_xO : - forall p:positive, Psucc (Pdouble_minus_one p) = xO p. + forall p:positive, Psucc (Pdouble_minus_one p) = p~0. Proof. -intro x; induction x as [x IHx| x| ]; simpl in |- *; try rewrite IHx; - reflexivity. + induction p; simpl; f_equal; auto. Qed. Lemma Pdouble_minus_one_o_succ_eq_xI : - forall p:positive, Pdouble_minus_one (Psucc p) = xI p. + forall p:positive, Pdouble_minus_one (Psucc p) = p~1. Proof. -intro x; induction x as [x IHx| x| ]; simpl in |- *; try rewrite IHx; - reflexivity. + induction p; simpl; f_equal; auto. Qed. Lemma xO_succ_permute : - forall p:positive, xO (Psucc p) = Psucc (Psucc (xO p)). + forall p:positive, (Psucc p)~0 = Psucc (Psucc p~0). Proof. -intro y; induction y as [y Hrecy| y Hrecy| ]; simpl in |- *; auto. + induction p; simpl; auto. Qed. Lemma double_moins_un_xO_discr : - forall p:positive, Pdouble_minus_one p <> xO p. + forall p:positive, Pdouble_minus_one p <> p~0. Proof. -intro x; destruct x as [p| p| ]; discriminate. + destruct p; discriminate. Qed. (** Successor and predecessor *) -Lemma Psucc_not_one : forall p:positive, Psucc p <> xH. +Lemma Psucc_not_one : forall p:positive, Psucc p <> 1. Proof. -intro x; destruct x as [x| x| ]; discriminate. + destruct p; discriminate. Qed. Lemma Ppred_succ : forall p:positive, Ppred (Psucc p) = p. Proof. -intro x; destruct x as [p| p| ]; [ idtac | idtac | simpl in |- *; auto ]; - (induction p as [p IHp| | ]; [ idtac | reflexivity | reflexivity ]); - simpl in |- *; simpl in IHp; try rewrite <- IHp; reflexivity. + intros [[p|p| ]|[p|p| ]| ]; simpl; auto. + f_equal; apply Pdouble_minus_one_o_succ_eq_xI. Qed. -Lemma Psucc_pred : forall p:positive, p = xH \/ Psucc (Ppred p) = p. +Lemma Psucc_pred : forall p:positive, p = 1 \/ Psucc (Ppred p) = p. Proof. -intro x; induction x as [x Hrecx| x Hrecx| ]; - [ simpl in |- *; auto - | simpl in |- *; intros; right; apply Psucc_o_double_minus_one_eq_xO - | auto ]. + induction p; simpl; auto. + right; apply Psucc_o_double_minus_one_eq_xO. Qed. +Ltac destr_eq H := discriminate H || (try (injection H; clear H; intro H)). + (** Injectivity of successor *) Lemma Psucc_inj : forall p q:positive, Psucc p = Psucc q -> p = q. Proof. -intro x; induction x; intro y; destruct y as [y| y| ]; simpl in |- *; intro H; - discriminate H || (try (injection H; clear H; intro H)). -rewrite (IHx y H); reflexivity. -absurd (Psucc x = xH); [ apply Psucc_not_one | assumption ]. -apply f_equal with (1 := H); assumption. -absurd (Psucc y = xH); - [ apply Psucc_not_one | symmetry in |- *; assumption ]. -reflexivity. + induction p; intros [q|q| ] H; simpl in *; destr_eq H; f_equal; auto. + elim (Psucc_not_one p); auto. + elim (Psucc_not_one q); auto. Qed. (**********************************************************************) @@ -312,656 +347,758 @@ Qed. (** Specification of [Psucc] in term of [Pplus] *) -Lemma Pplus_one_succ_r : forall p:positive, Psucc p = p + xH. +Lemma Pplus_one_succ_r : forall p:positive, Psucc p = p + 1. Proof. -intro q; destruct q as [p| p| ]; reflexivity. + destruct p; reflexivity. Qed. -Lemma Pplus_one_succ_l : forall p:positive, Psucc p = xH + p. +Lemma Pplus_one_succ_l : forall p:positive, Psucc p = 1 + p. Proof. -intro q; destruct q as [p| p| ]; reflexivity. + destruct p; reflexivity. Qed. (** Specification of [Pplus_carry] *) Theorem Pplus_carry_spec : - forall p q:positive, Pplus_carry p q = Psucc (p + q). + forall p q:positive, Pplus_carry p q = Psucc (p + q). Proof. -intro x; induction x as [p IHp| p IHp| ]; intro y; - [ destruct y as [p0| p0| ] - | destruct y as [p0| p0| ] - | destruct y as [p| p| ] ]; simpl in |- *; auto; rewrite IHp; - auto. + induction p; destruct q; simpl; f_equal; auto. Qed. (** Commutativity *) Theorem Pplus_comm : forall p q:positive, p + q = q + p. Proof. -intro x; induction x as [p IHp| p IHp| ]; intro y; - [ destruct y as [p0| p0| ] - | destruct y as [p0| p0| ] - | destruct y as [p| p| ] ]; simpl in |- *; auto; - try do 2 rewrite Pplus_carry_spec; rewrite IHp; auto. + induction p; destruct q; simpl; f_equal; auto. + rewrite 2 Pplus_carry_spec; f_equal; auto. Qed. (** Permutation of [Pplus] and [Psucc] *) Theorem Pplus_succ_permute_r : - forall p q:positive, p + Psucc q = Psucc (p + q). + forall p q:positive, p + Psucc q = Psucc (p + q). Proof. -intro x; induction x as [p IHp| p IHp| ]; intro y; - [ destruct y as [p0| p0| ] - | destruct y as [p0| p0| ] - | destruct y as [p| p| ] ]; simpl in |- *; auto; - [ rewrite Pplus_carry_spec; rewrite IHp; auto - | rewrite Pplus_carry_spec; auto - | destruct p; simpl in |- *; auto - | rewrite IHp; auto - | destruct p; simpl in |- *; auto ]. + induction p; destruct q; simpl; f_equal; + auto using Pplus_one_succ_r; rewrite Pplus_carry_spec; auto. Qed. Theorem Pplus_succ_permute_l : - forall p q:positive, Psucc p + q = Psucc (p + q). + forall p q:positive, Psucc p + q = Psucc (p + q). Proof. -intros x y; rewrite Pplus_comm; rewrite Pplus_comm with (p := x); - apply Pplus_succ_permute_r. + intros p q; rewrite Pplus_comm, (Pplus_comm p); + apply Pplus_succ_permute_r. Qed. Theorem Pplus_carry_pred_eq_plus : - forall p q:positive, q <> xH -> Pplus_carry p (Ppred q) = p + q. + forall p q:positive, q <> 1 -> Pplus_carry p (Ppred q) = p + q. Proof. -intros q z H; elim (Psucc_pred z); - [ intro; absurd (z = xH); auto - | intros E; pattern z at 2 in |- *; rewrite <- E; - rewrite Pplus_succ_permute_r; rewrite Pplus_carry_spec; - trivial ]. -Qed. + intros p q H; rewrite Pplus_carry_spec, <- Pplus_succ_permute_r; f_equal. + destruct (Psucc_pred q); [ elim H; assumption | assumption ]. +Qed. (** No neutral for addition on strictly positive numbers *) Lemma Pplus_no_neutral : forall p q:positive, q + p <> p. Proof. -intro x; induction x; intro y; destruct y as [y| y| ]; simpl in |- *; intro H; - discriminate H || injection H; clear H; intro H; apply (IHx y H). + induction p as [p IHp|p IHp| ]; intros [q|q| ] H; + destr_eq H; apply (IHp q H). Qed. Lemma Pplus_carry_no_neutral : - forall p q:positive, Pplus_carry q p <> Psucc p. + forall p q:positive, Pplus_carry q p <> Psucc p. Proof. -intros x y H; absurd (y + x = x); - [ apply Pplus_no_neutral - | apply Psucc_inj; rewrite <- Pplus_carry_spec; assumption ]. + intros p q H; elim (Pplus_no_neutral p q). + apply Psucc_inj; rewrite <- Pplus_carry_spec; assumption. Qed. (** Simplification *) Lemma Pplus_carry_plus : - forall p q r s:positive, Pplus_carry p r = Pplus_carry q s -> p + r = q + s. + forall p q r s:positive, Pplus_carry p r = Pplus_carry q s -> p + r = q + s. Proof. -intros x y z t H; apply Psucc_inj; do 2 rewrite <- Pplus_carry_spec; - assumption. + intros p q r s H; apply Psucc_inj; do 2 rewrite <- Pplus_carry_spec; + assumption. Qed. Lemma Pplus_reg_r : forall p q r:positive, p + r = q + r -> p = q. Proof. -intros x y z; generalize x y; clear x y. -induction z as [z| z| ]. - destruct x as [x| x| ]; intro y; destruct y as [y| y| ]; simpl in |- *; - intro H; discriminate H || (try (injection H; clear H; intro H)). - rewrite IHz with (1 := Pplus_carry_plus _ _ _ _ H); reflexivity. - absurd (Pplus_carry x z = Psucc z); - [ apply Pplus_carry_no_neutral | assumption ]. - rewrite IHz with (1 := H); reflexivity. - symmetry in H; absurd (Pplus_carry y z = Psucc z); - [ apply Pplus_carry_no_neutral | assumption ]. - reflexivity. - destruct x as [x| x| ]; intro y; destruct y as [y| y| ]; simpl in |- *; - intro H; discriminate H || (try (injection H; clear H; intro H)). - rewrite IHz with (1 := H); reflexivity. - absurd (x + z = z); [ apply Pplus_no_neutral | assumption ]. - rewrite IHz with (1 := H); reflexivity. - symmetry in H; absurd (y + z = z); - [ apply Pplus_no_neutral | assumption ]. - reflexivity. - intros H x y; apply Psucc_inj; do 2 rewrite Pplus_one_succ_r; assumption. + intros p q r; revert p q; induction r. + intros [p|p| ] [q|q| ] H; simpl; destr_eq H; + f_equal; auto using Pplus_carry_plus; + contradict H; auto using Pplus_carry_no_neutral. + intros [p|p| ] [q|q| ] H; simpl; destr_eq H; f_equal; auto; + contradict H; auto using Pplus_no_neutral. + intros p q H; apply Psucc_inj; do 2 rewrite Pplus_one_succ_r; assumption. Qed. Lemma Pplus_reg_l : forall p q r:positive, p + q = p + r -> q = r. Proof. -intros x y z H; apply Pplus_reg_r with (r := x); - rewrite Pplus_comm with (p := z); rewrite Pplus_comm with (p := y); - assumption. + intros p q r H; apply Pplus_reg_r with (r:=p). + rewrite (Pplus_comm r), (Pplus_comm q); assumption. Qed. Lemma Pplus_carry_reg_r : - forall p q r:positive, Pplus_carry p r = Pplus_carry q r -> p = q. + forall p q r:positive, Pplus_carry p r = Pplus_carry q r -> p = q. Proof. -intros x y z H; apply Pplus_reg_r with (r := z); apply Pplus_carry_plus; - assumption. + intros p q r H; apply Pplus_reg_r with (r:=r); apply Pplus_carry_plus; + assumption. Qed. Lemma Pplus_carry_reg_l : - forall p q r:positive, Pplus_carry p q = Pplus_carry p r -> q = r. + forall p q r:positive, Pplus_carry p q = Pplus_carry p r -> q = r. Proof. -intros x y z H; apply Pplus_reg_r with (r := x); - rewrite Pplus_comm with (p := z); rewrite Pplus_comm with (p := y); - apply Pplus_carry_plus; assumption. + intros p q r H; apply Pplus_reg_r with (r:=p); + rewrite (Pplus_comm r), (Pplus_comm q); apply Pplus_carry_plus; assumption. Qed. (** Addition on positive is associative *) Theorem Pplus_assoc : forall p q r:positive, p + (q + r) = p + q + r. Proof. -intros x y; generalize x; clear x. -induction y as [y| y| ]; intro x. - destruct x as [x| x| ]; intro z; destruct z as [z| z| ]; simpl in |- *; - repeat rewrite Pplus_carry_spec; repeat rewrite Pplus_succ_permute_r; - repeat rewrite Pplus_succ_permute_l; - reflexivity || (repeat apply f_equal with (A := positive)); - apply IHy. - destruct x as [x| x| ]; intro z; destruct z as [z| z| ]; simpl in |- *; - repeat rewrite Pplus_carry_spec; repeat rewrite Pplus_succ_permute_r; - repeat rewrite Pplus_succ_permute_l; - reflexivity || (repeat apply f_equal with (A := positive)); - apply IHy. - intro z; rewrite Pplus_comm with (p := xH); - do 2 rewrite <- Pplus_one_succ_r; rewrite Pplus_succ_permute_l; - rewrite Pplus_succ_permute_r; reflexivity. + induction p. + intros [q|q| ] [r|r| ]; simpl; f_equal; auto; + rewrite ?Pplus_carry_spec, ?Pplus_succ_permute_r, + ?Pplus_succ_permute_l, ?Pplus_one_succ_r; f_equal; auto. + intros [q|q| ] [r|r| ]; simpl; f_equal; auto; + rewrite ?Pplus_carry_spec, ?Pplus_succ_permute_r, + ?Pplus_succ_permute_l, ?Pplus_one_succ_r; f_equal; auto. + intros p r; rewrite <- 2 Pplus_one_succ_l, Pplus_succ_permute_l; auto. Qed. (** Commutation of addition with the double of a positive number *) +Lemma Pplus_xO : forall m n : positive, (m + n)~0 = m~0 + n~0. +Proof. + destruct n; destruct m; simpl; auto. +Qed. + Lemma Pplus_xI_double_minus_one : - forall p q:positive, xO (p + q) = xI p + Pdouble_minus_one q. + forall p q:positive, (p + q)~0 = p~1 + Pdouble_minus_one q. Proof. -intros; change (xI p) with (xO p + xH) in |- *. -rewrite <- Pplus_assoc; rewrite <- Pplus_one_succ_l; - rewrite Psucc_o_double_minus_one_eq_xO. -reflexivity. + intros; change (p~1) with (p~0 + 1). + rewrite <- Pplus_assoc, <- Pplus_one_succ_l, Psucc_o_double_minus_one_eq_xO. + reflexivity. Qed. Lemma Pplus_xO_double_minus_one : - forall p q:positive, Pdouble_minus_one (p + q) = xO p + Pdouble_minus_one q. + forall p q:positive, Pdouble_minus_one (p + q) = p~0 + Pdouble_minus_one q. Proof. -induction p as [p IHp| p IHp| ]; destruct q as [q| q| ]; simpl in |- *; - try rewrite Pplus_carry_spec; try rewrite Pdouble_minus_one_o_succ_eq_xI; - try rewrite IHp; try rewrite Pplus_xI_double_minus_one; - try reflexivity. - rewrite <- Psucc_o_double_minus_one_eq_xO; rewrite Pplus_one_succ_l; - reflexivity. + induction p as [p IHp| p IHp| ]; destruct q; simpl; + rewrite ?Pplus_carry_spec, ?Pdouble_minus_one_o_succ_eq_xI, + ?Pplus_xI_double_minus_one; try reflexivity. + rewrite IHp; auto. + rewrite <- Psucc_o_double_minus_one_eq_xO, Pplus_one_succ_l; reflexivity. Qed. (** Misc *) -Lemma Pplus_diag : forall p:positive, p + p = xO p. +Lemma Pplus_diag : forall p:positive, p + p = p~0. Proof. -intro x; induction x; simpl in |- *; try rewrite Pplus_carry_spec; - try rewrite IHx; reflexivity. + induction p as [p IHp| p IHp| ]; simpl; + try rewrite ?Pplus_carry_spec, ?IHp; reflexivity. Qed. (**********************************************************************) -(** Peano induction on binary positive positive numbers *) +(** Peano induction and recursion on binary positive positive numbers *) +(** (a nice proof from Conor McBride, see "The view from the left") *) -Fixpoint plus_iter (x y:positive) {struct x} : positive := - match x with - | xH => Psucc y - | xO x => plus_iter x (plus_iter x y) - | xI x => plus_iter x (plus_iter x (Psucc y)) +Inductive PeanoView : positive -> Type := +| PeanoOne : PeanoView 1 +| PeanoSucc : forall p, PeanoView p -> PeanoView (Psucc p). + +Fixpoint peanoView_xO p (q:PeanoView p) : PeanoView (p~0) := + match q in PeanoView x return PeanoView (x~0) with + | PeanoOne => PeanoSucc _ PeanoOne + | PeanoSucc _ q => PeanoSucc _ (PeanoSucc _ (peanoView_xO _ q)) end. -Lemma plus_iter_eq_plus : forall p q:positive, plus_iter p q = p + q. -Proof. -intro x; induction x as [p IHp| p IHp| ]; intro y; - [ destruct y as [p0| p0| ] - | destruct y as [p0| p0| ] - | destruct y as [p| p| ] ]; simpl in |- *; reflexivity || (do 2 rewrite IHp); - rewrite Pplus_assoc; rewrite Pplus_diag; try reflexivity. -rewrite Pplus_carry_spec; rewrite <- Pplus_succ_permute_r; reflexivity. -rewrite Pplus_one_succ_r; reflexivity. -Qed. +Fixpoint peanoView_xI p (q:PeanoView p) : PeanoView (p~1) := + match q in PeanoView x return PeanoView (x~1) with + | PeanoOne => PeanoSucc _ (PeanoSucc _ PeanoOne) + | PeanoSucc _ q => PeanoSucc _ (PeanoSucc _ (peanoView_xI _ q)) + end. + +Fixpoint peanoView p : PeanoView p := + match p return PeanoView p with + | 1 => PeanoOne + | p~0 => peanoView_xO p (peanoView p) + | p~1 => peanoView_xI p (peanoView p) + end. -Lemma plus_iter_xO : forall p:positive, plus_iter p p = xO p. +Definition PeanoView_iter (P:positive->Type) + (a:P 1) (f:forall p, P p -> P (Psucc p)) := + (fix iter p (q:PeanoView p) : P p := + match q in PeanoView p return P p with + | PeanoOne => a + | PeanoSucc _ q => f _ (iter _ q) + end). + +Require Import Eqdep_dec EqdepFacts. + +Theorem eq_dep_eq_positive : + forall (P:positive->Type) (p:positive) (x y:P p), + eq_dep positive P p x p y -> x = y. Proof. -intro; rewrite <- Pplus_diag; apply plus_iter_eq_plus. + apply eq_dep_eq_dec. + decide equality. Qed. -Lemma plus_iter_xI : forall p:positive, Psucc (plus_iter p p) = xI p. +Theorem PeanoViewUnique : forall p (q q':PeanoView p), q = q'. Proof. -intro; rewrite xI_succ_xO; rewrite <- Pplus_diag; - apply (f_equal (A:=positive)); apply plus_iter_eq_plus. + intros. + induction q as [ | p q IHq ]. + apply eq_dep_eq_positive. + cut (1=1). pattern 1 at 1 2 5, q'. destruct q'. trivial. + destruct p0; intros; discriminate. + trivial. + apply eq_dep_eq_positive. + cut (Psucc p=Psucc p). pattern (Psucc p) at 1 2 5, q'. destruct q'. + intro. destruct p; discriminate. + intro. unfold p0 in H. apply Psucc_inj in H. + generalize q'. rewrite H. intro. + rewrite (IHq q'0). + trivial. + trivial. Qed. -Lemma iterate_add : - forall P:positive -> Type, - (forall n:positive, P n -> P (Psucc n)) -> - forall p q:positive, P q -> P (plus_iter p q). -Proof. -intros P H; induction p; simpl in |- *; intros. -apply IHp; apply IHp; apply H; assumption. -apply IHp; apply IHp; assumption. -apply H; assumption. -Defined. +Definition Prect (P:positive->Type) (a:P 1) (f:forall p, P p -> P (Psucc p)) + (p:positive) := + PeanoView_iter P a f p (peanoView p). -(** Peano induction *) +Theorem Prect_succ : forall (P:positive->Type) (a:P 1) + (f:forall p, P p -> P (Psucc p)) (p:positive), + Prect P a f (Psucc p) = f _ (Prect P a f p). +Proof. + intros. + unfold Prect. + rewrite (PeanoViewUnique _ (peanoView (Psucc p)) (PeanoSucc _ (peanoView p))). + trivial. +Qed. -Theorem Pind : - forall P:positive -> Prop, - P xH -> (forall n:positive, P n -> P (Psucc n)) -> forall p:positive, P p. +Theorem Prect_base : forall (P:positive->Type) (a:P 1) + (f:forall p, P p -> P (Psucc p)), Prect P a f 1 = a. Proof. -intros P H1 Hsucc n; induction n. -rewrite <- plus_iter_xI; apply Hsucc; apply iterate_add; assumption. -rewrite <- plus_iter_xO; apply iterate_add; assumption. -assumption. + trivial. Qed. -(** Peano recursion *) +Definition Prec (P:positive->Set) := Prect P. -Definition Prec (A:Set) (a:A) (f:positive -> A -> A) : - positive -> A := - (fix Prec (p:positive) : A := - match p with - | xH => a - | xO p => iterate_add (fun _ => A) f p p (Prec p) - | xI p => f (plus_iter p p) (iterate_add (fun _ => A) f p p (Prec p)) - end). +(** Peano induction *) + +Definition Pind (P:positive->Prop) := Prect P. (** Peano case analysis *) Theorem Pcase : - forall P:positive -> Prop, - P xH -> (forall n:positive, P (Psucc n)) -> forall p:positive, P p. + forall P:positive -> Prop, + P 1 -> (forall n:positive, P (Psucc n)) -> forall p:positive, P p. Proof. -intros; apply Pind; auto. + intros; apply Pind; auto. Qed. -(* -Check - (let fact := Prec positive xH (fun p r => Psucc p * r) in - let seven := xI (xI xH) in - let five_thousand_forty := - xO (xO (xO (xO (xI (xI (xO (xI (xI (xI (xO (xO xH))))))))))) in - refl_equal _:fact seven = five_thousand_forty). -*) - (**********************************************************************) (** Properties of multiplication on binary positive numbers *) (** One is right neutral for multiplication *) -Lemma Pmult_1_r : forall p:positive, p * xH = p. +Lemma Pmult_1_r : forall p:positive, p * 1 = p. Proof. -intro x; induction x; simpl in |- *. - rewrite IHx; reflexivity. - rewrite IHx; reflexivity. + induction p; simpl; f_equal; auto. +Qed. + +(** Successor and multiplication *) + +Lemma Pmult_Sn_m : forall n m : positive, (Psucc n) * m = m + n * m. +Proof. + induction n as [n IHn | n IHn | ]; simpl; intro m. + rewrite IHn, Pplus_assoc, Pplus_diag, <-Pplus_xO; reflexivity. reflexivity. + symmetry; apply Pplus_diag. Qed. (** Right reduction properties for multiplication *) -Lemma Pmult_xO_permute_r : forall p q:positive, p * xO q = xO (p * q). +Lemma Pmult_xO_permute_r : forall p q:positive, p * q~0 = (p * q)~0. Proof. -intros x y; induction x; simpl in |- *. - rewrite IHx; reflexivity. - rewrite IHx; reflexivity. - reflexivity. + intros p q; induction p; simpl; do 2 (f_equal; auto). Qed. -Lemma Pmult_xI_permute_r : forall p q:positive, p * xI q = p + xO (p * q). +Lemma Pmult_xI_permute_r : forall p q:positive, p * q~1 = p + (p * q)~0. Proof. -intros x y; induction x; simpl in |- *. - rewrite IHx; do 2 rewrite Pplus_assoc; rewrite Pplus_comm with (p := y); - reflexivity. - rewrite IHx; reflexivity. - reflexivity. + intros p q; induction p as [p IHp|p IHp| ]; simpl; f_equal; auto. + rewrite IHp, 2 Pplus_assoc, (Pplus_comm p); reflexivity. Qed. (** Commutativity of multiplication *) Theorem Pmult_comm : forall p q:positive, p * q = q * p. Proof. -intros x y; induction y; simpl in |- *. - rewrite <- IHy; apply Pmult_xI_permute_r. - rewrite <- IHy; apply Pmult_xO_permute_r. - apply Pmult_1_r. + intros p q; induction q as [q IHq|q IHq| ]; simpl; try rewrite <- IHq; + auto using Pmult_xI_permute_r, Pmult_xO_permute_r, Pmult_1_r. Qed. (** Distributivity of multiplication over addition *) Theorem Pmult_plus_distr_l : - forall p q r:positive, p * (q + r) = p * q + p * r. -Proof. -intros x y z; induction x; simpl in |- *. - rewrite IHx; rewrite <- Pplus_assoc with (q := xO (x * y)); - rewrite Pplus_assoc with (p := xO (x * y)); - rewrite Pplus_comm with (p := xO (x * y)); - rewrite <- Pplus_assoc with (q := xO (x * y)); - rewrite Pplus_assoc with (q := z); reflexivity. - rewrite IHx; reflexivity. + forall p q r:positive, p * (q + r) = p * q + p * r. +Proof. + intros p q r; induction p as [p IHp|p IHp| ]; simpl. + rewrite IHp. set (m:=(p*q)~0). set (n:=(p*r)~0). + change ((p*q+p*r)~0) with (m+n). + rewrite 2 Pplus_assoc; f_equal. + rewrite <- 2 Pplus_assoc; f_equal. + apply Pplus_comm. + f_equal; auto. reflexivity. Qed. Theorem Pmult_plus_distr_r : - forall p q r:positive, (p + q) * r = p * r + q * r. + forall p q r:positive, (p + q) * r = p * r + q * r. Proof. -intros x y z; do 3 rewrite Pmult_comm with (q := z); apply Pmult_plus_distr_l. + intros p q r; do 3 rewrite Pmult_comm with (q:=r); apply Pmult_plus_distr_l. Qed. (** Associativity of multiplication *) Theorem Pmult_assoc : forall p q r:positive, p * (q * r) = p * q * r. Proof. -intro x; induction x as [x| x| ]; simpl in |- *; intros y z. - rewrite IHx; rewrite Pmult_plus_distr_r; reflexivity. - rewrite IHx; reflexivity. + induction p as [p IHp| p IHp | ]; simpl; intros q r. + rewrite IHp; rewrite Pmult_plus_distr_r; reflexivity. + rewrite IHp; reflexivity. reflexivity. Qed. (** Parity properties of multiplication *) -Lemma Pmult_xI_mult_xO_discr : forall p q r:positive, xI p * r <> xO q * r. +Lemma Pmult_xI_mult_xO_discr : forall p q r:positive, p~1 * r <> q~0 * r. Proof. -intros x y z; induction z as [| z IHz| ]; try discriminate. -intro H; apply IHz; clear IHz. -do 2 rewrite Pmult_xO_permute_r in H. -injection H; clear H; intro H; exact H. + intros p q r; induction r; try discriminate. + rewrite 2 Pmult_xO_permute_r; intro H; destr_eq H; auto. Qed. -Lemma Pmult_xO_discr : forall p q:positive, xO p * q <> q. +Lemma Pmult_xO_discr : forall p q:positive, p~0 * q <> q. Proof. -intros x y; induction y; try discriminate. -rewrite Pmult_xO_permute_r; injection; assumption. + intros p q; induction q; try discriminate. + rewrite Pmult_xO_permute_r; injection; assumption. Qed. (** Simplification properties of multiplication *) Theorem Pmult_reg_r : forall p q r:positive, p * r = q * r -> p = q. Proof. -intro x; induction x as [p IHp| p IHp| ]; intro y; destruct y as [q| q| ]; - intros z H; reflexivity || apply (f_equal (A:=positive)) || apply False_ind. - simpl in H; apply IHp with (xO z); simpl in |- *; - do 2 rewrite Pmult_xO_permute_r; apply Pplus_reg_l with (1 := H). - apply Pmult_xI_mult_xO_discr with (1 := H). - simpl in H; rewrite Pplus_comm in H; apply Pplus_no_neutral with (1 := H). - symmetry in H; apply Pmult_xI_mult_xO_discr with (1 := H). - apply IHp with (xO z); simpl in |- *; do 2 rewrite Pmult_xO_permute_r; - assumption. - apply Pmult_xO_discr with (1 := H). - simpl in H; symmetry in H; rewrite Pplus_comm in H; - apply Pplus_no_neutral with (1 := H). - symmetry in H; apply Pmult_xO_discr with (1 := H). + induction p as [p IHp| p IHp| ]; intros [q|q| ] r H; + reflexivity || apply (f_equal (A:=positive)) || apply False_ind. + apply IHp with (r~0); simpl in *; + rewrite 2 Pmult_xO_permute_r; apply Pplus_reg_l with (1:=H). + apply Pmult_xI_mult_xO_discr with (1:=H). + simpl in H; rewrite Pplus_comm in H; apply Pplus_no_neutral with (1:=H). + symmetry in H; apply Pmult_xI_mult_xO_discr with (1:=H). + apply IHp with (r~0); simpl; rewrite 2 Pmult_xO_permute_r; assumption. + apply Pmult_xO_discr with (1:= H). + simpl in H; symmetry in H; rewrite Pplus_comm in H; + apply Pplus_no_neutral with (1:=H). + symmetry in H; apply Pmult_xO_discr with (1:=H). Qed. Theorem Pmult_reg_l : forall p q r:positive, r * p = r * q -> p = q. Proof. -intros x y z H; apply Pmult_reg_r with (r := z). -rewrite Pmult_comm with (p := x); rewrite Pmult_comm with (p := y); - assumption. + intros p q r H; apply Pmult_reg_r with (r:=r). + rewrite (Pmult_comm p), (Pmult_comm q); assumption. Qed. (** Inversion of multiplication *) -Lemma Pmult_1_inversion_l : forall p q:positive, p * q = xH -> p = xH. +Lemma Pmult_1_inversion_l : forall p q:positive, p * q = 1 -> p = 1. Proof. -intros x y; destruct x as [p| p| ]; simpl in |- *. - destruct y as [p0| p0| ]; intro; discriminate. - intro; discriminate. - reflexivity. + intros [p|p| ] [q|q| ] H; destr_eq H; auto. Qed. (**********************************************************************) (** Properties of comparison on binary positive numbers *) +Theorem Pcompare_refl : forall p:positive, (p ?= p) Eq = Eq. + induction p; auto. +Qed. + +(* A generalization of Pcompare_refl *) + +Theorem Pcompare_refl_id : forall (p : positive) (r : comparison), (p ?= p) r = r. + induction p; auto. +Qed. + Theorem Pcompare_not_Eq : - forall p q:positive, (p ?= q) Gt <> Eq /\ (p ?= q) Lt <> Eq. + forall p q:positive, (p ?= q) Gt <> Eq /\ (p ?= q) Lt <> Eq. Proof. -intro x; induction x as [p IHp| p IHp| ]; intro y; destruct y as [q| q| ]; - split; simpl in |- *; auto; discriminate || (elim (IHp q); auto). + induction p as [p IHp| p IHp| ]; intros [q| q| ]; split; simpl; auto; + discriminate || (elim (IHp q); auto). Qed. Theorem Pcompare_Eq_eq : forall p q:positive, (p ?= q) Eq = Eq -> p = q. Proof. -intro x; induction x as [p IHp| p IHp| ]; intro y; destruct y as [q| q| ]; - simpl in |- *; auto; intro H; - [ rewrite (IHp q); trivial - | absurd ((p ?= q) Gt = Eq); - [ elim (Pcompare_not_Eq p q); auto | assumption ] - | discriminate H - | absurd ((p ?= q) Lt = Eq); - [ elim (Pcompare_not_Eq p q); auto | assumption ] - | rewrite (IHp q); auto - | discriminate H - | discriminate H - | discriminate H ]. + induction p; intros [q| q| ] H; simpl in *; auto; + try discriminate H; try (f_equal; auto; fail). + destruct (Pcompare_not_Eq p q) as (H',_); elim H'; auto. + destruct (Pcompare_not_Eq p q) as (_,H'); elim H'; auto. Qed. Lemma Pcompare_Gt_Lt : - forall p q:positive, (p ?= q) Gt = Lt -> (p ?= q) Eq = Lt. + forall p q:positive, (p ?= q) Gt = Lt -> (p ?= q) Eq = Lt. Proof. -intro x; induction x as [x Hrecx| x Hrecx| ]; intro y; - [ induction y as [y Hrecy| y Hrecy| ] - | induction y as [y Hrecy| y Hrecy| ] - | induction y as [y Hrecy| y Hrecy| ] ]; simpl in |- *; - auto; discriminate || intros H; discriminate H. + induction p; intros [q|q| ] H; simpl; auto; discriminate. +Qed. + +Lemma Pcompare_eq_Lt : + forall p q : positive, (p ?= q) Eq = Lt <-> (p ?= q) Gt = Lt. +Proof. + intros p q; split; [| apply Pcompare_Gt_Lt]. + revert q; induction p; intros [q|q| ] H; simpl; auto; discriminate. Qed. Lemma Pcompare_Lt_Gt : - forall p q:positive, (p ?= q) Lt = Gt -> (p ?= q) Eq = Gt. + forall p q:positive, (p ?= q) Lt = Gt -> (p ?= q) Eq = Gt. Proof. -intro x; induction x as [x Hrecx| x Hrecx| ]; intro y; - [ induction y as [y Hrecy| y Hrecy| ] - | induction y as [y Hrecy| y Hrecy| ] - | induction y as [y Hrecy| y Hrecy| ] ]; simpl in |- *; - auto; discriminate || intros H; discriminate H. + induction p; intros [q|q| ] H; simpl; auto; discriminate. +Qed. + +Lemma Pcompare_eq_Gt : + forall p q : positive, (p ?= q) Eq = Gt <-> (p ?= q) Lt = Gt. +Proof. + intros p q; split; [| apply Pcompare_Lt_Gt]. + revert q; induction p; intros [q|q| ] H; simpl; auto; discriminate. Qed. Lemma Pcompare_Lt_Lt : - forall p q:positive, (p ?= q) Lt = Lt -> (p ?= q) Eq = Lt \/ p = q. + forall p q:positive, (p ?= q) Lt = Lt -> (p ?= q) Eq = Lt \/ p = q. Proof. -intro x; induction x as [p IHp| p IHp| ]; intro y; destruct y as [q| q| ]; - simpl in |- *; auto; try discriminate; intro H2; elim (IHp q H2); - auto; intros E; rewrite E; auto. + induction p as [p IHp| p IHp| ]; intros [q|q| ] H; simpl in *; auto; + destruct (IHp q H); subst; auto. +Qed. + +Lemma Pcompare_Lt_eq_Lt : + forall p q:positive, (p ?= q) Lt = Lt <-> (p ?= q) Eq = Lt \/ p = q. +Proof. + intros p q; split; [apply Pcompare_Lt_Lt |]. + intros [H|H]; [|subst; apply Pcompare_refl_id]. + revert q H; induction p; intros [q|q| ] H; simpl in *; + auto; discriminate. Qed. Lemma Pcompare_Gt_Gt : - forall p q:positive, (p ?= q) Gt = Gt -> (p ?= q) Eq = Gt \/ p = q. + forall p q:positive, (p ?= q) Gt = Gt -> (p ?= q) Eq = Gt \/ p = q. +Proof. + induction p as [p IHp|p IHp| ]; intros [q|q| ] H; simpl in *; auto; + destruct (IHp q H); subst; auto. +Qed. + +Lemma Pcompare_Gt_eq_Gt : + forall p q:positive, (p ?= q) Gt = Gt <-> (p ?= q) Eq = Gt \/ p = q. Proof. -intro x; induction x as [p IHp| p IHp| ]; intro y; destruct y as [q| q| ]; - simpl in |- *; auto; try discriminate; intro H2; elim (IHp q H2); - auto; intros E; rewrite E; auto. + intros p q; split; [apply Pcompare_Gt_Gt |]. + intros [H|H]; [|subst; apply Pcompare_refl_id]. + revert q H; induction p; intros [q|q| ] H; simpl in *; + auto; discriminate. Qed. Lemma Dcompare : forall r:comparison, r = Eq \/ r = Lt \/ r = Gt. Proof. -simple induction r; auto. + destruct r; auto. Qed. Ltac ElimPcompare c1 c2 := elim (Dcompare ((c1 ?= c2) Eq)); - [ idtac | let x := fresh "H" in - (intro x; case x; clear x) ]. - -Theorem Pcompare_refl : forall p:positive, (p ?= p) Eq = Eq. -intro x; induction x as [x Hrecx| x Hrecx| ]; auto. -Qed. + [ idtac | let x := fresh "H" in (intro x; case x; clear x) ]. Lemma Pcompare_antisym : - forall (p q:positive) (r:comparison), - CompOpp ((p ?= q) r) = (q ?= p) (CompOpp r). + forall (p q:positive) (r:comparison), + CompOpp ((p ?= q) r) = (q ?= p) (CompOpp r). Proof. -intro x; induction x as [p IHp| p IHp| ]; intro y; - [ destruct y as [p0| p0| ] - | destruct y as [p0| p0| ] - | destruct y as [p| p| ] ]; intro r; - reflexivity || - (symmetry in |- *; assumption) || discriminate H || simpl in |- *; - apply IHp || (try rewrite IHp); try reflexivity. + induction p as [p IHp|p IHp| ]; intros [q|q| ] r; simpl; auto; + rewrite IHp; auto. Qed. Lemma ZC1 : forall p q:positive, (p ?= q) Eq = Gt -> (q ?= p) Eq = Lt. Proof. -intros; change Eq with (CompOpp Eq) in |- *. -rewrite <- Pcompare_antisym; rewrite H; reflexivity. + intros p q H; change Eq with (CompOpp Eq). + rewrite <- Pcompare_antisym, H; reflexivity. Qed. Lemma ZC2 : forall p q:positive, (p ?= q) Eq = Lt -> (q ?= p) Eq = Gt. Proof. -intros; change Eq with (CompOpp Eq) in |- *. -rewrite <- Pcompare_antisym; rewrite H; reflexivity. + intros p q H; change Eq with (CompOpp Eq). + rewrite <- Pcompare_antisym, H; reflexivity. Qed. Lemma ZC3 : forall p q:positive, (p ?= q) Eq = Eq -> (q ?= p) Eq = Eq. Proof. -intros; change Eq with (CompOpp Eq) in |- *. -rewrite <- Pcompare_antisym; rewrite H; reflexivity. + intros p q H; change Eq with (CompOpp Eq). + rewrite <- Pcompare_antisym, H; reflexivity. Qed. Lemma ZC4 : forall p q:positive, (p ?= q) Eq = CompOpp ((q ?= p) Eq). Proof. -intros; change Eq at 1 with (CompOpp Eq) in |- *. -symmetry in |- *; apply Pcompare_antisym. + intros; change Eq at 1 with (CompOpp Eq). + symmetry; apply Pcompare_antisym. +Qed. + +(** Comparison and the successor *) + +Lemma Pcompare_p_Sp : forall p : positive, (p ?= Psucc p) Eq = Lt. +Proof. + induction p; simpl in *; + [ elim (Pcompare_eq_Lt p (Psucc p)); auto | + apply Pcompare_refl_id | reflexivity]. +Qed. + +Theorem Pcompare_p_Sq : forall p q : positive, + (p ?= Psucc q) Eq = Lt <-> (p ?= q) Eq = Lt \/ p = q. +Proof. + intros p q; split. + (* -> *) + revert p q; induction p as [p IHp|p IHp| ]; intros [q|q| ] H; simpl in *; + try (left; reflexivity); try (right; reflexivity). + destruct (IHp q (Pcompare_Gt_Lt _ _ H)); subst; auto. + destruct (Pcompare_eq_Lt p q); auto. + destruct p; discriminate. + left; destruct (IHp q H); + [ elim (Pcompare_Lt_eq_Lt p q); auto | subst; apply Pcompare_refl_id]. + destruct (Pcompare_Lt_Lt p q H); subst; auto. + destruct p; discriminate. + (* <- *) + intros [H|H]; [|subst; apply Pcompare_p_Sp]. + revert q H; induction p; intros [q|q| ] H; simpl in *; + auto; try discriminate. + destruct (Pcompare_eq_Lt p (Psucc q)); auto. + apply Pcompare_Gt_Lt; auto. + destruct (Pcompare_Lt_Lt p q H); subst; auto using Pcompare_p_Sp. + destruct (Pcompare_Lt_eq_Lt p q); auto. +Qed. + +(** 1 is the least positive number *) + +Lemma Pcompare_1 : forall p, ~ (p ?= 1) Eq = Lt. +Proof. + destruct p; discriminate. +Qed. + +(** Properties of the strict order on positive numbers *) + +Lemma Plt_1 : forall p, ~ p < 1. +Proof. + exact Pcompare_1. +Qed. + +Lemma Plt_lt_succ : forall n m : positive, n < m -> n < Psucc m. +Proof. + unfold Plt; intros n m H; apply <- Pcompare_p_Sq; auto. +Qed. + +Lemma Plt_irrefl : forall p : positive, ~ p < p. +Proof. + unfold Plt; intro p; rewrite Pcompare_refl; discriminate. +Qed. + +Lemma Plt_trans : forall n m p : positive, n < m -> m < p -> n < p. +Proof. + intros n m p; induction p using Pind; intros H H0. + elim (Plt_1 _ H0). + apply Plt_lt_succ. + destruct (Pcompare_p_Sq m p) as (H',_); destruct (H' H0); subst; auto. +Qed. + +Theorem Plt_ind : forall (A : positive -> Prop) (n : positive), + A (Psucc n) -> + (forall m : positive, n < m -> A m -> A (Psucc m)) -> + forall m : positive, n < m -> A m. +Proof. + intros A n AB AS m. induction m using Pind; intros H. + elim (Plt_1 _ H). + destruct (Pcompare_p_Sq n m) as (H',_); destruct (H' H); subst; auto. Qed. (**********************************************************************) (** Properties of subtraction on binary positive numbers *) +Lemma Ppred_minus : forall p, Ppred p = Pminus p 1. +Proof. + destruct p; auto. +Qed. + +Definition Ppred_mask (p : positive_mask) := +match p with +| IsPos 1 => IsNul +| IsPos q => IsPos (Ppred q) +| IsNul => IsNeg +| IsNeg => IsNeg +end. + +Lemma Pminus_mask_succ_r : + forall p q : positive, Pminus_mask p (Psucc q) = Pminus_mask_carry p q. +Proof. + induction p ; destruct q; simpl; f_equal; auto; destruct p; auto. +Qed. + +Theorem Pminus_mask_carry_spec : + forall p q : positive, Pminus_mask_carry p q = Ppred_mask (Pminus_mask p q). +Proof. + induction p as [p IHp|p IHp| ]; destruct q; simpl; + try reflexivity; try rewrite IHp; + destruct (Pminus_mask p q) as [|[r|r| ]|] || destruct p; auto. +Qed. + +Theorem Pminus_succ_r : forall p q : positive, p - (Psucc q) = Ppred (p - q). +Proof. + intros p q; unfold Pminus; + rewrite Pminus_mask_succ_r, Pminus_mask_carry_spec. + destruct (Pminus_mask p q) as [|[r|r| ]|]; auto. +Qed. + Lemma double_eq_zero_inversion : - forall p:positive_mask, Pdouble_mask p = IsNul -> p = IsNul. + forall p:positive_mask, Pdouble_mask p = IsNul -> p = IsNul. Proof. -destruct p; simpl in |- *; [ trivial | discriminate 1 | discriminate 1 ]. + destruct p; simpl; intros; trivial; discriminate. Qed. Lemma double_plus_one_zero_discr : - forall p:positive_mask, Pdouble_plus_one_mask p <> IsNul. + forall p:positive_mask, Pdouble_plus_one_mask p <> IsNul. Proof. -simple induction p; intros; discriminate. + destruct p; discriminate. Qed. Lemma double_plus_one_eq_one_inversion : - forall p:positive_mask, Pdouble_plus_one_mask p = IsPos xH -> p = IsNul. + forall p:positive_mask, Pdouble_plus_one_mask p = IsPos 1 -> p = IsNul. Proof. -destruct p; simpl in |- *; [ trivial | discriminate 1 | discriminate 1 ]. + destruct p; simpl; intros; trivial; discriminate. Qed. Lemma double_eq_one_discr : - forall p:positive_mask, Pdouble_mask p <> IsPos xH. + forall p:positive_mask, Pdouble_mask p <> IsPos 1. Proof. -simple induction p; intros; discriminate. + destruct p; discriminate. Qed. Theorem Pminus_mask_diag : forall p:positive, Pminus_mask p p = IsNul. Proof. -intro x; induction x as [p IHp| p IHp| ]; - [ simpl in |- *; rewrite IHp; simpl in |- *; trivial - | simpl in |- *; rewrite IHp; auto - | auto ]. + induction p as [p IHp| p IHp| ]; simpl; try rewrite IHp; auto. +Qed. + +Lemma Pminus_mask_carry_diag : forall p, Pminus_mask_carry p p = IsNeg. +Proof. + induction p as [p IHp| p IHp| ]; simpl; try rewrite IHp; auto. +Qed. + +Lemma Pminus_mask_IsNeg : forall p q:positive, + Pminus_mask p q = IsNeg -> Pminus_mask_carry p q = IsNeg. +Proof. + induction p as [p IHp|p IHp| ]; intros [q|q| ] H; simpl in *; auto; + try discriminate; unfold Pdouble_mask, Pdouble_plus_one_mask in H; + specialize IHp with q. + destruct (Pminus_mask p q); try discriminate; rewrite IHp; auto. + destruct (Pminus_mask p q); simpl; auto; try discriminate. + destruct (Pminus_mask_carry p q); simpl; auto; try discriminate. + destruct (Pminus_mask p q); try discriminate; rewrite IHp; auto. Qed. Lemma ZL10 : - forall p q:positive, - Pminus_mask p q = IsPos xH -> Pminus_mask_carry p q = IsNul. -Proof. -intro x; induction x as [p| p| ]; intro y; destruct y as [q| q| ]; - simpl in |- *; intro H; try discriminate H; - [ absurd (Pdouble_mask (Pminus_mask p q) = IsPos xH); - [ apply double_eq_one_discr | assumption ] - | assert (Heq : Pminus_mask p q = IsNul); - [ apply double_plus_one_eq_one_inversion; assumption - | rewrite Heq; reflexivity ] - | assert (Heq : Pminus_mask_carry p q = IsNul); - [ apply double_plus_one_eq_one_inversion; assumption - | rewrite Heq; reflexivity ] - | absurd (Pdouble_mask (Pminus_mask p q) = IsPos xH); - [ apply double_eq_one_discr | assumption ] - | destruct p; simpl in |- *; - [ discriminate H | discriminate H | reflexivity ] ]. + forall p q:positive, + Pminus_mask p q = IsPos 1 -> Pminus_mask_carry p q = IsNul. +Proof. + induction p; intros [q|q| ] H; simpl in *; try discriminate. + elim (double_eq_one_discr _ H). + rewrite (double_plus_one_eq_one_inversion _ H); auto. + rewrite (double_plus_one_eq_one_inversion _ H); auto. + elim (double_eq_one_discr _ H). + destruct p; simpl; auto; discriminate. Qed. (** Properties of subtraction valid only for x>y *) Lemma Pminus_mask_Gt : - forall p q:positive, - (p ?= q) Eq = Gt -> + forall p q:positive, + (p ?= q) Eq = Gt -> exists h : positive, - Pminus_mask p q = IsPos h /\ - q + h = p /\ (h = xH \/ Pminus_mask_carry p q = IsPos (Ppred h)). -Proof. -intro x; induction x as [p| p| ]; intro y; destruct y as [q| q| ]; - simpl in |- *; intro H; try discriminate H. - destruct (IHp q H) as [z [H4 [H6 H7]]]; exists (xO z); split. - rewrite H4; reflexivity. - split. - simpl in |- *; rewrite H6; reflexivity. - right; clear H6; destruct (ZL11 z) as [H8| H8]; - [ rewrite H8; rewrite H8 in H4; rewrite ZL10; - [ reflexivity | assumption ] - | clear H4; destruct H7 as [H9| H9]; - [ absurd (z = xH); assumption - | rewrite H9; clear H9; destruct z as [p0| p0| ]; - [ reflexivity | reflexivity | absurd (xH = xH); trivial ] ] ]. - case Pcompare_Gt_Gt with (1 := H); - [ intros H3; elim (IHp q H3); intros z H4; exists (xI z); elim H4; - intros H5 H6; elim H6; intros H7 H8; split; - [ simpl in |- *; rewrite H5; auto - | split; - [ simpl in |- *; rewrite H7; trivial - | right; - change (Pdouble_mask (Pminus_mask p q) = IsPos (Ppred (xI z))) - in |- *; rewrite H5; auto ] ] - | intros H3; exists xH; rewrite H3; split; - [ simpl in |- *; rewrite Pminus_mask_diag; auto | split; auto ] ]. - exists (xO p); auto. - destruct (IHp q) as [z [H4 [H6 H7]]]. - apply Pcompare_Lt_Gt; assumption. - destruct (ZL11 z) as [vZ| ]; - [ exists xH; split; - [ rewrite ZL10; [ reflexivity | rewrite vZ in H4; assumption ] - | split; - [ simpl in |- *; rewrite Pplus_one_succ_r; rewrite <- vZ; - rewrite H6; trivial - | auto ] ] - | exists (xI (Ppred z)); destruct H7 as [| H8]; - [ absurd (z = xH); assumption - | split; - [ rewrite H8; trivial - | split; - [ simpl in |- *; rewrite Pplus_carry_pred_eq_plus; - [ rewrite H6; trivial | assumption ] - | right; rewrite H8; reflexivity ] ] ] ]. - destruct (IHp q H) as [z [H4 [H6 H7]]]. - exists (xO z); split; - [ rewrite H4; auto - | split; - [ simpl in |- *; rewrite H6; reflexivity - | right; - change - (Pdouble_plus_one_mask (Pminus_mask_carry p q) = - IsPos (Pdouble_minus_one z)) in |- *; - destruct (ZL11 z) as [H8| H8]; - [ rewrite H8; simpl in |- *; - assert (H9 : Pminus_mask_carry p q = IsNul); - [ apply ZL10; rewrite <- H8; assumption - | rewrite H9; reflexivity ] - | destruct H7 as [H9| H9]; - [ absurd (z = xH); auto - | rewrite H9; destruct z as [p0| p0| ]; simpl in |- *; - [ reflexivity - | reflexivity - | absurd (xH = xH); [ assumption | reflexivity ] ] ] ] ] ]. - exists (Pdouble_minus_one p); split; - [ reflexivity - | clear IHp; split; - [ destruct p; simpl in |- *; - [ reflexivity - | rewrite Psucc_o_double_minus_one_eq_xO; reflexivity - | reflexivity ] - | destruct p; [ right | right | left ]; reflexivity ] ]. + Pminus_mask p q = IsPos h /\ + q + h = p /\ (h = 1 \/ Pminus_mask_carry p q = IsPos (Ppred h)). +Proof. + induction p as [p IHp| p IHp| ]; intros [q| q| ] H; simpl in *; + try discriminate H. + (* p~1, q~1 *) + destruct (IHp q H) as (r & U & V & W); exists (r~0); rewrite ?U, ?V; auto. + repeat split; auto; right. + destruct (ZL11 r) as [EQ|NE]; [|destruct W as [|W]; [elim NE; auto|]]. + rewrite ZL10; subst; auto. + rewrite W; simpl; destruct r; auto; elim NE; auto. + (* p~1, q~0 *) + destruct (Pcompare_Gt_Gt _ _ H) as [H'|H']; clear H; rename H' into H. + destruct (IHp q H) as (r & U & V & W); exists (r~1); rewrite ?U, ?V; auto. + exists 1; subst; rewrite Pminus_mask_diag; auto. + (* p~1, 1 *) + exists (p~0); auto. + (* p~0, q~1 *) + destruct (IHp q (Pcompare_Lt_Gt _ _ H)) as (r & U & V & W). + destruct (ZL11 r) as [EQ|NE]; [|destruct W as [|W]; [elim NE; auto|]]. + exists 1; subst; rewrite ZL10, Pplus_one_succ_r; auto. + exists ((Ppred r)~1); rewrite W, Pplus_carry_pred_eq_plus, V; auto. + (* p~0, q~0 *) + destruct (IHp q H) as (r & U & V & W); exists (r~0); rewrite ?U, ?V; auto. + repeat split; auto; right. + destruct (ZL11 r) as [EQ|NE]; [|destruct W as [|W]; [elim NE; auto|]]. + rewrite ZL10; subst; auto. + rewrite W; simpl; destruct r; auto; elim NE; auto. + (* p~0, 1 *) + exists (Pdouble_minus_one p); repeat split; destruct p; simpl; auto. + rewrite Psucc_o_double_minus_one_eq_xO; auto. Qed. Theorem Pplus_minus : - forall p q:positive, (p ?= q) Eq = Gt -> q + (p - q) = p. + forall p q:positive, (p ?= q) Eq = Gt -> q + (p - q) = p. +Proof. + intros p q H; destruct (Pminus_mask_Gt p q H) as (r & U & V & _). + unfold Pminus; rewrite U; simpl; auto. +Qed. + +(** When x<y, the substraction of x by y returns 1 *) + +Lemma Pminus_mask_Lt : forall p q:positive, p<q -> Pminus_mask p q = IsNeg. +Proof. + unfold Plt; induction p as [p IHp|p IHp| ]; destruct q; simpl; intros; + try discriminate; try rewrite IHp; auto. + apply Pcompare_Gt_Lt; auto. + destruct (Pcompare_Lt_Lt _ _ H). + rewrite Pminus_mask_IsNeg; simpl; auto. + subst; rewrite Pminus_mask_carry_diag; auto. +Qed. + +Lemma Pminus_Lt : forall p q:positive, p<q -> p-q = 1. Proof. -intros x y H; elim Pminus_mask_Gt with (1 := H); intros z H1; elim H1; - intros H2 H3; elim H3; intros H4 H5; unfold Pminus in |- *; - rewrite H2; exact H4. + intros; unfold Plt, Pminus; rewrite Pminus_mask_Lt; auto. Qed. + +(** The substraction of x by x returns 1 *) + +Lemma Pminus_Eq : forall p:positive, p-p = 1. +Proof. + intros; unfold Pminus; rewrite Pminus_mask_diag; auto. +Qed. + +(** Number of digits in a number *) + +Fixpoint Psize (p:positive) : nat := + match p with + | 1 => S O + | p~1 => S (Psize p) + | p~0 => S (Psize p) + end. + +Lemma Psize_monotone : forall p q, (p?=q) Eq = Lt -> (Psize p <= Psize q)%nat. +Proof. + assert (le0 : forall n, (0<=n)%nat) by (induction n; auto). + assert (leS : forall n m, (n<=m -> S n <= S m)%nat) by (induction 1; auto). + induction p; destruct q; simpl; auto; intros; try discriminate. + intros; generalize (Pcompare_Gt_Lt _ _ H); auto. + intros; destruct (Pcompare_Lt_Lt _ _ H); auto; subst; auto. +Qed. + + + + + diff --git a/theories/NArith/NArith.v b/theories/NArith/NArith.v index 019ef5f7..6ece00d7 100644 --- a/theories/NArith/NArith.v +++ b/theories/NArith/NArith.v @@ -6,11 +6,13 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: NArith.v 9210 2006-10-05 10:12:15Z barras $ *) +(* $Id: NArith.v 10751 2008-04-04 10:23:35Z herbelin $ *) (** Library for binary natural numbers *) Require Export BinPos. Require Export BinNat. +Require Export Nnat. +Require Export Ndigits. Require Export NArithRing. diff --git a/theories/NArith/Ndec.v b/theories/NArith/Ndec.v index df2da25b..5bd9a378 100644 --- a/theories/NArith/Ndec.v +++ b/theories/NArith/Ndec.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Ndec.v 8733 2006-04-25 22:52:18Z letouzey $ i*) +(*i $Id: Ndec.v 10739 2008-04-01 14:45:20Z herbelin $ i*) Require Import Bool. Require Import Sumbool. @@ -37,6 +37,13 @@ Proof. induction p; destruct p'; simpl; intros; try discriminate; auto. Qed. +Lemma Peqb_complete : forall p p', Peqb p p' = true -> p = p'. +Proof. + intros. + apply Pcompare_Eq_eq. + apply Peqb_Pcompare; auto. +Qed. + Lemma Pcompare_Peqb : forall p p', Pcompare p p' Eq = Eq -> Peqb p p' = true. Proof. intros; rewrite <- (Pcompare_Eq_eq _ _ H). @@ -208,205 +215,220 @@ Qed. (** A boolean order on [N] *) -Definition Nle (a b:N) := leb (nat_of_N a) (nat_of_N b). +Definition Nleb (a b:N) := leb (nat_of_N a) (nat_of_N b). -Lemma Nle_Ncompare : forall a b, Nle a b = true <-> Ncompare a b <> Gt. +Lemma Nleb_Nle : forall a b, Nleb a b = true <-> Nle a b. Proof. - intros; rewrite nat_of_Ncompare. - unfold Nle; apply leb_compare. + intros; unfold Nle; rewrite nat_of_Ncompare. + unfold Nleb; apply leb_compare. Qed. -Lemma Nle_refl : forall a, Nle a a = true. +Lemma Nleb_refl : forall a, Nleb a a = true. Proof. - intro. unfold Nle in |- *. apply leb_correct. apply le_n. + intro. unfold Nleb in |- *. apply leb_correct. apply le_n. Qed. -Lemma Nle_antisym : - forall a b, Nle a b = true -> Nle b a = true -> a = b. +Lemma Nleb_antisym : + forall a b, Nleb a b = true -> Nleb b a = true -> a = b. Proof. - unfold Nle in |- *. intros. rewrite <- (N_of_nat_of_N a). rewrite <- (N_of_nat_of_N b). + unfold Nleb in |- *. intros. rewrite <- (N_of_nat_of_N a). rewrite <- (N_of_nat_of_N b). rewrite (le_antisym _ _ (leb_complete _ _ H) (leb_complete _ _ H0)). reflexivity. Qed. -Lemma Nle_trans : - forall a b c, Nle a b = true -> Nle b c = true -> Nle a c = true. +Lemma Nleb_trans : + forall a b c, Nleb a b = true -> Nleb b c = true -> Nleb a c = true. Proof. - unfold Nle in |- *. intros. apply leb_correct. apply le_trans with (m := nat_of_N b). + unfold Nleb in |- *. intros. apply leb_correct. apply le_trans with (m := nat_of_N b). apply leb_complete. assumption. apply leb_complete. assumption. Qed. -Lemma Nle_lt_trans : +Lemma Nleb_ltb_trans : forall a b c, - Nle a b = true -> Nle c b = false -> Nle c a = false. + Nleb a b = true -> Nleb c b = false -> Nleb c a = false. Proof. - unfold Nle in |- *. intros. apply leb_correct_conv. apply le_lt_trans with (m := nat_of_N b). + unfold Nleb in |- *. intros. apply leb_correct_conv. apply le_lt_trans with (m := nat_of_N b). apply leb_complete. assumption. apply leb_complete_conv. assumption. Qed. -Lemma Nlt_le_trans : +Lemma Nltb_leb_trans : forall a b c, - Nle b a = false -> Nle b c = true -> Nle c a = false. + Nleb b a = false -> Nleb b c = true -> Nleb c a = false. Proof. - unfold Nle in |- *. intros. apply leb_correct_conv. apply lt_le_trans with (m := nat_of_N b). + unfold Nleb in |- *. intros. apply leb_correct_conv. apply lt_le_trans with (m := nat_of_N b). apply leb_complete_conv. assumption. apply leb_complete. assumption. Qed. -Lemma Nlt_trans : +Lemma Nltb_trans : forall a b c, - Nle b a = false -> Nle c b = false -> Nle c a = false. + Nleb b a = false -> Nleb c b = false -> Nleb c a = false. Proof. - unfold Nle in |- *. intros. apply leb_correct_conv. apply lt_trans with (m := nat_of_N b). + unfold Nleb in |- *. intros. apply leb_correct_conv. apply lt_trans with (m := nat_of_N b). apply leb_complete_conv. assumption. apply leb_complete_conv. assumption. Qed. -Lemma Nlt_le_weak : forall a b:N, Nle b a = false -> Nle a b = true. +Lemma Nltb_leb_weak : forall a b:N, Nleb b a = false -> Nleb a b = true. Proof. - unfold Nle in |- *. intros. apply leb_correct. apply lt_le_weak. + unfold Nleb in |- *. intros. apply leb_correct. apply lt_le_weak. apply leb_complete_conv. assumption. Qed. -Lemma Nle_double_mono : +Lemma Nleb_double_mono : forall a b, - Nle a b = true -> Nle (Ndouble a) (Ndouble b) = true. + Nleb a b = true -> Nleb (Ndouble a) (Ndouble b) = true. Proof. - unfold Nle in |- *. intros. rewrite nat_of_Ndouble. rewrite nat_of_Ndouble. apply leb_correct. + unfold Nleb in |- *. intros. rewrite nat_of_Ndouble. rewrite nat_of_Ndouble. apply leb_correct. simpl in |- *. apply plus_le_compat. apply leb_complete. assumption. apply plus_le_compat. apply leb_complete. assumption. apply le_n. Qed. -Lemma Nle_double_plus_one_mono : +Lemma Nleb_double_plus_one_mono : forall a b, - Nle a b = true -> - Nle (Ndouble_plus_one a) (Ndouble_plus_one b) = true. + Nleb a b = true -> + Nleb (Ndouble_plus_one a) (Ndouble_plus_one b) = true. Proof. - unfold Nle in |- *. intros. rewrite nat_of_Ndouble_plus_one. rewrite nat_of_Ndouble_plus_one. + unfold Nleb in |- *. intros. rewrite nat_of_Ndouble_plus_one. rewrite nat_of_Ndouble_plus_one. apply leb_correct. apply le_n_S. simpl in |- *. apply plus_le_compat. apply leb_complete. assumption. apply plus_le_compat. apply leb_complete. assumption. apply le_n. Qed. -Lemma Nle_double_mono_conv : +Lemma Nleb_double_mono_conv : forall a b, - Nle (Ndouble a) (Ndouble b) = true -> Nle a b = true. + Nleb (Ndouble a) (Ndouble b) = true -> Nleb a b = true. Proof. - unfold Nle in |- *. intros a b. rewrite nat_of_Ndouble. rewrite nat_of_Ndouble. intro. + unfold Nleb in |- *. intros a b. rewrite nat_of_Ndouble. rewrite nat_of_Ndouble. intro. apply leb_correct. apply (mult_S_le_reg_l 1). apply leb_complete. assumption. Qed. -Lemma Nle_double_plus_one_mono_conv : +Lemma Nleb_double_plus_one_mono_conv : forall a b, - Nle (Ndouble_plus_one a) (Ndouble_plus_one b) = true -> - Nle a b = true. + Nleb (Ndouble_plus_one a) (Ndouble_plus_one b) = true -> + Nleb a b = true. Proof. - unfold Nle in |- *. intros a b. rewrite nat_of_Ndouble_plus_one. rewrite nat_of_Ndouble_plus_one. + unfold Nleb in |- *. intros a b. rewrite nat_of_Ndouble_plus_one. rewrite nat_of_Ndouble_plus_one. intro. apply leb_correct. apply (mult_S_le_reg_l 1). apply le_S_n. apply leb_complete. assumption. Qed. -Lemma Nlt_double_mono : +Lemma Nltb_double_mono : forall a b, - Nle a b = false -> Nle (Ndouble a) (Ndouble b) = false. + Nleb a b = false -> Nleb (Ndouble a) (Ndouble b) = false. Proof. - intros. elim (sumbool_of_bool (Nle (Ndouble a) (Ndouble b))). intro H0. - rewrite (Nle_double_mono_conv _ _ H0) in H. discriminate H. + intros. elim (sumbool_of_bool (Nleb (Ndouble a) (Ndouble b))). intro H0. + rewrite (Nleb_double_mono_conv _ _ H0) in H. discriminate H. trivial. Qed. -Lemma Nlt_double_plus_one_mono : +Lemma Nltb_double_plus_one_mono : forall a b, - Nle a b = false -> - Nle (Ndouble_plus_one a) (Ndouble_plus_one b) = false. + Nleb a b = false -> + Nleb (Ndouble_plus_one a) (Ndouble_plus_one b) = false. Proof. - intros. elim (sumbool_of_bool (Nle (Ndouble_plus_one a) (Ndouble_plus_one b))). intro H0. - rewrite (Nle_double_plus_one_mono_conv _ _ H0) in H. discriminate H. + intros. elim (sumbool_of_bool (Nleb (Ndouble_plus_one a) (Ndouble_plus_one b))). intro H0. + rewrite (Nleb_double_plus_one_mono_conv _ _ H0) in H. discriminate H. trivial. Qed. -Lemma Nlt_double_mono_conv : +Lemma Nltb_double_mono_conv : forall a b, - Nle (Ndouble a) (Ndouble b) = false -> Nle a b = false. + Nleb (Ndouble a) (Ndouble b) = false -> Nleb a b = false. Proof. - intros. elim (sumbool_of_bool (Nle a b)). intro H0. rewrite (Nle_double_mono _ _ H0) in H. + intros. elim (sumbool_of_bool (Nleb a b)). intro H0. rewrite (Nleb_double_mono _ _ H0) in H. discriminate H. trivial. Qed. -Lemma Nlt_double_plus_one_mono_conv : +Lemma Nltb_double_plus_one_mono_conv : forall a b, - Nle (Ndouble_plus_one a) (Ndouble_plus_one b) = false -> - Nle a b = false. + Nleb (Ndouble_plus_one a) (Ndouble_plus_one b) = false -> + Nleb a b = false. Proof. - intros. elim (sumbool_of_bool (Nle a b)). intro H0. - rewrite (Nle_double_plus_one_mono _ _ H0) in H. discriminate H. + intros. elim (sumbool_of_bool (Nleb a b)). intro H0. + rewrite (Nleb_double_plus_one_mono _ _ H0) in H. discriminate H. trivial. Qed. -(* A [min] function over [N] *) +(* An alternate [min] function over [N] *) -Definition Nmin (a b:N) := if Nle a b then a else b. +Definition Nmin' (a b:N) := if Nleb a b then a else b. + +Lemma Nmin_Nmin' : forall a b, Nmin a b = Nmin' a b. +Proof. + unfold Nmin, Nmin', Nleb; intros. + rewrite nat_of_Ncompare. + generalize (leb_compare (nat_of_N a) (nat_of_N b)); + destruct (nat_compare (nat_of_N a) (nat_of_N b)); + destruct (leb (nat_of_N a) (nat_of_N b)); intuition. + lapply H1; intros; discriminate. + lapply H1; intros; discriminate. +Qed. Lemma Nmin_choice : forall a b, {Nmin a b = a} + {Nmin a b = b}. Proof. - unfold Nmin in |- *. intros. elim (sumbool_of_bool (Nle a b)). intro H. left. rewrite H. - reflexivity. - intro H. right. rewrite H. reflexivity. + unfold Nmin in *; intros; destruct (Ncompare a b); auto. Qed. -Lemma Nmin_le_1 : forall a b, Nle (Nmin a b) a = true. +Lemma Nmin_le_1 : forall a b, Nleb (Nmin a b) a = true. Proof. - unfold Nmin in |- *. intros. elim (sumbool_of_bool (Nle a b)). intro H. rewrite H. - apply Nle_refl. - intro H. rewrite H. apply Nlt_le_weak. assumption. + intros; rewrite Nmin_Nmin'. + unfold Nmin'; elim (sumbool_of_bool (Nleb a b)). intro H. rewrite H. + apply Nleb_refl. + intro H. rewrite H. apply Nltb_leb_weak. assumption. Qed. -Lemma Nmin_le_2 : forall a b, Nle (Nmin a b) b = true. +Lemma Nmin_le_2 : forall a b, Nleb (Nmin a b) b = true. Proof. - unfold Nmin in |- *. intros. elim (sumbool_of_bool (Nle a b)). intro H. rewrite H. assumption. - intro H. rewrite H. apply Nle_refl. + intros; rewrite Nmin_Nmin'. + unfold Nmin'; elim (sumbool_of_bool (Nleb a b)). intro H. rewrite H. assumption. + intro H. rewrite H. apply Nleb_refl. Qed. Lemma Nmin_le_3 : - forall a b c, Nle a (Nmin b c) = true -> Nle a b = true. + forall a b c, Nleb a (Nmin b c) = true -> Nleb a b = true. Proof. - unfold Nmin in |- *. intros. elim (sumbool_of_bool (Nle b c)). intro H0. rewrite H0 in H. + intros; rewrite Nmin_Nmin' in *. + unfold Nmin' in *; elim (sumbool_of_bool (Nleb b c)). intro H0. rewrite H0 in H. assumption. - intro H0. rewrite H0 in H. apply Nlt_le_weak. apply Nle_lt_trans with (b := c); assumption. + intro H0. rewrite H0 in H. apply Nltb_leb_weak. apply Nleb_ltb_trans with (b := c); assumption. Qed. Lemma Nmin_le_4 : - forall a b c, Nle a (Nmin b c) = true -> Nle a c = true. + forall a b c, Nleb a (Nmin b c) = true -> Nleb a c = true. Proof. - unfold Nmin in |- *. intros. elim (sumbool_of_bool (Nle b c)). intro H0. rewrite H0 in H. - apply Nle_trans with (b := b); assumption. + intros; rewrite Nmin_Nmin' in *. + unfold Nmin' in *; elim (sumbool_of_bool (Nleb b c)). intro H0. rewrite H0 in H. + apply Nleb_trans with (b := b); assumption. intro H0. rewrite H0 in H. assumption. Qed. Lemma Nmin_le_5 : forall a b c, - Nle a b = true -> Nle a c = true -> Nle a (Nmin b c) = true. + Nleb a b = true -> Nleb a c = true -> Nleb a (Nmin b c) = true. Proof. intros. elim (Nmin_choice b c). intro H1. rewrite H1. assumption. intro H1. rewrite H1. assumption. Qed. Lemma Nmin_lt_3 : - forall a b c, Nle (Nmin b c) a = false -> Nle b a = false. + forall a b c, Nleb (Nmin b c) a = false -> Nleb b a = false. Proof. - unfold Nmin in |- *. intros. elim (sumbool_of_bool (Nle b c)). intro H0. rewrite H0 in H. + intros; rewrite Nmin_Nmin' in *. + unfold Nmin' in *. intros. elim (sumbool_of_bool (Nleb b c)). intro H0. rewrite H0 in H. assumption. - intro H0. rewrite H0 in H. apply Nlt_trans with (b := c); assumption. + intro H0. rewrite H0 in H. apply Nltb_trans with (b := c); assumption. Qed. Lemma Nmin_lt_4 : - forall a b c, Nle (Nmin b c) a = false -> Nle c a = false. + forall a b c, Nleb (Nmin b c) a = false -> Nleb c a = false. Proof. - unfold Nmin in |- *. intros. elim (sumbool_of_bool (Nle b c)). intro H0. rewrite H0 in H. - apply Nlt_le_trans with (b := b); assumption. + intros; rewrite Nmin_Nmin' in *. + unfold Nmin' in *. elim (sumbool_of_bool (Nleb b c)). intro H0. rewrite H0 in H. + apply Nltb_leb_trans with (b := b); assumption. intro H0. rewrite H0 in H. assumption. Qed. diff --git a/theories/NArith/Ndigits.v b/theories/NArith/Ndigits.v index ed8ced5b..dcdb5f92 100644 --- a/theories/NArith/Ndigits.v +++ b/theories/NArith/Ndigits.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Ndigits.v 8736 2006-04-26 21:18:44Z letouzey $ i*) +(*i $Id: Ndigits.v 10739 2008-04-01 14:45:20Z herbelin $ i*) Require Import Bool. Require Import Bvector. @@ -577,13 +577,6 @@ Qed. (** Number of digits in a number *) -Fixpoint Psize (p:positive) : nat := - match p with - | xH => 1%nat - | xI p => S (Psize p) - | xO p => S (Psize p) - end. - Definition Nsize (n:N) : nat := match n with | N0 => 0%nat | Npos p => Psize p diff --git a/theories/NArith/Ndist.v b/theories/NArith/Ndist.v index d5bfc15c..af90b8e7 100644 --- a/theories/NArith/Ndist.v +++ b/theories/NArith/Ndist.v @@ -5,7 +5,7 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Ndist.v 8733 2006-04-25 22:52:18Z letouzey $ i*) +(*i $Id: Ndist.v 10739 2008-04-01 14:45:20Z herbelin $ i*) Require Import Arith. Require Import Min. diff --git a/theories/NArith/Nnat.v b/theories/NArith/Nnat.v index 94f50bd0..bc3711ee 100644 --- a/theories/NArith/Nnat.v +++ b/theories/NArith/Nnat.v @@ -6,15 +6,21 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Nnat.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: Nnat.v 10739 2008-04-01 14:45:20Z herbelin $ i*) Require Import Arith_base. Require Import Compare_dec. Require Import Sumbool. Require Import Div2. +Require Import Min. +Require Import Max. Require Import BinPos. Require Import BinNat. +Require Import BinInt. Require Import Pnat. +Require Import Zmax. +Require Import Zmin. +Require Import Znat. (** Translation from [N] to [nat] and back. *) @@ -108,6 +114,30 @@ Proof. apply N_of_nat_of_N. Qed. +Lemma nat_of_Nminus : + forall a a', nat_of_N (Nminus a a') = ((nat_of_N a)-(nat_of_N a'))%nat. +Proof. + destruct a; destruct a'; simpl; auto with arith. + case_eq (Pcompare p p0 Eq); simpl; intros. + rewrite (Pcompare_Eq_eq _ _ H); auto with arith. + rewrite Pminus_mask_diag. simpl. apply minus_n_n. + rewrite Pminus_mask_Lt. pose proof (nat_of_P_lt_Lt_compare_morphism _ _ H). simpl. + symmetry; apply not_le_minus_0. auto with arith. assumption. + pose proof (Pminus_mask_Gt p p0 H) as H1. destruct H1 as [q [H1 _]]. rewrite H1; simpl. + replace q with (Pminus p p0) by (unfold Pminus; now rewrite H1). + apply nat_of_P_minus_morphism; auto. +Qed. + +Lemma N_of_minus : + forall n n', N_of_nat (n-n') = Nminus (N_of_nat n) (N_of_nat n'). +Proof. + intros. + pattern n at 1; rewrite <- (nat_of_N_of_nat n). + pattern n' at 1; rewrite <- (nat_of_N_of_nat n'). + rewrite <- nat_of_Nminus. + apply N_of_nat_of_N. +Qed. + Lemma nat_of_Nmult : forall a a', nat_of_N (Nmult a a') = (nat_of_N a)*(nat_of_N a'). Proof. @@ -175,3 +205,176 @@ Proof. pattern n' at 1; rewrite <- (nat_of_N_of_nat n'). symmetry; apply nat_of_Ncompare. Qed. + +Lemma nat_of_Nmin : + forall a a', nat_of_N (Nmin a a') = min (nat_of_N a) (nat_of_N a'). +Proof. + intros; unfold Nmin; rewrite nat_of_Ncompare. + unfold nat_compare. + destruct (lt_eq_lt_dec (nat_of_N a) (nat_of_N a')) as [[|]|]; + simpl; intros; symmetry; auto with arith. + apply min_l; rewrite e; auto with arith. +Qed. + +Lemma N_of_min : + forall n n', N_of_nat (min n n') = Nmin (N_of_nat n) (N_of_nat n'). +Proof. + intros. + pattern n at 1; rewrite <- (nat_of_N_of_nat n). + pattern n' at 1; rewrite <- (nat_of_N_of_nat n'). + rewrite <- nat_of_Nmin. + apply N_of_nat_of_N. +Qed. + +Lemma nat_of_Nmax : + forall a a', nat_of_N (Nmax a a') = max (nat_of_N a) (nat_of_N a'). +Proof. + intros; unfold Nmax; rewrite nat_of_Ncompare. + unfold nat_compare. + destruct (lt_eq_lt_dec (nat_of_N a) (nat_of_N a')) as [[|]|]; + simpl; intros; symmetry; auto with arith. + apply max_r; rewrite e; auto with arith. +Qed. + +Lemma N_of_max : + forall n n', N_of_nat (max n n') = Nmax (N_of_nat n) (N_of_nat n'). +Proof. + intros. + pattern n at 1; rewrite <- (nat_of_N_of_nat n). + pattern n' at 1; rewrite <- (nat_of_N_of_nat n'). + rewrite <- nat_of_Nmax. + apply N_of_nat_of_N. +Qed. + +(** Properties concerning [Z_of_N] *) + +Lemma Z_of_nat_of_N : forall n:N, Z_of_nat (nat_of_N n) = Z_of_N n. +Proof. + destruct n; simpl; auto; symmetry; apply Zpos_eq_Z_of_nat_o_nat_of_P. +Qed. + +Lemma Z_of_N_eq : forall n m, n = m -> Z_of_N n = Z_of_N m. +Proof. + intros; f_equal; assumption. +Qed. + +Lemma Z_of_N_eq_rev : forall n m, Z_of_N n = Z_of_N m -> n = m. +Proof. + intros [|n] [|m]; simpl; intros; try discriminate; congruence. +Qed. + +Lemma Z_of_N_eq_iff : forall n m, n = m <-> Z_of_N n = Z_of_N m. +Proof. + split; [apply Z_of_N_eq | apply Z_of_N_eq_rev]. +Qed. + +Lemma Z_of_N_le : forall n m, (n<=m)%N -> (Z_of_N n <= Z_of_N m)%Z. +Proof. + intros [|n] [|m]; simpl; auto. +Qed. + +Lemma Z_of_N_le_rev : forall n m, (Z_of_N n <= Z_of_N m)%Z -> (n<=m)%N. +Proof. + intros [|n] [|m]; simpl; auto. +Qed. + +Lemma Z_of_N_le_iff : forall n m, (n<=m)%N <-> (Z_of_N n <= Z_of_N m)%Z. +Proof. + split; [apply Z_of_N_le | apply Z_of_N_le_rev]. +Qed. + +Lemma Z_of_N_lt : forall n m, (n<m)%N -> (Z_of_N n < Z_of_N m)%Z. +Proof. + intros [|n] [|m]; simpl; auto. +Qed. + +Lemma Z_of_N_lt_rev : forall n m, (Z_of_N n < Z_of_N m)%Z -> (n<m)%N. +Proof. + intros [|n] [|m]; simpl; auto. +Qed. + +Lemma Z_of_N_lt_iff : forall n m, (n<m)%N <-> (Z_of_N n < Z_of_N m)%Z. +Proof. + split; [apply Z_of_N_lt | apply Z_of_N_lt_rev]. +Qed. + +Lemma Z_of_N_ge : forall n m, (n>=m)%N -> (Z_of_N n >= Z_of_N m)%Z. +Proof. + intros [|n] [|m]; simpl; auto. +Qed. + +Lemma Z_of_N_ge_rev : forall n m, (Z_of_N n >= Z_of_N m)%Z -> (n>=m)%N. +Proof. + intros [|n] [|m]; simpl; auto. +Qed. + +Lemma Z_of_N_ge_iff : forall n m, (n>=m)%N <-> (Z_of_N n >= Z_of_N m)%Z. +Proof. + split; [apply Z_of_N_ge | apply Z_of_N_ge_rev]. +Qed. + +Lemma Z_of_N_gt : forall n m, (n>m)%N -> (Z_of_N n > Z_of_N m)%Z. +Proof. + intros [|n] [|m]; simpl; auto. +Qed. + +Lemma Z_of_N_gt_rev : forall n m, (Z_of_N n > Z_of_N m)%Z -> (n>m)%N. +Proof. + intros [|n] [|m]; simpl; auto. +Qed. + +Lemma Z_of_N_gt_iff : forall n m, (n>m)%N <-> (Z_of_N n > Z_of_N m)%Z. +Proof. + split; [apply Z_of_N_gt | apply Z_of_N_gt_rev]. +Qed. + +Lemma Z_of_N_of_nat : forall n:nat, Z_of_N (N_of_nat n) = Z_of_nat n. +Proof. + destruct n; simpl; auto. +Qed. + +Lemma Z_of_N_pos : forall p:positive, Z_of_N (Npos p) = Zpos p. +Proof. + destruct p; simpl; auto. +Qed. + +Lemma Z_of_N_abs : forall z:Z, Z_of_N (Zabs_N z) = Zabs z. +Proof. + destruct z; simpl; auto. +Qed. + +Lemma Z_of_N_le_0 : forall n, (0 <= Z_of_N n)%Z. +Proof. + destruct n; intro; discriminate. +Qed. + +Lemma Z_of_N_plus : forall n m:N, Z_of_N (n+m) = (Z_of_N n + Z_of_N m)%Z. +Proof. + destruct n; destruct m; auto. +Qed. + +Lemma Z_of_N_mult : forall n m:N, Z_of_N (n*m) = (Z_of_N n * Z_of_N m)%Z. +Proof. + destruct n; destruct m; auto. +Qed. + +Lemma Z_of_N_minus : forall n m:N, Z_of_N (n-m) = Zmax 0 (Z_of_N n - Z_of_N m). +Proof. + intros; do 3 rewrite <- Z_of_nat_of_N; rewrite nat_of_Nminus; apply inj_minus. +Qed. + +Lemma Z_of_N_succ : forall n:N, Z_of_N (Nsucc n) = Zsucc (Z_of_N n). +Proof. + intros; do 2 rewrite <- Z_of_nat_of_N; rewrite nat_of_Nsucc; apply inj_S. +Qed. + +Lemma Z_of_N_min : forall n m:N, Z_of_N (Nmin n m) = Zmin (Z_of_N n) (Z_of_N m). +Proof. + intros; do 3 rewrite <- Z_of_nat_of_N; rewrite nat_of_Nmin; apply inj_min. +Qed. + +Lemma Z_of_N_max : forall n m:N, Z_of_N (Nmax n m) = Zmax (Z_of_N n) (Z_of_N m). +Proof. + intros; do 3 rewrite <- Z_of_nat_of_N; rewrite nat_of_Nmax; apply inj_max. +Qed. + diff --git a/theories/NArith/Pnat.v b/theories/NArith/Pnat.v index 88abc700..2c007398 100644 --- a/theories/NArith/Pnat.v +++ b/theories/NArith/Pnat.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Pnat.v 5920 2004-07-16 20:01:26Z herbelin $ i*) +(*i $Id: Pnat.v 9883 2007-06-07 18:44:59Z letouzey $ i*) Require Import BinPos. @@ -14,7 +14,7 @@ Require Import BinPos. (** Properties of the injection from binary positive numbers to Peano natural numbers *) -(** Original development by Pierre Crégut, CNET, Lannion, France *) +(** Original development by Pierre Crégut, CNET, Lannion, France *) Require Import Le. Require Import Lt. diff --git a/theories/Numbers/BigNumPrelude.v b/theories/Numbers/BigNumPrelude.v new file mode 100644 index 00000000..9669eacd --- /dev/null +++ b/theories/Numbers/BigNumPrelude.v @@ -0,0 +1,372 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: BigNumPrelude.v 11013 2008-05-28 18:17:30Z letouzey $ i*) + +(** * BigNumPrelude *) + +(** Auxillary functions & theorems used for arbitrary precision efficient + numbers. *) + + +Require Import ArithRing. +Require Export ZArith. +Require Export Znumtheory. +Require Export Zpow_facts. + +(* *** Nota Bene *** + All results that were general enough has been moved in ZArith. + Only remain here specialized lemmas and compatibility elements. + (P.L. 5/11/2007). +*) + + +Open Local Scope Z_scope. + +(* For compatibility of scripts, weaker version of some lemmas of Zdiv *) + +Lemma Zlt0_not_eq : forall n, 0<n -> n<>0. +Proof. + auto with zarith. +Qed. + +Definition Zdiv_mult_cancel_r a b c H := Zdiv.Zdiv_mult_cancel_r a b c (Zlt0_not_eq _ H). +Definition Zdiv_mult_cancel_l a b c H := Zdiv.Zdiv_mult_cancel_r a b c (Zlt0_not_eq _ H). +Definition Z_div_plus_l a b c H := Zdiv.Z_div_plus_full_l a b c (Zlt0_not_eq _ H). + +(* Automation *) + +Hint Extern 2 (Zle _ _) => + (match goal with + |- Zpos _ <= Zpos _ => exact (refl_equal _) +| H: _ <= ?p |- _ <= ?p => apply Zle_trans with (2 := H) +| H: _ < ?p |- _ <= ?p => apply Zlt_le_weak; apply Zle_lt_trans with (2 := H) + end). + +Hint Extern 2 (Zlt _ _) => + (match goal with + |- Zpos _ < Zpos _ => exact (refl_equal _) +| H: _ <= ?p |- _ <= ?p => apply Zlt_le_trans with (2 := H) +| H: _ < ?p |- _ <= ?p => apply Zle_lt_trans with (2 := H) + end). + + +Hint Resolve Zlt_gt Zle_ge Z_div_pos: zarith. + +(************************************** + Properties of order and product + **************************************) + + Theorem beta_lex: forall a b c d beta, + a * beta + b <= c * beta + d -> + 0 <= b < beta -> 0 <= d < beta -> + a <= c. + Proof. + intros a b c d beta H1 (H3, H4) (H5, H6). + assert (a - c < 1); auto with zarith. + apply Zmult_lt_reg_r with beta; auto with zarith. + apply Zle_lt_trans with (d - b); auto with zarith. + rewrite Zmult_minus_distr_r; auto with zarith. + Qed. + + Theorem beta_lex_inv: forall a b c d beta, + a < c -> 0 <= b < beta -> + 0 <= d < beta -> + a * beta + b < c * beta + d. + Proof. + intros a b c d beta H1 (H3, H4) (H5, H6). + case (Zle_or_lt (c * beta + d) (a * beta + b)); auto with zarith. + intros H7; contradict H1;apply Zle_not_lt;apply beta_lex with (1 := H7);auto. + Qed. + + Lemma beta_mult : forall h l beta, + 0 <= h < beta -> 0 <= l < beta -> 0 <= h*beta+l < beta^2. + Proof. + intros h l beta H1 H2;split. auto with zarith. + rewrite <- (Zplus_0_r (beta^2)); rewrite Zpower_2; + apply beta_lex_inv;auto with zarith. + Qed. + + Lemma Zmult_lt_b : + forall b x y, 0 <= x < b -> 0 <= y < b -> 0 <= x * y <= b^2 - 2*b + 1. + Proof. + intros b x y (Hx1,Hx2) (Hy1,Hy2);split;auto with zarith. + apply Zle_trans with ((b-1)*(b-1)). + apply Zmult_le_compat;auto with zarith. + apply Zeq_le;ring. + Qed. + + Lemma sum_mul_carry : forall xh xl yh yl wc cc beta, + 1 < beta -> + 0 <= wc < beta -> + 0 <= xh < beta -> + 0 <= xl < beta -> + 0 <= yh < beta -> + 0 <= yl < beta -> + 0 <= cc < beta^2 -> + wc*beta^2 + cc = xh*yl + xl*yh -> + 0 <= wc <= 1. + Proof. + intros xh xl yh yl wc cc beta U H1 H2 H3 H4 H5 H6 H7. + assert (H8 := Zmult_lt_b beta xh yl H2 H5). + assert (H9 := Zmult_lt_b beta xl yh H3 H4). + split;auto with zarith. + apply beta_lex with (cc) (beta^2 - 2) (beta^2); auto with zarith. + Qed. + + Theorem mult_add_ineq: forall x y cross beta, + 0 <= x < beta -> + 0 <= y < beta -> + 0 <= cross < beta -> + 0 <= x * y + cross < beta^2. + Proof. + intros x y cross beta HH HH1 HH2. + split; auto with zarith. + apply Zle_lt_trans with ((beta-1)*(beta-1)+(beta-1)); auto with zarith. + apply Zplus_le_compat; auto with zarith. + apply Zmult_le_compat; auto with zarith. + repeat (rewrite Zmult_minus_distr_l || rewrite Zmult_minus_distr_r); + rewrite Zpower_2; auto with zarith. + Qed. + + Theorem mult_add_ineq2: forall x y c cross beta, + 0 <= x < beta -> + 0 <= y < beta -> + 0 <= c*beta + cross <= 2*beta - 2 -> + 0 <= x * y + (c*beta + cross) < beta^2. + Proof. + intros x y c cross beta HH HH1 HH2. + split; auto with zarith. + apply Zle_lt_trans with ((beta-1)*(beta-1)+(2*beta-2));auto with zarith. + apply Zplus_le_compat; auto with zarith. + apply Zmult_le_compat; auto with zarith. + repeat (rewrite Zmult_minus_distr_l || rewrite Zmult_minus_distr_r); + rewrite Zpower_2; auto with zarith. + Qed. + +Theorem mult_add_ineq3: forall x y c cross beta, + 0 <= x < beta -> + 0 <= y < beta -> + 0 <= cross <= beta - 2 -> + 0 <= c <= 1 -> + 0 <= x * y + (c*beta + cross) < beta^2. + Proof. + intros x y c cross beta HH HH1 HH2 HH3. + apply mult_add_ineq2;auto with zarith. + split;auto with zarith. + apply Zle_trans with (1*beta+cross);auto with zarith. + Qed. + +Hint Rewrite Zmult_1_r Zmult_0_r Zmult_1_l Zmult_0_l Zplus_0_l Zplus_0_r Zminus_0_r: rm10. + + +(************************************** + Properties of Zdiv and Zmod +**************************************) + +Theorem Zmod_le_first: forall a b, 0 <= a -> 0 < b -> 0 <= a mod b <= a. + Proof. + intros a b H H1;case (Z_mod_lt a b);auto with zarith;intros H2 H3;split;auto. + case (Zle_or_lt b a); intros H4; auto with zarith. + rewrite Zmod_small; auto with zarith. + Qed. + + + Theorem Zmod_distr: forall a b r t, 0 <= a <= b -> 0 <= r -> 0 <= t < 2 ^a -> + (2 ^a * r + t) mod (2 ^ b) = (2 ^a * r) mod (2 ^ b) + t. + Proof. + intros a b r t (H1, H2) H3 (H4, H5). + assert (t < 2 ^ b). + apply Zlt_le_trans with (1:= H5); auto with zarith. + apply Zpower_le_monotone; auto with zarith. + rewrite Zplus_mod; auto with zarith. + rewrite Zmod_small with (a := t); auto with zarith. + apply Zmod_small; auto with zarith. + split; auto with zarith. + assert (0 <= 2 ^a * r); auto with zarith. + apply Zplus_le_0_compat; auto with zarith. + match goal with |- context [?X mod ?Y] => case (Z_mod_lt X Y) end; + auto with zarith. + pattern (2 ^ b) at 2; replace (2 ^ b) with ((2 ^ b - 2 ^a) + 2 ^ a); + try ring. + apply Zplus_le_lt_compat; auto with zarith. + replace b with ((b - a) + a); try ring. + rewrite Zpower_exp; auto with zarith. + pattern (2 ^a) at 4; rewrite <- (Zmult_1_l (2 ^a)); + try rewrite <- Zmult_minus_distr_r. + rewrite (Zmult_comm (2 ^(b - a))); rewrite Zmult_mod_distr_l; + auto with zarith. + rewrite (Zmult_comm (2 ^a)); apply Zmult_le_compat_r; auto with zarith. + match goal with |- context [?X mod ?Y] => case (Z_mod_lt X Y) end; + auto with zarith. + Qed. + + Theorem Zmod_shift_r: + forall a b r t, 0 <= a <= b -> 0 <= r -> 0 <= t < 2 ^a -> + (r * 2 ^a + t) mod (2 ^ b) = (r * 2 ^a) mod (2 ^ b) + t. + Proof. + intros a b r t (H1, H2) H3 (H4, H5). + assert (t < 2 ^ b). + apply Zlt_le_trans with (1:= H5); auto with zarith. + apply Zpower_le_monotone; auto with zarith. + rewrite Zplus_mod; auto with zarith. + rewrite Zmod_small with (a := t); auto with zarith. + apply Zmod_small; auto with zarith. + split; auto with zarith. + assert (0 <= 2 ^a * r); auto with zarith. + apply Zplus_le_0_compat; auto with zarith. + match goal with |- context [?X mod ?Y] => case (Z_mod_lt X Y) end; + auto with zarith. + pattern (2 ^ b) at 2;replace (2 ^ b) with ((2 ^ b - 2 ^a) + 2 ^ a); try ring. + apply Zplus_le_lt_compat; auto with zarith. + replace b with ((b - a) + a); try ring. + rewrite Zpower_exp; auto with zarith. + pattern (2 ^a) at 4; rewrite <- (Zmult_1_l (2 ^a)); + try rewrite <- Zmult_minus_distr_r. + repeat rewrite (fun x => Zmult_comm x (2 ^ a)); rewrite Zmult_mod_distr_l; + auto with zarith. + apply Zmult_le_compat_l; auto with zarith. + match goal with |- context [?X mod ?Y] => case (Z_mod_lt X Y) end; + auto with zarith. + Qed. + + Theorem Zdiv_shift_r: + forall a b r t, 0 <= a <= b -> 0 <= r -> 0 <= t < 2 ^a -> + (r * 2 ^a + t) / (2 ^ b) = (r * 2 ^a) / (2 ^ b). + Proof. + intros a b r t (H1, H2) H3 (H4, H5). + assert (Eq: t < 2 ^ b); auto with zarith. + apply Zlt_le_trans with (1 := H5); auto with zarith. + apply Zpower_le_monotone; auto with zarith. + pattern (r * 2 ^ a) at 1; rewrite Z_div_mod_eq with (b := 2 ^ b); + auto with zarith. + rewrite <- Zplus_assoc. + rewrite <- Zmod_shift_r; auto with zarith. + rewrite (Zmult_comm (2 ^ b)); rewrite Z_div_plus_full_l; auto with zarith. + rewrite (fun x y => @Zdiv_small (x mod y)); auto with zarith. + match goal with |- context [?X mod ?Y] => case (Z_mod_lt X Y) end; + auto with zarith. + Qed. + + + Lemma shift_unshift_mod : forall n p a, + 0 <= a < 2^n -> + 0 <= p <= n -> + a * 2^p = a / 2^(n - p) * 2^n + (a*2^p) mod 2^n. + Proof. + intros n p a H1 H2. + pattern (a*2^p) at 1;replace (a*2^p) with + (a*2^p/2^n * 2^n + a*2^p mod 2^n). + 2:symmetry;rewrite (Zmult_comm (a*2^p/2^n));apply Z_div_mod_eq. + replace (a * 2 ^ p / 2 ^ n) with (a / 2 ^ (n - p));trivial. + replace (2^n) with (2^(n-p)*2^p). + symmetry;apply Zdiv_mult_cancel_r. + destruct H1;trivial. + cut (0 < 2^p); auto with zarith. + rewrite <- Zpower_exp. + replace (n-p+p) with n;trivial. ring. + omega. omega. + apply Zlt_gt. apply Zpower_gt_0;auto with zarith. + Qed. + + + Lemma shift_unshift_mod_2 : forall n p a, (0<=p<=n)%Z -> + ((a * 2 ^ (n - p)) mod (2^n) / 2 ^ (n - p)) mod (2^n) = + a mod 2 ^ p. + Proof. + intros. + rewrite Zmod_small. + rewrite Zmod_eq by (auto with zarith). + unfold Zminus at 1. + rewrite Z_div_plus_l by (auto with zarith). + assert (2^n = 2^(n-p)*2^p). + rewrite <- Zpower_exp by (auto with zarith). + replace (n-p+p) with n; auto with zarith. + rewrite H0. + rewrite <- Zdiv_Zdiv, Z_div_mult by (auto with zarith). + rewrite (Zmult_comm (2^(n-p))), Zmult_assoc. + rewrite Zopp_mult_distr_l. + rewrite Z_div_mult by (auto with zarith). + symmetry; apply Zmod_eq; auto with zarith. + + remember (a * 2 ^ (n - p)) as b. + destruct (Z_mod_lt b (2^n)); auto with zarith. + split. + apply Z_div_pos; auto with zarith. + apply Zdiv_lt_upper_bound; auto with zarith. + apply Zlt_le_trans with (2^n); auto with zarith. + rewrite <- (Zmult_1_r (2^n)) at 1. + apply Zmult_le_compat; auto with zarith. + cut (0 < 2 ^ (n-p)); auto with zarith. + Qed. + + Lemma div_le_0 : forall p x, 0 <= x -> 0 <= x / 2 ^ p. + Proof. + intros p x Hle;destruct (Z_le_gt_dec 0 p). + apply Zdiv_le_lower_bound;auto with zarith. + replace (2^p) with 0. + destruct x;compute;intro;discriminate. + destruct p;trivial;discriminate z. + Qed. + + Lemma div_lt : forall p x y, 0 <= x < y -> x / 2^p < y. + Proof. + intros p x y H;destruct (Z_le_gt_dec 0 p). + apply Zdiv_lt_upper_bound;auto with zarith. + apply Zlt_le_trans with y;auto with zarith. + rewrite <- (Zmult_1_r y);apply Zmult_le_compat;auto with zarith. + assert (0 < 2^p);auto with zarith. + replace (2^p) with 0. + destruct x;change (0<y);auto with zarith. + destruct p;trivial;discriminate z. + Qed. + + Theorem Zgcd_div_pos a b: + (0 < b)%Z -> (0 < Zgcd a b)%Z -> (0 < b / Zgcd a b)%Z. + Proof. + intros a b Ha Hg. + case (Zle_lt_or_eq 0 (b/Zgcd a b)); auto. + apply Z_div_pos; auto with zarith. + intros H; generalize Ha. + pattern b at 1; rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto. + rewrite <- H; auto with zarith. + assert (F := (Zgcd_is_gcd a b)); inversion F; auto. + Qed. + +Theorem Zbounded_induction : + (forall Q : Z -> Prop, forall b : Z, + Q 0 -> + (forall n, 0 <= n -> n < b - 1 -> Q n -> Q (n + 1)) -> + forall n, 0 <= n -> n < b -> Q n)%Z. +Proof. +intros Q b Q0 QS. +set (Q' := fun n => (n < b /\ Q n) \/ (b <= n)). +assert (H : forall n, 0 <= n -> Q' n). +apply natlike_rec2; unfold Q'. +destruct (Zle_or_lt b 0) as [H | H]. now right. left; now split. +intros n H IH. destruct IH as [[IH1 IH2] | IH]. +destruct (Zle_or_lt (b - 1) n) as [H1 | H1]. +right; auto with zarith. +left. split; [auto with zarith | now apply (QS n)]. +right; auto with zarith. +unfold Q' in *; intros n H1 H2. destruct (H n H1) as [[H3 H4] | H3]. +assumption. apply Zle_not_lt in H3. false_hyp H2 H3. +Qed. + +Lemma Zsquare_le : forall x, x <= x*x. +Proof. +intros. +destruct (Z_lt_le_dec 0 x). +pattern x at 1; rewrite <- (Zmult_1_l x). +apply Zmult_le_compat; auto with zarith. +apply Zle_trans with 0; auto with zarith. +rewrite <- Zmult_opp_opp. +apply Zmult_le_0_compat; auto with zarith. +Qed. diff --git a/theories/Numbers/Cyclic/Abstract/CyclicAxioms.v b/theories/Numbers/Cyclic/Abstract/CyclicAxioms.v new file mode 100644 index 00000000..528d78c3 --- /dev/null +++ b/theories/Numbers/Cyclic/Abstract/CyclicAxioms.v @@ -0,0 +1,375 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(* $Id: CyclicAxioms.v 11012 2008-05-28 16:34:43Z letouzey $ *) + +(** * Signature and specification of a bounded integer structure *) + +(** This file specifies how to represent [Z/nZ] when [n=2^d], + [d] being the number of digits of these bounded integers. *) + +Set Implicit Arguments. + +Require Import ZArith. +Require Import Znumtheory. +Require Import BigNumPrelude. +Require Import DoubleType. + +Open Local Scope Z_scope. + +(** First, a description via an operator record and a spec record. *) + +Section Z_nZ_Op. + + Variable znz : Type. + + Record znz_op := mk_znz_op { + + (* Conversion functions with Z *) + znz_digits : positive; + znz_zdigits: znz; + znz_to_Z : znz -> Z; + znz_of_pos : positive -> N * znz; (* Euclidean division by [2^digits] *) + znz_head0 : znz -> znz; (* number of digits 0 in front of the number *) + znz_tail0 : znz -> znz; (* number of digits 0 at the bottom of the number *) + + (* Basic numbers *) + znz_0 : znz; + znz_1 : znz; + znz_Bm1 : znz; (* [2^digits-1], which is equivalent to [-1] *) + + (* Comparison *) + znz_compare : znz -> znz -> comparison; + znz_eq0 : znz -> bool; + + (* Basic arithmetic operations *) + znz_opp_c : znz -> carry znz; + znz_opp : znz -> znz; + znz_opp_carry : znz -> znz; (* the carry is known to be -1 *) + + znz_succ_c : znz -> carry znz; + znz_add_c : znz -> znz -> carry znz; + znz_add_carry_c : znz -> znz -> carry znz; + znz_succ : znz -> znz; + znz_add : znz -> znz -> znz; + znz_add_carry : znz -> znz -> znz; + + znz_pred_c : znz -> carry znz; + znz_sub_c : znz -> znz -> carry znz; + znz_sub_carry_c : znz -> znz -> carry znz; + znz_pred : znz -> znz; + znz_sub : znz -> znz -> znz; + znz_sub_carry : znz -> znz -> znz; + + znz_mul_c : znz -> znz -> zn2z znz; + znz_mul : znz -> znz -> znz; + znz_square_c : znz -> zn2z znz; + + (* Special divisions operations *) + znz_div21 : znz -> znz -> znz -> znz*znz; + znz_div_gt : znz -> znz -> znz * znz; (* specialized version of [znz_div] *) + znz_div : znz -> znz -> znz * znz; + + znz_mod_gt : znz -> znz -> znz; (* specialized version of [znz_mod] *) + znz_mod : znz -> znz -> znz; + + znz_gcd_gt : znz -> znz -> znz; (* specialized version of [znz_gcd] *) + znz_gcd : znz -> znz -> znz; + (* [znz_add_mul_div p i j] is a combination of the [(digits-p)] + low bits of [i] above the [p] high bits of [j]: + [znz_add_mul_div p i j = i*2^p+j/2^(digits-p)] *) + znz_add_mul_div : znz -> znz -> znz -> znz; + (* [znz_pos_mod p i] is [i mod 2^p] *) + znz_pos_mod : znz -> znz -> znz; + + znz_is_even : znz -> bool; + (* square root *) + znz_sqrt2 : znz -> znz -> znz * carry znz; + znz_sqrt : znz -> znz }. + +End Z_nZ_Op. + +Section Z_nZ_Spec. + Variable w : Type. + Variable w_op : znz_op w. + + Let w_digits := w_op.(znz_digits). + Let w_zdigits := w_op.(znz_zdigits). + Let w_to_Z := w_op.(znz_to_Z). + Let w_of_pos := w_op.(znz_of_pos). + Let w_head0 := w_op.(znz_head0). + Let w_tail0 := w_op.(znz_tail0). + + Let w0 := w_op.(znz_0). + Let w1 := w_op.(znz_1). + Let wBm1 := w_op.(znz_Bm1). + + Let w_compare := w_op.(znz_compare). + Let w_eq0 := w_op.(znz_eq0). + + Let w_opp_c := w_op.(znz_opp_c). + Let w_opp := w_op.(znz_opp). + Let w_opp_carry := w_op.(znz_opp_carry). + + Let w_succ_c := w_op.(znz_succ_c). + Let w_add_c := w_op.(znz_add_c). + Let w_add_carry_c := w_op.(znz_add_carry_c). + Let w_succ := w_op.(znz_succ). + Let w_add := w_op.(znz_add). + Let w_add_carry := w_op.(znz_add_carry). + + Let w_pred_c := w_op.(znz_pred_c). + Let w_sub_c := w_op.(znz_sub_c). + Let w_sub_carry_c := w_op.(znz_sub_carry_c). + Let w_pred := w_op.(znz_pred). + Let w_sub := w_op.(znz_sub). + Let w_sub_carry := w_op.(znz_sub_carry). + + Let w_mul_c := w_op.(znz_mul_c). + Let w_mul := w_op.(znz_mul). + Let w_square_c := w_op.(znz_square_c). + + Let w_div21 := w_op.(znz_div21). + Let w_div_gt := w_op.(znz_div_gt). + Let w_div := w_op.(znz_div). + + Let w_mod_gt := w_op.(znz_mod_gt). + Let w_mod := w_op.(znz_mod). + + Let w_gcd_gt := w_op.(znz_gcd_gt). + Let w_gcd := w_op.(znz_gcd). + + Let w_add_mul_div := w_op.(znz_add_mul_div). + + Let w_pos_mod := w_op.(znz_pos_mod). + + Let w_is_even := w_op.(znz_is_even). + Let w_sqrt2 := w_op.(znz_sqrt2). + Let w_sqrt := w_op.(znz_sqrt). + + Notation "[| x |]" := (w_to_Z x) (at level 0, x at level 99). + + Let wB := base w_digits. + + Notation "[+| c |]" := + (interp_carry 1 wB w_to_Z c) (at level 0, x at level 99). + + Notation "[-| c |]" := + (interp_carry (-1) wB w_to_Z c) (at level 0, x at level 99). + + Notation "[|| x ||]" := + (zn2z_to_Z wB w_to_Z x) (at level 0, x at level 99). + + Record znz_spec := mk_znz_spec { + + (* Conversion functions with Z *) + spec_to_Z : forall x, 0 <= [| x |] < wB; + spec_of_pos : forall p, + Zpos p = (Z_of_N (fst (w_of_pos p)))*wB + [|(snd (w_of_pos p))|]; + spec_zdigits : [| w_zdigits |] = Zpos w_digits; + spec_more_than_1_digit: 1 < Zpos w_digits; + + (* Basic numbers *) + spec_0 : [|w0|] = 0; + spec_1 : [|w1|] = 1; + spec_Bm1 : [|wBm1|] = wB - 1; + + (* Comparison *) + spec_compare : + forall x y, + match w_compare x y with + | Eq => [|x|] = [|y|] + | Lt => [|x|] < [|y|] + | Gt => [|x|] > [|y|] + end; + spec_eq0 : forall x, w_eq0 x = true -> [|x|] = 0; + (* Basic arithmetic operations *) + spec_opp_c : forall x, [-|w_opp_c x|] = -[|x|]; + spec_opp : forall x, [|w_opp x|] = (-[|x|]) mod wB; + spec_opp_carry : forall x, [|w_opp_carry x|] = wB - [|x|] - 1; + + spec_succ_c : forall x, [+|w_succ_c x|] = [|x|] + 1; + spec_add_c : forall x y, [+|w_add_c x y|] = [|x|] + [|y|]; + spec_add_carry_c : forall x y, [+|w_add_carry_c x y|] = [|x|] + [|y|] + 1; + spec_succ : forall x, [|w_succ x|] = ([|x|] + 1) mod wB; + spec_add : forall x y, [|w_add x y|] = ([|x|] + [|y|]) mod wB; + spec_add_carry : + forall x y, [|w_add_carry x y|] = ([|x|] + [|y|] + 1) mod wB; + + spec_pred_c : forall x, [-|w_pred_c x|] = [|x|] - 1; + spec_sub_c : forall x y, [-|w_sub_c x y|] = [|x|] - [|y|]; + spec_sub_carry_c : forall x y, [-|w_sub_carry_c x y|] = [|x|] - [|y|] - 1; + spec_pred : forall x, [|w_pred x|] = ([|x|] - 1) mod wB; + spec_sub : forall x y, [|w_sub x y|] = ([|x|] - [|y|]) mod wB; + spec_sub_carry : + forall x y, [|w_sub_carry x y|] = ([|x|] - [|y|] - 1) mod wB; + + spec_mul_c : forall x y, [|| w_mul_c x y ||] = [|x|] * [|y|]; + spec_mul : forall x y, [|w_mul x y|] = ([|x|] * [|y|]) mod wB; + spec_square_c : forall x, [|| w_square_c x||] = [|x|] * [|x|]; + + (* Special divisions operations *) + spec_div21 : forall a1 a2 b, + wB/2 <= [|b|] -> + [|a1|] < [|b|] -> + let (q,r) := w_div21 a1 a2 b in + [|a1|] *wB+ [|a2|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]; + spec_div_gt : forall a b, [|a|] > [|b|] -> 0 < [|b|] -> + let (q,r) := w_div_gt a b in + [|a|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]; + spec_div : forall a b, 0 < [|b|] -> + let (q,r) := w_div a b in + [|a|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]; + + spec_mod_gt : forall a b, [|a|] > [|b|] -> 0 < [|b|] -> + [|w_mod_gt a b|] = [|a|] mod [|b|]; + spec_mod : forall a b, 0 < [|b|] -> + [|w_mod a b|] = [|a|] mod [|b|]; + + spec_gcd_gt : forall a b, [|a|] > [|b|] -> + Zis_gcd [|a|] [|b|] [|w_gcd_gt a b|]; + spec_gcd : forall a b, Zis_gcd [|a|] [|b|] [|w_gcd a b|]; + + + (* shift operations *) + spec_head00: forall x, [|x|] = 0 -> [|w_head0 x|] = Zpos w_digits; + spec_head0 : forall x, 0 < [|x|] -> + wB/ 2 <= 2 ^ ([|w_head0 x|]) * [|x|] < wB; + spec_tail00: forall x, [|x|] = 0 -> [|w_tail0 x|] = Zpos w_digits; + spec_tail0 : forall x, 0 < [|x|] -> + exists y, 0 <= y /\ [|x|] = (2 * y + 1) * (2 ^ [|w_tail0 x|]) ; + spec_add_mul_div : forall x y p, + [|p|] <= Zpos w_digits -> + [| w_add_mul_div p x y |] = + ([|x|] * (2 ^ [|p|]) + + [|y|] / (2 ^ ((Zpos w_digits) - [|p|]))) mod wB; + spec_pos_mod : forall w p, + [|w_pos_mod p w|] = [|w|] mod (2 ^ [|p|]); + (* sqrt *) + spec_is_even : forall x, + if w_is_even x then [|x|] mod 2 = 0 else [|x|] mod 2 = 1; + spec_sqrt2 : forall x y, + wB/ 4 <= [|x|] -> + let (s,r) := w_sqrt2 x y in + [||WW x y||] = [|s|] ^ 2 + [+|r|] /\ + [+|r|] <= 2 * [|s|]; + spec_sqrt : forall x, + [|w_sqrt x|] ^ 2 <= [|x|] < ([|w_sqrt x|] + 1) ^ 2 + }. + +End Z_nZ_Spec. + +(** Generic construction of double words *) + +Section WW. + + Variable w : Type. + Variable w_op : znz_op w. + Variable op_spec : znz_spec w_op. + + Let wB := base w_op.(znz_digits). + Let w_to_Z := w_op.(znz_to_Z). + Let w_eq0 := w_op.(znz_eq0). + Let w_0 := w_op.(znz_0). + + Definition znz_W0 h := + if w_eq0 h then W0 else WW h w_0. + + Definition znz_0W l := + if w_eq0 l then W0 else WW w_0 l. + + Definition znz_WW h l := + if w_eq0 h then znz_0W l else WW h l. + + Lemma spec_W0 : forall h, + zn2z_to_Z wB w_to_Z (znz_W0 h) = (w_to_Z h)*wB. + Proof. + unfold zn2z_to_Z, znz_W0, w_to_Z; simpl; intros. + case_eq (w_eq0 h); intros. + rewrite (op_spec.(spec_eq0) _ H); auto. + unfold w_0; rewrite op_spec.(spec_0); auto with zarith. + Qed. + + Lemma spec_0W : forall l, + zn2z_to_Z wB w_to_Z (znz_0W l) = w_to_Z l. + Proof. + unfold zn2z_to_Z, znz_0W, w_to_Z; simpl; intros. + case_eq (w_eq0 l); intros. + rewrite (op_spec.(spec_eq0) _ H); auto. + unfold w_0; rewrite op_spec.(spec_0); auto with zarith. + Qed. + + Lemma spec_WW : forall h l, + zn2z_to_Z wB w_to_Z (znz_WW h l) = (w_to_Z h)*wB + w_to_Z l. + Proof. + unfold znz_WW, w_to_Z; simpl; intros. + case_eq (w_eq0 h); intros. + rewrite (op_spec.(spec_eq0) _ H); auto. + rewrite spec_0W; auto. + simpl; auto. + Qed. + +End WW. + +(** Injecting [Z] numbers into a cyclic structure *) + +Section znz_of_pos. + + Variable w : Type. + Variable w_op : znz_op w. + Variable op_spec : znz_spec w_op. + + Notation "[| x |]" := (znz_to_Z w_op x) (at level 0, x at level 99). + + Definition znz_of_Z (w:Type) (op:znz_op w) z := + match z with + | Zpos p => snd (op.(znz_of_pos) p) + | _ => op.(znz_0) + end. + + Theorem znz_of_pos_correct: + forall p, Zpos p < base (znz_digits w_op) -> [|(snd (znz_of_pos w_op p))|] = Zpos p. + intros p Hp. + generalize (spec_of_pos op_spec p). + case (znz_of_pos w_op p); intros n w1; simpl. + case n; simpl Npos; auto with zarith. + intros p1 Hp1; contradict Hp; apply Zle_not_lt. + rewrite Hp1; auto with zarith. + match goal with |- _ <= ?X + ?Y => + apply Zle_trans with X; auto with zarith + end. + match goal with |- ?X <= _ => + pattern X at 1; rewrite <- (Zmult_1_l); + apply Zmult_le_compat_r; auto with zarith + end. + case p1; simpl; intros; red; simpl; intros; discriminate. + unfold base; auto with zarith. + case (spec_to_Z op_spec w1); auto with zarith. + Qed. + + Theorem znz_of_Z_correct: + forall p, 0 <= p < base (znz_digits w_op) -> [|znz_of_Z w_op p|] = p. + intros p; case p; simpl; try rewrite spec_0; auto. + intros; rewrite znz_of_pos_correct; auto with zarith. + intros p1 (H1, _); contradict H1; apply Zlt_not_le; red; simpl; auto. + Qed. +End znz_of_pos. + + +(** A modular specification grouping the earlier records. *) + +Module Type CyclicType. + Parameter w : Type. + Parameter w_op : znz_op w. + Parameter w_spec : znz_spec w_op. +End CyclicType. diff --git a/theories/Numbers/Cyclic/Abstract/NZCyclic.v b/theories/Numbers/Cyclic/Abstract/NZCyclic.v new file mode 100644 index 00000000..22f6d95b --- /dev/null +++ b/theories/Numbers/Cyclic/Abstract/NZCyclic.v @@ -0,0 +1,236 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NZCyclic.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export NZAxioms. +Require Import BigNumPrelude. +Require Import DoubleType. +Require Import CyclicAxioms. + +(** * From [CyclicType] to [NZAxiomsSig] *) + +(** A [Z/nZ] representation given by a module type [CyclicType] + implements [NZAxiomsSig], e.g. the common properties between + N and Z with no ordering. Notice that the [n] in [Z/nZ] is + a power of 2. +*) + +Module NZCyclicAxiomsMod (Import Cyclic : CyclicType) <: NZAxiomsSig. + +Open Local Scope Z_scope. + +Definition NZ := w. + +Definition NZ_to_Z : NZ -> Z := znz_to_Z w_op. +Definition Z_to_NZ : Z -> NZ := znz_of_Z w_op. +Notation Local wB := (base w_op.(znz_digits)). + +Notation Local "[| x |]" := (w_op.(znz_to_Z) x) (at level 0, x at level 99). + +Definition NZeq (n m : NZ) := [| n |] = [| m |]. +Definition NZ0 := w_op.(znz_0). +Definition NZsucc := w_op.(znz_succ). +Definition NZpred := w_op.(znz_pred). +Definition NZadd := w_op.(znz_add). +Definition NZsub := w_op.(znz_sub). +Definition NZmul := w_op.(znz_mul). + +Theorem NZeq_equiv : equiv NZ NZeq. +Proof. +unfold equiv, reflexive, symmetric, transitive, NZeq; repeat split; intros; auto. +now transitivity [| y |]. +Qed. + +Add Relation NZ NZeq + reflexivity proved by (proj1 NZeq_equiv) + symmetry proved by (proj2 (proj2 NZeq_equiv)) + transitivity proved by (proj1 (proj2 NZeq_equiv)) +as NZeq_rel. + +Add Morphism NZsucc with signature NZeq ==> NZeq as NZsucc_wd. +Proof. +unfold NZeq; intros n m H. do 2 rewrite w_spec.(spec_succ). now rewrite H. +Qed. + +Add Morphism NZpred with signature NZeq ==> NZeq as NZpred_wd. +Proof. +unfold NZeq; intros n m H. do 2 rewrite w_spec.(spec_pred). now rewrite H. +Qed. + +Add Morphism NZadd with signature NZeq ==> NZeq ==> NZeq as NZadd_wd. +Proof. +unfold NZeq; intros n1 n2 H1 m1 m2 H2. do 2 rewrite w_spec.(spec_add). +now rewrite H1, H2. +Qed. + +Add Morphism NZsub with signature NZeq ==> NZeq ==> NZeq as NZsub_wd. +Proof. +unfold NZeq; intros n1 n2 H1 m1 m2 H2. do 2 rewrite w_spec.(spec_sub). +now rewrite H1, H2. +Qed. + +Add Morphism NZmul with signature NZeq ==> NZeq ==> NZeq as NZmul_wd. +Proof. +unfold NZeq; intros n1 n2 H1 m1 m2 H2. do 2 rewrite w_spec.(spec_mul). +now rewrite H1, H2. +Qed. + +Delimit Scope IntScope with Int. +Bind Scope IntScope with NZ. +Open Local Scope IntScope. +Notation "x == y" := (NZeq x y) (at level 70) : IntScope. +Notation "x ~= y" := (~ NZeq x y) (at level 70) : IntScope. +Notation "0" := NZ0 : IntScope. +Notation "'S'" := NZsucc : IntScope. +Notation "'P'" := NZpred : IntScope. +(*Notation "1" := (S 0) : IntScope.*) +Notation "x + y" := (NZadd x y) : IntScope. +Notation "x - y" := (NZsub x y) : IntScope. +Notation "x * y" := (NZmul x y) : IntScope. + +Theorem gt_wB_1 : 1 < wB. +Proof. +unfold base. +apply Zpower_gt_1; unfold Zlt; auto with zarith. +Qed. + +Theorem gt_wB_0 : 0 < wB. +Proof. +pose proof gt_wB_1; auto with zarith. +Qed. + +Lemma NZsucc_mod_wB : forall n : Z, (n + 1) mod wB = ((n mod wB) + 1) mod wB. +Proof. +intro n. +pattern 1 at 2. replace 1 with (1 mod wB). rewrite <- Zplus_mod. +reflexivity. +now rewrite Zmod_small; [ | split; [auto with zarith | apply gt_wB_1]]. +Qed. + +Lemma NZpred_mod_wB : forall n : Z, (n - 1) mod wB = ((n mod wB) - 1) mod wB. +Proof. +intro n. +pattern 1 at 2. replace 1 with (1 mod wB). rewrite <- Zminus_mod. +reflexivity. +now rewrite Zmod_small; [ | split; [auto with zarith | apply gt_wB_1]]. +Qed. + +Lemma NZ_to_Z_mod : forall n : NZ, [| n |] mod wB = [| n |]. +Proof. +intro n; rewrite Zmod_small. reflexivity. apply w_spec.(spec_to_Z). +Qed. + +Theorem NZpred_succ : forall n : NZ, P (S n) == n. +Proof. +intro n; unfold NZsucc, NZpred, NZeq. rewrite w_spec.(spec_pred), w_spec.(spec_succ). +rewrite <- NZpred_mod_wB. +replace ([| n |] + 1 - 1)%Z with [| n |] by auto with zarith. apply NZ_to_Z_mod. +Qed. + +Lemma Z_to_NZ_0 : Z_to_NZ 0%Z == 0%Int. +Proof. +unfold NZeq, NZ_to_Z, Z_to_NZ. rewrite znz_of_Z_correct. +symmetry; apply w_spec.(spec_0). +exact w_spec. split; [auto with zarith |apply gt_wB_0]. +Qed. + +Section Induction. + +Variable A : NZ -> Prop. +Hypothesis A_wd : predicate_wd NZeq A. +Hypothesis A0 : A 0. +Hypothesis AS : forall n : NZ, A n <-> A (S n). (* Below, we use only -> direction *) + +Add Morphism A with signature NZeq ==> iff as A_morph. +Proof. apply A_wd. Qed. + +Let B (n : Z) := A (Z_to_NZ n). + +Lemma B0 : B 0. +Proof. +unfold B. now rewrite Z_to_NZ_0. +Qed. + +Lemma BS : forall n : Z, 0 <= n -> n < wB - 1 -> B n -> B (n + 1). +Proof. +intros n H1 H2 H3. +unfold B in *. apply -> AS in H3. +setoid_replace (Z_to_NZ (n + 1)) with (S (Z_to_NZ n)) using relation NZeq. assumption. +unfold NZeq. rewrite w_spec.(spec_succ). +unfold NZ_to_Z, Z_to_NZ. +do 2 (rewrite znz_of_Z_correct; [ | exact w_spec | auto with zarith]). +symmetry; apply Zmod_small; auto with zarith. +Qed. + +Lemma B_holds : forall n : Z, 0 <= n < wB -> B n. +Proof. +intros n [H1 H2]. +apply Zbounded_induction with wB. +apply B0. apply BS. assumption. assumption. +Qed. + +Theorem NZinduction : forall n : NZ, A n. +Proof. +intro n. setoid_replace n with (Z_to_NZ (NZ_to_Z n)) using relation NZeq. +apply B_holds. apply w_spec.(spec_to_Z). +unfold NZeq, NZ_to_Z, Z_to_NZ; rewrite znz_of_Z_correct. +reflexivity. +exact w_spec. +apply w_spec.(spec_to_Z). +Qed. + +End Induction. + +Theorem NZadd_0_l : forall n : NZ, 0 + n == n. +Proof. +intro n; unfold NZadd, NZ0, NZeq. rewrite w_spec.(spec_add). rewrite w_spec.(spec_0). +rewrite Zplus_0_l. rewrite Zmod_small; [reflexivity | apply w_spec.(spec_to_Z)]. +Qed. + +Theorem NZadd_succ_l : forall n m : NZ, (S n) + m == S (n + m). +Proof. +intros n m; unfold NZadd, NZsucc, NZeq. rewrite w_spec.(spec_add). +do 2 rewrite w_spec.(spec_succ). rewrite w_spec.(spec_add). +rewrite NZsucc_mod_wB. repeat rewrite Zplus_mod_idemp_l; try apply gt_wB_0. +rewrite <- (Zplus_assoc ([| n |] mod wB) 1 [| m |]). rewrite Zplus_mod_idemp_l. +rewrite (Zplus_comm 1 [| m |]); now rewrite Zplus_assoc. +Qed. + +Theorem NZsub_0_r : forall n : NZ, n - 0 == n. +Proof. +intro n; unfold NZsub, NZ0, NZeq. rewrite w_spec.(spec_sub). +rewrite w_spec.(spec_0). rewrite Zminus_0_r. apply NZ_to_Z_mod. +Qed. + +Theorem NZsub_succ_r : forall n m : NZ, n - (S m) == P (n - m). +Proof. +intros n m; unfold NZsub, NZsucc, NZpred, NZeq. +rewrite w_spec.(spec_pred). do 2 rewrite w_spec.(spec_sub). +rewrite w_spec.(spec_succ). rewrite Zminus_mod_idemp_r. +rewrite Zminus_mod_idemp_l. +now replace ([|n|] - ([|m|] + 1))%Z with ([|n|] - [|m|] - 1)%Z by auto with zarith. +Qed. + +Theorem NZmul_0_l : forall n : NZ, 0 * n == 0. +Proof. +intro n; unfold NZmul, NZ0, NZ, NZeq. rewrite w_spec.(spec_mul). +rewrite w_spec.(spec_0). now rewrite Zmult_0_l. +Qed. + +Theorem NZmul_succ_l : forall n m : NZ, (S n) * m == n * m + m. +Proof. +intros n m; unfold NZmul, NZsucc, NZadd, NZeq. rewrite w_spec.(spec_mul). +rewrite w_spec.(spec_add), w_spec.(spec_mul), w_spec.(spec_succ). +rewrite Zplus_mod_idemp_l, Zmult_mod_idemp_l. +now rewrite Zmult_plus_distr_l, Zmult_1_l. +Qed. + +End NZCyclicAxiomsMod. diff --git a/theories/Numbers/Cyclic/DoubleCyclic/DoubleAdd.v b/theories/Numbers/Cyclic/DoubleCyclic/DoubleAdd.v new file mode 100644 index 00000000..61d8d0fb --- /dev/null +++ b/theories/Numbers/Cyclic/DoubleCyclic/DoubleAdd.v @@ -0,0 +1,318 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: DoubleAdd.v 10964 2008-05-22 11:08:13Z letouzey $ i*) + +Set Implicit Arguments. + +Require Import ZArith. +Require Import BigNumPrelude. +Require Import DoubleType. +Require Import DoubleBase. + +Open Local Scope Z_scope. + +Section DoubleAdd. + Variable w : Type. + Variable w_0 : w. + Variable w_1 : w. + Variable w_WW : w -> w -> zn2z w. + Variable w_W0 : w -> zn2z w. + Variable ww_1 : zn2z w. + Variable w_succ_c : w -> carry w. + Variable w_add_c : w -> w -> carry w. + Variable w_add_carry_c : w -> w -> carry w. + Variable w_succ : w -> w. + Variable w_add : w -> w -> w. + Variable w_add_carry : w -> w -> w. + + Definition ww_succ_c x := + match x with + | W0 => C0 ww_1 + | WW xh xl => + match w_succ_c xl with + | C0 l => C0 (WW xh l) + | C1 l => + match w_succ_c xh with + | C0 h => C0 (WW h w_0) + | C1 h => C1 W0 + end + end + end. + + Definition ww_succ x := + match x with + | W0 => ww_1 + | WW xh xl => + match w_succ_c xl with + | C0 l => WW xh l + | C1 l => w_W0 (w_succ xh) + end + end. + + Definition ww_add_c x y := + match x, y with + | W0, _ => C0 y + | _, W0 => C0 x + | WW xh xl, WW yh yl => + match w_add_c xl yl with + | C0 l => + match w_add_c xh yh with + | C0 h => C0 (WW h l) + | C1 h => C1 (w_WW h l) + end + | C1 l => + match w_add_carry_c xh yh with + | C0 h => C0 (WW h l) + | C1 h => C1 (w_WW h l) + end + end + end. + + Variable R : Type. + Variable f0 f1 : zn2z w -> R. + + Definition ww_add_c_cont x y := + match x, y with + | W0, _ => f0 y + | _, W0 => f0 x + | WW xh xl, WW yh yl => + match w_add_c xl yl with + | C0 l => + match w_add_c xh yh with + | C0 h => f0 (WW h l) + | C1 h => f1 (w_WW h l) + end + | C1 l => + match w_add_carry_c xh yh with + | C0 h => f0 (WW h l) + | C1 h => f1 (w_WW h l) + end + end + end. + + (* ww_add et ww_add_carry conserve la forme normale s'il n'y a pas + de debordement *) + Definition ww_add x y := + match x, y with + | W0, _ => y + | _, W0 => x + | WW xh xl, WW yh yl => + match w_add_c xl yl with + | C0 l => WW (w_add xh yh) l + | C1 l => WW (w_add_carry xh yh) l + end + end. + + Definition ww_add_carry_c x y := + match x, y with + | W0, W0 => C0 ww_1 + | W0, WW yh yl => ww_succ_c (WW yh yl) + | WW xh xl, W0 => ww_succ_c (WW xh xl) + | WW xh xl, WW yh yl => + match w_add_carry_c xl yl with + | C0 l => + match w_add_c xh yh with + | C0 h => C0 (WW h l) + | C1 h => C1 (WW h l) + end + | C1 l => + match w_add_carry_c xh yh with + | C0 h => C0 (WW h l) + | C1 h => C1 (w_WW h l) + end + end + end. + + Definition ww_add_carry x y := + match x, y with + | W0, W0 => ww_1 + | W0, WW yh yl => ww_succ (WW yh yl) + | WW xh xl, W0 => ww_succ (WW xh xl) + | WW xh xl, WW yh yl => + match w_add_carry_c xl yl with + | C0 l => WW (w_add xh yh) l + | C1 l => WW (w_add_carry xh yh) l + end + end. + + (*Section DoubleProof.*) + Variable w_digits : positive. + Variable w_to_Z : w -> Z. + + + Notation wB := (base w_digits). + Notation wwB := (base (ww_digits w_digits)). + Notation "[| x |]" := (w_to_Z x) (at level 0, x at level 99). + Notation "[+| c |]" := + (interp_carry 1 wB w_to_Z c) (at level 0, x at level 99). + Notation "[-| c |]" := + (interp_carry (-1) wB w_to_Z c) (at level 0, x at level 99). + + Notation "[[ x ]]" := (ww_to_Z w_digits w_to_Z x)(at level 0, x at level 99). + Notation "[+[ c ]]" := + (interp_carry 1 wwB (ww_to_Z w_digits w_to_Z) c) + (at level 0, x at level 99). + Notation "[-[ c ]]" := + (interp_carry (-1) wwB (ww_to_Z w_digits w_to_Z) c) + (at level 0, x at level 99). + + Variable spec_w_0 : [|w_0|] = 0. + Variable spec_w_1 : [|w_1|] = 1. + Variable spec_ww_1 : [[ww_1]] = 1. + Variable spec_to_Z : forall x, 0 <= [|x|] < wB. + Variable spec_w_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|]. + Variable spec_w_W0 : forall h, [[w_W0 h]] = [|h|] * wB. + Variable spec_w_succ_c : forall x, [+|w_succ_c x|] = [|x|] + 1. + Variable spec_w_add_c : forall x y, [+|w_add_c x y|] = [|x|] + [|y|]. + Variable spec_w_add_carry_c : + forall x y, [+|w_add_carry_c x y|] = [|x|] + [|y|] + 1. + Variable spec_w_succ : forall x, [|w_succ x|] = ([|x|] + 1) mod wB. + Variable spec_w_add : forall x y, [|w_add x y|] = ([|x|] + [|y|]) mod wB. + Variable spec_w_add_carry : + forall x y, [|w_add_carry x y|] = ([|x|] + [|y|] + 1) mod wB. + + Lemma spec_ww_succ_c : forall x, [+[ww_succ_c x]] = [[x]] + 1. + Proof. + destruct x as [ |xh xl];simpl. apply spec_ww_1. + generalize (spec_w_succ_c xl);destruct (w_succ_c xl) as [l|l]; + intro H;unfold interp_carry in H. simpl;rewrite H;ring. + rewrite <- Zplus_assoc;rewrite <- H;rewrite Zmult_1_l. + assert ([|l|] = 0). generalize (spec_to_Z xl)(spec_to_Z l);omega. + rewrite H0;generalize (spec_w_succ_c xh);destruct (w_succ_c xh) as [h|h]; + intro H1;unfold interp_carry in H1. + simpl;rewrite H1;rewrite spec_w_0;ring. + unfold interp_carry;simpl ww_to_Z;rewrite wwB_wBwB. + assert ([|xh|] = wB - 1). generalize (spec_to_Z xh)(spec_to_Z h);omega. + rewrite H2;ring. + Qed. + + Lemma spec_ww_add_c : forall x y, [+[ww_add_c x y]] = [[x]] + [[y]]. + Proof. + destruct x as [ |xh xl];simpl;trivial. + destruct y as [ |yh yl];simpl. rewrite Zplus_0_r;trivial. + replace ([|xh|] * wB + [|xl|] + ([|yh|] * wB + [|yl|])) + with (([|xh|]+[|yh|])*wB + ([|xl|]+[|yl|])). 2:ring. + generalize (spec_w_add_c xl yl);destruct (w_add_c xl yl) as [l|l]; + intros H;unfold interp_carry in H;rewrite <- H. + generalize (spec_w_add_c xh yh);destruct (w_add_c xh yh) as [h|h]; + intros H1;unfold interp_carry in *;rewrite <- H1. trivial. + repeat rewrite Zmult_1_l;rewrite spec_w_WW;rewrite wwB_wBwB; ring. + rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. + generalize (spec_w_add_carry_c xh yh);destruct (w_add_carry_c xh yh) + as [h|h]; intros H1;unfold interp_carry in *;rewrite <- H1. + simpl;ring. + repeat rewrite Zmult_1_l;rewrite wwB_wBwB;rewrite spec_w_WW;ring. + Qed. + + Section Cont. + Variable P : zn2z w -> zn2z w -> R -> Prop. + Variable x y : zn2z w. + Variable spec_f0 : forall r, [[r]] = [[x]] + [[y]] -> P x y (f0 r). + Variable spec_f1 : forall r, wwB + [[r]] = [[x]] + [[y]] -> P x y (f1 r). + + Lemma spec_ww_add_c_cont : P x y (ww_add_c_cont x y). + Proof. + destruct x as [ |xh xl];simpl;trivial. + apply spec_f0;trivial. + destruct y as [ |yh yl];simpl. + apply spec_f0;simpl;rewrite Zplus_0_r;trivial. + generalize (spec_w_add_c xl yl);destruct (w_add_c xl yl) as [l|l]; + intros H;unfold interp_carry in H. + generalize (spec_w_add_c xh yh);destruct (w_add_c xh yh) as [h|h]; + intros H1;unfold interp_carry in *. + apply spec_f0. simpl;rewrite H;rewrite H1;ring. + apply spec_f1. simpl;rewrite spec_w_WW;rewrite H. + rewrite Zplus_assoc;rewrite wwB_wBwB. rewrite Zpower_2; rewrite <- Zmult_plus_distr_l. + rewrite Zmult_1_l in H1;rewrite H1;ring. + generalize (spec_w_add_carry_c xh yh);destruct (w_add_carry_c xh yh) + as [h|h]; intros H1;unfold interp_carry in *. + apply spec_f0;simpl;rewrite H1. rewrite Zmult_plus_distr_l. + rewrite <- Zplus_assoc;rewrite H;ring. + apply spec_f1. simpl;rewrite spec_w_WW;rewrite wwB_wBwB. + rewrite Zplus_assoc; rewrite Zpower_2; rewrite <- Zmult_plus_distr_l. + rewrite Zmult_1_l in H1;rewrite H1. rewrite Zmult_plus_distr_l. + rewrite <- Zplus_assoc;rewrite H;ring. + Qed. + + End Cont. + + Lemma spec_ww_add_carry_c : + forall x y, [+[ww_add_carry_c x y]] = [[x]] + [[y]] + 1. + Proof. + destruct x as [ |xh xl];intro y;simpl. + exact (spec_ww_succ_c y). + destruct y as [ |yh yl];simpl. + rewrite Zplus_0_r;exact (spec_ww_succ_c (WW xh xl)). + replace ([|xh|] * wB + [|xl|] + ([|yh|] * wB + [|yl|]) + 1) + with (([|xh|]+[|yh|])*wB + ([|xl|]+[|yl|]+1)). 2:ring. + generalize (spec_w_add_carry_c xl yl);destruct (w_add_carry_c xl yl) + as [l|l];intros H;unfold interp_carry in H;rewrite <- H. + generalize (spec_w_add_c xh yh);destruct (w_add_c xh yh) as [h|h]; + intros H1;unfold interp_carry in H1;rewrite <- H1. trivial. + unfold interp_carry;repeat rewrite Zmult_1_l;simpl;rewrite wwB_wBwB;ring. + rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. + generalize (spec_w_add_carry_c xh yh);destruct (w_add_carry_c xh yh) + as [h|h];intros H1;unfold interp_carry in H1;rewrite <- H1. trivial. + unfold interp_carry;rewrite spec_w_WW; + repeat rewrite Zmult_1_l;simpl;rewrite wwB_wBwB;ring. + Qed. + + Lemma spec_ww_succ : forall x, [[ww_succ x]] = ([[x]] + 1) mod wwB. + Proof. + destruct x as [ |xh xl];simpl. + rewrite spec_ww_1;rewrite Zmod_small;trivial. + split;[intro;discriminate|apply wwB_pos]. + rewrite <- Zplus_assoc;generalize (spec_w_succ_c xl); + destruct (w_succ_c xl) as[l|l];intro H;unfold interp_carry in H;rewrite <-H. + rewrite Zmod_small;trivial. + rewrite wwB_wBwB;apply beta_mult;apply spec_to_Z. + assert ([|l|] = 0). clear spec_ww_1 spec_w_1 spec_w_0. + assert (H1:= spec_to_Z l); assert (H2:= spec_to_Z xl); omega. + rewrite H0;rewrite Zplus_0_r;rewrite <- Zmult_plus_distr_l;rewrite wwB_wBwB. + rewrite Zpower_2; rewrite Zmult_mod_distr_r;try apply lt_0_wB. + rewrite spec_w_W0;rewrite spec_w_succ;trivial. + Qed. + + Lemma spec_ww_add : forall x y, [[ww_add x y]] = ([[x]] + [[y]]) mod wwB. + Proof. + destruct x as [ |xh xl];intros y;simpl. + rewrite Zmod_small;trivial. apply spec_ww_to_Z;trivial. + destruct y as [ |yh yl]. + change [[W0]] with 0;rewrite Zplus_0_r. + rewrite Zmod_small;trivial. + exact (spec_ww_to_Z w_digits w_to_Z spec_to_Z (WW xh xl)). + simpl. replace ([|xh|] * wB + [|xl|] + ([|yh|] * wB + [|yl|])) + with (([|xh|]+[|yh|])*wB + ([|xl|]+[|yl|])). 2:ring. + generalize (spec_w_add_c xl yl);destruct (w_add_c xl yl) as [l|l]; + unfold interp_carry;intros H;simpl;rewrite <- H. + rewrite (mod_wwB w_digits w_to_Z spec_to_Z);rewrite spec_w_add;trivial. + rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. + rewrite(mod_wwB w_digits w_to_Z spec_to_Z);rewrite spec_w_add_carry;trivial. + Qed. + + Lemma spec_ww_add_carry : + forall x y, [[ww_add_carry x y]] = ([[x]] + [[y]] + 1) mod wwB. + Proof. + destruct x as [ |xh xl];intros y;simpl. + exact (spec_ww_succ y). + destruct y as [ |yh yl]. + change [[W0]] with 0;rewrite Zplus_0_r. exact (spec_ww_succ (WW xh xl)). + simpl;replace ([|xh|] * wB + [|xl|] + ([|yh|] * wB + [|yl|]) + 1) + with (([|xh|]+[|yh|])*wB + ([|xl|]+[|yl|]+1)). 2:ring. + generalize (spec_w_add_carry_c xl yl);destruct (w_add_carry_c xl yl) + as [l|l];unfold interp_carry;intros H;rewrite <- H;simpl ww_to_Z. + rewrite(mod_wwB w_digits w_to_Z spec_to_Z);rewrite spec_w_add;trivial. + rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. + rewrite(mod_wwB w_digits w_to_Z spec_to_Z);rewrite spec_w_add_carry;trivial. + Qed. + +(* End DoubleProof. *) +End DoubleAdd. diff --git a/theories/Numbers/Cyclic/DoubleCyclic/DoubleBase.v b/theories/Numbers/Cyclic/DoubleCyclic/DoubleBase.v new file mode 100644 index 00000000..952516ac --- /dev/null +++ b/theories/Numbers/Cyclic/DoubleCyclic/DoubleBase.v @@ -0,0 +1,446 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: DoubleBase.v 10964 2008-05-22 11:08:13Z letouzey $ i*) + +Set Implicit Arguments. + +Require Import ZArith. +Require Import BigNumPrelude. +Require Import DoubleType. + +Open Local Scope Z_scope. + +Section DoubleBase. + Variable w : Type. + Variable w_0 : w. + Variable w_1 : w. + Variable w_Bm1 : w. + Variable w_WW : w -> w -> zn2z w. + Variable w_0W : w -> zn2z w. + Variable w_digits : positive. + Variable w_zdigits: w. + Variable w_add: w -> w -> zn2z w. + Variable w_to_Z : w -> Z. + Variable w_compare : w -> w -> comparison. + + Definition ww_digits := xO w_digits. + + Definition ww_zdigits := w_add w_zdigits w_zdigits. + + Definition ww_to_Z := zn2z_to_Z (base w_digits) w_to_Z. + + Definition ww_1 := WW w_0 w_1. + + Definition ww_Bm1 := WW w_Bm1 w_Bm1. + + Definition ww_WW xh xl : zn2z (zn2z w) := + match xh, xl with + | W0, W0 => W0 + | _, _ => WW xh xl + end. + + Definition ww_W0 h : zn2z (zn2z w) := + match h with + | W0 => W0 + | _ => WW h W0 + end. + + Definition ww_0W l : zn2z (zn2z w) := + match l with + | W0 => W0 + | _ => WW W0 l + end. + + Definition double_WW (n:nat) := + match n return word w n -> word w n -> word w (S n) with + | O => w_WW + | S n => + fun (h l : zn2z (word w n)) => + match h, l with + | W0, W0 => W0 + | _, _ => WW h l + end + end. + + Fixpoint double_digits (n:nat) : positive := + match n with + | O => w_digits + | S n => xO (double_digits n) + end. + + Definition double_wB n := base (double_digits n). + + Fixpoint double_to_Z (n:nat) : word w n -> Z := + match n return word w n -> Z with + | O => w_to_Z + | S n => zn2z_to_Z (double_wB n) (double_to_Z n) + end. + + Fixpoint extend_aux (n:nat) (x:zn2z w) {struct n}: word w (S n) := + match n return word w (S n) with + | O => x + | S n1 => WW W0 (extend_aux n1 x) + end. + + Definition extend (n:nat) (x:w) : word w (S n) := + let r := w_0W x in + match r with + | W0 => W0 + | _ => extend_aux n r + end. + + Definition double_0 n : word w n := + match n return word w n with + | O => w_0 + | S _ => W0 + end. + + Definition double_split (n:nat) (x:zn2z (word w n)) := + match x with + | W0 => + match n return word w n * word w n with + | O => (w_0,w_0) + | S _ => (W0, W0) + end + | WW h l => (h,l) + end. + + Definition ww_compare x y := + match x, y with + | W0, W0 => Eq + | W0, WW yh yl => + match w_compare w_0 yh with + | Eq => w_compare w_0 yl + | _ => Lt + end + | WW xh xl, W0 => + match w_compare xh w_0 with + | Eq => w_compare xl w_0 + | _ => Gt + end + | WW xh xl, WW yh yl => + match w_compare xh yh with + | Eq => w_compare xl yl + | Lt => Lt + | Gt => Gt + end + end. + + + (* Return the low part of the composed word*) + Fixpoint get_low (n : nat) {struct n}: + word w n -> w := + match n return (word w n -> w) with + | 0%nat => fun x => x + | S n1 => + fun x => + match x with + | W0 => w_0 + | WW _ x1 => get_low n1 x1 + end + end. + + + Section DoubleProof. + Notation wB := (base w_digits). + Notation wwB := (base ww_digits). + Notation "[| x |]" := (w_to_Z x) (at level 0, x at level 99). + Notation "[[ x ]]" := (ww_to_Z x) (at level 0, x at level 99). + Notation "[+[ c ]]" := + (interp_carry 1 wwB ww_to_Z c) (at level 0, x at level 99). + Notation "[-[ c ]]" := + (interp_carry (-1) wwB ww_to_Z c) (at level 0, x at level 99). + Notation "[! n | x !]" := (double_to_Z n x) (at level 0, x at level 99). + + Variable spec_w_0 : [|w_0|] = 0. + Variable spec_w_1 : [|w_1|] = 1. + Variable spec_w_Bm1 : [|w_Bm1|] = wB - 1. + Variable spec_w_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|]. + Variable spec_w_0W : forall l, [[w_0W l]] = [|l|]. + Variable spec_to_Z : forall x, 0 <= [|x|] < wB. + Variable spec_w_compare : forall x y, + match w_compare x y with + | Eq => [|x|] = [|y|] + | Lt => [|x|] < [|y|] + | Gt => [|x|] > [|y|] + end. + + Lemma wwB_wBwB : wwB = wB^2. + Proof. + unfold base, ww_digits;rewrite Zpower_2; rewrite (Zpos_xO w_digits). + replace (2 * Zpos w_digits) with (Zpos w_digits + Zpos w_digits). + apply Zpower_exp; unfold Zge;simpl;intros;discriminate. + ring. + Qed. + + Lemma spec_ww_1 : [[ww_1]] = 1. + Proof. simpl;rewrite spec_w_0;rewrite spec_w_1;ring. Qed. + + Lemma spec_ww_Bm1 : [[ww_Bm1]] = wwB - 1. + Proof. simpl;rewrite spec_w_Bm1;rewrite wwB_wBwB;ring. Qed. + + Lemma lt_0_wB : 0 < wB. + Proof. + unfold base;apply Zpower_gt_0. unfold Zlt;reflexivity. + unfold Zle;intros H;discriminate H. + Qed. + + Lemma lt_0_wwB : 0 < wwB. + Proof. rewrite wwB_wBwB; rewrite Zpower_2; apply Zmult_lt_0_compat;apply lt_0_wB. Qed. + + Lemma wB_pos: 1 < wB. + Proof. + unfold base;apply Zlt_le_trans with (2^1). unfold Zlt;reflexivity. + apply Zpower_le_monotone. unfold Zlt;reflexivity. + split;unfold Zle;intros H. discriminate H. + clear spec_w_0W w_0W spec_w_Bm1 spec_to_Z spec_w_WW w_WW. + destruct w_digits; discriminate H. + Qed. + + Lemma wwB_pos: 1 < wwB. + Proof. + assert (H:= wB_pos);rewrite wwB_wBwB;rewrite <-(Zmult_1_r 1). + rewrite Zpower_2. + apply Zmult_lt_compat2;(split;[unfold Zlt;reflexivity|trivial]). + apply Zlt_le_weak;trivial. + Qed. + + Theorem wB_div_2: 2 * (wB / 2) = wB. + Proof. + clear spec_w_0 w_0 spec_w_1 w_1 spec_w_Bm1 w_Bm1 spec_w_WW spec_w_0W + spec_to_Z;unfold base. + assert (2 ^ Zpos w_digits = 2 * (2 ^ (Zpos w_digits - 1))). + pattern 2 at 2; rewrite <- Zpower_1_r. + rewrite <- Zpower_exp; auto with zarith. + f_equal; auto with zarith. + case w_digits; compute; intros; discriminate. + rewrite H; f_equal; auto with zarith. + rewrite Zmult_comm; apply Z_div_mult; auto with zarith. + Qed. + + Theorem wwB_div_2 : wwB / 2 = wB / 2 * wB. + Proof. + clear spec_w_0 w_0 spec_w_1 w_1 spec_w_Bm1 w_Bm1 spec_w_WW spec_w_0W + spec_to_Z. + rewrite wwB_wBwB; rewrite Zpower_2. + pattern wB at 1; rewrite <- wB_div_2; auto. + rewrite <- Zmult_assoc. + repeat (rewrite (Zmult_comm 2); rewrite Z_div_mult); auto with zarith. + Qed. + + Lemma mod_wwB : forall z x, + (z*wB + [|x|]) mod wwB = (z mod wB)*wB + [|x|]. + Proof. + intros z x. + rewrite Zplus_mod. + pattern wwB at 1;rewrite wwB_wBwB; rewrite Zpower_2. + rewrite Zmult_mod_distr_r;try apply lt_0_wB. + rewrite (Zmod_small [|x|]). + apply Zmod_small;rewrite wwB_wBwB;apply beta_mult;try apply spec_to_Z. + apply Z_mod_lt;apply Zlt_gt;apply lt_0_wB. + destruct (spec_to_Z x);split;trivial. + change [|x|] with (0*wB+[|x|]). rewrite wwB_wBwB. + rewrite Zpower_2;rewrite <- (Zplus_0_r (wB*wB));apply beta_lex_inv. + apply lt_0_wB. apply spec_to_Z. split;[apply Zle_refl | apply lt_0_wB]. + Qed. + + Lemma wB_div : forall x y, ([|x|] * wB + [|y|]) / wB = [|x|]. + Proof. + clear spec_w_0 spec_w_1 spec_w_Bm1 w_0 w_1 w_Bm1. + intros x y;unfold base;rewrite Zdiv_shift_r;auto with zarith. + rewrite Z_div_mult;auto with zarith. + destruct (spec_to_Z x);trivial. + Qed. + + Lemma wB_div_plus : forall x y p, + 0 <= p -> + ([|x|]*wB + [|y|]) / 2^(Zpos w_digits + p) = [|x|] / 2^p. + Proof. + clear spec_w_0 spec_w_1 spec_w_Bm1 w_0 w_1 w_Bm1. + intros x y p Hp;rewrite Zpower_exp;auto with zarith. + rewrite <- Zdiv_Zdiv;auto with zarith. + rewrite wB_div;trivial. + Qed. + + Lemma lt_wB_wwB : wB < wwB. + Proof. + clear spec_w_0 spec_w_1 spec_w_Bm1 w_0 w_1 w_Bm1. + unfold base;apply Zpower_lt_monotone;auto with zarith. + assert (0 < Zpos w_digits). compute;reflexivity. + unfold ww_digits;rewrite Zpos_xO;auto with zarith. + Qed. + + Lemma w_to_Z_wwB : forall x, x < wB -> x < wwB. + Proof. + intros x H;apply Zlt_trans with wB;trivial;apply lt_wB_wwB. + Qed. + + Lemma spec_ww_to_Z : forall x, 0 <= [[x]] < wwB. + Proof. + clear spec_w_0 spec_w_1 spec_w_Bm1 w_0 w_1 w_Bm1. + destruct x as [ |h l];simpl. + split;[apply Zle_refl|apply lt_0_wwB]. + assert (H:=spec_to_Z h);assert (L:=spec_to_Z l);split. + apply Zplus_le_0_compat;auto with zarith. + rewrite <- (Zplus_0_r wwB);rewrite wwB_wBwB; rewrite Zpower_2; + apply beta_lex_inv;auto with zarith. + Qed. + + Lemma double_wB_wwB : forall n, double_wB n * double_wB n = double_wB (S n). + Proof. + intros n;unfold double_wB;simpl. + unfold base;rewrite (Zpos_xO (double_digits n)). + replace (2 * Zpos (double_digits n)) with + (Zpos (double_digits n) + Zpos (double_digits n)). + symmetry; apply Zpower_exp;intro;discriminate. + ring. + Qed. + + Lemma double_wB_pos: + forall n, 0 <= double_wB n. + Proof. + intros n; unfold double_wB, base; auto with zarith. + Qed. + + Lemma double_wB_more_digits: + forall n, wB <= double_wB n. + Proof. + clear spec_w_0 spec_w_1 spec_w_Bm1 w_0 w_1 w_Bm1. + intros n; elim n; clear n; auto. + unfold double_wB, double_digits; auto with zarith. + intros n H1; rewrite <- double_wB_wwB. + apply Zle_trans with (wB * 1). + rewrite Zmult_1_r; apply Zle_refl. + apply Zmult_le_compat; auto with zarith. + apply Zle_trans with wB; auto with zarith. + unfold base. + rewrite <- (Zpower_0_r 2). + apply Zpower_le_monotone2; auto with zarith. + unfold base; auto with zarith. + Qed. + + Lemma spec_double_to_Z : + forall n (x:word w n), 0 <= [!n | x!] < double_wB n. + Proof. + clear spec_w_0 spec_w_1 spec_w_Bm1 w_0 w_1 w_Bm1. + induction n;intros. exact (spec_to_Z x). + unfold double_to_Z;fold double_to_Z. + destruct x;unfold zn2z_to_Z. + unfold double_wB,base;split;auto with zarith. + assert (U0:= IHn w0);assert (U1:= IHn w1). + split;auto with zarith. + apply Zlt_le_trans with ((double_wB n - 1) * double_wB n + double_wB n). + assert (double_to_Z n w0*double_wB n <= (double_wB n - 1)*double_wB n). + apply Zmult_le_compat_r;auto with zarith. + auto with zarith. + rewrite <- double_wB_wwB. + replace ((double_wB n - 1) * double_wB n + double_wB n) with (double_wB n * double_wB n); + [auto with zarith | ring]. + Qed. + + Lemma spec_get_low: + forall n x, + [!n | x!] < wB -> [|get_low n x|] = [!n | x!]. + Proof. + clear spec_w_1 spec_w_Bm1. + intros n; elim n; auto; clear n. + intros n Hrec x; case x; clear x; auto. + intros xx yy H1; simpl in H1. + assert (F1: [!n | xx!] = 0). + case (Zle_lt_or_eq 0 ([!n | xx!])); auto. + case (spec_double_to_Z n xx); auto. + intros F2. + assert (F3 := double_wB_more_digits n). + assert (F4: 0 <= [!n | yy!]). + case (spec_double_to_Z n yy); auto. + assert (F5: 1 * wB <= [!n | xx!] * double_wB n); + auto with zarith. + apply Zmult_le_compat; auto with zarith. + unfold base; auto with zarith. + simpl get_low; simpl double_to_Z. + generalize H1; clear H1. + rewrite F1; rewrite Zmult_0_l; rewrite Zplus_0_l. + intros H1; apply Hrec; auto. + Qed. + + Lemma spec_double_WW : forall n (h l : word w n), + [!S n|double_WW n h l!] = [!n|h!] * double_wB n + [!n|l!]. + Proof. + induction n;simpl;intros;trivial. + destruct h;auto. + destruct l;auto. + Qed. + + Lemma spec_extend_aux : forall n x, [!S n|extend_aux n x!] = [[x]]. + Proof. induction n;simpl;trivial. Qed. + + Lemma spec_extend : forall n x, [!S n|extend n x!] = [|x|]. + Proof. + intros n x;assert (H:= spec_w_0W x);unfold extend. + destruct (w_0W x);simpl;trivial. + rewrite <- H;exact (spec_extend_aux n (WW w0 w1)). + Qed. + + Lemma spec_double_0 : forall n, [!n|double_0 n!] = 0. + Proof. destruct n;trivial. Qed. + + Lemma spec_double_split : forall n x, + let (h,l) := double_split n x in + [!S n|x!] = [!n|h!] * double_wB n + [!n|l!]. + Proof. + destruct x;simpl;auto. + destruct n;simpl;trivial. + rewrite spec_w_0;trivial. + Qed. + + Lemma wB_lex_inv: forall a b c d, + a < c -> + a * wB + [|b|] < c * wB + [|d|]. + Proof. + intros a b c d H1; apply beta_lex_inv with (1 := H1); auto. + Qed. + + Lemma spec_ww_compare : forall x y, + match ww_compare x y with + | Eq => [[x]] = [[y]] + | Lt => [[x]] < [[y]] + | Gt => [[x]] > [[y]] + end. + Proof. + destruct x as [ |xh xl];destruct y as [ |yh yl];simpl;trivial. + generalize (spec_w_compare w_0 yh);destruct (w_compare w_0 yh); + intros H;rewrite spec_w_0 in H. + rewrite <- H;simpl;rewrite <- spec_w_0;apply spec_w_compare. + change 0 with (0*wB+0);pattern 0 at 2;rewrite <- spec_w_0. + apply wB_lex_inv;trivial. + absurd (0 <= [|yh|]). apply Zgt_not_le;trivial. + destruct (spec_to_Z yh);trivial. + generalize (spec_w_compare xh w_0);destruct (w_compare xh w_0); + intros H;rewrite spec_w_0 in H. + rewrite H;simpl;rewrite <- spec_w_0;apply spec_w_compare. + absurd (0 <= [|xh|]). apply Zgt_not_le;apply Zlt_gt;trivial. + destruct (spec_to_Z xh);trivial. + apply Zlt_gt;change 0 with (0*wB+0);pattern 0 at 2;rewrite <- spec_w_0. + apply wB_lex_inv;apply Zgt_lt;trivial. + + generalize (spec_w_compare xh yh);destruct (w_compare xh yh);intros H. + rewrite H;generalize (spec_w_compare xl yl);destruct (w_compare xl yl); + intros H1;[rewrite H1|apply Zplus_lt_compat_l|apply Zplus_gt_compat_l]; + trivial. + apply wB_lex_inv;trivial. + apply Zlt_gt;apply wB_lex_inv;apply Zgt_lt;trivial. + Qed. + + + End DoubleProof. + +End DoubleBase. + diff --git a/theories/Numbers/Cyclic/DoubleCyclic/DoubleCyclic.v b/theories/Numbers/Cyclic/DoubleCyclic/DoubleCyclic.v new file mode 100644 index 00000000..cca32a59 --- /dev/null +++ b/theories/Numbers/Cyclic/DoubleCyclic/DoubleCyclic.v @@ -0,0 +1,885 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: DoubleCyclic.v 11012 2008-05-28 16:34:43Z letouzey $ i*) + +Set Implicit Arguments. + +Require Import ZArith. +Require Import BigNumPrelude. +Require Import DoubleType. +Require Import DoubleBase. +Require Import DoubleAdd. +Require Import DoubleSub. +Require Import DoubleMul. +Require Import DoubleSqrt. +Require Import DoubleLift. +Require Import DoubleDivn1. +Require Import DoubleDiv. +Require Import CyclicAxioms. + +Open Local Scope Z_scope. + + +Section Z_2nZ. + + Variable w : Type. + Variable w_op : znz_op w. + Let w_digits := w_op.(znz_digits). + Let w_zdigits := w_op.(znz_zdigits). + + Let w_to_Z := w_op.(znz_to_Z). + Let w_of_pos := w_op.(znz_of_pos). + Let w_head0 := w_op.(znz_head0). + Let w_tail0 := w_op.(znz_tail0). + + Let w_0 := w_op.(znz_0). + Let w_1 := w_op.(znz_1). + Let w_Bm1 := w_op.(znz_Bm1). + + Let w_compare := w_op.(znz_compare). + Let w_eq0 := w_op.(znz_eq0). + + Let w_opp_c := w_op.(znz_opp_c). + Let w_opp := w_op.(znz_opp). + Let w_opp_carry := w_op.(znz_opp_carry). + + Let w_succ_c := w_op.(znz_succ_c). + Let w_add_c := w_op.(znz_add_c). + Let w_add_carry_c := w_op.(znz_add_carry_c). + Let w_succ := w_op.(znz_succ). + Let w_add := w_op.(znz_add). + Let w_add_carry := w_op.(znz_add_carry). + + Let w_pred_c := w_op.(znz_pred_c). + Let w_sub_c := w_op.(znz_sub_c). + Let w_sub_carry_c := w_op.(znz_sub_carry_c). + Let w_pred := w_op.(znz_pred). + Let w_sub := w_op.(znz_sub). + Let w_sub_carry := w_op.(znz_sub_carry). + + + Let w_mul_c := w_op.(znz_mul_c). + Let w_mul := w_op.(znz_mul). + Let w_square_c := w_op.(znz_square_c). + + Let w_div21 := w_op.(znz_div21). + Let w_div_gt := w_op.(znz_div_gt). + Let w_div := w_op.(znz_div). + + Let w_mod_gt := w_op.(znz_mod_gt). + Let w_mod := w_op.(znz_mod). + + Let w_gcd_gt := w_op.(znz_gcd_gt). + Let w_gcd := w_op.(znz_gcd). + + Let w_add_mul_div := w_op.(znz_add_mul_div). + + Let w_pos_mod := w_op.(znz_pos_mod). + + Let w_is_even := w_op.(znz_is_even). + Let w_sqrt2 := w_op.(znz_sqrt2). + Let w_sqrt := w_op.(znz_sqrt). + + Let _zn2z := zn2z w. + + Let wB := base w_digits. + + Let w_Bm2 := w_pred w_Bm1. + + Let ww_1 := ww_1 w_0 w_1. + Let ww_Bm1 := ww_Bm1 w_Bm1. + + Let w_add2 a b := match w_add_c a b with C0 p => WW w_0 p | C1 p => WW w_1 p end. + + Let _ww_digits := xO w_digits. + + Let _ww_zdigits := w_add2 w_zdigits w_zdigits. + + Let to_Z := zn2z_to_Z wB w_to_Z. + + Let w_W0 := znz_W0 w_op. + Let w_0W := znz_0W w_op. + Let w_WW := znz_WW w_op. + + Let ww_of_pos p := + match w_of_pos p with + | (N0, l) => (N0, WW w_0 l) + | (Npos ph,l) => + let (n,h) := w_of_pos ph in (n, w_WW h l) + end. + + Let head0 := + Eval lazy beta delta [ww_head0] in + ww_head0 w_0 w_0W w_compare w_head0 w_add2 w_zdigits _ww_zdigits. + + Let tail0 := + Eval lazy beta delta [ww_tail0] in + ww_tail0 w_0 w_0W w_compare w_tail0 w_add2 w_zdigits _ww_zdigits. + + Let ww_WW := Eval lazy beta delta [ww_WW] in (@ww_WW w). + Let ww_0W := Eval lazy beta delta [ww_0W] in (@ww_0W w). + Let ww_W0 := Eval lazy beta delta [ww_W0] in (@ww_W0 w). + + (* ** Comparison ** *) + Let compare := + Eval lazy beta delta[ww_compare] in ww_compare w_0 w_compare. + + Let eq0 (x:zn2z w) := + match x with + | W0 => true + | _ => false + end. + + (* ** Opposites ** *) + Let opp_c := + Eval lazy beta delta [ww_opp_c] in ww_opp_c w_0 w_opp_c w_opp_carry. + + Let opp := + Eval lazy beta delta [ww_opp] in ww_opp w_0 w_opp_c w_opp_carry w_opp. + + Let opp_carry := + Eval lazy beta delta [ww_opp_carry] in ww_opp_carry w_WW ww_Bm1 w_opp_carry. + + (* ** Additions ** *) + + Let succ_c := + Eval lazy beta delta [ww_succ_c] in ww_succ_c w_0 ww_1 w_succ_c. + + Let add_c := + Eval lazy beta delta [ww_add_c] in ww_add_c w_WW w_add_c w_add_carry_c. + + Let add_carry_c := + Eval lazy beta iota delta [ww_add_carry_c ww_succ_c] in + ww_add_carry_c w_0 w_WW ww_1 w_succ_c w_add_c w_add_carry_c. + + Let succ := + Eval lazy beta delta [ww_succ] in ww_succ w_W0 ww_1 w_succ_c w_succ. + + Let add := + Eval lazy beta delta [ww_add] in ww_add w_add_c w_add w_add_carry. + + Let add_carry := + Eval lazy beta iota delta [ww_add_carry ww_succ] in + ww_add_carry w_W0 ww_1 w_succ_c w_add_carry_c w_succ w_add w_add_carry. + + (* ** Subtractions ** *) + + Let pred_c := + Eval lazy beta delta [ww_pred_c] in ww_pred_c w_Bm1 w_WW ww_Bm1 w_pred_c. + + Let sub_c := + Eval lazy beta iota delta [ww_sub_c ww_opp_c] in + ww_sub_c w_0 w_WW w_opp_c w_opp_carry w_sub_c w_sub_carry_c. + + Let sub_carry_c := + Eval lazy beta iota delta [ww_sub_carry_c ww_pred_c ww_opp_carry] in + ww_sub_carry_c w_Bm1 w_WW ww_Bm1 w_opp_carry w_pred_c w_sub_c w_sub_carry_c. + + Let pred := + Eval lazy beta delta [ww_pred] in ww_pred w_Bm1 w_WW ww_Bm1 w_pred_c w_pred. + + Let sub := + Eval lazy beta iota delta [ww_sub ww_opp] in + ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c w_opp w_sub w_sub_carry. + + Let sub_carry := + Eval lazy beta iota delta [ww_sub_carry ww_pred ww_opp_carry] in + ww_sub_carry w_Bm1 w_WW ww_Bm1 w_opp_carry w_pred_c w_sub_carry_c w_pred + w_sub w_sub_carry. + + + (* ** Multiplication ** *) + + Let mul_c := + Eval lazy beta iota delta [ww_mul_c double_mul_c] in + ww_mul_c w_0 w_1 w_WW w_W0 w_mul_c add_c add add_carry. + + Let karatsuba_c := + Eval lazy beta iota delta [ww_karatsuba_c double_mul_c kara_prod] in + ww_karatsuba_c w_0 w_1 w_WW w_W0 w_compare w_add w_sub w_mul_c + add_c add add_carry sub_c sub. + + Let mul := + Eval lazy beta delta [ww_mul] in + ww_mul w_W0 w_add w_mul_c w_mul add. + + Let square_c := + Eval lazy beta delta [ww_square_c] in + ww_square_c w_0 w_1 w_WW w_W0 w_mul_c w_square_c add_c add add_carry. + + (* Division operation *) + + Let div32 := + Eval lazy beta iota delta [w_div32] in + w_div32 w_0 w_Bm1 w_Bm2 w_WW w_compare w_add_c w_add_carry_c + w_add w_add_carry w_pred w_sub w_mul_c w_div21 sub_c. + + Let div21 := + Eval lazy beta iota delta [ww_div21] in + ww_div21 w_0 w_0W div32 ww_1 compare sub. + + Let low (p: zn2z w) := match p with WW _ p1 => p1 | _ => w_0 end. + + Let add_mul_div := + Eval lazy beta delta [ww_add_mul_div] in + ww_add_mul_div w_0 w_WW w_W0 w_0W compare w_add_mul_div sub w_zdigits low. + + Let div_gt := + Eval lazy beta delta [ww_div_gt] in + ww_div_gt w_0 w_WW w_0W w_compare w_eq0 w_opp_c w_opp + w_opp_carry w_sub_c w_sub w_sub_carry + w_div_gt w_add_mul_div w_head0 w_div21 div32 _ww_zdigits ww_1 add_mul_div w_zdigits. + + Let div := + Eval lazy beta delta [ww_div] in ww_div ww_1 compare div_gt. + + Let mod_gt := + Eval lazy beta delta [ww_mod_gt] in + ww_mod_gt w_0 w_WW w_0W w_compare w_eq0 w_opp_c w_opp w_opp_carry w_sub_c w_sub w_sub_carry + w_mod_gt w_add_mul_div w_head0 w_div21 div32 _ww_zdigits add_mul_div w_zdigits. + + Let mod_ := + Eval lazy beta delta [ww_mod] in ww_mod compare mod_gt. + + Let pos_mod := + Eval lazy beta delta [ww_pos_mod] in + ww_pos_mod w_0 w_zdigits w_WW w_pos_mod compare w_0W low sub _ww_zdigits. + + Let is_even := + Eval lazy beta delta [ww_is_even] in ww_is_even w_is_even. + + Let sqrt2 := + Eval lazy beta delta [ww_sqrt2] in + ww_sqrt2 w_is_even w_compare w_0 w_1 w_Bm1 w_0W w_sub w_square_c + w_div21 w_add_mul_div w_zdigits w_add_c w_sqrt2 w_pred pred_c + pred add_c add sub_c add_mul_div. + + Let sqrt := + Eval lazy beta delta [ww_sqrt] in + ww_sqrt w_is_even w_0 w_sub w_add_mul_div w_zdigits + _ww_zdigits w_sqrt2 pred add_mul_div head0 compare low. + + Let gcd_gt_fix := + Eval cbv beta delta [ww_gcd_gt_aux ww_gcd_gt_body] in + ww_gcd_gt_aux w_0 w_WW w_0W w_compare w_opp_c w_opp w_opp_carry + w_sub_c w_sub w_sub_carry w_gcd_gt + w_add_mul_div w_head0 w_div21 div32 _ww_zdigits add_mul_div + w_zdigits. + + Let gcd_cont := + Eval lazy beta delta [gcd_cont] in gcd_cont ww_1 w_1 w_compare. + + Let gcd_gt := + Eval lazy beta delta [ww_gcd_gt] in + ww_gcd_gt w_0 w_eq0 w_gcd_gt _ww_digits gcd_gt_fix gcd_cont. + + Let gcd := + Eval lazy beta delta [ww_gcd] in + ww_gcd compare w_0 w_eq0 w_gcd_gt _ww_digits gcd_gt_fix gcd_cont. + + (* ** Record of operators on 2 words *) + + Definition mk_zn2z_op := + mk_znz_op _ww_digits _ww_zdigits + to_Z ww_of_pos head0 tail0 + W0 ww_1 ww_Bm1 + compare eq0 + opp_c opp opp_carry + succ_c add_c add_carry_c + succ add add_carry + pred_c sub_c sub_carry_c + pred sub sub_carry + mul_c mul square_c + div21 div_gt div + mod_gt mod_ + gcd_gt gcd + add_mul_div + pos_mod + is_even + sqrt2 + sqrt. + + Definition mk_zn2z_op_karatsuba := + mk_znz_op _ww_digits _ww_zdigits + to_Z ww_of_pos head0 tail0 + W0 ww_1 ww_Bm1 + compare eq0 + opp_c opp opp_carry + succ_c add_c add_carry_c + succ add add_carry + pred_c sub_c sub_carry_c + pred sub sub_carry + karatsuba_c mul square_c + div21 div_gt div + mod_gt mod_ + gcd_gt gcd + add_mul_div + pos_mod + is_even + sqrt2 + sqrt. + + (* Proof *) + Variable op_spec : znz_spec w_op. + + Hint Resolve + (spec_to_Z op_spec) + (spec_of_pos op_spec) + (spec_0 op_spec) + (spec_1 op_spec) + (spec_Bm1 op_spec) + (spec_compare op_spec) + (spec_eq0 op_spec) + (spec_opp_c op_spec) + (spec_opp op_spec) + (spec_opp_carry op_spec) + (spec_succ_c op_spec) + (spec_add_c op_spec) + (spec_add_carry_c op_spec) + (spec_succ op_spec) + (spec_add op_spec) + (spec_add_carry op_spec) + (spec_pred_c op_spec) + (spec_sub_c op_spec) + (spec_sub_carry_c op_spec) + (spec_pred op_spec) + (spec_sub op_spec) + (spec_sub_carry op_spec) + (spec_mul_c op_spec) + (spec_mul op_spec) + (spec_square_c op_spec) + (spec_div21 op_spec) + (spec_div_gt op_spec) + (spec_div op_spec) + (spec_mod_gt op_spec) + (spec_mod op_spec) + (spec_gcd_gt op_spec) + (spec_gcd op_spec) + (spec_head0 op_spec) + (spec_tail0 op_spec) + (spec_add_mul_div op_spec) + (spec_pos_mod) + (spec_is_even) + (spec_sqrt2) + (spec_sqrt) + (spec_W0 op_spec) + (spec_0W op_spec) + (spec_WW op_spec). + + Ltac wwauto := unfold ww_to_Z; auto. + + Let wwB := base _ww_digits. + + Notation "[| x |]" := (to_Z x) (at level 0, x at level 99). + + Notation "[+| c |]" := + (interp_carry 1 wwB to_Z c) (at level 0, x at level 99). + + Notation "[-| c |]" := + (interp_carry (-1) wwB to_Z c) (at level 0, x at level 99). + + Notation "[[ x ]]" := (zn2z_to_Z wwB to_Z x) (at level 0, x at level 99). + + Let spec_ww_to_Z : forall x, 0 <= [| x |] < wwB. + Proof. refine (spec_ww_to_Z w_digits w_to_Z _);auto. Qed. + + Let spec_ww_of_pos : forall p, + Zpos p = (Z_of_N (fst (ww_of_pos p)))*wwB + [|(snd (ww_of_pos p))|]. + Proof. + unfold ww_of_pos;intros. + assert (H:= spec_of_pos op_spec p);unfold w_of_pos; + destruct (znz_of_pos w_op p). simpl in H. + rewrite H;clear H;destruct n;simpl to_Z. + simpl;unfold w_to_Z,w_0;rewrite (spec_0 op_spec);trivial. + unfold Z_of_N; assert (H:= spec_of_pos op_spec p0); + destruct (znz_of_pos w_op p0). simpl in H. + rewrite H;unfold fst, snd,Z_of_N, to_Z. + rewrite (spec_WW op_spec). + replace wwB with (wB*wB). + unfold wB,w_to_Z,w_digits;clear H;destruct n;ring. + symmetry. rewrite <- Zpower_2; exact (wwB_wBwB w_digits). + Qed. + + Let spec_ww_0 : [|W0|] = 0. + Proof. reflexivity. Qed. + + Let spec_ww_1 : [|ww_1|] = 1. + Proof. refine (spec_ww_1 w_0 w_1 w_digits w_to_Z _ _);auto. Qed. + + Let spec_ww_Bm1 : [|ww_Bm1|] = wwB - 1. + Proof. refine (spec_ww_Bm1 w_Bm1 w_digits w_to_Z _);auto. Qed. + + Let spec_ww_compare : + forall x y, + match compare x y with + | Eq => [|x|] = [|y|] + | Lt => [|x|] < [|y|] + | Gt => [|x|] > [|y|] + end. + Proof. + refine (spec_ww_compare w_0 w_digits w_to_Z w_compare _ _ _);auto. + exact (spec_compare op_spec). + Qed. + + Let spec_ww_eq0 : forall x, eq0 x = true -> [|x|] = 0. + Proof. destruct x;simpl;intros;trivial;discriminate. Qed. + + Let spec_ww_opp_c : forall x, [-|opp_c x|] = -[|x|]. + Proof. + refine(spec_ww_opp_c w_0 w_0 W0 w_opp_c w_opp_carry w_digits w_to_Z _ _ _ _); + auto. + Qed. + + Let spec_ww_opp : forall x, [|opp x|] = (-[|x|]) mod wwB. + Proof. + refine(spec_ww_opp w_0 w_0 W0 w_opp_c w_opp_carry w_opp + w_digits w_to_Z _ _ _ _ _); + auto. + Qed. + + Let spec_ww_opp_carry : forall x, [|opp_carry x|] = wwB - [|x|] - 1. + Proof. + refine (spec_ww_opp_carry w_WW ww_Bm1 w_opp_carry w_digits w_to_Z _ _ _); + wwauto. + Qed. + + Let spec_ww_succ_c : forall x, [+|succ_c x|] = [|x|] + 1. + Proof. + refine (spec_ww_succ_c w_0 w_0 ww_1 w_succ_c w_digits w_to_Z _ _ _ _);auto. + Qed. + + Let spec_ww_add_c : forall x y, [+|add_c x y|] = [|x|] + [|y|]. + Proof. + refine (spec_ww_add_c w_WW w_add_c w_add_carry_c w_digits w_to_Z _ _ _);wwauto. + Qed. + + Let spec_ww_add_carry_c : forall x y, [+|add_carry_c x y|] = [|x|]+[|y|]+1. + Proof. + refine (spec_ww_add_carry_c w_0 w_0 w_WW ww_1 w_succ_c w_add_c w_add_carry_c + w_digits w_to_Z _ _ _ _ _ _ _);wwauto. + Qed. + + Let spec_ww_succ : forall x, [|succ x|] = ([|x|] + 1) mod wwB. + Proof. + refine (spec_ww_succ w_W0 ww_1 w_succ_c w_succ w_digits w_to_Z _ _ _ _ _); + wwauto. + Qed. + + Let spec_ww_add : forall x y, [|add x y|] = ([|x|] + [|y|]) mod wwB. + Proof. + refine (spec_ww_add w_add_c w_add w_add_carry w_digits w_to_Z _ _ _ _);auto. + Qed. + + Let spec_ww_add_carry : forall x y, [|add_carry x y|]=([|x|]+[|y|]+1)mod wwB. + Proof. + refine (spec_ww_add_carry w_W0 ww_1 w_succ_c w_add_carry_c w_succ + w_add w_add_carry w_digits w_to_Z _ _ _ _ _ _ _ _);wwauto. + Qed. + + Let spec_ww_pred_c : forall x, [-|pred_c x|] = [|x|] - 1. + Proof. + refine (spec_ww_pred_c w_0 w_Bm1 w_WW ww_Bm1 w_pred_c w_digits w_to_Z + _ _ _ _ _);wwauto. + Qed. + + Let spec_ww_sub_c : forall x y, [-|sub_c x y|] = [|x|] - [|y|]. + Proof. + refine (spec_ww_sub_c w_0 w_0 w_WW W0 w_opp_c w_opp_carry w_sub_c + w_sub_carry_c w_digits w_to_Z _ _ _ _ _ _ _);wwauto. + Qed. + + Let spec_ww_sub_carry_c : forall x y, [-|sub_carry_c x y|] = [|x|]-[|y|]-1. + Proof. + refine (spec_ww_sub_carry_c w_0 w_Bm1 w_WW ww_Bm1 w_opp_carry w_pred_c + w_sub_c w_sub_carry_c w_digits w_to_Z _ _ _ _ _ _ _ _);wwauto. + Qed. + + Let spec_ww_pred : forall x, [|pred x|] = ([|x|] - 1) mod wwB. + Proof. + refine (spec_ww_pred w_0 w_Bm1 w_WW ww_Bm1 w_pred_c w_pred w_digits w_to_Z + _ _ _ _ _ _);wwauto. + Qed. + + Let spec_ww_sub : forall x y, [|sub x y|] = ([|x|] - [|y|]) mod wwB. + Proof. + refine (spec_ww_sub w_0 w_0 w_WW W0 w_opp_c w_opp_carry w_sub_c w_opp + w_sub w_sub_carry w_digits w_to_Z _ _ _ _ _ _ _ _ _);wwauto. + Qed. + + Let spec_ww_sub_carry : forall x y, [|sub_carry x y|]=([|x|]-[|y|]-1) mod wwB. + Proof. + refine (spec_ww_sub_carry w_0 w_Bm1 w_WW ww_Bm1 w_opp_carry w_pred_c + w_sub_carry_c w_pred w_sub w_sub_carry w_digits w_to_Z _ _ _ _ _ _ _ _ _ _); + wwauto. + Qed. + + Let spec_ww_mul_c : forall x y, [[mul_c x y ]] = [|x|] * [|y|]. + Proof. + refine (spec_ww_mul_c w_0 w_1 w_WW w_W0 w_mul_c add_c add add_carry w_digits + w_to_Z _ _ _ _ _ _ _ _ _);wwauto. + Qed. + + Let spec_ww_karatsuba_c : forall x y, [[karatsuba_c x y ]] = [|x|] * [|y|]. + Proof. + refine (spec_ww_karatsuba_c _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ _ _ _ _); wwauto. + unfold w_digits; apply spec_more_than_1_digit; auto. + exact (spec_compare op_spec). + Qed. + + Let spec_ww_mul : forall x y, [|mul x y|] = ([|x|] * [|y|]) mod wwB. + Proof. + refine (spec_ww_mul w_W0 w_add w_mul_c w_mul add w_digits w_to_Z _ _ _ _ _); + wwauto. + Qed. + + Let spec_ww_square_c : forall x, [[square_c x]] = [|x|] * [|x|]. + Proof. + refine (spec_ww_square_c w_0 w_1 w_WW w_W0 w_mul_c w_square_c add_c add + add_carry w_digits w_to_Z _ _ _ _ _ _ _ _ _ _);wwauto. + Qed. + + Let spec_w_div32 : forall a1 a2 a3 b1 b2, + wB / 2 <= (w_to_Z b1) -> + [|WW a1 a2|] < [|WW b1 b2|] -> + let (q, r) := div32 a1 a2 a3 b1 b2 in + (w_to_Z a1) * wwB + (w_to_Z a2) * wB + (w_to_Z a3) = + (w_to_Z q) * ((w_to_Z b1)*wB + (w_to_Z b2)) + [|r|] /\ + 0 <= [|r|] < (w_to_Z b1)*wB + w_to_Z b2. + Proof. + refine (spec_w_div32 w_0 w_Bm1 w_Bm2 w_WW w_compare w_add_c w_add_carry_c + w_add w_add_carry w_pred w_sub w_mul_c w_div21 sub_c w_digits w_to_Z + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _);wwauto. + unfold w_Bm2, w_to_Z, w_pred, w_Bm1. + rewrite (spec_pred op_spec);rewrite (spec_Bm1 op_spec). + unfold w_digits;rewrite Zmod_small. ring. + assert (H:= wB_pos(znz_digits w_op)). omega. + exact (spec_compare op_spec). + exact (spec_div21 op_spec). + Qed. + + Let spec_ww_div21 : forall a1 a2 b, + wwB/2 <= [|b|] -> + [|a1|] < [|b|] -> + let (q,r) := div21 a1 a2 b in + [|a1|] *wwB+ [|a2|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]. + Proof. + refine (spec_ww_div21 w_0 w_0W div32 ww_1 compare sub w_digits w_to_Z + _ _ _ _ _ _ _);wwauto. + Qed. + + Let spec_add2: forall x y, + [|w_add2 x y|] = w_to_Z x + w_to_Z y. + unfold w_add2. + intros xh xl; generalize (spec_add_c op_spec xh xl). + unfold w_add_c; case znz_add_c; unfold interp_carry; simpl ww_to_Z. + intros w0 Hw0; simpl; unfold w_to_Z; rewrite Hw0. + unfold w_0; rewrite spec_0; simpl; auto with zarith. + intros w0; rewrite Zmult_1_l; simpl. + unfold w_to_Z, w_1; rewrite spec_1; auto with zarith. + rewrite Zmult_1_l; auto. + Qed. + + Let spec_low: forall x, + w_to_Z (low x) = [|x|] mod wB. + intros x; case x; simpl low. + unfold ww_to_Z, w_to_Z, w_0; rewrite (spec_0 op_spec); simpl. + rewrite Zmod_small; auto with zarith. + split; auto with zarith. + unfold wB, base; auto with zarith. + intros xh xl; simpl. + rewrite Zplus_comm; rewrite Z_mod_plus; auto with zarith. + rewrite Zmod_small; auto with zarith. + unfold wB, base; auto with zarith. + Qed. + + Let spec_ww_digits: + [|_ww_zdigits|] = Zpos (xO w_digits). + Proof. + unfold w_to_Z, _ww_zdigits. + rewrite spec_add2. + unfold w_to_Z, w_zdigits, w_digits. + rewrite spec_zdigits; auto. + rewrite Zpos_xO; auto with zarith. + Qed. + + + Let spec_ww_head00 : forall x, [|x|] = 0 -> [|head0 x|] = Zpos _ww_digits. + Proof. + refine (spec_ww_head00 w_0 w_0W + w_compare w_head0 w_add2 w_zdigits _ww_zdigits + w_to_Z _ _ _ (refl_equal _ww_digits) _ _ _ _); auto. + exact (spec_compare op_spec). + exact (spec_head00 op_spec). + exact (spec_zdigits op_spec). + Qed. + + Let spec_ww_head0 : forall x, 0 < [|x|] -> + wwB/ 2 <= 2 ^ [|head0 x|] * [|x|] < wwB. + Proof. + refine (spec_ww_head0 w_0 w_0W w_compare w_head0 + w_add2 w_zdigits _ww_zdigits + w_to_Z _ _ _ _ _ _ _);wwauto. + exact (spec_compare op_spec). + exact (spec_zdigits op_spec). + Qed. + + Let spec_ww_tail00 : forall x, [|x|] = 0 -> [|tail0 x|] = Zpos _ww_digits. + Proof. + refine (spec_ww_tail00 w_0 w_0W + w_compare w_tail0 w_add2 w_zdigits _ww_zdigits + w_to_Z _ _ _ (refl_equal _ww_digits) _ _ _ _); wwauto. + exact (spec_compare op_spec). + exact (spec_tail00 op_spec). + exact (spec_zdigits op_spec). + Qed. + + + Let spec_ww_tail0 : forall x, 0 < [|x|] -> + exists y, 0 <= y /\ [|x|] = (2 * y + 1) * 2 ^ [|tail0 x|]. + Proof. + refine (spec_ww_tail0 (w_digits := w_digits) w_0 w_0W w_compare w_tail0 + w_add2 w_zdigits _ww_zdigits w_to_Z _ _ _ _ _ _ _);wwauto. + exact (spec_compare op_spec). + exact (spec_zdigits op_spec). + Qed. + + Lemma spec_ww_add_mul_div : forall x y p, + [|p|] <= Zpos _ww_digits -> + [| add_mul_div p x y |] = + ([|x|] * (2 ^ [|p|]) + + [|y|] / (2 ^ ((Zpos _ww_digits) - [|p|]))) mod wwB. + Proof. + refine (@spec_ww_add_mul_div w w_0 w_WW w_W0 w_0W compare w_add_mul_div + sub w_digits w_zdigits low w_to_Z + _ _ _ _ _ _ _ _ _ _ _);wwauto. + exact (spec_zdigits op_spec). + Qed. + + Let spec_ww_div_gt : forall a b, + [|a|] > [|b|] -> 0 < [|b|] -> + let (q,r) := div_gt a b in + [|a|] = [|q|] * [|b|] + [|r|] /\ 0 <= [|r|] < [|b|]. + Proof. +refine +(@spec_ww_div_gt w w_digits w_0 w_WW w_0W w_compare w_eq0 + w_opp_c w_opp w_opp_carry w_sub_c w_sub w_sub_carry w_div_gt + w_add_mul_div w_head0 w_div21 div32 _ww_zdigits ww_1 add_mul_div w_zdigits w_to_Z + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +). + exact (spec_0 op_spec). + exact (spec_to_Z op_spec). + wwauto. + wwauto. + exact (spec_compare op_spec). + exact (spec_eq0 op_spec). + exact (spec_opp_c op_spec). + exact (spec_opp op_spec). + exact (spec_opp_carry op_spec). + exact (spec_sub_c op_spec). + exact (spec_sub op_spec). + exact (spec_sub_carry op_spec). + exact (spec_div_gt op_spec). + exact (spec_add_mul_div op_spec). + exact (spec_head0 op_spec). + exact (spec_div21 op_spec). + exact spec_w_div32. + exact (spec_zdigits op_spec). + exact spec_ww_digits. + exact spec_ww_1. + exact spec_ww_add_mul_div. + Qed. + + Let spec_ww_div : forall a b, 0 < [|b|] -> + let (q,r) := div a b in + [|a|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]. + Proof. + refine (spec_ww_div w_digits ww_1 compare div_gt w_to_Z _ _ _ _);auto. + Qed. + + Let spec_ww_mod_gt : forall a b, + [|a|] > [|b|] -> 0 < [|b|] -> + [|mod_gt a b|] = [|a|] mod [|b|]. + Proof. + refine (@spec_ww_mod_gt w w_digits w_0 w_WW w_0W w_compare w_eq0 + w_opp_c w_opp w_opp_carry w_sub_c w_sub w_sub_carry w_div_gt w_mod_gt + w_add_mul_div w_head0 w_div21 div32 _ww_zdigits ww_1 add_mul_div + w_zdigits w_to_Z + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _);wwauto. + exact (spec_compare op_spec). + exact (spec_div_gt op_spec). + exact (spec_div21 op_spec). + exact (spec_zdigits op_spec). + exact spec_ww_add_mul_div. + Qed. + + Let spec_ww_mod : forall a b, 0 < [|b|] -> [|mod_ a b|] = [|a|] mod [|b|]. + Proof. + refine (spec_ww_mod w_digits W0 compare mod_gt w_to_Z _ _ _);auto. + Qed. + + Let spec_ww_gcd_gt : forall a b, [|a|] > [|b|] -> + Zis_gcd [|a|] [|b|] [|gcd_gt a b|]. + Proof. + refine (@spec_ww_gcd_gt w w_digits W0 w_to_Z _ + w_0 w_0 w_eq0 w_gcd_gt _ww_digits + _ gcd_gt_fix _ _ _ _ gcd_cont _);auto. + refine (@spec_ww_gcd_gt_aux w w_digits w_0 w_WW w_0W w_compare w_opp_c w_opp + w_opp_carry w_sub_c w_sub w_sub_carry w_gcd_gt w_add_mul_div w_head0 + w_div21 div32 _ww_zdigits ww_1 add_mul_div w_zdigits w_to_Z + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _);wwauto. + exact (spec_compare op_spec). + exact (spec_div21 op_spec). + exact (spec_zdigits op_spec). + exact spec_ww_add_mul_div. + refine (@spec_gcd_cont w w_digits ww_1 w_to_Z _ _ w_0 w_1 w_compare + _ _);auto. + exact (spec_compare op_spec). + Qed. + + Let spec_ww_gcd : forall a b, Zis_gcd [|a|] [|b|] [|gcd a b|]. + Proof. + refine (@spec_ww_gcd w w_digits W0 compare w_to_Z _ _ w_0 w_0 w_eq0 w_gcd_gt + _ww_digits _ gcd_gt_fix _ _ _ _ gcd_cont _);auto. + refine (@spec_ww_gcd_gt_aux w w_digits w_0 w_WW w_0W w_compare w_opp_c w_opp + w_opp_carry w_sub_c w_sub w_sub_carry w_gcd_gt w_add_mul_div w_head0 + w_div21 div32 _ww_zdigits ww_1 add_mul_div w_zdigits w_to_Z + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _);wwauto. + exact (spec_compare op_spec). + exact (spec_div21 op_spec). + exact (spec_zdigits op_spec). + exact spec_ww_add_mul_div. + refine (@spec_gcd_cont w w_digits ww_1 w_to_Z _ _ w_0 w_1 w_compare + _ _);auto. + exact (spec_compare op_spec). + Qed. + + Let spec_ww_is_even : forall x, + match is_even x with + true => [|x|] mod 2 = 0 + | false => [|x|] mod 2 = 1 + end. + Proof. + refine (@spec_ww_is_even w w_is_even w_0 w_1 w_Bm1 w_digits _ _ _ _ _); auto. + exact (spec_is_even op_spec). + Qed. + + Let spec_ww_sqrt2 : forall x y, + wwB/ 4 <= [|x|] -> + let (s,r) := sqrt2 x y in + [[WW x y]] = [|s|] ^ 2 + [+|r|] /\ + [+|r|] <= 2 * [|s|]. + Proof. + intros x y H. + refine (@spec_ww_sqrt2 w w_is_even w_compare w_0 w_1 w_Bm1 + w_0W w_sub w_square_c w_div21 w_add_mul_div w_digits w_zdigits + _ww_zdigits + w_add_c w_sqrt2 w_pred pred_c pred add_c add sub_c add_mul_div + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _); wwauto. + exact (spec_zdigits op_spec). + exact (spec_more_than_1_digit op_spec). + exact (spec_is_even op_spec). + exact (spec_compare op_spec). + exact (spec_div21 op_spec). + exact (spec_ww_add_mul_div). + exact (spec_sqrt2 op_spec). + Qed. + + Let spec_ww_sqrt : forall x, + [|sqrt x|] ^ 2 <= [|x|] < ([|sqrt x|] + 1) ^ 2. + Proof. + refine (@spec_ww_sqrt w w_is_even w_0 w_1 w_Bm1 + w_sub w_add_mul_div w_digits w_zdigits _ww_zdigits + w_sqrt2 pred add_mul_div head0 compare + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _); wwauto. + exact (spec_zdigits op_spec). + exact (spec_more_than_1_digit op_spec). + exact (spec_is_even op_spec). + exact (spec_ww_add_mul_div). + exact (spec_sqrt2 op_spec). + Qed. + + Lemma mk_znz2_spec : znz_spec mk_zn2z_op. + Proof. + apply mk_znz_spec;auto. + exact spec_ww_add_mul_div. + + refine (@spec_ww_pos_mod w w_0 w_digits w_zdigits w_WW + w_pos_mod compare w_0W low sub _ww_zdigits w_to_Z + _ _ _ _ _ _ _ _ _ _ _ _);wwauto. + exact (spec_pos_mod op_spec). + exact (spec_zdigits op_spec). + unfold w_to_Z, w_zdigits. + rewrite (spec_zdigits op_spec). + rewrite <- Zpos_xO; exact spec_ww_digits. + Qed. + + Lemma mk_znz2_karatsuba_spec : znz_spec mk_zn2z_op_karatsuba. + Proof. + apply mk_znz_spec;auto. + exact spec_ww_add_mul_div. + refine (@spec_ww_pos_mod w w_0 w_digits w_zdigits w_WW + w_pos_mod compare w_0W low sub _ww_zdigits w_to_Z + _ _ _ _ _ _ _ _ _ _ _ _);wwauto. + exact (spec_pos_mod op_spec). + exact (spec_zdigits op_spec). + unfold w_to_Z, w_zdigits. + rewrite (spec_zdigits op_spec). + rewrite <- Zpos_xO; exact spec_ww_digits. + Qed. + +End Z_2nZ. + +Section MulAdd. + + Variable w: Type. + Variable op: znz_op w. + Variable sop: znz_spec op. + + Definition mul_add:= w_mul_add (znz_0 op) (znz_succ op) (znz_add_c op) (znz_mul_c op). + + Notation "[| x |]" := (znz_to_Z op x) (at level 0, x at level 99). + + Notation "[|| x ||]" := + (zn2z_to_Z (base (znz_digits op)) (znz_to_Z op) x) (at level 0, x at level 99). + + + Lemma spec_mul_add: forall x y z, + let (zh, zl) := mul_add x y z in + [||WW zh zl||] = [|x|] * [|y|] + [|z|]. + Proof. + intros x y z. + refine (spec_w_mul_add _ _ _ _ _ _ _ _ _ _ _ _ x y z); auto. + exact (spec_0 sop). + exact (spec_to_Z sop). + exact (spec_succ sop). + exact (spec_add_c sop). + exact (spec_mul_c sop). + Qed. + +End MulAdd. + + +(** Modular versions of DoubleCyclic *) + +Module DoubleCyclic (C:CyclicType) <: CyclicType. + Definition w := zn2z C.w. + Definition w_op := mk_zn2z_op C.w_op. + Definition w_spec := mk_znz2_spec C.w_spec. +End DoubleCyclic. + +Module DoubleCyclicKaratsuba (C:CyclicType) <: CyclicType. + Definition w := zn2z C.w. + Definition w_op := mk_zn2z_op_karatsuba C.w_op. + Definition w_spec := mk_znz2_karatsuba_spec C.w_spec. +End DoubleCyclicKaratsuba. diff --git a/theories/Numbers/Cyclic/DoubleCyclic/DoubleDiv.v b/theories/Numbers/Cyclic/DoubleCyclic/DoubleDiv.v new file mode 100644 index 00000000..075aef59 --- /dev/null +++ b/theories/Numbers/Cyclic/DoubleCyclic/DoubleDiv.v @@ -0,0 +1,1540 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: DoubleDiv.v 10964 2008-05-22 11:08:13Z letouzey $ i*) + +Set Implicit Arguments. + +Require Import ZArith. +Require Import BigNumPrelude. +Require Import DoubleType. +Require Import DoubleBase. +Require Import DoubleDivn1. +Require Import DoubleAdd. +Require Import DoubleSub. + +Open Local Scope Z_scope. + +Ltac zarith := auto with zarith. + + +Section POS_MOD. + + Variable w:Type. + Variable w_0 : w. + Variable w_digits : positive. + Variable w_zdigits : w. + Variable w_WW : w -> w -> zn2z w. + Variable w_pos_mod : w -> w -> w. + Variable w_compare : w -> w -> comparison. + Variable ww_compare : zn2z w -> zn2z w -> comparison. + Variable w_0W : w -> zn2z w. + Variable low: zn2z w -> w. + Variable ww_sub: zn2z w -> zn2z w -> zn2z w. + Variable ww_zdigits : zn2z w. + + + Definition ww_pos_mod p x := + let zdigits := w_0W w_zdigits in + match x with + | W0 => W0 + | WW xh xl => + match ww_compare p zdigits with + | Eq => w_WW w_0 xl + | Lt => w_WW w_0 (w_pos_mod (low p) xl) + | Gt => + match ww_compare p ww_zdigits with + | Lt => + let n := low (ww_sub p zdigits) in + w_WW (w_pos_mod n xh) xl + | _ => x + end + end + end. + + + Variable w_to_Z : w -> Z. + + Notation wB := (base w_digits). + Notation wwB := (base (ww_digits w_digits)). + Notation "[| x |]" := (w_to_Z x) (at level 0, x at level 99). + + Notation "[[ x ]]" := (ww_to_Z w_digits w_to_Z x)(at level 0, x at level 99). + + + Variable spec_w_0 : [|w_0|] = 0. + + Variable spec_to_Z : forall x, 0 <= [|x|] < wB. + + Variable spec_to_w_Z : forall x, 0 <= [[x]] < wwB. + + Variable spec_w_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|]. + + Variable spec_pos_mod : forall w p, + [|w_pos_mod p w|] = [|w|] mod (2 ^ [|p|]). + + Variable spec_w_0W : forall l, [[w_0W l]] = [|l|]. + Variable spec_ww_compare : forall x y, + match ww_compare x y with + | Eq => [[x]] = [[y]] + | Lt => [[x]] < [[y]] + | Gt => [[x]] > [[y]] + end. + Variable spec_ww_sub: forall x y, + [[ww_sub x y]] = ([[x]] - [[y]]) mod wwB. + + Variable spec_zdigits : [| w_zdigits |] = Zpos w_digits. + Variable spec_low: forall x, [| low x|] = [[x]] mod wB. + Variable spec_ww_zdigits : [[ww_zdigits]] = 2 * [|w_zdigits|]. + Variable spec_ww_digits : ww_digits w_digits = xO w_digits. + + + Hint Rewrite spec_w_0 spec_w_WW : w_rewrite. + + Lemma spec_ww_pos_mod : forall w p, + [[ww_pos_mod p w]] = [[w]] mod (2 ^ [[p]]). + assert (HHHHH:= lt_0_wB w_digits). + assert (F0: forall x y, x - y + y = x); auto with zarith. + intros w1 p; case (spec_to_w_Z p); intros HH1 HH2. + unfold ww_pos_mod; case w1. + simpl; rewrite Zmod_small; split; auto with zarith. + intros xh xl; generalize (spec_ww_compare p (w_0W w_zdigits)); + case ww_compare; + rewrite spec_w_0W; rewrite spec_zdigits; fold wB; + intros H1. + rewrite H1; simpl ww_to_Z. + autorewrite with w_rewrite rm10. + rewrite Zplus_mod; auto with zarith. + rewrite Z_mod_mult; auto with zarith. + autorewrite with rm10. + rewrite Zmod_mod; auto with zarith. + rewrite Zmod_small; auto with zarith. + autorewrite with w_rewrite rm10. + simpl ww_to_Z. + rewrite spec_pos_mod. + assert (HH0: [|low p|] = [[p]]). + rewrite spec_low. + apply Zmod_small; auto with zarith. + case (spec_to_w_Z p); intros HHH1 HHH2; split; auto with zarith. + apply Zlt_le_trans with (1 := H1). + unfold base; apply Zpower2_le_lin; auto with zarith. + rewrite HH0. + rewrite Zplus_mod; auto with zarith. + unfold base. + rewrite <- (F0 (Zpos w_digits) [[p]]). + rewrite Zpower_exp; auto with zarith. + rewrite Zmult_assoc. + rewrite Z_mod_mult; auto with zarith. + autorewrite with w_rewrite rm10. + rewrite Zmod_mod; auto with zarith. +generalize (spec_ww_compare p ww_zdigits); + case ww_compare; rewrite spec_ww_zdigits; + rewrite spec_zdigits; intros H2. + replace (2^[[p]]) with wwB. + rewrite Zmod_small; auto with zarith. + unfold base; rewrite H2. + rewrite spec_ww_digits; auto. + assert (HH0: [|low (ww_sub p (w_0W w_zdigits))|] = + [[p]] - Zpos w_digits). + rewrite spec_low. + rewrite spec_ww_sub. + rewrite spec_w_0W; rewrite spec_zdigits. + rewrite <- Zmod_div_mod; auto with zarith. + rewrite Zmod_small; auto with zarith. + split; auto with zarith. + apply Zlt_le_trans with (Zpos w_digits); auto with zarith. + unfold base; apply Zpower2_le_lin; auto with zarith. + exists wB; unfold base; rewrite <- Zpower_exp; auto with zarith. + rewrite spec_ww_digits; + apply f_equal with (f := Zpower 2); rewrite Zpos_xO; auto with zarith. + simpl ww_to_Z; autorewrite with w_rewrite. + rewrite spec_pos_mod; rewrite HH0. + pattern [|xh|] at 2; + rewrite Z_div_mod_eq with (b := 2 ^ ([[p]] - Zpos w_digits)); + auto with zarith. + rewrite (fun x => (Zmult_comm (2 ^ x))); rewrite Zmult_plus_distr_l. + unfold base; rewrite <- Zmult_assoc; rewrite <- Zpower_exp; + auto with zarith. + rewrite F0; auto with zarith. + rewrite <- Zplus_assoc; rewrite Zplus_mod; auto with zarith. + rewrite Z_mod_mult; auto with zarith. + autorewrite with rm10. + rewrite Zmod_mod; auto with zarith. + apply sym_equal; apply Zmod_small; auto with zarith. + case (spec_to_Z xh); intros U1 U2. + case (spec_to_Z xl); intros U3 U4. + split; auto with zarith. + apply Zplus_le_0_compat; auto with zarith. + apply Zmult_le_0_compat; auto with zarith. + match goal with |- 0 <= ?X mod ?Y => + case (Z_mod_lt X Y); auto with zarith + end. + match goal with |- ?X mod ?Y * ?U + ?Z < ?T => + apply Zle_lt_trans with ((Y - 1) * U + Z ); + [case (Z_mod_lt X Y); auto with zarith | idtac] + end. + match goal with |- ?X * ?U + ?Y < ?Z => + apply Zle_lt_trans with (X * U + (U - 1)) + end. + apply Zplus_le_compat_l; auto with zarith. + case (spec_to_Z xl); unfold base; auto with zarith. + rewrite Zmult_minus_distr_r; rewrite <- Zpower_exp; auto with zarith. + rewrite F0; auto with zarith. + rewrite Zmod_small; auto with zarith. + case (spec_to_w_Z (WW xh xl)); intros U1 U2. + split; auto with zarith. + apply Zlt_le_trans with (1:= U2). + unfold base; rewrite spec_ww_digits. + apply Zpower_le_monotone; auto with zarith. + split; auto with zarith. + rewrite Zpos_xO; auto with zarith. + Qed. + +End POS_MOD. + +Section DoubleDiv32. + + Variable w : Type. + Variable w_0 : w. + Variable w_Bm1 : w. + Variable w_Bm2 : w. + Variable w_WW : w -> w -> zn2z w. + Variable w_compare : w -> w -> comparison. + Variable w_add_c : w -> w -> carry w. + Variable w_add_carry_c : w -> w -> carry w. + Variable w_add : w -> w -> w. + Variable w_add_carry : w -> w -> w. + Variable w_pred : w -> w. + Variable w_sub : w -> w -> w. + Variable w_mul_c : w -> w -> zn2z w. + Variable w_div21 : w -> w -> w -> w*w. + Variable ww_sub_c : zn2z w -> zn2z w -> carry (zn2z w). + + Definition w_div32 a1 a2 a3 b1 b2 := + Eval lazy beta iota delta [ww_add_c_cont ww_add] in + match w_compare a1 b1 with + | Lt => + let (q,r) := w_div21 a1 a2 b1 in + match ww_sub_c (w_WW r a3) (w_mul_c q b2) with + | C0 r1 => (q,r1) + | C1 r1 => + let q := w_pred q in + ww_add_c_cont w_WW w_add_c w_add_carry_c + (fun r2=>(w_pred q, ww_add w_add_c w_add w_add_carry r2 (WW b1 b2))) + (fun r2 => (q,r2)) + r1 (WW b1 b2) + end + | Eq => + ww_add_c_cont w_WW w_add_c w_add_carry_c + (fun r => (w_Bm2, ww_add w_add_c w_add w_add_carry r (WW b1 b2))) + (fun r => (w_Bm1,r)) + (WW (w_sub a2 b2) a3) (WW b1 b2) + | Gt => (w_0, W0) (* cas absurde *) + end. + + (* Proof *) + + Variable w_digits : positive. + Variable w_to_Z : w -> Z. + + Notation wB := (base w_digits). + Notation wwB := (base (ww_digits w_digits)). + Notation "[| x |]" := (w_to_Z x) (at level 0, x at level 99). + Notation "[+| c |]" := + (interp_carry 1 wB w_to_Z c) (at level 0, x at level 99). + Notation "[-| c |]" := + (interp_carry (-1) wB w_to_Z c) (at level 0, x at level 99). + + Notation "[[ x ]]" := (ww_to_Z w_digits w_to_Z x)(at level 0, x at level 99). + Notation "[-[ c ]]" := + (interp_carry (-1) wwB (ww_to_Z w_digits w_to_Z) c) + (at level 0, x at level 99). + + + Variable spec_w_0 : [|w_0|] = 0. + Variable spec_w_Bm1 : [|w_Bm1|] = wB - 1. + Variable spec_w_Bm2 : [|w_Bm2|] = wB - 2. + + Variable spec_to_Z : forall x, 0 <= [|x|] < wB. + + Variable spec_w_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|]. + Variable spec_compare : + forall x y, + match w_compare x y with + | Eq => [|x|] = [|y|] + | Lt => [|x|] < [|y|] + | Gt => [|x|] > [|y|] + end. + Variable spec_w_add_c : forall x y, [+|w_add_c x y|] = [|x|] + [|y|]. + Variable spec_w_add_carry_c : + forall x y, [+|w_add_carry_c x y|] = [|x|] + [|y|] + 1. + + Variable spec_w_add : forall x y, [|w_add x y|] = ([|x|] + [|y|]) mod wB. + Variable spec_w_add_carry : + forall x y, [|w_add_carry x y|] = ([|x|] + [|y|] + 1) mod wB. + + Variable spec_pred : forall x, [|w_pred x|] = ([|x|] - 1) mod wB. + Variable spec_sub : forall x y, [|w_sub x y|] = ([|x|] - [|y|]) mod wB. + + Variable spec_mul_c : forall x y, [[ w_mul_c x y ]] = [|x|] * [|y|]. + Variable spec_div21 : forall a1 a2 b, + wB/2 <= [|b|] -> + [|a1|] < [|b|] -> + let (q,r) := w_div21 a1 a2 b in + [|a1|] *wB+ [|a2|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]. + + Variable spec_ww_sub_c : forall x y, [-[ww_sub_c x y]] = [[x]] - [[y]]. + + Ltac Spec_w_to_Z x := + let H:= fresh "HH" in + assert (H:= spec_to_Z x). + Ltac Spec_ww_to_Z x := + let H:= fresh "HH" in + assert (H:= spec_ww_to_Z w_digits w_to_Z spec_to_Z x). + + Theorem wB_div2: forall x, wB/2 <= x -> wB <= 2 * x. + intros x H; rewrite <- wB_div_2; apply Zmult_le_compat_l; auto with zarith. + Qed. + + Lemma Zmult_lt_0_reg_r_2 : forall n m : Z, 0 <= n -> 0 < m * n -> 0 < m. + Proof. + intros n m H1 H2;apply Zmult_lt_0_reg_r with n;trivial. + destruct (Zle_lt_or_eq _ _ H1);trivial. + subst;rewrite Zmult_0_r in H2;discriminate H2. + Qed. + + Theorem spec_w_div32 : forall a1 a2 a3 b1 b2, + wB/2 <= [|b1|] -> + [[WW a1 a2]] < [[WW b1 b2]] -> + let (q,r) := w_div32 a1 a2 a3 b1 b2 in + [|a1|] * wwB + [|a2|] * wB + [|a3|] = + [|q|] * ([|b1|] * wB + [|b2|]) + [[r]] /\ + 0 <= [[r]] < [|b1|] * wB + [|b2|]. + Proof. + intros a1 a2 a3 b1 b2 Hle Hlt. + assert (U:= lt_0_wB w_digits); assert (U1:= lt_0_wwB w_digits). + Spec_w_to_Z a1;Spec_w_to_Z a2;Spec_w_to_Z a3;Spec_w_to_Z b1;Spec_w_to_Z b2. + rewrite wwB_wBwB; rewrite Zpower_2; rewrite Zmult_assoc;rewrite <- Zmult_plus_distr_l. + change (w_div32 a1 a2 a3 b1 b2) with + match w_compare a1 b1 with + | Lt => + let (q,r) := w_div21 a1 a2 b1 in + match ww_sub_c (w_WW r a3) (w_mul_c q b2) with + | C0 r1 => (q,r1) + | C1 r1 => + let q := w_pred q in + ww_add_c_cont w_WW w_add_c w_add_carry_c + (fun r2=>(w_pred q, ww_add w_add_c w_add w_add_carry r2 (WW b1 b2))) + (fun r2 => (q,r2)) + r1 (WW b1 b2) + end + | Eq => + ww_add_c_cont w_WW w_add_c w_add_carry_c + (fun r => (w_Bm2, ww_add w_add_c w_add w_add_carry r (WW b1 b2))) + (fun r => (w_Bm1,r)) + (WW (w_sub a2 b2) a3) (WW b1 b2) + | Gt => (w_0, W0) (* cas absurde *) + end. + assert (Hcmp:=spec_compare a1 b1);destruct (w_compare a1 b1). + simpl in Hlt. + rewrite Hcmp in Hlt;assert ([|a2|] < [|b2|]). omega. + assert ([[WW (w_sub a2 b2) a3]] = ([|a2|]-[|b2|])*wB + [|a3|] + wwB). + simpl;rewrite spec_sub. + assert ([|a2|] - [|b2|] = wB*(-1) + ([|a2|] - [|b2|] + wB)). ring. + assert (0 <= [|a2|] - [|b2|] + wB < wB). omega. + rewrite <-(Zmod_unique ([|a2|]-[|b2|]) wB (-1) ([|a2|]-[|b2|]+wB) H1 H0). + rewrite wwB_wBwB;ring. + assert (U2 := wB_pos w_digits). + eapply spec_ww_add_c_cont with (P := + fun (x y:zn2z w) (res:w*zn2z w) => + let (q, r) := res in + ([|a1|] * wB + [|a2|]) * wB + [|a3|] = + [|q|] * ([|b1|] * wB + [|b2|]) + [[r]] /\ + 0 <= [[r]] < [|b1|] * wB + [|b2|]);eauto. + rewrite H0;intros r. + repeat + (rewrite spec_ww_add;eauto || rewrite spec_w_Bm1 || rewrite spec_w_Bm2); + simpl ww_to_Z;try rewrite Zmult_1_l;intros H1. + assert (0<= ([[r]] + ([|b1|] * wB + [|b2|])) - wwB < [|b1|] * wB + [|b2|]). + Spec_ww_to_Z r;split;zarith. + rewrite H1. + assert (H12:= wB_div2 Hle). assert (wwB <= 2 * [|b1|] * wB). + rewrite wwB_wBwB; rewrite Zpower_2; zarith. + assert (-wwB < ([|a2|] - [|b2|]) * wB + [|a3|] < 0). + split. apply Zlt_le_trans with (([|a2|] - [|b2|]) * wB);zarith. + rewrite wwB_wBwB;replace (-(wB^2)) with (-wB*wB);[zarith | ring]. + apply Zmult_lt_compat_r;zarith. + apply Zle_lt_trans with (([|a2|] - [|b2|]) * wB + (wB -1));zarith. + replace ( ([|a2|] - [|b2|]) * wB + (wB - 1)) with + (([|a2|] - [|b2|] + 1) * wB + - 1);[zarith | ring]. + assert (([|a2|] - [|b2|] + 1) * wB <= 0);zarith. + replace 0 with (0*wB);zarith. + replace (([|a2|] - [|b2|]) * wB + [|a3|] + wwB + ([|b1|] * wB + [|b2|]) + + ([|b1|] * wB + [|b2|]) - wwB) with + (([|a2|] - [|b2|]) * wB + [|a3|] + 2*[|b1|] * wB + 2*[|b2|]); + [zarith | ring]. + rewrite <- (Zmod_unique ([[r]] + ([|b1|] * wB + [|b2|])) wwB + 1 ([[r]] + ([|b1|] * wB + [|b2|]) - wwB));zarith;try (ring;fail). + split. rewrite H1;rewrite Hcmp;ring. trivial. + Spec_ww_to_Z (WW b1 b2). simpl in HH4;zarith. + rewrite H0;intros r;repeat + (rewrite spec_w_Bm1 || rewrite spec_w_Bm2); + simpl ww_to_Z;try rewrite Zmult_1_l;intros H1. + assert ([[r]]=([|a2|]-[|b2|])*wB+[|a3|]+([|b1|]*wB+[|b2|])). zarith. + split. rewrite H2;rewrite Hcmp;ring. + split. Spec_ww_to_Z r;zarith. + rewrite H2. + assert (([|a2|] - [|b2|]) * wB + [|a3|] < 0);zarith. + apply Zle_lt_trans with (([|a2|] - [|b2|]) * wB + (wB -1));zarith. + replace ( ([|a2|] - [|b2|]) * wB + (wB - 1)) with + (([|a2|] - [|b2|] + 1) * wB + - 1);[zarith|ring]. + assert (([|a2|] - [|b2|] + 1) * wB <= 0);zarith. + replace 0 with (0*wB);zarith. + (* Cas Lt *) + assert (Hdiv21 := spec_div21 a2 Hle Hcmp); + destruct (w_div21 a1 a2 b1) as (q, r);destruct Hdiv21. + rewrite H. + assert (Hq := spec_to_Z q). + generalize + (spec_ww_sub_c (w_WW r a3) (w_mul_c q b2)); + destruct (ww_sub_c (w_WW r a3) (w_mul_c q b2)) + as [r1|r1];repeat (rewrite spec_w_WW || rewrite spec_mul_c); + unfold interp_carry;intros H1. + rewrite H1. + split. ring. split. + rewrite <- H1;destruct (spec_ww_to_Z w_digits w_to_Z spec_to_Z r1);trivial. + apply Zle_lt_trans with ([|r|] * wB + [|a3|]). + assert ( 0 <= [|q|] * [|b2|]);zarith. + apply beta_lex_inv;zarith. + assert ([[r1]] = [|r|] * wB + [|a3|] - [|q|] * [|b2|] + wwB). + rewrite <- H1;ring. + Spec_ww_to_Z r1; assert (0 <= [|r|]*wB). zarith. + assert (0 < [|q|] * [|b2|]). zarith. + assert (0 < [|q|]). + apply Zmult_lt_0_reg_r_2 with [|b2|];zarith. + eapply spec_ww_add_c_cont with (P := + fun (x y:zn2z w) (res:w*zn2z w) => + let (q0, r0) := res in + ([|q|] * [|b1|] + [|r|]) * wB + [|a3|] = + [|q0|] * ([|b1|] * wB + [|b2|]) + [[r0]] /\ + 0 <= [[r0]] < [|b1|] * wB + [|b2|]);eauto. + intros r2;repeat (rewrite spec_pred || rewrite spec_ww_add;eauto); + simpl ww_to_Z;intros H7. + assert (0 < [|q|] - 1). + assert (1 <= [|q|]). zarith. + destruct (Zle_lt_or_eq _ _ H6);zarith. + rewrite <- H8 in H2;rewrite H2 in H7. + assert (0 < [|b1|]*wB). apply Zmult_lt_0_compat;zarith. + Spec_ww_to_Z r2. zarith. + rewrite (Zmod_small ([|q|] -1));zarith. + rewrite (Zmod_small ([|q|] -1 -1));zarith. + assert ([[r2]] + ([|b1|] * wB + [|b2|]) = + wwB * 1 + + ([|r|] * wB + [|a3|] - [|q|] * [|b2|] + 2 * ([|b1|] * wB + [|b2|]))). + rewrite H7;rewrite H2;ring. + assert + ([|r|]*wB + [|a3|] - [|q|]*[|b2|] + 2 * ([|b1|]*wB + [|b2|]) + < [|b1|]*wB + [|b2|]). + Spec_ww_to_Z r2;omega. + Spec_ww_to_Z (WW b1 b2). simpl in HH5. + assert + (0 <= [|r|]*wB + [|a3|] - [|q|]*[|b2|] + 2 * ([|b1|]*wB + [|b2|]) + < wwB). split;try omega. + replace (2*([|b1|]*wB+[|b2|])) with ((2*[|b1|])*wB+2*[|b2|]). 2:ring. + assert (H12:= wB_div2 Hle). assert (wwB <= 2 * [|b1|] * wB). + rewrite wwB_wBwB; rewrite Zpower_2; zarith. omega. + rewrite <- (Zmod_unique + ([[r2]] + ([|b1|] * wB + [|b2|])) + wwB + 1 + ([|r|] * wB + [|a3|] - [|q|] * [|b2|] + 2*([|b1|] * wB + [|b2|])) + H10 H8). + split. ring. zarith. + intros r2;repeat (rewrite spec_pred);simpl ww_to_Z;intros H7. + rewrite (Zmod_small ([|q|] -1));zarith. + split. + replace [[r2]] with ([[r1]] + ([|b1|] * wB + [|b2|]) -wwB). + rewrite H2; ring. rewrite <- H7; ring. + Spec_ww_to_Z r2;Spec_ww_to_Z r1. omega. + simpl in Hlt. + assert ([|a1|] * wB + [|a2|] <= [|b1|] * wB + [|b2|]). zarith. + assert (H1 := beta_lex _ _ _ _ _ H HH0 HH3). rewrite spec_w_0;simpl;zarith. + Qed. + + +End DoubleDiv32. + +Section DoubleDiv21. + Variable w : Type. + Variable w_0 : w. + + Variable w_0W : w -> zn2z w. + Variable w_div32 : w -> w -> w -> w -> w -> w * zn2z w. + + Variable ww_1 : zn2z w. + Variable ww_compare : zn2z w -> zn2z w -> comparison. + Variable ww_sub : zn2z w -> zn2z w -> zn2z w. + + + Definition ww_div21 a1 a2 b := + match a1 with + | W0 => + match ww_compare a2 b with + | Gt => (ww_1, ww_sub a2 b) + | Eq => (ww_1, W0) + | Lt => (W0, a2) + end + | WW a1h a1l => + match a2 with + | W0 => + match b with + | W0 => (W0,W0) (* cas absurde *) + | WW b1 b2 => + let (q1, r) := w_div32 a1h a1l w_0 b1 b2 in + match r with + | W0 => (WW q1 w_0, W0) + | WW r1 r2 => + let (q2, s) := w_div32 r1 r2 w_0 b1 b2 in + (WW q1 q2, s) + end + end + | WW a2h a2l => + match b with + | W0 => (W0,W0) (* cas absurde *) + | WW b1 b2 => + let (q1, r) := w_div32 a1h a1l a2h b1 b2 in + match r with + | W0 => (WW q1 w_0, w_0W a2l) + | WW r1 r2 => + let (q2, s) := w_div32 r1 r2 a2l b1 b2 in + (WW q1 q2, s) + end + end + end + end. + + (* Proof *) + + Variable w_digits : positive. + Variable w_to_Z : w -> Z. + Notation wB := (base w_digits). + Notation wwB := (base (ww_digits w_digits)). + Notation "[| x |]" := (w_to_Z x) (at level 0, x at level 99). + Notation "[[ x ]]" := (ww_to_Z w_digits w_to_Z x)(at level 0, x at level 99). + Notation "[-[ c ]]" := + (interp_carry (-1) wwB (ww_to_Z w_digits w_to_Z) c) + (at level 0, x at level 99). + + Variable spec_w_0 : [|w_0|] = 0. + Variable spec_to_Z : forall x, 0 <= [|x|] < wB. + Variable spec_w_0W : forall l, [[w_0W l]] = [|l|]. + Variable spec_w_div32 : forall a1 a2 a3 b1 b2, + wB/2 <= [|b1|] -> + [[WW a1 a2]] < [[WW b1 b2]] -> + let (q,r) := w_div32 a1 a2 a3 b1 b2 in + [|a1|] * wwB + [|a2|] * wB + [|a3|] = + [|q|] * ([|b1|] * wB + [|b2|]) + [[r]] /\ + 0 <= [[r]] < [|b1|] * wB + [|b2|]. + Variable spec_ww_1 : [[ww_1]] = 1. + Variable spec_ww_compare : forall x y, + match ww_compare x y with + | Eq => [[x]] = [[y]] + | Lt => [[x]] < [[y]] + | Gt => [[x]] > [[y]] + end. + Variable spec_ww_sub : forall x y, [[ww_sub x y]] = ([[x]] - [[y]]) mod wwB. + + Theorem wwB_div: wwB = 2 * (wwB / 2). + Proof. + rewrite wwB_div_2; rewrite Zmult_assoc; rewrite wB_div_2; auto. + rewrite <- Zpower_2; apply wwB_wBwB. + Qed. + + Ltac Spec_w_to_Z x := + let H:= fresh "HH" in + assert (H:= spec_to_Z x). + Ltac Spec_ww_to_Z x := + let H:= fresh "HH" in + assert (H:= spec_ww_to_Z w_digits w_to_Z spec_to_Z x). + + Theorem spec_ww_div21 : forall a1 a2 b, + wwB/2 <= [[b]] -> + [[a1]] < [[b]] -> + let (q,r) := ww_div21 a1 a2 b in + [[a1]] *wwB+[[a2]] = [[q]] * [[b]] + [[r]] /\ 0 <= [[r]] < [[b]]. + Proof. + assert (U:= lt_0_wB w_digits). + assert (U1:= lt_0_wwB w_digits). + intros a1 a2 b H Hlt; unfold ww_div21. + Spec_ww_to_Z b; assert (Eq: 0 < [[b]]). Spec_ww_to_Z a1;omega. + generalize Hlt H ;clear Hlt H;case a1. + intros H1 H2;simpl in H1;Spec_ww_to_Z a2; + match goal with |-context [ww_compare ?Y ?Z] => + generalize (spec_ww_compare Y Z); case (ww_compare Y Z) + end; simpl;try rewrite spec_ww_1;autorewrite with rm10; intros;zarith. + rewrite spec_ww_sub;simpl. rewrite Zmod_small;zarith. + split. ring. + assert (wwB <= 2*[[b]]);zarith. + rewrite wwB_div;zarith. + intros a1h a1l. Spec_w_to_Z a1h;Spec_w_to_Z a1l. Spec_ww_to_Z a2. + destruct a2 as [ |a3 a4]; + (destruct b as [ |b1 b2];[unfold Zle in Eq;discriminate Eq|idtac]); + try (Spec_w_to_Z a3; Spec_w_to_Z a4); Spec_w_to_Z b1; Spec_w_to_Z b2; + intros Hlt H; match goal with |-context [w_div32 ?X ?Y ?Z ?T ?U] => + generalize (@spec_w_div32 X Y Z T U); case (w_div32 X Y Z T U); + intros q1 r H0 + end; (assert (Eq1: wB / 2 <= [|b1|]);[ + apply (@beta_lex (wB / 2) 0 [|b1|] [|b2|] wB); auto with zarith; + autorewrite with rm10;repeat rewrite (Zmult_comm wB); + rewrite <- wwB_div_2; trivial + | generalize (H0 Eq1 Hlt);clear H0;destruct r as [ |r1 r2];simpl; + try rewrite spec_w_0; try rewrite spec_w_0W;repeat rewrite Zplus_0_r; + intros (H1,H2) ]). + split;[rewrite wwB_wBwB; rewrite Zpower_2 | trivial]. + rewrite Zmult_assoc;rewrite Zmult_plus_distr_l;rewrite <- Zmult_assoc; + rewrite <- Zpower_2; rewrite <- wwB_wBwB;rewrite H1;ring. + destruct H2 as (H2,H3);match goal with |-context [w_div32 ?X ?Y ?Z ?T ?U] => + generalize (@spec_w_div32 X Y Z T U); case (w_div32 X Y Z T U); + intros q r H0;generalize (H0 Eq1 H3);clear H0;intros (H4,H5) end. + split;[rewrite wwB_wBwB | trivial]. + rewrite Zpower_2. + rewrite Zmult_assoc;rewrite Zmult_plus_distr_l;rewrite <- Zmult_assoc; + rewrite <- Zpower_2. + rewrite <- wwB_wBwB;rewrite H1. + rewrite spec_w_0 in H4;rewrite Zplus_0_r in H4. + repeat rewrite Zmult_plus_distr_l. rewrite <- (Zmult_assoc [|r1|]). + rewrite <- Zpower_2; rewrite <- wwB_wBwB;rewrite H4;simpl;ring. + split;[rewrite wwB_wBwB | split;zarith]. + replace (([|a1h|] * wB + [|a1l|]) * wB^2 + ([|a3|] * wB + [|a4|])) + with (([|a1h|] * wwB + [|a1l|] * wB + [|a3|])*wB+ [|a4|]). + rewrite H1;ring. rewrite wwB_wBwB;ring. + change [|a4|] with (0*wB+[|a4|]);apply beta_lex_inv;zarith. + assert (1 <= wB/2);zarith. + assert (H_:= wB_pos w_digits);apply Zdiv_le_lower_bound;zarith. + destruct H2 as (H2,H3);match goal with |-context [w_div32 ?X ?Y ?Z ?T ?U] => + generalize (@spec_w_div32 X Y Z T U); case (w_div32 X Y Z T U); + intros q r H0;generalize (H0 Eq1 H3);clear H0;intros (H4,H5) end. + split;trivial. + replace (([|a1h|] * wB + [|a1l|]) * wwB + ([|a3|] * wB + [|a4|])) with + (([|a1h|] * wwB + [|a1l|] * wB + [|a3|])*wB + [|a4|]); + [rewrite H1 | rewrite wwB_wBwB;ring]. + replace (([|q1|]*([|b1|]*wB+[|b2|])+([|r1|]*wB+[|r2|]))*wB+[|a4|]) with + (([|q1|]*([|b1|]*wB+[|b2|]))*wB+([|r1|]*wwB+[|r2|]*wB+[|a4|])); + [rewrite H4;simpl|rewrite wwB_wBwB];ring. + Qed. + +End DoubleDiv21. + +Section DoubleDivGt. + Variable w : Type. + Variable w_digits : positive. + Variable w_0 : w. + + Variable w_WW : w -> w -> zn2z w. + Variable w_0W : w -> zn2z w. + Variable w_compare : w -> w -> comparison. + Variable w_eq0 : w -> bool. + Variable w_opp_c : w -> carry w. + Variable w_opp w_opp_carry : w -> w. + Variable w_sub_c : w -> w -> carry w. + Variable w_sub w_sub_carry : w -> w -> w. + + Variable w_div_gt : w -> w -> w*w. + Variable w_mod_gt : w -> w -> w. + Variable w_gcd_gt : w -> w -> w. + Variable w_add_mul_div : w -> w -> w -> w. + Variable w_head0 : w -> w. + Variable w_div21 : w -> w -> w -> w * w. + Variable w_div32 : w -> w -> w -> w -> w -> w * zn2z w. + + + Variable _ww_zdigits : zn2z w. + Variable ww_1 : zn2z w. + Variable ww_add_mul_div : zn2z w -> zn2z w -> zn2z w -> zn2z w. + + Variable w_zdigits : w. + + Definition ww_div_gt_aux ah al bh bl := + Eval lazy beta iota delta [ww_sub ww_opp] in + let p := w_head0 bh in + match w_compare p w_0 with + | Gt => + let b1 := w_add_mul_div p bh bl in + let b2 := w_add_mul_div p bl w_0 in + let a1 := w_add_mul_div p w_0 ah in + let a2 := w_add_mul_div p ah al in + let a3 := w_add_mul_div p al w_0 in + let (q,r) := w_div32 a1 a2 a3 b1 b2 in + (WW w_0 q, ww_add_mul_div + (ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c + w_opp w_sub w_sub_carry _ww_zdigits (w_0W p)) W0 r) + | _ => (ww_1, ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c + w_opp w_sub w_sub_carry (WW ah al) (WW bh bl)) + end. + + Definition ww_div_gt a b := + Eval lazy beta iota delta [ww_div_gt_aux double_divn1 + double_divn1_p double_divn1_p_aux double_divn1_0 double_divn1_0_aux + double_split double_0 double_WW] in + match a, b with + | W0, _ => (W0,W0) + | _, W0 => (W0,W0) + | WW ah al, WW bh bl => + if w_eq0 ah then + let (q,r) := w_div_gt al bl in + (WW w_0 q, w_0W r) + else + match w_compare w_0 bh with + | Eq => + let(q,r):= + double_divn1 w_zdigits w_0 w_WW w_head0 w_add_mul_div w_div21 + w_compare w_sub 1 a bl in + (q, w_0W r) + | Lt => ww_div_gt_aux ah al bh bl + | Gt => (W0,W0) (* cas absurde *) + end + end. + + Definition ww_mod_gt_aux ah al bh bl := + Eval lazy beta iota delta [ww_sub ww_opp] in + let p := w_head0 bh in + match w_compare p w_0 with + | Gt => + let b1 := w_add_mul_div p bh bl in + let b2 := w_add_mul_div p bl w_0 in + let a1 := w_add_mul_div p w_0 ah in + let a2 := w_add_mul_div p ah al in + let a3 := w_add_mul_div p al w_0 in + let (q,r) := w_div32 a1 a2 a3 b1 b2 in + ww_add_mul_div (ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c + w_opp w_sub w_sub_carry _ww_zdigits (w_0W p)) W0 r + | _ => + ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c + w_opp w_sub w_sub_carry (WW ah al) (WW bh bl) + end. + + Definition ww_mod_gt a b := + Eval lazy beta iota delta [ww_mod_gt_aux double_modn1 + double_modn1_p double_modn1_p_aux double_modn1_0 double_modn1_0_aux + double_split double_0 double_WW snd] in + match a, b with + | W0, _ => W0 + | _, W0 => W0 + | WW ah al, WW bh bl => + if w_eq0 ah then w_0W (w_mod_gt al bl) + else + match w_compare w_0 bh with + | Eq => + w_0W (double_modn1 w_zdigits w_0 w_head0 w_add_mul_div w_div21 + w_compare w_sub 1 a bl) + | Lt => ww_mod_gt_aux ah al bh bl + | Gt => W0 (* cas absurde *) + end + end. + + Definition ww_gcd_gt_body (cont: w->w->w->w->zn2z w) (ah al bh bl: w) := + Eval lazy beta iota delta [ww_mod_gt_aux double_modn1 + double_modn1_p double_modn1_p_aux double_modn1_0 double_modn1_0_aux + double_split double_0 double_WW snd] in + match w_compare w_0 bh with + | Eq => + match w_compare w_0 bl with + | Eq => WW ah al (* normalement n'arrive pas si forme normale *) + | Lt => + let m := double_modn1 w_zdigits w_0 w_head0 w_add_mul_div w_div21 + w_compare w_sub 1 (WW ah al) bl in + WW w_0 (w_gcd_gt bl m) + | Gt => W0 (* absurde *) + end + | Lt => + let m := ww_mod_gt_aux ah al bh bl in + match m with + | W0 => WW bh bl + | WW mh ml => + match w_compare w_0 mh with + | Eq => + match w_compare w_0 ml with + | Eq => WW bh bl + | _ => + let r := double_modn1 w_zdigits w_0 w_head0 w_add_mul_div w_div21 + w_compare w_sub 1 (WW bh bl) ml in + WW w_0 (w_gcd_gt ml r) + end + | Lt => + let r := ww_mod_gt_aux bh bl mh ml in + match r with + | W0 => m + | WW rh rl => cont mh ml rh rl + end + | Gt => W0 (* absurde *) + end + end + | Gt => W0 (* absurde *) + end. + + Fixpoint ww_gcd_gt_aux + (p:positive) (cont: w -> w -> w -> w -> zn2z w) (ah al bh bl : w) + {struct p} : zn2z w := + ww_gcd_gt_body + (fun mh ml rh rl => match p with + | xH => cont mh ml rh rl + | xO p => ww_gcd_gt_aux p (ww_gcd_gt_aux p cont) mh ml rh rl + | xI p => ww_gcd_gt_aux p (ww_gcd_gt_aux p cont) mh ml rh rl + end) ah al bh bl. + + + (* Proof *) + + Variable w_to_Z : w -> Z. + Notation wB := (base w_digits). + Notation wwB := (base (ww_digits w_digits)). + Notation "[| x |]" := (w_to_Z x) (at level 0, x at level 99). + Notation "[-| c |]" := + (interp_carry (-1) wB w_to_Z c) (at level 0, x at level 99). + + Notation "[[ x ]]" := (ww_to_Z w_digits w_to_Z x)(at level 0, x at level 99). + + Variable spec_w_0 : [|w_0|] = 0. + Variable spec_to_Z : forall x, 0 <= [|x|] < wB. + Variable spec_to_w_Z : forall x, 0 <= [[x]] < wwB. + + Variable spec_w_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|]. + Variable spec_w_0W : forall l, [[w_0W l]] = [|l|]. + Variable spec_compare : + forall x y, + match w_compare x y with + | Eq => [|x|] = [|y|] + | Lt => [|x|] < [|y|] + | Gt => [|x|] > [|y|] + end. + Variable spec_eq0 : forall x, w_eq0 x = true -> [|x|] = 0. + + Variable spec_opp_c : forall x, [-|w_opp_c x|] = -[|x|]. + Variable spec_opp : forall x, [|w_opp x|] = (-[|x|]) mod wB. + Variable spec_opp_carry : forall x, [|w_opp_carry x|] = wB - [|x|] - 1. + + Variable spec_sub_c : forall x y, [-|w_sub_c x y|] = [|x|] - [|y|]. + Variable spec_sub : forall x y, [|w_sub x y|] = ([|x|] - [|y|]) mod wB. + Variable spec_sub_carry : + forall x y, [|w_sub_carry x y|] = ([|x|] - [|y|] - 1) mod wB. + + Variable spec_div_gt : forall a b, [|a|] > [|b|] -> 0 < [|b|] -> + let (q,r) := w_div_gt a b in + [|a|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]. + Variable spec_mod_gt : forall a b, [|a|] > [|b|] -> 0 < [|b|] -> + [|w_mod_gt a b|] = [|a|] mod [|b|]. + Variable spec_gcd_gt : forall a b, [|a|] > [|b|] -> + Zis_gcd [|a|] [|b|] [|w_gcd_gt a b|]. + + Variable spec_add_mul_div : forall x y p, + [|p|] <= Zpos w_digits -> + [| w_add_mul_div p x y |] = + ([|x|] * (2 ^ ([|p|])) + + [|y|] / (2 ^ ((Zpos w_digits) - [|p|]))) mod wB. + Variable spec_head0 : forall x, 0 < [|x|] -> + wB/ 2 <= 2 ^ [|w_head0 x|] * [|x|] < wB. + + Variable spec_div21 : forall a1 a2 b, + wB/2 <= [|b|] -> + [|a1|] < [|b|] -> + let (q,r) := w_div21 a1 a2 b in + [|a1|] *wB+ [|a2|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]. + + Variable spec_w_div32 : forall a1 a2 a3 b1 b2, + wB/2 <= [|b1|] -> + [[WW a1 a2]] < [[WW b1 b2]] -> + let (q,r) := w_div32 a1 a2 a3 b1 b2 in + [|a1|] * wwB + [|a2|] * wB + [|a3|] = + [|q|] * ([|b1|] * wB + [|b2|]) + [[r]] /\ + 0 <= [[r]] < [|b1|] * wB + [|b2|]. + + Variable spec_w_zdigits: [|w_zdigits|] = Zpos w_digits. + + Variable spec_ww_digits_ : [[_ww_zdigits]] = Zpos (xO w_digits). + Variable spec_ww_1 : [[ww_1]] = 1. + Variable spec_ww_add_mul_div : forall x y p, + [[p]] <= Zpos (xO w_digits) -> + [[ ww_add_mul_div p x y ]] = + ([[x]] * (2^[[p]]) + + [[y]] / (2^(Zpos (xO w_digits) - [[p]]))) mod wwB. + + Ltac Spec_w_to_Z x := + let H:= fresh "HH" in + assert (H:= spec_to_Z x). + + Ltac Spec_ww_to_Z x := + let H:= fresh "HH" in + assert (H:= spec_ww_to_Z w_digits w_to_Z spec_to_Z x). + + Lemma to_Z_div_minus_p : forall x p, + 0 < [|p|] < Zpos w_digits -> + 0 <= [|x|] / 2 ^ (Zpos w_digits - [|p|]) < 2 ^ [|p|]. + Proof. + intros x p H;Spec_w_to_Z x. + split. apply Zdiv_le_lower_bound;zarith. + apply Zdiv_lt_upper_bound;zarith. + rewrite <- Zpower_exp;zarith. + ring_simplify ([|p|] + (Zpos w_digits - [|p|])); unfold base in HH;zarith. + Qed. + Hint Resolve to_Z_div_minus_p : zarith. + + Lemma spec_ww_div_gt_aux : forall ah al bh bl, + [[WW ah al]] > [[WW bh bl]] -> + 0 < [|bh|] -> + let (q,r) := ww_div_gt_aux ah al bh bl in + [[WW ah al]] = [[q]] * [[WW bh bl]] + [[r]] /\ + 0 <= [[r]] < [[WW bh bl]]. + Proof. + intros ah al bh bl Hgt Hpos;unfold ww_div_gt_aux. + change + (let (q, r) := let p := w_head0 bh in + match w_compare p w_0 with + | Gt => + let b1 := w_add_mul_div p bh bl in + let b2 := w_add_mul_div p bl w_0 in + let a1 := w_add_mul_div p w_0 ah in + let a2 := w_add_mul_div p ah al in + let a3 := w_add_mul_div p al w_0 in + let (q,r) := w_div32 a1 a2 a3 b1 b2 in + (WW w_0 q, ww_add_mul_div + (ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c + w_opp w_sub w_sub_carry _ww_zdigits (w_0W p)) W0 r) + | _ => (ww_1, ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c + w_opp w_sub w_sub_carry (WW ah al) (WW bh bl)) + end in [[WW ah al]]=[[q]]*[[WW bh bl]]+[[r]] /\ 0 <=[[r]]< [[WW bh bl]]). + assert (Hh := spec_head0 Hpos). + lazy zeta. + generalize (spec_compare (w_head0 bh) w_0); case w_compare; + rewrite spec_w_0; intros HH. + generalize Hh; rewrite HH; simpl Zpower; + rewrite Zmult_1_l; intros (HH1, HH2); clear HH. + assert (wwB <= 2*[[WW bh bl]]). + apply Zle_trans with (2*[|bh|]*wB). + rewrite wwB_wBwB; rewrite Zpower_2; apply Zmult_le_compat_r; zarith. + rewrite <- wB_div_2; apply Zmult_le_compat_l; zarith. + simpl ww_to_Z;rewrite Zmult_plus_distr_r;rewrite Zmult_assoc. + Spec_w_to_Z bl;zarith. + Spec_ww_to_Z (WW ah al). + rewrite spec_ww_sub;eauto. + simpl;rewrite spec_ww_1;rewrite Zmult_1_l;simpl. + simpl ww_to_Z in Hgt, H, HH;rewrite Zmod_small;split;zarith. + case (spec_to_Z (w_head0 bh)); auto with zarith. + assert ([|w_head0 bh|] < Zpos w_digits). + destruct (Z_lt_ge_dec [|w_head0 bh|] (Zpos w_digits));trivial. + elimtype False. + assert (2 ^ [|w_head0 bh|] * [|bh|] >= wB);auto with zarith. + apply Zle_ge; replace wB with (wB * 1);try ring. + Spec_w_to_Z bh;apply Zmult_le_compat;zarith. + unfold base;apply Zpower_le_monotone;zarith. + assert (HHHH : 0 < [|w_head0 bh|] < Zpos w_digits); auto with zarith. + assert (Hb:= Zlt_le_weak _ _ H). + generalize (spec_add_mul_div w_0 ah Hb) + (spec_add_mul_div ah al Hb) + (spec_add_mul_div al w_0 Hb) + (spec_add_mul_div bh bl Hb) + (spec_add_mul_div bl w_0 Hb); + rewrite spec_w_0; repeat rewrite Zmult_0_l;repeat rewrite Zplus_0_l; + rewrite Zdiv_0_l;repeat rewrite Zplus_0_r. + Spec_w_to_Z ah;Spec_w_to_Z bh. + unfold base;repeat rewrite Zmod_shift_r;zarith. + assert (H3:=to_Z_div_minus_p ah HHHH);assert(H4:=to_Z_div_minus_p al HHHH); + assert (H5:=to_Z_div_minus_p bl HHHH). + rewrite Zmult_comm in Hh. + assert (2^[|w_head0 bh|] < wB). unfold base;apply Zpower_lt_monotone;zarith. + unfold base in H0;rewrite Zmod_small;zarith. + fold wB; rewrite (Zmod_small ([|bh|] * 2 ^ [|w_head0 bh|]));zarith. + intros U1 U2 U3 V1 V2. + generalize (@spec_w_div32 (w_add_mul_div (w_head0 bh) w_0 ah) + (w_add_mul_div (w_head0 bh) ah al) + (w_add_mul_div (w_head0 bh) al w_0) + (w_add_mul_div (w_head0 bh) bh bl) + (w_add_mul_div (w_head0 bh) bl w_0)). + destruct (w_div32 (w_add_mul_div (w_head0 bh) w_0 ah) + (w_add_mul_div (w_head0 bh) ah al) + (w_add_mul_div (w_head0 bh) al w_0) + (w_add_mul_div (w_head0 bh) bh bl) + (w_add_mul_div (w_head0 bh) bl w_0)) as (q,r). + rewrite V1;rewrite V2. rewrite Zmult_plus_distr_l. + rewrite <- (Zplus_assoc ([|bh|] * 2 ^ [|w_head0 bh|] * wB)). + unfold base;rewrite <- shift_unshift_mod;zarith. fold wB. + replace ([|bh|] * 2 ^ [|w_head0 bh|] * wB + [|bl|] * 2 ^ [|w_head0 bh|]) with + ([[WW bh bl]] * 2^[|w_head0 bh|]). 2:simpl;ring. + fold wwB. rewrite wwB_wBwB. rewrite Zpower_2. rewrite U1;rewrite U2;rewrite U3. + rewrite Zmult_assoc. rewrite Zmult_plus_distr_l. + rewrite (Zplus_assoc ([|ah|] / 2^(Zpos(w_digits) - [|w_head0 bh|])*wB * wB)). + rewrite <- Zmult_plus_distr_l. rewrite <- Zplus_assoc. + unfold base;repeat rewrite <- shift_unshift_mod;zarith. fold wB. + replace ([|ah|] * 2 ^ [|w_head0 bh|] * wB + [|al|] * 2 ^ [|w_head0 bh|]) with + ([[WW ah al]] * 2^[|w_head0 bh|]). 2:simpl;ring. + intros Hd;destruct Hd;zarith. + simpl. apply beta_lex_inv;zarith. rewrite U1;rewrite V1. + assert ([|ah|] / 2 ^ (Zpos (w_digits) - [|w_head0 bh|]) < wB/2);zarith. + apply Zdiv_lt_upper_bound;zarith. + unfold base. + replace (2^Zpos (w_digits)) with (2^(Zpos (w_digits) - 1)*2). + rewrite Z_div_mult;zarith. rewrite <- Zpower_exp;zarith. + apply Zlt_le_trans with wB;zarith. + unfold base;apply Zpower_le_monotone;zarith. + pattern 2 at 2;replace 2 with (2^1);trivial. + rewrite <- Zpower_exp;zarith. ring_simplify (Zpos (w_digits) - 1 + 1);trivial. + change [[WW w_0 q]] with ([|w_0|]*wB+[|q|]);rewrite spec_w_0;rewrite + Zmult_0_l;rewrite Zplus_0_l. + replace [[ww_add_mul_div (ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c w_opp w_sub w_sub_carry + _ww_zdigits (w_0W (w_head0 bh))) W0 r]] with ([[r]]/2^[|w_head0 bh|]). + assert (0 < 2^[|w_head0 bh|]). apply Zpower_gt_0;zarith. + split. + rewrite <- (Z_div_mult [[WW ah al]] (2^[|w_head0 bh|]));zarith. + rewrite H1;rewrite Zmult_assoc;apply Z_div_plus_l;trivial. + split;[apply Zdiv_le_lower_bound| apply Zdiv_lt_upper_bound];zarith. + rewrite spec_ww_add_mul_div. + rewrite spec_ww_sub; auto with zarith. + rewrite spec_ww_digits_. + change (Zpos (xO (w_digits))) with (2*Zpos (w_digits));zarith. + simpl ww_to_Z;rewrite Zmult_0_l;rewrite Zplus_0_l. + rewrite spec_w_0W. + rewrite (fun x y => Zmod_small (x-y)); auto with zarith. + ring_simplify (2 * Zpos w_digits - (2 * Zpos w_digits - [|w_head0 bh|])). + rewrite Zmod_small;zarith. + split;[apply Zdiv_le_lower_bound| apply Zdiv_lt_upper_bound];zarith. + Spec_ww_to_Z r. + apply Zlt_le_trans with wwB;zarith. + rewrite <- (Zmult_1_r wwB);apply Zmult_le_compat;zarith. + split; auto with zarith. + apply Zle_lt_trans with (2 * Zpos w_digits); auto with zarith. + unfold base, ww_digits; rewrite (Zpos_xO w_digits). + apply Zpower2_lt_lin; auto with zarith. + rewrite spec_ww_sub; auto with zarith. + rewrite spec_ww_digits_; rewrite spec_w_0W. + rewrite Zmod_small;zarith. + rewrite Zpos_xO; split; auto with zarith. + apply Zle_lt_trans with (2 * Zpos w_digits); auto with zarith. + unfold base, ww_digits; rewrite (Zpos_xO w_digits). + apply Zpower2_lt_lin; auto with zarith. + Qed. + + Lemma spec_ww_div_gt : forall a b, [[a]] > [[b]] -> 0 < [[b]] -> + let (q,r) := ww_div_gt a b in + [[a]] = [[q]] * [[b]] + [[r]] /\ + 0 <= [[r]] < [[b]]. + Proof. + intros a b Hgt Hpos;unfold ww_div_gt. + change (let (q,r) := match a, b with + | W0, _ => (W0,W0) + | _, W0 => (W0,W0) + | WW ah al, WW bh bl => + if w_eq0 ah then + let (q,r) := w_div_gt al bl in + (WW w_0 q, w_0W r) + else + match w_compare w_0 bh with + | Eq => + let(q,r):= + double_divn1 w_zdigits w_0 w_WW w_head0 w_add_mul_div w_div21 + w_compare w_sub 1 a bl in + (q, w_0W r) + | Lt => ww_div_gt_aux ah al bh bl + | Gt => (W0,W0) (* cas absurde *) + end + end in [[a]] = [[q]] * [[b]] + [[r]] /\ 0 <= [[r]] < [[b]]). + destruct a as [ |ah al]. simpl in Hgt;omega. + destruct b as [ |bh bl]. simpl in Hpos;omega. + Spec_w_to_Z ah; Spec_w_to_Z al; Spec_w_to_Z bh; Spec_w_to_Z bl. + assert (H:=@spec_eq0 ah);destruct (w_eq0 ah). + simpl ww_to_Z;rewrite H;trivial. simpl in Hgt;rewrite H in Hgt;trivial. + assert ([|bh|] <= 0). + apply beta_lex with (d:=[|al|])(b:=[|bl|]) (beta := wB);zarith. + assert ([|bh|] = 0);zarith. rewrite H1 in Hgt;rewrite H1;simpl in Hgt. + simpl. simpl in Hpos;rewrite H1 in Hpos;simpl in Hpos. + assert (H2:=spec_div_gt Hgt Hpos);destruct (w_div_gt al bl). + repeat rewrite spec_w_0W;simpl;rewrite spec_w_0;simpl;trivial. + clear H. + assert (Hcmp := spec_compare w_0 bh); destruct (w_compare w_0 bh). + rewrite spec_w_0 in Hcmp. change [[WW bh bl]] with ([|bh|]*wB+[|bl|]). + rewrite <- Hcmp;rewrite Zmult_0_l;rewrite Zplus_0_l. + simpl in Hpos;rewrite <- Hcmp in Hpos;simpl in Hpos. + assert (H2:= @spec_double_divn1 w w_digits w_zdigits w_0 w_WW w_head0 w_add_mul_div + w_div21 w_compare w_sub w_to_Z spec_to_Z spec_w_zdigits spec_w_0 spec_w_WW spec_head0 + spec_add_mul_div spec_div21 spec_compare spec_sub 1 (WW ah al) bl Hpos). + unfold double_to_Z,double_wB,double_digits in H2. + destruct (double_divn1 w_zdigits w_0 w_WW w_head0 w_add_mul_div w_div21 + w_compare w_sub 1 + (WW ah al) bl). + rewrite spec_w_0W;unfold ww_to_Z;trivial. + apply spec_ww_div_gt_aux;trivial. rewrite spec_w_0 in Hcmp;trivial. + rewrite spec_w_0 in Hcmp;elimtype False;omega. + Qed. + + Lemma spec_ww_mod_gt_aux_eq : forall ah al bh bl, + ww_mod_gt_aux ah al bh bl = snd (ww_div_gt_aux ah al bh bl). + Proof. + intros ah al bh bl. unfold ww_mod_gt_aux, ww_div_gt_aux. + case w_compare; auto. + case w_div32; auto. + Qed. + + Lemma spec_ww_mod_gt_aux : forall ah al bh bl, + [[WW ah al]] > [[WW bh bl]] -> + 0 < [|bh|] -> + [[ww_mod_gt_aux ah al bh bl]] = [[WW ah al]] mod [[WW bh bl]]. + Proof. + intros. rewrite spec_ww_mod_gt_aux_eq;trivial. + assert (H3 := spec_ww_div_gt_aux ah al bl H H0). + destruct (ww_div_gt_aux ah al bh bl) as (q,r);simpl. simpl in H,H3. + destruct H3;apply Zmod_unique with [[q]];zarith. + rewrite H1;ring. + Qed. + + Lemma spec_w_mod_gt_eq : forall a b, [|a|] > [|b|] -> 0 <[|b|] -> + [|w_mod_gt a b|] = [|snd (w_div_gt a b)|]. + Proof. + intros a b Hgt Hpos. + rewrite spec_mod_gt;trivial. + assert (H:=spec_div_gt Hgt Hpos). + destruct (w_div_gt a b) as (q,r);simpl. + rewrite Zmult_comm in H;destruct H. + symmetry;apply Zmod_unique with [|q|];trivial. + Qed. + + Lemma spec_ww_mod_gt_eq : forall a b, [[a]] > [[b]] -> 0 < [[b]] -> + [[ww_mod_gt a b]] = [[snd (ww_div_gt a b)]]. + Proof. + intros a b Hgt Hpos. + change (ww_mod_gt a b) with + (match a, b with + | W0, _ => W0 + | _, W0 => W0 + | WW ah al, WW bh bl => + if w_eq0 ah then w_0W (w_mod_gt al bl) + else + match w_compare w_0 bh with + | Eq => + w_0W (double_modn1 w_zdigits w_0 w_head0 w_add_mul_div w_div21 + w_compare w_sub 1 a bl) + | Lt => ww_mod_gt_aux ah al bh bl + | Gt => W0 (* cas absurde *) + end end). + change (ww_div_gt a b) with + (match a, b with + | W0, _ => (W0,W0) + | _, W0 => (W0,W0) + | WW ah al, WW bh bl => + if w_eq0 ah then + let (q,r) := w_div_gt al bl in + (WW w_0 q, w_0W r) + else + match w_compare w_0 bh with + | Eq => + let(q,r):= + double_divn1 w_zdigits w_0 w_WW w_head0 w_add_mul_div w_div21 + w_compare w_sub 1 a bl in + (q, w_0W r) + | Lt => ww_div_gt_aux ah al bh bl + | Gt => (W0,W0) (* cas absurde *) + end + end). + destruct a as [ |ah al];trivial. + destruct b as [ |bh bl];trivial. + Spec_w_to_Z ah; Spec_w_to_Z al; Spec_w_to_Z bh; Spec_w_to_Z bl. + assert (H:=@spec_eq0 ah);destruct (w_eq0 ah). + simpl in Hgt;rewrite H in Hgt;trivial. + assert ([|bh|] <= 0). + apply beta_lex with (d:=[|al|])(b:=[|bl|]) (beta := wB);zarith. + assert ([|bh|] = 0);zarith. rewrite H1 in Hgt;simpl in Hgt. + simpl in Hpos;rewrite H1 in Hpos;simpl in Hpos. + rewrite spec_w_0W;rewrite spec_w_mod_gt_eq;trivial. + destruct (w_div_gt al bl);simpl;rewrite spec_w_0W;trivial. + clear H. + assert (H2 := spec_compare w_0 bh);destruct (w_compare w_0 bh). + rewrite (@spec_double_modn1_aux w w_zdigits w_0 w_WW w_head0 w_add_mul_div + w_div21 w_compare w_sub w_to_Z spec_w_0 spec_compare 1 (WW ah al) bl). + destruct (double_divn1 w_zdigits w_0 w_WW w_head0 w_add_mul_div w_div21 w_compare w_sub 1 + (WW ah al) bl);simpl;trivial. + rewrite spec_ww_mod_gt_aux_eq;trivial;symmetry;trivial. + trivial. + Qed. + + Lemma spec_ww_mod_gt : forall a b, [[a]] > [[b]] -> 0 < [[b]] -> + [[ww_mod_gt a b]] = [[a]] mod [[b]]. + Proof. + intros a b Hgt Hpos. + assert (H:= spec_ww_div_gt a b Hgt Hpos). + rewrite (spec_ww_mod_gt_eq a b Hgt Hpos). + destruct (ww_div_gt a b)as(q,r);destruct H. + apply Zmod_unique with[[q]];simpl;trivial. + rewrite Zmult_comm;trivial. + Qed. + + Lemma Zis_gcd_mod : forall a b d, + 0 < b -> Zis_gcd b (a mod b) d -> Zis_gcd a b d. + Proof. + intros a b d H H1; apply Zis_gcd_for_euclid with (a/b). + pattern a at 1;rewrite (Z_div_mod_eq a b). + ring_simplify (b * (a / b) + a mod b - a / b * b);trivial. zarith. + Qed. + + Lemma spec_ww_gcd_gt_aux_body : + forall ah al bh bl n cont, + [[WW bh bl]] <= 2^n -> + [[WW ah al]] > [[WW bh bl]] -> + (forall xh xl yh yl, + [[WW xh xl]] > [[WW yh yl]] -> [[WW yh yl]] <= 2^(n-1) -> + Zis_gcd [[WW xh xl]] [[WW yh yl]] [[cont xh xl yh yl]]) -> + Zis_gcd [[WW ah al]] [[WW bh bl]] [[ww_gcd_gt_body cont ah al bh bl]]. + Proof. + intros ah al bh bl n cont Hlog Hgt Hcont. + change (ww_gcd_gt_body cont ah al bh bl) with (match w_compare w_0 bh with + | Eq => + match w_compare w_0 bl with + | Eq => WW ah al (* normalement n'arrive pas si forme normale *) + | Lt => + let m := double_modn1 w_zdigits w_0 w_head0 w_add_mul_div w_div21 + w_compare w_sub 1 (WW ah al) bl in + WW w_0 (w_gcd_gt bl m) + | Gt => W0 (* absurde *) + end + | Lt => + let m := ww_mod_gt_aux ah al bh bl in + match m with + | W0 => WW bh bl + | WW mh ml => + match w_compare w_0 mh with + | Eq => + match w_compare w_0 ml with + | Eq => WW bh bl + | _ => + let r := double_modn1 w_zdigits w_0 w_head0 w_add_mul_div w_div21 + w_compare w_sub 1 (WW bh bl) ml in + WW w_0 (w_gcd_gt ml r) + end + | Lt => + let r := ww_mod_gt_aux bh bl mh ml in + match r with + | W0 => m + | WW rh rl => cont mh ml rh rl + end + | Gt => W0 (* absurde *) + end + end + | Gt => W0 (* absurde *) + end). + assert (Hbh := spec_compare w_0 bh);destruct (w_compare w_0 bh). + simpl ww_to_Z in *. rewrite spec_w_0 in Hbh;rewrite <- Hbh; + rewrite Zmult_0_l;rewrite Zplus_0_l. + assert (Hbl := spec_compare w_0 bl); destruct (w_compare w_0 bl). + rewrite spec_w_0 in Hbl;rewrite <- Hbl;apply Zis_gcd_0. + simpl;rewrite spec_w_0;rewrite Zmult_0_l;rewrite Zplus_0_l. + rewrite spec_w_0 in Hbl. + apply Zis_gcd_mod;zarith. + change ([|ah|] * wB + [|al|]) with (double_to_Z w_digits w_to_Z 1 (WW ah al)). + rewrite <- (@spec_double_modn1 w w_digits w_zdigits w_0 w_WW w_head0 w_add_mul_div + w_div21 w_compare w_sub w_to_Z spec_to_Z spec_w_zdigits spec_w_0 spec_w_WW spec_head0 spec_add_mul_div + spec_div21 spec_compare spec_sub 1 (WW ah al) bl Hbl). + apply spec_gcd_gt. + rewrite (@spec_double_modn1 w w_digits w_zdigits w_0 w_WW); trivial. + apply Zlt_gt;match goal with | |- ?x mod ?y < ?y => + destruct (Z_mod_lt x y);zarith end. + rewrite spec_w_0 in Hbl;Spec_w_to_Z bl;elimtype False;omega. + rewrite spec_w_0 in Hbh;assert (H:= spec_ww_mod_gt_aux _ _ _ Hgt Hbh). + assert (H2 : 0 < [[WW bh bl]]). + simpl;Spec_w_to_Z bl. apply Zlt_le_trans with ([|bh|]*wB);zarith. + apply Zmult_lt_0_compat;zarith. + apply Zis_gcd_mod;trivial. rewrite <- H. + simpl in *;destruct (ww_mod_gt_aux ah al bh bl) as [ |mh ml]. + simpl;apply Zis_gcd_0;zarith. + assert (Hmh := spec_compare w_0 mh);destruct (w_compare w_0 mh). + simpl;rewrite spec_w_0 in Hmh; rewrite <- Hmh;simpl. + assert (Hml := spec_compare w_0 ml);destruct (w_compare w_0 ml). + rewrite <- Hml;rewrite spec_w_0;simpl;apply Zis_gcd_0. + simpl;rewrite spec_w_0;simpl. + rewrite spec_w_0 in Hml. apply Zis_gcd_mod;zarith. + change ([|bh|] * wB + [|bl|]) with (double_to_Z w_digits w_to_Z 1 (WW bh bl)). + rewrite <- (@spec_double_modn1 w w_digits w_zdigits w_0 w_WW w_head0 w_add_mul_div + w_div21 w_compare w_sub w_to_Z spec_to_Z spec_w_zdigits spec_w_0 spec_w_WW spec_head0 spec_add_mul_div + spec_div21 spec_compare spec_sub 1 (WW bh bl) ml Hml). + apply spec_gcd_gt. + rewrite (@spec_double_modn1 w w_digits w_zdigits w_0 w_WW); trivial. + apply Zlt_gt;match goal with | |- ?x mod ?y < ?y => + destruct (Z_mod_lt x y);zarith end. + rewrite spec_w_0 in Hml;Spec_w_to_Z ml;elimtype False;omega. + rewrite spec_w_0 in Hmh. assert ([[WW bh bl]] > [[WW mh ml]]). + rewrite H;simpl; apply Zlt_gt;match goal with | |- ?x mod ?y < ?y => + destruct (Z_mod_lt x y);zarith end. + assert (H1:= spec_ww_mod_gt_aux _ _ _ H0 Hmh). + assert (H3 : 0 < [[WW mh ml]]). + simpl;Spec_w_to_Z ml. apply Zlt_le_trans with ([|mh|]*wB);zarith. + apply Zmult_lt_0_compat;zarith. + apply Zis_gcd_mod;zarith. simpl in *;rewrite <- H1. + destruct (ww_mod_gt_aux bh bl mh ml) as [ |rh rl]. simpl; apply Zis_gcd_0. + simpl;apply Hcont. simpl in H1;rewrite H1. + apply Zlt_gt;match goal with | |- ?x mod ?y < ?y => + destruct (Z_mod_lt x y);zarith end. + apply Zle_trans with (2^n/2). + apply Zdiv_le_lower_bound;zarith. + apply Zle_trans with ([|bh|] * wB + [|bl|]);zarith. + assert (H3' := Z_div_mod_eq [[WW bh bl]] [[WW mh ml]] (Zlt_gt _ _ H3)). + assert (H4' : 0 <= [[WW bh bl]]/[[WW mh ml]]). + apply Zge_le;apply Z_div_ge0;zarith. simpl in *;rewrite H1. + pattern ([|bh|] * wB + [|bl|]) at 2;rewrite H3'. + destruct (Zle_lt_or_eq _ _ H4'). + assert (H6' : [[WW bh bl]] mod [[WW mh ml]] = + [[WW bh bl]] - [[WW mh ml]] * ([[WW bh bl]]/[[WW mh ml]])). + simpl;pattern ([|bh|] * wB + [|bl|]) at 2;rewrite H3';ring. simpl in H6'. + assert ([[WW mh ml]] <= [[WW mh ml]] * ([[WW bh bl]]/[[WW mh ml]])). + simpl;pattern ([|mh|]*wB+[|ml|]) at 1;rewrite <- Zmult_1_r;zarith. + simpl in *;assert (H8 := Z_mod_lt [[WW bh bl]] [[WW mh ml]]);simpl in H8; + zarith. + assert (H8 := Z_mod_lt [[WW bh bl]] [[WW mh ml]]);simpl in *;zarith. + rewrite <- H4 in H3';rewrite Zmult_0_r in H3';simpl in H3';zarith. + pattern n at 1;replace n with (n-1+1);try ring. + rewrite Zpower_exp;zarith. change (2^1) with 2. + rewrite Z_div_mult;zarith. + assert (2^1 <= 2^n). change (2^1) with 2;zarith. + assert (H7 := @Zpower_le_monotone_inv 2 1 n);zarith. + rewrite spec_w_0 in Hmh;Spec_w_to_Z mh;elimtype False;zarith. + rewrite spec_w_0 in Hbh;Spec_w_to_Z bh;elimtype False;zarith. + Qed. + + Lemma spec_ww_gcd_gt_aux : + forall p cont n, + (forall xh xl yh yl, + [[WW xh xl]] > [[WW yh yl]] -> + [[WW yh yl]] <= 2^n -> + Zis_gcd [[WW xh xl]] [[WW yh yl]] [[cont xh xl yh yl]]) -> + forall ah al bh bl , [[WW ah al]] > [[WW bh bl]] -> + [[WW bh bl]] <= 2^(Zpos p + n) -> + Zis_gcd [[WW ah al]] [[WW bh bl]] + [[ww_gcd_gt_aux p cont ah al bh bl]]. + Proof. + induction p;intros cont n Hcont ah al bh bl Hgt Hs;simpl ww_gcd_gt_aux. + assert (0 < Zpos p). unfold Zlt;reflexivity. + apply spec_ww_gcd_gt_aux_body with (n := Zpos (xI p) + n); + trivial;rewrite Zpos_xI. + intros. apply IHp with (n := Zpos p + n);zarith. + intros. apply IHp with (n := n );zarith. + apply Zle_trans with (2 ^ (2* Zpos p + 1+ n -1));zarith. + apply Zpower_le_monotone2;zarith. + assert (0 < Zpos p). unfold Zlt;reflexivity. + apply spec_ww_gcd_gt_aux_body with (n := Zpos (xO p) + n );trivial. + rewrite (Zpos_xO p). + intros. apply IHp with (n := Zpos p + n - 1);zarith. + intros. apply IHp with (n := n -1 );zarith. + intros;apply Hcont;zarith. + apply Zle_trans with (2^(n-1));zarith. + apply Zpower_le_monotone2;zarith. + apply Zle_trans with (2 ^ (Zpos p + n -1));zarith. + apply Zpower_le_monotone2;zarith. + apply Zle_trans with (2 ^ (2*Zpos p + n -1));zarith. + apply Zpower_le_monotone2;zarith. + apply spec_ww_gcd_gt_aux_body with (n := n+1);trivial. + rewrite Zplus_comm;trivial. + ring_simplify (n + 1 - 1);trivial. + Qed. + +End DoubleDivGt. + +Section DoubleDiv. + + Variable w : Type. + Variable w_digits : positive. + Variable ww_1 : zn2z w. + Variable ww_compare : zn2z w -> zn2z w -> comparison. + + Variable ww_div_gt : zn2z w -> zn2z w -> zn2z w * zn2z w. + Variable ww_mod_gt : zn2z w -> zn2z w -> zn2z w. + + Definition ww_div a b := + match ww_compare a b with + | Gt => ww_div_gt a b + | Eq => (ww_1, W0) + | Lt => (W0, a) + end. + + Definition ww_mod a b := + match ww_compare a b with + | Gt => ww_mod_gt a b + | Eq => W0 + | Lt => a + end. + + Variable w_to_Z : w -> Z. + Notation wB := (base w_digits). + Notation wwB := (base (ww_digits w_digits)). + Notation "[| x |]" := (w_to_Z x) (at level 0, x at level 99). + Notation "[[ x ]]" := (ww_to_Z w_digits w_to_Z x)(at level 0, x at level 99). + Variable spec_to_Z : forall x, 0 <= [|x|] < wB. + Variable spec_ww_1 : [[ww_1]] = 1. + Variable spec_ww_compare : forall x y, + match ww_compare x y with + | Eq => [[x]] = [[y]] + | Lt => [[x]] < [[y]] + | Gt => [[x]] > [[y]] + end. + Variable spec_ww_div_gt : forall a b, [[a]] > [[b]] -> 0 < [[b]] -> + let (q,r) := ww_div_gt a b in + [[a]] = [[q]] * [[b]] + [[r]] /\ + 0 <= [[r]] < [[b]]. + Variable spec_ww_mod_gt : forall a b, [[a]] > [[b]] -> 0 < [[b]] -> + [[ww_mod_gt a b]] = [[a]] mod [[b]]. + + Ltac Spec_w_to_Z x := + let H:= fresh "HH" in + assert (H:= spec_to_Z x). + + Ltac Spec_ww_to_Z x := + let H:= fresh "HH" in + assert (H:= spec_ww_to_Z w_digits w_to_Z spec_to_Z x). + + Lemma spec_ww_div : forall a b, 0 < [[b]] -> + let (q,r) := ww_div a b in + [[a]] = [[q]] * [[b]] + [[r]] /\ + 0 <= [[r]] < [[b]]. + Proof. + intros a b Hpos;unfold ww_div. + assert (H:=spec_ww_compare a b);destruct (ww_compare a b). + simpl;rewrite spec_ww_1;split;zarith. + simpl;split;[ring|Spec_ww_to_Z a;zarith]. + apply spec_ww_div_gt;trivial. + Qed. + + Lemma spec_ww_mod : forall a b, 0 < [[b]] -> + [[ww_mod a b]] = [[a]] mod [[b]]. + Proof. + intros a b Hpos;unfold ww_mod. + assert (H := spec_ww_compare a b);destruct (ww_compare a b). + simpl;apply Zmod_unique with 1;try rewrite H;zarith. + Spec_ww_to_Z a;symmetry;apply Zmod_small;zarith. + apply spec_ww_mod_gt;trivial. + Qed. + + + Variable w_0 : w. + Variable w_1 : w. + Variable w_compare : w -> w -> comparison. + Variable w_eq0 : w -> bool. + Variable w_gcd_gt : w -> w -> w. + Variable _ww_digits : positive. + Variable spec_ww_digits_ : _ww_digits = xO w_digits. + Variable ww_gcd_gt_fix : + positive -> (w -> w -> w -> w -> zn2z w) -> + w -> w -> w -> w -> zn2z w. + + Variable spec_w_0 : [|w_0|] = 0. + Variable spec_w_1 : [|w_1|] = 1. + Variable spec_compare : + forall x y, + match w_compare x y with + | Eq => [|x|] = [|y|] + | Lt => [|x|] < [|y|] + | Gt => [|x|] > [|y|] + end. + Variable spec_eq0 : forall x, w_eq0 x = true -> [|x|] = 0. + Variable spec_gcd_gt : forall a b, [|a|] > [|b|] -> + Zis_gcd [|a|] [|b|] [|w_gcd_gt a b|]. + Variable spec_gcd_gt_fix : + forall p cont n, + (forall xh xl yh yl, + [[WW xh xl]] > [[WW yh yl]] -> + [[WW yh yl]] <= 2^n -> + Zis_gcd [[WW xh xl]] [[WW yh yl]] [[cont xh xl yh yl]]) -> + forall ah al bh bl , [[WW ah al]] > [[WW bh bl]] -> + [[WW bh bl]] <= 2^(Zpos p + n) -> + Zis_gcd [[WW ah al]] [[WW bh bl]] + [[ww_gcd_gt_fix p cont ah al bh bl]]. + + Definition gcd_cont (xh xl yh yl:w) := + match w_compare w_1 yl with + | Eq => ww_1 + | _ => WW xh xl + end. + + Lemma spec_gcd_cont : forall xh xl yh yl, + [[WW xh xl]] > [[WW yh yl]] -> + [[WW yh yl]] <= 1 -> + Zis_gcd [[WW xh xl]] [[WW yh yl]] [[gcd_cont xh xl yh yl]]. + Proof. + intros xh xl yh yl Hgt' Hle. simpl in Hle. + assert ([|yh|] = 0). + change 1 with (0*wB+1) in Hle. + assert (0 <= 1 < wB). split;zarith. apply wB_pos. + assert (H1:= beta_lex _ _ _ _ _ Hle (spec_to_Z yl) H). + Spec_w_to_Z yh;zarith. + unfold gcd_cont;assert (Hcmpy:=spec_compare w_1 yl); + rewrite spec_w_1 in Hcmpy. + simpl;rewrite H;simpl;destruct (w_compare w_1 yl). + rewrite spec_ww_1;rewrite <- Hcmpy;apply Zis_gcd_mod;zarith. + rewrite <- (Zmod_unique ([|xh|]*wB+[|xl|]) 1 ([|xh|]*wB+[|xl|]) 0);zarith. + rewrite H in Hle; elimtype False;zarith. + assert ([|yl|] = 0). Spec_w_to_Z yl;zarith. + rewrite H0;simpl;apply Zis_gcd_0;trivial. + Qed. + + + Variable cont : w -> w -> w -> w -> zn2z w. + Variable spec_cont : forall xh xl yh yl, + [[WW xh xl]] > [[WW yh yl]] -> + [[WW yh yl]] <= 1 -> + Zis_gcd [[WW xh xl]] [[WW yh yl]] [[cont xh xl yh yl]]. + + Definition ww_gcd_gt a b := + match a, b with + | W0, _ => b + | _, W0 => a + | WW ah al, WW bh bl => + if w_eq0 ah then (WW w_0 (w_gcd_gt al bl)) + else ww_gcd_gt_fix _ww_digits cont ah al bh bl + end. + + Definition ww_gcd a b := + Eval lazy beta delta [ww_gcd_gt] in + match ww_compare a b with + | Gt => ww_gcd_gt a b + | Eq => a + | Lt => ww_gcd_gt b a + end. + + Lemma spec_ww_gcd_gt : forall a b, [[a]] > [[b]] -> + Zis_gcd [[a]] [[b]] [[ww_gcd_gt a b]]. + Proof. + intros a b Hgt;unfold ww_gcd_gt. + destruct a as [ |ah al]. simpl;apply Zis_gcd_sym;apply Zis_gcd_0. + destruct b as [ |bh bl]. simpl;apply Zis_gcd_0. + simpl in Hgt. generalize (@spec_eq0 ah);destruct (w_eq0 ah);intros. + simpl;rewrite H in Hgt;trivial;rewrite H;trivial;rewrite spec_w_0;simpl. + assert ([|bh|] <= 0). + apply beta_lex with (d:=[|al|])(b:=[|bl|]) (beta := wB);zarith. + Spec_w_to_Z bh;assert ([|bh|] = 0);zarith. rewrite H1 in Hgt;simpl in Hgt. + rewrite H1;simpl;auto. clear H. + apply spec_gcd_gt_fix with (n:= 0);trivial. + rewrite Zplus_0_r;rewrite spec_ww_digits_. + change (2 ^ Zpos (xO w_digits)) with wwB. Spec_ww_to_Z (WW bh bl);zarith. + Qed. + + Lemma spec_ww_gcd : forall a b, Zis_gcd [[a]] [[b]] [[ww_gcd a b]]. + Proof. + intros a b. + change (ww_gcd a b) with + (match ww_compare a b with + | Gt => ww_gcd_gt a b + | Eq => a + | Lt => ww_gcd_gt b a + end). + assert (Hcmp := spec_ww_compare a b);destruct (ww_compare a b). + Spec_ww_to_Z b;rewrite Hcmp. + apply Zis_gcd_for_euclid with 1;zarith. + ring_simplify ([[b]] - 1 * [[b]]). apply Zis_gcd_0;zarith. + apply Zis_gcd_sym;apply spec_ww_gcd_gt;zarith. + apply spec_ww_gcd_gt;zarith. + Qed. + +End DoubleDiv. + diff --git a/theories/Numbers/Cyclic/DoubleCyclic/DoubleDivn1.v b/theories/Numbers/Cyclic/DoubleCyclic/DoubleDivn1.v new file mode 100644 index 00000000..d6f6a05f --- /dev/null +++ b/theories/Numbers/Cyclic/DoubleCyclic/DoubleDivn1.v @@ -0,0 +1,528 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: DoubleDivn1.v 10964 2008-05-22 11:08:13Z letouzey $ i*) + +Set Implicit Arguments. + +Require Import ZArith. +Require Import BigNumPrelude. +Require Import DoubleType. +Require Import DoubleBase. + +Open Local Scope Z_scope. + +Section GENDIVN1. + + Variable w : Type. + Variable w_digits : positive. + Variable w_zdigits : w. + Variable w_0 : w. + Variable w_WW : w -> w -> zn2z w. + Variable w_head0 : w -> w. + Variable w_add_mul_div : w -> w -> w -> w. + Variable w_div21 : w -> w -> w -> w * w. + Variable w_compare : w -> w -> comparison. + Variable w_sub : w -> w -> w. + + + + (* ** For proofs ** *) + Variable w_to_Z : w -> Z. + + Notation wB := (base w_digits). + + Notation "[| x |]" := (w_to_Z x) (at level 0, x at level 99). + Notation "[! n | x !]" := (double_to_Z w_digits w_to_Z n x) + (at level 0, x at level 99). + Notation "[[ x ]]" := (zn2z_to_Z wB w_to_Z x) (at level 0, x at level 99). + + Variable spec_to_Z : forall x, 0 <= [| x |] < wB. + Variable spec_w_zdigits: [|w_zdigits|] = Zpos w_digits. + Variable spec_0 : [|w_0|] = 0. + Variable spec_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|]. + Variable spec_head0 : forall x, 0 < [|x|] -> + wB/ 2 <= 2 ^ [|w_head0 x|] * [|x|] < wB. + Variable spec_add_mul_div : forall x y p, + [|p|] <= Zpos w_digits -> + [| w_add_mul_div p x y |] = + ([|x|] * (2 ^ [|p|]) + + [|y|] / (2 ^ ((Zpos w_digits) - [|p|]))) mod wB. + Variable spec_div21 : forall a1 a2 b, + wB/2 <= [|b|] -> + [|a1|] < [|b|] -> + let (q,r) := w_div21 a1 a2 b in + [|a1|] *wB+ [|a2|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]. + Variable spec_compare : + forall x y, + match w_compare x y with + | Eq => [|x|] = [|y|] + | Lt => [|x|] < [|y|] + | Gt => [|x|] > [|y|] + end. + Variable spec_sub: forall x y, + [|w_sub x y|] = ([|x|] - [|y|]) mod wB. + + + + Section DIVAUX. + Variable b2p : w. + Variable b2p_le : wB/2 <= [|b2p|]. + + Definition double_divn1_0_aux n (divn1: w -> word w n -> word w n * w) r h := + let (hh,hl) := double_split w_0 n h in + let (qh,rh) := divn1 r hh in + let (ql,rl) := divn1 rh hl in + (double_WW w_WW n qh ql, rl). + + Fixpoint double_divn1_0 (n:nat) : w -> word w n -> word w n * w := + match n return w -> word w n -> word w n * w with + | O => fun r x => w_div21 r x b2p + | S n => double_divn1_0_aux n (double_divn1_0 n) + end. + + Lemma spec_split : forall (n : nat) (x : zn2z (word w n)), + let (h, l) := double_split w_0 n x in + [!S n | x!] = [!n | h!] * double_wB w_digits n + [!n | l!]. + Proof (spec_double_split w_0 w_digits w_to_Z spec_0). + + Lemma spec_double_divn1_0 : forall n r a, + [|r|] < [|b2p|] -> + let (q,r') := double_divn1_0 n r a in + [|r|] * double_wB w_digits n + [!n|a!] = [!n|q!] * [|b2p|] + [|r'|] /\ + 0 <= [|r'|] < [|b2p|]. + Proof. + induction n;intros. + exact (spec_div21 a b2p_le H). + simpl (double_divn1_0 (S n) r a); unfold double_divn1_0_aux. + assert (H1 := spec_split n a);destruct (double_split w_0 n a) as (hh,hl). + rewrite H1. + assert (H2 := IHn r hh H);destruct (double_divn1_0 n r hh) as (qh,rh). + destruct H2. + assert ([|rh|] < [|b2p|]). omega. + assert (H4 := IHn rh hl H3);destruct (double_divn1_0 n rh hl) as (ql,rl). + destruct H4;split;trivial. + rewrite spec_double_WW;trivial. + rewrite <- double_wB_wwB. + rewrite Zmult_assoc;rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. + rewrite H0;rewrite Zmult_plus_distr_l;rewrite <- Zplus_assoc. + rewrite H4;ring. + Qed. + + Definition double_modn1_0_aux n (modn1:w -> word w n -> w) r h := + let (hh,hl) := double_split w_0 n h in modn1 (modn1 r hh) hl. + + Fixpoint double_modn1_0 (n:nat) : w -> word w n -> w := + match n return w -> word w n -> w with + | O => fun r x => snd (w_div21 r x b2p) + | S n => double_modn1_0_aux n (double_modn1_0 n) + end. + + Lemma spec_double_modn1_0 : forall n r x, + double_modn1_0 n r x = snd (double_divn1_0 n r x). + Proof. + induction n;simpl;intros;trivial. + unfold double_modn1_0_aux, double_divn1_0_aux. + destruct (double_split w_0 n x) as (hh,hl). + rewrite (IHn r hh). + destruct (double_divn1_0 n r hh) as (qh,rh);simpl. + rewrite IHn. destruct (double_divn1_0 n rh hl);trivial. + Qed. + + Variable p : w. + Variable p_bounded : [|p|] <= Zpos w_digits. + + Lemma spec_add_mul_divp : forall x y, + [| w_add_mul_div p x y |] = + ([|x|] * (2 ^ [|p|]) + + [|y|] / (2 ^ ((Zpos w_digits) - [|p|]))) mod wB. + Proof. + intros;apply spec_add_mul_div;auto. + Qed. + + Definition double_divn1_p_aux n + (divn1 : w -> word w n -> word w n -> word w n * w) r h l := + let (hh,hl) := double_split w_0 n h in + let (lh,ll) := double_split w_0 n l in + let (qh,rh) := divn1 r hh hl in + let (ql,rl) := divn1 rh hl lh in + (double_WW w_WW n qh ql, rl). + + Fixpoint double_divn1_p (n:nat) : w -> word w n -> word w n -> word w n * w := + match n return w -> word w n -> word w n -> word w n * w with + | O => fun r h l => w_div21 r (w_add_mul_div p h l) b2p + | S n => double_divn1_p_aux n (double_divn1_p n) + end. + + Lemma p_lt_double_digits : forall n, [|p|] <= Zpos (double_digits w_digits n). + Proof. +(* + induction n;simpl. destruct p_bounded;trivial. + case (spec_to_Z p); rewrite Zpos_xO;auto with zarith. +*) + induction n;simpl. trivial. + case (spec_to_Z p); rewrite Zpos_xO;auto with zarith. + Qed. + + Lemma spec_double_divn1_p : forall n r h l, + [|r|] < [|b2p|] -> + let (q,r') := double_divn1_p n r h l in + [|r|] * double_wB w_digits n + + ([!n|h!]*2^[|p|] + + [!n|l!] / (2^(Zpos(double_digits w_digits n) - [|p|]))) + mod double_wB w_digits n = [!n|q!] * [|b2p|] + [|r'|] /\ + 0 <= [|r'|] < [|b2p|]. + Proof. + case (spec_to_Z p); intros HH0 HH1. + induction n;intros. + simpl (double_divn1_p 0 r h l). + unfold double_to_Z, double_wB, double_digits. + rewrite <- spec_add_mul_divp. + exact (spec_div21 (w_add_mul_div p h l) b2p_le H). + simpl (double_divn1_p (S n) r h l). + unfold double_divn1_p_aux. + assert (H1 := spec_split n h);destruct (double_split w_0 n h) as (hh,hl). + rewrite H1. rewrite <- double_wB_wwB. + assert (H2 := spec_split n l);destruct (double_split w_0 n l) as (lh,ll). + rewrite H2. + replace ([|r|] * (double_wB w_digits n * double_wB w_digits n) + + (([!n|hh!] * double_wB w_digits n + [!n|hl!]) * 2 ^ [|p|] + + ([!n|lh!] * double_wB w_digits n + [!n|ll!]) / + 2^(Zpos (double_digits w_digits (S n)) - [|p|])) mod + (double_wB w_digits n * double_wB w_digits n)) with + (([|r|] * double_wB w_digits n + ([!n|hh!] * 2^[|p|] + + [!n|hl!] / 2^(Zpos (double_digits w_digits n) - [|p|])) mod + double_wB w_digits n) * double_wB w_digits n + + ([!n|hl!] * 2^[|p|] + + [!n|lh!] / 2^(Zpos (double_digits w_digits n) - [|p|])) mod + double_wB w_digits n). + generalize (IHn r hh hl H);destruct (double_divn1_p n r hh hl) as (qh,rh); + intros (H3,H4);rewrite H3. + assert ([|rh|] < [|b2p|]). omega. + replace (([!n|qh!] * [|b2p|] + [|rh|]) * double_wB w_digits n + + ([!n|hl!] * 2 ^ [|p|] + + [!n|lh!] / 2 ^ (Zpos (double_digits w_digits n) - [|p|])) mod + double_wB w_digits n) with + ([!n|qh!] * [|b2p|] *double_wB w_digits n + ([|rh|]*double_wB w_digits n + + ([!n|hl!] * 2 ^ [|p|] + + [!n|lh!] / 2 ^ (Zpos (double_digits w_digits n) - [|p|])) mod + double_wB w_digits n)). 2:ring. + generalize (IHn rh hl lh H0);destruct (double_divn1_p n rh hl lh) as (ql,rl); + intros (H5,H6);rewrite H5. + split;[rewrite spec_double_WW;trivial;ring|trivial]. + assert (Uhh := spec_double_to_Z w_digits w_to_Z spec_to_Z n hh); + unfold double_wB,base in Uhh. + assert (Uhl := spec_double_to_Z w_digits w_to_Z spec_to_Z n hl); + unfold double_wB,base in Uhl. + assert (Ulh := spec_double_to_Z w_digits w_to_Z spec_to_Z n lh); + unfold double_wB,base in Ulh. + assert (Ull := spec_double_to_Z w_digits w_to_Z spec_to_Z n ll); + unfold double_wB,base in Ull. + unfold double_wB,base. + assert (UU:=p_lt_double_digits n). + rewrite Zdiv_shift_r;auto with zarith. + 2:change (Zpos (double_digits w_digits (S n))) + with (2*Zpos (double_digits w_digits n));auto with zarith. + replace (2 ^ (Zpos (double_digits w_digits (S n)) - [|p|])) with + (2^(Zpos (double_digits w_digits n) - [|p|])*2^Zpos (double_digits w_digits n)). + rewrite Zdiv_mult_cancel_r;auto with zarith. + rewrite Zmult_plus_distr_l with (p:= 2^[|p|]). + pattern ([!n|hl!] * 2^[|p|]) at 2; + rewrite (shift_unshift_mod (Zpos(double_digits w_digits n))([|p|])([!n|hl!])); + auto with zarith. + rewrite Zplus_assoc. + replace + ([!n|hh!] * 2^Zpos (double_digits w_digits n)* 2^[|p|] + + ([!n|hl!] / 2^(Zpos (double_digits w_digits n)-[|p|])* + 2^Zpos(double_digits w_digits n))) + with + (([!n|hh!] *2^[|p|] + double_to_Z w_digits w_to_Z n hl / + 2^(Zpos (double_digits w_digits n)-[|p|])) + * 2^Zpos(double_digits w_digits n));try (ring;fail). + rewrite <- Zplus_assoc. + rewrite <- (Zmod_shift_r ([|p|]));auto with zarith. + replace + (2 ^ Zpos (double_digits w_digits n) * 2 ^ Zpos (double_digits w_digits n)) with + (2 ^ (Zpos (double_digits w_digits n) + Zpos (double_digits w_digits n))). + rewrite (Zmod_shift_r (Zpos (double_digits w_digits n)));auto with zarith. + replace (2 ^ (Zpos (double_digits w_digits n) + Zpos (double_digits w_digits n))) + with (2^Zpos(double_digits w_digits n) *2^Zpos(double_digits w_digits n)). + rewrite (Zmult_comm (([!n|hh!] * 2 ^ [|p|] + + [!n|hl!] / 2 ^ (Zpos (double_digits w_digits n) - [|p|])))). + rewrite Zmult_mod_distr_l;auto with zarith. + ring. + rewrite Zpower_exp;auto with zarith. + assert (0 < Zpos (double_digits w_digits n)). unfold Zlt;reflexivity. + auto with zarith. + apply Z_mod_lt;auto with zarith. + rewrite Zpower_exp;auto with zarith. + split;auto with zarith. + apply Zdiv_lt_upper_bound;auto with zarith. + rewrite <- Zpower_exp;auto with zarith. + replace ([|p|] + (Zpos (double_digits w_digits n) - [|p|])) with + (Zpos(double_digits w_digits n));auto with zarith. + rewrite <- Zpower_exp;auto with zarith. + replace (Zpos (double_digits w_digits (S n)) - [|p|]) with + (Zpos (double_digits w_digits n) - [|p|] + + Zpos (double_digits w_digits n));trivial. + change (Zpos (double_digits w_digits (S n))) with + (2*Zpos (double_digits w_digits n)). ring. + Qed. + + Definition double_modn1_p_aux n (modn1 : w -> word w n -> word w n -> w) r h l:= + let (hh,hl) := double_split w_0 n h in + let (lh,ll) := double_split w_0 n l in + modn1 (modn1 r hh hl) hl lh. + + Fixpoint double_modn1_p (n:nat) : w -> word w n -> word w n -> w := + match n return w -> word w n -> word w n -> w with + | O => fun r h l => snd (w_div21 r (w_add_mul_div p h l) b2p) + | S n => double_modn1_p_aux n (double_modn1_p n) + end. + + Lemma spec_double_modn1_p : forall n r h l , + double_modn1_p n r h l = snd (double_divn1_p n r h l). + Proof. + induction n;simpl;intros;trivial. + unfold double_modn1_p_aux, double_divn1_p_aux. + destruct(double_split w_0 n h)as(hh,hl);destruct(double_split w_0 n l) as (lh,ll). + rewrite (IHn r hh hl);destruct (double_divn1_p n r hh hl) as (qh,rh). + rewrite IHn;simpl;destruct (double_divn1_p n rh hl lh);trivial. + Qed. + + End DIVAUX. + + Fixpoint high (n:nat) : word w n -> w := + match n return word w n -> w with + | O => fun a => a + | S n => + fun (a:zn2z (word w n)) => + match a with + | W0 => w_0 + | WW h l => high n h + end + end. + + Lemma spec_double_digits:forall n, Zpos w_digits <= Zpos (double_digits w_digits n). + Proof. + induction n;simpl;auto with zarith. + change (Zpos (xO (double_digits w_digits n))) with + (2*Zpos (double_digits w_digits n)). + assert (0 < Zpos w_digits);auto with zarith. + exact (refl_equal Lt). + Qed. + + Lemma spec_high : forall n (x:word w n), + [|high n x|] = [!n|x!] / 2^(Zpos (double_digits w_digits n) - Zpos w_digits). + Proof. + induction n;intros. + unfold high,double_digits,double_to_Z. + replace (Zpos w_digits - Zpos w_digits) with 0;try ring. + simpl. rewrite <- (Zdiv_unique [|x|] 1 [|x|] 0);auto with zarith. + assert (U2 := spec_double_digits n). + assert (U3 : 0 < Zpos w_digits). exact (refl_equal Lt). + destruct x;unfold high;fold high. + unfold double_to_Z,zn2z_to_Z;rewrite spec_0. + rewrite Zdiv_0_l;trivial. + assert (U0 := spec_double_to_Z w_digits w_to_Z spec_to_Z n w0); + assert (U1 := spec_double_to_Z w_digits w_to_Z spec_to_Z n w1). + simpl [!S n|WW w0 w1!]. + unfold double_wB,base;rewrite Zdiv_shift_r;auto with zarith. + replace (2 ^ (Zpos (double_digits w_digits (S n)) - Zpos w_digits)) with + (2^(Zpos (double_digits w_digits n) - Zpos w_digits) * + 2^Zpos (double_digits w_digits n)). + rewrite Zdiv_mult_cancel_r;auto with zarith. + rewrite <- Zpower_exp;auto with zarith. + replace (Zpos (double_digits w_digits n) - Zpos w_digits + + Zpos (double_digits w_digits n)) with + (Zpos (double_digits w_digits (S n)) - Zpos w_digits);trivial. + change (Zpos (double_digits w_digits (S n))) with + (2*Zpos (double_digits w_digits n));ring. + change (Zpos (double_digits w_digits (S n))) with + (2*Zpos (double_digits w_digits n)); auto with zarith. + Qed. + + Definition double_divn1 (n:nat) (a:word w n) (b:w) := + let p := w_head0 b in + match w_compare p w_0 with + | Gt => + let b2p := w_add_mul_div p b w_0 in + let ha := high n a in + let k := w_sub w_zdigits p in + let lsr_n := w_add_mul_div k w_0 in + let r0 := w_add_mul_div p w_0 ha in + let (q,r) := double_divn1_p b2p p n r0 a (double_0 w_0 n) in + (q, lsr_n r) + | _ => double_divn1_0 b n w_0 a + end. + + Lemma spec_double_divn1 : forall n a b, + 0 < [|b|] -> + let (q,r) := double_divn1 n a b in + [!n|a!] = [!n|q!] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]. + Proof. + intros n a b H. unfold double_divn1. + case (spec_head0 H); intros H0 H1. + case (spec_to_Z (w_head0 b)); intros HH1 HH2. + generalize (spec_compare (w_head0 b) w_0); case w_compare; + rewrite spec_0; intros H2; auto with zarith. + assert (Hv1: wB/2 <= [|b|]). + generalize H0; rewrite H2; rewrite Zpower_0_r; + rewrite Zmult_1_l; auto. + assert (Hv2: [|w_0|] < [|b|]). + rewrite spec_0; auto. + generalize (spec_double_divn1_0 Hv1 n a Hv2). + rewrite spec_0;rewrite Zmult_0_l; rewrite Zplus_0_l; auto. + contradict H2; auto with zarith. + assert (HHHH : 0 < [|w_head0 b|]); auto with zarith. + assert ([|w_head0 b|] < Zpos w_digits). + case (Zle_or_lt (Zpos w_digits) [|w_head0 b|]); auto; intros HH. + assert (2 ^ [|w_head0 b|] < wB). + apply Zle_lt_trans with (2 ^ [|w_head0 b|] * [|b|]);auto with zarith. + replace (2 ^ [|w_head0 b|]) with (2^[|w_head0 b|] * 1);try (ring;fail). + apply Zmult_le_compat;auto with zarith. + assert (wB <= 2^[|w_head0 b|]). + unfold base;apply Zpower_le_monotone;auto with zarith. omega. + assert ([|w_add_mul_div (w_head0 b) b w_0|] = + 2 ^ [|w_head0 b|] * [|b|]). + rewrite (spec_add_mul_div b w_0); auto with zarith. + rewrite spec_0;rewrite Zdiv_0_l; try omega. + rewrite Zplus_0_r; rewrite Zmult_comm. + rewrite Zmod_small; auto with zarith. + assert (H5 := spec_to_Z (high n a)). + assert + ([|w_add_mul_div (w_head0 b) w_0 (high n a)|] + <[|w_add_mul_div (w_head0 b) b w_0|]). + rewrite H4. + rewrite spec_add_mul_div;auto with zarith. + rewrite spec_0;rewrite Zmult_0_l;rewrite Zplus_0_l. + assert (([|high n a|]/2^(Zpos w_digits - [|w_head0 b|])) < wB). + apply Zdiv_lt_upper_bound;auto with zarith. + apply Zlt_le_trans with wB;auto with zarith. + pattern wB at 1;replace wB with (wB*1);try ring. + apply Zmult_le_compat;auto with zarith. + assert (H6 := Zpower_gt_0 2 (Zpos w_digits - [|w_head0 b|])); + auto with zarith. + rewrite Zmod_small;auto with zarith. + apply Zdiv_lt_upper_bound;auto with zarith. + apply Zlt_le_trans with wB;auto with zarith. + apply Zle_trans with (2 ^ [|w_head0 b|] * [|b|] * 2). + rewrite <- wB_div_2; try omega. + apply Zmult_le_compat;auto with zarith. + pattern 2 at 1;rewrite <- Zpower_1_r. + apply Zpower_le_monotone;split;auto with zarith. + rewrite <- H4 in H0. + assert (Hb3: [|w_head0 b|] <= Zpos w_digits); auto with zarith. + assert (H7:= spec_double_divn1_p H0 Hb3 n a (double_0 w_0 n) H6). + destruct (double_divn1_p (w_add_mul_div (w_head0 b) b w_0) (w_head0 b) n + (w_add_mul_div (w_head0 b) w_0 (high n a)) a + (double_0 w_0 n)) as (q,r). + assert (U:= spec_double_digits n). + rewrite spec_double_0 in H7;trivial;rewrite Zdiv_0_l in H7. + rewrite Zplus_0_r in H7. + rewrite spec_add_mul_div in H7;auto with zarith. + rewrite spec_0 in H7;rewrite Zmult_0_l in H7;rewrite Zplus_0_l in H7. + assert (([|high n a|] / 2 ^ (Zpos w_digits - [|w_head0 b|])) mod wB + = [!n|a!] / 2^(Zpos (double_digits w_digits n) - [|w_head0 b|])). + rewrite Zmod_small;auto with zarith. + rewrite spec_high. rewrite Zdiv_Zdiv;auto with zarith. + rewrite <- Zpower_exp;auto with zarith. + replace (Zpos (double_digits w_digits n) - Zpos w_digits + + (Zpos w_digits - [|w_head0 b|])) + with (Zpos (double_digits w_digits n) - [|w_head0 b|]);trivial;ring. + assert (H8 := Zpower_gt_0 2 (Zpos w_digits - [|w_head0 b|]));auto with zarith. + split;auto with zarith. + apply Zle_lt_trans with ([|high n a|]);auto with zarith. + apply Zdiv_le_upper_bound;auto with zarith. + pattern ([|high n a|]) at 1;rewrite <- Zmult_1_r. + apply Zmult_le_compat;auto with zarith. + rewrite H8 in H7;unfold double_wB,base in H7. + rewrite <- shift_unshift_mod in H7;auto with zarith. + rewrite H4 in H7. + assert ([|w_add_mul_div (w_sub w_zdigits (w_head0 b)) w_0 r|] + = [|r|]/2^[|w_head0 b|]). + rewrite spec_add_mul_div. + rewrite spec_0;rewrite Zmult_0_l;rewrite Zplus_0_l. + replace (Zpos w_digits - [|w_sub w_zdigits (w_head0 b)|]) + with ([|w_head0 b|]). + rewrite Zmod_small;auto with zarith. + assert (H9 := spec_to_Z r). + split;auto with zarith. + apply Zle_lt_trans with ([|r|]);auto with zarith. + apply Zdiv_le_upper_bound;auto with zarith. + pattern ([|r|]) at 1;rewrite <- Zmult_1_r. + apply Zmult_le_compat;auto with zarith. + assert (H10 := Zpower_gt_0 2 ([|w_head0 b|]));auto with zarith. + rewrite spec_sub. + rewrite Zmod_small; auto with zarith. + split; auto with zarith. + case (spec_to_Z w_zdigits); auto with zarith. + rewrite spec_sub. + rewrite Zmod_small; auto with zarith. + split; auto with zarith. + case (spec_to_Z w_zdigits); auto with zarith. + case H7; intros H71 H72. + split. + rewrite <- (Z_div_mult [!n|a!] (2^[|w_head0 b|]));auto with zarith. + rewrite H71;rewrite H9. + replace ([!n|q!] * (2 ^ [|w_head0 b|] * [|b|])) + with ([!n|q!] *[|b|] * 2^[|w_head0 b|]); + try (ring;fail). + rewrite Z_div_plus_l;auto with zarith. + assert (H10 := spec_to_Z + (w_add_mul_div (w_sub w_zdigits (w_head0 b)) w_0 r));split; + auto with zarith. + rewrite H9. + apply Zdiv_lt_upper_bound;auto with zarith. + rewrite Zmult_comm;auto with zarith. + exact (spec_double_to_Z w_digits w_to_Z spec_to_Z n a). + Qed. + + + Definition double_modn1 (n:nat) (a:word w n) (b:w) := + let p := w_head0 b in + match w_compare p w_0 with + | Gt => + let b2p := w_add_mul_div p b w_0 in + let ha := high n a in + let k := w_sub w_zdigits p in + let lsr_n := w_add_mul_div k w_0 in + let r0 := w_add_mul_div p w_0 ha in + let r := double_modn1_p b2p p n r0 a (double_0 w_0 n) in + lsr_n r + | _ => double_modn1_0 b n w_0 a + end. + + Lemma spec_double_modn1_aux : forall n a b, + double_modn1 n a b = snd (double_divn1 n a b). + Proof. + intros n a b;unfold double_divn1,double_modn1. + generalize (spec_compare (w_head0 b) w_0); case w_compare; + rewrite spec_0; intros H2; auto with zarith. + apply spec_double_modn1_0. + apply spec_double_modn1_0. + rewrite spec_double_modn1_p. + destruct (double_divn1_p (w_add_mul_div (w_head0 b) b w_0) (w_head0 b) n + (w_add_mul_div (w_head0 b) w_0 (high n a)) a (double_0 w_0 n));simpl;trivial. + Qed. + + Lemma spec_double_modn1 : forall n a b, 0 < [|b|] -> + [|double_modn1 n a b|] = [!n|a!] mod [|b|]. + Proof. + intros n a b H;assert (H1 := spec_double_divn1 n a H). + assert (H2 := spec_double_modn1_aux n a b). + rewrite H2;destruct (double_divn1 n a b) as (q,r). + simpl;apply Zmod_unique with (double_to_Z w_digits w_to_Z n q);auto with zarith. + destruct H1 as (h1,h2);rewrite h1;ring. + Qed. + +End GENDIVN1. diff --git a/theories/Numbers/Cyclic/DoubleCyclic/DoubleLift.v b/theories/Numbers/Cyclic/DoubleCyclic/DoubleLift.v new file mode 100644 index 00000000..50c72487 --- /dev/null +++ b/theories/Numbers/Cyclic/DoubleCyclic/DoubleLift.v @@ -0,0 +1,487 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: DoubleLift.v 10964 2008-05-22 11:08:13Z letouzey $ i*) + +Set Implicit Arguments. + +Require Import ZArith. +Require Import BigNumPrelude. +Require Import DoubleType. +Require Import DoubleBase. + +Open Local Scope Z_scope. + +Section DoubleLift. + Variable w : Type. + Variable w_0 : w. + Variable w_WW : w -> w -> zn2z w. + Variable w_W0 : w -> zn2z w. + Variable w_0W : w -> zn2z w. + Variable w_compare : w -> w -> comparison. + Variable ww_compare : zn2z w -> zn2z w -> comparison. + Variable w_head0 : w -> w. + Variable w_tail0 : w -> w. + Variable w_add: w -> w -> zn2z w. + Variable w_add_mul_div : w -> w -> w -> w. + Variable ww_sub: zn2z w -> zn2z w -> zn2z w. + Variable w_digits : positive. + Variable ww_Digits : positive. + Variable w_zdigits : w. + Variable ww_zdigits : zn2z w. + Variable low: zn2z w -> w. + + Definition ww_head0 x := + match x with + | W0 => ww_zdigits + | WW xh xl => + match w_compare w_0 xh with + | Eq => w_add w_zdigits (w_head0 xl) + | _ => w_0W (w_head0 xh) + end + end. + + + Definition ww_tail0 x := + match x with + | W0 => ww_zdigits + | WW xh xl => + match w_compare w_0 xl with + | Eq => w_add w_zdigits (w_tail0 xh) + | _ => w_0W (w_tail0 xl) + end + end. + + + (* 0 < p < ww_digits *) + Definition ww_add_mul_div p x y := + let zdigits := w_0W w_zdigits in + match x, y with + | W0, W0 => W0 + | W0, WW yh yl => + match ww_compare p zdigits with + | Eq => w_0W yh + | Lt => w_0W (w_add_mul_div (low p) w_0 yh) + | Gt => + let n := low (ww_sub p zdigits) in + w_WW (w_add_mul_div n w_0 yh) (w_add_mul_div n yh yl) + end + | WW xh xl, W0 => + match ww_compare p zdigits with + | Eq => w_W0 xl + | Lt => w_WW (w_add_mul_div (low p) xh xl) (w_add_mul_div (low p) xl w_0) + | Gt => + let n := low (ww_sub p zdigits) in + w_W0 (w_add_mul_div n xl w_0) + end + | WW xh xl, WW yh yl => + match ww_compare p zdigits with + | Eq => w_WW xl yh + | Lt => w_WW (w_add_mul_div (low p) xh xl) (w_add_mul_div (low p) xl yh) + | Gt => + let n := low (ww_sub p zdigits) in + w_WW (w_add_mul_div n xl yh) (w_add_mul_div n yh yl) + end + end. + + Section DoubleProof. + Variable w_to_Z : w -> Z. + + Notation wB := (base w_digits). + Notation wwB := (base (ww_digits w_digits)). + Notation "[| x |]" := (w_to_Z x) (at level 0, x at level 99). + Notation "[[ x ]]" := (ww_to_Z w_digits w_to_Z x)(at level 0, x at level 99). + + Variable spec_w_0 : [|w_0|] = 0. + Variable spec_to_Z : forall x, 0 <= [|x|] < wB. + Variable spec_to_w_Z : forall x, 0 <= [[x]] < wwB. + Variable spec_w_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|]. + Variable spec_w_W0 : forall h, [[w_W0 h]] = [|h|] * wB. + Variable spec_w_0W : forall l, [[w_0W l]] = [|l|]. + Variable spec_compare : forall x y, + match w_compare x y with + | Eq => [|x|] = [|y|] + | Lt => [|x|] < [|y|] + | Gt => [|x|] > [|y|] + end. + Variable spec_ww_compare : forall x y, + match ww_compare x y with + | Eq => [[x]] = [[y]] + | Lt => [[x]] < [[y]] + | Gt => [[x]] > [[y]] + end. + Variable spec_ww_digits : ww_Digits = xO w_digits. + Variable spec_w_head00 : forall x, [|x|] = 0 -> [|w_head0 x|] = Zpos w_digits. + Variable spec_w_head0 : forall x, 0 < [|x|] -> + wB/ 2 <= 2 ^ ([|w_head0 x|]) * [|x|] < wB. + Variable spec_w_tail00 : forall x, [|x|] = 0 -> [|w_tail0 x|] = Zpos w_digits. + Variable spec_w_tail0 : forall x, 0 < [|x|] -> + exists y, 0 <= y /\ [|x|] = (2* y + 1) * (2 ^ [|w_tail0 x|]). + Variable spec_w_add_mul_div : forall x y p, + [|p|] <= Zpos w_digits -> + [| w_add_mul_div p x y |] = + ([|x|] * (2 ^ [|p|]) + + [|y|] / (2 ^ ((Zpos w_digits) - [|p|]))) mod wB. + Variable spec_w_add: forall x y, + [[w_add x y]] = [|x|] + [|y|]. + Variable spec_ww_sub: forall x y, + [[ww_sub x y]] = ([[x]] - [[y]]) mod wwB. + + Variable spec_zdigits : [| w_zdigits |] = Zpos w_digits. + Variable spec_low: forall x, [| low x|] = [[x]] mod wB. + + Variable spec_ww_zdigits : [[ww_zdigits]] = Zpos ww_Digits. + + Hint Resolve div_le_0 div_lt w_to_Z_wwB: lift. + Ltac zarith := auto with zarith lift. + + Lemma spec_ww_head00 : forall x, [[x]] = 0 -> [[ww_head0 x]] = Zpos ww_Digits. + Proof. + intros x; case x; unfold ww_head0. + intros HH; rewrite spec_ww_zdigits; auto. + intros xh xl; simpl; intros Hx. + case (spec_to_Z xh); intros Hx1 Hx2. + case (spec_to_Z xl); intros Hy1 Hy2. + assert (F1: [|xh|] = 0). + case (Zle_lt_or_eq _ _ Hy1); auto; intros Hy3. + absurd (0 < [|xh|] * wB + [|xl|]); auto with zarith. + apply Zlt_le_trans with (1 := Hy3); auto with zarith. + pattern [|xl|] at 1; rewrite <- (Zplus_0_l [|xl|]). + apply Zplus_le_compat_r; auto with zarith. + case (Zle_lt_or_eq _ _ Hx1); auto; intros Hx3. + absurd (0 < [|xh|] * wB + [|xl|]); auto with zarith. + rewrite <- Hy3; rewrite Zplus_0_r; auto with zarith. + apply Zmult_lt_0_compat; auto with zarith. + generalize (spec_compare w_0 xh); case w_compare. + intros H; simpl. + rewrite spec_w_add; rewrite spec_w_head00. + rewrite spec_zdigits; rewrite spec_ww_digits. + rewrite Zpos_xO; auto with zarith. + rewrite F1 in Hx; auto with zarith. + rewrite spec_w_0; auto with zarith. + rewrite spec_w_0; auto with zarith. + Qed. + + Lemma spec_ww_head0 : forall x, 0 < [[x]] -> + wwB/ 2 <= 2 ^ [[ww_head0 x]] * [[x]] < wwB. + Proof. + clear spec_ww_zdigits. + rewrite wwB_div_2;rewrite Zmult_comm;rewrite wwB_wBwB. + assert (U:= lt_0_wB w_digits); destruct x as [ |xh xl];simpl ww_to_Z;intros H. + unfold Zlt in H;discriminate H. + assert (H0 := spec_compare w_0 xh);rewrite spec_w_0 in H0. + destruct (w_compare w_0 xh). + rewrite <- H0. simpl Zplus. rewrite <- H0 in H;simpl in H. + case (spec_to_Z w_zdigits); + case (spec_to_Z (w_head0 xl)); intros HH1 HH2 HH3 HH4. + rewrite spec_w_add. + rewrite spec_zdigits; rewrite Zpower_exp; auto with zarith. + case (spec_w_head0 H); intros H1 H2. + rewrite Zpower_2; fold wB; rewrite <- Zmult_assoc; split. + apply Zmult_le_compat_l; auto with zarith. + apply Zmult_lt_compat_l; auto with zarith. + assert (H1 := spec_w_head0 H0). + rewrite spec_w_0W. + split. + rewrite Zmult_plus_distr_r;rewrite Zmult_assoc. + apply Zle_trans with (2 ^ [|w_head0 xh|] * [|xh|] * wB). + rewrite Zmult_comm; zarith. + assert (0 <= 2 ^ [|w_head0 xh|] * [|xl|]);zarith. + assert (H2:=spec_to_Z xl);apply Zmult_le_0_compat;zarith. + case (spec_to_Z (w_head0 xh)); intros H2 _. + generalize ([|w_head0 xh|]) H1 H2;clear H1 H2; + intros p H1 H2. + assert (Eq1 : 2^p < wB). + rewrite <- (Zmult_1_r (2^p));apply Zle_lt_trans with (2^p*[|xh|]);zarith. + assert (Eq2: p < Zpos w_digits). + destruct (Zle_or_lt (Zpos w_digits) p);trivial;contradict Eq1. + apply Zle_not_lt;unfold base;apply Zpower_le_monotone;zarith. + assert (Zpos w_digits = p + (Zpos w_digits - p)). ring. + rewrite Zpower_2. + unfold base at 2;rewrite H3;rewrite Zpower_exp;zarith. + rewrite <- Zmult_assoc; apply Zmult_lt_compat_l; zarith. + rewrite <- (Zplus_0_r (2^(Zpos w_digits - p)*wB));apply beta_lex_inv;zarith. + apply Zmult_lt_reg_r with (2 ^ p); zarith. + rewrite <- Zpower_exp;zarith. + rewrite Zmult_comm;ring_simplify (Zpos w_digits - p + p);fold wB;zarith. + assert (H1 := spec_to_Z xh);zarith. + Qed. + + Lemma spec_ww_tail00 : forall x, [[x]] = 0 -> [[ww_tail0 x]] = Zpos ww_Digits. + Proof. + intros x; case x; unfold ww_tail0. + intros HH; rewrite spec_ww_zdigits; auto. + intros xh xl; simpl; intros Hx. + case (spec_to_Z xh); intros Hx1 Hx2. + case (spec_to_Z xl); intros Hy1 Hy2. + assert (F1: [|xh|] = 0). + case (Zle_lt_or_eq _ _ Hy1); auto; intros Hy3. + absurd (0 < [|xh|] * wB + [|xl|]); auto with zarith. + apply Zlt_le_trans with (1 := Hy3); auto with zarith. + pattern [|xl|] at 1; rewrite <- (Zplus_0_l [|xl|]). + apply Zplus_le_compat_r; auto with zarith. + case (Zle_lt_or_eq _ _ Hx1); auto; intros Hx3. + absurd (0 < [|xh|] * wB + [|xl|]); auto with zarith. + rewrite <- Hy3; rewrite Zplus_0_r; auto with zarith. + apply Zmult_lt_0_compat; auto with zarith. + assert (F2: [|xl|] = 0). + rewrite F1 in Hx; auto with zarith. + generalize (spec_compare w_0 xl); case w_compare. + intros H; simpl. + rewrite spec_w_add; rewrite spec_w_tail00; auto. + rewrite spec_zdigits; rewrite spec_ww_digits. + rewrite Zpos_xO; auto with zarith. + rewrite spec_w_0; auto with zarith. + rewrite spec_w_0; auto with zarith. + Qed. + + Lemma spec_ww_tail0 : forall x, 0 < [[x]] -> + exists y, 0 <= y /\ [[x]] = (2 * y + 1) * 2 ^ [[ww_tail0 x]]. + Proof. + clear spec_ww_zdigits. + destruct x as [ |xh xl];simpl ww_to_Z;intros H. + unfold Zlt in H;discriminate H. + assert (H0 := spec_compare w_0 xl);rewrite spec_w_0 in H0. + destruct (w_compare w_0 xl). + rewrite <- H0; rewrite Zplus_0_r. + case (spec_to_Z (w_tail0 xh)); intros HH1 HH2. + generalize H; rewrite <- H0; rewrite Zplus_0_r; clear H; intros H. + case (@spec_w_tail0 xh). + apply Zmult_lt_reg_r with wB; auto with zarith. + unfold base; auto with zarith. + intros z (Hz1, Hz2); exists z; split; auto. + rewrite spec_w_add; rewrite (fun x => Zplus_comm [|x|]). + rewrite spec_zdigits; rewrite Zpower_exp; auto with zarith. + rewrite Zmult_assoc; rewrite <- Hz2; auto. + + case (spec_to_Z (w_tail0 xh)); intros HH1 HH2. + case (spec_w_tail0 H0); intros z (Hz1, Hz2). + assert (Hp: [|w_tail0 xl|] < Zpos w_digits). + case (Zle_or_lt (Zpos w_digits) [|w_tail0 xl|]); auto; intros H1. + absurd (2 ^ (Zpos w_digits) <= 2 ^ [|w_tail0 xl|]). + apply Zlt_not_le. + case (spec_to_Z xl); intros HH3 HH4. + apply Zle_lt_trans with (2 := HH4). + apply Zle_trans with (1 * 2 ^ [|w_tail0 xl|]); auto with zarith. + rewrite Hz2. + apply Zmult_le_compat_r; auto with zarith. + apply Zpower_le_monotone; auto with zarith. + exists ([|xh|] * (2 ^ ((Zpos w_digits - [|w_tail0 xl|]) - 1)) + z); split. + apply Zplus_le_0_compat; auto. + apply Zmult_le_0_compat; auto with zarith. + case (spec_to_Z xh); auto. + rewrite spec_w_0W. + rewrite (Zmult_plus_distr_r 2); rewrite <- Zplus_assoc. + rewrite Zmult_plus_distr_l; rewrite <- Hz2. + apply f_equal2 with (f := Zplus); auto. + rewrite (Zmult_comm 2). + repeat rewrite <- Zmult_assoc. + apply f_equal2 with (f := Zmult); auto. + case (spec_to_Z (w_tail0 xl)); intros HH3 HH4. + pattern 2 at 2; rewrite <- Zpower_1_r. + lazy beta; repeat rewrite <- Zpower_exp; auto with zarith. + unfold base; apply f_equal with (f := Zpower 2); auto with zarith. + + contradict H0; case (spec_to_Z xl); auto with zarith. + Qed. + + Hint Rewrite Zdiv_0_l Zmult_0_l Zplus_0_l Zmult_0_r Zplus_0_r + spec_w_W0 spec_w_0W spec_w_WW spec_w_0 + (wB_div w_digits w_to_Z spec_to_Z) + (wB_div_plus w_digits w_to_Z spec_to_Z) : w_rewrite. + Ltac w_rewrite := autorewrite with w_rewrite;trivial. + + Lemma spec_ww_add_mul_div_aux : forall xh xl yh yl p, + let zdigits := w_0W w_zdigits in + [[p]] <= Zpos (xO w_digits) -> + [[match ww_compare p zdigits with + | Eq => w_WW xl yh + | Lt => w_WW (w_add_mul_div (low p) xh xl) + (w_add_mul_div (low p) xl yh) + | Gt => + let n := low (ww_sub p zdigits) in + w_WW (w_add_mul_div n xl yh) (w_add_mul_div n yh yl) + end]] = + ([[WW xh xl]] * (2^[[p]]) + + [[WW yh yl]] / (2^(Zpos (xO w_digits) - [[p]]))) mod wwB. + Proof. + clear spec_ww_zdigits. + intros xh xl yh yl p zdigits;assert (HwwB := wwB_pos w_digits). + case (spec_to_w_Z p); intros Hv1 Hv2. + replace (Zpos (xO w_digits)) with (Zpos w_digits + Zpos w_digits). + 2 : rewrite Zpos_xO;ring. + replace (Zpos w_digits + Zpos w_digits - [[p]]) with + (Zpos w_digits + (Zpos w_digits - [[p]])). 2:ring. + intros Hp; assert (Hxh := spec_to_Z xh);assert (Hxl:=spec_to_Z xl); + assert (Hx := spec_ww_to_Z w_digits w_to_Z spec_to_Z (WW xh xl)); + simpl in Hx;assert (Hyh := spec_to_Z yh);assert (Hyl:=spec_to_Z yl); + assert (Hy:=spec_ww_to_Z w_digits w_to_Z spec_to_Z (WW yh yl));simpl in Hy. + generalize (spec_ww_compare p zdigits); case ww_compare; intros H1. + rewrite H1; unfold zdigits; rewrite spec_w_0W. + rewrite spec_zdigits; rewrite Zminus_diag; rewrite Zplus_0_r. + simpl ww_to_Z; w_rewrite;zarith. + fold wB. + rewrite Zmult_plus_distr_l;rewrite <- Zmult_assoc;rewrite <- Zplus_assoc. + rewrite <- Zpower_2. + rewrite <- wwB_wBwB;apply Zmod_unique with [|xh|]. + exact (spec_ww_to_Z w_digits w_to_Z spec_to_Z (WW xl yh)). ring. + simpl ww_to_Z; w_rewrite;zarith. + assert (HH0: [|low p|] = [[p]]). + rewrite spec_low. + apply Zmod_small. + case (spec_to_w_Z p); intros HH1 HH2; split; auto. + generalize H1; unfold zdigits; rewrite spec_w_0W; + rewrite spec_zdigits; intros tmp. + apply Zlt_le_trans with (1 := tmp). + unfold base. + apply Zpower2_le_lin; auto with zarith. + 2: generalize H1; unfold zdigits; rewrite spec_w_0W; + rewrite spec_zdigits; auto with zarith. + generalize H1; unfold zdigits; rewrite spec_w_0W; + rewrite spec_zdigits; auto; clear H1; intros H1. + assert (HH: [|low p|] <= Zpos w_digits). + rewrite HH0; auto with zarith. + repeat rewrite spec_w_add_mul_div with (1 := HH). + rewrite HH0. + rewrite Zmult_plus_distr_l. + pattern ([|xl|] * 2 ^ [[p]]) at 2; + rewrite shift_unshift_mod with (n:= Zpos w_digits);fold wB;zarith. + replace ([|xh|] * wB * 2^[[p]]) with ([|xh|] * 2^[[p]] * wB). 2:ring. + rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. rewrite <- Zplus_assoc. + unfold base at 5;rewrite <- Zmod_shift_r;zarith. + unfold base;rewrite Zmod_shift_r with (b:= Zpos (ww_digits w_digits)); + fold wB;fold wwB;zarith. + rewrite wwB_wBwB;rewrite Zpower_2; rewrite Zmult_mod_distr_r;zarith. + unfold ww_digits;rewrite Zpos_xO;zarith. apply Z_mod_lt;zarith. + split;zarith. apply Zdiv_lt_upper_bound;zarith. + rewrite <- Zpower_exp;zarith. + ring_simplify ([[p]] + (Zpos w_digits - [[p]]));fold wB;zarith. + assert (Hv: [[p]] > Zpos w_digits). + generalize H1; clear H1. + unfold zdigits; rewrite spec_w_0W; rewrite spec_zdigits; auto. + clear H1. + assert (HH0: [|low (ww_sub p zdigits)|] = [[p]] - Zpos w_digits). + rewrite spec_low. + rewrite spec_ww_sub. + unfold zdigits; rewrite spec_w_0W; rewrite spec_zdigits. + rewrite <- Zmod_div_mod; auto with zarith. + rewrite Zmod_small; auto with zarith. + split; auto with zarith. + apply Zle_lt_trans with (Zpos w_digits); auto with zarith. + unfold base; apply Zpower2_lt_lin; auto with zarith. + exists wB; unfold base. + unfold ww_digits; rewrite (Zpos_xO w_digits). + rewrite <- Zpower_exp; auto with zarith. + apply f_equal with (f := fun x => 2 ^ x); auto with zarith. + assert (HH: [|low (ww_sub p zdigits)|] <= Zpos w_digits). + rewrite HH0; auto with zarith. + replace (Zpos w_digits + (Zpos w_digits - [[p]])) with + (Zpos w_digits - ([[p]] - Zpos w_digits)); zarith. + lazy zeta; simpl ww_to_Z; w_rewrite;zarith. + repeat rewrite spec_w_add_mul_div;zarith. + rewrite HH0. + pattern wB at 5;replace wB with + (2^(([[p]] - Zpos w_digits) + + (Zpos w_digits - ([[p]] - Zpos w_digits)))). + rewrite Zpower_exp;zarith. rewrite Zmult_assoc. + rewrite Z_div_plus_l;zarith. + rewrite shift_unshift_mod with (a:= [|yh|]) (p:= [[p]] - Zpos w_digits) + (n := Zpos w_digits);zarith. fold wB. + set (u := [[p]] - Zpos w_digits). + replace [[p]] with (u + Zpos w_digits);zarith. + rewrite Zpower_exp;zarith. rewrite Zmult_assoc. fold wB. + repeat rewrite Zplus_assoc. rewrite <- Zmult_plus_distr_l. + repeat rewrite <- Zplus_assoc. + unfold base;rewrite Zmod_shift_r with (b:= Zpos (ww_digits w_digits)); + fold wB;fold wwB;zarith. + unfold base;rewrite Zmod_shift_r with (a:= Zpos w_digits) + (b:= Zpos w_digits);fold wB;fold wwB;zarith. + rewrite wwB_wBwB; rewrite Zpower_2; rewrite Zmult_mod_distr_r;zarith. + rewrite Zmult_plus_distr_l. + replace ([|xh|] * wB * 2 ^ u) with + ([|xh|]*2^u*wB). 2:ring. + repeat rewrite <- Zplus_assoc. + rewrite (Zplus_comm ([|xh|] * 2 ^ u * wB)). + rewrite Z_mod_plus;zarith. rewrite Z_mod_mult;zarith. + unfold base;rewrite <- Zmod_shift_r;zarith. fold base;apply Z_mod_lt;zarith. + unfold u; split;zarith. + split;zarith. unfold u; apply Zdiv_lt_upper_bound;zarith. + rewrite <- Zpower_exp;zarith. + fold u. + ring_simplify (u + (Zpos w_digits - u)); fold + wB;zarith. unfold ww_digits;rewrite Zpos_xO;zarith. + unfold base;rewrite <- Zmod_shift_r;zarith. fold base;apply Z_mod_lt;zarith. + unfold u; split;zarith. + unfold u; split;zarith. + apply Zdiv_lt_upper_bound;zarith. + rewrite <- Zpower_exp;zarith. + fold u. + ring_simplify (u + (Zpos w_digits - u)); fold wB; auto with zarith. + unfold u;zarith. + unfold u;zarith. + set (u := [[p]] - Zpos w_digits). + ring_simplify (u + (Zpos w_digits - u)); fold wB; auto with zarith. + Qed. + + Lemma spec_ww_add_mul_div : forall x y p, + [[p]] <= Zpos (xO w_digits) -> + [[ ww_add_mul_div p x y ]] = + ([[x]] * (2^[[p]]) + + [[y]] / (2^(Zpos (xO w_digits) - [[p]]))) mod wwB. + Proof. + clear spec_ww_zdigits. + intros x y p H. + destruct x as [ |xh xl]; + [assert (H1 := @spec_ww_add_mul_div_aux w_0 w_0) + |assert (H1 := @spec_ww_add_mul_div_aux xh xl)]; + (destruct y as [ |yh yl]; + [generalize (H1 w_0 w_0 p H) | generalize (H1 yh yl p H)]; + clear H1;w_rewrite);simpl ww_add_mul_div. + replace [[WW w_0 w_0]] with 0;[w_rewrite|simpl;w_rewrite;trivial]. + intros Heq;rewrite <- Heq;clear Heq; auto. + generalize (spec_ww_compare p (w_0W w_zdigits)); + case ww_compare; intros H1; w_rewrite. + rewrite (spec_w_add_mul_div w_0 w_0);w_rewrite;zarith. + generalize H1; w_rewrite; rewrite spec_zdigits; clear H1; intros H1. + assert (HH0: [|low p|] = [[p]]). + rewrite spec_low. + apply Zmod_small. + case (spec_to_w_Z p); intros HH1 HH2; split; auto. + apply Zlt_le_trans with (1 := H1). + unfold base; apply Zpower2_le_lin; auto with zarith. + rewrite HH0; auto with zarith. + replace [[WW w_0 w_0]] with 0;[w_rewrite|simpl;w_rewrite;trivial]. + intros Heq;rewrite <- Heq;clear Heq. + generalize (spec_ww_compare p (w_0W w_zdigits)); + case ww_compare; intros H1; w_rewrite. + rewrite (spec_w_add_mul_div w_0 w_0);w_rewrite;zarith. + rewrite Zpos_xO in H;zarith. + assert (HH: [|low (ww_sub p (w_0W w_zdigits)) |] = [[p]] - Zpos w_digits). + generalize H1; clear H1. + rewrite spec_low. + rewrite spec_ww_sub; w_rewrite; intros H1. + rewrite <- Zmod_div_mod; auto with zarith. + rewrite Zmod_small; auto with zarith. + split; auto with zarith. + apply Zle_lt_trans with (Zpos w_digits); auto with zarith. + unfold base; apply Zpower2_lt_lin; auto with zarith. + unfold base; auto with zarith. + unfold base; auto with zarith. + exists wB; unfold base. + unfold ww_digits; rewrite (Zpos_xO w_digits). + rewrite <- Zpower_exp; auto with zarith. + apply f_equal with (f := fun x => 2 ^ x); auto with zarith. + case (spec_to_Z xh); auto with zarith. + Qed. + + End DoubleProof. + +End DoubleLift. + diff --git a/theories/Numbers/Cyclic/DoubleCyclic/DoubleMul.v b/theories/Numbers/Cyclic/DoubleCyclic/DoubleMul.v new file mode 100644 index 00000000..c7d83acc --- /dev/null +++ b/theories/Numbers/Cyclic/DoubleCyclic/DoubleMul.v @@ -0,0 +1,628 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: DoubleMul.v 10964 2008-05-22 11:08:13Z letouzey $ i*) + +Set Implicit Arguments. + +Require Import ZArith. +Require Import BigNumPrelude. +Require Import DoubleType. +Require Import DoubleBase. + +Open Local Scope Z_scope. + +Section DoubleMul. + Variable w : Type. + Variable w_0 : w. + Variable w_1 : w. + Variable w_WW : w -> w -> zn2z w. + Variable w_W0 : w -> zn2z w. + Variable w_0W : w -> zn2z w. + Variable w_compare : w -> w -> comparison. + Variable w_succ : w -> w. + Variable w_add_c : w -> w -> carry w. + Variable w_add : w -> w -> w. + Variable w_sub: w -> w -> w. + Variable w_mul_c : w -> w -> zn2z w. + Variable w_mul : w -> w -> w. + Variable w_square_c : w -> zn2z w. + Variable ww_add_c : zn2z w -> zn2z w -> carry (zn2z w). + Variable ww_add : zn2z w -> zn2z w -> zn2z w. + Variable ww_add_carry : zn2z w -> zn2z w -> zn2z w. + Variable ww_sub_c : zn2z w -> zn2z w -> carry (zn2z w). + Variable ww_sub : zn2z w -> zn2z w -> zn2z w. + + (* ** Multiplication ** *) + + (* (xh*B+xl) (yh*B + yl) + xh*yh = hh = |hhh|hhl|B2 + xh*yl +xl*yh = cc = |cch|ccl|B + xl*yl = ll = |llh|lll + *) + + Definition double_mul_c (cross:w->w->w->w->zn2z w -> zn2z w -> w*zn2z w) x y := + match x, y with + | W0, _ => W0 + | _, W0 => W0 + | WW xh xl, WW yh yl => + let hh := w_mul_c xh yh in + let ll := w_mul_c xl yl in + let (wc,cc) := cross xh xl yh yl hh ll in + match cc with + | W0 => WW (ww_add hh (w_W0 wc)) ll + | WW cch ccl => + match ww_add_c (w_W0 ccl) ll with + | C0 l => WW (ww_add hh (w_WW wc cch)) l + | C1 l => WW (ww_add_carry hh (w_WW wc cch)) l + end + end + end. + + Definition ww_mul_c := + double_mul_c + (fun xh xl yh yl hh ll=> + match ww_add_c (w_mul_c xh yl) (w_mul_c xl yh) with + | C0 cc => (w_0, cc) + | C1 cc => (w_1, cc) + end). + + Definition w_2 := w_add w_1 w_1. + + Definition kara_prod xh xl yh yl hh ll := + match ww_add_c hh ll with + C0 m => + match w_compare xl xh with + Eq => (w_0, m) + | Lt => + match w_compare yl yh with + Eq => (w_0, m) + | Lt => (w_0, ww_sub m (w_mul_c (w_sub xh xl) (w_sub yh yl))) + | Gt => match ww_add_c m (w_mul_c (w_sub xh xl) (w_sub yl yh)) with + C1 m1 => (w_1, m1) | C0 m1 => (w_0, m1) + end + end + | Gt => + match w_compare yl yh with + Eq => (w_0, m) + | Lt => match ww_add_c m (w_mul_c (w_sub xl xh) (w_sub yh yl)) with + C1 m1 => (w_1, m1) | C0 m1 => (w_0, m1) + end + | Gt => (w_0, ww_sub m (w_mul_c (w_sub xl xh) (w_sub yl yh))) + end + end + | C1 m => + match w_compare xl xh with + Eq => (w_1, m) + | Lt => + match w_compare yl yh with + Eq => (w_1, m) + | Lt => match ww_sub_c m (w_mul_c (w_sub xh xl) (w_sub yh yl)) with + C0 m1 => (w_1, m1) | C1 m1 => (w_0, m1) + end + | Gt => match ww_add_c m (w_mul_c (w_sub xh xl) (w_sub yl yh)) with + C1 m1 => (w_2, m1) | C0 m1 => (w_1, m1) + end + end + | Gt => + match w_compare yl yh with + Eq => (w_1, m) + | Lt => match ww_add_c m (w_mul_c (w_sub xl xh) (w_sub yh yl)) with + C1 m1 => (w_2, m1) | C0 m1 => (w_1, m1) + end + | Gt => match ww_sub_c m (w_mul_c (w_sub xl xh) (w_sub yl yh)) with + C1 m1 => (w_0, m1) | C0 m1 => (w_1, m1) + end + end + end + end. + + Definition ww_karatsuba_c := double_mul_c kara_prod. + + Definition ww_mul x y := + match x, y with + | W0, _ => W0 + | _, W0 => W0 + | WW xh xl, WW yh yl => + let ccl := w_add (w_mul xh yl) (w_mul xl yh) in + ww_add (w_W0 ccl) (w_mul_c xl yl) + end. + + Definition ww_square_c x := + match x with + | W0 => W0 + | WW xh xl => + let hh := w_square_c xh in + let ll := w_square_c xl in + let xhxl := w_mul_c xh xl in + let (wc,cc) := + match ww_add_c xhxl xhxl with + | C0 cc => (w_0, cc) + | C1 cc => (w_1, cc) + end in + match cc with + | W0 => WW (ww_add hh (w_W0 wc)) ll + | WW cch ccl => + match ww_add_c (w_W0 ccl) ll with + | C0 l => WW (ww_add hh (w_WW wc cch)) l + | C1 l => WW (ww_add_carry hh (w_WW wc cch)) l + end + end + end. + + Section DoubleMulAddn1. + Variable w_mul_add : w -> w -> w -> w * w. + + Fixpoint double_mul_add_n1 (n:nat) : word w n -> w -> w -> w * word w n := + match n return word w n -> w -> w -> w * word w n with + | O => w_mul_add + | S n1 => + let mul_add := double_mul_add_n1 n1 in + fun x y r => + match x with + | W0 => (w_0,extend w_0W n1 r) + | WW xh xl => + let (rl,l) := mul_add xl y r in + let (rh,h) := mul_add xh y rl in + (rh, double_WW w_WW n1 h l) + end + end. + + End DoubleMulAddn1. + + Section DoubleMulAddmn1. + Variable wn: Type. + Variable extend_n : w -> wn. + Variable wn_0W : wn -> zn2z wn. + Variable wn_WW : wn -> wn -> zn2z wn. + Variable w_mul_add_n1 : wn -> w -> w -> w*wn. + Fixpoint double_mul_add_mn1 (m:nat) : + word wn m -> w -> w -> w*word wn m := + match m return word wn m -> w -> w -> w*word wn m with + | O => w_mul_add_n1 + | S m1 => + let mul_add := double_mul_add_mn1 m1 in + fun x y r => + match x with + | W0 => (w_0,extend wn_0W m1 (extend_n r)) + | WW xh xl => + let (rl,l) := mul_add xl y r in + let (rh,h) := mul_add xh y rl in + (rh, double_WW wn_WW m1 h l) + end + end. + + End DoubleMulAddmn1. + + Definition w_mul_add x y r := + match w_mul_c x y with + | W0 => (w_0, r) + | WW h l => + match w_add_c l r with + | C0 lr => (h,lr) + | C1 lr => (w_succ h, lr) + end + end. + + + (*Section DoubleProof. *) + Variable w_digits : positive. + Variable w_to_Z : w -> Z. + + Notation wB := (base w_digits). + Notation wwB := (base (ww_digits w_digits)). + Notation "[| x |]" := (w_to_Z x) (at level 0, x at level 99). + Notation "[+| c |]" := + (interp_carry 1 wB w_to_Z c) (at level 0, x at level 99). + Notation "[-| c |]" := + (interp_carry (-1) wB w_to_Z c) (at level 0, x at level 99). + + Notation "[[ x ]]" := (ww_to_Z w_digits w_to_Z x)(at level 0, x at level 99). + Notation "[+[ c ]]" := + (interp_carry 1 wwB (ww_to_Z w_digits w_to_Z) c) + (at level 0, x at level 99). + Notation "[-[ c ]]" := + (interp_carry (-1) wwB (ww_to_Z w_digits w_to_Z) c) + (at level 0, x at level 99). + + Notation "[|| x ||]" := + (zn2z_to_Z wwB (ww_to_Z w_digits w_to_Z) x) (at level 0, x at level 99). + + Notation "[! n | x !]" := (double_to_Z w_digits w_to_Z n x) + (at level 0, x at level 99). + + Variable spec_more_than_1_digit: 1 < Zpos w_digits. + Variable spec_w_0 : [|w_0|] = 0. + Variable spec_w_1 : [|w_1|] = 1. + + Variable spec_to_Z : forall x, 0 <= [|x|] < wB. + + Variable spec_w_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|]. + Variable spec_w_W0 : forall h, [[w_W0 h]] = [|h|] * wB. + Variable spec_w_0W : forall l, [[w_0W l]] = [|l|]. + Variable spec_w_compare : + forall x y, + match w_compare x y with + | Eq => [|x|] = [|y|] + | Lt => [|x|] < [|y|] + | Gt => [|x|] > [|y|] + end. + Variable spec_w_succ : forall x, [|w_succ x|] = ([|x|] + 1) mod wB. + Variable spec_w_add_c : forall x y, [+|w_add_c x y|] = [|x|] + [|y|]. + Variable spec_w_add : forall x y, [|w_add x y|] = ([|x|] + [|y|]) mod wB. + Variable spec_w_sub : forall x y, [|w_sub x y|] = ([|x|] - [|y|]) mod wB. + + Variable spec_w_mul_c : forall x y, [[ w_mul_c x y ]] = [|x|] * [|y|]. + Variable spec_w_mul : forall x y, [|w_mul x y|] = ([|x|] * [|y|]) mod wB. + Variable spec_w_square_c : forall x, [[ w_square_c x]] = [|x|] * [|x|]. + + Variable spec_ww_add_c : forall x y, [+[ww_add_c x y]] = [[x]] + [[y]]. + Variable spec_ww_add : forall x y, [[ww_add x y]] = ([[x]] + [[y]]) mod wwB. + Variable spec_ww_add_carry : + forall x y, [[ww_add_carry x y]] = ([[x]] + [[y]] + 1) mod wwB. + Variable spec_ww_sub : forall x y, [[ww_sub x y]] = ([[x]] - [[y]]) mod wwB. + Variable spec_ww_sub_c : forall x y, [-[ww_sub_c x y]] = [[x]] - [[y]]. + + + Lemma spec_ww_to_Z : forall x, 0 <= [[x]] < wwB. + Proof. intros x;apply spec_ww_to_Z;auto. Qed. + + Lemma spec_ww_to_Z_wBwB : forall x, 0 <= [[x]] < wB^2. + Proof. rewrite <- wwB_wBwB;apply spec_ww_to_Z. Qed. + + Hint Resolve spec_ww_to_Z spec_ww_to_Z_wBwB : mult. + Ltac zarith := auto with zarith mult. + + Lemma wBwB_lex: forall a b c d, + a * wB^2 + [[b]] <= c * wB^2 + [[d]] -> + a <= c. + Proof. + intros a b c d H; apply beta_lex with [[b]] [[d]] (wB^2);zarith. + Qed. + + Lemma wBwB_lex_inv: forall a b c d, + a < c -> + a * wB^2 + [[b]] < c * wB^2 + [[d]]. + Proof. + intros a b c d H; apply beta_lex_inv; zarith. + Qed. + + Lemma sum_mul_carry : forall xh xl yh yl wc cc, + [|wc|]*wB^2 + [[cc]] = [|xh|] * [|yl|] + [|xl|] * [|yh|] -> + 0 <= [|wc|] <= 1. + Proof. + intros. + apply (sum_mul_carry [|xh|] [|xl|] [|yh|] [|yl|] [|wc|][[cc]] wB);zarith. + apply wB_pos. + Qed. + + Theorem mult_add_ineq: forall xH yH crossH, + 0 <= [|xH|] * [|yH|] + [|crossH|] < wwB. + Proof. + intros;rewrite wwB_wBwB;apply mult_add_ineq;zarith. + Qed. + + Hint Resolve mult_add_ineq : mult. + + Lemma spec_mul_aux : forall xh xl yh yl wc (cc:zn2z w) hh ll, + [[hh]] = [|xh|] * [|yh|] -> + [[ll]] = [|xl|] * [|yl|] -> + [|wc|]*wB^2 + [[cc]] = [|xh|] * [|yl|] + [|xl|] * [|yh|] -> + [||match cc with + | W0 => WW (ww_add hh (w_W0 wc)) ll + | WW cch ccl => + match ww_add_c (w_W0 ccl) ll with + | C0 l => WW (ww_add hh (w_WW wc cch)) l + | C1 l => WW (ww_add_carry hh (w_WW wc cch)) l + end + end||] = ([|xh|] * wB + [|xl|]) * ([|yh|] * wB + [|yl|]). + Proof. + intros;assert (U1 := wB_pos w_digits). + replace (([|xh|] * wB + [|xl|]) * ([|yh|] * wB + [|yl|])) with + ([|xh|]*[|yh|]*wB^2 + ([|xh|]*[|yl|] + [|xl|]*[|yh|])*wB + [|xl|]*[|yl|]). + 2:ring. rewrite <- H1;rewrite <- H;rewrite <- H0. + assert (H2 := sum_mul_carry _ _ _ _ _ _ H1). + destruct cc as [ | cch ccl]; simpl zn2z_to_Z; simpl ww_to_Z. + rewrite spec_ww_add;rewrite spec_w_W0;rewrite Zmod_small; + rewrite wwB_wBwB. ring. + rewrite <- (Zplus_0_r ([|wc|]*wB));rewrite H;apply mult_add_ineq3;zarith. + simpl ww_to_Z in H1. assert (U:=spec_to_Z cch). + assert ([|wc|]*wB + [|cch|] <= 2*wB - 3). + destruct (Z_le_gt_dec ([|wc|]*wB + [|cch|]) (2*wB - 3));trivial. + assert ([|xh|] * [|yl|] + [|xl|] * [|yh|] <= (2*wB - 4)*wB + 2). + ring_simplify ((2*wB - 4)*wB + 2). + assert (H4 := Zmult_lt_b _ _ _ (spec_to_Z xh) (spec_to_Z yl)). + assert (H5 := Zmult_lt_b _ _ _ (spec_to_Z xl) (spec_to_Z yh)). + omega. + generalize H3;clear H3;rewrite <- H1. + rewrite Zplus_assoc; rewrite Zpower_2; rewrite Zmult_assoc; + rewrite <- Zmult_plus_distr_l. + assert (((2 * wB - 4) + 2)*wB <= ([|wc|] * wB + [|cch|])*wB). + apply Zmult_le_compat;zarith. + rewrite Zmult_plus_distr_l in H3. + intros. assert (U2 := spec_to_Z ccl);omega. + generalize (spec_ww_add_c (w_W0 ccl) ll);destruct (ww_add_c (w_W0 ccl) ll) + as [l|l];unfold interp_carry;rewrite spec_w_W0;try rewrite Zmult_1_l; + simpl zn2z_to_Z; + try rewrite spec_ww_add;try rewrite spec_ww_add_carry;rewrite spec_w_WW; + rewrite Zmod_small;rewrite wwB_wBwB;intros. + rewrite H4;ring. rewrite H;apply mult_add_ineq2;zarith. + rewrite Zplus_assoc;rewrite Zmult_plus_distr_l. + rewrite Zmult_1_l;rewrite <- Zplus_assoc;rewrite H4;ring. + repeat rewrite <- Zplus_assoc;rewrite H;apply mult_add_ineq2;zarith. + Qed. + + Lemma spec_double_mul_c : forall cross:w->w->w->w->zn2z w -> zn2z w -> w*zn2z w, + (forall xh xl yh yl hh ll, + [[hh]] = [|xh|]*[|yh|] -> + [[ll]] = [|xl|]*[|yl|] -> + let (wc,cc) := cross xh xl yh yl hh ll in + [|wc|]*wwB + [[cc]] = [|xh|]*[|yl|] + [|xl|]*[|yh|]) -> + forall x y, [||double_mul_c cross x y||] = [[x]] * [[y]]. + Proof. + intros cross Hcross x y;destruct x as [ |xh xl];simpl;trivial. + destruct y as [ |yh yl];simpl. rewrite Zmult_0_r;trivial. + assert (H1:= spec_w_mul_c xh yh);assert (H2:= spec_w_mul_c xl yl). + generalize (Hcross _ _ _ _ _ _ H1 H2). + destruct (cross xh xl yh yl (w_mul_c xh yh) (w_mul_c xl yl)) as (wc,cc). + intros;apply spec_mul_aux;trivial. + rewrite <- wwB_wBwB;trivial. + Qed. + + Lemma spec_ww_mul_c : forall x y, [||ww_mul_c x y||] = [[x]] * [[y]]. + Proof. + intros x y;unfold ww_mul_c;apply spec_double_mul_c. + intros xh xl yh yl hh ll H1 H2. + generalize (spec_ww_add_c (w_mul_c xh yl) (w_mul_c xl yh)); + destruct (ww_add_c (w_mul_c xh yl) (w_mul_c xl yh)) as [c|c]; + unfold interp_carry;repeat rewrite spec_w_mul_c;intros H; + (rewrite spec_w_0 || rewrite spec_w_1);rewrite H;ring. + Qed. + + Lemma spec_w_2: [|w_2|] = 2. + unfold w_2; rewrite spec_w_add; rewrite spec_w_1; simpl. + apply Zmod_small; split; auto with zarith. + rewrite <- (Zpower_1_r 2); unfold base; apply Zpower_lt_monotone; auto with zarith. + Qed. + + Lemma kara_prod_aux : forall xh xl yh yl, + xh*yh + xl*yl - (xh-xl)*(yh-yl) = xh*yl + xl*yh. + Proof. intros;ring. Qed. + + Lemma spec_kara_prod : forall xh xl yh yl hh ll, + [[hh]] = [|xh|]*[|yh|] -> + [[ll]] = [|xl|]*[|yl|] -> + let (wc,cc) := kara_prod xh xl yh yl hh ll in + [|wc|]*wwB + [[cc]] = [|xh|]*[|yl|] + [|xl|]*[|yh|]. + Proof. + intros xh xl yh yl hh ll H H0; rewrite <- kara_prod_aux; + rewrite <- H; rewrite <- H0; unfold kara_prod. + assert (Hxh := (spec_to_Z xh)); assert (Hxl := (spec_to_Z xl)); + assert (Hyh := (spec_to_Z yh)); assert (Hyl := (spec_to_Z yl)). + generalize (spec_ww_add_c hh ll); case (ww_add_c hh ll); + intros z Hz; rewrite <- Hz; unfold interp_carry; assert (Hz1 := (spec_ww_to_Z z)). + generalize (spec_w_compare xl xh); case (w_compare xl xh); intros Hxlh; + try rewrite Hxlh; try rewrite spec_w_0; try (ring; fail). + generalize (spec_w_compare yl yh); case (w_compare yl yh); intros Hylh. + rewrite Hylh; rewrite spec_w_0; try (ring; fail). + rewrite spec_w_0; try (ring; fail). + repeat (rewrite spec_ww_sub || rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + split; auto with zarith. + simpl in Hz; rewrite Hz; rewrite H; rewrite H0. + rewrite kara_prod_aux; apply Zplus_le_0_compat; apply Zmult_le_0_compat; auto with zarith. + apply Zle_lt_trans with ([[z]]-0); auto with zarith. + unfold Zminus; apply Zplus_le_compat_l; apply Zle_left_rev; simpl; rewrite Zopp_involutive. + apply Zmult_le_0_compat; auto with zarith. + match goal with |- context[ww_add_c ?x ?y] => + generalize (spec_ww_add_c x y); case (ww_add_c x y); try rewrite spec_w_0; + intros z1 Hz2 + end. + simpl in Hz2; rewrite Hz2; repeat (rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + rewrite spec_w_1; unfold interp_carry in Hz2; rewrite Hz2; + repeat (rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + generalize (spec_w_compare yl yh); case (w_compare yl yh); intros Hylh. + rewrite Hylh; rewrite spec_w_0; try (ring; fail). + match goal with |- context[ww_add_c ?x ?y] => + generalize (spec_ww_add_c x y); case (ww_add_c x y); try rewrite spec_w_0; + intros z1 Hz2 + end. + simpl in Hz2; rewrite Hz2; repeat (rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + rewrite spec_w_1; unfold interp_carry in Hz2; rewrite Hz2; + repeat (rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + rewrite spec_w_0; try (ring; fail). + repeat (rewrite spec_ww_sub || rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + split. + match goal with |- context[(?x - ?y) * (?z - ?t)] => + replace ((x - y) * (z - t)) with ((y - x) * (t - z)); [idtac | ring] + end. + simpl in Hz; rewrite Hz; rewrite H; rewrite H0. + rewrite kara_prod_aux; apply Zplus_le_0_compat; apply Zmult_le_0_compat; auto with zarith. + apply Zle_lt_trans with ([[z]]-0); auto with zarith. + unfold Zminus; apply Zplus_le_compat_l; apply Zle_left_rev; simpl; rewrite Zopp_involutive. + apply Zmult_le_0_compat; auto with zarith. + (** there is a carry in hh + ll **) + rewrite Zmult_1_l. + generalize (spec_w_compare xl xh); case (w_compare xl xh); intros Hxlh; + try rewrite Hxlh; try rewrite spec_w_1; try (ring; fail). + generalize (spec_w_compare yl yh); case (w_compare yl yh); intros Hylh; + try rewrite Hylh; try rewrite spec_w_1; try (ring; fail). + match goal with |- context[ww_sub_c ?x ?y] => + generalize (spec_ww_sub_c x y); case (ww_sub_c x y); try rewrite spec_w_1; + intros z1 Hz2 + end. + simpl in Hz2; rewrite Hz2; repeat (rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + rewrite spec_w_0; rewrite Zmult_0_l; rewrite Zplus_0_l. + generalize Hz2; clear Hz2; unfold interp_carry. + repeat (rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + match goal with |- context[ww_add_c ?x ?y] => + generalize (spec_ww_add_c x y); case (ww_add_c x y); try rewrite spec_w_1; + intros z1 Hz2 + end. + simpl in Hz2; rewrite Hz2; repeat (rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + rewrite spec_w_2; unfold interp_carry in Hz2. + apply trans_equal with (wwB + (1 * wwB + [[z1]])). + ring. + rewrite Hz2; repeat (rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + generalize (spec_w_compare yl yh); case (w_compare yl yh); intros Hylh; + try rewrite Hylh; try rewrite spec_w_1; try (ring; fail). + match goal with |- context[ww_add_c ?x ?y] => + generalize (spec_ww_add_c x y); case (ww_add_c x y); try rewrite spec_w_1; + intros z1 Hz2 + end. + simpl in Hz2; rewrite Hz2; repeat (rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + rewrite spec_w_2; unfold interp_carry in Hz2. + apply trans_equal with (wwB + (1 * wwB + [[z1]])). + ring. + rewrite Hz2; repeat (rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + match goal with |- context[ww_sub_c ?x ?y] => + generalize (spec_ww_sub_c x y); case (ww_sub_c x y); try rewrite spec_w_1; + intros z1 Hz2 + end. + simpl in Hz2; rewrite Hz2; repeat (rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + rewrite spec_w_0; rewrite Zmult_0_l; rewrite Zplus_0_l. + match goal with |- context[(?x - ?y) * (?z - ?t)] => + replace ((x - y) * (z - t)) with ((y - x) * (t - z)); [idtac | ring] + end. + generalize Hz2; clear Hz2; unfold interp_carry. + repeat (rewrite spec_w_sub || rewrite spec_w_mul_c). + repeat rewrite Zmod_small; auto with zarith; try (ring; fail). + Qed. + + Lemma sub_carry : forall xh xl yh yl z, + 0 <= z -> + [|xh|]*[|yl|] + [|xl|]*[|yh|] = wwB + z -> + z < wwB. + Proof. + intros xh xl yh yl z Hle Heq. + destruct (Z_le_gt_dec wwB z);auto with zarith. + generalize (Zmult_lt_b _ _ _ (spec_to_Z xh) (spec_to_Z yl)). + generalize (Zmult_lt_b _ _ _ (spec_to_Z xl) (spec_to_Z yh)). + rewrite <- wwB_wBwB;intros H1 H2. + assert (H3 := wB_pos w_digits). + assert (2*wB <= wwB). + rewrite wwB_wBwB; rewrite Zpower_2; apply Zmult_le_compat;zarith. + omega. + Qed. + + Ltac Spec_ww_to_Z x := + let H:= fresh "H" in + assert (H:= spec_ww_to_Z x). + + Ltac Zmult_lt_b x y := + let H := fresh "H" in + assert (H := Zmult_lt_b _ _ _ (spec_to_Z x) (spec_to_Z y)). + + Lemma spec_ww_karatsuba_c : forall x y, [||ww_karatsuba_c x y||]=[[x]]*[[y]]. + Proof. + intros x y; unfold ww_karatsuba_c;apply spec_double_mul_c. + intros; apply spec_kara_prod; auto. + Qed. + + Lemma spec_ww_mul : forall x y, [[ww_mul x y]] = [[x]]*[[y]] mod wwB. + Proof. + assert (U:= lt_0_wB w_digits). + assert (U1:= lt_0_wwB w_digits). + intros x y; case x; auto; intros xh xl. + case y; auto. + simpl; rewrite Zmult_0_r; rewrite Zmod_small; auto with zarith. + intros yh yl;simpl. + repeat (rewrite spec_ww_add || rewrite spec_w_W0 || rewrite spec_w_mul_c + || rewrite spec_w_add || rewrite spec_w_mul). + rewrite <- Zplus_mod; auto with zarith. + repeat (rewrite Zmult_plus_distr_l || rewrite Zmult_plus_distr_r). + rewrite <- Zmult_mod_distr_r; auto with zarith. + rewrite <- Zpower_2; rewrite <- wwB_wBwB; auto with zarith. + rewrite Zplus_mod; auto with zarith. + rewrite Zmod_mod; auto with zarith. + rewrite <- Zplus_mod; auto with zarith. + match goal with |- ?X mod _ = _ => + rewrite <- Z_mod_plus with (a := X) (b := [|xh|] * [|yh|]) + end; auto with zarith. + f_equal; auto; rewrite wwB_wBwB; ring. + Qed. + + Lemma spec_ww_square_c : forall x, [||ww_square_c x||] = [[x]]*[[x]]. + Proof. + destruct x as [ |xh xl];simpl;trivial. + case_eq match ww_add_c (w_mul_c xh xl) (w_mul_c xh xl) with + | C0 cc => (w_0, cc) + | C1 cc => (w_1, cc) + end;intros wc cc Heq. + apply (spec_mul_aux xh xl xh xl wc cc);trivial. + generalize Heq (spec_ww_add_c (w_mul_c xh xl) (w_mul_c xh xl));clear Heq. + rewrite spec_w_mul_c;destruct (ww_add_c (w_mul_c xh xl) (w_mul_c xh xl)); + unfold interp_carry;try rewrite Zmult_1_l;intros Heq Heq';inversion Heq; + rewrite (Zmult_comm [|xl|]);subst. + rewrite spec_w_0;rewrite Zmult_0_l;rewrite Zplus_0_l;trivial. + rewrite spec_w_1;rewrite Zmult_1_l;rewrite <- wwB_wBwB;trivial. + Qed. + + Section DoubleMulAddn1Proof. + + Variable w_mul_add : w -> w -> w -> w * w. + Variable spec_w_mul_add : forall x y r, + let (h,l):= w_mul_add x y r in + [|h|]*wB+[|l|] = [|x|]*[|y|] + [|r|]. + + Lemma spec_double_mul_add_n1 : forall n x y r, + let (h,l) := double_mul_add_n1 w_mul_add n x y r in + [|h|]*double_wB w_digits n + [!n|l!] = [!n|x!]*[|y|]+[|r|]. + Proof. + induction n;intros x y r;trivial. + exact (spec_w_mul_add x y r). + unfold double_mul_add_n1;destruct x as[ |xh xl]; + fold(double_mul_add_n1 w_mul_add). + rewrite spec_w_0;rewrite spec_extend;simpl;trivial. + assert(H:=IHn xl y r);destruct (double_mul_add_n1 w_mul_add n xl y r)as(rl,l). + assert(U:=IHn xh y rl);destruct(double_mul_add_n1 w_mul_add n xh y rl)as(rh,h). + rewrite <- double_wB_wwB. rewrite spec_double_WW;simpl;trivial. + rewrite Zmult_plus_distr_l;rewrite <- Zplus_assoc;rewrite <- H. + rewrite Zmult_assoc;rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. + rewrite U;ring. + Qed. + + End DoubleMulAddn1Proof. + + Lemma spec_w_mul_add : forall x y r, + let (h,l):= w_mul_add x y r in + [|h|]*wB+[|l|] = [|x|]*[|y|] + [|r|]. + Proof. + intros x y r;unfold w_mul_add;assert (H:=spec_w_mul_c x y); + destruct (w_mul_c x y) as [ |h l];simpl;rewrite <- H. + rewrite spec_w_0;trivial. + assert (U:=spec_w_add_c l r);destruct (w_add_c l r) as [lr|lr];unfold + interp_carry in U;try rewrite Zmult_1_l in H;simpl. + rewrite U;ring. rewrite spec_w_succ. rewrite Zmod_small. + rewrite <- Zplus_assoc;rewrite <- U;ring. + simpl in H;assert (H1:= Zmult_lt_b _ _ _ (spec_to_Z x) (spec_to_Z y)). + rewrite <- H in H1. + assert (H2:=spec_to_Z h);split;zarith. + case H1;clear H1;intro H1;clear H1. + replace (wB ^ 2 - 2 * wB) with ((wB - 2)*wB). 2:ring. + intros H0;assert (U1:= wB_pos w_digits). + assert (H1 := beta_lex _ _ _ _ _ H0 (spec_to_Z l));zarith. + Qed. + +(* End DoubleProof. *) + +End DoubleMul. diff --git a/theories/Numbers/Cyclic/DoubleCyclic/DoubleSqrt.v b/theories/Numbers/Cyclic/DoubleCyclic/DoubleSqrt.v new file mode 100644 index 00000000..043ff351 --- /dev/null +++ b/theories/Numbers/Cyclic/DoubleCyclic/DoubleSqrt.v @@ -0,0 +1,1389 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: DoubleSqrt.v 10964 2008-05-22 11:08:13Z letouzey $ i*) + +Set Implicit Arguments. + +Require Import ZArith. +Require Import BigNumPrelude. +Require Import DoubleType. +Require Import DoubleBase. + +Open Local Scope Z_scope. + +Section DoubleSqrt. + Variable w : Type. + Variable w_is_even : w -> bool. + Variable w_compare : w -> w -> comparison. + Variable w_0 : w. + Variable w_1 : w. + Variable w_Bm1 : w. + Variable w_WW : w -> w -> zn2z w. + Variable w_W0 : w -> zn2z w. + Variable w_0W : w -> zn2z w. + Variable w_sub : w -> w -> w. + Variable w_sub_c : w -> w -> carry w. + Variable w_square_c : w -> zn2z w. + Variable w_div21 : w -> w -> w -> w * w. + Variable w_add_mul_div : w -> w -> w -> w. + Variable w_digits : positive. + Variable w_zdigits : w. + Variable ww_zdigits : zn2z w. + Variable w_add_c : w -> w -> carry w. + Variable w_sqrt2 : w -> w -> w * carry w. + Variable w_pred : w -> w. + Variable ww_pred_c : zn2z w -> carry (zn2z w). + Variable ww_pred : zn2z w -> zn2z w. + Variable ww_add_c : zn2z w -> zn2z w -> carry (zn2z w). + Variable ww_add : zn2z w -> zn2z w -> zn2z w. + Variable ww_sub_c : zn2z w -> zn2z w -> carry (zn2z w). + Variable ww_add_mul_div : zn2z w -> zn2z w -> zn2z w -> zn2z w. + Variable ww_head0 : zn2z w -> zn2z w. + Variable ww_compare : zn2z w -> zn2z w -> comparison. + Variable low : zn2z w -> w. + + Let wwBm1 := ww_Bm1 w_Bm1. + + Definition ww_is_even x := + match x with + | W0 => true + | WW xh xl => w_is_even xl + end. + + Let w_div21c x y z := + match w_compare x z with + | Eq => + match w_compare y z with + Eq => (C1 w_1, w_0) + | Gt => (C1 w_1, w_sub y z) + | Lt => (C1 w_0, y) + end + | Gt => + let x1 := w_sub x z in + let (q, r) := w_div21 x1 y z in + (C1 q, r) + | Lt => + let (q, r) := w_div21 x y z in + (C0 q, r) + end. + + Let w_div2s x y s := + match x with + C1 x1 => + let x2 := w_sub x1 s in + let (q, r) := w_div21c x2 y s in + match q with + C0 q1 => + if w_is_even q1 then + (C0 (w_add_mul_div (w_pred w_zdigits) w_1 q1), C0 r) + else + (C0 (w_add_mul_div (w_pred w_zdigits) w_1 q1), w_add_c r s) + | C1 q1 => + if w_is_even q1 then + (C1 (w_add_mul_div (w_pred w_zdigits) w_0 q1), C0 r) + else + (C1 (w_add_mul_div (w_pred w_zdigits) w_0 q1), w_add_c r s) + end + | C0 x1 => + let (q, r) := w_div21c x1 y s in + match q with + C0 q1 => + if w_is_even q1 then + (C0 (w_add_mul_div (w_pred w_zdigits) w_0 q1), C0 r) + else + (C0 (w_add_mul_div (w_pred w_zdigits) w_0 q1), w_add_c r s) + | C1 q1 => + if w_is_even q1 then + (C0 (w_add_mul_div (w_pred w_zdigits) w_1 q1), C0 r) + else + (C0 (w_add_mul_div (w_pred w_zdigits) w_1 q1), w_add_c r s) + end + end. + + Definition split x := + match x with + | W0 => (w_0,w_0) + | WW h l => (h,l) + end. + + Definition ww_sqrt2 x y := + let (x1, x2) := split x in + let (y1, y2) := split y in + let ( q, r) := w_sqrt2 x1 x2 in + let (q1, r1) := w_div2s r y1 q in + match q1 with + C0 q1 => + let q2 := w_square_c q1 in + let a := WW q q1 in + match r1 with + C1 r2 => + match ww_sub_c (WW r2 y2) q2 with + C0 r3 => (a, C1 r3) + | C1 r3 => (a, C0 r3) + end + | C0 r2 => + match ww_sub_c (WW r2 y2) q2 with + C0 r3 => (a, C0 r3) + | C1 r3 => + let a2 := ww_add_mul_div (w_0W w_1) a W0 in + match ww_pred_c a2 with + C0 a3 => + (ww_pred a, ww_add_c a3 r3) + | C1 a3 => + (ww_pred a, C0 (ww_add a3 r3)) + end + end + end + | C1 q1 => + let a1 := WW q w_Bm1 in + let a2 := ww_add_mul_div (w_0W w_1) a1 wwBm1 in + (a1, ww_add_c a2 y) + end. + + Definition ww_is_zero x := + match ww_compare W0 x with + Eq => true + | _ => false + end. + + Definition ww_head1 x := + let p := ww_head0 x in + if (ww_is_even p) then p else ww_pred p. + + Definition ww_sqrt x := + if (ww_is_zero x) then W0 + else + let p := ww_head1 x in + match ww_compare p W0 with + | Gt => + match ww_add_mul_div p x W0 with + W0 => W0 + | WW x1 x2 => + let (r, _) := w_sqrt2 x1 x2 in + WW w_0 (w_add_mul_div + (w_sub w_zdigits + (low (ww_add_mul_div (ww_pred ww_zdigits) + W0 p))) w_0 r) + end + | _ => + match x with + W0 => W0 + | WW x1 x2 => WW w_0 (fst (w_sqrt2 x1 x2)) + end + end. + + + Variable w_to_Z : w -> Z. + + Notation wB := (base w_digits). + Notation wwB := (base (ww_digits w_digits)). + Notation "[| x |]" := (w_to_Z x) (at level 0, x at level 99). + Notation "[+| c |]" := + (interp_carry 1 wB w_to_Z c) (at level 0, x at level 99). + Notation "[-| c |]" := + (interp_carry (-1) wB w_to_Z c) (at level 0, x at level 99). + + Notation "[[ x ]]" := (ww_to_Z w_digits w_to_Z x)(at level 0, x at level 99). + Notation "[+[ c ]]" := + (interp_carry 1 wwB (ww_to_Z w_digits w_to_Z) c) + (at level 0, x at level 99). + Notation "[-[ c ]]" := + (interp_carry (-1) wwB (ww_to_Z w_digits w_to_Z) c) + (at level 0, x at level 99). + + Notation "[|| x ||]" := + (zn2z_to_Z wwB (ww_to_Z w_digits w_to_Z) x) (at level 0, x at level 99). + + Notation "[! n | x !]" := (double_to_Z w_digits w_to_Z n x) + (at level 0, x at level 99). + + Variable spec_w_0 : [|w_0|] = 0. + Variable spec_w_1 : [|w_1|] = 1. + Variable spec_w_Bm1 : [|w_Bm1|] = wB - 1. + Variable spec_w_zdigits : [|w_zdigits|] = Zpos w_digits. + Variable spec_more_than_1_digit: 1 < Zpos w_digits. + + Variable spec_ww_zdigits : [[ww_zdigits]] = Zpos (xO w_digits). + Variable spec_to_Z : forall x, 0 <= [|x|] < wB. + Variable spec_to_w_Z : forall x, 0 <= [[x]] < wwB. + + Variable spec_w_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|]. + Variable spec_w_W0 : forall h, [[w_W0 h]] = [|h|] * wB. + Variable spec_w_0W : forall l, [[w_0W l]] = [|l|]. + Variable spec_w_is_even : forall x, + if w_is_even x then [|x|] mod 2 = 0 else [|x|] mod 2 = 1. + Variable spec_w_compare : forall x y, + match w_compare x y with + | Eq => [|x|] = [|y|] + | Lt => [|x|] < [|y|] + | Gt => [|x|] > [|y|] + end. + Variable spec_w_sub : forall x y, [|w_sub x y|] = ([|x|] - [|y|]) mod wB. + Variable spec_w_square_c : forall x, [[ w_square_c x]] = [|x|] * [|x|]. + Variable spec_w_div21 : forall a1 a2 b, + wB/2 <= [|b|] -> + [|a1|] < [|b|] -> + let (q,r) := w_div21 a1 a2 b in + [|a1|] *wB+ [|a2|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]. + Variable spec_w_add_mul_div : forall x y p, + [|p|] <= Zpos w_digits -> + [| w_add_mul_div p x y |] = + ([|x|] * (2 ^ [|p|]) + + [|y|] / (Zpower 2 ((Zpos w_digits) - [|p|]))) mod wB. + Variable spec_ww_add_mul_div : forall x y p, + [[p]] <= Zpos (xO w_digits) -> + [[ ww_add_mul_div p x y ]] = + ([[x]] * (2^ [[p]]) + + [[y]] / (2^ (Zpos (xO w_digits) - [[p]]))) mod wwB. + Variable spec_w_add_c : forall x y, [+|w_add_c x y|] = [|x|] + [|y|]. + Variable spec_ww_add : forall x y, [[ww_add x y]] = ([[x]] + [[y]]) mod wwB. + Variable spec_w_sqrt2 : forall x y, + wB/ 4 <= [|x|] -> + let (s,r) := w_sqrt2 x y in + [[WW x y]] = [|s|] ^ 2 + [+|r|] /\ + [+|r|] <= 2 * [|s|]. + Variable spec_ww_sub_c : forall x y, [-[ww_sub_c x y]] = [[x]] - [[y]]. + Variable spec_ww_pred_c : forall x, [-[ww_pred_c x]] = [[x]] - 1. + Variable spec_pred : forall x, [|w_pred x|] = ([|x|] - 1) mod wB. + Variable spec_ww_pred : forall x, [[ww_pred x]] = ([[x]] - 1) mod wwB. + Variable spec_ww_add_c : forall x y, [+[ww_add_c x y]] = [[x]] + [[y]]. + Variable spec_ww_compare : forall x y, + match ww_compare x y with + | Eq => [[x]] = [[y]] + | Lt => [[x]] < [[y]] + | Gt => [[x]] > [[y]] + end. + Variable spec_ww_head0 : forall x, 0 < [[x]] -> + wwB/ 2 <= 2 ^ [[ww_head0 x]] * [[x]] < wwB. + Variable spec_low: forall x, [|low x|] = [[x]] mod wB. + + Let spec_ww_Bm1 : [[wwBm1]] = wwB - 1. + Proof. refine (spec_ww_Bm1 w_Bm1 w_digits w_to_Z _);auto. Qed. + + + Hint Rewrite spec_w_0 spec_w_1 w_Bm1 spec_w_WW spec_w_sub + spec_w_div21 spec_w_add_mul_div spec_ww_Bm1 + spec_w_add_c spec_w_sqrt2: w_rewrite. + + Lemma spec_ww_is_even : forall x, + if ww_is_even x then [[x]] mod 2 = 0 else [[x]] mod 2 = 1. +clear spec_more_than_1_digit. +intros x; case x; simpl ww_is_even. + simpl. + rewrite Zmod_small; auto with zarith. + intros w1 w2; simpl. + unfold base. + rewrite Zplus_mod; auto with zarith. + rewrite (fun x y => (Zdivide_mod (x * y))); auto with zarith. + rewrite Zplus_0_l; rewrite Zmod_mod; auto with zarith. + apply spec_w_is_even; auto with zarith. + apply Zdivide_mult_r; apply Zpower_divide; auto with zarith. + red; simpl; auto. + Qed. + + + Theorem spec_w_div21c : forall a1 a2 b, + wB/2 <= [|b|] -> + let (q,r) := w_div21c a1 a2 b in + [|a1|] * wB + [|a2|] = [+|q|] * [|b|] + [|r|] /\ 0 <= [|r|] < [|b|]. + intros a1 a2 b Hb; unfold w_div21c. + assert (H: 0 < [|b|]); auto with zarith. + assert (U := wB_pos w_digits). + apply Zlt_le_trans with (2 := Hb); auto with zarith. + apply Zlt_le_trans with 1; auto with zarith. + apply Zdiv_le_lower_bound; auto with zarith. + repeat match goal with |- context[w_compare ?y ?z] => + generalize (spec_w_compare y z); + case (w_compare y z) + end. + intros H1 H2; split. + unfold interp_carry; autorewrite with w_rewrite rm10; auto with zarith. + rewrite H1; rewrite H2; ring. + autorewrite with w_rewrite; auto with zarith. + intros H1 H2; split. + unfold interp_carry; autorewrite with w_rewrite rm10; auto with zarith. + rewrite H2; ring. + destruct (spec_to_Z a2);auto with zarith. + intros H1 H2; split. + unfold interp_carry; autorewrite with w_rewrite rm10; auto with zarith. + rewrite H2; rewrite Zmod_small; auto with zarith. + ring. + destruct (spec_to_Z a2);auto with zarith. + rewrite spec_w_sub; auto with zarith. + destruct (spec_to_Z a2) as [H3 H4];auto with zarith. + rewrite Zmod_small; auto with zarith. + split; auto with zarith. + assert ([|a2|] < 2 * [|b|]); auto with zarith. + apply Zlt_le_trans with (2 * (wB / 2)); auto with zarith. + rewrite wB_div_2; auto. + intros H1. + match goal with |- context[w_div21 ?y ?z ?t] => + generalize (@spec_w_div21 y z t Hb H1); + case (w_div21 y z t); simpl; autorewrite with w_rewrite; + auto + end. + intros H1. + assert (H2: [|w_sub a1 b|] < [|b|]). + rewrite spec_w_sub; auto with zarith. + rewrite Zmod_small; auto with zarith. + assert ([|a1|] < 2 * [|b|]); auto with zarith. + apply Zlt_le_trans with (2 * (wB / 2)); auto with zarith. + rewrite wB_div_2; auto. + destruct (spec_to_Z a1);auto with zarith. + destruct (spec_to_Z a1);auto with zarith. + match goal with |- context[w_div21 ?y ?z ?t] => + generalize (@spec_w_div21 y z t Hb H2); + case (w_div21 y z t); autorewrite with w_rewrite; + auto + end. + intros w0 w1; replace [+|C1 w0|] with (wB + [|w0|]). + rewrite Zmod_small; auto with zarith. + intros (H3, H4); split; auto. + rewrite Zmult_plus_distr_l. + rewrite <- Zplus_assoc; rewrite <- H3; ring. + split; auto with zarith. + assert ([|a1|] < 2 * [|b|]); auto with zarith. + apply Zlt_le_trans with (2 * (wB / 2)); auto with zarith. + rewrite wB_div_2; auto. + destruct (spec_to_Z a1);auto with zarith. + destruct (spec_to_Z a1);auto with zarith. + simpl; case wB; auto. + Qed. + + Theorem C0_id: forall p, [+|C0 p|] = [|p|]. + intros p; simpl; auto. + Qed. + + Theorem add_mult_div_2: forall w, + [|w_add_mul_div (w_pred w_zdigits) w_0 w|] = [|w|] / 2. + intros w1. + assert (Hp: [|w_pred w_zdigits|] = Zpos w_digits - 1). + rewrite spec_pred; rewrite spec_w_zdigits. + rewrite Zmod_small; auto with zarith. + split; auto with zarith. + apply Zlt_le_trans with (Zpos w_digits); auto with zarith. + unfold base; apply Zpower2_le_lin; auto with zarith. + rewrite spec_w_add_mul_div; auto with zarith. + autorewrite with w_rewrite rm10. + match goal with |- context[?X - ?Y] => + replace (X - Y) with 1 + end. + rewrite Zpower_1_r; rewrite Zmod_small; auto with zarith. + destruct (spec_to_Z w1) as [H1 H2];auto with zarith. + split; auto with zarith. + apply Zdiv_lt_upper_bound; auto with zarith. + rewrite Hp; ring. + Qed. + + Theorem add_mult_div_2_plus_1: forall w, + [|w_add_mul_div (w_pred w_zdigits) w_1 w|] = + [|w|] / 2 + 2 ^ Zpos (w_digits - 1). + intros w1. + assert (Hp: [|w_pred w_zdigits|] = Zpos w_digits - 1). + rewrite spec_pred; rewrite spec_w_zdigits. + rewrite Zmod_small; auto with zarith. + split; auto with zarith. + apply Zlt_le_trans with (Zpos w_digits); auto with zarith. + unfold base; apply Zpower2_le_lin; auto with zarith. + autorewrite with w_rewrite rm10; auto with zarith. + match goal with |- context[?X - ?Y] => + replace (X - Y) with 1 + end; rewrite Hp; try ring. + rewrite Zpos_minus; auto with zarith. + rewrite Zmax_right; auto with zarith. + rewrite Zpower_1_r; rewrite Zmod_small; auto with zarith. + destruct (spec_to_Z w1) as [H1 H2];auto with zarith. + split; auto with zarith. + unfold base. + match goal with |- _ < _ ^ ?X => + assert (tmp: forall p, 1 + (p - 1) = p); auto with zarith; + rewrite <- (tmp X); clear tmp + end. + rewrite Zpower_exp; try rewrite Zpower_1_r; auto with zarith. + assert (tmp: forall p, 1 + (p -1) - 1 = p - 1); auto with zarith; + rewrite tmp; clear tmp; auto with zarith. + match goal with |- ?X + ?Y < _ => + assert (Y < X); auto with zarith + end. + apply Zdiv_lt_upper_bound; auto with zarith. + pattern 2 at 2; rewrite <- Zpower_1_r; rewrite <- Zpower_exp; + auto with zarith. + assert (tmp: forall p, (p - 1) + 1 = p); auto with zarith; + rewrite tmp; clear tmp; auto with zarith. + Qed. + + Theorem add_mult_mult_2: forall w, + [|w_add_mul_div w_1 w w_0|] = 2 * [|w|] mod wB. + intros w1. + autorewrite with w_rewrite rm10; auto with zarith. + rewrite Zpower_1_r; auto with zarith. + rewrite Zmult_comm; auto. + Qed. + + Theorem ww_add_mult_mult_2: forall w, + [[ww_add_mul_div (w_0W w_1) w W0]] = 2 * [[w]] mod wwB. + intros w1. + rewrite spec_ww_add_mul_div; auto with zarith. + autorewrite with w_rewrite rm10. + rewrite spec_w_0W; rewrite spec_w_1. + rewrite Zpower_1_r; auto with zarith. + rewrite Zmult_comm; auto. + rewrite spec_w_0W; rewrite spec_w_1; auto with zarith. + red; simpl; intros; discriminate. + Qed. + + Theorem ww_add_mult_mult_2_plus_1: forall w, + [[ww_add_mul_div (w_0W w_1) w wwBm1]] = + (2 * [[w]] + 1) mod wwB. + intros w1. + rewrite spec_ww_add_mul_div; auto with zarith. + rewrite spec_w_0W; rewrite spec_w_1; auto with zarith. + rewrite Zpower_1_r; auto with zarith. + f_equal; auto. + rewrite Zmult_comm; f_equal; auto. + autorewrite with w_rewrite rm10. + unfold ww_digits, base. + apply sym_equal; apply Zdiv_unique with (r := 2 ^ (Zpos (ww_digits w_digits) - 1) -1); + auto with zarith. + unfold ww_digits; split; auto with zarith. + match goal with |- 0 <= ?X - 1 => + assert (0 < X); auto with zarith + end. + apply Zpower_gt_0; auto with zarith. + match goal with |- 0 <= ?X - 1 => + assert (0 < X); auto with zarith; red; reflexivity + end. + unfold ww_digits; autorewrite with rm10. + assert (tmp: forall p q r, p + (q - r) = p + q - r); auto with zarith; + rewrite tmp; clear tmp. + assert (tmp: forall p, p + p = 2 * p); auto with zarith; + rewrite tmp; clear tmp. + f_equal; auto. + pattern 2 at 2; rewrite <- Zpower_1_r; rewrite <- Zpower_exp; + auto with zarith. + assert (tmp: forall p, 1 + (p - 1) = p); auto with zarith; + rewrite tmp; clear tmp; auto. + match goal with |- ?X - 1 >= 0 => + assert (0 < X); auto with zarith; red; reflexivity + end. + rewrite spec_w_0W; rewrite spec_w_1; auto with zarith. + red; simpl; intros; discriminate. + Qed. + + Theorem Zplus_mod_one: forall a1 b1, 0 < b1 -> (a1 + b1) mod b1 = a1 mod b1. + intros a1 b1 H; rewrite Zplus_mod; auto with zarith. + rewrite Z_mod_same; try rewrite Zplus_0_r; auto with zarith. + apply Zmod_mod; auto. + Qed. + + Lemma C1_plus_wB: forall x, [+|C1 x|] = wB + [|x|]. + unfold interp_carry; auto with zarith. + Qed. + + Theorem spec_w_div2s : forall a1 a2 b, + wB/2 <= [|b|] -> [+|a1|] <= 2 * [|b|] -> + let (q,r) := w_div2s a1 a2 b in + [+|a1|] * wB + [|a2|] = [+|q|] * (2 * [|b|]) + [+|r|] /\ 0 <= [+|r|] < 2 * [|b|]. + intros a1 a2 b H. + assert (HH: 0 < [|b|]); auto with zarith. + assert (U := wB_pos w_digits). + apply Zlt_le_trans with (2 := H); auto with zarith. + apply Zlt_le_trans with 1; auto with zarith. + apply Zdiv_le_lower_bound; auto with zarith. + unfold w_div2s; case a1; intros w0 H0. + match goal with |- context[w_div21c ?y ?z ?t] => + generalize (@spec_w_div21c y z t H); + case (w_div21c y z t); autorewrite with w_rewrite; + auto + end. + intros c w1; case c. + simpl interp_carry; intros w2 (Hw1, Hw2). + match goal with |- context[w_is_even ?y] => + generalize (spec_w_is_even y); + case (w_is_even y) + end. + repeat rewrite C0_id. + rewrite add_mult_div_2. + intros H1; split; auto with zarith. + rewrite Hw1. + pattern [|w2|] at 1; rewrite (Z_div_mod_eq [|w2|] 2); + auto with zarith. + rewrite H1; ring. + repeat rewrite C0_id. + rewrite add_mult_div_2. + rewrite spec_w_add_c; auto with zarith. + intros H1; split; auto with zarith. + rewrite Hw1. + pattern [|w2|] at 1; rewrite (Z_div_mod_eq [|w2|] 2); + auto with zarith. + rewrite H1; ring. + intros w2; rewrite C1_plus_wB. + intros (Hw1, Hw2). + match goal with |- context[w_is_even ?y] => + generalize (spec_w_is_even y); + case (w_is_even y) + end. + repeat rewrite C0_id. + intros H1; split; auto with zarith. + rewrite Hw1. + pattern [|w2|] at 1; rewrite (Z_div_mod_eq [|w2|] 2); + auto with zarith. + rewrite H1. + repeat rewrite C0_id. + rewrite add_mult_div_2_plus_1; unfold base. + match goal with |- context[_ ^ ?X] => + assert (tmp: forall p, 1 + (p - 1) = p); auto with zarith; + rewrite <- (tmp X); clear tmp; rewrite Zpower_exp; + try rewrite Zpower_1_r; auto with zarith + end. + rewrite Zpos_minus; auto with zarith. + rewrite Zmax_right; auto with zarith. + ring. + repeat rewrite C0_id. + rewrite spec_w_add_c; auto with zarith. + intros H1; split; auto with zarith. + rewrite add_mult_div_2_plus_1. + rewrite Hw1. + pattern [|w2|] at 1; rewrite (Z_div_mod_eq [|w2|] 2); + auto with zarith. + rewrite H1. + unfold base. + match goal with |- context[_ ^ ?X] => + assert (tmp: forall p, 1 + (p - 1) = p); auto with zarith; + rewrite <- (tmp X); clear tmp; rewrite Zpower_exp; + try rewrite Zpower_1_r; auto with zarith + end. + rewrite Zpos_minus; auto with zarith. + rewrite Zmax_right; auto with zarith. + ring. + repeat rewrite C1_plus_wB in H0. + rewrite C1_plus_wB. + match goal with |- context[w_div21c ?y ?z ?t] => + generalize (@spec_w_div21c y z t H); + case (w_div21c y z t); autorewrite with w_rewrite; + auto + end. + intros c w1; case c. + intros w2 (Hw1, Hw2); rewrite C0_id in Hw1. + rewrite <- Zplus_mod_one in Hw1; auto with zarith. + rewrite Zmod_small in Hw1; auto with zarith. + match goal with |- context[w_is_even ?y] => + generalize (spec_w_is_even y); + case (w_is_even y) + end. + repeat rewrite C0_id. + intros H1; split; auto with zarith. + rewrite add_mult_div_2_plus_1. + replace (wB + [|w0|]) with ([|b|] + ([|w0|] - [|b|] + wB)); + auto with zarith. + rewrite Zmult_plus_distr_l; rewrite <- Zplus_assoc. + rewrite Hw1. + pattern [|w2|] at 1; rewrite (Z_div_mod_eq [|w2|] 2); + auto with zarith. + rewrite H1; unfold base. + match goal with |- context[_ ^ ?X] => + assert (tmp: forall p, 1 + (p - 1) = p); auto with zarith; + rewrite <- (tmp X); clear tmp; rewrite Zpower_exp; + try rewrite Zpower_1_r; auto with zarith + end. + rewrite Zpos_minus; auto with zarith. + rewrite Zmax_right; auto with zarith. + ring. + repeat rewrite C0_id. + rewrite add_mult_div_2_plus_1. + rewrite spec_w_add_c; auto with zarith. + intros H1; split; auto with zarith. + replace (wB + [|w0|]) with ([|b|] + ([|w0|] - [|b|] + wB)); + auto with zarith. + rewrite Zmult_plus_distr_l; rewrite <- Zplus_assoc. + rewrite Hw1. + pattern [|w2|] at 1; rewrite (Z_div_mod_eq [|w2|] 2); + auto with zarith. + rewrite H1; unfold base. + match goal with |- context[_ ^ ?X] => + assert (tmp: forall p, 1 + (p - 1) = p); auto with zarith; + rewrite <- (tmp X); clear tmp; rewrite Zpower_exp; + try rewrite Zpower_1_r; auto with zarith + end. + rewrite Zpos_minus; auto with zarith. + rewrite Zmax_right; auto with zarith. + ring. + split; auto with zarith. + destruct (spec_to_Z b);auto with zarith. + destruct (spec_to_Z w0);auto with zarith. + destruct (spec_to_Z b);auto with zarith. + destruct (spec_to_Z b);auto with zarith. + intros w2; rewrite C1_plus_wB. + rewrite <- Zplus_mod_one; auto with zarith. + rewrite Zmod_small; auto with zarith. + intros (Hw1, Hw2). + match goal with |- context[w_is_even ?y] => + generalize (spec_w_is_even y); + case (w_is_even y) + end. + repeat (rewrite C0_id || rewrite C1_plus_wB). + intros H1; split; auto with zarith. + rewrite add_mult_div_2. + replace (wB + [|w0|]) with ([|b|] + ([|w0|] - [|b|] + wB)); + auto with zarith. + rewrite Zmult_plus_distr_l; rewrite <- Zplus_assoc. + rewrite Hw1. + pattern [|w2|] at 1; rewrite (Z_div_mod_eq [|w2|] 2); + auto with zarith. + rewrite H1; ring. + repeat (rewrite C0_id || rewrite C1_plus_wB). + rewrite spec_w_add_c; auto with zarith. + intros H1; split; auto with zarith. + rewrite add_mult_div_2. + replace (wB + [|w0|]) with ([|b|] + ([|w0|] - [|b|] + wB)); + auto with zarith. + rewrite Zmult_plus_distr_l; rewrite <- Zplus_assoc. + rewrite Hw1. + pattern [|w2|] at 1; rewrite (Z_div_mod_eq [|w2|] 2); + auto with zarith. + rewrite H1; ring. + split; auto with zarith. + destruct (spec_to_Z b);auto with zarith. + destruct (spec_to_Z w0);auto with zarith. + destruct (spec_to_Z b);auto with zarith. + destruct (spec_to_Z b);auto with zarith. + Qed. + + Theorem wB_div_4: 4 * (wB / 4) = wB. + Proof. + unfold base. + assert (2 ^ Zpos w_digits = + 4 * (2 ^ (Zpos w_digits - 2))). + change 4 with (2 ^ 2). + rewrite <- Zpower_exp; auto with zarith. + f_equal; auto with zarith. + rewrite H. + rewrite (fun x => (Zmult_comm 4 (2 ^x))). + rewrite Z_div_mult; auto with zarith. + Qed. + + Theorem Zsquare_mult: forall p, p ^ 2 = p * p. + intros p; change 2 with (1 + 1); rewrite Zpower_exp; + try rewrite Zpower_1_r; auto with zarith. + Qed. + + Theorem Zsquare_pos: forall p, 0 <= p ^ 2. + intros p; case (Zle_or_lt 0 p); intros H1. + rewrite Zsquare_mult; apply Zmult_le_0_compat; auto with zarith. + rewrite Zsquare_mult; replace (p * p) with ((- p) * (- p)); try ring. + apply Zmult_le_0_compat; auto with zarith. + Qed. + + Lemma spec_split: forall x, + [|fst (split x)|] * wB + [|snd (split x)|] = [[x]]. + intros x; case x; simpl; autorewrite with w_rewrite; + auto with zarith. + Qed. + + Theorem mult_wwB: forall x y, [|x|] * [|y|] < wwB. + Proof. + intros x y; rewrite wwB_wBwB; rewrite Zpower_2. + generalize (spec_to_Z x); intros U. + generalize (spec_to_Z y); intros U1. + apply Zle_lt_trans with ((wB -1 ) * (wB - 1)); auto with zarith. + apply Zmult_le_compat; auto with zarith. + repeat (rewrite Zmult_minus_distr_r || rewrite Zmult_minus_distr_l); + auto with zarith. + Qed. + Hint Resolve mult_wwB. + + Lemma spec_ww_sqrt2 : forall x y, + wwB/ 4 <= [[x]] -> + let (s,r) := ww_sqrt2 x y in + [||WW x y||] = [[s]] ^ 2 + [+[r]] /\ + [+[r]] <= 2 * [[s]]. + intros x y H; unfold ww_sqrt2. + repeat match goal with |- context[split ?x] => + generalize (spec_split x); case (split x) + end; simpl fst; simpl snd. + intros w0 w1 Hw0 w2 w3 Hw1. + assert (U: wB/4 <= [|w2|]). + case (Zle_or_lt (wB / 4) [|w2|]); auto; intros H1. + contradict H; apply Zlt_not_le. + rewrite wwB_wBwB; rewrite Zpower_2. + pattern wB at 1; rewrite <- wB_div_4; rewrite <- Zmult_assoc; + rewrite Zmult_comm. + rewrite Z_div_mult; auto with zarith. + rewrite <- Hw1. + match goal with |- _ < ?X => + pattern X; rewrite <- Zplus_0_r; apply beta_lex_inv; + auto with zarith + end. + destruct (spec_to_Z w3);auto with zarith. + generalize (@spec_w_sqrt2 w2 w3 U); case (w_sqrt2 w2 w3). + intros w4 c (H1, H2). + assert (U1: wB/2 <= [|w4|]). + case (Zle_or_lt (wB/2) [|w4|]); auto with zarith. + intros U1. + assert (U2 : [|w4|] <= wB/2 -1); auto with zarith. + assert (U3 : [|w4|] ^ 2 <= wB/4 * wB - wB + 1); auto with zarith. + match goal with |- ?X ^ 2 <= ?Y => + rewrite Zsquare_mult; + replace Y with ((wB/2 - 1) * (wB/2 -1)) + end. + apply Zmult_le_compat; auto with zarith. + destruct (spec_to_Z w4);auto with zarith. + destruct (spec_to_Z w4);auto with zarith. + pattern wB at 4 5; rewrite <- wB_div_2. + rewrite Zmult_assoc. + replace ((wB / 4) * 2) with (wB / 2). + ring. + pattern wB at 1; rewrite <- wB_div_4. + change 4 with (2 * 2). + rewrite <- Zmult_assoc; rewrite (Zmult_comm 2). + rewrite Z_div_mult; try ring; auto with zarith. + assert (U4 : [+|c|] <= wB -2); auto with zarith. + apply Zle_trans with (1 := H2). + match goal with |- ?X <= ?Y => + replace Y with (2 * (wB/ 2 - 1)); auto with zarith + end. + pattern wB at 2; rewrite <- wB_div_2; auto with zarith. + match type of H1 with ?X = _ => + assert (U5: X < wB / 4 * wB) + end. + rewrite H1; auto with zarith. + contradict U; apply Zlt_not_le. + apply Zmult_lt_reg_r with wB; auto with zarith. + destruct (spec_to_Z w4);auto with zarith. + apply Zle_lt_trans with (2 := U5). + unfold ww_to_Z, zn2z_to_Z. + destruct (spec_to_Z w3);auto with zarith. + generalize (@spec_w_div2s c w0 w4 U1 H2). + case (w_div2s c w0 w4). + intros c0; case c0; intros w5; + repeat (rewrite C0_id || rewrite C1_plus_wB). + intros c1; case c1; intros w6; + repeat (rewrite C0_id || rewrite C1_plus_wB). + intros (H3, H4). + match goal with |- context [ww_sub_c ?y ?z] => + generalize (spec_ww_sub_c y z); case (ww_sub_c y z) + end. + intros z; change [-[C0 z]] with ([[z]]). + change [+[C0 z]] with ([[z]]). + intros H5; rewrite spec_w_square_c in H5; + auto. + split. + unfold zn2z_to_Z; rewrite <- Hw1. + unfold ww_to_Z, zn2z_to_Z in H1; rewrite H1. + rewrite <- Hw0. + match goal with |- (?X ^2 + ?Y) * wwB + (?Z * wB + ?T) = ?U => + apply trans_equal with ((X * wB) ^ 2 + (Y * wB + Z) * wB + T) + end. + repeat rewrite Zsquare_mult. + rewrite wwB_wBwB; ring. + rewrite H3. + rewrite H5. + unfold ww_to_Z, zn2z_to_Z. + repeat rewrite Zsquare_mult; ring. + rewrite H5. + unfold ww_to_Z, zn2z_to_Z. + match goal with |- ?X - ?Y * ?Y <= _ => + assert (V := Zsquare_pos Y); + rewrite Zsquare_mult in V; + apply Zle_trans with X; auto with zarith; + clear V + end. + match goal with |- ?X * wB + ?Y <= 2 * (?Z * wB + ?T) => + apply Zle_trans with ((2 * Z - 1) * wB + wB); auto with zarith + end. + destruct (spec_to_Z w1);auto with zarith. + match goal with |- ?X <= _ => + replace X with (2 * [|w4|] * wB); auto with zarith + end. + rewrite Zmult_plus_distr_r; rewrite Zmult_assoc. + destruct (spec_to_Z w5); auto with zarith. + ring. + intros z; replace [-[C1 z]] with (- wwB + [[z]]). + 2: simpl; case wwB; auto with zarith. + intros H5; rewrite spec_w_square_c in H5; + auto. + match goal with |- context [ww_pred_c ?y] => + generalize (spec_ww_pred_c y); case (ww_pred_c y) + end. + intros z1; change [-[C0 z1]] with ([[z1]]). + rewrite ww_add_mult_mult_2. + rewrite spec_ww_add_c. + rewrite spec_ww_pred. + rewrite <- Zmod_unique with (q := 1) (r := -wwB + 2 * [[WW w4 w5]]); + auto with zarith. + intros Hz1; rewrite Zmod_small; auto with zarith. + match type of H5 with -?X + ?Y = ?Z => + assert (V: Y = Z + X); + try (rewrite <- H5; ring) + end. + split. + unfold zn2z_to_Z; rewrite <- Hw1. + unfold ww_to_Z, zn2z_to_Z in H1; rewrite H1. + rewrite <- Hw0. + match goal with |- (?X ^2 + ?Y) * wwB + (?Z * wB + ?T) = ?U => + apply trans_equal with ((X * wB) ^ 2 + (Y * wB + Z) * wB + T) + end. + repeat rewrite Zsquare_mult. + rewrite wwB_wBwB; ring. + rewrite H3. + rewrite V. + rewrite Hz1. + unfold ww_to_Z; simpl zn2z_to_Z. + repeat rewrite Zsquare_mult; ring. + rewrite Hz1. + destruct (spec_ww_to_Z w_digits w_to_Z spec_to_Z z);auto with zarith. + assert (V1 := spec_ww_to_Z w_digits w_to_Z spec_to_Z (WW w4 w5)). + assert (0 < [[WW w4 w5]]); auto with zarith. + apply Zlt_le_trans with (wB/ 2 * wB + 0); auto with zarith. + autorewrite with rm10; apply Zmult_lt_0_compat; auto with zarith. + apply Zmult_lt_reg_r with 2; auto with zarith. + autorewrite with rm10. + rewrite Zmult_comm; rewrite wB_div_2; auto with zarith. + case (spec_to_Z w5);auto with zarith. + case (spec_to_Z w5);auto with zarith. + simpl. + assert (V2 := spec_to_Z w5);auto with zarith. + assert (V1 := spec_ww_to_Z w_digits w_to_Z spec_to_Z (WW w4 w5)); auto with zarith. + split; auto with zarith. + assert (wwB <= 2 * [[WW w4 w5]]); auto with zarith. + apply Zle_trans with (2 * ([|w4|] * wB)). + rewrite wwB_wBwB; rewrite Zpower_2. + rewrite Zmult_assoc; apply Zmult_le_compat_r; auto with zarith. + rewrite <- wB_div_2; auto with zarith. + assert (V2 := spec_to_Z w5);auto with zarith. + simpl ww_to_Z; assert (V2 := spec_to_Z w5);auto with zarith. + assert (V1 := spec_ww_to_Z w_digits w_to_Z spec_to_Z (WW w4 w5)); auto with zarith. + intros z1; change [-[C1 z1]] with (-wwB + [[z1]]). + match goal with |- context[([+[C0 ?z]])] => + change [+[C0 z]] with ([[z]]) + end. + rewrite spec_ww_add; auto with zarith. + rewrite spec_ww_pred; auto with zarith. + rewrite ww_add_mult_mult_2. + rename V1 into VV1. + assert (VV2: 0 < [[WW w4 w5]]); auto with zarith. + apply Zlt_le_trans with (wB/ 2 * wB + 0); auto with zarith. + autorewrite with rm10; apply Zmult_lt_0_compat; auto with zarith. + apply Zmult_lt_reg_r with 2; auto with zarith. + autorewrite with rm10. + rewrite Zmult_comm; rewrite wB_div_2; auto with zarith. + assert (VV3 := spec_to_Z w5);auto with zarith. + assert (VV3 := spec_to_Z w5);auto with zarith. + simpl. + assert (VV3 := spec_to_Z w5);auto with zarith. + assert (VV3: wwB <= 2 * [[WW w4 w5]]); auto with zarith. + apply Zle_trans with (2 * ([|w4|] * wB)). + rewrite wwB_wBwB; rewrite Zpower_2. + rewrite Zmult_assoc; apply Zmult_le_compat_r; auto with zarith. + rewrite <- wB_div_2; auto with zarith. + case (spec_to_Z w5);auto with zarith. + simpl ww_to_Z; assert (V4 := spec_to_Z w5);auto with zarith. + rewrite <- Zmod_unique with (q := 1) (r := -wwB + 2 * [[WW w4 w5]]); + auto with zarith. + intros Hz1; rewrite Zmod_small; auto with zarith. + match type of H5 with -?X + ?Y = ?Z => + assert (V: Y = Z + X); + try (rewrite <- H5; ring) + end. + match type of Hz1 with -?X + ?Y = -?X + ?Z - 1 => + assert (V1: Y = Z - 1); + [replace (Z - 1) with (X + (-X + Z -1)); + [rewrite <- Hz1 | idtac]; ring + | idtac] + end. + rewrite <- Zmod_unique with (q := 1) (r := -wwB + [[z1]] + [[z]]); + auto with zarith. + unfold zn2z_to_Z; rewrite <- Hw1. + unfold ww_to_Z, zn2z_to_Z in H1; rewrite H1. + rewrite <- Hw0. + split. + match goal with |- (?X ^2 + ?Y) * wwB + (?Z * wB + ?T) = ?U => + apply trans_equal with ((X * wB) ^ 2 + (Y * wB + Z) * wB + T) + end. + repeat rewrite Zsquare_mult. + rewrite wwB_wBwB; ring. + rewrite H3. + rewrite V. + rewrite Hz1. + unfold ww_to_Z; simpl zn2z_to_Z. + repeat rewrite Zsquare_mult; ring. + assert (V2 := spec_ww_to_Z w_digits w_to_Z spec_to_Z z);auto with zarith. + assert (V2 := spec_ww_to_Z w_digits w_to_Z spec_to_Z z);auto with zarith. + assert (V3 := spec_ww_to_Z w_digits w_to_Z spec_to_Z z1);auto with zarith. + split; auto with zarith. + rewrite (Zplus_comm (-wwB)); rewrite <- Zplus_assoc. + rewrite H5. + match goal with |- 0 <= ?X + (?Y - ?Z) => + apply Zle_trans with (X - Z); auto with zarith + end. + 2: generalize (spec_ww_to_Z w_digits w_to_Z spec_to_Z (WW w6 w1)); unfold ww_to_Z; auto with zarith. + rewrite V1. + match goal with |- 0 <= ?X - 1 - ?Y => + assert (Y < X); auto with zarith + end. + apply Zlt_le_trans with wwB; auto with zarith. + intros (H3, H4). + match goal with |- context [ww_sub_c ?y ?z] => + generalize (spec_ww_sub_c y z); case (ww_sub_c y z) + end. + intros z; change [-[C0 z]] with ([[z]]). + match goal with |- context[([+[C1 ?z]])] => + replace [+[C1 z]] with (wwB + [[z]]) + end. + 2: simpl; case wwB; auto. + intros H5; rewrite spec_w_square_c in H5; + auto. + split. + change ([||WW x y||]) with ([[x]] * wwB + [[y]]). + rewrite <- Hw1. + unfold ww_to_Z, zn2z_to_Z in H1; rewrite H1. + rewrite <- Hw0. + match goal with |- (?X ^2 + ?Y) * wwB + (?Z * wB + ?T) = ?U => + apply trans_equal with ((X * wB) ^ 2 + (Y * wB + Z) * wB + T) + end. + repeat rewrite Zsquare_mult. + rewrite wwB_wBwB; ring. + rewrite H3. + rewrite H5. + unfold ww_to_Z; simpl zn2z_to_Z. + rewrite wwB_wBwB. + repeat rewrite Zsquare_mult; ring. + simpl ww_to_Z. + rewrite H5. + simpl ww_to_Z. + rewrite wwB_wBwB; rewrite Zpower_2. + match goal with |- ?X * ?Y + (?Z * ?Y + ?T - ?U) <= _ => + apply Zle_trans with (X * Y + (Z * Y + T - 0)); + auto with zarith + end. + assert (V := Zsquare_pos [|w5|]); + rewrite Zsquare_mult in V; auto with zarith. + autorewrite with rm10. + match goal with |- _ <= 2 * (?U * ?V + ?W) => + apply Zle_trans with (2 * U * V + 0); + auto with zarith + end. + match goal with |- ?X * ?Y + (?Z * ?Y + ?T) <= _ => + replace (X * Y + (Z * Y + T)) with ((X + Z) * Y + T); + try ring + end. + apply Zlt_le_weak; apply beta_lex_inv; auto with zarith. + destruct (spec_to_Z w1);auto with zarith. + destruct (spec_to_Z w5);auto with zarith. + rewrite Zmult_plus_distr_r; auto with zarith. + rewrite Zmult_assoc; auto with zarith. + intros z; replace [-[C1 z]] with (- wwB + [[z]]). + 2: simpl; case wwB; auto with zarith. + intros H5; rewrite spec_w_square_c in H5; + auto. + match goal with |- context[([+[C0 ?z]])] => + change [+[C0 z]] with ([[z]]) + end. + match type of H5 with -?X + ?Y = ?Z => + assert (V: Y = Z + X); + try (rewrite <- H5; ring) + end. + change ([||WW x y||]) with ([[x]] * wwB + [[y]]). + simpl ww_to_Z. + rewrite <- Hw1. + simpl ww_to_Z in H1; rewrite H1. + rewrite <- Hw0. + split. + match goal with |- (?X ^2 + ?Y) * wwB + (?Z * wB + ?T) = ?U => + apply trans_equal with ((X * wB) ^ 2 + (Y * wB + Z) * wB + T) + end. + repeat rewrite Zsquare_mult. + rewrite wwB_wBwB; ring. + rewrite H3. + rewrite V. + simpl ww_to_Z. + rewrite wwB_wBwB. + repeat rewrite Zsquare_mult; ring. + rewrite V. + simpl ww_to_Z. + rewrite wwB_wBwB; rewrite Zpower_2. + match goal with |- (?Z * ?Y + ?T - ?U) + ?X * ?Y <= _ => + apply Zle_trans with ((Z * Y + T - 0) + X * Y); + auto with zarith + end. + assert (V1 := Zsquare_pos [|w5|]); + rewrite Zsquare_mult in V1; auto with zarith. + autorewrite with rm10. + match goal with |- _ <= 2 * (?U * ?V + ?W) => + apply Zle_trans with (2 * U * V + 0); + auto with zarith + end. + match goal with |- (?Z * ?Y + ?T) + ?X * ?Y <= _ => + replace ((Z * Y + T) + X * Y) with ((X + Z) * Y + T); + try ring + end. + apply Zlt_le_weak; apply beta_lex_inv; auto with zarith. + destruct (spec_to_Z w1);auto with zarith. + destruct (spec_to_Z w5);auto with zarith. + rewrite Zmult_plus_distr_r; auto with zarith. + rewrite Zmult_assoc; auto with zarith. + case Zle_lt_or_eq with (1 := H2); clear H2; intros H2. + intros c1 (H3, H4). + match type of H3 with ?X = ?Y => + absurd (X < Y) + end. + apply Zle_not_lt; rewrite <- H3; auto with zarith. + rewrite Zmult_plus_distr_l. + apply Zlt_le_trans with ((2 * [|w4|]) * wB + 0); + auto with zarith. + apply beta_lex_inv; auto with zarith. + destruct (spec_to_Z w0);auto with zarith. + assert (V1 := spec_to_Z w5);auto with zarith. + rewrite (Zmult_comm wB); auto with zarith. + assert (0 <= [|w5|] * (2 * [|w4|])); auto with zarith. + intros c1 (H3, H4); rewrite H2 in H3. + match type of H3 with ?X + ?Y = (?Z + ?T) * ?U + ?V => + assert (VV: (Y = (T * U) + V)); + [replace Y with ((X + Y) - X); + [rewrite H3; ring | ring] | idtac] + end. + assert (V1 := spec_to_Z w0);auto with zarith. + assert (V2 := spec_to_Z w5);auto with zarith. + case (Zle_lt_or_eq 0 [|w5|]); auto with zarith; intros V3. + match type of VV with ?X = ?Y => + absurd (X < Y) + end. + apply Zle_not_lt; rewrite <- VV; auto with zarith. + apply Zlt_le_trans with wB; auto with zarith. + match goal with |- _ <= ?X + _ => + apply Zle_trans with X; auto with zarith + end. + match goal with |- _ <= _ * ?X => + apply Zle_trans with (1 * X); auto with zarith + end. + autorewrite with rm10. + rewrite <- wB_div_2; apply Zmult_le_compat_l; auto with zarith. + rewrite <- V3 in VV; generalize VV; autorewrite with rm10; + clear VV; intros VV. + rewrite spec_ww_add_c; auto with zarith. + rewrite ww_add_mult_mult_2_plus_1. + match goal with |- context[?X mod wwB] => + rewrite <- Zmod_unique with (q := 1) (r := -wwB + X) + end; auto with zarith. + simpl ww_to_Z. + rewrite spec_w_Bm1; auto with zarith. + split. + change ([||WW x y||]) with ([[x]] * wwB + [[y]]). + rewrite <- Hw1. + simpl ww_to_Z in H1; rewrite H1. + rewrite <- Hw0. + match goal with |- (?X ^2 + ?Y) * wwB + (?Z * wB + ?T) = ?U => + apply trans_equal with ((X * wB) ^ 2 + (Y * wB + Z) * wB + T) + end. + repeat rewrite Zsquare_mult. + rewrite wwB_wBwB; ring. + rewrite H2. + rewrite wwB_wBwB. + repeat rewrite Zsquare_mult; ring. + assert (V4 := spec_ww_to_Z w_digits w_to_Z spec_to_Z y);auto with zarith. + assert (V4 := spec_ww_to_Z w_digits w_to_Z spec_to_Z y);auto with zarith. + simpl ww_to_Z; unfold ww_to_Z. + rewrite spec_w_Bm1; auto with zarith. + split. + rewrite wwB_wBwB; rewrite Zpower_2. + match goal with |- _ <= -?X + (2 * (?Z * ?T + ?U) + ?V) => + assert (X <= 2 * Z * T); auto with zarith + end. + apply Zmult_le_compat_r; auto with zarith. + rewrite <- wB_div_2; apply Zmult_le_compat_l; auto with zarith. + rewrite Zmult_plus_distr_r; auto with zarith. + rewrite Zmult_assoc; auto with zarith. + match goal with |- _ + ?X < _ => + replace X with ((2 * (([|w4|]) + 1) * wB) - 1); try ring + end. + assert (2 * ([|w4|] + 1) * wB <= 2 * wwB); auto with zarith. + rewrite <- Zmult_assoc; apply Zmult_le_compat_l; auto with zarith. + rewrite wwB_wBwB; rewrite Zpower_2. + apply Zmult_le_compat_r; auto with zarith. + case (spec_to_Z w4);auto with zarith. + Qed. + + Lemma spec_ww_is_zero: forall x, + if ww_is_zero x then [[x]] = 0 else 0 < [[x]]. + intro x; unfold ww_is_zero. + generalize (spec_ww_compare W0 x); case (ww_compare W0 x); + auto with zarith. + simpl ww_to_Z. + assert (V4 := spec_ww_to_Z w_digits w_to_Z spec_to_Z x);auto with zarith. + Qed. + + Lemma wwB_4_2: 2 * (wwB / 4) = wwB/ 2. + pattern wwB at 1; rewrite wwB_wBwB; rewrite Zpower_2. + rewrite <- wB_div_2. + match goal with |- context[(2 * ?X) * (2 * ?Z)] => + replace ((2 * X) * (2 * Z)) with ((X * Z) * 4); try ring + end. + rewrite Z_div_mult; auto with zarith. + rewrite Zmult_assoc; rewrite wB_div_2. + rewrite wwB_div_2; ring. + Qed. + + + Lemma spec_ww_head1 + : forall x : zn2z w, + (ww_is_even (ww_head1 x) = true) /\ + (0 < [[x]] -> wwB / 4 <= 2 ^ [[ww_head1 x]] * [[x]] < wwB). + assert (U := wB_pos w_digits). + intros x; unfold ww_head1. + generalize (spec_ww_is_even (ww_head0 x)); case_eq (ww_is_even (ww_head0 x)). + intros HH H1; rewrite HH; split; auto. + intros H2. + generalize (spec_ww_head0 x H2); case (ww_head0 x); autorewrite with rm10. + intros (H3, H4); split; auto with zarith. + apply Zle_trans with (2 := H3). + apply Zdiv_le_compat_l; auto with zarith. + intros xh xl (H3, H4); split; auto with zarith. + apply Zle_trans with (2 := H3). + apply Zdiv_le_compat_l; auto with zarith. + intros H1. + case (spec_to_w_Z (ww_head0 x)); intros Hv1 Hv2. + assert (Hp0: 0 < [[ww_head0 x]]). + generalize (spec_ww_is_even (ww_head0 x)); rewrite H1. + generalize Hv1; case [[ww_head0 x]]. + rewrite Zmod_small; auto with zarith. + intros; assert (0 < Zpos p); auto with zarith. + red; simpl; auto. + intros p H2; case H2; auto. + assert (Hp: [[ww_pred (ww_head0 x)]] = [[ww_head0 x]] - 1). + rewrite spec_ww_pred. + rewrite Zmod_small; auto with zarith. + intros H2; split. + generalize (spec_ww_is_even (ww_pred (ww_head0 x))); + case ww_is_even; auto. + rewrite Hp. + rewrite Zminus_mod; auto with zarith. + rewrite H2; repeat rewrite Zmod_small; auto with zarith. + intros H3; rewrite Hp. + case (spec_ww_head0 x); auto; intros Hv3 Hv4. + assert (Hu: forall u, 0 < u -> 2 * 2 ^ (u - 1) = 2 ^u). + intros u Hu. + pattern 2 at 1; rewrite <- Zpower_1_r. + rewrite <- Zpower_exp; auto with zarith. + ring_simplify (1 + (u - 1)); auto with zarith. + split; auto with zarith. + apply Zmult_le_reg_r with 2; auto with zarith. + repeat rewrite (fun x => Zmult_comm x 2). + rewrite wwB_4_2. + rewrite Zmult_assoc; rewrite Hu; auto with zarith. + apply Zle_lt_trans with (2 * 2 ^ ([[ww_head0 x]] - 1) * [[x]]); auto with zarith; + rewrite Hu; auto with zarith. + apply Zmult_le_compat_r; auto with zarith. + apply Zpower_le_monotone; auto with zarith. + Qed. + + Theorem wwB_4_wB_4: wwB / 4 = wB / 4 * wB. + apply sym_equal; apply Zdiv_unique with 0; + auto with zarith. + rewrite Zmult_assoc; rewrite wB_div_4; auto with zarith. + rewrite wwB_wBwB; ring. + Qed. + + Lemma spec_ww_sqrt : forall x, + [[ww_sqrt x]] ^ 2 <= [[x]] < ([[ww_sqrt x]] + 1) ^ 2. + assert (U := wB_pos w_digits). + intro x; unfold ww_sqrt. + generalize (spec_ww_is_zero x); case (ww_is_zero x). + simpl ww_to_Z; simpl Zpower; unfold Zpower_pos; simpl; + auto with zarith. + intros H1. + generalize (spec_ww_compare (ww_head1 x) W0); case ww_compare; + simpl ww_to_Z; autorewrite with rm10. + generalize H1; case x. + intros HH; contradict HH; simpl ww_to_Z; auto with zarith. + intros w0 w1; simpl ww_to_Z; autorewrite with w_rewrite rm10. + intros H2; case (spec_ww_head1 (WW w0 w1)); intros H3 H4 H5. + generalize (H4 H2); clear H4; rewrite H5; clear H5; autorewrite with rm10. + intros (H4, H5). + assert (V: wB/4 <= [|w0|]). + apply beta_lex with 0 [|w1|] wB; auto with zarith; autorewrite with rm10. + rewrite <- wwB_4_wB_4; auto. + generalize (@spec_w_sqrt2 w0 w1 V);auto with zarith. + case (w_sqrt2 w0 w1); intros w2 c. + simpl ww_to_Z; simpl fst. + case c; unfold interp_carry; autorewrite with rm10. + intros w3 (H6, H7); rewrite H6. + assert (V1 := spec_to_Z w3);auto with zarith. + split; auto with zarith. + apply Zle_lt_trans with ([|w2|] ^2 + 2 * [|w2|]); auto with zarith. + match goal with |- ?X < ?Z => + replace Z with (X + 1); auto with zarith + end. + repeat rewrite Zsquare_mult; ring. + intros w3 (H6, H7); rewrite H6. + assert (V1 := spec_to_Z w3);auto with zarith. + split; auto with zarith. + apply Zle_lt_trans with ([|w2|] ^2 + 2 * [|w2|]); auto with zarith. + match goal with |- ?X < ?Z => + replace Z with (X + 1); auto with zarith + end. + repeat rewrite Zsquare_mult; ring. + intros HH; case (spec_to_w_Z (ww_head1 x)); auto with zarith. + intros Hv1. + case (spec_ww_head1 x); intros Hp1 Hp2. + generalize (Hp2 H1); clear Hp2; intros Hp2. + assert (Hv2: [[ww_head1 x]] <= Zpos (xO w_digits)). + case (Zle_or_lt (Zpos (xO w_digits)) [[ww_head1 x]]); auto with zarith; intros HH1. + case Hp2; intros _ HH2; contradict HH2. + apply Zle_not_lt; unfold base. + apply Zle_trans with (2 ^ [[ww_head1 x]]). + apply Zpower_le_monotone; auto with zarith. + pattern (2 ^ [[ww_head1 x]]) at 1; + rewrite <- (Zmult_1_r (2 ^ [[ww_head1 x]])). + apply Zmult_le_compat_l; auto with zarith. + generalize (spec_ww_add_mul_div x W0 (ww_head1 x) Hv2); + case ww_add_mul_div. + simpl ww_to_Z; autorewrite with w_rewrite rm10. + rewrite Zmod_small; auto with zarith. + intros H2; case (Zmult_integral _ _ (sym_equal H2)); clear H2; intros H2. + rewrite H2; unfold Zpower, Zpower_pos; simpl; auto with zarith. + match type of H2 with ?X = ?Y => + absurd (Y < X); try (rewrite H2; auto with zarith; fail) + end. + apply Zpower_gt_0; auto with zarith. + split; auto with zarith. + case Hp2; intros _ tmp; apply Zle_lt_trans with (2 := tmp); + clear tmp. + rewrite Zmult_comm; apply Zmult_le_compat_r; auto with zarith. + assert (Hv0: [[ww_head1 x]] = 2 * ([[ww_head1 x]]/2)). + pattern [[ww_head1 x]] at 1; rewrite (Z_div_mod_eq [[ww_head1 x]] 2); + auto with zarith. + generalize (spec_ww_is_even (ww_head1 x)); rewrite Hp1; + intros tmp; rewrite tmp; rewrite Zplus_0_r; auto. + intros w0 w1; autorewrite with w_rewrite rm10. + rewrite Zmod_small; auto with zarith. + 2: rewrite Zmult_comm; auto with zarith. + intros H2. + assert (V: wB/4 <= [|w0|]). + apply beta_lex with 0 [|w1|] wB; auto with zarith; autorewrite with rm10. + simpl ww_to_Z in H2; rewrite H2. + rewrite <- wwB_4_wB_4; auto with zarith. + rewrite Zmult_comm; auto with zarith. + assert (V1 := spec_to_Z w1);auto with zarith. + generalize (@spec_w_sqrt2 w0 w1 V);auto with zarith. + case (w_sqrt2 w0 w1); intros w2 c. + case (spec_to_Z w2); intros HH1 HH2. + simpl ww_to_Z; simpl fst. + assert (Hv3: [[ww_pred ww_zdigits]] + = Zpos (xO w_digits) - 1). + rewrite spec_ww_pred; rewrite spec_ww_zdigits. + rewrite Zmod_small; auto with zarith. + split; auto with zarith. + apply Zlt_le_trans with (Zpos (xO w_digits)); auto with zarith. + unfold base; apply Zpower2_le_lin; auto with zarith. + assert (Hv4: [[ww_head1 x]]/2 < wB). + apply Zle_lt_trans with (Zpos w_digits). + apply Zmult_le_reg_r with 2; auto with zarith. + repeat rewrite (fun x => Zmult_comm x 2). + rewrite <- Hv0; rewrite <- Zpos_xO; auto. + unfold base; apply Zpower2_lt_lin; auto with zarith. + assert (Hv5: [[(ww_add_mul_div (ww_pred ww_zdigits) W0 (ww_head1 x))]] + = [[ww_head1 x]]/2). + rewrite spec_ww_add_mul_div. + simpl ww_to_Z; autorewrite with rm10. + rewrite Hv3. + ring_simplify (Zpos (xO w_digits) - (Zpos (xO w_digits) - 1)). + rewrite Zpower_1_r. + rewrite Zmod_small; auto with zarith. + split; auto with zarith. + apply Zlt_le_trans with (1 := Hv4); auto with zarith. + unfold base; apply Zpower_le_monotone; auto with zarith. + split; unfold ww_digits; try rewrite Zpos_xO; auto with zarith. + rewrite Hv3; auto with zarith. + assert (Hv6: [|low(ww_add_mul_div (ww_pred ww_zdigits) W0 (ww_head1 x))|] + = [[ww_head1 x]]/2). + rewrite spec_low. + rewrite Hv5; rewrite Zmod_small; auto with zarith. + rewrite spec_w_add_mul_div; auto with zarith. + rewrite spec_w_sub; auto with zarith. + rewrite spec_w_0. + simpl ww_to_Z; autorewrite with rm10. + rewrite Hv6; rewrite spec_w_zdigits. + rewrite (fun x y => Zmod_small (x - y)). + ring_simplify (Zpos w_digits - (Zpos w_digits - [[ww_head1 x]] / 2)). + rewrite Zmod_small. + simpl ww_to_Z in H2; rewrite H2; auto with zarith. + intros (H4, H5); split. + apply Zmult_le_reg_r with (2 ^ [[ww_head1 x]]); auto with zarith. + rewrite H4. + apply Zle_trans with ([|w2|] ^ 2); auto with zarith. + rewrite Zmult_comm. + pattern [[ww_head1 x]] at 1; + rewrite Hv0; auto with zarith. + rewrite (Zmult_comm 2); rewrite Zpower_mult; + auto with zarith. + assert (tmp: forall p q, p ^ 2 * q ^ 2 = (p * q) ^2); + try (intros; repeat rewrite Zsquare_mult; ring); + rewrite tmp; clear tmp. + apply Zpower_le_monotone3; auto with zarith. + split; auto with zarith. + pattern [|w2|] at 2; + rewrite (Z_div_mod_eq [|w2|] (2 ^ ([[ww_head1 x]] / 2))); + auto with zarith. + match goal with |- ?X <= ?X + ?Y => + assert (0 <= Y); auto with zarith + end. + case (Z_mod_lt [|w2|] (2 ^ ([[ww_head1 x]] / 2))); auto with zarith. + case c; unfold interp_carry; autorewrite with rm10; + intros w3; assert (V3 := spec_to_Z w3);auto with zarith. + apply Zmult_lt_reg_r with (2 ^ [[ww_head1 x]]); auto with zarith. + rewrite H4. + apply Zle_lt_trans with ([|w2|] ^ 2 + 2 * [|w2|]); auto with zarith. + apply Zlt_le_trans with (([|w2|] + 1) ^ 2); auto with zarith. + match goal with |- ?X < ?Y => + replace Y with (X + 1); auto with zarith + end. + repeat rewrite (Zsquare_mult); ring. + rewrite Zmult_comm. + pattern [[ww_head1 x]] at 1; rewrite Hv0. + rewrite (Zmult_comm 2); rewrite Zpower_mult; + auto with zarith. + assert (tmp: forall p q, p ^ 2 * q ^ 2 = (p * q) ^2); + try (intros; repeat rewrite Zsquare_mult; ring); + rewrite tmp; clear tmp. + apply Zpower_le_monotone3; auto with zarith. + split; auto with zarith. + pattern [|w2|] at 1; rewrite (Z_div_mod_eq [|w2|] (2 ^ ([[ww_head1 x]]/2))); + auto with zarith. + rewrite <- Zplus_assoc; rewrite Zmult_plus_distr_r. + autorewrite with rm10; apply Zplus_le_compat_l; auto with zarith. + case (Z_mod_lt [|w2|] (2 ^ ([[ww_head1 x]]/2))); auto with zarith. + split; auto with zarith. + apply Zle_lt_trans with ([|w2|]); auto with zarith. + apply Zdiv_le_upper_bound; auto with zarith. + pattern [|w2|] at 1; replace [|w2|] with ([|w2|] * 2 ^0); + auto with zarith. + apply Zmult_le_compat_l; auto with zarith. + apply Zpower_le_monotone; auto with zarith. + rewrite Zpower_0_r; autorewrite with rm10; auto. + split; auto with zarith. + rewrite Hv0 in Hv2; rewrite (Zpos_xO w_digits) in Hv2; auto with zarith. + apply Zle_lt_trans with (Zpos w_digits); auto with zarith. + unfold base; apply Zpower2_lt_lin; auto with zarith. + rewrite spec_w_sub; auto with zarith. + rewrite Hv6; rewrite spec_w_zdigits; auto with zarith. + assert (Hv7: 0 < [[ww_head1 x]]/2); auto with zarith. + rewrite Zmod_small; auto with zarith. + split; auto with zarith. + assert ([[ww_head1 x]]/2 <= Zpos w_digits); auto with zarith. + apply Zmult_le_reg_r with 2; auto with zarith. + repeat rewrite (fun x => Zmult_comm x 2). + rewrite <- Hv0; rewrite <- Zpos_xO; auto with zarith. + apply Zle_lt_trans with (Zpos w_digits); auto with zarith. + unfold base; apply Zpower2_lt_lin; auto with zarith. + Qed. + +End DoubleSqrt. diff --git a/theories/Numbers/Cyclic/DoubleCyclic/DoubleSub.v b/theories/Numbers/Cyclic/DoubleCyclic/DoubleSub.v new file mode 100644 index 00000000..269d62bb --- /dev/null +++ b/theories/Numbers/Cyclic/DoubleCyclic/DoubleSub.v @@ -0,0 +1,357 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: DoubleSub.v 10964 2008-05-22 11:08:13Z letouzey $ i*) + +Set Implicit Arguments. + +Require Import ZArith. +Require Import BigNumPrelude. +Require Import DoubleType. +Require Import DoubleBase. + +Open Local Scope Z_scope. + +Section DoubleSub. + Variable w : Type. + Variable w_0 : w. + Variable w_Bm1 : w. + Variable w_WW : w -> w -> zn2z w. + Variable ww_Bm1 : zn2z w. + Variable w_opp_c : w -> carry w. + Variable w_opp_carry : w -> w. + Variable w_pred_c : w -> carry w. + Variable w_sub_c : w -> w -> carry w. + Variable w_sub_carry_c : w -> w -> carry w. + Variable w_opp : w -> w. + Variable w_pred : w -> w. + Variable w_sub : w -> w -> w. + Variable w_sub_carry : w -> w -> w. + + (* ** Opposites ** *) + Definition ww_opp_c x := + match x with + | W0 => C0 W0 + | WW xh xl => + match w_opp_c xl with + | C0 _ => + match w_opp_c xh with + | C0 h => C0 W0 + | C1 h => C1 (WW h w_0) + end + | C1 l => C1 (WW (w_opp_carry xh) l) + end + end. + + Definition ww_opp x := + match x with + | W0 => W0 + | WW xh xl => + match w_opp_c xl with + | C0 _ => WW (w_opp xh) w_0 + | C1 l => WW (w_opp_carry xh) l + end + end. + + Definition ww_opp_carry x := + match x with + | W0 => ww_Bm1 + | WW xh xl => w_WW (w_opp_carry xh) (w_opp_carry xl) + end. + + Definition ww_pred_c x := + match x with + | W0 => C1 ww_Bm1 + | WW xh xl => + match w_pred_c xl with + | C0 l => C0 (w_WW xh l) + | C1 _ => + match w_pred_c xh with + | C0 h => C0 (WW h w_Bm1) + | C1 _ => C1 ww_Bm1 + end + end + end. + + Definition ww_pred x := + match x with + | W0 => ww_Bm1 + | WW xh xl => + match w_pred_c xl with + | C0 l => w_WW xh l + | C1 l => WW (w_pred xh) w_Bm1 + end + end. + + Definition ww_sub_c x y := + match y, x with + | W0, _ => C0 x + | WW yh yl, W0 => ww_opp_c (WW yh yl) + | WW yh yl, WW xh xl => + match w_sub_c xl yl with + | C0 l => + match w_sub_c xh yh with + | C0 h => C0 (w_WW h l) + | C1 h => C1 (WW h l) + end + | C1 l => + match w_sub_carry_c xh yh with + | C0 h => C0 (WW h l) + | C1 h => C1 (WW h l) + end + end + end. + + Definition ww_sub x y := + match y, x with + | W0, _ => x + | WW yh yl, W0 => ww_opp (WW yh yl) + | WW yh yl, WW xh xl => + match w_sub_c xl yl with + | C0 l => w_WW (w_sub xh yh) l + | C1 l => WW (w_sub_carry xh yh) l + end + end. + + Definition ww_sub_carry_c x y := + match y, x with + | W0, W0 => C1 ww_Bm1 + | W0, WW xh xl => ww_pred_c (WW xh xl) + | WW yh yl, W0 => C1 (ww_opp_carry (WW yh yl)) + | WW yh yl, WW xh xl => + match w_sub_carry_c xl yl with + | C0 l => + match w_sub_c xh yh with + | C0 h => C0 (w_WW h l) + | C1 h => C1 (WW h l) + end + | C1 l => + match w_sub_carry_c xh yh with + | C0 h => C0 (w_WW h l) + | C1 h => C1 (w_WW h l) + end + end + end. + + Definition ww_sub_carry x y := + match y, x with + | W0, W0 => ww_Bm1 + | W0, WW xh xl => ww_pred (WW xh xl) + | WW yh yl, W0 => ww_opp_carry (WW yh yl) + | WW yh yl, WW xh xl => + match w_sub_carry_c xl yl with + | C0 l => w_WW (w_sub xh yh) l + | C1 l => w_WW (w_sub_carry xh yh) l + end + end. + + (*Section DoubleProof.*) + Variable w_digits : positive. + Variable w_to_Z : w -> Z. + + + Notation wB := (base w_digits). + Notation wwB := (base (ww_digits w_digits)). + Notation "[| x |]" := (w_to_Z x) (at level 0, x at level 99). + Notation "[+| c |]" := + (interp_carry 1 wB w_to_Z c) (at level 0, x at level 99). + Notation "[-| c |]" := + (interp_carry (-1) wB w_to_Z c) (at level 0, x at level 99). + + Notation "[[ x ]]" := (ww_to_Z w_digits w_to_Z x)(at level 0, x at level 99). + Notation "[+[ c ]]" := + (interp_carry 1 wwB (ww_to_Z w_digits w_to_Z) c) + (at level 0, x at level 99). + Notation "[-[ c ]]" := + (interp_carry (-1) wwB (ww_to_Z w_digits w_to_Z) c) + (at level 0, x at level 99). + + Variable spec_w_0 : [|w_0|] = 0. + Variable spec_w_Bm1 : [|w_Bm1|] = wB - 1. + Variable spec_ww_Bm1 : [[ww_Bm1]] = wwB - 1. + Variable spec_to_Z : forall x, 0 <= [|x|] < wB. + Variable spec_w_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|]. + + Variable spec_opp_c : forall x, [-|w_opp_c x|] = -[|x|]. + Variable spec_opp : forall x, [|w_opp x|] = (-[|x|]) mod wB. + Variable spec_opp_carry : forall x, [|w_opp_carry x|] = wB - [|x|] - 1. + + Variable spec_pred_c : forall x, [-|w_pred_c x|] = [|x|] - 1. + Variable spec_sub_c : forall x y, [-|w_sub_c x y|] = [|x|] - [|y|]. + Variable spec_sub_carry_c : + forall x y, [-|w_sub_carry_c x y|] = [|x|] - [|y|] - 1. + + Variable spec_pred : forall x, [|w_pred x|] = ([|x|] - 1) mod wB. + Variable spec_sub : forall x y, [|w_sub x y|] = ([|x|] - [|y|]) mod wB. + Variable spec_sub_carry : + forall x y, [|w_sub_carry x y|] = ([|x|] - [|y|] - 1) mod wB. + + + Lemma spec_ww_opp_c : forall x, [-[ww_opp_c x]] = -[[x]]. + Proof. + destruct x as [ |xh xl];simpl. reflexivity. + rewrite Zopp_plus_distr;generalize (spec_opp_c xl);destruct (w_opp_c xl) + as [l|l];intros H;unfold interp_carry in H;rewrite <- H; + rewrite Zopp_mult_distr_l. + assert ([|l|] = 0). + assert (H1:= spec_to_Z l);assert (H2 := spec_to_Z xl);omega. + rewrite H0;generalize (spec_opp_c xh);destruct (w_opp_c xh) + as [h|h];intros H1;unfold interp_carry in *;rewrite <- H1. + assert ([|h|] = 0). + assert (H3:= spec_to_Z h);assert (H2 := spec_to_Z xh);omega. + rewrite H2;reflexivity. + simpl ww_to_Z;rewrite wwB_wBwB;rewrite spec_w_0;ring. + unfold interp_carry;simpl ww_to_Z;rewrite wwB_wBwB;rewrite spec_opp_carry; + ring. + Qed. + + Lemma spec_ww_opp : forall x, [[ww_opp x]] = (-[[x]]) mod wwB. + Proof. + destruct x as [ |xh xl];simpl. reflexivity. + rewrite Zopp_plus_distr;rewrite Zopp_mult_distr_l. + generalize (spec_opp_c xl);destruct (w_opp_c xl) + as [l|l];intros H;unfold interp_carry in H;rewrite <- H;simpl ww_to_Z. + rewrite spec_w_0;rewrite Zplus_0_r;rewrite wwB_wBwB. + assert ([|l|] = 0). + assert (H1:= spec_to_Z l);assert (H2 := spec_to_Z xl);omega. + rewrite H0;rewrite Zplus_0_r; rewrite Zpower_2; + rewrite Zmult_mod_distr_r;try apply lt_0_wB. + rewrite spec_opp;trivial. + apply Zmod_unique with (q:= -1). + exact (spec_ww_to_Z w_digits w_to_Z spec_to_Z (WW (w_opp_carry xh) l)). + rewrite spec_opp_carry;rewrite wwB_wBwB;ring. + Qed. + + Lemma spec_ww_opp_carry : forall x, [[ww_opp_carry x]] = wwB - [[x]] - 1. + Proof. + destruct x as [ |xh xl];simpl. rewrite spec_ww_Bm1;ring. + rewrite spec_w_WW;simpl;repeat rewrite spec_opp_carry;rewrite wwB_wBwB;ring. + Qed. + + Lemma spec_ww_pred_c : forall x, [-[ww_pred_c x]] = [[x]] - 1. + Proof. + destruct x as [ |xh xl];unfold ww_pred_c. + unfold interp_carry;rewrite spec_ww_Bm1;simpl ww_to_Z;ring. + simpl ww_to_Z;replace (([|xh|]*wB+[|xl|])-1) with ([|xh|]*wB+([|xl|]-1)). + 2:ring. generalize (spec_pred_c xl);destruct (w_pred_c xl) as [l|l]; + intros H;unfold interp_carry in H;rewrite <- H. simpl;apply spec_w_WW. + rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. + assert ([|l|] = wB - 1). + assert (H1:= spec_to_Z l);assert (H2 := spec_to_Z xl);omega. + rewrite H0;change ([|xh|] + -1) with ([|xh|] - 1). + generalize (spec_pred_c xh);destruct (w_pred_c xh) as [h|h]; + intros H1;unfold interp_carry in H1;rewrite <- H1. + simpl;rewrite spec_w_Bm1;ring. + assert ([|h|] = wB - 1). + assert (H3:= spec_to_Z h);assert (H2 := spec_to_Z xh);omega. + rewrite H2;unfold interp_carry;rewrite spec_ww_Bm1;rewrite wwB_wBwB;ring. + Qed. + + Lemma spec_ww_sub_c : forall x y, [-[ww_sub_c x y]] = [[x]] - [[y]]. + Proof. + destruct y as [ |yh yl];simpl. ring. + destruct x as [ |xh xl];simpl. exact (spec_ww_opp_c (WW yh yl)). + replace ([|xh|] * wB + [|xl|] - ([|yh|] * wB + [|yl|])) + with (([|xh|]-[|yh|])*wB + ([|xl|]-[|yl|])). 2:ring. + generalize (spec_sub_c xl yl);destruct (w_sub_c xl yl) as [l|l];intros H; + unfold interp_carry in H;rewrite <- H. + generalize (spec_sub_c xh yh);destruct (w_sub_c xh yh) as [h|h];intros H1; + unfold interp_carry in H1;rewrite <- H1;unfold interp_carry; + try rewrite spec_w_WW;simpl ww_to_Z;try rewrite wwB_wBwB;ring. + rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. + change ([|xh|] - [|yh|] + -1) with ([|xh|] - [|yh|] - 1). + generalize (spec_sub_carry_c xh yh);destruct (w_sub_carry_c xh yh) as [h|h]; + intros H1;unfold interp_carry in *;rewrite <- H1;simpl ww_to_Z; + try rewrite wwB_wBwB;ring. + Qed. + + Lemma spec_ww_sub_carry_c : + forall x y, [-[ww_sub_carry_c x y]] = [[x]] - [[y]] - 1. + Proof. + destruct y as [ |yh yl];simpl. + unfold Zminus;simpl;rewrite Zplus_0_r;exact (spec_ww_pred_c x). + destruct x as [ |xh xl]. + unfold interp_carry;rewrite spec_w_WW;simpl ww_to_Z;rewrite wwB_wBwB; + repeat rewrite spec_opp_carry;ring. + simpl ww_to_Z. + replace ([|xh|] * wB + [|xl|] - ([|yh|] * wB + [|yl|]) - 1) + with (([|xh|]-[|yh|])*wB + ([|xl|]-[|yl|]-1)). 2:ring. + generalize (spec_sub_carry_c xl yl);destruct (w_sub_carry_c xl yl) + as [l|l];intros H;unfold interp_carry in H;rewrite <- H. + generalize (spec_sub_c xh yh);destruct (w_sub_c xh yh) as [h|h];intros H1; + unfold interp_carry in H1;rewrite <- H1;unfold interp_carry; + try rewrite spec_w_WW;simpl ww_to_Z;try rewrite wwB_wBwB;ring. + rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. + change ([|xh|] - [|yh|] + -1) with ([|xh|] - [|yh|] - 1). + generalize (spec_sub_carry_c xh yh);destruct (w_sub_carry_c xh yh) as [h|h]; + intros H1;unfold interp_carry in *;rewrite <- H1;try rewrite spec_w_WW; + simpl ww_to_Z; try rewrite wwB_wBwB;ring. + Qed. + + Lemma spec_ww_pred : forall x, [[ww_pred x]] = ([[x]] - 1) mod wwB. + Proof. + destruct x as [ |xh xl];simpl. + apply Zmod_unique with (-1). apply spec_ww_to_Z;trivial. + rewrite spec_ww_Bm1;ring. + replace ([|xh|]*wB + [|xl|] - 1) with ([|xh|]*wB + ([|xl|] - 1)). 2:ring. + generalize (spec_pred_c xl);destruct (w_pred_c xl) as [l|l];intro H; + unfold interp_carry in H;rewrite <- H;simpl ww_to_Z. + rewrite Zmod_small. apply spec_w_WW. + exact (spec_ww_to_Z w_digits w_to_Z spec_to_Z (WW xh l)). + rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. + change ([|xh|] + -1) with ([|xh|] - 1). + assert ([|l|] = wB - 1). + assert (H1:= spec_to_Z l);assert (H2:= spec_to_Z xl);omega. + rewrite (mod_wwB w_digits w_to_Z);trivial. + rewrite spec_pred;rewrite spec_w_Bm1;rewrite <- H0;trivial. + Qed. + + Lemma spec_ww_sub : forall x y, [[ww_sub x y]] = ([[x]] - [[y]]) mod wwB. + Proof. + destruct y as [ |yh yl];simpl. + ring_simplify ([[x]] - 0);rewrite Zmod_small;trivial. apply spec_ww_to_Z;trivial. + destruct x as [ |xh xl];simpl. exact (spec_ww_opp (WW yh yl)). + replace ([|xh|] * wB + [|xl|] - ([|yh|] * wB + [|yl|])) + with (([|xh|] - [|yh|]) * wB + ([|xl|] - [|yl|])). 2:ring. + generalize (spec_sub_c xl yl);destruct (w_sub_c xl yl)as[l|l];intros H; + unfold interp_carry in H;rewrite <- H. + rewrite spec_w_WW;rewrite (mod_wwB w_digits w_to_Z spec_to_Z). + rewrite spec_sub;trivial. + simpl ww_to_Z;rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. + rewrite (mod_wwB w_digits w_to_Z spec_to_Z);rewrite spec_sub_carry;trivial. + Qed. + + Lemma spec_ww_sub_carry : + forall x y, [[ww_sub_carry x y]] = ([[x]] - [[y]] - 1) mod wwB. + Proof. + destruct y as [ |yh yl];simpl. + ring_simplify ([[x]] - 0);exact (spec_ww_pred x). + destruct x as [ |xh xl];simpl. + apply Zmod_unique with (-1). + apply spec_ww_to_Z;trivial. + fold (ww_opp_carry (WW yh yl)). + rewrite (spec_ww_opp_carry (WW yh yl));simpl ww_to_Z;ring. + replace ([|xh|] * wB + [|xl|] - ([|yh|] * wB + [|yl|]) - 1) + with (([|xh|] - [|yh|]) * wB + ([|xl|] - [|yl|] - 1)). 2:ring. + generalize (spec_sub_carry_c xl yl);destruct (w_sub_carry_c xl yl)as[l|l]; + intros H;unfold interp_carry in H;rewrite <- H;rewrite spec_w_WW. + rewrite (mod_wwB w_digits w_to_Z spec_to_Z);rewrite spec_sub;trivial. + rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. + rewrite (mod_wwB w_digits w_to_Z spec_to_Z);rewrite spec_sub_carry;trivial. + Qed. + +(* End DoubleProof. *) + +End DoubleSub. + + + + + diff --git a/theories/Numbers/Cyclic/DoubleCyclic/DoubleType.v b/theories/Numbers/Cyclic/DoubleCyclic/DoubleType.v new file mode 100644 index 00000000..28d40094 --- /dev/null +++ b/theories/Numbers/Cyclic/DoubleCyclic/DoubleType.v @@ -0,0 +1,71 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: DoubleType.v 10964 2008-05-22 11:08:13Z letouzey $ i*) + +Set Implicit Arguments. + +Require Import ZArith. +Open Local Scope Z_scope. + +Definition base digits := Zpower 2 (Zpos digits). + +Section Carry. + + Variable A : Type. + + Inductive carry := + | C0 : A -> carry + | C1 : A -> carry. + + Definition interp_carry (sign:Z)(B:Z)(interp:A -> Z) c := + match c with + | C0 x => interp x + | C1 x => sign*B + interp x + end. + +End Carry. + +Section Zn2Z. + + Variable znz : Type. + + (** From a type [znz] representing a cyclic structure Z/nZ, + we produce a representation of Z/2nZ by pairs of elements of [znz] + (plus a special case for zero). High half of the new number comes + first. + *) + + Inductive zn2z := + | W0 : zn2z + | WW : znz -> znz -> zn2z. + + Definition zn2z_to_Z (wB:Z) (w_to_Z:znz->Z) (x:zn2z) := + match x with + | W0 => 0 + | WW xh xl => w_to_Z xh * wB + w_to_Z xl + end. + +End Zn2Z. + +Implicit Arguments W0 [znz]. + +(** From a cyclic representation [w], we iterate the [zn2z] construct + [n] times, gaining the type of binary trees of depth at most [n], + whose leafs are either W0 (if depth < n) or elements of w + (if depth = n). +*) + +Fixpoint word (w:Type) (n:nat) : Type := + match n with + | O => w + | S n => zn2z (word w n) + end. + diff --git a/theories/Numbers/Cyclic/Int31/Cyclic31.v b/theories/Numbers/Cyclic/Int31/Cyclic31.v new file mode 100644 index 00000000..4d655eac --- /dev/null +++ b/theories/Numbers/Cyclic/Int31/Cyclic31.v @@ -0,0 +1,2516 @@ +(************************************************************************) +(* 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: Cyclic31.v 11034 2008-06-02 08:15:34Z thery $ i*) + +(** * Int31 numbers defines indeed a cyclic structure : Z/(2^31)Z *) + +(** +Author: Arnaud Spiwack (+ Pierre Letouzey) +*) + +Require Import List. +Require Import Min. +Require Export Int31. +Require Import Znumtheory. +Require Import Zgcd_alt. +Require Import Zpow_facts. +Require Import BigNumPrelude. +Require Import CyclicAxioms. +Require Import ROmega. + +Open Scope nat_scope. +Open Scope int31_scope. + +Section Basics. + + (** * Basic results about [iszero], [shiftl], [shiftr] *) + + Lemma iszero_eq0 : forall x, iszero x = true -> x=0. + Proof. + destruct x; simpl; intros. + repeat + match goal with H:(if ?d then _ else _) = true |- _ => + destruct d; try discriminate + end. + reflexivity. + Qed. + + Lemma iszero_not_eq0 : forall x, iszero x = false -> x<>0. + Proof. + intros x H Eq; rewrite Eq in H; simpl in *; discriminate. + Qed. + + Lemma sneakl_shiftr : forall x, + x = sneakl (firstr x) (shiftr x). + Proof. + destruct x; simpl; auto. + Qed. + + Lemma sneakr_shiftl : forall x, + x = sneakr (firstl x) (shiftl x). + Proof. + destruct x; simpl; auto. + Qed. + + Lemma twice_zero : forall x, + twice x = 0 <-> twice_plus_one x = 1. + Proof. + destruct x; simpl in *; split; + intro H; injection H; intros; subst; auto. + Qed. + + Lemma twice_or_twice_plus_one : forall x, + x = twice (shiftr x) \/ x = twice_plus_one (shiftr x). + Proof. + intros; case_eq (firstr x); intros. + destruct x; simpl in *; rewrite H; auto. + destruct x; simpl in *; rewrite H; auto. + Qed. + + + + (** * Iterated shift to the right *) + + Definition nshiftr n x := iter_nat n _ shiftr x. + + Lemma nshiftr_S : + forall n x, nshiftr (S n) x = shiftr (nshiftr n x). + Proof. + reflexivity. + Qed. + + Lemma nshiftr_S_tail : + forall n x, nshiftr (S n) x = nshiftr n (shiftr x). + Proof. + induction n; simpl; auto. + intros; rewrite nshiftr_S, IHn, nshiftr_S; auto. + Qed. + + Lemma nshiftr_n_0 : forall n, nshiftr n 0 = 0. + Proof. + induction n; simpl; auto. + rewrite nshiftr_S, IHn; auto. + Qed. + + Lemma nshiftr_size : forall x, nshiftr size x = 0. + Proof. + destruct x; simpl; auto. + Qed. + + Lemma nshiftr_above_size : forall k x, size<=k -> + nshiftr k x = 0. + Proof. + intros. + replace k with ((k-size)+size)%nat by omega. + induction (k-size)%nat; auto. + rewrite nshiftr_size; auto. + simpl; rewrite nshiftr_S, IHn; auto. + Qed. + + (** * Iterated shift to the left *) + + Definition nshiftl n x := iter_nat n _ shiftl x. + + Lemma nshiftl_S : + forall n x, nshiftl (S n) x = shiftl (nshiftl n x). + Proof. + reflexivity. + Qed. + + Lemma nshiftl_S_tail : + forall n x, nshiftl (S n) x = nshiftl n (shiftl x). + Proof. + induction n; simpl; auto. + intros; rewrite nshiftl_S, IHn, nshiftl_S; auto. + Qed. + + Lemma nshiftl_n_0 : forall n, nshiftl n 0 = 0. + Proof. + induction n; simpl; auto. + rewrite nshiftl_S, IHn; auto. + Qed. + + Lemma nshiftl_size : forall x, nshiftl size x = 0. + Proof. + destruct x; simpl; auto. + Qed. + + Lemma nshiftl_above_size : forall k x, size<=k -> + nshiftl k x = 0. + Proof. + intros. + replace k with ((k-size)+size)%nat by omega. + induction (k-size)%nat; auto. + rewrite nshiftl_size; auto. + simpl; rewrite nshiftl_S, IHn; auto. + Qed. + + Lemma firstr_firstl : + forall x, firstr x = firstl (nshiftl (pred size) x). + Proof. + destruct x; simpl; auto. + Qed. + + Lemma firstl_firstr : + forall x, firstl x = firstr (nshiftr (pred size) x). + Proof. + destruct x; simpl; auto. + Qed. + + (** More advanced results about [nshiftr] *) + + Lemma nshiftr_predsize_0_firstl : forall x, + nshiftr (pred size) x = 0 -> firstl x = D0. + Proof. + destruct x; compute; intros H; injection H; intros; subst; auto. + Qed. + + Lemma nshiftr_0_propagates : forall n p x, n <= p -> + nshiftr n x = 0 -> nshiftr p x = 0. + Proof. + intros. + replace p with ((p-n)+n)%nat by omega. + induction (p-n)%nat. + simpl; auto. + simpl; rewrite nshiftr_S; rewrite IHn0; auto. + Qed. + + Lemma nshiftr_0_firstl : forall n x, n < size -> + nshiftr n x = 0 -> firstl x = D0. + Proof. + intros. + apply nshiftr_predsize_0_firstl. + apply nshiftr_0_propagates with n; auto; omega. + Qed. + + (** * Some induction principles over [int31] *) + + (** Not used for the moment. Are they really useful ? *) + + Lemma int31_ind_sneakl : forall P : int31->Prop, + P 0 -> + (forall x d, P x -> P (sneakl d x)) -> + forall x, P x. + Proof. + intros. + assert (forall n, n<=size -> P (nshiftr (size - n) x)). + induction n; intros. + rewrite nshiftr_size; auto. + rewrite sneakl_shiftr. + apply H0. + change (P (nshiftr (S (size - S n)) x)). + replace (S (size - S n))%nat with (size - n)%nat by omega. + apply IHn; omega. + change x with (nshiftr (size-size) x); auto. + Qed. + + Lemma int31_ind_twice : forall P : int31->Prop, + P 0 -> + (forall x, P x -> P (twice x)) -> + (forall x, P x -> P (twice_plus_one x)) -> + forall x, P x. + Proof. + induction x using int31_ind_sneakl; auto. + destruct d; auto. + Qed. + + + (** * Some generic results about [recr] *) + + Section Recr. + + (** [recr] satisfies the fixpoint equation used for its definition. *) + + Variable (A:Type)(case0:A)(caserec:digits->int31->A->A). + + Lemma recr_aux_eqn : forall n x, iszero x = false -> + recr_aux (S n) A case0 caserec x = + caserec (firstr x) (shiftr x) (recr_aux n A case0 caserec (shiftr x)). + Proof. + intros; simpl; rewrite H; auto. + Qed. + + Lemma recr_aux_converges : + forall n p x, n <= size -> n <= p -> + recr_aux n A case0 caserec (nshiftr (size - n) x) = + recr_aux p A case0 caserec (nshiftr (size - n) x). + Proof. + induction n. + simpl; intros. + rewrite nshiftr_size; destruct p; simpl; auto. + intros. + destruct p. + inversion H0. + unfold recr_aux; fold recr_aux. + destruct (iszero (nshiftr (size - S n) x)); auto. + f_equal. + change (shiftr (nshiftr (size - S n) x)) with (nshiftr (S (size - S n)) x). + replace (S (size - S n))%nat with (size - n)%nat by omega. + apply IHn; auto with arith. + Qed. + + Lemma recr_eqn : forall x, iszero x = false -> + recr A case0 caserec x = + caserec (firstr x) (shiftr x) (recr A case0 caserec (shiftr x)). + Proof. + intros. + unfold recr. + change x with (nshiftr (size - size) x). + rewrite (recr_aux_converges size (S size)); auto with arith. + rewrite recr_aux_eqn; auto. + Qed. + + (** [recr] is usually equivalent to a variant [recrbis] + written without [iszero] check. *) + + Fixpoint recrbis_aux (n:nat)(A:Type)(case0:A)(caserec:digits->int31->A->A) + (i:int31) : A := + match n with + | O => case0 + | S next => + let si := shiftr i in + caserec (firstr i) si (recrbis_aux next A case0 caserec si) + end. + + Definition recrbis := recrbis_aux size. + + Hypothesis case0_caserec : caserec D0 0 case0 = case0. + + Lemma recrbis_aux_equiv : forall n x, + recrbis_aux n A case0 caserec x = recr_aux n A case0 caserec x. + Proof. + induction n; simpl; auto; intros. + case_eq (iszero x); intros; [ | f_equal; auto ]. + rewrite (iszero_eq0 _ H); simpl; auto. + replace (recrbis_aux n A case0 caserec 0) with case0; auto. + clear H IHn; induction n; simpl; congruence. + Qed. + + Lemma recrbis_equiv : forall x, + recrbis A case0 caserec x = recr A case0 caserec x. + Proof. + intros; apply recrbis_aux_equiv; auto. + Qed. + + End Recr. + + (** * Incrementation *) + + Section Incr. + + (** Variant of [incr] via [recrbis] *) + + Let Incr (b : digits) (si rec : int31) := + match b with + | D0 => sneakl D1 si + | D1 => sneakl D0 rec + end. + + Definition incrbis_aux n x := recrbis_aux n _ In Incr x. + + Lemma incrbis_aux_equiv : forall x, incrbis_aux size x = incr x. + Proof. + unfold incr, recr, incrbis_aux; fold Incr; intros. + apply recrbis_aux_equiv; auto. + Qed. + + (** Recursive equations satisfied by [incr] *) + + Lemma incr_eqn1 : + forall x, firstr x = D0 -> incr x = twice_plus_one (shiftr x). + Proof. + intros. + case_eq (iszero x); intros. + rewrite (iszero_eq0 _ H0); simpl; auto. + unfold incr; rewrite recr_eqn; fold incr; auto. + rewrite H; auto. + Qed. + + Lemma incr_eqn2 : + forall x, firstr x = D1 -> incr x = twice (incr (shiftr x)). + Proof. + intros. + case_eq (iszero x); intros. + rewrite (iszero_eq0 _ H0) in H; simpl in H; discriminate. + unfold incr; rewrite recr_eqn; fold incr; auto. + rewrite H; auto. + Qed. + + Lemma incr_twice : forall x, incr (twice x) = twice_plus_one x. + Proof. + intros. + rewrite incr_eqn1; destruct x; simpl; auto. + Qed. + + Lemma incr_twice_plus_one_firstl : + forall x, firstl x = D0 -> incr (twice_plus_one x) = twice (incr x). + Proof. + intros. + rewrite incr_eqn2; [ | destruct x; simpl; auto ]. + f_equal; f_equal. + destruct x; simpl in *; rewrite H; auto. + Qed. + + (** The previous result is actually true even without the + constraint on [firstl], but this is harder to prove + (see later). *) + + End Incr. + + (** * Conversion to [Z] : the [phi] function *) + + Section Phi. + + (** Variant of [phi] via [recrbis] *) + + Let Phi := fun b (_:int31) => + match b with D0 => Zdouble | D1 => Zdouble_plus_one end. + + Definition phibis_aux n x := recrbis_aux n _ Z0 Phi x. + + Lemma phibis_aux_equiv : forall x, phibis_aux size x = phi x. + Proof. + unfold phi, recr, phibis_aux; fold Phi; intros. + apply recrbis_aux_equiv; auto. + Qed. + + (** Recursive equations satisfied by [phi] *) + + Lemma phi_eqn1 : forall x, firstr x = D0 -> + phi x = Zdouble (phi (shiftr x)). + Proof. + intros. + case_eq (iszero x); intros. + rewrite (iszero_eq0 _ H0); simpl; auto. + intros; unfold phi; rewrite recr_eqn; fold phi; auto. + rewrite H; auto. + Qed. + + Lemma phi_eqn2 : forall x, firstr x = D1 -> + phi x = Zdouble_plus_one (phi (shiftr x)). + Proof. + intros. + case_eq (iszero x); intros. + rewrite (iszero_eq0 _ H0) in H; simpl in H; discriminate. + intros; unfold phi; rewrite recr_eqn; fold phi; auto. + rewrite H; auto. + Qed. + + Lemma phi_twice_firstl : forall x, firstl x = D0 -> + phi (twice x) = Zdouble (phi x). + Proof. + intros. + rewrite phi_eqn1; auto; [ | destruct x; auto ]. + f_equal; f_equal. + destruct x; simpl in *; rewrite H; auto. + Qed. + + Lemma phi_twice_plus_one_firstl : forall x, firstl x = D0 -> + phi (twice_plus_one x) = Zdouble_plus_one (phi x). + Proof. + intros. + rewrite phi_eqn2; auto; [ | destruct x; auto ]. + f_equal; f_equal. + destruct x; simpl in *; rewrite H; auto. + Qed. + + End Phi. + + (** [phi x] is positive and lower than [2^31] *) + + Lemma phibis_aux_pos : forall n x, (0 <= phibis_aux n x)%Z. + Proof. + induction n. + simpl; unfold phibis_aux; simpl; auto with zarith. + intros. + unfold phibis_aux, recrbis_aux; fold recrbis_aux; + fold (phibis_aux n (shiftr x)). + destruct (firstr x). + specialize IHn with (shiftr x); rewrite Zdouble_mult; omega. + specialize IHn with (shiftr x); rewrite Zdouble_plus_one_mult; omega. + Qed. + + Lemma phibis_aux_bounded : + forall n x, n <= size -> + (phibis_aux n (nshiftr (size-n) x) < 2 ^ (Z_of_nat n))%Z. + Proof. + induction n. + simpl; unfold phibis_aux; simpl; auto with zarith. + intros. + unfold phibis_aux, recrbis_aux; fold recrbis_aux; + fold (phibis_aux n (shiftr (nshiftr (size - S n) x))). + assert (shiftr (nshiftr (size - S n) x) = nshiftr (size-n) x). + replace (size - n)%nat with (S (size - (S n))) by omega. + simpl; auto. + rewrite H0. + assert (H1 : n <= size) by omega. + specialize (IHn x H1). + set (y:=phibis_aux n (nshiftr (size - n) x)) in *. + rewrite inj_S, Zpower_Zsucc; auto with zarith. + case_eq (firstr (nshiftr (size - S n) x)); intros. + rewrite Zdouble_mult; auto with zarith. + rewrite Zdouble_plus_one_mult; auto with zarith. + Qed. + + Lemma phi_bounded : forall x, (0 <= phi x < 2 ^ (Z_of_nat size))%Z. + Proof. + intros. + rewrite <- phibis_aux_equiv. + split. + apply phibis_aux_pos. + change x with (nshiftr (size-size) x). + apply phibis_aux_bounded; auto. + Qed. + + Lemma phibis_aux_lowerbound : + forall n x, firstr (nshiftr n x) = D1 -> + (2 ^ Z_of_nat n <= phibis_aux (S n) x)%Z. + Proof. + induction n. + intros. + unfold nshiftr in H; simpl in *. + unfold phibis_aux, recrbis_aux. + rewrite H, Zdouble_plus_one_mult; omega. + + intros. + remember (S n) as m. + unfold phibis_aux, recrbis_aux; fold recrbis_aux; + fold (phibis_aux m (shiftr x)). + subst m. + rewrite inj_S, Zpower_Zsucc; auto with zarith. + assert (2^(Z_of_nat n) <= phibis_aux (S n) (shiftr x))%Z. + apply IHn. + rewrite <- nshiftr_S_tail; auto. + destruct (firstr x). + change (Zdouble (phibis_aux (S n) (shiftr x))) with + (2*(phibis_aux (S n) (shiftr x)))%Z. + omega. + rewrite Zdouble_plus_one_mult; omega. + Qed. + + Lemma phi_lowerbound : + forall x, firstl x = D1 -> (2^(Z_of_nat (pred size)) <= phi x)%Z. + Proof. + intros. + generalize (phibis_aux_lowerbound (pred size) x). + rewrite <- firstl_firstr. + change (S (pred size)) with size; auto. + rewrite phibis_aux_equiv; auto. + Qed. + + (** * Equivalence modulo [2^n] *) + + Section EqShiftL. + + (** After killing [n] bits at the left, are the numbers equal ?*) + + Definition EqShiftL n x y := + nshiftl n x = nshiftl n y. + + Lemma EqShiftL_zero : forall x y, EqShiftL O x y <-> x = y. + Proof. + unfold EqShiftL; intros; unfold nshiftl; simpl; split; auto. + Qed. + + Lemma EqShiftL_size : forall k x y, size<=k -> EqShiftL k x y. + Proof. + red; intros; rewrite 2 nshiftl_above_size; auto. + Qed. + + Lemma EqShiftL_le : forall k k' x y, k <= k' -> + EqShiftL k x y -> EqShiftL k' x y. + Proof. + unfold EqShiftL; intros. + replace k' with ((k'-k)+k)%nat by omega. + remember (k'-k)%nat as n. + clear Heqn H k'. + induction n; simpl; auto. + rewrite 2 nshiftl_S; f_equal; auto. + Qed. + + Lemma EqShiftL_firstr : forall k x y, k < size -> + EqShiftL k x y -> firstr x = firstr y. + Proof. + intros. + rewrite 2 firstr_firstl. + f_equal. + apply EqShiftL_le with k; auto. + unfold size. + auto with arith. + Qed. + + Lemma EqShiftL_twice : forall k x y, + EqShiftL k (twice x) (twice y) <-> EqShiftL (S k) x y. + Proof. + intros; unfold EqShiftL. + rewrite 2 nshiftl_S_tail; split; auto. + Qed. + + (** * From int31 to list of digits. *) + + (** Lower (=rightmost) bits comes first. *) + + Definition i2l := recrbis _ nil (fun d _ rec => d::rec). + + Lemma i2l_length : forall x, length (i2l x) = size. + Proof. + intros; reflexivity. + Qed. + + Fixpoint lshiftl l x := + match l with + | nil => x + | d::l => sneakl d (lshiftl l x) + end. + + Definition l2i l := lshiftl l On. + + Lemma l2i_i2l : forall x, l2i (i2l x) = x. + Proof. + destruct x; compute; auto. + Qed. + + Lemma i2l_sneakr : forall x d, + i2l (sneakr d x) = tail (i2l x) ++ d::nil. + Proof. + destruct x; compute; auto. + Qed. + + Lemma i2l_sneakl : forall x d, + i2l (sneakl d x) = d :: removelast (i2l x). + Proof. + destruct x; compute; auto. + Qed. + + Lemma i2l_l2i : forall l, length l = size -> + i2l (l2i l) = l. + Proof. + repeat (destruct l as [ |? l]; [intros; discriminate | ]). + destruct l; [ | intros; discriminate]. + intros _; compute; auto. + Qed. + + Fixpoint cstlist (A:Type)(a:A) n := + match n with + | O => nil + | S n => a::cstlist _ a n + end. + + Lemma i2l_nshiftl : forall n x, n<=size -> + i2l (nshiftl n x) = cstlist _ D0 n ++ firstn (size-n) (i2l x). + Proof. + induction n. + intros. + assert (firstn (size-0) (i2l x) = i2l x). + rewrite <- minus_n_O, <- (i2l_length x). + induction (i2l x); simpl; f_equal; auto. + rewrite H0; clear H0. + reflexivity. + + intros. + rewrite nshiftl_S. + unfold shiftl; rewrite i2l_sneakl. + simpl cstlist. + rewrite <- app_comm_cons; f_equal. + rewrite IHn; [ | omega]. + rewrite removelast_app. + f_equal. + replace (size-n)%nat with (S (size - S n))%nat by omega. + rewrite removelast_firstn; auto. + rewrite i2l_length; omega. + generalize (firstn_length (size-n) (i2l x)). + rewrite i2l_length. + intros H0 H1; rewrite H1 in H0. + rewrite min_l in H0 by omega. + simpl length in H0. + omega. + Qed. + + (** [i2l] can be used to define a relation equivalent to [EqShiftL] *) + + Lemma EqShiftL_i2l : forall k x y, + EqShiftL k x y <-> firstn (size-k) (i2l x) = firstn (size-k) (i2l y). + Proof. + intros. + destruct (le_lt_dec size k). + split; intros. + replace (size-k)%nat with O by omega. + unfold firstn; auto. + apply EqShiftL_size; auto. + + unfold EqShiftL. + assert (k <= size) by omega. + split; intros. + assert (i2l (nshiftl k x) = i2l (nshiftl k y)) by (f_equal; auto). + rewrite 2 i2l_nshiftl in H1; auto. + eapply app_inv_head; eauto. + assert (i2l (nshiftl k x) = i2l (nshiftl k y)). + rewrite 2 i2l_nshiftl; auto. + f_equal; auto. + rewrite <- (l2i_i2l (nshiftl k x)), <- (l2i_i2l (nshiftl k y)). + f_equal; auto. + Qed. + + (** This equivalence allows to prove easily the following delicate + result *) + + Lemma EqShiftL_twice_plus_one : forall k x y, + EqShiftL k (twice_plus_one x) (twice_plus_one y) <-> EqShiftL (S k) x y. + Proof. + intros. + destruct (le_lt_dec size k). + split; intros; apply EqShiftL_size; auto. + + rewrite 2 EqShiftL_i2l. + unfold twice_plus_one. + rewrite 2 i2l_sneakl. + replace (size-k)%nat with (S (size - S k))%nat by omega. + remember (size - S k)%nat as n. + remember (i2l x) as lx. + remember (i2l y) as ly. + simpl. + rewrite 2 firstn_removelast. + split; intros. + injection H; auto. + f_equal; auto. + subst ly n; rewrite i2l_length; omega. + subst lx n; rewrite i2l_length; omega. + Qed. + + Lemma EqShiftL_shiftr : forall k x y, EqShiftL k x y -> + EqShiftL (S k) (shiftr x) (shiftr y). + Proof. + intros. + destruct (le_lt_dec size (S k)). + apply EqShiftL_size; auto. + case_eq (firstr x); intros. + rewrite <- EqShiftL_twice. + unfold twice; rewrite <- H0. + rewrite <- sneakl_shiftr. + rewrite (EqShiftL_firstr k x y); auto. + rewrite <- sneakl_shiftr; auto. + omega. + rewrite <- EqShiftL_twice_plus_one. + unfold twice_plus_one; rewrite <- H0. + rewrite <- sneakl_shiftr. + rewrite (EqShiftL_firstr k x y); auto. + rewrite <- sneakl_shiftr; auto. + omega. + Qed. + + Lemma EqShiftL_incrbis : forall n k x y, n<=size -> + (n+k=S size)%nat -> + EqShiftL k x y -> + EqShiftL k (incrbis_aux n x) (incrbis_aux n y). + Proof. + induction n; simpl; intros. + red; auto. + destruct (eq_nat_dec k size). + subst k; apply EqShiftL_size; auto. + unfold incrbis_aux; simpl; + fold (incrbis_aux n (shiftr x)); fold (incrbis_aux n (shiftr y)). + + rewrite (EqShiftL_firstr k x y); auto; try omega. + case_eq (firstr y); intros. + rewrite EqShiftL_twice_plus_one. + apply EqShiftL_shiftr; auto. + + rewrite EqShiftL_twice. + apply IHn; try omega. + apply EqShiftL_shiftr; auto. + Qed. + + Lemma EqShiftL_incr : forall x y, + EqShiftL 1 x y -> EqShiftL 1 (incr x) (incr y). + Proof. + intros. + rewrite <- 2 incrbis_aux_equiv. + apply EqShiftL_incrbis; auto. + Qed. + + End EqShiftL. + + (** * More equations about [incr] *) + + Lemma incr_twice_plus_one : + forall x, incr (twice_plus_one x) = twice (incr x). + Proof. + intros. + rewrite incr_eqn2; [ | destruct x; simpl; auto]. + apply EqShiftL_incr. + red; destruct x; simpl; auto. + Qed. + + Lemma incr_firstr : forall x, firstr (incr x) <> firstr x. + Proof. + intros. + case_eq (firstr x); intros. + rewrite incr_eqn1; auto. + destruct (shiftr x); simpl; discriminate. + rewrite incr_eqn2; auto. + destruct (incr (shiftr x)); simpl; discriminate. + Qed. + + Lemma incr_inv : forall x y, + incr x = twice_plus_one y -> x = twice y. + Proof. + intros. + case_eq (iszero x); intros. + rewrite (iszero_eq0 _ H0) in *; simpl in *. + change (incr 0) with 1 in H. + symmetry; rewrite twice_zero; auto. + case_eq (firstr x); intros. + rewrite incr_eqn1 in H; auto. + clear H0; destruct x; destruct y; simpl in *. + injection H; intros; subst; auto. + elim (incr_firstr x). + rewrite H1, H; destruct y; simpl; auto. + Qed. + + (** * Conversion from [Z] : the [phi_inv] function *) + + (** First, recursive equations *) + + Lemma phi_inv_double_plus_one : forall z, + phi_inv (Zdouble_plus_one z) = twice_plus_one (phi_inv z). + Proof. + destruct z; simpl; auto. + induction p; simpl. + rewrite 2 incr_twice; auto. + rewrite incr_twice, incr_twice_plus_one. + f_equal. + apply incr_inv; auto. + auto. + Qed. + + Lemma phi_inv_double : forall z, + phi_inv (Zdouble z) = twice (phi_inv z). + Proof. + destruct z; simpl; auto. + rewrite incr_twice_plus_one; auto. + Qed. + + Lemma phi_inv_incr : forall z, + phi_inv (Zsucc z) = incr (phi_inv z). + Proof. + destruct z. + simpl; auto. + simpl; auto. + induction p; simpl; auto. + rewrite Pplus_one_succ_r, IHp, incr_twice_plus_one; auto. + rewrite incr_twice; auto. + simpl; auto. + destruct p; simpl; auto. + rewrite incr_twice; auto. + f_equal. + rewrite incr_twice_plus_one; auto. + induction p; simpl; auto. + rewrite incr_twice; auto. + f_equal. + rewrite incr_twice_plus_one; auto. + Qed. + + (** [phi_inv o inv], the always-exact and easy-to-prove trip : + from int31 to Z and then back to int31. *) + + Lemma phi_inv_phi_aux : + forall n x, n <= size -> + phi_inv (phibis_aux n (nshiftr (size-n) x)) = + nshiftr (size-n) x. + Proof. + induction n. + intros; simpl. + rewrite nshiftr_size; auto. + intros. + unfold phibis_aux, recrbis_aux; fold recrbis_aux; + fold (phibis_aux n (shiftr (nshiftr (size-S n) x))). + assert (shiftr (nshiftr (size - S n) x) = nshiftr (size-n) x). + replace (size - n)%nat with (S (size - (S n))); auto; omega. + rewrite H0. + case_eq (firstr (nshiftr (size - S n) x)); intros. + + rewrite phi_inv_double. + rewrite IHn by omega. + rewrite <- H0. + remember (nshiftr (size - S n) x) as y. + destruct y; simpl in H1; rewrite H1; auto. + + rewrite phi_inv_double_plus_one. + rewrite IHn by omega. + rewrite <- H0. + remember (nshiftr (size - S n) x) as y. + destruct y; simpl in H1; rewrite H1; auto. + Qed. + + Lemma phi_inv_phi : forall x, phi_inv (phi x) = x. + Proof. + intros. + rewrite <- phibis_aux_equiv. + replace x with (nshiftr (size - size) x) by auto. + apply phi_inv_phi_aux; auto. + Qed. + + (** The other composition [phi o phi_inv] is harder to prove correct. + In particular, an overflow can happen, so a modulo is needed. + For the moment, we proceed via several steps, the first one + being a detour to [positive_to_in31]. *) + + (** * [positive_to_int31] *) + + (** A variant of [p2i] with [twice] and [twice_plus_one] instead of + [2*i] and [2*i+1] *) + + Fixpoint p2ibis n p : (N*int31)%type := + match n with + | O => (Npos p, On) + | S n => match p with + | xO p => let (r,i) := p2ibis n p in (r, twice i) + | xI p => let (r,i) := p2ibis n p in (r, twice_plus_one i) + | xH => (N0, In) + end + end. + + Lemma p2ibis_bounded : forall n p, + nshiftr n (snd (p2ibis n p)) = 0. + Proof. + induction n. + simpl; intros; auto. + simpl; intros. + destruct p; simpl. + + specialize IHn with p. + destruct (p2ibis n p); simpl in *. + rewrite nshiftr_S_tail. + destruct (le_lt_dec size n). + rewrite nshiftr_above_size; auto. + assert (H:=nshiftr_0_firstl _ _ l IHn). + replace (shiftr (twice_plus_one i)) with i; auto. + destruct i; simpl in *; rewrite H; auto. + + specialize IHn with p. + destruct (p2ibis n p); simpl in *. + rewrite nshiftr_S_tail. + destruct (le_lt_dec size n). + rewrite nshiftr_above_size; auto. + assert (H:=nshiftr_0_firstl _ _ l IHn). + replace (shiftr (twice i)) with i; auto. + destruct i; simpl in *; rewrite H; auto. + + rewrite nshiftr_S_tail; auto. + replace (shiftr In) with 0; auto. + apply nshiftr_n_0. + Qed. + + Lemma p2ibis_spec : forall n p, n<=size -> + Zpos p = ((Z_of_N (fst (p2ibis n p)))*2^(Z_of_nat n) + + phi (snd (p2ibis n p)))%Z. + Proof. + induction n; intros. + simpl; rewrite Pmult_1_r; auto. + replace (2^(Z_of_nat (S n)))%Z with (2*2^(Z_of_nat n))%Z by + (rewrite <- Zpower_Zsucc, <- Zpos_P_of_succ_nat; + auto with zarith). + rewrite (Zmult_comm 2). + assert (n<=size) by omega. + destruct p; simpl; [ | | auto]; + specialize (IHn p H0); + generalize (p2ibis_bounded n p); + destruct (p2ibis n p) as (r,i); simpl in *; intros. + + change (Zpos p~1) with (2*Zpos p + 1)%Z. + rewrite phi_twice_plus_one_firstl, Zdouble_plus_one_mult. + rewrite IHn; ring. + apply (nshiftr_0_firstl n); auto; try omega. + + change (Zpos p~0) with (2*Zpos p)%Z. + rewrite phi_twice_firstl. + change (Zdouble (phi i)) with (2*(phi i))%Z. + rewrite IHn; ring. + apply (nshiftr_0_firstl n); auto; try omega. + Qed. + + (** We now prove that this [p2ibis] is related to [phi_inv_positive] *) + + Lemma phi_inv_positive_p2ibis : forall n p, (n<=size)%nat -> + EqShiftL (size-n) (phi_inv_positive p) (snd (p2ibis n p)). + Proof. + induction n. + intros. + apply EqShiftL_size; auto. + intros. + simpl p2ibis; destruct p; [ | | red; auto]; + specialize IHn with p; + destruct (p2ibis n p); simpl snd in *; simpl phi_inv_positive; + rewrite ?EqShiftL_twice_plus_one, ?EqShiftL_twice; + replace (S (size - S n))%nat with (size - n)%nat by omega; + apply IHn; omega. + Qed. + + (** This gives the expected result about [phi o phi_inv], at least + for the positive case. *) + + Lemma phi_phi_inv_positive : forall p, + phi (phi_inv_positive p) = (Zpos p) mod (2^(Z_of_nat size)). + Proof. + intros. + replace (phi_inv_positive p) with (snd (p2ibis size p)). + rewrite (p2ibis_spec size p) by auto. + rewrite Zplus_comm, Z_mod_plus. + symmetry; apply Zmod_small. + apply phi_bounded. + auto with zarith. + symmetry. + rewrite <- EqShiftL_zero. + apply (phi_inv_positive_p2ibis size p); auto. + Qed. + + (** Moreover, [p2ibis] is also related with [p2i] and hence with + [positive_to_int31]. *) + + Lemma double_twice_firstl : forall x, firstl x = D0 -> Twon*x = twice x. + Proof. + intros. + unfold mul31. + rewrite <- Zdouble_mult, <- phi_twice_firstl, phi_inv_phi; auto. + Qed. + + Lemma double_twice_plus_one_firstl : forall x, firstl x = D0 -> + Twon*x+In = twice_plus_one x. + Proof. + intros. + rewrite double_twice_firstl; auto. + unfold add31. + rewrite phi_twice_firstl, <- Zdouble_plus_one_mult, + <- phi_twice_plus_one_firstl, phi_inv_phi; auto. + Qed. + + Lemma p2i_p2ibis : forall n p, (n<=size)%nat -> + p2i n p = p2ibis n p. + Proof. + induction n; simpl; auto; intros. + destruct p; auto; specialize IHn with p; + generalize (p2ibis_bounded n p); + rewrite IHn; try omega; destruct (p2ibis n p); simpl; intros; + f_equal; auto. + apply double_twice_plus_one_firstl. + apply (nshiftr_0_firstl n); auto; omega. + apply double_twice_firstl. + apply (nshiftr_0_firstl n); auto; omega. + Qed. + + Lemma positive_to_int31_phi_inv_positive : forall p, + snd (positive_to_int31 p) = phi_inv_positive p. + Proof. + intros; unfold positive_to_int31. + rewrite p2i_p2ibis; auto. + symmetry. + rewrite <- EqShiftL_zero. + apply (phi_inv_positive_p2ibis size); auto. + Qed. + + Lemma positive_to_int31_spec : forall p, + Zpos p = ((Z_of_N (fst (positive_to_int31 p)))*2^(Z_of_nat size) + + phi (snd (positive_to_int31 p)))%Z. + Proof. + unfold positive_to_int31. + intros; rewrite p2i_p2ibis; auto. + apply p2ibis_spec; auto. + Qed. + + (** Thanks to the result about [phi o phi_inv_positive], we can + now establish easily the most general results about + [phi o twice] and so one. *) + + Lemma phi_twice : forall x, + phi (twice x) = (Zdouble (phi x)) mod 2^(Z_of_nat size). + Proof. + intros. + pattern x at 1; rewrite <- (phi_inv_phi x). + rewrite <- phi_inv_double. + assert (0 <= Zdouble (phi x))%Z. + rewrite Zdouble_mult; generalize (phi_bounded x); omega. + destruct (Zdouble (phi x)). + simpl; auto. + apply phi_phi_inv_positive. + compute in H; elim H; auto. + Qed. + + Lemma phi_twice_plus_one : forall x, + phi (twice_plus_one x) = (Zdouble_plus_one (phi x)) mod 2^(Z_of_nat size). + Proof. + intros. + pattern x at 1; rewrite <- (phi_inv_phi x). + rewrite <- phi_inv_double_plus_one. + assert (0 <= Zdouble_plus_one (phi x))%Z. + rewrite Zdouble_plus_one_mult; generalize (phi_bounded x); omega. + destruct (Zdouble_plus_one (phi x)). + simpl; auto. + apply phi_phi_inv_positive. + compute in H; elim H; auto. + Qed. + + Lemma phi_incr : forall x, + phi (incr x) = (Zsucc (phi x)) mod 2^(Z_of_nat size). + Proof. + intros. + pattern x at 1; rewrite <- (phi_inv_phi x). + rewrite <- phi_inv_incr. + assert (0 <= Zsucc (phi x))%Z. + change (Zsucc (phi x)) with ((phi x)+1)%Z; + generalize (phi_bounded x); omega. + destruct (Zsucc (phi x)). + simpl; auto. + apply phi_phi_inv_positive. + compute in H; elim H; auto. + Qed. + + (** With the previous results, we can deal with [phi o phi_inv] even + in the negative case *) + + Lemma phi_phi_inv_negative : + forall p, phi (incr (complement_negative p)) = (Zneg p) mod 2^(Z_of_nat size). + Proof. + induction p. + + simpl complement_negative. + rewrite phi_incr in IHp. + rewrite incr_twice, phi_twice_plus_one. + remember (phi (complement_negative p)) as q. + rewrite Zdouble_plus_one_mult. + replace (2*q+1)%Z with (2*(Zsucc q)-1)%Z by omega. + rewrite <- Zminus_mod_idemp_l, <- Zmult_mod_idemp_r, IHp. + rewrite Zmult_mod_idemp_r, Zminus_mod_idemp_l; auto with zarith. + + simpl complement_negative. + rewrite incr_twice_plus_one, phi_twice. + remember (phi (incr (complement_negative p))) as q. + rewrite Zdouble_mult, IHp, Zmult_mod_idemp_r; auto with zarith. + + simpl; auto. + Qed. + + Lemma phi_phi_inv : + forall z, phi (phi_inv z) = z mod 2 ^ (Z_of_nat size). + Proof. + destruct z. + simpl; auto. + apply phi_phi_inv_positive. + apply phi_phi_inv_negative. + Qed. + +End Basics. + + +Section Int31_Op. + +(** Nullity test *) +Let w_iszero i := match i ?= 0 with Eq => true | _ => false end. + +(** Modulo [2^p] *) +Let w_pos_mod p i := + match compare31 p 31 with + | Lt => addmuldiv31 p 0 (addmuldiv31 (31-p) i 0) + | _ => i + end. + +(** Parity test *) +Let w_iseven i := + let (_,r) := i/2 in + match r ?= 0 with Eq => true | _ => false end. + +Definition int31_op := (mk_znz_op + 31%positive (* number of digits *) + 31 (* number of digits *) + phi (* conversion to Z *) + positive_to_int31 (* positive -> N*int31 : p => N,i where p = N*2^31+phi i *) + head031 (* number of head 0 *) + tail031 (* number of tail 0 *) + (* Basic constructors *) + 0 + 1 + Tn (* 2^31 - 1 *) + (* Comparison *) + compare31 + w_iszero + (* Basic arithmetic operations *) + (fun i => 0 -c i) + (fun i => 0 - i) + (fun i => 0-i-1) + (fun i => i +c 1) + add31c + add31carryc + (fun i => i + 1) + add31 + (fun i j => i + j + 1) + (fun i => i -c 1) + sub31c + sub31carryc + (fun i => i - 1) + sub31 + (fun i j => i - j - 1) + mul31c + mul31 + (fun x => x *c x) + (* special (euclidian) division operations *) + div3121 + div31 (* this is supposed to be the special case of division a/b where a > b *) + div31 + (* euclidian division remainder *) + (* again special case for a > b *) + (fun i j => let (_,r) := i/j in r) + (fun i j => let (_,r) := i/j in r) + gcd31 (*gcd_gt*) + gcd31 (*gcd*) + (* shift operations *) + addmuldiv31 (*add_mul_div *) + (* modulo 2^p *) + w_pos_mod + (* is i even ? *) + w_iseven + (* square root operations *) + sqrt312 (* sqrt2 *) + sqrt31 (* sqrt *) +). + +End Int31_Op. + +Section Int31_Spec. + + Open Local Scope Z_scope. + + Notation "[| x |]" := (phi x) (at level 0, x at level 99). + + Notation Local wB := (2 ^ (Z_of_nat size)). + + Lemma wB_pos : wB > 0. + Proof. + auto with zarith. + Qed. + + Notation "[+| c |]" := + (interp_carry 1 wB phi c) (at level 0, x at level 99). + + Notation "[-| c |]" := + (interp_carry (-1) wB phi c) (at level 0, x at level 99). + + Notation "[|| x ||]" := + (zn2z_to_Z wB phi x) (at level 0, x at level 99). + + Lemma spec_zdigits : [| 31 |] = 31. + Proof. + reflexivity. + Qed. + + Lemma spec_more_than_1_digit: 1 < 31. + Proof. + auto with zarith. + Qed. + + Lemma spec_0 : [| 0 |] = 0. + Proof. + reflexivity. + Qed. + + Lemma spec_1 : [| 1 |] = 1. + Proof. + reflexivity. + Qed. + + Lemma spec_Bm1 : [| Tn |] = wB - 1. + Proof. + reflexivity. + Qed. + + Lemma spec_compare : forall x y, + match (x ?= y)%int31 with + | Eq => [|x|] = [|y|] + | Lt => [|x|] < [|y|] + | Gt => [|x|] > [|y|] + end. + Proof. + clear; unfold compare31; simpl; intros. + case_eq ([|x|] ?= [|y|]); auto. + intros; apply Zcompare_Eq_eq; auto. + Qed. + + (** Addition *) + + Lemma spec_add_c : forall x y, [+|add31c x y|] = [|x|] + [|y|]. + Proof. + intros; unfold add31c, add31, interp_carry; rewrite phi_phi_inv. + generalize (phi_bounded x)(phi_bounded y); intros. + set (X:=[|x|]) in *; set (Y:=[|y|]) in *; clearbody X Y. + + assert ((X+Y) mod wB ?= X+Y <> Eq -> [+|C1 (phi_inv (X+Y))|] = X+Y). + unfold interp_carry; rewrite phi_phi_inv, Zcompare_Eq_iff_eq; intros. + destruct (Z_lt_le_dec (X+Y) wB). + contradict H1; auto using Zmod_small with zarith. + rewrite <- (Z_mod_plus_full (X+Y) (-1) wB). + rewrite Zmod_small; romega. + + generalize (Zcompare_Eq_eq ((X+Y) mod wB) (X+Y)); intros Heq. + destruct Zcompare; intros; + [ rewrite phi_phi_inv; auto | now apply H1 | now apply H1]. + Qed. + + Lemma spec_succ_c : forall x, [+|add31c x 1|] = [|x|] + 1. + Proof. + intros; apply spec_add_c. + Qed. + + Lemma spec_add_carry_c : forall x y, [+|add31carryc x y|] = [|x|] + [|y|] + 1. + Proof. + intros. + unfold add31carryc, interp_carry; rewrite phi_phi_inv. + generalize (phi_bounded x)(phi_bounded y); intros. + set (X:=[|x|]) in *; set (Y:=[|y|]) in *; clearbody X Y. + + assert ((X+Y+1) mod wB ?= X+Y+1 <> Eq -> [+|C1 (phi_inv (X+Y+1))|] = X+Y+1). + unfold interp_carry; rewrite phi_phi_inv, Zcompare_Eq_iff_eq; intros. + destruct (Z_lt_le_dec (X+Y+1) wB). + contradict H1; auto using Zmod_small with zarith. + rewrite <- (Z_mod_plus_full (X+Y+1) (-1) wB). + rewrite Zmod_small; romega. + + generalize (Zcompare_Eq_eq ((X+Y+1) mod wB) (X+Y+1)); intros Heq. + destruct Zcompare; intros; + [ rewrite phi_phi_inv; auto | now apply H1 | now apply H1]. + Qed. + + Lemma spec_add : forall x y, [|x+y|] = ([|x|] + [|y|]) mod wB. + Proof. + intros; apply phi_phi_inv. + Qed. + + Lemma spec_add_carry : + forall x y, [|x+y+1|] = ([|x|] + [|y|] + 1) mod wB. + Proof. + unfold add31; intros. + repeat rewrite phi_phi_inv. + apply Zplus_mod_idemp_l. + Qed. + + Lemma spec_succ : forall x, [|x+1|] = ([|x|] + 1) mod wB. + Proof. + intros; rewrite <- spec_1; apply spec_add. + Qed. + + (** Substraction *) + + Lemma spec_sub_c : forall x y, [-|sub31c x y|] = [|x|] - [|y|]. + Proof. + unfold sub31c, sub31, interp_carry; intros. + rewrite phi_phi_inv. + generalize (phi_bounded x)(phi_bounded y); intros. + set (X:=[|x|]) in *; set (Y:=[|y|]) in *; clearbody X Y. + + assert ((X-Y) mod wB ?= X-Y <> Eq -> [-|C1 (phi_inv (X-Y))|] = X-Y). + unfold interp_carry; rewrite phi_phi_inv, Zcompare_Eq_iff_eq; intros. + destruct (Z_lt_le_dec (X-Y) 0). + rewrite <- (Z_mod_plus_full (X-Y) 1 wB). + rewrite Zmod_small; romega. + contradict H1; apply Zmod_small; romega. + + generalize (Zcompare_Eq_eq ((X-Y) mod wB) (X-Y)); intros Heq. + destruct Zcompare; intros; + [ rewrite phi_phi_inv; auto | now apply H1 | now apply H1]. + Qed. + + Lemma spec_sub_carry_c : forall x y, [-|sub31carryc x y|] = [|x|] - [|y|] - 1. + Proof. + unfold sub31carryc, sub31, interp_carry; intros. + rewrite phi_phi_inv. + generalize (phi_bounded x)(phi_bounded y); intros. + set (X:=[|x|]) in *; set (Y:=[|y|]) in *; clearbody X Y. + + assert ((X-Y-1) mod wB ?= X-Y-1 <> Eq -> [-|C1 (phi_inv (X-Y-1))|] = X-Y-1). + unfold interp_carry; rewrite phi_phi_inv, Zcompare_Eq_iff_eq; intros. + destruct (Z_lt_le_dec (X-Y-1) 0). + rewrite <- (Z_mod_plus_full (X-Y-1) 1 wB). + rewrite Zmod_small; romega. + contradict H1; apply Zmod_small; romega. + + generalize (Zcompare_Eq_eq ((X-Y-1) mod wB) (X-Y-1)); intros Heq. + destruct Zcompare; intros; + [ rewrite phi_phi_inv; auto | now apply H1 | now apply H1]. + Qed. + + Lemma spec_sub : forall x y, [|x-y|] = ([|x|] - [|y|]) mod wB. + Proof. + intros; apply phi_phi_inv. + Qed. + + Lemma spec_sub_carry : + forall x y, [|x-y-1|] = ([|x|] - [|y|] - 1) mod wB. + Proof. + unfold sub31; intros. + repeat rewrite phi_phi_inv. + apply Zminus_mod_idemp_l. + Qed. + + Lemma spec_opp_c : forall x, [-|sub31c 0 x|] = -[|x|]. + Proof. + intros; apply spec_sub_c. + Qed. + + Lemma spec_opp : forall x, [|0 - x|] = (-[|x|]) mod wB. + Proof. + intros; apply phi_phi_inv. + Qed. + + Lemma spec_opp_carry : forall x, [|0 - x - 1|] = wB - [|x|] - 1. + Proof. + unfold sub31; intros. + repeat rewrite phi_phi_inv. + change [|1|] with 1; change [|0|] with 0. + rewrite <- (Z_mod_plus_full (0-[|x|]) 1 wB). + rewrite Zminus_mod_idemp_l. + rewrite Zmod_small; generalize (phi_bounded x); romega. + Qed. + + Lemma spec_pred_c : forall x, [-|sub31c x 1|] = [|x|] - 1. + Proof. + intros; apply spec_sub_c. + Qed. + + Lemma spec_pred : forall x, [|x-1|] = ([|x|] - 1) mod wB. + Proof. + intros; apply spec_sub. + Qed. + + (** Multiplication *) + + Lemma phi2_phi_inv2 : forall x, [||phi_inv2 x||] = x mod (wB^2). + Proof. + assert (forall z, (z / wB) mod wB * wB + z mod wB = z mod wB ^ 2). + intros. + assert ((z/wB) mod wB = z/wB - (z/wB/wB)*wB). + rewrite (Z_div_mod_eq (z/wB) wB wB_pos) at 2; ring. + assert (z mod wB = z - (z/wB)*wB). + rewrite (Z_div_mod_eq z wB wB_pos) at 2; ring. + rewrite H. + rewrite H0 at 1. + ring_simplify. + rewrite Zdiv_Zdiv; auto with zarith. + rewrite (Z_div_mod_eq z (wB*wB)) at 2; auto with zarith. + change (wB*wB) with (wB^2); ring. + + unfold phi_inv2. + destruct x; unfold zn2z_to_Z; rewrite ?phi_phi_inv; + change base with wB; auto. + Qed. + + Lemma spec_mul_c : forall x y, [|| mul31c x y ||] = [|x|] * [|y|]. + Proof. + unfold mul31c; intros. + rewrite phi2_phi_inv2. + apply Zmod_small. + generalize (phi_bounded x)(phi_bounded y); intros. + change (wB^2) with (wB * wB). + auto using Zmult_lt_compat with zarith. + Qed. + + Lemma spec_mul : forall x y, [|x*y|] = ([|x|] * [|y|]) mod wB. + Proof. + intros; apply phi_phi_inv. + Qed. + + Lemma spec_square_c : forall x, [|| mul31c x x ||] = [|x|] * [|x|]. + Proof. + intros; apply spec_mul_c. + Qed. + + (** Division *) + + Lemma spec_div21 : forall a1 a2 b, + wB/2 <= [|b|] -> + [|a1|] < [|b|] -> + let (q,r) := div3121 a1 a2 b in + [|a1|] *wB+ [|a2|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]. + Proof. + unfold div3121; intros. + generalize (phi_bounded a1)(phi_bounded a2)(phi_bounded b); intros. + assert ([|b|]>0) by (auto with zarith). + generalize (Z_div_mod (phi2 a1 a2) [|b|] H4) (Z_div_pos (phi2 a1 a2) [|b|] H4). + unfold Zdiv; destruct (Zdiv_eucl (phi2 a1 a2) [|b|]); simpl. + rewrite ?phi_phi_inv. + destruct 1; intros. + unfold phi2 in *. + change base with wB; change base with wB in H5. + change (Zpower_pos 2 31) with wB; change (Zpower_pos 2 31) with wB in H. + rewrite H5, Zmult_comm. + replace (z0 mod wB) with z0 by (symmetry; apply Zmod_small; omega). + replace (z mod wB) with z; auto with zarith. + symmetry; apply Zmod_small. + split. + apply H7; change base with wB; auto with zarith. + apply Zmult_gt_0_lt_reg_r with [|b|]. + omega. + rewrite Zmult_comm. + apply Zle_lt_trans with ([|b|]*z+z0). + omega. + rewrite <- H5. + apply Zle_lt_trans with ([|a1|]*wB+(wB-1)). + omega. + replace ([|a1|]*wB+(wB-1)) with (wB*([|a1|]+1)-1) by ring. + assert (wB*([|a1|]+1) <= wB*[|b|]); try omega. + apply Zmult_le_compat; omega. + Qed. + + Lemma spec_div : forall a b, 0 < [|b|] -> + let (q,r) := div31 a b in + [|a|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]. + Proof. + unfold div31; intros. + assert ([|b|]>0) by (auto with zarith). + generalize (Z_div_mod [|a|] [|b|] H0) (Z_div_pos [|a|] [|b|] H0). + unfold Zdiv; destruct (Zdiv_eucl [|a|] [|b|]); simpl. + rewrite ?phi_phi_inv. + destruct 1; intros. + rewrite H1, Zmult_comm. + generalize (phi_bounded a)(phi_bounded b); intros. + replace (z0 mod wB) with z0 by (symmetry; apply Zmod_small; omega). + replace (z mod wB) with z; auto with zarith. + symmetry; apply Zmod_small. + split; auto with zarith. + apply Zle_lt_trans with [|a|]; auto with zarith. + rewrite H1. + apply Zle_trans with ([|b|]*z); try omega. + rewrite <- (Zmult_1_l z) at 1. + apply Zmult_le_compat; auto with zarith. + Qed. + + Lemma spec_mod : forall a b, 0 < [|b|] -> + [|let (_,r) := (a/b)%int31 in r|] = [|a|] mod [|b|]. + Proof. + unfold div31; intros. + assert ([|b|]>0) by (auto with zarith). + unfold Zmod. + generalize (Z_div_mod [|a|] [|b|] H0). + destruct (Zdiv_eucl [|a|] [|b|]); simpl. + rewrite ?phi_phi_inv. + destruct 1; intros. + generalize (phi_bounded b); intros. + apply Zmod_small; omega. + Qed. + + Lemma phi_gcd : forall i j, + [|gcd31 i j|] = Zgcdn (2*size) [|j|] [|i|]. + Proof. + unfold gcd31. + induction (2*size)%nat; intros. + reflexivity. + simpl. + unfold compare31. + change [|On|] with 0. + generalize (phi_bounded j)(phi_bounded i); intros. + case_eq [|j|]; intros. + simpl; intros. + generalize (Zabs_spec [|i|]); omega. + simpl. + rewrite IHn, H1; f_equal. + rewrite spec_mod, H1; auto. + rewrite H1; compute; auto. + rewrite H1 in H; destruct H as [H _]; compute in H; elim H; auto. + Qed. + + Lemma spec_gcd : forall a b, Zis_gcd [|a|] [|b|] [|gcd31 a b|]. + Proof. + intros. + rewrite phi_gcd. + apply Zis_gcd_sym. + apply Zgcdn_is_gcd. + unfold Zgcd_bound. + generalize (phi_bounded b). + destruct [|b|]. + unfold size; auto with zarith. + intros (_,H). + cut (Psize p <= size)%nat; [ omega | rewrite <- Zpower2_Psize; auto]. + intros (H,_); compute in H; elim H; auto. + Qed. + + Lemma iter_int31_iter_nat : forall A f i a, + iter_int31 i A f a = iter_nat (Zabs_nat [|i|]) A f a. + Proof. + intros. + unfold iter_int31. + rewrite <- recrbis_equiv; auto; unfold recrbis. + rewrite <- phibis_aux_equiv. + + revert i a; induction size. + simpl; auto. + simpl; intros. + case_eq (firstr i); intros H; rewrite 2 IHn; + unfold phibis_aux; simpl; rewrite H; fold (phibis_aux n (shiftr i)); + generalize (phibis_aux_pos n (shiftr i)); intros; + set (z := phibis_aux n (shiftr i)) in *; clearbody z; + rewrite <- iter_nat_plus. + + f_equal. + rewrite Zdouble_mult, Zmult_comm, <- Zplus_diag_eq_mult_2. + symmetry; apply Zabs_nat_Zplus; auto with zarith. + + change (iter_nat (S (Zabs_nat z + Zabs_nat z)) A f a = + iter_nat (Zabs_nat (Zdouble_plus_one z)) A f a); f_equal. + rewrite Zdouble_plus_one_mult, Zmult_comm, <- Zplus_diag_eq_mult_2. + rewrite Zabs_nat_Zplus; auto with zarith. + rewrite Zabs_nat_Zplus; auto with zarith. + change (Zabs_nat 1) with 1%nat; omega. + Qed. + + Fixpoint addmuldiv31_alt n i j := + match n with + | O => i + | S n => addmuldiv31_alt n (sneakl (firstl j) i) (shiftl j) + end. + + Lemma addmuldiv31_equiv : forall p x y, + addmuldiv31 p x y = addmuldiv31_alt (Zabs_nat [|p|]) x y. + Proof. + intros. + unfold addmuldiv31. + rewrite iter_int31_iter_nat. + set (n:=Zabs_nat [|p|]); clearbody n; clear p. + revert x y; induction n. + simpl; auto. + intros. + simpl addmuldiv31_alt. + replace (S n) with (n+1)%nat by (rewrite plus_comm; auto). + rewrite iter_nat_plus; simpl; auto. + Qed. + + Lemma spec_add_mul_div : forall x y p, [|p|] <= Zpos 31 -> + [| addmuldiv31 p x y |] = + ([|x|] * (2 ^ [|p|]) + [|y|] / (2 ^ ((Zpos 31) - [|p|]))) mod wB. + Proof. + intros. + rewrite addmuldiv31_equiv. + assert ([|p|] = Z_of_nat (Zabs_nat [|p|])). + rewrite inj_Zabs_nat; symmetry; apply Zabs_eq. + destruct (phi_bounded p); auto. + rewrite H0; rewrite H0 in H; clear H0; rewrite Zabs_nat_Z_of_nat. + set (n := Zabs_nat [|p|]) in *; clearbody n. + assert (n <= 31)%nat. + rewrite inj_le_iff; auto with zarith. + clear p H; revert x y. + + induction n. + simpl; intros. + change (Zpower_pos 2 31) with (2^31). + rewrite Zmult_1_r. + replace ([|y|] / 2^31) with 0. + rewrite Zplus_0_r. + symmetry; apply Zmod_small; apply phi_bounded. + symmetry; apply Zdiv_small; apply phi_bounded. + + simpl addmuldiv31_alt; intros. + rewrite IHn; [ | omega ]. + case_eq (firstl y); intros. + + rewrite phi_twice, Zdouble_mult. + rewrite phi_twice_firstl; auto. + change (Zdouble [|y|]) with (2*[|y|]). + rewrite inj_S, Zpower_Zsucc; auto with zarith. + rewrite Zplus_mod; rewrite Zmult_mod_idemp_l; rewrite <- Zplus_mod. + f_equal. + apply Zplus_eq_compat. + ring. + replace (31-Z_of_nat n) with (Zsucc(31-Zsucc(Z_of_nat n))) by ring. + rewrite Zpower_Zsucc, <- Zdiv_Zdiv; auto with zarith. + rewrite Zmult_comm, Z_div_mult; auto with zarith. + + rewrite phi_twice_plus_one, Zdouble_plus_one_mult. + rewrite phi_twice; auto. + change (Zdouble [|y|]) with (2*[|y|]). + rewrite inj_S, Zpower_Zsucc; auto with zarith. + rewrite Zplus_mod; rewrite Zmult_mod_idemp_l; rewrite <- Zplus_mod. + rewrite Zmult_plus_distr_l, Zmult_1_l, <- Zplus_assoc. + f_equal. + apply Zplus_eq_compat. + ring. + assert ((2*[|y|]) mod wB = 2*[|y|] - wB). + admit. + rewrite H1. + replace wB with (2^(Z_of_nat n)*2^(31-Z_of_nat n)) by + (rewrite <- Zpower_exp; auto with zarith; f_equal; unfold size; ring). + unfold Zminus; rewrite Zopp_mult_distr_l. + rewrite Z_div_plus; auto with zarith. + ring_simplify. + replace (31+-Z_of_nat n) with (Zsucc(31-Zsucc(Z_of_nat n))) by ring. + rewrite Zpower_Zsucc, <- Zdiv_Zdiv; auto with zarith. + rewrite Zmult_comm, Z_div_mult; auto with zarith. + Qed. + + Let w_pos_mod := int31_op.(znz_pos_mod). + + Lemma spec_pos_mod : forall w p, + [|w_pos_mod p w|] = [|w|] mod (2 ^ [|p|]). + Proof. + unfold w_pos_mod, znz_pos_mod, int31_op, compare31. + change [|31|] with 31%Z. + assert (forall w p, 31<=p -> [|w|] = [|w|] mod 2^p). + intros. + generalize (phi_bounded w). + symmetry; apply Zmod_small. + split; auto with zarith. + apply Zlt_le_trans with wB; auto with zarith. + apply Zpower_le_monotone; auto with zarith. + intros. + case_eq ([|p|] ?= 31); intros; + [ apply H; rewrite (Zcompare_Eq_eq _ _ H0); auto with zarith | | + apply H; change ([|p|]>31)%Z in H0; auto with zarith ]. + change ([|p|]<31) in H0. + rewrite spec_add_mul_div by auto with zarith. + change [|0|] with 0%Z; rewrite Zmult_0_l, Zplus_0_l. + generalize (phi_bounded p)(phi_bounded w); intros. + assert (31-[|p|]<wB). + apply Zle_lt_trans with 31%Z; auto with zarith. + compute; auto. + assert ([|31-p|]=31-[|p|]). + unfold sub31; rewrite phi_phi_inv. + change [|31|] with 31%Z. + apply Zmod_small; auto with zarith. + rewrite spec_add_mul_div by (rewrite H4; auto with zarith). + change [|0|] with 0%Z; rewrite Zdiv_0_l, Zplus_0_r. + rewrite H4. + apply shift_unshift_mod_2; auto with zarith. + Qed. + + + (** Shift operations *) + + Lemma spec_head00: forall x, [|x|] = 0 -> [|head031 x|] = Zpos 31. + Proof. + intros. + generalize (phi_inv_phi x). + rewrite H; simpl. + intros H'; rewrite <- H'. + simpl; auto. + Qed. + + Fixpoint head031_alt n x := + match n with + | O => 0%nat + | S n => match firstl x with + | D0 => S (head031_alt n (shiftl x)) + | D1 => 0%nat + end + end. + + Lemma head031_equiv : + forall x, [|head031 x|] = Z_of_nat (head031_alt size x). + Proof. + intros. + case_eq (iszero x); intros. + rewrite (iszero_eq0 _ H). + simpl; auto. + + unfold head031, recl. + change On with (phi_inv (Z_of_nat (31-size))). + replace (head031_alt size x) with + (head031_alt size x + (31 - size))%nat by (apply plus_0_r; auto). + assert (size <= 31)%nat by auto with arith. + + revert x H; induction size; intros. + simpl; auto. + unfold recl_aux; fold recl_aux. + unfold head031_alt; fold head031_alt. + rewrite H. + assert ([|phi_inv (Z_of_nat (31-S n))|] = Z_of_nat (31 - S n)). + rewrite phi_phi_inv. + apply Zmod_small. + split. + change 0 with (Z_of_nat O); apply inj_le; omega. + apply Zle_lt_trans with (Z_of_nat 31). + apply inj_le; omega. + compute; auto. + case_eq (firstl x); intros; auto. + rewrite plus_Sn_m, plus_n_Sm. + replace (S (31 - S n)) with (31 - n)%nat by omega. + rewrite <- IHn; [ | omega | ]. + f_equal; f_equal. + unfold add31. + rewrite H1. + f_equal. + change [|In|] with 1. + replace (31-n)%nat with (S (31 - S n))%nat by omega. + rewrite inj_S; ring. + + clear - H H2. + rewrite (sneakr_shiftl x) in H. + rewrite H2 in H. + case_eq (iszero (shiftl x)); intros; auto. + rewrite (iszero_eq0 _ H0) in H; discriminate. + Qed. + + Lemma phi_nz : forall x, 0 < [|x|] <-> x <> 0%int31. + Proof. + split; intros. + red; intro; subst x; discriminate. + assert ([|x|]<>0%Z). + contradict H. + rewrite <- (phi_inv_phi x); rewrite H; auto. + generalize (phi_bounded x); auto with zarith. + Qed. + + Lemma spec_head0 : forall x, 0 < [|x|] -> + wB/ 2 <= 2 ^ ([|head031 x|]) * [|x|] < wB. + Proof. + intros. + rewrite head031_equiv. + assert (nshiftl size x = 0%int31). + apply nshiftl_size. + revert x H H0. + unfold size at 2 5. + induction size. + simpl Z_of_nat. + intros. + compute in H0; rewrite H0 in H; discriminate. + + intros. + simpl head031_alt. + case_eq (firstl x); intros. + rewrite (inj_S (head031_alt n (shiftl x))), Zpower_Zsucc; auto with zarith. + rewrite <- Zmult_assoc, Zmult_comm, <- Zmult_assoc, <-(Zmult_comm 2). + rewrite <- Zdouble_mult, <- (phi_twice_firstl _ H1). + apply IHn. + + rewrite phi_nz; rewrite phi_nz in H; contradict H. + change twice with shiftl in H. + rewrite (sneakr_shiftl x), H1, H; auto. + + rewrite <- nshiftl_S_tail; auto. + + change (2^(Z_of_nat 0)) with 1; rewrite Zmult_1_l. + generalize (phi_bounded x); unfold size; split; auto with zarith. + change (2^(Z_of_nat 31)/2) with (2^(Z_of_nat (pred size))). + apply phi_lowerbound; auto. + Qed. + + Lemma spec_tail00: forall x, [|x|] = 0 -> [|tail031 x|] = Zpos 31. + Proof. + intros. + generalize (phi_inv_phi x). + rewrite H; simpl. + intros H'; rewrite <- H'. + simpl; auto. + Qed. + + Fixpoint tail031_alt n x := + match n with + | O => 0%nat + | S n => match firstr x with + | D0 => S (tail031_alt n (shiftr x)) + | D1 => 0%nat + end + end. + + Lemma tail031_equiv : + forall x, [|tail031 x|] = Z_of_nat (tail031_alt size x). + Proof. + intros. + case_eq (iszero x); intros. + rewrite (iszero_eq0 _ H). + simpl; auto. + + unfold tail031, recr. + change On with (phi_inv (Z_of_nat (31-size))). + replace (tail031_alt size x) with + (tail031_alt size x + (31 - size))%nat by (apply plus_0_r; auto). + assert (size <= 31)%nat by auto with arith. + + revert x H; induction size; intros. + simpl; auto. + unfold recr_aux; fold recr_aux. + unfold tail031_alt; fold tail031_alt. + rewrite H. + assert ([|phi_inv (Z_of_nat (31-S n))|] = Z_of_nat (31 - S n)). + rewrite phi_phi_inv. + apply Zmod_small. + split. + change 0 with (Z_of_nat O); apply inj_le; omega. + apply Zle_lt_trans with (Z_of_nat 31). + apply inj_le; omega. + compute; auto. + case_eq (firstr x); intros; auto. + rewrite plus_Sn_m, plus_n_Sm. + replace (S (31 - S n)) with (31 - n)%nat by omega. + rewrite <- IHn; [ | omega | ]. + f_equal; f_equal. + unfold add31. + rewrite H1. + f_equal. + change [|In|] with 1. + replace (31-n)%nat with (S (31 - S n))%nat by omega. + rewrite inj_S; ring. + + clear - H H2. + rewrite (sneakl_shiftr x) in H. + rewrite H2 in H. + case_eq (iszero (shiftr x)); intros; auto. + rewrite (iszero_eq0 _ H0) in H; discriminate. + Qed. + + Lemma spec_tail0 : forall x, 0 < [|x|] -> + exists y, 0 <= y /\ [|x|] = (2 * y + 1) * (2 ^ [|tail031 x|]). + Proof. + intros. + rewrite tail031_equiv. + assert (nshiftr size x = 0%int31). + apply nshiftr_size. + revert x H H0. + induction size. + simpl Z_of_nat. + intros. + compute in H0; rewrite H0 in H; discriminate. + + intros. + simpl tail031_alt. + case_eq (firstr x); intros. + rewrite (inj_S (tail031_alt n (shiftr x))), Zpower_Zsucc; auto with zarith. + destruct (IHn (shiftr x)) as (y & Hy1 & Hy2). + + rewrite phi_nz; rewrite phi_nz in H; contradict H. + rewrite (sneakl_shiftr x), H1, H; auto. + + rewrite <- nshiftr_S_tail; auto. + + exists y; split; auto. + rewrite phi_eqn1; auto. + rewrite Zdouble_mult, Hy2; ring. + + exists [|shiftr x|]. + split. + generalize (phi_bounded (shiftr x)); auto with zarith. + rewrite phi_eqn2; auto. + rewrite Zdouble_plus_one_mult; simpl; ring. + Qed. + + (* Sqrt *) + + (* Direct transcription of an old proof + of a fortran program in boyer-moore *) + + Lemma quotient_by_2 a: a - 1 <= (a/2) + (a/2). + Proof. + intros a; case (Z_mod_lt a 2); auto with zarith. + intros H1; rewrite Zmod_eq_full; auto with zarith. + Qed. + + Lemma sqrt_main_trick j k: 0 <= j -> 0 <= k -> + (j * k) + j <= ((j + k)/2 + 1) ^ 2. + Proof. + intros j k Hj; generalize Hj k; pattern j; apply natlike_ind; + auto; clear k j Hj. + intros _ k Hk; repeat rewrite Zplus_0_l. + apply Zmult_le_0_compat; generalize (Z_div_pos k 2); auto with zarith. + intros j Hj Hrec _ k Hk; pattern k; apply natlike_ind; auto; clear k Hk. + rewrite Zmult_0_r, Zplus_0_r, Zplus_0_l. + generalize (sqr_pos (Zsucc j / 2)) (quotient_by_2 (Zsucc j)); + unfold Zsucc. + rewrite Zpower_2, Zmult_plus_distr_l; repeat rewrite Zmult_plus_distr_r. + auto with zarith. + intros k Hk _. + replace ((Zsucc j + Zsucc k) / 2) with ((j + k)/2 + 1). + generalize (Hrec Hj k Hk) (quotient_by_2 (j + k)). + unfold Zsucc; repeat rewrite Zpower_2; + repeat rewrite Zmult_plus_distr_l; repeat rewrite Zmult_plus_distr_r. + repeat rewrite Zmult_1_l; repeat rewrite Zmult_1_r. + auto with zarith. + rewrite Zplus_comm, <- Z_div_plus_full_l; auto with zarith. + apply f_equal2 with (f := Zdiv); auto with zarith. + Qed. + + Lemma sqrt_main i j: 0 <= i -> 0 < j -> i < ((j + (i/j))/2 + 1) ^ 2. + Proof. + intros i j Hi Hj. + assert (Hij: 0 <= i/j) by (apply Z_div_pos; auto with zarith). + apply Zlt_le_trans with (2 := sqrt_main_trick _ _ (Zlt_le_weak _ _ Hj) Hij). + pattern i at 1; rewrite (Z_div_mod_eq i j); case (Z_mod_lt i j); auto with zarith. + Qed. + + Lemma sqrt_init i: 1 < i -> i < (i/2 + 1) ^ 2. + Proof. + intros i Hi. + assert (H1: 0 <= i - 2) by auto with zarith. + assert (H2: 1 <= (i / 2) ^ 2); auto with zarith. + replace i with (1* 2 + (i - 2)); auto with zarith. + rewrite Zpower_2, Z_div_plus_full_l; auto with zarith. + generalize (sqr_pos ((i - 2)/ 2)) (Z_div_pos (i - 2) 2). + rewrite Zmult_plus_distr_l; repeat rewrite Zmult_plus_distr_r. + auto with zarith. + generalize (quotient_by_2 i). + rewrite Zpower_2 in H2 |- *; + repeat (rewrite Zmult_plus_distr_l || + rewrite Zmult_plus_distr_r || + rewrite Zmult_1_l || rewrite Zmult_1_r). + auto with zarith. + Qed. + + Lemma sqrt_test_true i j: 0 <= i -> 0 < j -> i/j >= j -> j ^ 2 <= i. + Proof. + intros i j Hi Hj Hd; rewrite Zpower_2. + apply Zle_trans with (j * (i/j)); auto with zarith. + apply Z_mult_div_ge; auto with zarith. + Qed. + + Lemma sqrt_test_false i j: 0 <= i -> 0 < j -> i/j < j -> (j + (i/j))/2 < j. + Proof. + intros i j Hi Hj H; case (Zle_or_lt j ((j + (i/j))/2)); auto. + intros H1; contradict H; apply Zle_not_lt. + assert (2 * j <= j + (i/j)); auto with zarith. + apply Zle_trans with (2 * ((j + (i/j))/2)); auto with zarith. + apply Z_mult_div_ge; auto with zarith. + Qed. + + (* George's trick *) + Inductive ZcompareSpec (i j: Z): comparison -> Prop := + ZcompareSpecEq: i = j -> ZcompareSpec i j Eq + | ZcompareSpecLt: i < j -> ZcompareSpec i j Lt + | ZcompareSpecGt: j < i -> ZcompareSpec i j Gt. + + Lemma Zcompare_spec i j: ZcompareSpec i j (i ?= j). + Proof. + intros i j; case_eq (Zcompare i j); intros H. + apply ZcompareSpecEq; apply Zcompare_Eq_eq; auto. + apply ZcompareSpecLt; auto. + apply ZcompareSpecGt; apply Zgt_lt; auto. + Qed. + + Lemma sqrt31_step_def rec i j: + sqrt31_step rec i j = + match (fst (i/j) ?= j)%int31 with + Lt => rec i (fst ((j + fst(i/j))/2))%int31 + | _ => j + end. + Proof. + intros rec i j; unfold sqrt31_step; case div31; intros. + simpl; case compare31; auto. + Qed. + + Lemma div31_phi i j: 0 < [|j|] -> [|fst (i/j)%int31|] = [|i|]/[|j|]. + intros i j Hj; generalize (spec_div i j Hj). + case div31; intros q r; simpl fst. + intros (H1,H2); apply Zdiv_unique with [|r|]; auto with zarith. + rewrite H1; ring. + Qed. + + Lemma sqrt31_step_correct rec i j: + 0 < [|i|] -> 0 < [|j|] -> [|i|] < ([|j|] + 1) ^ 2 -> + 2 * [|j|] < wB -> + (forall j1 : int31, + 0 < [|j1|] < [|j|] -> [|i|] < ([|j1|] + 1) ^ 2 -> + [|rec i j1|] ^ 2 <= [|i|] < ([|rec i j1|] + 1) ^ 2) -> + [|sqrt31_step rec i j|] ^ 2 <= [|i|] < ([|sqrt31_step rec i j|] + 1) ^ 2. + Proof. + assert (Hp2: 0 < [|2|]) by exact (refl_equal Lt). + intros rec i j Hi Hj Hij H31 Hrec; rewrite sqrt31_step_def. + generalize (spec_compare (fst (i/j)%int31) j); case compare31; + rewrite div31_phi; auto; intros Hc; + try (split; auto; apply sqrt_test_true; auto with zarith; fail). + apply Hrec; repeat rewrite div31_phi; auto with zarith. + replace [|(j + fst (i / j)%int31)|] with ([|j|] + [|i|] / [|j|]). + split. + case (Zle_lt_or_eq 1 [|j|]); auto with zarith; intros Hj1. + replace ([|j|] + [|i|]/[|j|]) with + (1 * 2 + (([|j|] - 2) + [|i|] / [|j|])); try ring. + rewrite Z_div_plus_full_l; auto with zarith. + assert (0 <= [|i|]/ [|j|]) by (apply Z_div_pos; auto with zarith). + assert (0 <= ([|j|] - 2 + [|i|] / [|j|]) / [|2|]) ; auto with zarith. + rewrite <- Hj1, Zdiv_1_r. + replace (1 + [|i|])%Z with (1 * 2 + ([|i|] - 1))%Z; try ring. + rewrite Z_div_plus_full_l; auto with zarith. + assert (0 <= ([|i|] - 1) /2)%Z by (apply Z_div_pos; auto with zarith). + change ([|2|]) with 2%Z; auto with zarith. + apply sqrt_test_false; auto with zarith. + rewrite spec_add, div31_phi; auto. + apply sym_equal; apply Zmod_small. + split; auto with zarith. + replace [|j + fst (i / j)%int31|] with ([|j|] + [|i|] / [|j|]). + apply sqrt_main; auto with zarith. + rewrite spec_add, div31_phi; auto. + apply sym_equal; apply Zmod_small. + split; auto with zarith. + Qed. + + Lemma iter31_sqrt_correct n rec i j: 0 < [|i|] -> 0 < [|j|] -> + [|i|] < ([|j|] + 1) ^ 2 -> 2 * [|j|] < 2 ^ (Z_of_nat size) -> + (forall j1, 0 < [|j1|] -> 2^(Z_of_nat n) + [|j1|] <= [|j|] -> + [|i|] < ([|j1|] + 1) ^ 2 -> 2 * [|j1|] < 2 ^ (Z_of_nat size) -> + [|rec i j1|] ^ 2 <= [|i|] < ([|rec i j1|] + 1) ^ 2) -> + [|iter31_sqrt n rec i j|] ^ 2 <= [|i|] < ([|iter31_sqrt n rec i j|] + 1) ^ 2. + Proof. + intros n; elim n; unfold iter31_sqrt; fold iter31_sqrt; clear n. + intros rec i j Hi Hj Hij H31 Hrec; apply sqrt31_step_correct; auto with zarith. + intros; apply Hrec; auto with zarith. + rewrite Zpower_0_r; auto with zarith. + intros n Hrec rec i j Hi Hj Hij H31 HHrec. + apply sqrt31_step_correct; auto. + intros j1 Hj1 Hjp1; apply Hrec; auto with zarith. + intros j2 Hj2 H2j2 Hjp2 Hj31; apply Hrec; auto with zarith. + intros j3 Hj3 Hpj3. + apply HHrec; auto. + rewrite inj_S, Zpower_Zsucc. + apply Zle_trans with (2 ^Z_of_nat n + [|j2|]); auto with zarith. + apply Zle_0_nat. + Qed. + + Lemma spec_sqrt : forall x, + [|sqrt31 x|] ^ 2 <= [|x|] < ([|sqrt31 x|] + 1) ^ 2. + Proof. + intros i; unfold sqrt31. + generalize (spec_compare 1 i); case compare31; change [|1|] with 1; + intros Hi; auto with zarith. + repeat rewrite Zpower_2; auto with zarith. + apply iter31_sqrt_correct; auto with zarith. + rewrite div31_phi; change ([|2|]) with 2; auto with zarith. + replace ([|i|]) with (1 * 2 + ([|i|] - 2))%Z; try ring. + assert (0 <= ([|i|] - 2)/2)%Z by (apply Z_div_pos; auto with zarith). + rewrite Z_div_plus_full_l; auto with zarith. + rewrite div31_phi; change ([|2|]) with 2; auto with zarith. + apply sqrt_init; auto. + rewrite div31_phi; change ([|2|]) with 2; auto with zarith. + apply Zle_lt_trans with ([|i|]). + apply Z_mult_div_ge; auto with zarith. + case (phi_bounded i); auto. + intros j2 H1 H2; contradict H2; apply Zlt_not_le. + rewrite div31_phi; change ([|2|]) with 2; auto with zarith. + apply Zle_lt_trans with ([|i|]); auto with zarith. + assert (0 <= [|i|]/2)%Z by (apply Z_div_pos; auto with zarith). + apply Zle_trans with (2 * ([|i|]/2)); auto with zarith. + apply Z_mult_div_ge; auto with zarith. + case (phi_bounded i); unfold size; auto with zarith. + change [|0|] with 0; auto with zarith. + case (phi_bounded i); repeat rewrite Zpower_2; auto with zarith. + Qed. + + Lemma sqrt312_step_def rec ih il j: + sqrt312_step rec ih il j = + match (ih ?= j)%int31 with + Eq => j + | Gt => j + | _ => + match (fst (div3121 ih il j) ?= j)%int31 with + Lt => let m := match j +c fst (div3121 ih il j) with + C0 m1 => fst (m1/2)%int31 + | C1 m1 => (fst (m1/2) + v30)%int31 + end in rec ih il m + | _ => j + end + end. + Proof. + intros rec ih il j; unfold sqrt312_step; case div3121; intros. + simpl; case compare31; auto. + Qed. + + Lemma sqrt312_lower_bound ih il j: + phi2 ih il < ([|j|] + 1) ^ 2 -> [|ih|] <= [|j|]. + Proof. + intros ih il j H1. + case (phi_bounded j); intros Hbj _. + case (phi_bounded il); intros Hbil _. + case (phi_bounded ih); intros Hbih Hbih1. + assert (([|ih|] < [|j|] + 1)%Z); auto with zarith. + apply Zlt_square_simpl; auto with zarith. + repeat rewrite <-Zpower_2; apply Zle_lt_trans with (2 := H1). + apply Zle_trans with ([|ih|] * base)%Z; unfold phi2, base; + try rewrite Zpower_2; auto with zarith. + Qed. + + Lemma div312_phi ih il j: (2^30 <= [|j|] -> [|ih|] < [|j|] -> + [|fst (div3121 ih il j)|] = phi2 ih il/[|j|])%Z. + Proof. + intros ih il j Hj Hj1. + generalize (spec_div21 ih il j Hj Hj1). + case div3121; intros q r (Hq, Hr). + apply Zdiv_unique with (phi r); auto with zarith. + simpl fst; apply trans_equal with (1 := Hq); ring. + Qed. + + Lemma sqrt312_step_correct rec ih il j: + 2 ^ 29 <= [|ih|] -> 0 < [|j|] -> phi2 ih il < ([|j|] + 1) ^ 2 -> + (forall j1, 0 < [|j1|] < [|j|] -> phi2 ih il < ([|j1|] + 1) ^ 2 -> + [|rec ih il j1|] ^ 2 <= phi2 ih il < ([|rec ih il j1|] + 1) ^ 2) -> + [|sqrt312_step rec ih il j|] ^ 2 <= phi2 ih il + < ([|sqrt312_step rec ih il j|] + 1) ^ 2. + Proof. + assert (Hp2: (0 < [|2|])%Z) by exact (refl_equal Lt). + intros rec ih il j Hih Hj Hij Hrec; rewrite sqrt312_step_def. + assert (H1: ([|ih|] <= [|j|])%Z) by (apply sqrt312_lower_bound with il; auto). + case (phi_bounded ih); intros Hih1 _. + case (phi_bounded il); intros Hil1 _. + case (phi_bounded j); intros _ Hj1. + assert (Hp3: (0 < phi2 ih il)). + unfold phi2; apply Zlt_le_trans with ([|ih|] * base)%Z; auto with zarith. + apply Zmult_lt_0_compat; auto with zarith. + apply Zlt_le_trans with (2:= Hih); auto with zarith. + generalize (spec_compare ih j); case compare31; intros Hc1. + split; auto. + apply sqrt_test_true; auto. + unfold phi2, base; auto with zarith. + unfold phi2; rewrite Hc1. + assert (0 <= [|il|]/[|j|]) by (apply Z_div_pos; auto with zarith). + rewrite Zmult_comm, Z_div_plus_full_l; unfold base; auto with zarith. + unfold Zpower, Zpower_pos in Hj1; simpl in Hj1; auto with zarith. + case (Zle_or_lt (2 ^ 30) [|j|]); intros Hjj. + generalize (spec_compare (fst (div3121 ih il j)) j); case compare31; + rewrite div312_phi; auto; intros Hc; + try (split; auto; apply sqrt_test_true; auto with zarith; fail). + apply Hrec. + assert (Hf1: 0 <= phi2 ih il/ [|j|]) by (apply Z_div_pos; auto with zarith). + case (Zle_lt_or_eq 1 ([|j|])); auto with zarith; intros Hf2. + 2: contradict Hc; apply Zle_not_lt; rewrite <- Hf2, Zdiv_1_r; auto with zarith. + assert (Hf3: 0 < ([|j|] + phi2 ih il / [|j|]) / 2). + replace ([|j|] + phi2 ih il/ [|j|])%Z with + (1 * 2 + (([|j|] - 2) + phi2 ih il / [|j|])); try ring. + rewrite Z_div_plus_full_l; auto with zarith. + assert (0 <= ([|j|] - 2 + phi2 ih il / [|j|]) / 2) ; auto with zarith. + assert (Hf4: ([|j|] + phi2 ih il / [|j|]) / 2 < [|j|]). + apply sqrt_test_false; auto with zarith. + generalize (spec_add_c j (fst (div3121 ih il j))). + unfold interp_carry; case add31c; intros r; + rewrite div312_phi; auto with zarith. + rewrite div31_phi; change [|2|] with 2%Z; auto with zarith. + intros HH; rewrite HH; clear HH; auto with zarith. + rewrite spec_add, div31_phi; change [|2|] with 2%Z; auto. + rewrite Zmult_1_l; intros HH. + rewrite Zplus_comm, <- Z_div_plus_full_l; auto with zarith. + change (phi v30 * 2) with (2 ^ Z_of_nat size). + rewrite HH, Zmod_small; auto with zarith. + replace (phi + match j +c fst (div3121 ih il j) with + | C0 m1 => fst (m1 / 2)%int31 + | C1 m1 => fst (m1 / 2)%int31 + v30 + end) with ((([|j|] + (phi2 ih il)/([|j|]))/2)). + apply sqrt_main; auto with zarith. + generalize (spec_add_c j (fst (div3121 ih il j))). + unfold interp_carry; case add31c; intros r; + rewrite div312_phi; auto with zarith. + rewrite div31_phi; auto with zarith. + intros HH; rewrite HH; auto with zarith. + intros HH; rewrite <- HH. + change (1 * 2 ^ Z_of_nat size) with (phi (v30) * 2). + rewrite Z_div_plus_full_l; auto with zarith. + rewrite Zplus_comm. + rewrite spec_add, Zmod_small. + rewrite div31_phi; auto. + split; auto with zarith. + case (phi_bounded (fst (r/2)%int31)); + case (phi_bounded v30); auto with zarith. + rewrite div31_phi; change (phi 2) with 2%Z; auto. + change (2 ^Z_of_nat size) with (base/2 + phi v30). + assert (phi r / 2 < base/2); auto with zarith. + apply Zmult_gt_0_lt_reg_r with 2; auto with zarith. + change (base/2 * 2) with base. + apply Zle_lt_trans with (phi r). + rewrite Zmult_comm; apply Z_mult_div_ge; auto with zarith. + case (phi_bounded r); auto with zarith. + contradict Hij; apply Zle_not_lt. + assert ((1 + [|j|]) <= 2 ^ 30); auto with zarith. + apply Zle_trans with ((2 ^ 30) * (2 ^ 30)); auto with zarith. + assert (0 <= 1 + [|j|]); auto with zarith. + apply Zmult_le_compat; auto with zarith. + change ((2 ^ 30) * (2 ^ 30)) with ((2 ^ 29) * base). + apply Zle_trans with ([|ih|] * base); auto with zarith. + unfold phi2, base; auto with zarith. + split; auto. + apply sqrt_test_true; auto. + unfold phi2, base; auto with zarith. + apply Zle_ge; apply Zle_trans with (([|j|] * base)/[|j|]). + rewrite Zmult_comm, Z_div_mult; auto with zarith. + apply Zge_le; apply Z_div_ge; auto with zarith. + Qed. + + Lemma iter312_sqrt_correct n rec ih il j: + 2^29 <= [|ih|] -> 0 < [|j|] -> phi2 ih il < ([|j|] + 1) ^ 2 -> + (forall j1, 0 < [|j1|] -> 2^(Z_of_nat n) + [|j1|] <= [|j|] -> + phi2 ih il < ([|j1|] + 1) ^ 2 -> + [|rec ih il j1|] ^ 2 <= phi2 ih il < ([|rec ih il j1|] + 1) ^ 2) -> + [|iter312_sqrt n rec ih il j|] ^ 2 <= phi2 ih il + < ([|iter312_sqrt n rec ih il j|] + 1) ^ 2. + Proof. + intros n; elim n; unfold iter312_sqrt; fold iter312_sqrt; clear n. + intros rec ih il j Hi Hj Hij Hrec; apply sqrt312_step_correct; auto with zarith. + intros; apply Hrec; auto with zarith. + rewrite Zpower_0_r; auto with zarith. + intros n Hrec rec ih il j Hi Hj Hij HHrec. + apply sqrt312_step_correct; auto. + intros j1 Hj1 Hjp1; apply Hrec; auto with zarith. + intros j2 Hj2 H2j2 Hjp2; apply Hrec; auto with zarith. + intros j3 Hj3 Hpj3. + apply HHrec; auto. + rewrite inj_S, Zpower_Zsucc. + apply Zle_trans with (2 ^Z_of_nat n + [|j2|])%Z; auto with zarith. + apply Zle_0_nat. + Qed. + + Lemma spec_sqrt2 : forall x y, + wB/ 4 <= [|x|] -> + let (s,r) := sqrt312 x y in + [||WW x y||] = [|s|] ^ 2 + [+|r|] /\ + [+|r|] <= 2 * [|s|]. + Proof. + intros ih il Hih; unfold sqrt312. + change [||WW ih il||] with (phi2 ih il). + assert (Hbin: forall s, s * s + 2* s + 1 = (s + 1) ^ 2) by + (intros s; ring). + assert (Hb: 0 <= base) by (red; intros HH; discriminate). + assert (Hi2: phi2 ih il < (phi Tn + 1) ^ 2). + change ((phi Tn + 1) ^ 2) with (2^62). + apply Zle_lt_trans with ((2^31 -1) * base + (2^31 - 1)); auto with zarith. + 2: simpl; unfold Zpower_pos; simpl; auto with zarith. + case (phi_bounded ih); case (phi_bounded il); intros H1 H2 H3 H4. + unfold base, Zpower, Zpower_pos in H2,H4; simpl in H2,H4. + unfold phi2,Zpower, Zpower_pos; simpl iter_pos; auto with zarith. + case (iter312_sqrt_correct 31 (fun _ _ j => j) ih il Tn); auto with zarith. + change [|Tn|] with 2147483647; auto with zarith. + intros j1 _ HH; contradict HH. + apply Zlt_not_le. + change [|Tn|] with 2147483647; auto with zarith. + change (2 ^ Z_of_nat 31) with 2147483648; auto with zarith. + case (phi_bounded j1); auto with zarith. + set (s := iter312_sqrt 31 (fun _ _ j : int31 => j) ih il Tn). + intros Hs1 Hs2. + generalize (spec_mul_c s s); case mul31c. + simpl zn2z_to_Z; intros HH. + assert ([|s|] = 0). + case (Zmult_integral _ _ (sym_equal HH)); auto. + contradict Hs2; apply Zle_not_lt; rewrite H. + change ((0 + 1) ^ 2) with 1. + apply Zle_trans with (2 ^ Z_of_nat size / 4 * base). + simpl; auto with zarith. + apply Zle_trans with ([|ih|] * base); auto with zarith. + unfold phi2; case (phi_bounded il); auto with zarith. + intros ih1 il1. + change [||WW ih1 il1||] with (phi2 ih1 il1). + intros Hihl1. + generalize (spec_sub_c il il1). + case sub31c; intros il2 Hil2. + simpl interp_carry in Hil2. + generalize (spec_compare ih ih1); case compare31. + unfold interp_carry. + intros H1; split. + rewrite Zpower_2, <- Hihl1. + unfold phi2; ring[Hil2 H1]. + replace [|il2|] with (phi2 ih il - phi2 ih1 il1). + rewrite Hihl1. + rewrite <-Hbin in Hs2; auto with zarith. + unfold phi2; rewrite H1, Hil2; ring. + unfold interp_carry. + intros H1; contradict Hs1. + apply Zlt_not_le; rewrite Zpower_2, <-Hihl1. + unfold phi2. + case (phi_bounded il); intros _ H2. + apply Zlt_le_trans with (([|ih|] + 1) * base + 0). + rewrite Zmult_plus_distr_l, Zplus_0_r; auto with zarith. + case (phi_bounded il1); intros H3 _. + apply Zplus_le_compat; auto with zarith. + unfold interp_carry; change (1 * 2 ^ Z_of_nat size) with base. + rewrite Zpower_2, <- Hihl1, Hil2. + intros H1. + case (Zle_lt_or_eq ([|ih1|] + 1) ([|ih|])); auto with zarith. + intros H2; contradict Hs2; apply Zle_not_lt. + replace (([|s|] + 1) ^ 2) with (phi2 ih1 il1 + 2 * [|s|] + 1). + unfold phi2. + case (phi_bounded il); intros Hpil _. + assert (Hl1l: [|il1|] <= [|il|]). + case (phi_bounded il2); rewrite Hil2; auto with zarith. + assert ([|ih1|] * base + 2 * [|s|] + 1 <= [|ih|] * base); auto with zarith. + case (phi_bounded s); change (2 ^ Z_of_nat size) with base; intros _ Hps. + case (phi_bounded ih1); intros Hpih1 _; auto with zarith. + apply Zle_trans with (([|ih1|] + 2) * base); auto with zarith. + rewrite Zmult_plus_distr_l. + assert (2 * [|s|] + 1 <= 2 * base); auto with zarith. + rewrite Hihl1, Hbin; auto. + intros H2; split. + unfold phi2; rewrite <- H2; ring. + replace (base + ([|il|] - [|il1|])) with (phi2 ih il - ([|s|] * [|s|])). + rewrite <-Hbin in Hs2; auto with zarith. + rewrite <- Hihl1; unfold phi2; rewrite <- H2; ring. + unfold interp_carry in Hil2 |- *. + unfold interp_carry; change (1 * 2 ^ Z_of_nat size) with base. + assert (Hsih: [|ih - 1|] = [|ih|] - 1). + rewrite spec_sub, Zmod_small; auto; change [|1|] with 1. + case (phi_bounded ih); intros H1 H2. + generalize Hih; change (2 ^ Z_of_nat size / 4) with 536870912. + split; auto with zarith. + generalize (spec_compare (ih - 1) ih1); case compare31. + rewrite Hsih. + intros H1; split. + rewrite Zpower_2, <- Hihl1. + unfold phi2; rewrite <-H1. + apply trans_equal with ([|ih|] * base + [|il1|] + ([|il|] - [|il1|])). + ring. + rewrite <-Hil2. + change (2 ^ Z_of_nat size) with base; ring. + replace [|il2|] with (phi2 ih il - phi2 ih1 il1). + rewrite Hihl1. + rewrite <-Hbin in Hs2; auto with zarith. + unfold phi2. + rewrite <-H1. + ring_simplify. + apply trans_equal with (base + ([|il|] - [|il1|])). + ring. + rewrite <-Hil2. + change (2 ^ Z_of_nat size) with base; ring. + rewrite Hsih; intros H1. + assert (He: [|ih|] = [|ih1|]). + apply Zle_antisym; auto with zarith. + case (Zle_or_lt [|ih1|] [|ih|]); auto; intros H2. + contradict Hs1; apply Zlt_not_le; rewrite Zpower_2, <-Hihl1. + unfold phi2. + case (phi_bounded il); change (2 ^ Z_of_nat size) with base; + intros _ Hpil1. + apply Zlt_le_trans with (([|ih|] + 1) * base). + rewrite Zmult_plus_distr_l, Zmult_1_l; auto with zarith. + case (phi_bounded il1); intros Hpil2 _. + apply Zle_trans with (([|ih1|]) * base); auto with zarith. + rewrite Zpower_2, <-Hihl1; unfold phi2; rewrite <-He. + contradict Hs1; apply Zlt_not_le; rewrite Zpower_2, <-Hihl1. + unfold phi2; rewrite He. + assert (phi il - phi il1 < 0); auto with zarith. + rewrite <-Hil2. + case (phi_bounded il2); auto with zarith. + intros H1. + rewrite Zpower_2, <-Hihl1. + case (Zle_lt_or_eq ([|ih1|] + 2) [|ih|]); auto with zarith. + intros H2; contradict Hs2; apply Zle_not_lt. + replace (([|s|] + 1) ^ 2) with (phi2 ih1 il1 + 2 * [|s|] + 1). + unfold phi2. + assert ([|ih1|] * base + 2 * phi s + 1 <= [|ih|] * base + ([|il|] - [|il1|])); + auto with zarith. + rewrite <-Hil2. + change (-1 * 2 ^ Z_of_nat size) with (-base). + case (phi_bounded il2); intros Hpil2 _. + apply Zle_trans with ([|ih|] * base + - base); auto with zarith. + case (phi_bounded s); change (2 ^ Z_of_nat size) with base; intros _ Hps. + assert (2 * [|s|] + 1 <= 2 * base); auto with zarith. + apply Zle_trans with ([|ih1|] * base + 2 * base); auto with zarith. + assert (Hi: ([|ih1|] + 3) * base <= [|ih|] * base); auto with zarith. + rewrite Zmult_plus_distr_l in Hi; auto with zarith. + rewrite Hihl1, Hbin; auto. + intros H2; unfold phi2; rewrite <-H2. + split. + replace [|il|] with (([|il|] - [|il1|]) + [|il1|]); try ring. + rewrite <-Hil2. + change (-1 * 2 ^ Z_of_nat size) with (-base); ring. + replace (base + [|il2|]) with (phi2 ih il - phi2 ih1 il1). + rewrite Hihl1. + rewrite <-Hbin in Hs2; auto with zarith. + unfold phi2; rewrite <-H2. + replace [|il|] with (([|il|] - [|il1|]) + [|il1|]); try ring. + rewrite <-Hil2. + change (-1 * 2 ^ Z_of_nat size) with (-base); ring. + Qed. + + (** [iszero] *) + + Let w_eq0 := int31_op.(znz_eq0). + + Lemma spec_eq0 : forall x, w_eq0 x = true -> [|x|] = 0. + Proof. + clear; unfold w_eq0, znz_eq0; simpl. + unfold compare31; simpl; intros. + change [|0|] with 0 in H. + apply Zcompare_Eq_eq. + now destruct ([|x|] ?= 0). + Qed. + + (* Even *) + + Let w_is_even := int31_op.(znz_is_even). + + Lemma spec_is_even : forall x, + if w_is_even x then [|x|] mod 2 = 0 else [|x|] mod 2 = 1. + Proof. + unfold w_is_even; simpl; intros. + generalize (spec_div x 2). + destruct (x/2)%int31 as (q,r); intros. + unfold compare31. + change [|2|] with 2 in H. + change [|0|] with 0. + destruct H; auto with zarith. + replace ([|x|] mod 2) with [|r|]. + destruct H; auto with zarith. + case_eq ([|r|] ?= 0)%Z; intros. + apply Zcompare_Eq_eq; auto. + change ([|r|] < 0)%Z in H; auto with zarith. + change ([|r|] > 0)%Z in H; auto with zarith. + apply Zmod_unique with [|q|]; auto with zarith. + Qed. + + Definition int31_spec : znz_spec int31_op. + split. + exact phi_bounded. + exact positive_to_int31_spec. + exact spec_zdigits. + exact spec_more_than_1_digit. + + exact spec_0. + exact spec_1. + exact spec_Bm1. + + exact spec_compare. + exact spec_eq0. + + exact spec_opp_c. + exact spec_opp. + exact spec_opp_carry. + + exact spec_succ_c. + exact spec_add_c. + exact spec_add_carry_c. + exact spec_succ. + exact spec_add. + exact spec_add_carry. + + exact spec_pred_c. + exact spec_sub_c. + exact spec_sub_carry_c. + exact spec_pred. + exact spec_sub. + exact spec_sub_carry. + + exact spec_mul_c. + exact spec_mul. + exact spec_square_c. + + exact spec_div21. + intros; apply spec_div; auto. + exact spec_div. + + intros; unfold int31_op; simpl; apply spec_mod; auto. + exact spec_mod. + + intros; apply spec_gcd; auto. + exact spec_gcd. + + exact spec_head00. + exact spec_head0. + exact spec_tail00. + exact spec_tail0. + + exact spec_add_mul_div. + exact spec_pos_mod. + + exact spec_is_even. + exact spec_sqrt2. + exact spec_sqrt. + Qed. + +End Int31_Spec. + + +Module Int31Cyclic <: CyclicType. + Definition w := int31. + Definition w_op := int31_op. + Definition w_spec := int31_spec. +End Int31Cyclic. diff --git a/theories/Numbers/Cyclic/Int31/Int31.v b/theories/Numbers/Cyclic/Int31/Int31.v new file mode 100644 index 00000000..154b436b --- /dev/null +++ b/theories/Numbers/Cyclic/Int31/Int31.v @@ -0,0 +1,469 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: Int31.v 11072 2008-06-08 16:13:37Z herbelin $ i*) + +Require Import NaryFunctions. +Require Import Wf_nat. +Require Export ZArith. +Require Export DoubleType. + +Unset Boxed Definitions. + +(** * 31-bit integers *) + +(** This file contains basic definitions of a 31-bit integer + arithmetic. In fact it is more general than that. The only reason + for this use of 31 is the underlying mecanism for hardware-efficient + computations by A. Spiwack. Apart from this, a switch to, say, + 63-bit integers is now just a matter of replacing every occurences + of 31 by 63. This is actually made possible by the use of + dependently-typed n-ary constructions for the inductive type + [int31], its constructor [I31] and any pattern matching on it. + If you modify this file, please preserve this genericity. *) + +Definition size := 31%nat. + +(** Digits *) + +Inductive digits : Type := D0 | D1. + +(** The type of 31-bit integers *) + +(** The type [int31] has a unique constructor [I31] that expects + 31 arguments of type [digits]. *) + +Inductive int31 : Type := I31 : nfun digits size int31. + +(* spiwack: Registration of the type of integers, so that the matchs in + the functions below perform dynamic decompilation (otherwise some segfault + occur when they are applied to one non-closed term and one closed term). *) +Register digits as int31 bits in "coq_int31" by True. +Register int31 as int31 type in "coq_int31" by True. + +Delimit Scope int31_scope with int31. +Bind Scope int31_scope with int31. +Open Scope int31_scope. + +(** * Constants *) + +(** Zero is [I31 D0 ... D0] *) +Definition On : int31 := Eval compute in napply_cst _ _ D0 size I31. + +(** One is [I31 D0 ... D0 D1] *) +Definition In : int31 := Eval compute in (napply_cst _ _ D0 (size-1) I31) D1. + +(** The biggest integer is [I31 D1 ... D1], corresponding to [(2^size)-1] *) +Definition Tn : int31 := Eval compute in napply_cst _ _ D1 size I31. + +(** Two is [I31 D0 ... D0 D1 D0] *) +Definition Twon : int31 := Eval compute in (napply_cst _ _ D0 (size-2) I31) D1 D0. + +(** * Bits manipulation *) + + +(** [sneakr b x] shifts [x] to the right by one bit. + Rightmost digit is lost while leftmost digit becomes [b]. + Pseudo-code is + [ match x with (I31 d0 ... dN) => I31 b d0 ... d(N-1) end ] +*) + +Definition sneakr : digits -> int31 -> int31 := Eval compute in + fun b => int31_rect _ (napply_except_last _ _ (size-1) (I31 b)). + +(** [sneakl b x] shifts [x] to the left by one bit. + Leftmost digit is lost while rightmost digit becomes [b]. + Pseudo-code is + [ match x with (I31 d0 ... dN) => I31 d1 ... dN b end ] +*) + +Definition sneakl : digits -> int31 -> int31 := Eval compute in + fun b => int31_rect _ (fun _ => napply_then_last _ _ b (size-1) I31). + + +(** [shiftl], [shiftr], [twice] and [twice_plus_one] are direct + consequences of [sneakl] and [sneakr]. *) + +Definition shiftl := sneakl D0. +Definition shiftr := sneakr D0. +Definition twice := sneakl D0. +Definition twice_plus_one := sneakl D1. + +(** [firstl x] returns the leftmost digit of number [x]. + Pseudo-code is [ match x with (I31 d0 ... dN) => d0 end ] *) + +Definition firstl : int31 -> digits := Eval compute in + int31_rect _ (fun d => napply_discard _ _ d (size-1)). + +(** [firstr x] returns the rightmost digit of number [x]. + Pseudo-code is [ match x with (I31 d0 ... dN) => dN end ] *) + +Definition firstr : int31 -> digits := Eval compute in + int31_rect _ (napply_discard _ _ (fun d=>d) (size-1)). + +(** [iszero x] is true iff [x = I31 D0 ... D0]. Pseudo-code is + [ match x with (I31 D0 ... D0) => true | _ => false end ] *) + +Definition iszero : int31 -> bool := Eval compute in + let f d b := match d with D0 => b | D1 => false end + in int31_rect _ (nfold_bis _ _ f true size). + +(* NB: DO NOT transform the above match in a nicer (if then else). + It seems to work, but later "unfold iszero" takes forever. *) + + +(** [base] is [2^31], obtained via iterations of [Zdouble]. + It can also be seen as the smallest b > 0 s.t. phi_inv b = 0 + (see below) *) + +Definition base := Eval compute in + iter_nat size Z Zdouble 1%Z. + +(** * Recursors *) + +Fixpoint recl_aux (n:nat)(A:Type)(case0:A)(caserec:digits->int31->A->A) + (i:int31) : A := + match n with + | O => case0 + | S next => + if iszero i then + case0 + else + let si := shiftl i in + caserec (firstl i) si (recl_aux next A case0 caserec si) + end. + +Fixpoint recr_aux (n:nat)(A:Type)(case0:A)(caserec:digits->int31->A->A) + (i:int31) : A := + match n with + | O => case0 + | S next => + if iszero i then + case0 + else + let si := shiftr i in + caserec (firstr i) si (recr_aux next A case0 caserec si) + end. + +Definition recl := recl_aux size. +Definition recr := recr_aux size. + +(** * Conversions *) + +(** From int31 to Z, we simply iterates [Zdouble] or [Zdouble_plus_one]. *) + +Definition phi : int31 -> Z := + recr Z (0%Z) + (fun b _ => match b with D0 => Zdouble | D1 => Zdouble_plus_one end). + +(** From positive to int31. An abstract definition could be : + [ phi_inv (2n) = 2*(phi_inv n) /\ + phi_inv 2n+1 = 2*(phi_inv n) + 1 ] *) + +Fixpoint phi_inv_positive p := + match p with + | xI q => twice_plus_one (phi_inv_positive q) + | xO q => twice (phi_inv_positive q) + | xH => In + end. + +(** The negative part : 2-complement *) + +Fixpoint complement_negative p := + match p with + | xI q => twice (complement_negative q) + | xO q => twice_plus_one (complement_negative q) + | xH => twice Tn + end. + +(** A simple incrementation function *) + +Definition incr : int31 -> int31 := + recr int31 In + (fun b si rec => match b with + | D0 => sneakl D1 si + | D1 => sneakl D0 rec end). + +(** We can now define the conversion from Z to int31. *) + +Definition phi_inv : Z -> int31 := fun n => + match n with + | Z0 => On + | Zpos p => phi_inv_positive p + | Zneg p => incr (complement_negative p) + end. + +(** [phi_inv2] is similar to [phi_inv] but returns a double word + [zn2z int31] *) + +Definition phi_inv2 n := + match n with + | Z0 => W0 + | _ => WW (phi_inv (n/base)%Z) (phi_inv n) + end. + +(** [phi2] is similar to [phi] but takes a double word (two args) *) + +Definition phi2 nh nl := + ((phi nh)*base+(phi nl))%Z. + +(** * Addition *) + +(** Addition modulo [2^31] *) + +Definition add31 (n m : int31) := phi_inv ((phi n)+(phi m)). +Notation "n + m" := (add31 n m) : int31_scope. + +(** Addition with carry (the result is thus exact) *) + +(* spiwack : when executed in non-compiled*) +(* mode, (phi n)+(phi m) is computed twice*) +(* it may be considered to optimize it *) + +Definition add31c (n m : int31) := + let npm := n+m in + match (phi npm ?= (phi n)+(phi m))%Z with + | Eq => C0 npm + | _ => C1 npm + end. +Notation "n '+c' m" := (add31c n m) (at level 50, no associativity) : int31_scope. + +(** Addition plus one with carry (the result is thus exact) *) + +Definition add31carryc (n m : int31) := + let npmpone_exact := ((phi n)+(phi m)+1)%Z in + let npmpone := phi_inv npmpone_exact in + match (phi npmpone ?= npmpone_exact)%Z with + | Eq => C0 npmpone + | _ => C1 npmpone + end. + +(** * Substraction *) + +(** Subtraction modulo [2^31] *) + +Definition sub31 (n m : int31) := phi_inv ((phi n)-(phi m)). +Notation "n - m" := (sub31 n m) : int31_scope. + +(** Subtraction with carry (thus exact) *) + +Definition sub31c (n m : int31) := + let nmm := n-m in + match (phi nmm ?= (phi n)-(phi m))%Z with + | Eq => C0 nmm + | _ => C1 nmm + end. +Notation "n '-c' m" := (sub31c n m) (at level 50, no associativity) : int31_scope. + +(** subtraction minus one with carry (thus exact) *) + +Definition sub31carryc (n m : int31) := + let nmmmone_exact := ((phi n)-(phi m)-1)%Z in + let nmmmone := phi_inv nmmmone_exact in + match (phi nmmmone ?= nmmmone_exact)%Z with + | Eq => C0 nmmmone + | _ => C1 nmmmone + end. + + +(** Multiplication *) + +(** multiplication modulo [2^31] *) + +Definition mul31 (n m : int31) := phi_inv ((phi n)*(phi m)). +Notation "n * m" := (mul31 n m) : int31_scope. + +(** multiplication with double word result (thus exact) *) + +Definition mul31c (n m : int31) := phi_inv2 ((phi n)*(phi m)). +Notation "n '*c' m" := (mul31c n m) (at level 40, no associativity) : int31_scope. + + +(** * Division *) + +(** Division of a double size word modulo [2^31] *) + +Definition div3121 (nh nl m : int31) := + let (q,r) := Zdiv_eucl (phi2 nh nl) (phi m) in + (phi_inv q, phi_inv r). + +(** Division modulo [2^31] *) + +Definition div31 (n m : int31) := + let (q,r) := Zdiv_eucl (phi n) (phi m) in + (phi_inv q, phi_inv r). +Notation "n / m" := (div31 n m) : int31_scope. + + +(** * Unsigned comparison *) + +Definition compare31 (n m : int31) := ((phi n)?=(phi m))%Z. +Notation "n ?= m" := (compare31 n m) (at level 70, no associativity) : int31_scope. + + +(** Computing the [i]-th iterate of a function: + [iter_int31 i A f = f^i] *) + +Definition iter_int31 i A f := + recr (A->A) (fun x => x) + (fun b si rec => match b with + | D0 => fun x => rec (rec x) + | D1 => fun x => f (rec (rec x)) + end) + i. + +(** Combining the [(31-p)] low bits of [i] above the [p] high bits of [j]: + [addmuldiv31 p i j = i*2^p+j/2^(31-p)] (modulo [2^31]) *) + +Definition addmuldiv31 p i j := + let (res, _ ) := + iter_int31 p (int31*int31) + (fun ij => let (i,j) := ij in (sneakl (firstl j) i, shiftl j)) + (i,j) + in + res. + + +Register add31 as int31 plus in "coq_int31" by True. +Register add31c as int31 plusc in "coq_int31" by True. +Register add31carryc as int31 pluscarryc in "coq_int31" by True. +Register sub31 as int31 minus in "coq_int31" by True. +Register sub31c as int31 minusc in "coq_int31" by True. +Register sub31carryc as int31 minuscarryc in "coq_int31" by True. +Register mul31 as int31 times in "coq_int31" by True. +Register mul31c as int31 timesc in "coq_int31" by True. +Register div3121 as int31 div21 in "coq_int31" by True. +Register div31 as int31 div in "coq_int31" by True. +Register compare31 as int31 compare in "coq_int31" by True. +Register addmuldiv31 as int31 addmuldiv in "coq_int31" by True. + +Definition gcd31 (i j:int31) := + (fix euler (guard:nat) (i j:int31) {struct guard} := + match guard with + | O => In + | S p => match j ?= On with + | Eq => i + | _ => euler p j (let (_, r ) := i/j in r) + end + end) + (2*size)%nat i j. + +(** Square root functions using newton iteration + we use a very naive upper-bound on the iteration + 2^31 instead of the usual 31. +**) + + + +Definition sqrt31_step (rec: int31 -> int31 -> int31) (i j: int31) := +Eval lazy delta [Twon] in + let (quo,_) := i/j in + match quo ?= j with + Lt => rec i (fst ((j + quo)/Twon)) + | _ => j + end. + +Fixpoint iter31_sqrt (n: nat) (rec: int31 -> int31 -> int31) + (i j: int31) {struct n} : int31 := + sqrt31_step + (match n with + O => rec + | S n => (iter31_sqrt n (iter31_sqrt n rec)) + end) i j. + +Definition sqrt31 i := +Eval lazy delta [On In Twon] in + match compare31 In i with + Gt => On + | Eq => In + | Lt => iter31_sqrt 31 (fun i j => j) i (fst (i/Twon)) + end. + +Definition v30 := Eval compute in (addmuldiv31 (phi_inv (Z_of_nat size - 1)) In On). + +Definition sqrt312_step (rec: int31 -> int31 -> int31 -> int31) + (ih il j: int31) := +Eval lazy delta [Twon v30] in + match ih ?= j with Eq => j | Gt => j | _ => + let (quo,_) := div3121 ih il j in + match quo ?= j with + Lt => let m := match j +c quo with + C0 m1 => fst (m1/Twon) + | C1 m1 => fst (m1/Twon) + v30 + end in rec ih il m + | _ => j + end end. + +Fixpoint iter312_sqrt (n: nat) + (rec: int31 -> int31 -> int31 -> int31) + (ih il j: int31) {struct n} : int31 := + sqrt312_step + (match n with + O => rec + | S n => (iter312_sqrt n (iter312_sqrt n rec)) + end) ih il j. + +Definition sqrt312 ih il := +Eval lazy delta [On In] in + let s := iter312_sqrt 31 (fun ih il j => j) ih il Tn in + match s *c s with + W0 => (On, C0 On) (* impossible *) + | WW ih1 il1 => + match il -c il1 with + C0 il2 => + match ih ?= ih1 with + Gt => (s, C1 il2) + | _ => (s, C0 il2) + end + | C1 il2 => + match (ih - In) ?= ih1 with (* we could parametrize ih - 1 *) + Gt => (s, C1 il2) + | _ => (s, C0 il2) + end + end + end. + + +Fixpoint p2i n p : (N*int31)%type := + match n with + | O => (Npos p, On) + | S n => match p with + | xO p => let (r,i) := p2i n p in (r, Twon*i) + | xI p => let (r,i) := p2i n p in (r, Twon*i+In) + | xH => (N0, In) + end + end. + +Definition positive_to_int31 (p:positive) := p2i size p. + +(** Constant 31 converted into type int31. + It is used as default answer for numbers of zeros + in [head0] and [tail0] *) + +Definition T31 : int31 := Eval compute in phi_inv (Z_of_nat size). + +Definition head031 (i:int31) := + recl _ (fun _ => T31) + (fun b si rec n => match b with + | D0 => rec (add31 n In) + | D1 => n + end) + i On. + +Definition tail031 (i:int31) := + recr _ (fun _ => T31) + (fun b si rec n => match b with + | D0 => rec (add31 n In) + | D1 => n + end) + i On. + +Register head031 as int31 head0 in "coq_int31" by True. +Register tail031 as int31 tail0 in "coq_int31" by True. diff --git a/theories/Numbers/Cyclic/ZModulo/ZModulo.v b/theories/Numbers/Cyclic/ZModulo/ZModulo.v new file mode 100644 index 00000000..7c770e97 --- /dev/null +++ b/theories/Numbers/Cyclic/ZModulo/ZModulo.v @@ -0,0 +1,946 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* $Id: ZModulo.v 11033 2008-06-01 22:56:50Z letouzey $ *) + +(** * Type [Z] viewed modulo a particular constant corresponds to [Z/nZ] + as defined abstractly in CyclicAxioms. *) + +(** Even if the construction provided here is not reused for building + the efficient arbitrary precision numbers, it provides a simple + implementation of CyclicAxioms, hence ensuring its coherence. *) + +Set Implicit Arguments. + +Require Import Bool. +Require Import ZArith. +Require Import Znumtheory. +Require Import BigNumPrelude. +Require Import DoubleType. +Require Import CyclicAxioms. + +Open Local Scope Z_scope. + +Section ZModulo. + + Variable digits : positive. + Hypothesis digits_ne_1 : digits <> 1%positive. + + Definition wB := base digits. + + Definition znz := Z. + Definition znz_digits := digits. + Definition znz_zdigits := Zpos digits. + Definition znz_to_Z x := x mod wB. + + Notation "[| x |]" := (znz_to_Z x) (at level 0, x at level 99). + + Notation "[+| c |]" := + (interp_carry 1 wB znz_to_Z c) (at level 0, x at level 99). + + Notation "[-| c |]" := + (interp_carry (-1) wB znz_to_Z c) (at level 0, x at level 99). + + Notation "[|| x ||]" := + (zn2z_to_Z wB znz_to_Z x) (at level 0, x at level 99). + + Lemma spec_more_than_1_digit: 1 < Zpos digits. + Proof. + unfold znz_digits. + generalize digits_ne_1; destruct digits; auto. + destruct 1; auto. + Qed. + Let digits_gt_1 := spec_more_than_1_digit. + + Lemma wB_pos : wB > 0. + Proof. + unfold wB, base; auto with zarith. + Qed. + Hint Resolve wB_pos. + + Lemma spec_to_Z_1 : forall x, 0 <= [|x|]. + Proof. + unfold znz_to_Z; intros; destruct (Z_mod_lt x wB wB_pos); auto. + Qed. + + Lemma spec_to_Z_2 : forall x, [|x|] < wB. + Proof. + unfold znz_to_Z; intros; destruct (Z_mod_lt x wB wB_pos); auto. + Qed. + Hint Resolve spec_to_Z_1 spec_to_Z_2. + + Lemma spec_to_Z : forall x, 0 <= [|x|] < wB. + Proof. + auto. + Qed. + + Definition znz_of_pos x := + let (q,r) := Zdiv_eucl_POS x wB in (N_of_Z q, r). + + Lemma spec_of_pos : forall p, + Zpos p = (Z_of_N (fst (znz_of_pos p)))*wB + [|(snd (znz_of_pos p))|]. + Proof. + intros; unfold znz_of_pos; simpl. + generalize (Z_div_mod_POS wB wB_pos p). + destruct (Zdiv_eucl_POS p wB); simpl; destruct 1. + unfold znz_to_Z; rewrite Zmod_small; auto. + assert (0 <= z). + replace z with (Zpos p / wB) by + (symmetry; apply Zdiv_unique with z0; auto). + apply Z_div_pos; auto with zarith. + replace (Z_of_N (N_of_Z z)) with z by + (destruct z; simpl; auto; elim H1; auto). + rewrite Zmult_comm; auto. + Qed. + + Lemma spec_zdigits : [|znz_zdigits|] = Zpos znz_digits. + Proof. + unfold znz_to_Z, znz_zdigits, znz_digits. + apply Zmod_small. + unfold wB, base. + split; auto with zarith. + apply Zpower2_lt_lin; auto with zarith. + Qed. + + Definition znz_0 := 0. + Definition znz_1 := 1. + Definition znz_Bm1 := wB - 1. + + Lemma spec_0 : [|znz_0|] = 0. + Proof. + unfold znz_to_Z, znz_0. + apply Zmod_small; generalize wB_pos; auto with zarith. + Qed. + + Lemma spec_1 : [|znz_1|] = 1. + Proof. + unfold znz_to_Z, znz_1. + apply Zmod_small; split; auto with zarith. + unfold wB, base. + apply Zlt_trans with (Zpos digits); auto. + apply Zpower2_lt_lin; auto with zarith. + Qed. + + Lemma spec_Bm1 : [|znz_Bm1|] = wB - 1. + Proof. + unfold znz_to_Z, znz_Bm1. + apply Zmod_small; split; auto with zarith. + unfold wB, base. + cut (1 <= 2 ^ Zpos digits); auto with zarith. + apply Zle_trans with (Zpos digits); auto with zarith. + apply Zpower2_le_lin; auto with zarith. + Qed. + + Definition znz_compare x y := Zcompare [|x|] [|y|]. + + Lemma spec_compare : forall x y, + match znz_compare x y with + | Eq => [|x|] = [|y|] + | Lt => [|x|] < [|y|] + | Gt => [|x|] > [|y|] + end. + Proof. + intros; unfold znz_compare, Zlt, Zgt. + case_eq (Zcompare [|x|] [|y|]); auto. + intros; apply Zcompare_Eq_eq; auto. + Qed. + + Definition znz_eq0 x := + match [|x|] with Z0 => true | _ => false end. + + Lemma spec_eq0 : forall x, znz_eq0 x = true -> [|x|] = 0. + Proof. + unfold znz_eq0; intros; now destruct [|x|]. + Qed. + + Definition znz_opp_c x := + if znz_eq0 x then C0 0 else C1 (- x). + Definition znz_opp x := - x. + Definition znz_opp_carry x := - x - 1. + + Lemma spec_opp_c : forall x, [-|znz_opp_c x|] = -[|x|]. + Proof. + intros; unfold znz_opp_c, znz_to_Z; auto. + case_eq (znz_eq0 x); intros; unfold interp_carry. + fold [|x|]; rewrite (spec_eq0 x H); auto. + assert (x mod wB <> 0). + unfold znz_eq0, znz_to_Z in H. + intro H0; rewrite H0 in H; discriminate. + rewrite Z_mod_nz_opp_full; auto with zarith. + Qed. + + Lemma spec_opp : forall x, [|znz_opp x|] = (-[|x|]) mod wB. + Proof. + intros; unfold znz_opp, znz_to_Z; auto. + change ((- x) mod wB = (0 - (x mod wB)) mod wB). + rewrite Zminus_mod_idemp_r; simpl; auto. + Qed. + + Lemma spec_opp_carry : forall x, [|znz_opp_carry x|] = wB - [|x|] - 1. + Proof. + intros; unfold znz_opp_carry, znz_to_Z; auto. + replace (- x - 1) with (- 1 - x) by omega. + rewrite <- Zminus_mod_idemp_r. + replace ( -1 - x mod wB) with (0 + ( -1 - x mod wB)) by omega. + rewrite <- (Z_mod_same_full wB). + rewrite Zplus_mod_idemp_l. + replace (wB + (-1 - x mod wB)) with (wB - x mod wB -1) by omega. + apply Zmod_small. + generalize (Z_mod_lt x wB wB_pos); omega. + Qed. + + Definition znz_succ_c x := + let y := Zsucc x in + if znz_eq0 y then C1 0 else C0 y. + + Definition znz_add_c x y := + let z := [|x|] + [|y|] in + if Z_lt_le_dec z wB then C0 z else C1 (z-wB). + + Definition znz_add_carry_c x y := + let z := [|x|]+[|y|]+1 in + if Z_lt_le_dec z wB then C0 z else C1 (z-wB). + + Definition znz_succ := Zsucc. + Definition znz_add := Zplus. + Definition znz_add_carry x y := x + y + 1. + + Lemma Zmod_equal : + forall x y z, z>0 -> (x-y) mod z = 0 -> x mod z = y mod z. + Proof. + intros. + generalize (Z_div_mod_eq (x-y) z H); rewrite H0, Zplus_0_r. + remember ((x-y)/z) as k. + intros H1; symmetry in H1; rewrite <- Zeq_plus_swap in H1. + subst x. + rewrite Zplus_comm, Zmult_comm, Z_mod_plus; auto. + Qed. + + Lemma spec_succ_c : forall x, [+|znz_succ_c x|] = [|x|] + 1. + Proof. + intros; unfold znz_succ_c, znz_to_Z, Zsucc. + case_eq (znz_eq0 (x+1)); intros; unfold interp_carry. + + rewrite Zmult_1_l. + replace (wB + 0 mod wB) with wB by auto with zarith. + symmetry; rewrite Zeq_plus_swap. + assert ((x+1) mod wB = 0) by (apply spec_eq0; auto). + replace (wB-1) with ((wB-1) mod wB) by + (apply Zmod_small; generalize wB_pos; omega). + rewrite <- Zminus_mod_idemp_l; rewrite Z_mod_same; simpl; auto. + apply Zmod_equal; auto. + + assert ((x+1) mod wB <> 0). + unfold znz_eq0, znz_to_Z in *; now destruct ((x+1) mod wB). + assert (x mod wB + 1 <> wB). + contradict H0. + rewrite Zeq_plus_swap in H0; simpl in H0. + rewrite <- Zplus_mod_idemp_l; rewrite H0. + replace (wB-1+1) with wB; auto with zarith; apply Z_mod_same; auto. + rewrite <- Zplus_mod_idemp_l. + apply Zmod_small. + generalize (Z_mod_lt x wB wB_pos); omega. + Qed. + + Lemma spec_add_c : forall x y, [+|znz_add_c x y|] = [|x|] + [|y|]. + Proof. + intros; unfold znz_add_c, znz_to_Z, interp_carry. + destruct Z_lt_le_dec. + apply Zmod_small; + generalize (Z_mod_lt x wB wB_pos) (Z_mod_lt y wB wB_pos); omega. + rewrite Zmult_1_l, Zplus_comm, Zeq_plus_swap. + apply Zmod_small; + generalize (Z_mod_lt x wB wB_pos) (Z_mod_lt y wB wB_pos); omega. + Qed. + + Lemma spec_add_carry_c : forall x y, [+|znz_add_carry_c x y|] = [|x|] + [|y|] + 1. + Proof. + intros; unfold znz_add_carry_c, znz_to_Z, interp_carry. + destruct Z_lt_le_dec. + apply Zmod_small; + generalize (Z_mod_lt x wB wB_pos) (Z_mod_lt y wB wB_pos); omega. + rewrite Zmult_1_l, Zplus_comm, Zeq_plus_swap. + apply Zmod_small; + generalize (Z_mod_lt x wB wB_pos) (Z_mod_lt y wB wB_pos); omega. + Qed. + + Lemma spec_succ : forall x, [|znz_succ x|] = ([|x|] + 1) mod wB. + Proof. + intros; unfold znz_succ, znz_to_Z, Zsucc. + symmetry; apply Zplus_mod_idemp_l. + Qed. + + Lemma spec_add : forall x y, [|znz_add x y|] = ([|x|] + [|y|]) mod wB. + Proof. + intros; unfold znz_add, znz_to_Z; apply Zplus_mod. + Qed. + + Lemma spec_add_carry : + forall x y, [|znz_add_carry x y|] = ([|x|] + [|y|] + 1) mod wB. + Proof. + intros; unfold znz_add_carry, znz_to_Z. + rewrite <- Zplus_mod_idemp_l. + rewrite (Zplus_mod x y). + rewrite Zplus_mod_idemp_l; auto. + Qed. + + Definition znz_pred_c x := + if znz_eq0 x then C1 (wB-1) else C0 (x-1). + + Definition znz_sub_c x y := + let z := [|x|]-[|y|] in + if Z_lt_le_dec z 0 then C1 (wB+z) else C0 z. + + Definition znz_sub_carry_c x y := + let z := [|x|]-[|y|]-1 in + if Z_lt_le_dec z 0 then C1 (wB+z) else C0 z. + + Definition znz_pred := Zpred. + Definition znz_sub := Zminus. + Definition znz_sub_carry x y := x - y - 1. + + Lemma spec_pred_c : forall x, [-|znz_pred_c x|] = [|x|] - 1. + Proof. + intros; unfold znz_pred_c, znz_to_Z, interp_carry. + case_eq (znz_eq0 x); intros. + fold [|x|]; rewrite spec_eq0; auto. + replace ((wB-1) mod wB) with (wB-1); auto with zarith. + symmetry; apply Zmod_small; generalize wB_pos; omega. + + assert (x mod wB <> 0). + unfold znz_eq0, znz_to_Z in *; now destruct (x mod wB). + rewrite <- Zminus_mod_idemp_l. + apply Zmod_small. + generalize (Z_mod_lt x wB wB_pos); omega. + Qed. + + Lemma spec_sub_c : forall x y, [-|znz_sub_c x y|] = [|x|] - [|y|]. + Proof. + intros; unfold znz_sub_c, znz_to_Z, interp_carry. + destruct Z_lt_le_dec. + replace ((wB + (x mod wB - y mod wB)) mod wB) with + (wB + (x mod wB - y mod wB)). + omega. + symmetry; apply Zmod_small. + generalize wB_pos (Z_mod_lt x wB wB_pos) (Z_mod_lt y wB wB_pos); omega. + + apply Zmod_small. + generalize wB_pos (Z_mod_lt x wB wB_pos) (Z_mod_lt y wB wB_pos); omega. + Qed. + + Lemma spec_sub_carry_c : forall x y, [-|znz_sub_carry_c x y|] = [|x|] - [|y|] - 1. + Proof. + intros; unfold znz_sub_carry_c, znz_to_Z, interp_carry. + destruct Z_lt_le_dec. + replace ((wB + (x mod wB - y mod wB - 1)) mod wB) with + (wB + (x mod wB - y mod wB -1)). + omega. + symmetry; apply Zmod_small. + generalize wB_pos (Z_mod_lt x wB wB_pos) (Z_mod_lt y wB wB_pos); omega. + + apply Zmod_small. + generalize wB_pos (Z_mod_lt x wB wB_pos) (Z_mod_lt y wB wB_pos); omega. + Qed. + + Lemma spec_pred : forall x, [|znz_pred x|] = ([|x|] - 1) mod wB. + Proof. + intros; unfold znz_pred, znz_to_Z, Zpred. + rewrite <- Zplus_mod_idemp_l; auto. + Qed. + + Lemma spec_sub : forall x y, [|znz_sub x y|] = ([|x|] - [|y|]) mod wB. + Proof. + intros; unfold znz_sub, znz_to_Z; apply Zminus_mod. + Qed. + + Lemma spec_sub_carry : + forall x y, [|znz_sub_carry x y|] = ([|x|] - [|y|] - 1) mod wB. + Proof. + intros; unfold znz_sub_carry, znz_to_Z. + rewrite <- Zminus_mod_idemp_l. + rewrite (Zminus_mod x y). + rewrite Zminus_mod_idemp_l. + auto. + Qed. + + Definition znz_mul_c x y := + let (h,l) := Zdiv_eucl ([|x|]*[|y|]) wB in + if znz_eq0 h then if znz_eq0 l then W0 else WW h l else WW h l. + + Definition znz_mul := Zmult. + + Definition znz_square_c x := znz_mul_c x x. + + Lemma spec_mul_c : forall x y, [|| znz_mul_c x y ||] = [|x|] * [|y|]. + Proof. + intros; unfold znz_mul_c, zn2z_to_Z. + assert (Zdiv_eucl ([|x|]*[|y|]) wB = (([|x|]*[|y|])/wB,([|x|]*[|y|]) mod wB)). + unfold Zmod, Zdiv; destruct Zdiv_eucl; auto. + generalize (Z_div_mod ([|x|]*[|y|]) wB wB_pos); destruct Zdiv_eucl as (h,l). + destruct 1; injection H; clear H; intros. + rewrite H0. + assert ([|l|] = l). + apply Zmod_small; auto. + assert ([|h|] = h). + apply Zmod_small. + subst h. + split. + apply Z_div_pos; auto with zarith. + apply Zdiv_lt_upper_bound; auto with zarith. + apply Zmult_lt_compat; auto with zarith. + clear H H0 H1 H2. + case_eq (znz_eq0 h); simpl; intros. + case_eq (znz_eq0 l); simpl; intros. + rewrite <- H3, <- H4, (spec_eq0 h), (spec_eq0 l); auto with zarith. + rewrite H3, H4; auto with zarith. + rewrite H3, H4; auto with zarith. + Qed. + + Lemma spec_mul : forall x y, [|znz_mul x y|] = ([|x|] * [|y|]) mod wB. + Proof. + intros; unfold znz_mul, znz_to_Z; apply Zmult_mod. + Qed. + + Lemma spec_square_c : forall x, [|| znz_square_c x||] = [|x|] * [|x|]. + Proof. + intros x; exact (spec_mul_c x x). + Qed. + + Definition znz_div x y := Zdiv_eucl [|x|] [|y|]. + + Lemma spec_div : forall a b, 0 < [|b|] -> + let (q,r) := znz_div a b in + [|a|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]. + Proof. + intros; unfold znz_div. + assert ([|b|]>0) by auto with zarith. + assert (Zdiv_eucl [|a|] [|b|] = ([|a|]/[|b|], [|a|] mod [|b|])). + unfold Zmod, Zdiv; destruct Zdiv_eucl; auto. + generalize (Z_div_mod [|a|] [|b|] H0). + destruct Zdiv_eucl as (q,r); destruct 1; intros. + injection H1; clear H1; intros. + assert ([|r|]=r). + apply Zmod_small; generalize (Z_mod_lt b wB wB_pos); fold [|b|]; + auto with zarith. + assert ([|q|]=q). + apply Zmod_small. + subst q. + split. + apply Z_div_pos; auto with zarith. + apply Zdiv_lt_upper_bound; auto with zarith. + apply Zlt_le_trans with (wB*1). + rewrite Zmult_1_r; auto with zarith. + apply Zmult_le_compat; generalize wB_pos; auto with zarith. + rewrite H5, H6; rewrite Zmult_comm; auto with zarith. + Qed. + + Definition znz_div_gt := znz_div. + + Lemma spec_div_gt : forall a b, [|a|] > [|b|] -> 0 < [|b|] -> + let (q,r) := znz_div_gt a b in + [|a|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]. + Proof. + intros. + apply spec_div; auto. + Qed. + + Definition znz_mod x y := [|x|] mod [|y|]. + Definition znz_mod_gt x y := [|x|] mod [|y|]. + + Lemma spec_mod : forall a b, 0 < [|b|] -> + [|znz_mod a b|] = [|a|] mod [|b|]. + Proof. + intros; unfold znz_mod. + apply Zmod_small. + assert ([|b|]>0) by auto with zarith. + generalize (Z_mod_lt [|a|] [|b|] H0) (Z_mod_lt b wB wB_pos). + fold [|b|]; omega. + Qed. + + Lemma spec_mod_gt : forall a b, [|a|] > [|b|] -> 0 < [|b|] -> + [|znz_mod_gt a b|] = [|a|] mod [|b|]. + Proof. + intros; apply spec_mod; auto. + Qed. + + Definition znz_gcd x y := Zgcd [|x|] [|y|]. + Definition znz_gcd_gt x y := Zgcd [|x|] [|y|]. + + Lemma Zgcd_bound : forall a b, 0<=a -> 0<=b -> Zgcd a b <= Zmax a b. + Proof. + intros. + generalize (Zgcd_is_gcd a b); inversion_clear 1. + destruct H2; destruct H3; clear H4. + assert (H3:=Zgcd_is_pos a b). + destruct (Z_eq_dec (Zgcd a b) 0). + rewrite e; generalize (Zmax_spec a b); omega. + assert (0 <= q). + apply Zmult_le_reg_r with (Zgcd a b); auto with zarith. + destruct (Z_eq_dec q 0). + + subst q; simpl in *; subst a; simpl; auto. + generalize (Zmax_spec 0 b) (Zabs_spec b); omega. + + apply Zle_trans with a. + rewrite H1 at 2. + rewrite <- (Zmult_1_l (Zgcd a b)) at 1. + apply Zmult_le_compat; auto with zarith. + generalize (Zmax_spec a b); omega. + Qed. + + Lemma spec_gcd : forall a b, Zis_gcd [|a|] [|b|] [|znz_gcd a b|]. + Proof. + intros; unfold znz_gcd. + generalize (Z_mod_lt a wB wB_pos)(Z_mod_lt b wB wB_pos); intros. + fold [|a|] in *; fold [|b|] in *. + replace ([|Zgcd [|a|] [|b|]|]) with (Zgcd [|a|] [|b|]). + apply Zgcd_is_gcd. + symmetry; apply Zmod_small. + split. + apply Zgcd_is_pos. + apply Zle_lt_trans with (Zmax [|a|] [|b|]). + apply Zgcd_bound; auto with zarith. + generalize (Zmax_spec [|a|] [|b|]); omega. + Qed. + + Lemma spec_gcd_gt : forall a b, [|a|] > [|b|] -> + Zis_gcd [|a|] [|b|] [|znz_gcd_gt a b|]. + Proof. + intros. apply spec_gcd; auto. + Qed. + + Definition znz_div21 a1 a2 b := + Zdiv_eucl ([|a1|]*wB+[|a2|]) [|b|]. + + Lemma spec_div21 : forall a1 a2 b, + wB/2 <= [|b|] -> + [|a1|] < [|b|] -> + let (q,r) := znz_div21 a1 a2 b in + [|a1|] *wB+ [|a2|] = [|q|] * [|b|] + [|r|] /\ + 0 <= [|r|] < [|b|]. + Proof. + intros; unfold znz_div21. + generalize (Z_mod_lt a1 wB wB_pos); fold [|a1|]; intros. + generalize (Z_mod_lt a2 wB wB_pos); fold [|a2|]; intros. + assert ([|b|]>0) by auto with zarith. + remember ([|a1|]*wB+[|a2|]) as a. + assert (Zdiv_eucl a [|b|] = (a/[|b|], a mod [|b|])). + unfold Zmod, Zdiv; destruct Zdiv_eucl; auto. + generalize (Z_div_mod a [|b|] H3). + destruct Zdiv_eucl as (q,r); destruct 1; intros. + injection H4; clear H4; intros. + assert ([|r|]=r). + apply Zmod_small; generalize (Z_mod_lt b wB wB_pos); fold [|b|]; + auto with zarith. + assert ([|q|]=q). + apply Zmod_small. + subst q. + split. + apply Z_div_pos; auto with zarith. + subst a; auto with zarith. + apply Zdiv_lt_upper_bound; auto with zarith. + subst a; auto with zarith. + subst a. + replace (wB*[|b|]) with (([|b|]-1)*wB + wB) by ring. + apply Zlt_le_trans with ([|a1|]*wB+wB); auto with zarith. + rewrite H8, H9; rewrite Zmult_comm; auto with zarith. + Qed. + + Definition znz_add_mul_div p x y := + ([|x|] * (2 ^ [|p|]) + [|y|] / (2 ^ ((Zpos znz_digits) - [|p|]))). + Lemma spec_add_mul_div : forall x y p, + [|p|] <= Zpos znz_digits -> + [| znz_add_mul_div p x y |] = + ([|x|] * (2 ^ [|p|]) + + [|y|] / (2 ^ ((Zpos znz_digits) - [|p|]))) mod wB. + Proof. + intros; unfold znz_add_mul_div; auto. + Qed. + + Definition znz_pos_mod p w := [|w|] mod (2 ^ [|p|]). + Lemma spec_pos_mod : forall w p, + [|znz_pos_mod p w|] = [|w|] mod (2 ^ [|p|]). + Proof. + intros; unfold znz_pos_mod. + apply Zmod_small. + generalize (Z_mod_lt [|w|] (2 ^ [|p|])); intros. + split. + destruct H; auto with zarith. + apply Zle_lt_trans with [|w|]; auto with zarith. + apply Zmod_le; auto with zarith. + Qed. + + Definition znz_is_even x := + if Z_eq_dec ([|x|] mod 2) 0 then true else false. + + Lemma spec_is_even : forall x, + if znz_is_even x then [|x|] mod 2 = 0 else [|x|] mod 2 = 1. + Proof. + intros; unfold znz_is_even; destruct Z_eq_dec; auto. + generalize (Z_mod_lt [|x|] 2); omega. + Qed. + + Definition znz_sqrt x := Zsqrt_plain [|x|]. + Lemma spec_sqrt : forall x, + [|znz_sqrt x|] ^ 2 <= [|x|] < ([|znz_sqrt x|] + 1) ^ 2. + Proof. + intros. + unfold znz_sqrt. + repeat rewrite Zpower_2. + replace [|Zsqrt_plain [|x|]|] with (Zsqrt_plain [|x|]). + apply Zsqrt_interval; auto with zarith. + symmetry; apply Zmod_small. + split. + apply Zsqrt_plain_is_pos; auto with zarith. + + cut (Zsqrt_plain [|x|] <= (wB-1)); try omega. + rewrite <- (Zsqrt_square_id (wB-1)). + apply Zsqrt_le. + split; auto. + apply Zle_trans with (wB-1); auto with zarith. + generalize (spec_to_Z x); auto with zarith. + apply Zsquare_le. + generalize wB_pos; auto with zarith. + Qed. + + Definition znz_sqrt2 x y := + let z := [|x|]*wB+[|y|] in + match z with + | Z0 => (0, C0 0) + | Zpos p => + let (s,r,_,_) := sqrtrempos p in + (s, if Z_lt_le_dec r wB then C0 r else C1 (r-wB)) + | Zneg _ => (0, C0 0) + end. + + Lemma spec_sqrt2 : forall x y, + wB/ 4 <= [|x|] -> + let (s,r) := znz_sqrt2 x y in + [||WW x y||] = [|s|] ^ 2 + [+|r|] /\ + [+|r|] <= 2 * [|s|]. + Proof. + intros; unfold znz_sqrt2. + simpl zn2z_to_Z. + remember ([|x|]*wB+[|y|]) as z. + destruct z. + auto with zarith. + destruct sqrtrempos; intros. + assert (s < wB). + destruct (Z_lt_le_dec s wB); auto. + assert (wB * wB <= Zpos p). + rewrite e. + apply Zle_trans with (s*s); try omega. + apply Zmult_le_compat; generalize wB_pos; auto with zarith. + assert (Zpos p < wB*wB). + rewrite Heqz. + replace (wB*wB) with ((wB-1)*wB+wB) by ring. + apply Zplus_le_lt_compat; auto with zarith. + apply Zmult_le_compat; auto with zarith. + generalize (spec_to_Z x); auto with zarith. + generalize wB_pos; auto with zarith. + omega. + replace [|s|] with s by (symmetry; apply Zmod_small; auto with zarith). + destruct Z_lt_le_dec; unfold interp_carry. + replace [|r|] with r by (symmetry; apply Zmod_small; auto with zarith). + rewrite Zpower_2; auto with zarith. + replace [|r-wB|] with (r-wB) by (symmetry; apply Zmod_small; auto with zarith). + rewrite Zpower_2; omega. + + assert (0<=Zneg p). + rewrite Heqz; generalize wB_pos; auto with zarith. + compute in H0; elim H0; auto. + Qed. + + Lemma two_p_power2 : forall x, x>=0 -> two_p x = 2 ^ x. + Proof. + intros. + unfold two_p. + destruct x; simpl; auto. + apply two_power_pos_correct. + Qed. + + Definition znz_head0 x := match [|x|] with + | Z0 => znz_zdigits + | Zpos p => znz_zdigits - log_inf p - 1 + | _ => 0 + end. + + Lemma spec_head00: forall x, [|x|] = 0 -> [|znz_head0 x|] = Zpos znz_digits. + Proof. + unfold znz_head0; intros. + rewrite H; simpl. + apply spec_zdigits. + Qed. + + Lemma log_inf_bounded : forall x p, Zpos x < 2^p -> log_inf x < p. + Proof. + induction x; simpl; intros. + + assert (0 < p) by (destruct p; compute; auto with zarith; discriminate). + cut (log_inf x < p - 1); [omega| ]. + apply IHx. + change (Zpos x~1) with (2*(Zpos x)+1) in H. + replace p with (Zsucc (p-1)) in H; auto with zarith. + rewrite Zpower_Zsucc in H; auto with zarith. + + assert (0 < p) by (destruct p; compute; auto with zarith; discriminate). + cut (log_inf x < p - 1); [omega| ]. + apply IHx. + change (Zpos x~0) with (2*(Zpos x)) in H. + replace p with (Zsucc (p-1)) in H; auto with zarith. + rewrite Zpower_Zsucc in H; auto with zarith. + + simpl; intros; destruct p; compute; auto with zarith. + Qed. + + + Lemma spec_head0 : forall x, 0 < [|x|] -> + wB/ 2 <= 2 ^ ([|znz_head0 x|]) * [|x|] < wB. + Proof. + intros; unfold znz_head0. + generalize (spec_to_Z x). + destruct [|x|]; try discriminate. + intros. + destruct (log_inf_correct p). + rewrite 2 two_p_power2 in H2; auto with zarith. + assert (0 <= znz_zdigits - log_inf p - 1 < wB). + split. + cut (log_inf p < znz_zdigits); try omega. + unfold znz_zdigits. + unfold wB, base in *. + apply log_inf_bounded; auto with zarith. + apply Zlt_trans with znz_zdigits. + omega. + unfold znz_zdigits, wB, base; apply Zpower2_lt_lin; auto with zarith. + + unfold znz_to_Z; rewrite (Zmod_small _ _ H3). + destruct H2. + split. + apply Zle_trans with (2^(znz_zdigits - log_inf p - 1)*(2^log_inf p)). + apply Zdiv_le_upper_bound; auto with zarith. + rewrite <- Zpower_exp; auto with zarith. + rewrite Zmult_comm; rewrite <- Zpower_Zsucc; auto with zarith. + replace (Zsucc (znz_zdigits - log_inf p -1 +log_inf p)) with znz_zdigits + by ring. + unfold wB, base, znz_zdigits; auto with zarith. + apply Zmult_le_compat; auto with zarith. + + apply Zlt_le_trans + with (2^(znz_zdigits - log_inf p - 1)*(2^(Zsucc (log_inf p)))). + apply Zmult_lt_compat_l; auto with zarith. + rewrite <- Zpower_exp; auto with zarith. + replace (znz_zdigits - log_inf p -1 +Zsucc (log_inf p)) with znz_zdigits + by ring. + unfold wB, base, znz_zdigits; auto with zarith. + Qed. + + Fixpoint Ptail p := match p with + | xO p => (Ptail p)+1 + | _ => 0 + end. + + Lemma Ptail_pos : forall p, 0 <= Ptail p. + Proof. + induction p; simpl; auto with zarith. + Qed. + Hint Resolve Ptail_pos. + + Lemma Ptail_bounded : forall p d, Zpos p < 2^(Zpos d) -> Ptail p < Zpos d. + Proof. + induction p; try (compute; auto; fail). + intros; simpl. + assert (d <> xH). + intro; subst. + compute in H; destruct p; discriminate. + assert (Zsucc (Zpos (Ppred d)) = Zpos d). + simpl; f_equal. + rewrite <- Pplus_one_succ_r. + destruct (Psucc_pred d); auto. + rewrite H1 in H0; elim H0; auto. + assert (Ptail p < Zpos (Ppred d)). + apply IHp. + apply Zmult_lt_reg_r with 2; auto with zarith. + rewrite (Zmult_comm (Zpos p)). + change (2 * Zpos p) with (Zpos p~0). + rewrite Zmult_comm. + rewrite <- Zpower_Zsucc; auto with zarith. + rewrite H1; auto. + rewrite <- H1; omega. + Qed. + + Definition znz_tail0 x := + match [|x|] with + | Z0 => znz_zdigits + | Zpos p => Ptail p + | Zneg _ => 0 + end. + + Lemma spec_tail00: forall x, [|x|] = 0 -> [|znz_tail0 x|] = Zpos znz_digits. + Proof. + unfold znz_tail0; intros. + rewrite H; simpl. + apply spec_zdigits. + Qed. + + Lemma spec_tail0 : forall x, 0 < [|x|] -> + exists y, 0 <= y /\ [|x|] = (2 * y + 1) * (2 ^ [|znz_tail0 x|]). + Proof. + intros; unfold znz_tail0. + generalize (spec_to_Z x). + destruct [|x|]; try discriminate; intros. + assert ([|Ptail p|] = Ptail p). + apply Zmod_small. + split; auto. + unfold wB, base in *. + apply Zlt_trans with (Zpos digits). + apply Ptail_bounded; auto with zarith. + apply Zpower2_lt_lin; auto with zarith. + rewrite H1. + + clear; induction p. + exists (Zpos p); simpl; rewrite Pmult_1_r; auto with zarith. + destruct IHp as (y & Yp & Ye). + exists y. + split; auto. + change (Zpos p~0) with (2*Zpos p). + rewrite Ye. + change (Ptail p~0) with (Zsucc (Ptail p)). + rewrite Zpower_Zsucc; auto; ring. + + exists 0; simpl; auto with zarith. + Qed. + + (** Let's now group everything in two records *) + + Definition zmod_op := mk_znz_op + (znz_digits : positive) + (znz_zdigits: znz) + (znz_to_Z : znz -> Z) + (znz_of_pos : positive -> N * znz) + (znz_head0 : znz -> znz) + (znz_tail0 : znz -> znz) + + (znz_0 : znz) + (znz_1 : znz) + (znz_Bm1 : znz) + + (znz_compare : znz -> znz -> comparison) + (znz_eq0 : znz -> bool) + + (znz_opp_c : znz -> carry znz) + (znz_opp : znz -> znz) + (znz_opp_carry : znz -> znz) + + (znz_succ_c : znz -> carry znz) + (znz_add_c : znz -> znz -> carry znz) + (znz_add_carry_c : znz -> znz -> carry znz) + (znz_succ : znz -> znz) + (znz_add : znz -> znz -> znz) + (znz_add_carry : znz -> znz -> znz) + + (znz_pred_c : znz -> carry znz) + (znz_sub_c : znz -> znz -> carry znz) + (znz_sub_carry_c : znz -> znz -> carry znz) + (znz_pred : znz -> znz) + (znz_sub : znz -> znz -> znz) + (znz_sub_carry : znz -> znz -> znz) + + (znz_mul_c : znz -> znz -> zn2z znz) + (znz_mul : znz -> znz -> znz) + (znz_square_c : znz -> zn2z znz) + + (znz_div21 : znz -> znz -> znz -> znz*znz) + (znz_div_gt : znz -> znz -> znz * znz) + (znz_div : znz -> znz -> znz * znz) + + (znz_mod_gt : znz -> znz -> znz) + (znz_mod : znz -> znz -> znz) + + (znz_gcd_gt : znz -> znz -> znz) + (znz_gcd : znz -> znz -> znz) + (znz_add_mul_div : znz -> znz -> znz -> znz) + (znz_pos_mod : znz -> znz -> znz) + + (znz_is_even : znz -> bool) + (znz_sqrt2 : znz -> znz -> znz * carry znz) + (znz_sqrt : znz -> znz). + + Definition zmod_spec := mk_znz_spec zmod_op + spec_to_Z + spec_of_pos + spec_zdigits + spec_more_than_1_digit + + spec_0 + spec_1 + spec_Bm1 + + spec_compare + spec_eq0 + + spec_opp_c + spec_opp + spec_opp_carry + + spec_succ_c + spec_add_c + spec_add_carry_c + spec_succ + spec_add + spec_add_carry + + spec_pred_c + spec_sub_c + spec_sub_carry_c + spec_pred + spec_sub + spec_sub_carry + + spec_mul_c + spec_mul + spec_square_c + + spec_div21 + spec_div_gt + spec_div + + spec_mod_gt + spec_mod + + spec_gcd_gt + spec_gcd + + spec_head00 + spec_head0 + spec_tail00 + spec_tail0 + + spec_add_mul_div + spec_pos_mod + + spec_is_even + spec_sqrt2 + spec_sqrt. + +End ZModulo. + +(** A modular version of the previous construction. *) + +Module Type PositiveNotOne. + Parameter p : positive. + Axiom not_one : p<> 1%positive. +End PositiveNotOne. + +Module ZModuloCyclicType (P:PositiveNotOne) <: CyclicType. + Definition w := Z. + Definition w_op := zmod_op P.p. + Definition w_spec := zmod_spec P.not_one. +End ZModuloCyclicType. + diff --git a/theories/Numbers/Integer/Abstract/ZAdd.v b/theories/Numbers/Integer/Abstract/ZAdd.v new file mode 100644 index 00000000..df941d90 --- /dev/null +++ b/theories/Numbers/Integer/Abstract/ZAdd.v @@ -0,0 +1,345 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: ZAdd.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export ZBase. + +Module ZAddPropFunct (Import ZAxiomsMod : ZAxiomsSig). +Module Export ZBasePropMod := ZBasePropFunct ZAxiomsMod. +Open Local Scope IntScope. + +Theorem Zadd_wd : + forall n1 n2 : Z, n1 == n2 -> forall m1 m2 : Z, m1 == m2 -> n1 + m1 == n2 + m2. +Proof NZadd_wd. + +Theorem Zadd_0_l : forall n : Z, 0 + n == n. +Proof NZadd_0_l. + +Theorem Zadd_succ_l : forall n m : Z, (S n) + m == S (n + m). +Proof NZadd_succ_l. + +Theorem Zsub_0_r : forall n : Z, n - 0 == n. +Proof NZsub_0_r. + +Theorem Zsub_succ_r : forall n m : Z, n - (S m) == P (n - m). +Proof NZsub_succ_r. + +Theorem Zopp_0 : - 0 == 0. +Proof Zopp_0. + +Theorem Zopp_succ : forall n : Z, - (S n) == P (- n). +Proof Zopp_succ. + +(* Theorems that are valid for both natural numbers and integers *) + +Theorem Zadd_0_r : forall n : Z, n + 0 == n. +Proof NZadd_0_r. + +Theorem Zadd_succ_r : forall n m : Z, n + S m == S (n + m). +Proof NZadd_succ_r. + +Theorem Zadd_comm : forall n m : Z, n + m == m + n. +Proof NZadd_comm. + +Theorem Zadd_assoc : forall n m p : Z, n + (m + p) == (n + m) + p. +Proof NZadd_assoc. + +Theorem Zadd_shuffle1 : forall n m p q : Z, (n + m) + (p + q) == (n + p) + (m + q). +Proof NZadd_shuffle1. + +Theorem Zadd_shuffle2 : forall n m p q : Z, (n + m) + (p + q) == (n + q) + (m + p). +Proof NZadd_shuffle2. + +Theorem Zadd_1_l : forall n : Z, 1 + n == S n. +Proof NZadd_1_l. + +Theorem Zadd_1_r : forall n : Z, n + 1 == S n. +Proof NZadd_1_r. + +Theorem Zadd_cancel_l : forall n m p : Z, p + n == p + m <-> n == m. +Proof NZadd_cancel_l. + +Theorem Zadd_cancel_r : forall n m p : Z, n + p == m + p <-> n == m. +Proof NZadd_cancel_r. + +(* Theorems that are either not valid on N or have different proofs on N and Z *) + +Theorem Zadd_pred_l : forall n m : Z, P n + m == P (n + m). +Proof. +intros n m. +rewrite <- (Zsucc_pred n) at 2. +rewrite Zadd_succ_l. now rewrite Zpred_succ. +Qed. + +Theorem Zadd_pred_r : forall n m : Z, n + P m == P (n + m). +Proof. +intros n m; rewrite (Zadd_comm n (P m)), (Zadd_comm n m); +apply Zadd_pred_l. +Qed. + +Theorem Zadd_opp_r : forall n m : Z, n + (- m) == n - m. +Proof. +NZinduct m. +rewrite Zopp_0; rewrite Zsub_0_r; now rewrite Zadd_0_r. +intro m. rewrite Zopp_succ, Zsub_succ_r, Zadd_pred_r; now rewrite Zpred_inj_wd. +Qed. + +Theorem Zsub_0_l : forall n : Z, 0 - n == - n. +Proof. +intro n; rewrite <- Zadd_opp_r; now rewrite Zadd_0_l. +Qed. + +Theorem Zsub_succ_l : forall n m : Z, S n - m == S (n - m). +Proof. +intros n m; do 2 rewrite <- Zadd_opp_r; now rewrite Zadd_succ_l. +Qed. + +Theorem Zsub_pred_l : forall n m : Z, P n - m == P (n - m). +Proof. +intros n m. rewrite <- (Zsucc_pred n) at 2. +rewrite Zsub_succ_l; now rewrite Zpred_succ. +Qed. + +Theorem Zsub_pred_r : forall n m : Z, n - (P m) == S (n - m). +Proof. +intros n m. rewrite <- (Zsucc_pred m) at 2. +rewrite Zsub_succ_r; now rewrite Zsucc_pred. +Qed. + +Theorem Zopp_pred : forall n : Z, - (P n) == S (- n). +Proof. +intro n. rewrite <- (Zsucc_pred n) at 2. +rewrite Zopp_succ. now rewrite Zsucc_pred. +Qed. + +Theorem Zsub_diag : forall n : Z, n - n == 0. +Proof. +NZinduct n. +now rewrite Zsub_0_r. +intro n. rewrite Zsub_succ_r, Zsub_succ_l; now rewrite Zpred_succ. +Qed. + +Theorem Zadd_opp_diag_l : forall n : Z, - n + n == 0. +Proof. +intro n; now rewrite Zadd_comm, Zadd_opp_r, Zsub_diag. +Qed. + +Theorem Zadd_opp_diag_r : forall n : Z, n + (- n) == 0. +Proof. +intro n; rewrite Zadd_comm; apply Zadd_opp_diag_l. +Qed. + +Theorem Zadd_opp_l : forall n m : Z, - m + n == n - m. +Proof. +intros n m; rewrite <- Zadd_opp_r; now rewrite Zadd_comm. +Qed. + +Theorem Zadd_sub_assoc : forall n m p : Z, n + (m - p) == (n + m) - p. +Proof. +intros n m p; do 2 rewrite <- Zadd_opp_r; now rewrite Zadd_assoc. +Qed. + +Theorem Zopp_involutive : forall n : Z, - (- n) == n. +Proof. +NZinduct n. +now do 2 rewrite Zopp_0. +intro n. rewrite Zopp_succ, Zopp_pred; now rewrite Zsucc_inj_wd. +Qed. + +Theorem Zopp_add_distr : forall n m : Z, - (n + m) == - n + (- m). +Proof. +intros n m; NZinduct n. +rewrite Zopp_0; now do 2 rewrite Zadd_0_l. +intro n. rewrite Zadd_succ_l; do 2 rewrite Zopp_succ; rewrite Zadd_pred_l. +now rewrite Zpred_inj_wd. +Qed. + +Theorem Zopp_sub_distr : forall n m : Z, - (n - m) == - n + m. +Proof. +intros n m; rewrite <- Zadd_opp_r, Zopp_add_distr. +now rewrite Zopp_involutive. +Qed. + +Theorem Zopp_inj : forall n m : Z, - n == - m -> n == m. +Proof. +intros n m H. apply Zopp_wd in H. now do 2 rewrite Zopp_involutive in H. +Qed. + +Theorem Zopp_inj_wd : forall n m : Z, - n == - m <-> n == m. +Proof. +intros n m; split; [apply Zopp_inj | apply Zopp_wd]. +Qed. + +Theorem Zeq_opp_l : forall n m : Z, - n == m <-> n == - m. +Proof. +intros n m. now rewrite <- (Zopp_inj_wd (- n) m), Zopp_involutive. +Qed. + +Theorem Zeq_opp_r : forall n m : Z, n == - m <-> - n == m. +Proof. +symmetry; apply Zeq_opp_l. +Qed. + +Theorem Zsub_add_distr : forall n m p : Z, n - (m + p) == (n - m) - p. +Proof. +intros n m p; rewrite <- Zadd_opp_r, Zopp_add_distr, Zadd_assoc. +now do 2 rewrite Zadd_opp_r. +Qed. + +Theorem Zsub_sub_distr : forall n m p : Z, n - (m - p) == (n - m) + p. +Proof. +intros n m p; rewrite <- Zadd_opp_r, Zopp_sub_distr, Zadd_assoc. +now rewrite Zadd_opp_r. +Qed. + +Theorem sub_opp_l : forall n m : Z, - n - m == - m - n. +Proof. +intros n m. do 2 rewrite <- Zadd_opp_r. now rewrite Zadd_comm. +Qed. + +Theorem Zsub_opp_r : forall n m : Z, n - (- m) == n + m. +Proof. +intros n m; rewrite <- Zadd_opp_r; now rewrite Zopp_involutive. +Qed. + +Theorem Zadd_sub_swap : forall n m p : Z, n + m - p == n - p + m. +Proof. +intros n m p. rewrite <- Zadd_sub_assoc, <- (Zadd_opp_r n p), <- Zadd_assoc. +now rewrite Zadd_opp_l. +Qed. + +Theorem Zsub_cancel_l : forall n m p : Z, n - m == n - p <-> m == p. +Proof. +intros n m p. rewrite <- (Zadd_cancel_l (n - m) (n - p) (- n)). +do 2 rewrite Zadd_sub_assoc. rewrite Zadd_opp_diag_l; do 2 rewrite Zsub_0_l. +apply Zopp_inj_wd. +Qed. + +Theorem Zsub_cancel_r : forall n m p : Z, n - p == m - p <-> n == m. +Proof. +intros n m p. +stepl (n - p + p == m - p + p) by apply Zadd_cancel_r. +now do 2 rewrite <- Zsub_sub_distr, Zsub_diag, Zsub_0_r. +Qed. + +(* The next several theorems are devoted to moving terms from one side of +an equation to the other. The name contains the operation in the original +equation (add or sub) and the indication whether the left or right term +is moved. *) + +Theorem Zadd_move_l : forall n m p : Z, n + m == p <-> m == p - n. +Proof. +intros n m p. +stepl (n + m - n == p - n) by apply Zsub_cancel_r. +now rewrite Zadd_comm, <- Zadd_sub_assoc, Zsub_diag, Zadd_0_r. +Qed. + +Theorem Zadd_move_r : forall n m p : Z, n + m == p <-> n == p - m. +Proof. +intros n m p; rewrite Zadd_comm; now apply Zadd_move_l. +Qed. + +(* The two theorems above do not allow rewriting subformulas of the form +n - m == p to n == p + m since subtraction is in the right-hand side of +the equation. Hence the following two theorems. *) + +Theorem Zsub_move_l : forall n m p : Z, n - m == p <-> - m == p - n. +Proof. +intros n m p; rewrite <- (Zadd_opp_r n m); apply Zadd_move_l. +Qed. + +Theorem Zsub_move_r : forall n m p : Z, n - m == p <-> n == p + m. +Proof. +intros n m p; rewrite <- (Zadd_opp_r n m). now rewrite Zadd_move_r, Zsub_opp_r. +Qed. + +Theorem Zadd_move_0_l : forall n m : Z, n + m == 0 <-> m == - n. +Proof. +intros n m; now rewrite Zadd_move_l, Zsub_0_l. +Qed. + +Theorem Zadd_move_0_r : forall n m : Z, n + m == 0 <-> n == - m. +Proof. +intros n m; now rewrite Zadd_move_r, Zsub_0_l. +Qed. + +Theorem Zsub_move_0_l : forall n m : Z, n - m == 0 <-> - m == - n. +Proof. +intros n m. now rewrite Zsub_move_l, Zsub_0_l. +Qed. + +Theorem Zsub_move_0_r : forall n m : Z, n - m == 0 <-> n == m. +Proof. +intros n m. now rewrite Zsub_move_r, Zadd_0_l. +Qed. + +(* The following section is devoted to cancellation of like terms. The name +includes the first operator and the position of the term being canceled. *) + +Theorem Zadd_simpl_l : forall n m : Z, n + m - n == m. +Proof. +intros; now rewrite Zadd_sub_swap, Zsub_diag, Zadd_0_l. +Qed. + +Theorem Zadd_simpl_r : forall n m : Z, n + m - m == n. +Proof. +intros; now rewrite <- Zadd_sub_assoc, Zsub_diag, Zadd_0_r. +Qed. + +Theorem Zsub_simpl_l : forall n m : Z, - n - m + n == - m. +Proof. +intros; now rewrite <- Zadd_sub_swap, Zadd_opp_diag_l, Zsub_0_l. +Qed. + +Theorem Zsub_simpl_r : forall n m : Z, n - m + m == n. +Proof. +intros; now rewrite <- Zsub_sub_distr, Zsub_diag, Zsub_0_r. +Qed. + +(* Now we have two sums or differences; the name includes the two operators +and the position of the terms being canceled *) + +Theorem Zadd_add_simpl_l_l : forall n m p : Z, (n + m) - (n + p) == m - p. +Proof. +intros n m p. now rewrite (Zadd_comm n m), <- Zadd_sub_assoc, +Zsub_add_distr, Zsub_diag, Zsub_0_l, Zadd_opp_r. +Qed. + +Theorem Zadd_add_simpl_l_r : forall n m p : Z, (n + m) - (p + n) == m - p. +Proof. +intros n m p. rewrite (Zadd_comm p n); apply Zadd_add_simpl_l_l. +Qed. + +Theorem Zadd_add_simpl_r_l : forall n m p : Z, (n + m) - (m + p) == n - p. +Proof. +intros n m p. rewrite (Zadd_comm n m); apply Zadd_add_simpl_l_l. +Qed. + +Theorem Zadd_add_simpl_r_r : forall n m p : Z, (n + m) - (p + m) == n - p. +Proof. +intros n m p. rewrite (Zadd_comm p m); apply Zadd_add_simpl_r_l. +Qed. + +Theorem Zsub_add_simpl_r_l : forall n m p : Z, (n - m) + (m + p) == n + p. +Proof. +intros n m p. now rewrite <- Zsub_sub_distr, Zsub_add_distr, Zsub_diag, +Zsub_0_l, Zsub_opp_r. +Qed. + +Theorem Zsub_add_simpl_r_r : forall n m p : Z, (n - m) + (p + m) == n + p. +Proof. +intros n m p. rewrite (Zadd_comm p m); apply Zsub_add_simpl_r_l. +Qed. + +(* Of course, there are many other variants *) + +End ZAddPropFunct. + diff --git a/theories/Numbers/Integer/Abstract/ZAddOrder.v b/theories/Numbers/Integer/Abstract/ZAddOrder.v new file mode 100644 index 00000000..101ea634 --- /dev/null +++ b/theories/Numbers/Integer/Abstract/ZAddOrder.v @@ -0,0 +1,373 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: ZAddOrder.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export ZLt. + +Module ZAddOrderPropFunct (Import ZAxiomsMod : ZAxiomsSig). +Module Export ZOrderPropMod := ZOrderPropFunct ZAxiomsMod. +Open Local Scope IntScope. + +(* Theorems that are true on both natural numbers and integers *) + +Theorem Zadd_lt_mono_l : forall n m p : Z, n < m <-> p + n < p + m. +Proof NZadd_lt_mono_l. + +Theorem Zadd_lt_mono_r : forall n m p : Z, n < m <-> n + p < m + p. +Proof NZadd_lt_mono_r. + +Theorem Zadd_lt_mono : forall n m p q : Z, n < m -> p < q -> n + p < m + q. +Proof NZadd_lt_mono. + +Theorem Zadd_le_mono_l : forall n m p : Z, n <= m <-> p + n <= p + m. +Proof NZadd_le_mono_l. + +Theorem Zadd_le_mono_r : forall n m p : Z, n <= m <-> n + p <= m + p. +Proof NZadd_le_mono_r. + +Theorem Zadd_le_mono : forall n m p q : Z, n <= m -> p <= q -> n + p <= m + q. +Proof NZadd_le_mono. + +Theorem Zadd_lt_le_mono : forall n m p q : Z, n < m -> p <= q -> n + p < m + q. +Proof NZadd_lt_le_mono. + +Theorem Zadd_le_lt_mono : forall n m p q : Z, n <= m -> p < q -> n + p < m + q. +Proof NZadd_le_lt_mono. + +Theorem Zadd_pos_pos : forall n m : Z, 0 < n -> 0 < m -> 0 < n + m. +Proof NZadd_pos_pos. + +Theorem Zadd_pos_nonneg : forall n m : Z, 0 < n -> 0 <= m -> 0 < n + m. +Proof NZadd_pos_nonneg. + +Theorem Zadd_nonneg_pos : forall n m : Z, 0 <= n -> 0 < m -> 0 < n + m. +Proof NZadd_nonneg_pos. + +Theorem Zadd_nonneg_nonneg : forall n m : Z, 0 <= n -> 0 <= m -> 0 <= n + m. +Proof NZadd_nonneg_nonneg. + +Theorem Zlt_add_pos_l : forall n m : Z, 0 < n -> m < n + m. +Proof NZlt_add_pos_l. + +Theorem Zlt_add_pos_r : forall n m : Z, 0 < n -> m < m + n. +Proof NZlt_add_pos_r. + +Theorem Zle_lt_add_lt : forall n m p q : Z, n <= m -> p + m < q + n -> p < q. +Proof NZle_lt_add_lt. + +Theorem Zlt_le_add_lt : forall n m p q : Z, n < m -> p + m <= q + n -> p < q. +Proof NZlt_le_add_lt. + +Theorem Zle_le_add_le : forall n m p q : Z, n <= m -> p + m <= q + n -> p <= q. +Proof NZle_le_add_le. + +Theorem Zadd_lt_cases : forall n m p q : Z, n + m < p + q -> n < p \/ m < q. +Proof NZadd_lt_cases. + +Theorem Zadd_le_cases : forall n m p q : Z, n + m <= p + q -> n <= p \/ m <= q. +Proof NZadd_le_cases. + +Theorem Zadd_neg_cases : forall n m : Z, n + m < 0 -> n < 0 \/ m < 0. +Proof NZadd_neg_cases. + +Theorem Zadd_pos_cases : forall n m : Z, 0 < n + m -> 0 < n \/ 0 < m. +Proof NZadd_pos_cases. + +Theorem Zadd_nonpos_cases : forall n m : Z, n + m <= 0 -> n <= 0 \/ m <= 0. +Proof NZadd_nonpos_cases. + +Theorem Zadd_nonneg_cases : forall n m : Z, 0 <= n + m -> 0 <= n \/ 0 <= m. +Proof NZadd_nonneg_cases. + +(* Theorems that are either not valid on N or have different proofs on N and Z *) + +Theorem Zadd_neg_neg : forall n m : Z, n < 0 -> m < 0 -> n + m < 0. +Proof. +intros n m H1 H2. rewrite <- (Zadd_0_l 0). now apply Zadd_lt_mono. +Qed. + +Theorem Zadd_neg_nonpos : forall n m : Z, n < 0 -> m <= 0 -> n + m < 0. +Proof. +intros n m H1 H2. rewrite <- (Zadd_0_l 0). now apply Zadd_lt_le_mono. +Qed. + +Theorem Zadd_nonpos_neg : forall n m : Z, n <= 0 -> m < 0 -> n + m < 0. +Proof. +intros n m H1 H2. rewrite <- (Zadd_0_l 0). now apply Zadd_le_lt_mono. +Qed. + +Theorem Zadd_nonpos_nonpos : forall n m : Z, n <= 0 -> m <= 0 -> n + m <= 0. +Proof. +intros n m H1 H2. rewrite <- (Zadd_0_l 0). now apply Zadd_le_mono. +Qed. + +(** Sub and order *) + +Theorem Zlt_0_sub : forall n m : Z, 0 < m - n <-> n < m. +Proof. +intros n m. stepl (0 + n < m - n + n) by symmetry; apply Zadd_lt_mono_r. +rewrite Zadd_0_l; now rewrite Zsub_simpl_r. +Qed. + +Notation Zsub_pos := Zlt_0_sub (only parsing). + +Theorem Zle_0_sub : forall n m : Z, 0 <= m - n <-> n <= m. +Proof. +intros n m; stepl (0 + n <= m - n + n) by symmetry; apply Zadd_le_mono_r. +rewrite Zadd_0_l; now rewrite Zsub_simpl_r. +Qed. + +Notation Zsub_nonneg := Zle_0_sub (only parsing). + +Theorem Zlt_sub_0 : forall n m : Z, n - m < 0 <-> n < m. +Proof. +intros n m. stepl (n - m + m < 0 + m) by symmetry; apply Zadd_lt_mono_r. +rewrite Zadd_0_l; now rewrite Zsub_simpl_r. +Qed. + +Notation Zsub_neg := Zlt_sub_0 (only parsing). + +Theorem Zle_sub_0 : forall n m : Z, n - m <= 0 <-> n <= m. +Proof. +intros n m. stepl (n - m + m <= 0 + m) by symmetry; apply Zadd_le_mono_r. +rewrite Zadd_0_l; now rewrite Zsub_simpl_r. +Qed. + +Notation Zsub_nonpos := Zle_sub_0 (only parsing). + +Theorem Zopp_lt_mono : forall n m : Z, n < m <-> - m < - n. +Proof. +intros n m. stepr (m + - m < m + - n) by symmetry; apply Zadd_lt_mono_l. +do 2 rewrite Zadd_opp_r. rewrite Zsub_diag. symmetry; apply Zlt_0_sub. +Qed. + +Theorem Zopp_le_mono : forall n m : Z, n <= m <-> - m <= - n. +Proof. +intros n m. stepr (m + - m <= m + - n) by symmetry; apply Zadd_le_mono_l. +do 2 rewrite Zadd_opp_r. rewrite Zsub_diag. symmetry; apply Zle_0_sub. +Qed. + +Theorem Zopp_pos_neg : forall n : Z, 0 < - n <-> n < 0. +Proof. +intro n; rewrite (Zopp_lt_mono n 0); now rewrite Zopp_0. +Qed. + +Theorem Zopp_neg_pos : forall n : Z, - n < 0 <-> 0 < n. +Proof. +intro n. rewrite (Zopp_lt_mono 0 n). now rewrite Zopp_0. +Qed. + +Theorem Zopp_nonneg_nonpos : forall n : Z, 0 <= - n <-> n <= 0. +Proof. +intro n; rewrite (Zopp_le_mono n 0); now rewrite Zopp_0. +Qed. + +Theorem Zopp_nonpos_nonneg : forall n : Z, - n <= 0 <-> 0 <= n. +Proof. +intro n. rewrite (Zopp_le_mono 0 n). now rewrite Zopp_0. +Qed. + +Theorem Zsub_lt_mono_l : forall n m p : Z, n < m <-> p - m < p - n. +Proof. +intros n m p. do 2 rewrite <- Zadd_opp_r. rewrite <- Zadd_lt_mono_l. +apply Zopp_lt_mono. +Qed. + +Theorem Zsub_lt_mono_r : forall n m p : Z, n < m <-> n - p < m - p. +Proof. +intros n m p; do 2 rewrite <- Zadd_opp_r; apply Zadd_lt_mono_r. +Qed. + +Theorem Zsub_lt_mono : forall n m p q : Z, n < m -> q < p -> n - p < m - q. +Proof. +intros n m p q H1 H2. +apply NZlt_trans with (m - p); +[now apply -> Zsub_lt_mono_r | now apply -> Zsub_lt_mono_l]. +Qed. + +Theorem Zsub_le_mono_l : forall n m p : Z, n <= m <-> p - m <= p - n. +Proof. +intros n m p; do 2 rewrite <- Zadd_opp_r; rewrite <- Zadd_le_mono_l; +apply Zopp_le_mono. +Qed. + +Theorem Zsub_le_mono_r : forall n m p : Z, n <= m <-> n - p <= m - p. +Proof. +intros n m p; do 2 rewrite <- Zadd_opp_r; apply Zadd_le_mono_r. +Qed. + +Theorem Zsub_le_mono : forall n m p q : Z, n <= m -> q <= p -> n - p <= m - q. +Proof. +intros n m p q H1 H2. +apply NZle_trans with (m - p); +[now apply -> Zsub_le_mono_r | now apply -> Zsub_le_mono_l]. +Qed. + +Theorem Zsub_lt_le_mono : forall n m p q : Z, n < m -> q <= p -> n - p < m - q. +Proof. +intros n m p q H1 H2. +apply NZlt_le_trans with (m - p); +[now apply -> Zsub_lt_mono_r | now apply -> Zsub_le_mono_l]. +Qed. + +Theorem Zsub_le_lt_mono : forall n m p q : Z, n <= m -> q < p -> n - p < m - q. +Proof. +intros n m p q H1 H2. +apply NZle_lt_trans with (m - p); +[now apply -> Zsub_le_mono_r | now apply -> Zsub_lt_mono_l]. +Qed. + +Theorem Zle_lt_sub_lt : forall n m p q : Z, n <= m -> p - n < q - m -> p < q. +Proof. +intros n m p q H1 H2. apply (Zle_lt_add_lt (- m) (- n)); +[now apply -> Zopp_le_mono | now do 2 rewrite Zadd_opp_r]. +Qed. + +Theorem Zlt_le_sub_lt : forall n m p q : Z, n < m -> p - n <= q - m -> p < q. +Proof. +intros n m p q H1 H2. apply (Zlt_le_add_lt (- m) (- n)); +[now apply -> Zopp_lt_mono | now do 2 rewrite Zadd_opp_r]. +Qed. + +Theorem Zle_le_sub_lt : forall n m p q : Z, n <= m -> p - n <= q - m -> p <= q. +Proof. +intros n m p q H1 H2. apply (Zle_le_add_le (- m) (- n)); +[now apply -> Zopp_le_mono | now do 2 rewrite Zadd_opp_r]. +Qed. + +Theorem Zlt_add_lt_sub_r : forall n m p : Z, n + p < m <-> n < m - p. +Proof. +intros n m p. stepl (n + p - p < m - p) by symmetry; apply Zsub_lt_mono_r. +now rewrite Zadd_simpl_r. +Qed. + +Theorem Zle_add_le_sub_r : forall n m p : Z, n + p <= m <-> n <= m - p. +Proof. +intros n m p. stepl (n + p - p <= m - p) by symmetry; apply Zsub_le_mono_r. +now rewrite Zadd_simpl_r. +Qed. + +Theorem Zlt_add_lt_sub_l : forall n m p : Z, n + p < m <-> p < m - n. +Proof. +intros n m p. rewrite Zadd_comm; apply Zlt_add_lt_sub_r. +Qed. + +Theorem Zle_add_le_sub_l : forall n m p : Z, n + p <= m <-> p <= m - n. +Proof. +intros n m p. rewrite Zadd_comm; apply Zle_add_le_sub_r. +Qed. + +Theorem Zlt_sub_lt_add_r : forall n m p : Z, n - p < m <-> n < m + p. +Proof. +intros n m p. stepl (n - p + p < m + p) by symmetry; apply Zadd_lt_mono_r. +now rewrite Zsub_simpl_r. +Qed. + +Theorem Zle_sub_le_add_r : forall n m p : Z, n - p <= m <-> n <= m + p. +Proof. +intros n m p. stepl (n - p + p <= m + p) by symmetry; apply Zadd_le_mono_r. +now rewrite Zsub_simpl_r. +Qed. + +Theorem Zlt_sub_lt_add_l : forall n m p : Z, n - m < p <-> n < m + p. +Proof. +intros n m p. rewrite Zadd_comm; apply Zlt_sub_lt_add_r. +Qed. + +Theorem Zle_sub_le_add_l : forall n m p : Z, n - m <= p <-> n <= m + p. +Proof. +intros n m p. rewrite Zadd_comm; apply Zle_sub_le_add_r. +Qed. + +Theorem Zlt_sub_lt_add : forall n m p q : Z, n - m < p - q <-> n + q < m + p. +Proof. +intros n m p q. rewrite Zlt_sub_lt_add_l. rewrite Zadd_sub_assoc. +now rewrite <- Zlt_add_lt_sub_r. +Qed. + +Theorem Zle_sub_le_add : forall n m p q : Z, n - m <= p - q <-> n + q <= m + p. +Proof. +intros n m p q. rewrite Zle_sub_le_add_l. rewrite Zadd_sub_assoc. +now rewrite <- Zle_add_le_sub_r. +Qed. + +Theorem Zlt_sub_pos : forall n m : Z, 0 < m <-> n - m < n. +Proof. +intros n m. stepr (n - m < n - 0) by now rewrite Zsub_0_r. apply Zsub_lt_mono_l. +Qed. + +Theorem Zle_sub_nonneg : forall n m : Z, 0 <= m <-> n - m <= n. +Proof. +intros n m. stepr (n - m <= n - 0) by now rewrite Zsub_0_r. apply Zsub_le_mono_l. +Qed. + +Theorem Zsub_lt_cases : forall n m p q : Z, n - m < p - q -> n < m \/ q < p. +Proof. +intros n m p q H. rewrite Zlt_sub_lt_add in H. now apply Zadd_lt_cases. +Qed. + +Theorem Zsub_le_cases : forall n m p q : Z, n - m <= p - q -> n <= m \/ q <= p. +Proof. +intros n m p q H. rewrite Zle_sub_le_add in H. now apply Zadd_le_cases. +Qed. + +Theorem Zsub_neg_cases : forall n m : Z, n - m < 0 -> n < 0 \/ 0 < m. +Proof. +intros n m H; rewrite <- Zadd_opp_r in H. +setoid_replace (0 < m) with (- m < 0) using relation iff by (symmetry; apply Zopp_neg_pos). +now apply Zadd_neg_cases. +Qed. + +Theorem Zsub_pos_cases : forall n m : Z, 0 < n - m -> 0 < n \/ m < 0. +Proof. +intros n m H; rewrite <- Zadd_opp_r in H. +setoid_replace (m < 0) with (0 < - m) using relation iff by (symmetry; apply Zopp_pos_neg). +now apply Zadd_pos_cases. +Qed. + +Theorem Zsub_nonpos_cases : forall n m : Z, n - m <= 0 -> n <= 0 \/ 0 <= m. +Proof. +intros n m H; rewrite <- Zadd_opp_r in H. +setoid_replace (0 <= m) with (- m <= 0) using relation iff by (symmetry; apply Zopp_nonpos_nonneg). +now apply Zadd_nonpos_cases. +Qed. + +Theorem Zsub_nonneg_cases : forall n m : Z, 0 <= n - m -> 0 <= n \/ m <= 0. +Proof. +intros n m H; rewrite <- Zadd_opp_r in H. +setoid_replace (m <= 0) with (0 <= - m) using relation iff by (symmetry; apply Zopp_nonneg_nonpos). +now apply Zadd_nonneg_cases. +Qed. + +Section PosNeg. + +Variable P : Z -> Prop. +Hypothesis P_wd : predicate_wd Zeq P. + +Add Morphism P with signature Zeq ==> iff as P_morph. Proof. exact P_wd. Qed. + +Theorem Z0_pos_neg : + P 0 -> (forall n : Z, 0 < n -> P n /\ P (- n)) -> forall n : Z, P n. +Proof. +intros H1 H2 n. destruct (Zlt_trichotomy n 0) as [H3 | [H3 | H3]]. +apply <- Zopp_pos_neg in H3. apply H2 in H3. destruct H3 as [_ H3]. +now rewrite Zopp_involutive in H3. +now rewrite H3. +apply H2 in H3; now destruct H3. +Qed. + +End PosNeg. + +Ltac Z0_pos_neg n := induction_maker n ltac:(apply Z0_pos_neg). + +End ZAddOrderPropFunct. + + diff --git a/theories/Numbers/Integer/Abstract/ZAxioms.v b/theories/Numbers/Integer/Abstract/ZAxioms.v new file mode 100644 index 00000000..c4a4b6b8 --- /dev/null +++ b/theories/Numbers/Integer/Abstract/ZAxioms.v @@ -0,0 +1,65 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: ZAxioms.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export NZAxioms. + +Set Implicit Arguments. + +Module Type ZAxiomsSig. +Declare Module Export NZOrdAxiomsMod : NZOrdAxiomsSig. + +Delimit Scope IntScope with Int. +Notation Z := NZ. +Notation Zeq := NZeq. +Notation Z0 := NZ0. +Notation Z1 := (NZsucc NZ0). +Notation S := NZsucc. +Notation P := NZpred. +Notation Zadd := NZadd. +Notation Zmul := NZmul. +Notation Zsub := NZsub. +Notation Zlt := NZlt. +Notation Zle := NZle. +Notation Zmin := NZmin. +Notation Zmax := NZmax. +Notation "x == y" := (NZeq x y) (at level 70) : IntScope. +Notation "x ~= y" := (~ NZeq x y) (at level 70) : IntScope. +Notation "0" := NZ0 : IntScope. +Notation "1" := (NZsucc NZ0) : IntScope. +Notation "x + y" := (NZadd x y) : IntScope. +Notation "x - y" := (NZsub x y) : IntScope. +Notation "x * y" := (NZmul x y) : IntScope. +Notation "x < y" := (NZlt x y) : IntScope. +Notation "x <= y" := (NZle x y) : IntScope. +Notation "x > y" := (NZlt y x) (only parsing) : IntScope. +Notation "x >= y" := (NZle y x) (only parsing) : IntScope. + +Parameter Zopp : Z -> Z. + +(*Notation "- 1" := (Zopp 1) : IntScope. +Check (-1).*) + +Add Morphism Zopp with signature Zeq ==> Zeq as Zopp_wd. + +Notation "- x" := (Zopp x) (at level 35, right associativity) : IntScope. +Notation "- 1" := (Zopp (NZsucc NZ0)) : IntScope. + +Open Local Scope IntScope. + +(* Integers are obtained by postulating that every number has a predecessor *) +Axiom Zsucc_pred : forall n : Z, S (P n) == n. + +Axiom Zopp_0 : - 0 == 0. +Axiom Zopp_succ : forall n : Z, - (S n) == P (- n). + +End ZAxiomsSig. + diff --git a/theories/Numbers/Integer/Abstract/ZBase.v b/theories/Numbers/Integer/Abstract/ZBase.v new file mode 100644 index 00000000..29e18548 --- /dev/null +++ b/theories/Numbers/Integer/Abstract/ZBase.v @@ -0,0 +1,86 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: ZBase.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export Decidable. +Require Export ZAxioms. +Require Import NZMulOrder. + +Module ZBasePropFunct (Import ZAxiomsMod : ZAxiomsSig). + +(* Note: writing "Export" instead of "Import" on the previous line leads to +some warnings about hiding repeated declarations and results in the loss of +notations in Zadd and later *) + +Open Local Scope IntScope. + +Module Export NZMulOrderMod := NZMulOrderPropFunct NZOrdAxiomsMod. + +Theorem Zsucc_wd : forall n1 n2 : Z, n1 == n2 -> S n1 == S n2. +Proof NZsucc_wd. + +Theorem Zpred_wd : forall n1 n2 : Z, n1 == n2 -> P n1 == P n2. +Proof NZpred_wd. + +Theorem Zpred_succ : forall n : Z, P (S n) == n. +Proof NZpred_succ. + +Theorem Zeq_refl : forall n : Z, n == n. +Proof (proj1 NZeq_equiv). + +Theorem Zeq_symm : forall n m : Z, n == m -> m == n. +Proof (proj2 (proj2 NZeq_equiv)). + +Theorem Zeq_trans : forall n m p : Z, n == m -> m == p -> n == p. +Proof (proj1 (proj2 NZeq_equiv)). + +Theorem Zneq_symm : forall n m : Z, n ~= m -> m ~= n. +Proof NZneq_symm. + +Theorem Zsucc_inj : forall n1 n2 : Z, S n1 == S n2 -> n1 == n2. +Proof NZsucc_inj. + +Theorem Zsucc_inj_wd : forall n1 n2 : Z, S n1 == S n2 <-> n1 == n2. +Proof NZsucc_inj_wd. + +Theorem Zsucc_inj_wd_neg : forall n m : Z, S n ~= S m <-> n ~= m. +Proof NZsucc_inj_wd_neg. + +(* Decidability and stability of equality was proved only in NZOrder, but +since it does not mention order, we'll put it here *) + +Theorem Zeq_dec : forall n m : Z, decidable (n == m). +Proof NZeq_dec. + +Theorem Zeq_dne : forall n m : Z, ~ ~ n == m <-> n == m. +Proof NZeq_dne. + +Theorem Zcentral_induction : +forall A : Z -> Prop, predicate_wd Zeq A -> + forall z : Z, A z -> + (forall n : Z, A n <-> A (S n)) -> + forall n : Z, A n. +Proof NZcentral_induction. + +(* Theorems that are true for integers but not for natural numbers *) + +Theorem Zpred_inj : forall n m : Z, P n == P m -> n == m. +Proof. +intros n m H. apply NZsucc_wd in H. now do 2 rewrite Zsucc_pred in H. +Qed. + +Theorem Zpred_inj_wd : forall n1 n2 : Z, P n1 == P n2 <-> n1 == n2. +Proof. +intros n1 n2; split; [apply Zpred_inj | apply NZpred_wd]. +Qed. + +End ZBasePropFunct. + diff --git a/theories/Numbers/Integer/Abstract/ZDomain.v b/theories/Numbers/Integer/Abstract/ZDomain.v new file mode 100644 index 00000000..15beb2b9 --- /dev/null +++ b/theories/Numbers/Integer/Abstract/ZDomain.v @@ -0,0 +1,69 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: ZDomain.v 10934 2008-05-15 21:58:20Z letouzey $ i*) + +Require Export NumPrelude. + +Module Type ZDomainSignature. + +Parameter Inline Z : Set. +Parameter Inline Zeq : Z -> Z -> Prop. +Parameter Inline e : Z -> Z -> bool. + +Axiom eq_equiv_e : forall x y : Z, Zeq x y <-> e x y. +Axiom eq_equiv : equiv Z Zeq. + +Add Relation Z Zeq + reflexivity proved by (proj1 eq_equiv) + symmetry proved by (proj2 (proj2 eq_equiv)) + transitivity proved by (proj1 (proj2 eq_equiv)) +as eq_rel. + +Delimit Scope IntScope with Int. +Bind Scope IntScope with Z. +Notation "x == y" := (Zeq x y) (at level 70) : IntScope. +Notation "x # y" := (~ Zeq x y) (at level 70) : IntScope. + +End ZDomainSignature. + +Module ZDomainProperties (Import ZDomainModule : ZDomainSignature). +Open Local Scope IntScope. + +Add Morphism e with signature Zeq ==> Zeq ==> eq_bool as e_wd. +Proof. +intros x x' Exx' y y' Eyy'. +case_eq (e x y); case_eq (e x' y'); intros H1 H2; trivial. +assert (x == y); [apply <- eq_equiv_e; now rewrite H2 | +assert (x' == y'); [rewrite <- Exx'; now rewrite <- Eyy' | +rewrite <- H1; assert (H3 : e x' y'); [now apply -> eq_equiv_e | now inversion H3]]]. +assert (x' == y'); [apply <- eq_equiv_e; now rewrite H1 | +assert (x == y); [rewrite Exx'; now rewrite Eyy' | +rewrite <- H2; assert (H3 : e x y); [now apply -> eq_equiv_e | now inversion H3]]]. +Qed. + +Theorem neq_symm : forall n m, n # m -> m # n. +Proof. +intros n m H1 H2; symmetry in H2; false_hyp H2 H1. +Qed. + +Theorem ZE_stepl : forall x y z : Z, x == y -> x == z -> z == y. +Proof. +intros x y z H1 H2; now rewrite <- H1. +Qed. + +Declare Left Step ZE_stepl. + +(* The right step lemma is just transitivity of Zeq *) +Declare Right Step (proj1 (proj2 eq_equiv)). + +End ZDomainProperties. + + diff --git a/theories/Numbers/Integer/Abstract/ZLt.v b/theories/Numbers/Integer/Abstract/ZLt.v new file mode 100644 index 00000000..2a88a535 --- /dev/null +++ b/theories/Numbers/Integer/Abstract/ZLt.v @@ -0,0 +1,432 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: ZLt.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export ZMul. + +Module ZOrderPropFunct (Import ZAxiomsMod : ZAxiomsSig). +Module Export ZMulPropMod := ZMulPropFunct ZAxiomsMod. +Open Local Scope IntScope. + +(* Axioms *) + +Theorem Zlt_wd : + forall n1 n2 : Z, n1 == n2 -> forall m1 m2 : Z, m1 == m2 -> (n1 < m1 <-> n2 < m2). +Proof NZlt_wd. + +Theorem Zle_wd : + forall n1 n2 : Z, n1 == n2 -> forall m1 m2 : Z, m1 == m2 -> (n1 <= m1 <-> n2 <= m2). +Proof NZle_wd. + +Theorem Zmin_wd : + forall n1 n2 : Z, n1 == n2 -> forall m1 m2 : Z, m1 == m2 -> Zmin n1 m1 == Zmin n2 m2. +Proof NZmin_wd. + +Theorem Zmax_wd : + forall n1 n2 : Z, n1 == n2 -> forall m1 m2 : Z, m1 == m2 -> Zmax n1 m1 == Zmax n2 m2. +Proof NZmax_wd. + +Theorem Zlt_eq_cases : forall n m : Z, n <= m <-> n < m \/ n == m. +Proof NZlt_eq_cases. + +Theorem Zlt_irrefl : forall n : Z, ~ n < n. +Proof NZlt_irrefl. + +Theorem Zlt_succ_r : forall n m : Z, n < S m <-> n <= m. +Proof NZlt_succ_r. + +Theorem Zmin_l : forall n m : Z, n <= m -> Zmin n m == n. +Proof NZmin_l. + +Theorem Zmin_r : forall n m : Z, m <= n -> Zmin n m == m. +Proof NZmin_r. + +Theorem Zmax_l : forall n m : Z, m <= n -> Zmax n m == n. +Proof NZmax_l. + +Theorem Zmax_r : forall n m : Z, n <= m -> Zmax n m == m. +Proof NZmax_r. + +(* Renaming theorems from NZOrder.v *) + +Theorem Zlt_le_incl : forall n m : Z, n < m -> n <= m. +Proof NZlt_le_incl. + +Theorem Zlt_neq : forall n m : Z, n < m -> n ~= m. +Proof NZlt_neq. + +Theorem Zle_neq : forall n m : Z, n < m <-> n <= m /\ n ~= m. +Proof NZle_neq. + +Theorem Zle_refl : forall n : Z, n <= n. +Proof NZle_refl. + +Theorem Zlt_succ_diag_r : forall n : Z, n < S n. +Proof NZlt_succ_diag_r. + +Theorem Zle_succ_diag_r : forall n : Z, n <= S n. +Proof NZle_succ_diag_r. + +Theorem Zlt_0_1 : 0 < 1. +Proof NZlt_0_1. + +Theorem Zle_0_1 : 0 <= 1. +Proof NZle_0_1. + +Theorem Zlt_lt_succ_r : forall n m : Z, n < m -> n < S m. +Proof NZlt_lt_succ_r. + +Theorem Zle_le_succ_r : forall n m : Z, n <= m -> n <= S m. +Proof NZle_le_succ_r. + +Theorem Zle_succ_r : forall n m : Z, n <= S m <-> n <= m \/ n == S m. +Proof NZle_succ_r. + +Theorem Zneq_succ_diag_l : forall n : Z, S n ~= n. +Proof NZneq_succ_diag_l. + +Theorem Zneq_succ_diag_r : forall n : Z, n ~= S n. +Proof NZneq_succ_diag_r. + +Theorem Znlt_succ_diag_l : forall n : Z, ~ S n < n. +Proof NZnlt_succ_diag_l. + +Theorem Znle_succ_diag_l : forall n : Z, ~ S n <= n. +Proof NZnle_succ_diag_l. + +Theorem Zle_succ_l : forall n m : Z, S n <= m <-> n < m. +Proof NZle_succ_l. + +Theorem Zlt_succ_l : forall n m : Z, S n < m -> n < m. +Proof NZlt_succ_l. + +Theorem Zsucc_lt_mono : forall n m : Z, n < m <-> S n < S m. +Proof NZsucc_lt_mono. + +Theorem Zsucc_le_mono : forall n m : Z, n <= m <-> S n <= S m. +Proof NZsucc_le_mono. + +Theorem Zlt_asymm : forall n m, n < m -> ~ m < n. +Proof NZlt_asymm. + +Notation Zlt_ngt := Zlt_asymm (only parsing). + +Theorem Zlt_trans : forall n m p : Z, n < m -> m < p -> n < p. +Proof NZlt_trans. + +Theorem Zle_trans : forall n m p : Z, n <= m -> m <= p -> n <= p. +Proof NZle_trans. + +Theorem Zle_lt_trans : forall n m p : Z, n <= m -> m < p -> n < p. +Proof NZle_lt_trans. + +Theorem Zlt_le_trans : forall n m p : Z, n < m -> m <= p -> n < p. +Proof NZlt_le_trans. + +Theorem Zle_antisymm : forall n m : Z, n <= m -> m <= n -> n == m. +Proof NZle_antisymm. + +Theorem Zlt_1_l : forall n m : Z, 0 < n -> n < m -> 1 < m. +Proof NZlt_1_l. + +(** Trichotomy, decidability, and double negation elimination *) + +Theorem Zlt_trichotomy : forall n m : Z, n < m \/ n == m \/ m < n. +Proof NZlt_trichotomy. + +Notation Zlt_eq_gt_cases := Zlt_trichotomy (only parsing). + +Theorem Zlt_gt_cases : forall n m : Z, n ~= m <-> n < m \/ n > m. +Proof NZlt_gt_cases. + +Theorem Zle_gt_cases : forall n m : Z, n <= m \/ n > m. +Proof NZle_gt_cases. + +Theorem Zlt_ge_cases : forall n m : Z, n < m \/ n >= m. +Proof NZlt_ge_cases. + +Theorem Zle_ge_cases : forall n m : Z, n <= m \/ n >= m. +Proof NZle_ge_cases. + +(** Instances of the previous theorems for m == 0 *) + +Theorem Zneg_pos_cases : forall n : Z, n ~= 0 <-> n < 0 \/ n > 0. +Proof. +intro; apply Zlt_gt_cases. +Qed. + +Theorem Znonpos_pos_cases : forall n : Z, n <= 0 \/ n > 0. +Proof. +intro; apply Zle_gt_cases. +Qed. + +Theorem Zneg_nonneg_cases : forall n : Z, n < 0 \/ n >= 0. +Proof. +intro; apply Zlt_ge_cases. +Qed. + +Theorem Znonpos_nonneg_cases : forall n : Z, n <= 0 \/ n >= 0. +Proof. +intro; apply Zle_ge_cases. +Qed. + +Theorem Zle_ngt : forall n m : Z, n <= m <-> ~ n > m. +Proof NZle_ngt. + +Theorem Znlt_ge : forall n m : Z, ~ n < m <-> n >= m. +Proof NZnlt_ge. + +Theorem Zlt_dec : forall n m : Z, decidable (n < m). +Proof NZlt_dec. + +Theorem Zlt_dne : forall n m, ~ ~ n < m <-> n < m. +Proof NZlt_dne. + +Theorem Znle_gt : forall n m : Z, ~ n <= m <-> n > m. +Proof NZnle_gt. + +Theorem Zlt_nge : forall n m : Z, n < m <-> ~ n >= m. +Proof NZlt_nge. + +Theorem Zle_dec : forall n m : Z, decidable (n <= m). +Proof NZle_dec. + +Theorem Zle_dne : forall n m : Z, ~ ~ n <= m <-> n <= m. +Proof NZle_dne. + +Theorem Znlt_succ_r : forall n m : Z, ~ m < S n <-> n < m. +Proof NZnlt_succ_r. + +Theorem Zlt_exists_pred : + forall z n : Z, z < n -> exists k : Z, n == S k /\ z <= k. +Proof NZlt_exists_pred. + +Theorem Zlt_succ_iter_r : + forall (n : nat) (m : Z), m < NZsucc_iter (Datatypes.S n) m. +Proof NZlt_succ_iter_r. + +Theorem Zneq_succ_iter_l : + forall (n : nat) (m : Z), NZsucc_iter (Datatypes.S n) m ~= m. +Proof NZneq_succ_iter_l. + +(** Stronger variant of induction with assumptions n >= 0 (n < 0) +in the induction step *) + +Theorem Zright_induction : + forall A : Z -> Prop, predicate_wd Zeq A -> + forall z : Z, A z -> + (forall n : Z, z <= n -> A n -> A (S n)) -> + forall n : Z, z <= n -> A n. +Proof NZright_induction. + +Theorem Zleft_induction : + forall A : Z -> Prop, predicate_wd Zeq A -> + forall z : Z, A z -> + (forall n : Z, n < z -> A (S n) -> A n) -> + forall n : Z, n <= z -> A n. +Proof NZleft_induction. + +Theorem Zright_induction' : + forall A : Z -> Prop, predicate_wd Zeq A -> + forall z : Z, + (forall n : Z, n <= z -> A n) -> + (forall n : Z, z <= n -> A n -> A (S n)) -> + forall n : Z, A n. +Proof NZright_induction'. + +Theorem Zleft_induction' : + forall A : Z -> Prop, predicate_wd Zeq A -> + forall z : Z, + (forall n : Z, z <= n -> A n) -> + (forall n : Z, n < z -> A (S n) -> A n) -> + forall n : Z, A n. +Proof NZleft_induction'. + +Theorem Zstrong_right_induction : + forall A : Z -> Prop, predicate_wd Zeq A -> + forall z : Z, + (forall n : Z, z <= n -> (forall m : Z, z <= m -> m < n -> A m) -> A n) -> + forall n : Z, z <= n -> A n. +Proof NZstrong_right_induction. + +Theorem Zstrong_left_induction : + forall A : Z -> Prop, predicate_wd Zeq A -> + forall z : Z, + (forall n : Z, n <= z -> (forall m : Z, m <= z -> S n <= m -> A m) -> A n) -> + forall n : Z, n <= z -> A n. +Proof NZstrong_left_induction. + +Theorem Zstrong_right_induction' : + forall A : Z -> Prop, predicate_wd Zeq A -> + forall z : Z, + (forall n : Z, n <= z -> A n) -> + (forall n : Z, z <= n -> (forall m : Z, z <= m -> m < n -> A m) -> A n) -> + forall n : Z, A n. +Proof NZstrong_right_induction'. + +Theorem Zstrong_left_induction' : + forall A : Z -> Prop, predicate_wd Zeq A -> + forall z : Z, + (forall n : Z, z <= n -> A n) -> + (forall n : Z, n <= z -> (forall m : Z, m <= z -> S n <= m -> A m) -> A n) -> + forall n : Z, A n. +Proof NZstrong_left_induction'. + +Theorem Zorder_induction : + forall A : Z -> Prop, predicate_wd Zeq A -> + forall z : Z, A z -> + (forall n : Z, z <= n -> A n -> A (S n)) -> + (forall n : Z, n < z -> A (S n) -> A n) -> + forall n : Z, A n. +Proof NZorder_induction. + +Theorem Zorder_induction' : + forall A : Z -> Prop, predicate_wd Zeq A -> + forall z : Z, A z -> + (forall n : Z, z <= n -> A n -> A (S n)) -> + (forall n : Z, n <= z -> A n -> A (P n)) -> + forall n : Z, A n. +Proof NZorder_induction'. + +Theorem Zorder_induction_0 : + forall A : Z -> Prop, predicate_wd Zeq A -> + A 0 -> + (forall n : Z, 0 <= n -> A n -> A (S n)) -> + (forall n : Z, n < 0 -> A (S n) -> A n) -> + forall n : Z, A n. +Proof NZorder_induction_0. + +Theorem Zorder_induction'_0 : + forall A : Z -> Prop, predicate_wd Zeq A -> + A 0 -> + (forall n : Z, 0 <= n -> A n -> A (S n)) -> + (forall n : Z, n <= 0 -> A n -> A (P n)) -> + forall n : Z, A n. +Proof NZorder_induction'_0. + +Ltac Zinduct n := induction_maker n ltac:(apply Zorder_induction_0). + +(** Elimintation principle for < *) + +Theorem Zlt_ind : + forall A : Z -> Prop, predicate_wd Zeq A -> + forall n : Z, A (S n) -> + (forall m : Z, n < m -> A m -> A (S m)) -> forall m : Z, n < m -> A m. +Proof NZlt_ind. + +(** Elimintation principle for <= *) + +Theorem Zle_ind : + forall A : Z -> Prop, predicate_wd Zeq A -> + forall n : Z, A n -> + (forall m : Z, n <= m -> A m -> A (S m)) -> forall m : Z, n <= m -> A m. +Proof NZle_ind. + +(** Well-founded relations *) + +Theorem Zlt_wf : forall z : Z, well_founded (fun n m : Z => z <= n /\ n < m). +Proof NZlt_wf. + +Theorem Zgt_wf : forall z : Z, well_founded (fun n m : Z => m < n /\ n <= z). +Proof NZgt_wf. + +(* Theorems that are either not valid on N or have different proofs on N and Z *) + +Theorem Zlt_pred_l : forall n : Z, P n < n. +Proof. +intro n; rewrite <- (Zsucc_pred n) at 2; apply Zlt_succ_diag_r. +Qed. + +Theorem Zle_pred_l : forall n : Z, P n <= n. +Proof. +intro; apply Zlt_le_incl; apply Zlt_pred_l. +Qed. + +Theorem Zlt_le_pred : forall n m : Z, n < m <-> n <= P m. +Proof. +intros n m; rewrite <- (Zsucc_pred m); rewrite Zpred_succ. apply Zlt_succ_r. +Qed. + +Theorem Znle_pred_r : forall n : Z, ~ n <= P n. +Proof. +intro; rewrite <- Zlt_le_pred; apply Zlt_irrefl. +Qed. + +Theorem Zlt_pred_le : forall n m : Z, P n < m <-> n <= m. +Proof. +intros n m; rewrite <- (Zsucc_pred n) at 2. +symmetry; apply Zle_succ_l. +Qed. + +Theorem Zlt_lt_pred : forall n m : Z, n < m -> P n < m. +Proof. +intros; apply <- Zlt_pred_le; now apply Zlt_le_incl. +Qed. + +Theorem Zle_le_pred : forall n m : Z, n <= m -> P n <= m. +Proof. +intros; apply Zlt_le_incl; now apply <- Zlt_pred_le. +Qed. + +Theorem Zlt_pred_lt : forall n m : Z, n < P m -> n < m. +Proof. +intros n m H; apply Zlt_trans with (P m); [assumption | apply Zlt_pred_l]. +Qed. + +Theorem Zle_pred_lt : forall n m : Z, n <= P m -> n <= m. +Proof. +intros; apply Zlt_le_incl; now apply <- Zlt_le_pred. +Qed. + +Theorem Zpred_lt_mono : forall n m : Z, n < m <-> P n < P m. +Proof. +intros; rewrite Zlt_le_pred; symmetry; apply Zlt_pred_le. +Qed. + +Theorem Zpred_le_mono : forall n m : Z, n <= m <-> P n <= P m. +Proof. +intros; rewrite <- Zlt_pred_le; now rewrite Zlt_le_pred. +Qed. + +Theorem Zlt_succ_lt_pred : forall n m : Z, S n < m <-> n < P m. +Proof. +intros n m; now rewrite (Zpred_lt_mono (S n) m), Zpred_succ. +Qed. + +Theorem Zle_succ_le_pred : forall n m : Z, S n <= m <-> n <= P m. +Proof. +intros n m; now rewrite (Zpred_le_mono (S n) m), Zpred_succ. +Qed. + +Theorem Zlt_pred_lt_succ : forall n m : Z, P n < m <-> n < S m. +Proof. +intros; rewrite Zlt_pred_le; symmetry; apply Zlt_succ_r. +Qed. + +Theorem Zle_pred_lt_succ : forall n m : Z, P n <= m <-> n <= S m. +Proof. +intros n m; now rewrite (Zpred_le_mono n (S m)), Zpred_succ. +Qed. + +Theorem Zneq_pred_l : forall n : Z, P n ~= n. +Proof. +intro; apply Zlt_neq; apply Zlt_pred_l. +Qed. + +Theorem Zlt_n1_r : forall n m : Z, n < m -> m < 0 -> n < -1. +Proof. +intros n m H1 H2. apply -> Zlt_le_pred in H2. +setoid_replace (P 0) with (-1) in H2. now apply NZlt_le_trans with m. +apply <- Zeq_opp_r. now rewrite Zopp_pred, Zopp_0. +Qed. + +End ZOrderPropFunct. + diff --git a/theories/Numbers/Integer/Abstract/ZMul.v b/theories/Numbers/Integer/Abstract/ZMul.v new file mode 100644 index 00000000..c48d1b4c --- /dev/null +++ b/theories/Numbers/Integer/Abstract/ZMul.v @@ -0,0 +1,115 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: ZMul.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export ZAdd. + +Module ZMulPropFunct (Import ZAxiomsMod : ZAxiomsSig). +Module Export ZAddPropMod := ZAddPropFunct ZAxiomsMod. +Open Local Scope IntScope. + +Theorem Zmul_wd : + forall n1 n2 : Z, n1 == n2 -> forall m1 m2 : Z, m1 == m2 -> n1 * m1 == n2 * m2. +Proof NZmul_wd. + +Theorem Zmul_0_l : forall n : Z, 0 * n == 0. +Proof NZmul_0_l. + +Theorem Zmul_succ_l : forall n m : Z, (S n) * m == n * m + m. +Proof NZmul_succ_l. + +(* Theorems that are valid for both natural numbers and integers *) + +Theorem Zmul_0_r : forall n : Z, n * 0 == 0. +Proof NZmul_0_r. + +Theorem Zmul_succ_r : forall n m : Z, n * (S m) == n * m + n. +Proof NZmul_succ_r. + +Theorem Zmul_comm : forall n m : Z, n * m == m * n. +Proof NZmul_comm. + +Theorem Zmul_add_distr_r : forall n m p : Z, (n + m) * p == n * p + m * p. +Proof NZmul_add_distr_r. + +Theorem Zmul_add_distr_l : forall n m p : Z, n * (m + p) == n * m + n * p. +Proof NZmul_add_distr_l. + +(* A note on naming: right (correspondingly, left) distributivity happens +when the sum is multiplied by a number on the right (left), not when the +sum itself is the right (left) factor in the product (see planetmath.org +and mathworld.wolfram.com). In the old library BinInt, distributivity over +subtraction was named correctly, but distributivity over addition was named +incorrectly. The names in Isabelle/HOL library are also incorrect. *) + +Theorem Zmul_assoc : forall n m p : Z, n * (m * p) == (n * m) * p. +Proof NZmul_assoc. + +Theorem Zmul_1_l : forall n : Z, 1 * n == n. +Proof NZmul_1_l. + +Theorem Zmul_1_r : forall n : Z, n * 1 == n. +Proof NZmul_1_r. + +(* The following two theorems are true in an ordered ring, +but since they don't mention order, we'll put them here *) + +Theorem Zeq_mul_0 : forall n m : Z, n * m == 0 <-> n == 0 \/ m == 0. +Proof NZeq_mul_0. + +Theorem Zneq_mul_0 : forall n m : Z, n ~= 0 /\ m ~= 0 <-> n * m ~= 0. +Proof NZneq_mul_0. + +(* Theorems that are either not valid on N or have different proofs on N and Z *) + +Theorem Zmul_pred_r : forall n m : Z, n * (P m) == n * m - n. +Proof. +intros n m. +rewrite <- (Zsucc_pred m) at 2. +now rewrite Zmul_succ_r, <- Zadd_sub_assoc, Zsub_diag, Zadd_0_r. +Qed. + +Theorem Zmul_pred_l : forall n m : Z, (P n) * m == n * m - m. +Proof. +intros n m; rewrite (Zmul_comm (P n) m), (Zmul_comm n m). apply Zmul_pred_r. +Qed. + +Theorem Zmul_opp_l : forall n m : Z, (- n) * m == - (n * m). +Proof. +intros n m. apply -> Zadd_move_0_r. +now rewrite <- Zmul_add_distr_r, Zadd_opp_diag_l, Zmul_0_l. +Qed. + +Theorem Zmul_opp_r : forall n m : Z, n * (- m) == - (n * m). +Proof. +intros n m; rewrite (Zmul_comm n (- m)), (Zmul_comm n m); apply Zmul_opp_l. +Qed. + +Theorem Zmul_opp_opp : forall n m : Z, (- n) * (- m) == n * m. +Proof. +intros n m; now rewrite Zmul_opp_l, Zmul_opp_r, Zopp_involutive. +Qed. + +Theorem Zmul_sub_distr_l : forall n m p : Z, n * (m - p) == n * m - n * p. +Proof. +intros n m p. do 2 rewrite <- Zadd_opp_r. rewrite Zmul_add_distr_l. +now rewrite Zmul_opp_r. +Qed. + +Theorem Zmul_sub_distr_r : forall n m p : Z, (n - m) * p == n * p - m * p. +Proof. +intros n m p; rewrite (Zmul_comm (n - m) p), (Zmul_comm n p), (Zmul_comm m p); +now apply Zmul_sub_distr_l. +Qed. + +End ZMulPropFunct. + + diff --git a/theories/Numbers/Integer/Abstract/ZMulOrder.v b/theories/Numbers/Integer/Abstract/ZMulOrder.v new file mode 100644 index 00000000..e3f1d9aa --- /dev/null +++ b/theories/Numbers/Integer/Abstract/ZMulOrder.v @@ -0,0 +1,343 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: ZMulOrder.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export ZAddOrder. + +Module ZMulOrderPropFunct (Import ZAxiomsMod : ZAxiomsSig). +Module Export ZAddOrderPropMod := ZAddOrderPropFunct ZAxiomsMod. +Open Local Scope IntScope. + +Theorem Zmul_lt_pred : + forall p q n m : Z, S p == q -> (p * n < p * m <-> q * n + m < q * m + n). +Proof NZmul_lt_pred. + +Theorem Zmul_lt_mono_pos_l : forall p n m : Z, 0 < p -> (n < m <-> p * n < p * m). +Proof NZmul_lt_mono_pos_l. + +Theorem Zmul_lt_mono_pos_r : forall p n m : Z, 0 < p -> (n < m <-> n * p < m * p). +Proof NZmul_lt_mono_pos_r. + +Theorem Zmul_lt_mono_neg_l : forall p n m : Z, p < 0 -> (n < m <-> p * m < p * n). +Proof NZmul_lt_mono_neg_l. + +Theorem Zmul_lt_mono_neg_r : forall p n m : Z, p < 0 -> (n < m <-> m * p < n * p). +Proof NZmul_lt_mono_neg_r. + +Theorem Zmul_le_mono_nonneg_l : forall n m p : Z, 0 <= p -> n <= m -> p * n <= p * m. +Proof NZmul_le_mono_nonneg_l. + +Theorem Zmul_le_mono_nonpos_l : forall n m p : Z, p <= 0 -> n <= m -> p * m <= p * n. +Proof NZmul_le_mono_nonpos_l. + +Theorem Zmul_le_mono_nonneg_r : forall n m p : Z, 0 <= p -> n <= m -> n * p <= m * p. +Proof NZmul_le_mono_nonneg_r. + +Theorem Zmul_le_mono_nonpos_r : forall n m p : Z, p <= 0 -> n <= m -> m * p <= n * p. +Proof NZmul_le_mono_nonpos_r. + +Theorem Zmul_cancel_l : forall n m p : Z, p ~= 0 -> (p * n == p * m <-> n == m). +Proof NZmul_cancel_l. + +Theorem Zmul_cancel_r : forall n m p : Z, p ~= 0 -> (n * p == m * p <-> n == m). +Proof NZmul_cancel_r. + +Theorem Zmul_id_l : forall n m : Z, m ~= 0 -> (n * m == m <-> n == 1). +Proof NZmul_id_l. + +Theorem Zmul_id_r : forall n m : Z, n ~= 0 -> (n * m == n <-> m == 1). +Proof NZmul_id_r. + +Theorem Zmul_le_mono_pos_l : forall n m p : Z, 0 < p -> (n <= m <-> p * n <= p * m). +Proof NZmul_le_mono_pos_l. + +Theorem Zmul_le_mono_pos_r : forall n m p : Z, 0 < p -> (n <= m <-> n * p <= m * p). +Proof NZmul_le_mono_pos_r. + +Theorem Zmul_le_mono_neg_l : forall n m p : Z, p < 0 -> (n <= m <-> p * m <= p * n). +Proof NZmul_le_mono_neg_l. + +Theorem Zmul_le_mono_neg_r : forall n m p : Z, p < 0 -> (n <= m <-> m * p <= n * p). +Proof NZmul_le_mono_neg_r. + +Theorem Zmul_lt_mono_nonneg : + forall n m p q : Z, 0 <= n -> n < m -> 0 <= p -> p < q -> n * p < m * q. +Proof NZmul_lt_mono_nonneg. + +Theorem Zmul_lt_mono_nonpos : + forall n m p q : Z, m <= 0 -> n < m -> q <= 0 -> p < q -> m * q < n * p. +Proof. +intros n m p q H1 H2 H3 H4. +apply Zle_lt_trans with (m * p). +apply Zmul_le_mono_nonpos_l; [assumption | now apply Zlt_le_incl]. +apply -> Zmul_lt_mono_neg_r; [assumption | now apply Zlt_le_trans with q]. +Qed. + +Theorem Zmul_le_mono_nonneg : + forall n m p q : Z, 0 <= n -> n <= m -> 0 <= p -> p <= q -> n * p <= m * q. +Proof NZmul_le_mono_nonneg. + +Theorem Zmul_le_mono_nonpos : + forall n m p q : Z, m <= 0 -> n <= m -> q <= 0 -> p <= q -> m * q <= n * p. +Proof. +intros n m p q H1 H2 H3 H4. +apply Zle_trans with (m * p). +now apply Zmul_le_mono_nonpos_l. +apply Zmul_le_mono_nonpos_r; [now apply Zle_trans with q | assumption]. +Qed. + +Theorem Zmul_pos_pos : forall n m : Z, 0 < n -> 0 < m -> 0 < n * m. +Proof NZmul_pos_pos. + +Theorem Zmul_neg_neg : forall n m : Z, n < 0 -> m < 0 -> 0 < n * m. +Proof NZmul_neg_neg. + +Theorem Zmul_pos_neg : forall n m : Z, 0 < n -> m < 0 -> n * m < 0. +Proof NZmul_pos_neg. + +Theorem Zmul_neg_pos : forall n m : Z, n < 0 -> 0 < m -> n * m < 0. +Proof NZmul_neg_pos. + +Theorem Zmul_nonneg_nonneg : forall n m : Z, 0 <= n -> 0 <= m -> 0 <= n * m. +Proof. +intros n m H1 H2. +rewrite <- (Zmul_0_l m). now apply Zmul_le_mono_nonneg_r. +Qed. + +Theorem Zmul_nonpos_nonpos : forall n m : Z, n <= 0 -> m <= 0 -> 0 <= n * m. +Proof. +intros n m H1 H2. +rewrite <- (Zmul_0_l m). now apply Zmul_le_mono_nonpos_r. +Qed. + +Theorem Zmul_nonneg_nonpos : forall n m : Z, 0 <= n -> m <= 0 -> n * m <= 0. +Proof. +intros n m H1 H2. +rewrite <- (Zmul_0_l m). now apply Zmul_le_mono_nonpos_r. +Qed. + +Theorem Zmul_nonpos_nonneg : forall n m : Z, n <= 0 -> 0 <= m -> n * m <= 0. +Proof. +intros; rewrite Zmul_comm; now apply Zmul_nonneg_nonpos. +Qed. + +Theorem Zlt_1_mul_pos : forall n m : Z, 1 < n -> 0 < m -> 1 < n * m. +Proof NZlt_1_mul_pos. + +Theorem Zeq_mul_0 : forall n m : Z, n * m == 0 <-> n == 0 \/ m == 0. +Proof NZeq_mul_0. + +Theorem Zneq_mul_0 : forall n m : Z, n ~= 0 /\ m ~= 0 <-> n * m ~= 0. +Proof NZneq_mul_0. + +Theorem Zeq_square_0 : forall n : Z, n * n == 0 <-> n == 0. +Proof NZeq_square_0. + +Theorem Zeq_mul_0_l : forall n m : Z, n * m == 0 -> m ~= 0 -> n == 0. +Proof NZeq_mul_0_l. + +Theorem Zeq_mul_0_r : forall n m : Z, n * m == 0 -> n ~= 0 -> m == 0. +Proof NZeq_mul_0_r. + +Theorem Zlt_0_mul : forall n m : Z, 0 < n * m <-> 0 < n /\ 0 < m \/ m < 0 /\ n < 0. +Proof NZlt_0_mul. + +Notation Zmul_pos := Zlt_0_mul (only parsing). + +Theorem Zlt_mul_0 : + forall n m : Z, n * m < 0 <-> n < 0 /\ m > 0 \/ n > 0 /\ m < 0. +Proof. +intros n m; split; [intro H | intros [[H1 H2] | [H1 H2]]]. +destruct (Zlt_trichotomy n 0) as [H1 | [H1 | H1]]; +[| rewrite H1 in H; rewrite Zmul_0_l in H; false_hyp H Zlt_irrefl |]; +(destruct (Zlt_trichotomy m 0) as [H2 | [H2 | H2]]; +[| rewrite H2 in H; rewrite Zmul_0_r in H; false_hyp H Zlt_irrefl |]); +try (left; now split); try (right; now split). +assert (H3 : n * m > 0) by now apply Zmul_neg_neg. +elimtype False; now apply (Zlt_asymm (n * m) 0). +assert (H3 : n * m > 0) by now apply Zmul_pos_pos. +elimtype False; now apply (Zlt_asymm (n * m) 0). +now apply Zmul_neg_pos. now apply Zmul_pos_neg. +Qed. + +Notation Zmul_neg := Zlt_mul_0 (only parsing). + +Theorem Zle_0_mul : + forall n m : Z, 0 <= n * m -> 0 <= n /\ 0 <= m \/ n <= 0 /\ m <= 0. +Proof. +assert (R : forall n : Z, 0 == n <-> n == 0) by (intros; split; apply Zeq_symm). +intros n m. repeat rewrite Zlt_eq_cases. repeat rewrite R. +rewrite Zlt_0_mul, Zeq_mul_0. +pose proof (Zlt_trichotomy n 0); pose proof (Zlt_trichotomy m 0). tauto. +Qed. + +Notation Zmul_nonneg := Zle_0_mul (only parsing). + +Theorem Zle_mul_0 : + forall n m : Z, n * m <= 0 -> 0 <= n /\ m <= 0 \/ n <= 0 /\ 0 <= m. +Proof. +assert (R : forall n : Z, 0 == n <-> n == 0) by (intros; split; apply Zeq_symm). +intros n m. repeat rewrite Zlt_eq_cases. repeat rewrite R. +rewrite Zlt_mul_0, Zeq_mul_0. +pose proof (Zlt_trichotomy n 0); pose proof (Zlt_trichotomy m 0). tauto. +Qed. + +Notation Zmul_nonpos := Zle_mul_0 (only parsing). + +Theorem Zle_0_square : forall n : Z, 0 <= n * n. +Proof. +intro n; destruct (Zneg_nonneg_cases n). +apply Zlt_le_incl; now apply Zmul_neg_neg. +now apply Zmul_nonneg_nonneg. +Qed. + +Notation Zsquare_nonneg := Zle_0_square (only parsing). + +Theorem Znlt_square_0 : forall n : Z, ~ n * n < 0. +Proof. +intros n H. apply -> Zlt_nge in H. apply H. apply Zsquare_nonneg. +Qed. + +Theorem Zsquare_lt_mono_nonneg : forall n m : Z, 0 <= n -> n < m -> n * n < m * m. +Proof NZsquare_lt_mono_nonneg. + +Theorem Zsquare_lt_mono_nonpos : forall n m : Z, n <= 0 -> m < n -> n * n < m * m. +Proof. +intros n m H1 H2. now apply Zmul_lt_mono_nonpos. +Qed. + +Theorem Zsquare_le_mono_nonneg : forall n m : Z, 0 <= n -> n <= m -> n * n <= m * m. +Proof NZsquare_le_mono_nonneg. + +Theorem Zsquare_le_mono_nonpos : forall n m : Z, n <= 0 -> m <= n -> n * n <= m * m. +Proof. +intros n m H1 H2. now apply Zmul_le_mono_nonpos. +Qed. + +Theorem Zsquare_lt_simpl_nonneg : forall n m : Z, 0 <= m -> n * n < m * m -> n < m. +Proof NZsquare_lt_simpl_nonneg. + +Theorem Zsquare_le_simpl_nonneg : forall n m : Z, 0 <= m -> n * n <= m * m -> n <= m. +Proof NZsquare_le_simpl_nonneg. + +Theorem Zsquare_lt_simpl_nonpos : forall n m : Z, m <= 0 -> n * n < m * m -> m < n. +Proof. +intros n m H1 H2. destruct (Zle_gt_cases n 0). +destruct (NZlt_ge_cases m n). +assumption. assert (F : m * m <= n * n) by now apply Zsquare_le_mono_nonpos. +apply -> NZle_ngt in F. false_hyp H2 F. +now apply Zle_lt_trans with 0. +Qed. + +Theorem Zsquare_le_simpl_nonpos : forall n m : NZ, m <= 0 -> n * n <= m * m -> m <= n. +Proof. +intros n m H1 H2. destruct (NZle_gt_cases n 0). +destruct (NZle_gt_cases m n). +assumption. assert (F : m * m < n * n) by now apply Zsquare_lt_mono_nonpos. +apply -> NZlt_nge in F. false_hyp H2 F. +apply Zlt_le_incl; now apply NZle_lt_trans with 0. +Qed. + +Theorem Zmul_2_mono_l : forall n m : Z, n < m -> 1 + (1 + 1) * n < (1 + 1) * m. +Proof NZmul_2_mono_l. + +Theorem Zlt_1_mul_neg : forall n m : Z, n < -1 -> m < 0 -> 1 < n * m. +Proof. +intros n m H1 H2. apply -> (NZmul_lt_mono_neg_r m) in H1. +apply <- Zopp_pos_neg in H2. rewrite Zmul_opp_l, Zmul_1_l in H1. +now apply Zlt_1_l with (- m). +assumption. +Qed. + +Theorem Zlt_mul_n1_neg : forall n m : Z, 1 < n -> m < 0 -> n * m < -1. +Proof. +intros n m H1 H2. apply -> (NZmul_lt_mono_neg_r m) in H1. +rewrite Zmul_1_l in H1. now apply Zlt_n1_r with m. +assumption. +Qed. + +Theorem Zlt_mul_n1_pos : forall n m : Z, n < -1 -> 0 < m -> n * m < -1. +Proof. +intros n m H1 H2. apply -> (NZmul_lt_mono_pos_r m) in H1. +rewrite Zmul_opp_l, Zmul_1_l in H1. +apply <- Zopp_neg_pos in H2. now apply Zlt_n1_r with (- m). +assumption. +Qed. + +Theorem Zlt_1_mul_l : forall n m : Z, 1 < n -> n * m < -1 \/ n * m == 0 \/ 1 < n * m. +Proof. +intros n m H; destruct (Zlt_trichotomy m 0) as [H1 | [H1 | H1]]. +left. now apply Zlt_mul_n1_neg. +right; left; now rewrite H1, Zmul_0_r. +right; right; now apply Zlt_1_mul_pos. +Qed. + +Theorem Zlt_n1_mul_r : forall n m : Z, n < -1 -> n * m < -1 \/ n * m == 0 \/ 1 < n * m. +Proof. +intros n m H; destruct (Zlt_trichotomy m 0) as [H1 | [H1 | H1]]. +right; right. now apply Zlt_1_mul_neg. +right; left; now rewrite H1, Zmul_0_r. +left. now apply Zlt_mul_n1_pos. +Qed. + +Theorem Zeq_mul_1 : forall n m : Z, n * m == 1 -> n == 1 \/ n == -1. +Proof. +assert (F : ~ 1 < -1). +intro H. +assert (H1 : -1 < 0). apply <- Zopp_neg_pos. apply Zlt_succ_diag_r. +assert (H2 : 1 < 0) by now apply Zlt_trans with (-1). false_hyp H2 Znlt_succ_diag_l. +Z0_pos_neg n. +intros m H; rewrite Zmul_0_l in H; false_hyp H Zneq_succ_diag_r. +intros n H; split; apply <- Zle_succ_l in H; le_elim H. +intros m H1; apply (Zlt_1_mul_l n m) in H. +rewrite H1 in H; destruct H as [H | [H | H]]. +false_hyp H F. false_hyp H Zneq_succ_diag_l. false_hyp H Zlt_irrefl. +intros; now left. +intros m H1; apply (Zlt_1_mul_l n m) in H. rewrite Zmul_opp_l in H1; +apply -> Zeq_opp_l in H1. rewrite H1 in H; destruct H as [H | [H | H]]. +false_hyp H Zlt_irrefl. apply -> Zeq_opp_l in H. rewrite Zopp_0 in H. +false_hyp H Zneq_succ_diag_l. false_hyp H F. +intros; right; symmetry; now apply Zopp_wd. +Qed. + +Theorem Zlt_mul_diag_l : forall n m : Z, n < 0 -> (1 < m <-> n * m < n). +Proof. +intros n m H. stepr (n * m < n * 1) by now rewrite Zmul_1_r. +now apply Zmul_lt_mono_neg_l. +Qed. + +Theorem Zlt_mul_diag_r : forall n m : Z, 0 < n -> (1 < m <-> n < n * m). +Proof. +intros n m H. stepr (n * 1 < n * m) by now rewrite Zmul_1_r. +now apply Zmul_lt_mono_pos_l. +Qed. + +Theorem Zle_mul_diag_l : forall n m : Z, n < 0 -> (1 <= m <-> n * m <= n). +Proof. +intros n m H. stepr (n * m <= n * 1) by now rewrite Zmul_1_r. +now apply Zmul_le_mono_neg_l. +Qed. + +Theorem Zle_mul_diag_r : forall n m : Z, 0 < n -> (1 <= m <-> n <= n * m). +Proof. +intros n m H. stepr (n * 1 <= n * m) by now rewrite Zmul_1_r. +now apply Zmul_le_mono_pos_l. +Qed. + +Theorem Zlt_mul_r : forall n m p : Z, 0 < n -> 1 < p -> n < m -> n < m * p. +Proof. +intros. stepl (n * 1) by now rewrite Zmul_1_r. +apply Zmul_lt_mono_nonneg. +now apply Zlt_le_incl. assumption. apply Zle_0_1. assumption. +Qed. + +End ZMulOrderPropFunct. + diff --git a/theories/Numbers/Integer/BigZ/BigZ.v b/theories/Numbers/Integer/BigZ/BigZ.v new file mode 100644 index 00000000..09abf424 --- /dev/null +++ b/theories/Numbers/Integer/BigZ/BigZ.v @@ -0,0 +1,109 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: BigZ.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export BigN. +Require Import ZMulOrder. +Require Import ZSig. +Require Import ZSigZAxioms. +Require Import ZMake. + +Module BigZ <: ZType := ZMake.Make BigN. + +(** Module [BigZ] implements [ZAxiomsSig] *) + +Module Export BigZAxiomsMod := ZSig_ZAxioms BigZ. +Module Export BigZMulOrderPropMod := ZMulOrderPropFunct BigZAxiomsMod. + +(** Notations about [BigZ] *) + +Notation bigZ := BigZ.t. + +Delimit Scope bigZ_scope with bigZ. +Bind Scope bigZ_scope with bigZ. +Bind Scope bigZ_scope with BigZ.t. +Bind Scope bigZ_scope with BigZ.t_. + +Notation Local "0" := BigZ.zero : bigZ_scope. +Infix "+" := BigZ.add : bigZ_scope. +Infix "-" := BigZ.sub : bigZ_scope. +Notation "- x" := (BigZ.opp x) : bigZ_scope. +Infix "*" := BigZ.mul : bigZ_scope. +Infix "/" := BigZ.div : bigZ_scope. +Infix "?=" := BigZ.compare : bigZ_scope. +Infix "==" := BigZ.eq (at level 70, no associativity) : bigZ_scope. +Infix "<" := BigZ.lt : bigZ_scope. +Infix "<=" := BigZ.le : bigZ_scope. +Notation "[ i ]" := (BigZ.to_Z i) : bigZ_scope. + +Open Scope bigZ_scope. + +(** Some additional results about [BigZ] *) + +Theorem spec_to_Z: forall n:bigZ, + BigN.to_Z (BigZ.to_N n) = ((Zsgn [n]) * [n])%Z. +Proof. +intros n; case n; simpl; intros p; + generalize (BigN.spec_pos p); case (BigN.to_Z p); auto. +intros p1 H1; case H1; auto. +intros p1 H1; case H1; auto. +Qed. + +Theorem spec_to_N n: + ([n] = Zsgn [n] * (BigN.to_Z (BigZ.to_N n)))%Z. +Proof. +intros n; case n; simpl; intros p; + generalize (BigN.spec_pos p); case (BigN.to_Z p); auto. +intros p1 H1; case H1; auto. +intros p1 H1; case H1; auto. +Qed. + +Theorem spec_to_Z_pos: forall n, (0 <= [n])%Z -> + BigN.to_Z (BigZ.to_N n) = [n]. +Proof. +intros n; case n; simpl; intros p; + generalize (BigN.spec_pos p); case (BigN.to_Z p); auto. +intros p1 _ H1; case H1; auto. +intros p1 H1; case H1; auto. +Qed. + +Lemma sub_opp : forall x y : bigZ, x - y == x + (- y). +Proof. +red; intros; zsimpl; auto. +Qed. + +Lemma add_opp : forall x : bigZ, x + (- x) == 0. +Proof. +red; intros; zsimpl; auto with zarith. +Qed. + +(** [BigZ] is a ring *) + +Lemma BigZring : + ring_theory BigZ.zero BigZ.one BigZ.add BigZ.mul BigZ.sub BigZ.opp BigZ.eq. +Proof. +constructor. +exact Zadd_0_l. +exact Zadd_comm. +exact Zadd_assoc. +exact Zmul_1_l. +exact Zmul_comm. +exact Zmul_assoc. +exact Zmul_add_distr_r. +exact sub_opp. +exact add_opp. +Qed. + +Add Ring BigZr : BigZring. + +(** Todo: tactic translating from [BigZ] to [Z] + omega *) + +(** Todo: micromega *) diff --git a/theories/Numbers/Integer/BigZ/ZMake.v b/theories/Numbers/Integer/BigZ/ZMake.v new file mode 100644 index 00000000..1f2b12bb --- /dev/null +++ b/theories/Numbers/Integer/BigZ/ZMake.v @@ -0,0 +1,491 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: ZMake.v 11027 2008-06-01 13:28:59Z letouzey $ i*) + +Require Import ZArith. +Require Import BigNumPrelude. +Require Import NSig. +Require Import ZSig. + +Open Scope Z_scope. + +(** * ZMake + + A generic transformation from a structure of natural numbers + [NSig.NType] to a structure of integers [ZSig.ZType]. +*) + +Module Make (N:NType) <: ZType. + + Inductive t_ := + | Pos : N.t -> t_ + | Neg : N.t -> t_. + + Definition t := t_. + + Definition zero := Pos N.zero. + Definition one := Pos N.one. + Definition minus_one := Neg N.one. + + Definition of_Z x := + match x with + | Zpos x => Pos (N.of_N (Npos x)) + | Z0 => zero + | Zneg x => Neg (N.of_N (Npos x)) + end. + + Definition to_Z x := + match x with + | Pos nx => N.to_Z nx + | Neg nx => Zopp (N.to_Z nx) + end. + + Theorem spec_of_Z: forall x, to_Z (of_Z x) = x. + intros x; case x; unfold to_Z, of_Z, zero. + exact N.spec_0. + intros; rewrite N.spec_of_N; auto. + intros; rewrite N.spec_of_N; auto. + Qed. + + Definition eq x y := (to_Z x = to_Z y). + + Theorem spec_0: to_Z zero = 0. + exact N.spec_0. + Qed. + + Theorem spec_1: to_Z one = 1. + exact N.spec_1. + Qed. + + Theorem spec_m1: to_Z minus_one = -1. + simpl; rewrite N.spec_1; auto. + Qed. + + Definition compare x y := + match x, y with + | Pos nx, Pos ny => N.compare nx ny + | Pos nx, Neg ny => + match N.compare nx N.zero with + | Gt => Gt + | _ => N.compare ny N.zero + end + | Neg nx, Pos ny => + match N.compare N.zero nx with + | Lt => Lt + | _ => N.compare N.zero ny + end + | Neg nx, Neg ny => N.compare ny nx + end. + + Definition lt n m := compare n m = Lt. + Definition le n m := compare n m <> Gt. + Definition min n m := match compare n m with Gt => m | _ => n end. + Definition max n m := match compare n m with Lt => m | _ => n end. + + Theorem spec_compare: forall x y, + match compare x y with + Eq => to_Z x = to_Z y + | Lt => to_Z x < to_Z y + | Gt => to_Z x > to_Z y + end. + unfold compare, to_Z; intros x y; case x; case y; clear x y; + intros x y; auto; generalize (N.spec_pos x) (N.spec_pos y). + generalize (N.spec_compare y x); case N.compare; auto with zarith. + generalize (N.spec_compare y N.zero); case N.compare; + try rewrite N.spec_0; auto with zarith. + generalize (N.spec_compare x N.zero); case N.compare; + rewrite N.spec_0; auto with zarith. + generalize (N.spec_compare x N.zero); case N.compare; + rewrite N.spec_0; auto with zarith. + generalize (N.spec_compare N.zero y); case N.compare; + try rewrite N.spec_0; auto with zarith. + generalize (N.spec_compare N.zero x); case N.compare; + rewrite N.spec_0; auto with zarith. + generalize (N.spec_compare N.zero x); case N.compare; + rewrite N.spec_0; auto with zarith. + generalize (N.spec_compare x y); case N.compare; auto with zarith. + Qed. + + Definition eq_bool x y := + match compare x y with + | Eq => true + | _ => false + end. + + Theorem spec_eq_bool: forall x y, + if eq_bool x y then to_Z x = to_Z y else to_Z x <> to_Z y. + intros x y; unfold eq_bool; + generalize (spec_compare x y); case compare; auto with zarith. + Qed. + + Definition cmp_sign x y := + match x, y with + | Pos nx, Neg ny => + if N.eq_bool ny N.zero then Eq else Gt + | Neg nx, Pos ny => + if N.eq_bool nx N.zero then Eq else Lt + | _, _ => Eq + end. + + Theorem spec_cmp_sign: forall x y, + match cmp_sign x y with + | Gt => 0 <= to_Z x /\ to_Z y < 0 + | Lt => to_Z x < 0 /\ 0 <= to_Z y + | Eq => True + end. + Proof. + intros [x | x] [y | y]; unfold cmp_sign; auto. + generalize (N.spec_eq_bool y N.zero); case N.eq_bool; auto. + rewrite N.spec_0; unfold to_Z. + generalize (N.spec_pos x) (N.spec_pos y); auto with zarith. + generalize (N.spec_eq_bool x N.zero); case N.eq_bool; auto. + rewrite N.spec_0; unfold to_Z. + generalize (N.spec_pos x) (N.spec_pos y); auto with zarith. + Qed. + + Definition to_N x := + match x with + | Pos nx => nx + | Neg nx => nx + end. + + Definition abs x := Pos (to_N x). + + Theorem spec_abs: forall x, to_Z (abs x) = Zabs (to_Z x). + intros x; case x; clear x; intros x; assert (F:=N.spec_pos x). + simpl; rewrite Zabs_eq; auto. + simpl; rewrite Zabs_non_eq; simpl; auto with zarith. + Qed. + + Definition opp x := + match x with + | Pos nx => Neg nx + | Neg nx => Pos nx + end. + + Theorem spec_opp: forall x, to_Z (opp x) = - to_Z x. + intros x; case x; simpl; auto with zarith. + Qed. + + Definition succ x := + match x with + | Pos n => Pos (N.succ n) + | Neg n => + match N.compare N.zero n with + | Lt => Neg (N.pred n) + | _ => one + end + end. + + Theorem spec_succ: forall n, to_Z (succ n) = to_Z n + 1. + intros x; case x; clear x; intros x. + exact (N.spec_succ x). + simpl; generalize (N.spec_compare N.zero x); case N.compare; + rewrite N.spec_0; simpl. + intros HH; rewrite <- HH; rewrite N.spec_1; ring. + intros HH; rewrite N.spec_pred; auto with zarith. + generalize (N.spec_pos x); auto with zarith. + Qed. + + Definition add x y := + match x, y with + | Pos nx, Pos ny => Pos (N.add nx ny) + | Pos nx, Neg ny => + match N.compare nx ny with + | Gt => Pos (N.sub nx ny) + | Eq => zero + | Lt => Neg (N.sub ny nx) + end + | Neg nx, Pos ny => + match N.compare nx ny with + | Gt => Neg (N.sub nx ny) + | Eq => zero + | Lt => Pos (N.sub ny nx) + end + | Neg nx, Neg ny => Neg (N.add nx ny) + end. + + Theorem spec_add: forall x y, to_Z (add x y) = to_Z x + to_Z y. + unfold add, to_Z; intros [x | x] [y | y]. + exact (N.spec_add x y). + unfold zero; generalize (N.spec_compare x y); case N.compare. + rewrite N.spec_0; auto with zarith. + intros; rewrite N.spec_sub; try ring; auto with zarith. + intros; rewrite N.spec_sub; try ring; auto with zarith. + unfold zero; generalize (N.spec_compare x y); case N.compare. + rewrite N.spec_0; auto with zarith. + intros; rewrite N.spec_sub; try ring; auto with zarith. + intros; rewrite N.spec_sub; try ring; auto with zarith. + intros; rewrite N.spec_add; try ring; auto with zarith. + Qed. + + Definition pred x := + match x with + | Pos nx => + match N.compare N.zero nx with + | Lt => Pos (N.pred nx) + | _ => minus_one + end + | Neg nx => Neg (N.succ nx) + end. + + Theorem spec_pred: forall x, to_Z (pred x) = to_Z x - 1. + unfold pred, to_Z, minus_one; intros [x | x]. + generalize (N.spec_compare N.zero x); case N.compare; + rewrite N.spec_0; try rewrite N.spec_1; auto with zarith. + intros H; exact (N.spec_pred _ H). + generalize (N.spec_pos x); auto with zarith. + rewrite N.spec_succ; ring. + Qed. + + Definition sub x y := + match x, y with + | Pos nx, Pos ny => + match N.compare nx ny with + | Gt => Pos (N.sub nx ny) + | Eq => zero + | Lt => Neg (N.sub ny nx) + end + | Pos nx, Neg ny => Pos (N.add nx ny) + | Neg nx, Pos ny => Neg (N.add nx ny) + | Neg nx, Neg ny => + match N.compare nx ny with + | Gt => Neg (N.sub nx ny) + | Eq => zero + | Lt => Pos (N.sub ny nx) + end + end. + + Theorem spec_sub: forall x y, to_Z (sub x y) = to_Z x - to_Z y. + unfold sub, to_Z; intros [x | x] [y | y]. + unfold zero; generalize (N.spec_compare x y); case N.compare. + rewrite N.spec_0; auto with zarith. + intros; rewrite N.spec_sub; try ring; auto with zarith. + intros; rewrite N.spec_sub; try ring; auto with zarith. + rewrite N.spec_add; ring. + rewrite N.spec_add; ring. + unfold zero; generalize (N.spec_compare x y); case N.compare. + rewrite N.spec_0; auto with zarith. + intros; rewrite N.spec_sub; try ring; auto with zarith. + intros; rewrite N.spec_sub; try ring; auto with zarith. + Qed. + + Definition mul x y := + match x, y with + | Pos nx, Pos ny => Pos (N.mul nx ny) + | Pos nx, Neg ny => Neg (N.mul nx ny) + | Neg nx, Pos ny => Neg (N.mul nx ny) + | Neg nx, Neg ny => Pos (N.mul nx ny) + end. + + + Theorem spec_mul: forall x y, to_Z (mul x y) = to_Z x * to_Z y. + unfold mul, to_Z; intros [x | x] [y | y]; rewrite N.spec_mul; ring. + Qed. + + Definition square x := + match x with + | Pos nx => Pos (N.square nx) + | Neg nx => Pos (N.square nx) + end. + + Theorem spec_square: forall x, to_Z (square x) = to_Z x * to_Z x. + unfold square, to_Z; intros [x | x]; rewrite N.spec_square; ring. + Qed. + + Definition power_pos x p := + match x with + | Pos nx => Pos (N.power_pos nx p) + | Neg nx => + match p with + | xH => x + | xO _ => Pos (N.power_pos nx p) + | xI _ => Neg (N.power_pos nx p) + end + end. + + Theorem spec_power_pos: forall x n, to_Z (power_pos x n) = to_Z x ^ Zpos n. + assert (F0: forall x, (-x)^2 = x^2). + intros x; rewrite Zpower_2; ring. + unfold power_pos, to_Z; intros [x | x] [p | p |]; + try rewrite N.spec_power_pos; try ring. + assert (F: 0 <= 2 * Zpos p). + assert (0 <= Zpos p); auto with zarith. + rewrite Zpos_xI; repeat rewrite Zpower_exp; auto with zarith. + repeat rewrite Zpower_mult; auto with zarith. + rewrite F0; ring. + assert (F: 0 <= 2 * Zpos p). + assert (0 <= Zpos p); auto with zarith. + rewrite Zpos_xO; repeat rewrite Zpower_exp; auto with zarith. + repeat rewrite Zpower_mult; auto with zarith. + rewrite F0; ring. + Qed. + + Definition sqrt x := + match x with + | Pos nx => Pos (N.sqrt nx) + | Neg nx => Neg N.zero + end. + + + Theorem spec_sqrt: forall x, 0 <= to_Z x -> + to_Z (sqrt x) ^ 2 <= to_Z x < (to_Z (sqrt x) + 1) ^ 2. + unfold to_Z, sqrt; intros [x | x] H. + exact (N.spec_sqrt x). + replace (N.to_Z x) with 0. + rewrite N.spec_0; simpl Zpower; unfold Zpower_pos, iter_pos; + auto with zarith. + generalize (N.spec_pos x); auto with zarith. + Qed. + + Definition div_eucl x y := + match x, y with + | Pos nx, Pos ny => + let (q, r) := N.div_eucl nx ny in + (Pos q, Pos r) + | Pos nx, Neg ny => + let (q, r) := N.div_eucl nx ny in + match N.compare N.zero r with + | Eq => (Neg q, zero) + | _ => (Neg (N.succ q), Neg (N.sub ny r)) + end + | Neg nx, Pos ny => + let (q, r) := N.div_eucl nx ny in + match N.compare N.zero r with + | Eq => (Neg q, zero) + | _ => (Neg (N.succ q), Pos (N.sub ny r)) + end + | Neg nx, Neg ny => + let (q, r) := N.div_eucl nx ny in + (Pos q, Neg r) + end. + + + Theorem spec_div_eucl: forall x y, + to_Z y <> 0 -> + let (q,r) := div_eucl x y in + (to_Z q, to_Z r) = Zdiv_eucl (to_Z x) (to_Z y). + unfold div_eucl, to_Z; intros [x | x] [y | y] H. + assert (H1: 0 < N.to_Z y). + generalize (N.spec_pos y); auto with zarith. + generalize (N.spec_div_eucl x y H1); case N.div_eucl; auto. + assert (HH: 0 < N.to_Z y). + generalize (N.spec_pos y); auto with zarith. + generalize (N.spec_div_eucl x y HH); case N.div_eucl; auto. + intros q r; generalize (N.spec_pos x) HH; unfold Zdiv_eucl; + case_eq (N.to_Z x); case_eq (N.to_Z y); + try (intros; apply False_ind; auto with zarith; fail). + intros p He1 He2 _ _ H1; injection H1; intros H2 H3. + generalize (N.spec_compare N.zero r); case N.compare; + unfold zero; rewrite N.spec_0; try rewrite H3; auto. + rewrite H2; intros; apply False_ind; auto with zarith. + rewrite H2; intros; apply False_ind; auto with zarith. + intros p _ _ _ H1; discriminate H1. + intros p He p1 He1 H1 _. + generalize (N.spec_compare N.zero r); case N.compare. + change (- Zpos p) with (Zneg p). + unfold zero; lazy zeta. + rewrite N.spec_0; intros H2; rewrite <- H2. + intros H3; rewrite <- H3; auto. + rewrite N.spec_0; intros H2. + change (- Zpos p) with (Zneg p); lazy iota beta. + intros H3; rewrite <- H3; auto. + rewrite N.spec_succ; rewrite N.spec_sub. + generalize H2; case (N.to_Z r). + intros; apply False_ind; auto with zarith. + intros p2 _; rewrite He; auto with zarith. + change (Zneg p) with (- (Zpos p)); apply f_equal2 with (f := @pair Z Z); ring. + intros p2 H4; discriminate H4. + assert (N.to_Z r = (Zpos p1 mod (Zpos p))). + unfold Zmod, Zdiv_eucl; rewrite <- H3; auto. + case (Z_mod_lt (Zpos p1) (Zpos p)); auto with zarith. + rewrite N.spec_0; intros H2; generalize (N.spec_pos r); + intros; apply False_ind; auto with zarith. + assert (HH: 0 < N.to_Z y). + generalize (N.spec_pos y); auto with zarith. + generalize (N.spec_div_eucl x y HH); case N.div_eucl; auto. + intros q r; generalize (N.spec_pos x) HH; unfold Zdiv_eucl; + case_eq (N.to_Z x); case_eq (N.to_Z y); + try (intros; apply False_ind; auto with zarith; fail). + intros p He1 He2 _ _ H1; injection H1; intros H2 H3. + generalize (N.spec_compare N.zero r); case N.compare; + unfold zero; rewrite N.spec_0; try rewrite H3; auto. + rewrite H2; intros; apply False_ind; auto with zarith. + rewrite H2; intros; apply False_ind; auto with zarith. + intros p _ _ _ H1; discriminate H1. + intros p He p1 He1 H1 _. + generalize (N.spec_compare N.zero r); case N.compare. + change (- Zpos p1) with (Zneg p1). + unfold zero; lazy zeta. + rewrite N.spec_0; intros H2; rewrite <- H2. + intros H3; rewrite <- H3; auto. + rewrite N.spec_0; intros H2. + change (- Zpos p1) with (Zneg p1); lazy iota beta. + intros H3; rewrite <- H3; auto. + rewrite N.spec_succ; rewrite N.spec_sub. + generalize H2; case (N.to_Z r). + intros; apply False_ind; auto with zarith. + intros p2 _; rewrite He; auto with zarith. + intros p2 H4; discriminate H4. + assert (N.to_Z r = (Zpos p1 mod (Zpos p))). + unfold Zmod, Zdiv_eucl; rewrite <- H3; auto. + case (Z_mod_lt (Zpos p1) (Zpos p)); auto with zarith. + rewrite N.spec_0; generalize (N.spec_pos r); intros; apply False_ind; auto with zarith. + assert (H1: 0 < N.to_Z y). + generalize (N.spec_pos y); auto with zarith. + generalize (N.spec_div_eucl x y H1); case N.div_eucl; auto. + intros q r; generalize (N.spec_pos x) H1; unfold Zdiv_eucl; + case_eq (N.to_Z x); case_eq (N.to_Z y); + try (intros; apply False_ind; auto with zarith; fail). + change (-0) with 0; lazy iota beta; auto. + intros p _ _ _ _ H2; injection H2. + intros H3 H4; rewrite H3; rewrite H4; auto. + intros p _ _ _ H2; discriminate H2. + intros p He p1 He1 _ _ H2. + change (- Zpos p1) with (Zneg p1); lazy iota beta. + change (- Zpos p) with (Zneg p); lazy iota beta. + rewrite <- H2; auto. + Qed. + + Definition div x y := fst (div_eucl x y). + + Definition spec_div: forall x y, + to_Z y <> 0 -> to_Z (div x y) = to_Z x / to_Z y. + intros x y H1; generalize (spec_div_eucl x y H1); unfold div, Zdiv. + case div_eucl; case Zdiv_eucl; simpl; auto. + intros q r q11 r1 H; injection H; auto. + Qed. + + Definition modulo x y := snd (div_eucl x y). + + Theorem spec_modulo: + forall x y, to_Z y <> 0 -> to_Z (modulo x y) = to_Z x mod to_Z y. + intros x y H1; generalize (spec_div_eucl x y H1); unfold modulo, Zmod. + case div_eucl; case Zdiv_eucl; simpl; auto. + intros q r q11 r1 H; injection H; auto. + Qed. + + Definition gcd x y := + match x, y with + | Pos nx, Pos ny => Pos (N.gcd nx ny) + | Pos nx, Neg ny => Pos (N.gcd nx ny) + | Neg nx, Pos ny => Pos (N.gcd nx ny) + | Neg nx, Neg ny => Pos (N.gcd nx ny) + end. + + Theorem spec_gcd: forall a b, to_Z (gcd a b) = Zgcd (to_Z a) (to_Z b). + unfold gcd, Zgcd, to_Z; intros [x | x] [y | y]; rewrite N.spec_gcd; unfold Zgcd; + auto; case N.to_Z; simpl; auto with zarith; + try rewrite Zabs_Zopp; auto; + case N.to_Z; simpl; auto with zarith. + Qed. + +End Make. diff --git a/theories/Numbers/Integer/Binary/ZBinary.v b/theories/Numbers/Integer/Binary/ZBinary.v new file mode 100644 index 00000000..66d2a96a --- /dev/null +++ b/theories/Numbers/Integer/Binary/ZBinary.v @@ -0,0 +1,249 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: ZBinary.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Import ZMulOrder. +Require Import ZArith. + +Open Local Scope Z_scope. + +Module ZBinAxiomsMod <: ZAxiomsSig. +Module Export NZOrdAxiomsMod <: NZOrdAxiomsSig. +Module Export NZAxiomsMod <: NZAxiomsSig. + +Definition NZ := Z. +Definition NZeq := (@eq Z). +Definition NZ0 := 0. +Definition NZsucc := Zsucc'. +Definition NZpred := Zpred'. +Definition NZadd := Zplus. +Definition NZsub := Zminus. +Definition NZmul := Zmult. + +Theorem NZeq_equiv : equiv Z NZeq. +Proof. +exact (@eq_equiv Z). +Qed. + +Add Relation Z NZeq + reflexivity proved by (proj1 NZeq_equiv) + symmetry proved by (proj2 (proj2 NZeq_equiv)) + transitivity proved by (proj1 (proj2 NZeq_equiv)) +as NZeq_rel. + +Add Morphism NZsucc with signature NZeq ==> NZeq as NZsucc_wd. +Proof. +congruence. +Qed. + +Add Morphism NZpred with signature NZeq ==> NZeq as NZpred_wd. +Proof. +congruence. +Qed. + +Add Morphism NZadd with signature NZeq ==> NZeq ==> NZeq as NZadd_wd. +Proof. +congruence. +Qed. + +Add Morphism NZsub with signature NZeq ==> NZeq ==> NZeq as NZsub_wd. +Proof. +congruence. +Qed. + +Add Morphism NZmul with signature NZeq ==> NZeq ==> NZeq as NZmul_wd. +Proof. +congruence. +Qed. + +Theorem NZpred_succ : forall n : Z, NZpred (NZsucc n) = n. +Proof. +exact Zpred'_succ'. +Qed. + +Theorem NZinduction : + forall A : Z -> Prop, predicate_wd NZeq A -> + A 0 -> (forall n : Z, A n <-> A (NZsucc n)) -> forall n : Z, A n. +Proof. +intros A A_wd A0 AS n; apply Zind; clear n. +assumption. +intros; now apply -> AS. +intros n H. rewrite <- (Zsucc'_pred' n) in H. now apply <- AS. +Qed. + +Theorem NZadd_0_l : forall n : Z, 0 + n = n. +Proof. +exact Zplus_0_l. +Qed. + +Theorem NZadd_succ_l : forall n m : Z, (NZsucc n) + m = NZsucc (n + m). +Proof. +intros; do 2 rewrite <- Zsucc_succ'; apply Zplus_succ_l. +Qed. + +Theorem NZsub_0_r : forall n : Z, n - 0 = n. +Proof. +exact Zminus_0_r. +Qed. + +Theorem NZsub_succ_r : forall n m : Z, n - (NZsucc m) = NZpred (n - m). +Proof. +intros; rewrite <- Zsucc_succ'; rewrite <- Zpred_pred'; +apply Zminus_succ_r. +Qed. + +Theorem NZmul_0_l : forall n : Z, 0 * n = 0. +Proof. +reflexivity. +Qed. + +Theorem NZmul_succ_l : forall n m : Z, (NZsucc n) * m = n * m + m. +Proof. +intros; rewrite <- Zsucc_succ'; apply Zmult_succ_l. +Qed. + +End NZAxiomsMod. + +Definition NZlt := Zlt. +Definition NZle := Zle. +Definition NZmin := Zmin. +Definition NZmax := Zmax. + +Add Morphism NZlt with signature NZeq ==> NZeq ==> iff as NZlt_wd. +Proof. +unfold NZeq. intros n1 n2 H1 m1 m2 H2; rewrite H1; now rewrite H2. +Qed. + +Add Morphism NZle with signature NZeq ==> NZeq ==> iff as NZle_wd. +Proof. +unfold NZeq. intros n1 n2 H1 m1 m2 H2; rewrite H1; now rewrite H2. +Qed. + +Add Morphism NZmin with signature NZeq ==> NZeq ==> NZeq as NZmin_wd. +Proof. +congruence. +Qed. + +Add Morphism NZmax with signature NZeq ==> NZeq ==> NZeq as NZmax_wd. +Proof. +congruence. +Qed. + +Theorem NZlt_eq_cases : forall n m : Z, n <= m <-> n < m \/ n = m. +Proof. +intros n m; split. apply Zle_lt_or_eq. +intro H; destruct H as [H | H]. now apply Zlt_le_weak. rewrite H; apply Zle_refl. +Qed. + +Theorem NZlt_irrefl : forall n : Z, ~ n < n. +Proof. +exact Zlt_irrefl. +Qed. + +Theorem NZlt_succ_r : forall n m : Z, n < (NZsucc m) <-> n <= m. +Proof. +intros; unfold NZsucc; rewrite <- Zsucc_succ'; split; +[apply Zlt_succ_le | apply Zle_lt_succ]. +Qed. + +Theorem NZmin_l : forall n m : NZ, n <= m -> NZmin n m = n. +Proof. +unfold NZmin, Zmin, Zle; intros n m H. +destruct (n ?= m); try reflexivity. now elim H. +Qed. + +Theorem NZmin_r : forall n m : NZ, m <= n -> NZmin n m = m. +Proof. +unfold NZmin, Zmin, Zle; intros n m H. +case_eq (n ?= m); intro H1; try reflexivity. +now apply Zcompare_Eq_eq. +apply <- Zcompare_Gt_Lt_antisym in H1. now elim H. +Qed. + +Theorem NZmax_l : forall n m : NZ, m <= n -> NZmax n m = n. +Proof. +unfold NZmax, Zmax, Zle; intros n m H. +case_eq (n ?= m); intro H1; try reflexivity. +apply <- Zcompare_Gt_Lt_antisym in H1. now elim H. +Qed. + +Theorem NZmax_r : forall n m : NZ, n <= m -> NZmax n m = m. +Proof. +unfold NZmax, Zmax, Zle; intros n m H. +case_eq (n ?= m); intro H1. +now apply Zcompare_Eq_eq. reflexivity. now elim H. +Qed. + +End NZOrdAxiomsMod. + +Definition Zopp (x : Z) := +match x with +| Z0 => Z0 +| Zpos x => Zneg x +| Zneg x => Zpos x +end. + +Add Morphism Zopp with signature NZeq ==> NZeq as Zopp_wd. +Proof. +congruence. +Qed. + +Theorem Zsucc_pred : forall n : Z, NZsucc (NZpred n) = n. +Proof. +exact Zsucc'_pred'. +Qed. + +Theorem Zopp_0 : - 0 = 0. +Proof. +reflexivity. +Qed. + +Theorem Zopp_succ : forall n : Z, - (NZsucc n) = NZpred (- n). +Proof. +intro; rewrite <- Zsucc_succ'; rewrite <- Zpred_pred'. apply Zopp_succ. +Qed. + +End ZBinAxiomsMod. + +Module Export ZBinMulOrderPropMod := ZMulOrderPropFunct ZBinAxiomsMod. + +(** Z forms a ring *) + +(*Lemma Zring : ring_theory 0 1 NZadd NZmul NZsub Zopp NZeq. +Proof. +constructor. +exact Zadd_0_l. +exact Zadd_comm. +exact Zadd_assoc. +exact Zmul_1_l. +exact Zmul_comm. +exact Zmul_assoc. +exact Zmul_add_distr_r. +intros; now rewrite Zadd_opp_minus. +exact Zadd_opp_r. +Qed. + +Add Ring ZR : Zring.*) + + + +(* +Theorem eq_equiv_e : forall x y : Z, E x y <-> e x y. +Proof. +intros x y; unfold E, e, Zeq_bool; split; intro H. +rewrite H; now rewrite Zcompare_refl. +rewrite eq_true_unfold_pos in H. +assert (H1 : (x ?= y) = Eq). +case_eq (x ?= y); intro H1; rewrite H1 in H; simpl in H; +[reflexivity | discriminate H | discriminate H]. +now apply Zcompare_Eq_eq. +Qed. +*) diff --git a/theories/Numbers/Integer/NatPairs/ZNatPairs.v b/theories/Numbers/Integer/NatPairs/ZNatPairs.v new file mode 100644 index 00000000..8b3d815d --- /dev/null +++ b/theories/Numbers/Integer/NatPairs/ZNatPairs.v @@ -0,0 +1,422 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: ZNatPairs.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Import NSub. (* The most complete file for natural numbers *) +Require Export ZMulOrder. (* The most complete file for integers *) +Require Export Ring. + +Module ZPairsAxiomsMod (Import NAxiomsMod : NAxiomsSig) <: ZAxiomsSig. +Module Import NPropMod := NSubPropFunct NAxiomsMod. (* Get all properties of natural numbers *) + +(* We do not declare ring in Natural/Abstract for two reasons. First, some +of the properties proved in NAdd and NMul are used in the new BinNat, +and it is in turn used in Ring. Using ring in Natural/Abstract would be +circular. It is possible, however, not to make BinNat dependent on +Numbers/Natural and prove the properties necessary for ring from scratch +(this is, of course, how it used to be). In addition, if we define semiring +structures in the implementation subdirectories of Natural, we are able to +specify binary natural numbers as the type of coefficients. For these +reasons we define an abstract semiring here. *) + +Open Local Scope NatScope. + +Lemma Nsemi_ring : semi_ring_theory 0 1 add mul Neq. +Proof. +constructor. +exact add_0_l. +exact add_comm. +exact add_assoc. +exact mul_1_l. +exact mul_0_l. +exact mul_comm. +exact mul_assoc. +exact mul_add_distr_r. +Qed. + +Add Ring NSR : Nsemi_ring. + +(* The definitios of functions (NZadd, NZmul, etc.) will be unfolded by +the properties functor. Since we don't want Zadd_comm to refer to unfolded +definitions of equality: fun p1 p2 : NZ => (fst p1 + snd p2) = (fst p2 + snd p1), +we will provide an extra layer of definitions. *) + +Definition Z := (N * N)%type. +Definition Z0 : Z := (0, 0). +Definition Zeq (p1 p2 : Z) := ((fst p1) + (snd p2) == (fst p2) + (snd p1)). +Definition Zsucc (n : Z) : Z := (S (fst n), snd n). +Definition Zpred (n : Z) : Z := (fst n, S (snd n)). + +(* We do not have Zpred (Zsucc n) = n but only Zpred (Zsucc n) == n. It +could be possible to consider as canonical only pairs where one of the +elements is 0, and make all operations convert canonical values into other +canonical values. In that case, we could get rid of setoids and arrive at +integers as signed natural numbers. *) + +Definition Zadd (n m : Z) : Z := ((fst n) + (fst m), (snd n) + (snd m)). +Definition Zsub (n m : Z) : Z := ((fst n) + (snd m), (snd n) + (fst m)). + +(* Unfortunately, the elements of the pair keep increasing, even during +subtraction *) + +Definition Zmul (n m : Z) : Z := + ((fst n) * (fst m) + (snd n) * (snd m), (fst n) * (snd m) + (snd n) * (fst m)). +Definition Zlt (n m : Z) := (fst n) + (snd m) < (fst m) + (snd n). +Definition Zle (n m : Z) := (fst n) + (snd m) <= (fst m) + (snd n). +Definition Zmin (n m : Z) := (min ((fst n) + (snd m)) ((fst m) + (snd n)), (snd n) + (snd m)). +Definition Zmax (n m : Z) := (max ((fst n) + (snd m)) ((fst m) + (snd n)), (snd n) + (snd m)). + +Delimit Scope IntScope with Int. +Bind Scope IntScope with Z. +Notation "x == y" := (Zeq x y) (at level 70) : IntScope. +Notation "x ~= y" := (~ Zeq x y) (at level 70) : IntScope. +Notation "0" := Z0 : IntScope. +Notation "1" := (Zsucc Z0) : IntScope. +Notation "x + y" := (Zadd x y) : IntScope. +Notation "x - y" := (Zsub x y) : IntScope. +Notation "x * y" := (Zmul x y) : IntScope. +Notation "x < y" := (Zlt x y) : IntScope. +Notation "x <= y" := (Zle x y) : IntScope. +Notation "x > y" := (Zlt y x) (only parsing) : IntScope. +Notation "x >= y" := (Zle y x) (only parsing) : IntScope. + +Notation Local N := NZ. +(* To remember N without having to use a long qualifying name. since NZ will be redefined *) +Notation Local NE := NZeq (only parsing). +Notation Local add_wd := NZadd_wd (only parsing). + +Module Export NZOrdAxiomsMod <: NZOrdAxiomsSig. +Module Export NZAxiomsMod <: NZAxiomsSig. + +Definition NZ : Type := Z. +Definition NZeq := Zeq. +Definition NZ0 := Z0. +Definition NZsucc := Zsucc. +Definition NZpred := Zpred. +Definition NZadd := Zadd. +Definition NZsub := Zsub. +Definition NZmul := Zmul. + +Theorem ZE_refl : reflexive Z Zeq. +Proof. +unfold reflexive, Zeq. reflexivity. +Qed. + +Theorem ZE_symm : symmetric Z Zeq. +Proof. +unfold symmetric, Zeq; now symmetry. +Qed. + +Theorem ZE_trans : transitive Z Zeq. +Proof. +unfold transitive, Zeq. intros n m p H1 H2. +assert (H3 : (fst n + snd m) + (fst m + snd p) == (fst m + snd n) + (fst p + snd m)) +by now apply add_wd. +stepl ((fst n + snd p) + (fst m + snd m)) in H3 by ring. +stepr ((fst p + snd n) + (fst m + snd m)) in H3 by ring. +now apply -> add_cancel_r in H3. +Qed. + +Theorem NZeq_equiv : equiv Z Zeq. +Proof. +unfold equiv; repeat split; [apply ZE_refl | apply ZE_trans | apply ZE_symm]. +Qed. + +Add Relation Z Zeq + reflexivity proved by (proj1 NZeq_equiv) + symmetry proved by (proj2 (proj2 NZeq_equiv)) + transitivity proved by (proj1 (proj2 NZeq_equiv)) +as NZeq_rel. + +Add Morphism (@pair N N) with signature NE ==> NE ==> Zeq as Zpair_wd. +Proof. +intros n1 n2 H1 m1 m2 H2; unfold Zeq; simpl; rewrite H1; now rewrite H2. +Qed. + +Add Morphism NZsucc with signature Zeq ==> Zeq as NZsucc_wd. +Proof. +unfold NZsucc, Zeq; intros n m H; simpl. +do 2 rewrite add_succ_l; now rewrite H. +Qed. + +Add Morphism NZpred with signature Zeq ==> Zeq as NZpred_wd. +Proof. +unfold NZpred, Zeq; intros n m H; simpl. +do 2 rewrite add_succ_r; now rewrite H. +Qed. + +Add Morphism NZadd with signature Zeq ==> Zeq ==> Zeq as NZadd_wd. +Proof. +unfold Zeq, NZadd; intros n1 m1 H1 n2 m2 H2; simpl. +assert (H3 : (fst n1 + snd m1) + (fst n2 + snd m2) == (fst m1 + snd n1) + (fst m2 + snd n2)) +by now apply add_wd. +stepl (fst n1 + snd m1 + (fst n2 + snd m2)) by ring. +now stepr (fst m1 + snd n1 + (fst m2 + snd n2)) by ring. +Qed. + +Add Morphism NZsub with signature Zeq ==> Zeq ==> Zeq as NZsub_wd. +Proof. +unfold Zeq, NZsub; intros n1 m1 H1 n2 m2 H2; simpl. +symmetry in H2. +assert (H3 : (fst n1 + snd m1) + (fst m2 + snd n2) == (fst m1 + snd n1) + (fst n2 + snd m2)) +by now apply add_wd. +stepl (fst n1 + snd m1 + (fst m2 + snd n2)) by ring. +now stepr (fst m1 + snd n1 + (fst n2 + snd m2)) by ring. +Qed. + +Add Morphism NZmul with signature Zeq ==> Zeq ==> Zeq as NZmul_wd. +Proof. +unfold NZmul, Zeq; intros n1 m1 H1 n2 m2 H2; simpl. +stepl (fst n1 * fst n2 + (snd n1 * snd n2 + fst m1 * snd m2 + snd m1 * fst m2)) by ring. +stepr (fst n1 * snd n2 + (fst m1 * fst m2 + snd m1 * snd m2 + snd n1 * fst n2)) by ring. +apply add_mul_repl_pair with (n := fst m2) (m := snd m2); [| now idtac]. +stepl (snd n1 * snd n2 + (fst n1 * fst m2 + fst m1 * snd m2 + snd m1 * fst m2)) by ring. +stepr (snd n1 * fst n2 + (fst n1 * snd m2 + fst m1 * fst m2 + snd m1 * snd m2)) by ring. +apply add_mul_repl_pair with (n := snd m2) (m := fst m2); +[| (stepl (fst n2 + snd m2) by ring); now stepr (fst m2 + snd n2) by ring]. +stepl (snd m2 * snd n1 + (fst n1 * fst m2 + fst m1 * snd m2 + snd m1 * fst m2)) by ring. +stepr (snd m2 * fst n1 + (snd n1 * fst m2 + fst m1 * fst m2 + snd m1 * snd m2)) by ring. +apply add_mul_repl_pair with (n := snd m1) (m := fst m1); +[ | (stepl (fst n1 + snd m1) by ring); now stepr (fst m1 + snd n1) by ring]. +stepl (fst m2 * fst n1 + (snd m2 * snd m1 + fst m1 * snd m2 + snd m1 * fst m2)) by ring. +stepr (fst m2 * snd n1 + (snd m2 * fst m1 + fst m1 * fst m2 + snd m1 * snd m2)) by ring. +apply add_mul_repl_pair with (n := fst m1) (m := snd m1); [| now idtac]. +ring. +Qed. + +Section Induction. +Open Scope NatScope. (* automatically closes at the end of the section *) +Variable A : Z -> Prop. +Hypothesis A_wd : predicate_wd Zeq A. + +Add Morphism A with signature Zeq ==> iff as A_morph. +Proof. +exact A_wd. +Qed. + +Theorem NZinduction : + A 0 -> (forall n : Z, A n <-> A (Zsucc n)) -> forall n : Z, A n. (* 0 is interpreted as in Z due to "Bind" directive *) +Proof. +intros A0 AS n; unfold NZ0, Zsucc, predicate_wd, fun_wd, Zeq in *. +destruct n as [n m]. +cut (forall p : N, A (p, 0)); [intro H1 |]. +cut (forall p : N, A (0, p)); [intro H2 |]. +destruct (add_dichotomy n m) as [[p H] | [p H]]. +rewrite (A_wd (n, m) (0, p)) by (rewrite add_0_l; now rewrite add_comm). +apply H2. +rewrite (A_wd (n, m) (p, 0)) by now rewrite add_0_r. apply H1. +induct p. assumption. intros p IH. +apply -> (A_wd (0, p) (1, S p)) in IH; [| now rewrite add_0_l, add_1_l]. +now apply <- AS. +induct p. assumption. intros p IH. +replace 0 with (snd (p, 0)); [| reflexivity]. +replace (S p) with (S (fst (p, 0))); [| reflexivity]. now apply -> AS. +Qed. + +End Induction. + +(* Time to prove theorems in the language of Z *) + +Open Local Scope IntScope. + +Theorem NZpred_succ : forall n : Z, Zpred (Zsucc n) == n. +Proof. +unfold NZpred, NZsucc, Zeq; intro n; simpl. +rewrite add_succ_l; now rewrite add_succ_r. +Qed. + +Theorem NZadd_0_l : forall n : Z, 0 + n == n. +Proof. +intro n; unfold NZadd, Zeq; simpl. now do 2 rewrite add_0_l. +Qed. + +Theorem NZadd_succ_l : forall n m : Z, (Zsucc n) + m == Zsucc (n + m). +Proof. +intros n m; unfold NZadd, Zeq; simpl. now do 2 rewrite add_succ_l. +Qed. + +Theorem NZsub_0_r : forall n : Z, n - 0 == n. +Proof. +intro n; unfold NZsub, Zeq; simpl. now do 2 rewrite add_0_r. +Qed. + +Theorem NZsub_succ_r : forall n m : Z, n - (Zsucc m) == Zpred (n - m). +Proof. +intros n m; unfold NZsub, Zeq; simpl. symmetry; now rewrite add_succ_r. +Qed. + +Theorem NZmul_0_l : forall n : Z, 0 * n == 0. +Proof. +intro n; unfold NZmul, Zeq; simpl. +repeat rewrite mul_0_l. now rewrite add_assoc. +Qed. + +Theorem NZmul_succ_l : forall n m : Z, (Zsucc n) * m == n * m + m. +Proof. +intros n m; unfold NZmul, NZsucc, Zeq; simpl. +do 2 rewrite mul_succ_l. ring. +Qed. + +End NZAxiomsMod. + +Definition NZlt := Zlt. +Definition NZle := Zle. +Definition NZmin := Zmin. +Definition NZmax := Zmax. + +Add Morphism NZlt with signature Zeq ==> Zeq ==> iff as NZlt_wd. +Proof. +unfold NZlt, Zlt, Zeq; intros n1 m1 H1 n2 m2 H2; simpl. split; intro H. +stepr (snd m1 + fst m2) by apply add_comm. +apply (add_lt_repl_pair (fst n1) (snd n1)); [| assumption]. +stepl (snd m2 + fst n1) by apply add_comm. +stepr (fst m2 + snd n1) by apply add_comm. +apply (add_lt_repl_pair (snd n2) (fst n2)). +now stepl (fst n1 + snd n2) by apply add_comm. +stepl (fst m2 + snd n2) by apply add_comm. now stepr (fst n2 + snd m2) by apply add_comm. +stepr (snd n1 + fst n2) by apply add_comm. +apply (add_lt_repl_pair (fst m1) (snd m1)); [| now symmetry]. +stepl (snd n2 + fst m1) by apply add_comm. +stepr (fst n2 + snd m1) by apply add_comm. +apply (add_lt_repl_pair (snd m2) (fst m2)). +now stepl (fst m1 + snd m2) by apply add_comm. +stepl (fst n2 + snd m2) by apply add_comm. now stepr (fst m2 + snd n2) by apply add_comm. +Qed. + +Add Morphism NZle with signature Zeq ==> Zeq ==> iff as NZle_wd. +Proof. +unfold NZle, Zle, Zeq; intros n1 m1 H1 n2 m2 H2; simpl. +do 2 rewrite lt_eq_cases. rewrite (NZlt_wd n1 m1 H1 n2 m2 H2). fold (m1 < m2)%Int. +fold (n1 == n2)%Int (m1 == m2)%Int; fold (n1 == m1)%Int in H1; fold (n2 == m2)%Int in H2. +now rewrite H1, H2. +Qed. + +Add Morphism NZmin with signature Zeq ==> Zeq ==> Zeq as NZmin_wd. +Proof. +intros n1 m1 H1 n2 m2 H2; unfold NZmin, Zeq; simpl. +destruct (le_ge_cases (fst n1 + snd n2) (fst n2 + snd n1)) as [H | H]. +rewrite (min_l (fst n1 + snd n2) (fst n2 + snd n1)) by assumption. +rewrite (min_l (fst m1 + snd m2) (fst m2 + snd m1)) by +now apply -> (NZle_wd n1 m1 H1 n2 m2 H2). +stepl ((fst n1 + snd m1) + (snd n2 + snd m2)) by ring. +unfold Zeq in H1. rewrite H1. ring. +rewrite (min_r (fst n1 + snd n2) (fst n2 + snd n1)) by assumption. +rewrite (min_r (fst m1 + snd m2) (fst m2 + snd m1)) by +now apply -> (NZle_wd n2 m2 H2 n1 m1 H1). +stepl ((fst n2 + snd m2) + (snd n1 + snd m1)) by ring. +unfold Zeq in H2. rewrite H2. ring. +Qed. + +Add Morphism NZmax with signature Zeq ==> Zeq ==> Zeq as NZmax_wd. +Proof. +intros n1 m1 H1 n2 m2 H2; unfold NZmax, Zeq; simpl. +destruct (le_ge_cases (fst n1 + snd n2) (fst n2 + snd n1)) as [H | H]. +rewrite (max_r (fst n1 + snd n2) (fst n2 + snd n1)) by assumption. +rewrite (max_r (fst m1 + snd m2) (fst m2 + snd m1)) by +now apply -> (NZle_wd n1 m1 H1 n2 m2 H2). +stepl ((fst n2 + snd m2) + (snd n1 + snd m1)) by ring. +unfold Zeq in H2. rewrite H2. ring. +rewrite (max_l (fst n1 + snd n2) (fst n2 + snd n1)) by assumption. +rewrite (max_l (fst m1 + snd m2) (fst m2 + snd m1)) by +now apply -> (NZle_wd n2 m2 H2 n1 m1 H1). +stepl ((fst n1 + snd m1) + (snd n2 + snd m2)) by ring. +unfold Zeq in H1. rewrite H1. ring. +Qed. + +Open Local Scope IntScope. + +Theorem NZlt_eq_cases : forall n m : Z, n <= m <-> n < m \/ n == m. +Proof. +intros n m; unfold Zlt, Zle, Zeq; simpl. apply lt_eq_cases. +Qed. + +Theorem NZlt_irrefl : forall n : Z, ~ (n < n). +Proof. +intros n; unfold Zlt, Zeq; simpl. apply lt_irrefl. +Qed. + +Theorem NZlt_succ_r : forall n m : Z, n < (Zsucc m) <-> n <= m. +Proof. +intros n m; unfold Zlt, Zle, Zeq; simpl. rewrite add_succ_l; apply lt_succ_r. +Qed. + +Theorem NZmin_l : forall n m : Z, n <= m -> Zmin n m == n. +Proof. +unfold Zmin, Zle, Zeq; simpl; intros n m H. +rewrite min_l by assumption. ring. +Qed. + +Theorem NZmin_r : forall n m : Z, m <= n -> Zmin n m == m. +Proof. +unfold Zmin, Zle, Zeq; simpl; intros n m H. +rewrite min_r by assumption. ring. +Qed. + +Theorem NZmax_l : forall n m : Z, m <= n -> Zmax n m == n. +Proof. +unfold Zmax, Zle, Zeq; simpl; intros n m H. +rewrite max_l by assumption. ring. +Qed. + +Theorem NZmax_r : forall n m : Z, n <= m -> Zmax n m == m. +Proof. +unfold Zmax, Zle, Zeq; simpl; intros n m H. +rewrite max_r by assumption. ring. +Qed. + +End NZOrdAxiomsMod. + +Definition Zopp (n : Z) : Z := (snd n, fst n). + +Notation "- x" := (Zopp x) : IntScope. + +Add Morphism Zopp with signature Zeq ==> Zeq as Zopp_wd. +Proof. +unfold Zeq; intros n m H; simpl. symmetry. +stepl (fst n + snd m) by apply add_comm. +now stepr (fst m + snd n) by apply add_comm. +Qed. + +Open Local Scope IntScope. + +Theorem Zsucc_pred : forall n : Z, Zsucc (Zpred n) == n. +Proof. +intro n; unfold Zsucc, Zpred, Zeq; simpl. +rewrite add_succ_l; now rewrite add_succ_r. +Qed. + +Theorem Zopp_0 : - 0 == 0. +Proof. +unfold Zopp, Zeq; simpl. now rewrite add_0_l. +Qed. + +Theorem Zopp_succ : forall n, - (Zsucc n) == Zpred (- n). +Proof. +reflexivity. +Qed. + +End ZPairsAxiomsMod. + +(* For example, let's build integers out of pairs of Peano natural numbers +and get their properties *) + +(* The following lines increase the compilation time at least twice *) +(* +Require Import NPeano. + +Module Export ZPairsPeanoAxiomsMod := ZPairsAxiomsMod NPeanoAxiomsMod. +Module Export ZPairsMulOrderPropMod := ZMulOrderPropFunct ZPairsPeanoAxiomsMod. + +Open Local Scope IntScope. + +Eval compute in (3, 5) * (4, 6). +*) + diff --git a/theories/Numbers/Integer/SpecViaZ/ZSig.v b/theories/Numbers/Integer/SpecViaZ/ZSig.v new file mode 100644 index 00000000..0af98c74 --- /dev/null +++ b/theories/Numbers/Integer/SpecViaZ/ZSig.v @@ -0,0 +1,117 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: ZSig.v 11027 2008-06-01 13:28:59Z letouzey $ i*) + +Require Import ZArith Znumtheory. + +Open Scope Z_scope. + +(** * ZSig *) + +(** Interface of a rich structure about integers. + Specifications are written via translation to Z. +*) + +Module Type ZType. + + Parameter t : Type. + + Parameter to_Z : t -> Z. + Notation "[ x ]" := (to_Z x). + + Definition eq x y := ([x] = [y]). + + Parameter of_Z : Z -> t. + Parameter spec_of_Z: forall x, to_Z (of_Z x) = x. + + Parameter zero : t. + Parameter one : t. + Parameter minus_one : t. + + Parameter spec_0: [zero] = 0. + Parameter spec_1: [one] = 1. + Parameter spec_m1: [minus_one] = -1. + + Parameter compare : t -> t -> comparison. + + Parameter spec_compare: forall x y, + match compare x y with + | Eq => [x] = [y] + | Lt => [x] < [y] + | Gt => [x] > [y] + end. + + Definition lt n m := compare n m = Lt. + Definition le n m := compare n m <> Gt. + Definition min n m := match compare n m with Gt => m | _ => n end. + Definition max n m := match compare n m with Lt => m | _ => n end. + + Parameter eq_bool : t -> t -> bool. + + Parameter spec_eq_bool: forall x y, + if eq_bool x y then [x] = [y] else [x] <> [y]. + + Parameter succ : t -> t. + + Parameter spec_succ: forall n, [succ n] = [n] + 1. + + Parameter add : t -> t -> t. + + Parameter spec_add: forall x y, [add x y] = [x] + [y]. + + Parameter pred : t -> t. + + Parameter spec_pred: forall x, [pred x] = [x] - 1. + + Parameter sub : t -> t -> t. + + Parameter spec_sub: forall x y, [sub x y] = [x] - [y]. + + Parameter opp : t -> t. + + Parameter spec_opp: forall x, [opp x] = - [x]. + + Parameter mul : t -> t -> t. + + Parameter spec_mul: forall x y, [mul x y] = [x] * [y]. + + Parameter square : t -> t. + + Parameter spec_square: forall x, [square x] = [x] * [x]. + + Parameter power_pos : t -> positive -> t. + + Parameter spec_power_pos: forall x n, [power_pos x n] = [x] ^ Zpos n. + + Parameter sqrt : t -> t. + + Parameter spec_sqrt: forall x, 0 <= [x] -> + [sqrt x] ^ 2 <= [x] < ([sqrt x] + 1) ^ 2. + + Parameter div_eucl : t -> t -> t * t. + + Parameter spec_div_eucl: forall x y, [y] <> 0 -> + let (q,r) := div_eucl x y in ([q], [r]) = Zdiv_eucl [x] [y]. + + Parameter div : t -> t -> t. + + Parameter spec_div: forall x y, [y] <> 0 -> [div x y] = [x] / [y]. + + Parameter modulo : t -> t -> t. + + Parameter spec_modulo: forall x y, [y] <> 0 -> + [modulo x y] = [x] mod [y]. + + Parameter gcd : t -> t -> t. + + Parameter spec_gcd: forall a b, [gcd a b] = Zgcd (to_Z a) (to_Z b). + +End ZType. diff --git a/theories/Numbers/Integer/SpecViaZ/ZSigZAxioms.v b/theories/Numbers/Integer/SpecViaZ/ZSigZAxioms.v new file mode 100644 index 00000000..d7c56267 --- /dev/null +++ b/theories/Numbers/Integer/SpecViaZ/ZSigZAxioms.v @@ -0,0 +1,306 @@ +(************************************************************************) +(* 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: ZSigZAxioms.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Import ZArith. +Require Import ZAxioms. +Require Import ZSig. + +(** * The interface [ZSig.ZType] implies the interface [ZAxiomsSig] *) + +Module ZSig_ZAxioms (Z:ZType) <: ZAxiomsSig. + +Delimit Scope IntScope with Int. +Bind Scope IntScope with Z.t. +Open Local Scope IntScope. +Notation "[ x ]" := (Z.to_Z x) : IntScope. +Infix "==" := Z.eq (at level 70) : IntScope. +Notation "0" := Z.zero : IntScope. +Infix "+" := Z.add : IntScope. +Infix "-" := Z.sub : IntScope. +Infix "*" := Z.mul : IntScope. +Notation "- x" := (Z.opp x) : IntScope. + +Hint Rewrite + Z.spec_0 Z.spec_1 Z.spec_add Z.spec_sub Z.spec_pred Z.spec_succ + Z.spec_mul Z.spec_opp Z.spec_of_Z : Zspec. + +Ltac zsimpl := unfold Z.eq in *; autorewrite with Zspec. + +Module Export NZOrdAxiomsMod <: NZOrdAxiomsSig. +Module Export NZAxiomsMod <: NZAxiomsSig. + +Definition NZ := Z.t. +Definition NZeq := Z.eq. +Definition NZ0 := Z.zero. +Definition NZsucc := Z.succ. +Definition NZpred := Z.pred. +Definition NZadd := Z.add. +Definition NZsub := Z.sub. +Definition NZmul := Z.mul. + +Theorem NZeq_equiv : equiv Z.t Z.eq. +Proof. +repeat split; repeat red; intros; auto; congruence. +Qed. + +Add Relation Z.t Z.eq + reflexivity proved by (proj1 NZeq_equiv) + symmetry proved by (proj2 (proj2 NZeq_equiv)) + transitivity proved by (proj1 (proj2 NZeq_equiv)) + as NZeq_rel. + +Add Morphism NZsucc with signature Z.eq ==> Z.eq as NZsucc_wd. +Proof. +intros; zsimpl; f_equal; assumption. +Qed. + +Add Morphism NZpred with signature Z.eq ==> Z.eq as NZpred_wd. +Proof. +intros; zsimpl; f_equal; assumption. +Qed. + +Add Morphism NZadd with signature Z.eq ==> Z.eq ==> Z.eq as NZadd_wd. +Proof. +intros; zsimpl; f_equal; assumption. +Qed. + +Add Morphism NZsub with signature Z.eq ==> Z.eq ==> Z.eq as NZsub_wd. +Proof. +intros; zsimpl; f_equal; assumption. +Qed. + +Add Morphism NZmul with signature Z.eq ==> Z.eq ==> Z.eq as NZmul_wd. +Proof. +intros; zsimpl; f_equal; assumption. +Qed. + +Theorem NZpred_succ : forall n, Z.pred (Z.succ n) == n. +Proof. +intros; zsimpl; auto with zarith. +Qed. + +Section Induction. + +Variable A : Z.t -> Prop. +Hypothesis A_wd : predicate_wd Z.eq A. +Hypothesis A0 : A 0. +Hypothesis AS : forall n, A n <-> A (Z.succ n). + +Add Morphism A with signature Z.eq ==> iff as A_morph. +Proof. apply A_wd. Qed. + +Let B (z : Z) := A (Z.of_Z z). + +Lemma B0 : B 0. +Proof. +unfold B; simpl. +rewrite <- (A_wd 0); auto. +zsimpl; auto. +Qed. + +Lemma BS : forall z : Z, B z -> B (z + 1). +Proof. +intros z H. +unfold B in *. apply -> AS in H. +setoid_replace (Z.of_Z (z + 1)) with (Z.succ (Z.of_Z z)); auto. +zsimpl; auto. +Qed. + +Lemma BP : forall z : Z, B z -> B (z - 1). +Proof. +intros z H. +unfold B in *. rewrite AS. +setoid_replace (Z.succ (Z.of_Z (z - 1))) with (Z.of_Z z); auto. +zsimpl; auto with zarith. +Qed. + +Lemma B_holds : forall z : Z, B z. +Proof. +intros; destruct (Z_lt_le_dec 0 z). +apply natlike_ind; auto with zarith. +apply B0. +intros; apply BS; auto. +replace z with (-(-z))%Z in * by (auto with zarith). +remember (-z)%Z as z'. +pattern z'; apply natlike_ind. +apply B0. +intros; rewrite Zopp_succ; unfold Zpred; apply BP; auto. +subst z'; auto with zarith. +Qed. + +Theorem NZinduction : forall n, A n. +Proof. +intro n. setoid_replace n with (Z.of_Z (Z.to_Z n)). +apply B_holds. +zsimpl; auto. +Qed. + +End Induction. + +Theorem NZadd_0_l : forall n, 0 + n == n. +Proof. +intros; zsimpl; auto with zarith. +Qed. + +Theorem NZadd_succ_l : forall n m, (Z.succ n) + m == Z.succ (n + m). +Proof. +intros; zsimpl; auto with zarith. +Qed. + +Theorem NZsub_0_r : forall n, n - 0 == n. +Proof. +intros; zsimpl; auto with zarith. +Qed. + +Theorem NZsub_succ_r : forall n m, n - (Z.succ m) == Z.pred (n - m). +Proof. +intros; zsimpl; auto with zarith. +Qed. + +Theorem NZmul_0_l : forall n, 0 * n == 0. +Proof. +intros; zsimpl; auto with zarith. +Qed. + +Theorem NZmul_succ_l : forall n m, (Z.succ n) * m == n * m + m. +Proof. +intros; zsimpl; ring. +Qed. + +End NZAxiomsMod. + +Definition NZlt := Z.lt. +Definition NZle := Z.le. +Definition NZmin := Z.min. +Definition NZmax := Z.max. + +Infix "<=" := Z.le : IntScope. +Infix "<" := Z.lt : IntScope. + +Lemma spec_compare_alt : forall x y, Z.compare x y = ([x] ?= [y])%Z. +Proof. + intros; generalize (Z.spec_compare x y). + destruct (Z.compare x y); auto. + intros H; rewrite H; symmetry; apply Zcompare_refl. +Qed. + +Lemma spec_lt : forall x y, (x<y) <-> ([x]<[y])%Z. +Proof. + intros; unfold Z.lt, Zlt; rewrite spec_compare_alt; intuition. +Qed. + +Lemma spec_le : forall x y, (x<=y) <-> ([x]<=[y])%Z. +Proof. + intros; unfold Z.le, Zle; rewrite spec_compare_alt; intuition. +Qed. + +Lemma spec_min : forall x y, [Z.min x y] = Zmin [x] [y]. +Proof. + intros; unfold Z.min, Zmin. + rewrite spec_compare_alt; destruct Zcompare; auto. +Qed. + +Lemma spec_max : forall x y, [Z.max x y] = Zmax [x] [y]. +Proof. + intros; unfold Z.max, Zmax. + rewrite spec_compare_alt; destruct Zcompare; auto. +Qed. + +Add Morphism Z.compare with signature Z.eq ==> Z.eq ==> (@eq comparison) as compare_wd. +Proof. +intros x x' Hx y y' Hy. +rewrite 2 spec_compare_alt; rewrite Hx, Hy; intuition. +Qed. + +Add Morphism Z.lt with signature Z.eq ==> Z.eq ==> iff as NZlt_wd. +Proof. +intros x x' Hx y y' Hy; unfold Z.lt; rewrite Hx, Hy; intuition. +Qed. + +Add Morphism Z.le with signature Z.eq ==> Z.eq ==> iff as NZle_wd. +Proof. +intros x x' Hx y y' Hy; unfold Z.le; rewrite Hx, Hy; intuition. +Qed. + +Add Morphism Z.min with signature Z.eq ==> Z.eq ==> Z.eq as NZmin_wd. +Proof. +intros; red; rewrite 2 spec_min; congruence. +Qed. + +Add Morphism Z.max with signature Z.eq ==> Z.eq ==> Z.eq as NZmax_wd. +Proof. +intros; red; rewrite 2 spec_max; congruence. +Qed. + +Theorem NZlt_eq_cases : forall n m, n <= m <-> n < m \/ n == m. +Proof. +intros. +unfold Z.eq; rewrite spec_lt, spec_le; omega. +Qed. + +Theorem NZlt_irrefl : forall n, ~ n < n. +Proof. +intros; rewrite spec_lt; auto with zarith. +Qed. + +Theorem NZlt_succ_r : forall n m, n < (Z.succ m) <-> n <= m. +Proof. +intros; rewrite spec_lt, spec_le, Z.spec_succ; omega. +Qed. + +Theorem NZmin_l : forall n m, n <= m -> Z.min n m == n. +Proof. +intros n m; unfold Z.eq; rewrite spec_le, spec_min. +generalize (Zmin_spec [n] [m]); omega. +Qed. + +Theorem NZmin_r : forall n m, m <= n -> Z.min n m == m. +Proof. +intros n m; unfold Z.eq; rewrite spec_le, spec_min. +generalize (Zmin_spec [n] [m]); omega. +Qed. + +Theorem NZmax_l : forall n m, m <= n -> Z.max n m == n. +Proof. +intros n m; unfold Z.eq; rewrite spec_le, spec_max. +generalize (Zmax_spec [n] [m]); omega. +Qed. + +Theorem NZmax_r : forall n m, n <= m -> Z.max n m == m. +Proof. +intros n m; unfold Z.eq; rewrite spec_le, spec_max. +generalize (Zmax_spec [n] [m]); omega. +Qed. + +End NZOrdAxiomsMod. + +Definition Zopp := Z.opp. + +Add Morphism Z.opp with signature Z.eq ==> Z.eq as Zopp_wd. +Proof. +intros; zsimpl; auto with zarith. +Qed. + +Theorem Zsucc_pred : forall n, Z.succ (Z.pred n) == n. +Proof. +red; intros; zsimpl; auto with zarith. +Qed. + +Theorem Zopp_0 : - 0 == 0. +Proof. +red; intros; zsimpl; auto with zarith. +Qed. + +Theorem Zopp_succ : forall n, - (Z.succ n) == Z.pred (- n). +Proof. +intros; zsimpl; auto with zarith. +Qed. + +End ZSig_ZAxioms. diff --git a/theories/Numbers/NaryFunctions.v b/theories/Numbers/NaryFunctions.v new file mode 100644 index 00000000..04a48d51 --- /dev/null +++ b/theories/Numbers/NaryFunctions.v @@ -0,0 +1,142 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Pierre Letouzey, Jerome Vouillon, PPS, Paris 7, 2008 *) +(************************************************************************) + +(*i $Id: NaryFunctions.v 10967 2008-05-22 12:59:38Z letouzey $ i*) + +Open Local Scope type_scope. + +Require Import List. + +(** * Generic dependently-typed operators about [n]-ary functions *) + +(** The type of [n]-ary function: [nfun A n B] is + [A -> ... -> A -> B] with [n] occurences of [A] in this type. *) + +Fixpoint nfun A n B := + match n with + | O => B + | S n => A -> (nfun A n B) + end. + +Notation " A ^^ n --> B " := (nfun A n B) + (at level 50, n at next level) : type_scope. + +(** [napply_cst _ _ a n f] iterates [n] times the application of a + particular constant [a] to the [n]-ary function [f]. *) + +Fixpoint napply_cst (A B:Type)(a:A) n : (A^^n-->B) -> B := + match n return (A^^n-->B) -> B with + | O => fun x => x + | S n => fun x => napply_cst _ _ a n (x a) + end. + + +(** A generic transformation from an n-ary function to another one.*) + +Fixpoint nfun_to_nfun (A B C:Type)(f:B -> C) n : + (A^^n-->B) -> (A^^n-->C) := + match n return (A^^n-->B) -> (A^^n-->C) with + | O => f + | S n => fun g a => nfun_to_nfun _ _ _ f n (g a) + end. + +(** [napply_except_last _ _ n f] expects [n] arguments of type [A], + applies [n-1] of them to [f] and discard the last one. *) + +Definition napply_except_last (A B:Type) := + nfun_to_nfun A B (A->B) (fun b a => b). + +(** [napply_then_last _ _ a n f] expects [n] arguments of type [A], + applies them to [f] and then apply [a] to the result. *) + +Definition napply_then_last (A B:Type)(a:A) := + nfun_to_nfun A (A->B) B (fun fab => fab a). + +(** [napply_discard _ b n] expects [n] arguments, discards then, + and returns [b]. *) + +Fixpoint napply_discard (A B:Type)(b:B) n : A^^n-->B := + match n return A^^n-->B with + | O => b + | S n => fun _ => napply_discard _ _ b n + end. + +(** A fold function *) + +Fixpoint nfold A B (f:A->B->B)(b:B) n : (A^^n-->B) := + match n return (A^^n-->B) with + | O => b + | S n => fun a => (nfold _ _ f (f a b) n) + end. + + +(** [n]-ary products : [nprod A n] is [A*...*A*unit], + with [n] occurrences of [A] in this type. *) + +Fixpoint nprod A n : Type := match n with + | O => unit + | S n => (A * nprod A n)%type +end. + +Notation "A ^ n" := (nprod A n) : type_scope. + +(** [n]-ary curryfication / uncurryfication *) + +Fixpoint ncurry (A B:Type) n : (A^n -> B) -> (A^^n-->B) := + match n return (A^n -> B) -> (A^^n-->B) with + | O => fun x => x tt + | S n => fun f a => ncurry _ _ n (fun p => f (a,p)) + end. + +Fixpoint nuncurry (A B:Type) n : (A^^n-->B) -> (A^n -> B) := + match n return (A^^n-->B) -> (A^n -> B) with + | O => fun x _ => x + | S n => fun f p => let (x,p) := p in nuncurry _ _ n (f x) p + end. + +(** Earlier functions can also be defined via [ncurry/nuncurry]. + For instance : *) + +Definition nfun_to_nfun_bis A B C (f:B->C) n : + (A^^n-->B) -> (A^^n-->C) := + fun anb => ncurry _ _ n (fun an => f ((nuncurry _ _ n anb) an)). + +(** We can also us it to obtain another [fold] function, + equivalent to the previous one, but with a nicer expansion + (see for instance Int31.iszero). *) + +Fixpoint nfold_bis A B (f:A->B->B)(b:B) n : (A^^n-->B) := + match n return (A^^n-->B) with + | O => b + | S n => fun a => + nfun_to_nfun_bis _ _ _ (f a) n (nfold_bis _ _ f b n) + end. + +(** From [nprod] to [list] *) + +Fixpoint nprod_to_list (A:Type) n : A^n -> list A := + match n with + | O => fun _ => nil + | S n => fun p => let (x,p) := p in x::(nprod_to_list _ n p) + end. + +(** From [list] to [nprod] *) + +Fixpoint nprod_of_list (A:Type)(l:list A) : A^(length l) := + match l return A^(length l) with + | nil => tt + | x::l => (x, nprod_of_list _ l) + end. + +(** This gives an additional way to write the fold *) + +Definition nfold_list (A B:Type)(f:A->B->B)(b:B) n : (A^^n-->B) := + ncurry _ _ n (fun p => fold_right f b (nprod_to_list _ _ p)). + diff --git a/theories/Numbers/NatInt/NZAdd.v b/theories/Numbers/NatInt/NZAdd.v new file mode 100644 index 00000000..c9bb5c95 --- /dev/null +++ b/theories/Numbers/NatInt/NZAdd.v @@ -0,0 +1,91 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NZAdd.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Import NZAxioms. +Require Import NZBase. + +Module NZAddPropFunct (Import NZAxiomsMod : NZAxiomsSig). +Module Export NZBasePropMod := NZBasePropFunct NZAxiomsMod. +Open Local Scope NatIntScope. + +Theorem NZadd_0_r : forall n : NZ, n + 0 == n. +Proof. +NZinduct n. now rewrite NZadd_0_l. +intro. rewrite NZadd_succ_l. now rewrite NZsucc_inj_wd. +Qed. + +Theorem NZadd_succ_r : forall n m : NZ, n + S m == S (n + m). +Proof. +intros n m; NZinduct n. +now do 2 rewrite NZadd_0_l. +intro. repeat rewrite NZadd_succ_l. now rewrite NZsucc_inj_wd. +Qed. + +Theorem NZadd_comm : forall n m : NZ, n + m == m + n. +Proof. +intros n m; NZinduct n. +rewrite NZadd_0_l; now rewrite NZadd_0_r. +intros n. rewrite NZadd_succ_l; rewrite NZadd_succ_r. now rewrite NZsucc_inj_wd. +Qed. + +Theorem NZadd_1_l : forall n : NZ, 1 + n == S n. +Proof. +intro n; rewrite NZadd_succ_l; now rewrite NZadd_0_l. +Qed. + +Theorem NZadd_1_r : forall n : NZ, n + 1 == S n. +Proof. +intro n; rewrite NZadd_comm; apply NZadd_1_l. +Qed. + +Theorem NZadd_assoc : forall n m p : NZ, n + (m + p) == (n + m) + p. +Proof. +intros n m p; NZinduct n. +now do 2 rewrite NZadd_0_l. +intro. do 3 rewrite NZadd_succ_l. now rewrite NZsucc_inj_wd. +Qed. + +Theorem NZadd_shuffle1 : forall n m p q : NZ, (n + m) + (p + q) == (n + p) + (m + q). +Proof. +intros n m p q. +rewrite <- (NZadd_assoc n m (p + q)). rewrite (NZadd_comm m (p + q)). +rewrite <- (NZadd_assoc p q m). rewrite (NZadd_assoc n p (q + m)). +now rewrite (NZadd_comm q m). +Qed. + +Theorem NZadd_shuffle2 : forall n m p q : NZ, (n + m) + (p + q) == (n + q) + (m + p). +Proof. +intros n m p q. +rewrite <- (NZadd_assoc n m (p + q)). rewrite (NZadd_assoc m p q). +rewrite (NZadd_comm (m + p) q). now rewrite <- (NZadd_assoc n q (m + p)). +Qed. + +Theorem NZadd_cancel_l : forall n m p : NZ, p + n == p + m <-> n == m. +Proof. +intros n m p; NZinduct p. +now do 2 rewrite NZadd_0_l. +intro p. do 2 rewrite NZadd_succ_l. now rewrite NZsucc_inj_wd. +Qed. + +Theorem NZadd_cancel_r : forall n m p : NZ, n + p == m + p <-> n == m. +Proof. +intros n m p. rewrite (NZadd_comm n p); rewrite (NZadd_comm m p). +apply NZadd_cancel_l. +Qed. + +Theorem NZsub_1_r : forall n : NZ, n - 1 == P n. +Proof. +intro n; rewrite NZsub_succ_r; now rewrite NZsub_0_r. +Qed. + +End NZAddPropFunct. + diff --git a/theories/Numbers/NatInt/NZAddOrder.v b/theories/Numbers/NatInt/NZAddOrder.v new file mode 100644 index 00000000..50d1c42f --- /dev/null +++ b/theories/Numbers/NatInt/NZAddOrder.v @@ -0,0 +1,166 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NZAddOrder.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Import NZAxioms. +Require Import NZOrder. + +Module NZAddOrderPropFunct (Import NZOrdAxiomsMod : NZOrdAxiomsSig). +Module Export NZOrderPropMod := NZOrderPropFunct NZOrdAxiomsMod. +Open Local Scope NatIntScope. + +Theorem NZadd_lt_mono_l : forall n m p : NZ, n < m <-> p + n < p + m. +Proof. +intros n m p; NZinduct p. +now do 2 rewrite NZadd_0_l. +intro p. do 2 rewrite NZadd_succ_l. now rewrite <- NZsucc_lt_mono. +Qed. + +Theorem NZadd_lt_mono_r : forall n m p : NZ, n < m <-> n + p < m + p. +Proof. +intros n m p. +rewrite (NZadd_comm n p); rewrite (NZadd_comm m p); apply NZadd_lt_mono_l. +Qed. + +Theorem NZadd_lt_mono : forall n m p q : NZ, n < m -> p < q -> n + p < m + q. +Proof. +intros n m p q H1 H2. +apply NZlt_trans with (m + p); +[now apply -> NZadd_lt_mono_r | now apply -> NZadd_lt_mono_l]. +Qed. + +Theorem NZadd_le_mono_l : forall n m p : NZ, n <= m <-> p + n <= p + m. +Proof. +intros n m p; NZinduct p. +now do 2 rewrite NZadd_0_l. +intro p. do 2 rewrite NZadd_succ_l. now rewrite <- NZsucc_le_mono. +Qed. + +Theorem NZadd_le_mono_r : forall n m p : NZ, n <= m <-> n + p <= m + p. +Proof. +intros n m p. +rewrite (NZadd_comm n p); rewrite (NZadd_comm m p); apply NZadd_le_mono_l. +Qed. + +Theorem NZadd_le_mono : forall n m p q : NZ, n <= m -> p <= q -> n + p <= m + q. +Proof. +intros n m p q H1 H2. +apply NZle_trans with (m + p); +[now apply -> NZadd_le_mono_r | now apply -> NZadd_le_mono_l]. +Qed. + +Theorem NZadd_lt_le_mono : forall n m p q : NZ, n < m -> p <= q -> n + p < m + q. +Proof. +intros n m p q H1 H2. +apply NZlt_le_trans with (m + p); +[now apply -> NZadd_lt_mono_r | now apply -> NZadd_le_mono_l]. +Qed. + +Theorem NZadd_le_lt_mono : forall n m p q : NZ, n <= m -> p < q -> n + p < m + q. +Proof. +intros n m p q H1 H2. +apply NZle_lt_trans with (m + p); +[now apply -> NZadd_le_mono_r | now apply -> NZadd_lt_mono_l]. +Qed. + +Theorem NZadd_pos_pos : forall n m : NZ, 0 < n -> 0 < m -> 0 < n + m. +Proof. +intros n m H1 H2. rewrite <- (NZadd_0_l 0). now apply NZadd_lt_mono. +Qed. + +Theorem NZadd_pos_nonneg : forall n m : NZ, 0 < n -> 0 <= m -> 0 < n + m. +Proof. +intros n m H1 H2. rewrite <- (NZadd_0_l 0). now apply NZadd_lt_le_mono. +Qed. + +Theorem NZadd_nonneg_pos : forall n m : NZ, 0 <= n -> 0 < m -> 0 < n + m. +Proof. +intros n m H1 H2. rewrite <- (NZadd_0_l 0). now apply NZadd_le_lt_mono. +Qed. + +Theorem NZadd_nonneg_nonneg : forall n m : NZ, 0 <= n -> 0 <= m -> 0 <= n + m. +Proof. +intros n m H1 H2. rewrite <- (NZadd_0_l 0). now apply NZadd_le_mono. +Qed. + +Theorem NZlt_add_pos_l : forall n m : NZ, 0 < n -> m < n + m. +Proof. +intros n m H. apply -> (NZadd_lt_mono_r 0 n m) in H. +now rewrite NZadd_0_l in H. +Qed. + +Theorem NZlt_add_pos_r : forall n m : NZ, 0 < n -> m < m + n. +Proof. +intros; rewrite NZadd_comm; now apply NZlt_add_pos_l. +Qed. + +Theorem NZle_lt_add_lt : forall n m p q : NZ, n <= m -> p + m < q + n -> p < q. +Proof. +intros n m p q H1 H2. destruct (NZle_gt_cases q p); [| assumption]. +pose proof (NZadd_le_mono q p n m H H1) as H3. apply <- NZnle_gt in H2. +false_hyp H3 H2. +Qed. + +Theorem NZlt_le_add_lt : forall n m p q : NZ, n < m -> p + m <= q + n -> p < q. +Proof. +intros n m p q H1 H2. destruct (NZle_gt_cases q p); [| assumption]. +pose proof (NZadd_le_lt_mono q p n m H H1) as H3. apply <- NZnle_gt in H3. +false_hyp H2 H3. +Qed. + +Theorem NZle_le_add_le : forall n m p q : NZ, n <= m -> p + m <= q + n -> p <= q. +Proof. +intros n m p q H1 H2. destruct (NZle_gt_cases p q); [assumption |]. +pose proof (NZadd_lt_le_mono q p n m H H1) as H3. apply <- NZnle_gt in H3. +false_hyp H2 H3. +Qed. + +Theorem NZadd_lt_cases : forall n m p q : NZ, n + m < p + q -> n < p \/ m < q. +Proof. +intros n m p q H; +destruct (NZle_gt_cases p n) as [H1 | H1]. +destruct (NZle_gt_cases q m) as [H2 | H2]. +pose proof (NZadd_le_mono p n q m H1 H2) as H3. apply -> NZle_ngt in H3. +false_hyp H H3. +now right. now left. +Qed. + +Theorem NZadd_le_cases : forall n m p q : NZ, n + m <= p + q -> n <= p \/ m <= q. +Proof. +intros n m p q H. +destruct (NZle_gt_cases n p) as [H1 | H1]. now left. +destruct (NZle_gt_cases m q) as [H2 | H2]. now right. +assert (H3 : p + q < n + m) by now apply NZadd_lt_mono. +apply -> NZle_ngt in H. false_hyp H3 H. +Qed. + +Theorem NZadd_neg_cases : forall n m : NZ, n + m < 0 -> n < 0 \/ m < 0. +Proof. +intros n m H; apply NZadd_lt_cases; now rewrite NZadd_0_l. +Qed. + +Theorem NZadd_pos_cases : forall n m : NZ, 0 < n + m -> 0 < n \/ 0 < m. +Proof. +intros n m H; apply NZadd_lt_cases; now rewrite NZadd_0_l. +Qed. + +Theorem NZadd_nonpos_cases : forall n m : NZ, n + m <= 0 -> n <= 0 \/ m <= 0. +Proof. +intros n m H; apply NZadd_le_cases; now rewrite NZadd_0_l. +Qed. + +Theorem NZadd_nonneg_cases : forall n m : NZ, 0 <= n + m -> 0 <= n \/ 0 <= m. +Proof. +intros n m H; apply NZadd_le_cases; now rewrite NZadd_0_l. +Qed. + +End NZAddOrderPropFunct. + diff --git a/theories/Numbers/NatInt/NZAxioms.v b/theories/Numbers/NatInt/NZAxioms.v new file mode 100644 index 00000000..26933646 --- /dev/null +++ b/theories/Numbers/NatInt/NZAxioms.v @@ -0,0 +1,99 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NZAxioms.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export NumPrelude. + +Module Type NZAxiomsSig. + +Parameter Inline NZ : Type. +Parameter Inline NZeq : NZ -> NZ -> Prop. +Parameter Inline NZ0 : NZ. +Parameter Inline NZsucc : NZ -> NZ. +Parameter Inline NZpred : NZ -> NZ. +Parameter Inline NZadd : NZ -> NZ -> NZ. +Parameter Inline NZsub : NZ -> NZ -> NZ. +Parameter Inline NZmul : NZ -> NZ -> NZ. + +(* Unary subtraction (opp) is not defined on natural numbers, so we have + it for integers only *) + +Axiom NZeq_equiv : equiv NZ NZeq. +Add Relation NZ NZeq + reflexivity proved by (proj1 NZeq_equiv) + symmetry proved by (proj2 (proj2 NZeq_equiv)) + transitivity proved by (proj1 (proj2 NZeq_equiv)) +as NZeq_rel. + +Add Morphism NZsucc with signature NZeq ==> NZeq as NZsucc_wd. +Add Morphism NZpred with signature NZeq ==> NZeq as NZpred_wd. +Add Morphism NZadd with signature NZeq ==> NZeq ==> NZeq as NZadd_wd. +Add Morphism NZsub with signature NZeq ==> NZeq ==> NZeq as NZsub_wd. +Add Morphism NZmul with signature NZeq ==> NZeq ==> NZeq as NZmul_wd. + +Delimit Scope NatIntScope with NatInt. +Open Local Scope NatIntScope. +Notation "x == y" := (NZeq x y) (at level 70) : NatIntScope. +Notation "x ~= y" := (~ NZeq x y) (at level 70) : NatIntScope. +Notation "0" := NZ0 : NatIntScope. +Notation S := NZsucc. +Notation P := NZpred. +Notation "1" := (S 0) : NatIntScope. +Notation "x + y" := (NZadd x y) : NatIntScope. +Notation "x - y" := (NZsub x y) : NatIntScope. +Notation "x * y" := (NZmul x y) : NatIntScope. + +Axiom NZpred_succ : forall n : NZ, P (S n) == n. + +Axiom NZinduction : + forall A : NZ -> Prop, predicate_wd NZeq A -> + A 0 -> (forall n : NZ, A n <-> A (S n)) -> forall n : NZ, A n. + +Axiom NZadd_0_l : forall n : NZ, 0 + n == n. +Axiom NZadd_succ_l : forall n m : NZ, (S n) + m == S (n + m). + +Axiom NZsub_0_r : forall n : NZ, n - 0 == n. +Axiom NZsub_succ_r : forall n m : NZ, n - (S m) == P (n - m). + +Axiom NZmul_0_l : forall n : NZ, 0 * n == 0. +Axiom NZmul_succ_l : forall n m : NZ, S n * m == n * m + m. + +End NZAxiomsSig. + +Module Type NZOrdAxiomsSig. +Declare Module Export NZAxiomsMod : NZAxiomsSig. +Open Local Scope NatIntScope. + +Parameter Inline NZlt : NZ -> NZ -> Prop. +Parameter Inline NZle : NZ -> NZ -> Prop. +Parameter Inline NZmin : NZ -> NZ -> NZ. +Parameter Inline NZmax : NZ -> NZ -> NZ. + +Add Morphism NZlt with signature NZeq ==> NZeq ==> iff as NZlt_wd. +Add Morphism NZle with signature NZeq ==> NZeq ==> iff as NZle_wd. +Add Morphism NZmin with signature NZeq ==> NZeq ==> NZeq as NZmin_wd. +Add Morphism NZmax with signature NZeq ==> NZeq ==> NZeq as NZmax_wd. + +Notation "x < y" := (NZlt x y) : NatIntScope. +Notation "x <= y" := (NZle x y) : NatIntScope. +Notation "x > y" := (NZlt y x) (only parsing) : NatIntScope. +Notation "x >= y" := (NZle y x) (only parsing) : NatIntScope. + +Axiom NZlt_eq_cases : forall n m : NZ, n <= m <-> n < m \/ n == m. +Axiom NZlt_irrefl : forall n : NZ, ~ (n < n). +Axiom NZlt_succ_r : forall n m : NZ, n < S m <-> n <= m. + +Axiom NZmin_l : forall n m : NZ, n <= m -> NZmin n m == n. +Axiom NZmin_r : forall n m : NZ, m <= n -> NZmin n m == m. +Axiom NZmax_l : forall n m : NZ, m <= n -> NZmax n m == n. +Axiom NZmax_r : forall n m : NZ, n <= m -> NZmax n m == m. + +End NZOrdAxiomsSig. diff --git a/theories/Numbers/NatInt/NZBase.v b/theories/Numbers/NatInt/NZBase.v new file mode 100644 index 00000000..8b01e353 --- /dev/null +++ b/theories/Numbers/NatInt/NZBase.v @@ -0,0 +1,84 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NZBase.v 10934 2008-05-15 21:58:20Z letouzey $ i*) + +Require Import NZAxioms. + +Module NZBasePropFunct (Import NZAxiomsMod : NZAxiomsSig). +Open Local Scope NatIntScope. + +Theorem NZneq_symm : forall n m : NZ, n ~= m -> m ~= n. +Proof. +intros n m H1 H2; symmetry in H2; false_hyp H2 H1. +Qed. + +Theorem NZE_stepl : forall x y z : NZ, x == y -> x == z -> z == y. +Proof. +intros x y z H1 H2; now rewrite <- H1. +Qed. + +Declare Left Step NZE_stepl. +(* The right step lemma is just the transitivity of NZeq *) +Declare Right Step (proj1 (proj2 NZeq_equiv)). + +Theorem NZsucc_inj : forall n1 n2 : NZ, S n1 == S n2 -> n1 == n2. +Proof. +intros n1 n2 H. +apply NZpred_wd in H. now do 2 rewrite NZpred_succ in H. +Qed. + +(* The following theorem is useful as an equivalence for proving +bidirectional induction steps *) +Theorem NZsucc_inj_wd : forall n1 n2 : NZ, S n1 == S n2 <-> n1 == n2. +Proof. +intros; split. +apply NZsucc_inj. +apply NZsucc_wd. +Qed. + +Theorem NZsucc_inj_wd_neg : forall n m : NZ, S n ~= S m <-> n ~= m. +Proof. +intros; now rewrite NZsucc_inj_wd. +Qed. + +(* We cannot prove that the predecessor is injective, nor that it is +left-inverse to the successor at this point *) + +Section CentralInduction. + +Variable A : predicate NZ. + +Hypothesis A_wd : predicate_wd NZeq A. + +Add Morphism A with signature NZeq ==> iff as A_morph. +Proof. apply A_wd. Qed. + +Theorem NZcentral_induction : + forall z : NZ, A z -> + (forall n : NZ, A n <-> A (S n)) -> + forall n : NZ, A n. +Proof. +intros z Base Step; revert Base; pattern z; apply NZinduction. +solve_predicate_wd. +intro; now apply NZinduction. +intro; pose proof (Step n); tauto. +Qed. + +End CentralInduction. + +Tactic Notation "NZinduct" ident(n) := + induction_maker n ltac:(apply NZinduction). + +Tactic Notation "NZinduct" ident(n) constr(u) := + induction_maker n ltac:(apply NZcentral_induction with (z := u)). + +End NZBasePropFunct. + diff --git a/theories/Numbers/NatInt/NZMul.v b/theories/Numbers/NatInt/NZMul.v new file mode 100644 index 00000000..fda8b7a3 --- /dev/null +++ b/theories/Numbers/NatInt/NZMul.v @@ -0,0 +1,80 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NZMul.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Import NZAxioms. +Require Import NZAdd. + +Module NZMulPropFunct (Import NZAxiomsMod : NZAxiomsSig). +Module Export NZAddPropMod := NZAddPropFunct NZAxiomsMod. +Open Local Scope NatIntScope. + +Theorem NZmul_0_r : forall n : NZ, n * 0 == 0. +Proof. +NZinduct n. +now rewrite NZmul_0_l. +intro. rewrite NZmul_succ_l. now rewrite NZadd_0_r. +Qed. + +Theorem NZmul_succ_r : forall n m : NZ, n * (S m) == n * m + n. +Proof. +intros n m; NZinduct n. +do 2 rewrite NZmul_0_l; now rewrite NZadd_0_l. +intro n. do 2 rewrite NZmul_succ_l. do 2 rewrite NZadd_succ_r. +rewrite NZsucc_inj_wd. rewrite <- (NZadd_assoc (n * m) m n). +rewrite (NZadd_comm m n). rewrite NZadd_assoc. +now rewrite NZadd_cancel_r. +Qed. + +Theorem NZmul_comm : forall n m : NZ, n * m == m * n. +Proof. +intros n m; NZinduct n. +rewrite NZmul_0_l; now rewrite NZmul_0_r. +intro. rewrite NZmul_succ_l; rewrite NZmul_succ_r. now rewrite NZadd_cancel_r. +Qed. + +Theorem NZmul_add_distr_r : forall n m p : NZ, (n + m) * p == n * p + m * p. +Proof. +intros n m p; NZinduct n. +rewrite NZmul_0_l. now do 2 rewrite NZadd_0_l. +intro n. rewrite NZadd_succ_l. do 2 rewrite NZmul_succ_l. +rewrite <- (NZadd_assoc (n * p) p (m * p)). +rewrite (NZadd_comm p (m * p)). rewrite (NZadd_assoc (n * p) (m * p) p). +now rewrite NZadd_cancel_r. +Qed. + +Theorem NZmul_add_distr_l : forall n m p : NZ, n * (m + p) == n * m + n * p. +Proof. +intros n m p. +rewrite (NZmul_comm n (m + p)). rewrite (NZmul_comm n m). +rewrite (NZmul_comm n p). apply NZmul_add_distr_r. +Qed. + +Theorem NZmul_assoc : forall n m p : NZ, n * (m * p) == (n * m) * p. +Proof. +intros n m p; NZinduct n. +now do 3 rewrite NZmul_0_l. +intro n. do 2 rewrite NZmul_succ_l. rewrite NZmul_add_distr_r. +now rewrite NZadd_cancel_r. +Qed. + +Theorem NZmul_1_l : forall n : NZ, 1 * n == n. +Proof. +intro n. rewrite NZmul_succ_l; rewrite NZmul_0_l. now rewrite NZadd_0_l. +Qed. + +Theorem NZmul_1_r : forall n : NZ, n * 1 == n. +Proof. +intro n; rewrite NZmul_comm; apply NZmul_1_l. +Qed. + +End NZMulPropFunct. + diff --git a/theories/Numbers/NatInt/NZMulOrder.v b/theories/Numbers/NatInt/NZMulOrder.v new file mode 100644 index 00000000..c707bf73 --- /dev/null +++ b/theories/Numbers/NatInt/NZMulOrder.v @@ -0,0 +1,310 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NZMulOrder.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Import NZAxioms. +Require Import NZAddOrder. + +Module NZMulOrderPropFunct (Import NZOrdAxiomsMod : NZOrdAxiomsSig). +Module Export NZAddOrderPropMod := NZAddOrderPropFunct NZOrdAxiomsMod. +Open Local Scope NatIntScope. + +Theorem NZmul_lt_pred : + forall p q n m : NZ, S p == q -> (p * n < p * m <-> q * n + m < q * m + n). +Proof. +intros p q n m H. rewrite <- H. do 2 rewrite NZmul_succ_l. +rewrite <- (NZadd_assoc (p * n) n m). +rewrite <- (NZadd_assoc (p * m) m n). +rewrite (NZadd_comm n m). now rewrite <- NZadd_lt_mono_r. +Qed. + +Theorem NZmul_lt_mono_pos_l : forall p n m : NZ, 0 < p -> (n < m <-> p * n < p * m). +Proof. +NZord_induct p. +intros n m H; false_hyp H NZlt_irrefl. +intros p H IH n m H1. do 2 rewrite NZmul_succ_l. +le_elim H. assert (LR : forall n m : NZ, n < m -> p * n + n < p * m + m). +intros n1 m1 H2. apply NZadd_lt_mono; [now apply -> IH | assumption]. +split; [apply LR |]. intro H2. apply -> NZlt_dne; intro H3. +apply <- NZle_ngt in H3. le_elim H3. +apply NZlt_asymm in H2. apply H2. now apply LR. +rewrite H3 in H2; false_hyp H2 NZlt_irrefl. +rewrite <- H; do 2 rewrite NZmul_0_l; now do 2 rewrite NZadd_0_l. +intros p H1 _ n m H2. apply NZlt_asymm in H1. false_hyp H2 H1. +Qed. + +Theorem NZmul_lt_mono_pos_r : forall p n m : NZ, 0 < p -> (n < m <-> n * p < m * p). +Proof. +intros p n m. +rewrite (NZmul_comm n p); rewrite (NZmul_comm m p). now apply NZmul_lt_mono_pos_l. +Qed. + +Theorem NZmul_lt_mono_neg_l : forall p n m : NZ, p < 0 -> (n < m <-> p * m < p * n). +Proof. +NZord_induct p. +intros n m H; false_hyp H NZlt_irrefl. +intros p H1 _ n m H2. apply NZlt_succ_l in H2. apply <- NZnle_gt in H2. false_hyp H1 H2. +intros p H IH n m H1. apply <- NZle_succ_l in H. +le_elim H. assert (LR : forall n m : NZ, n < m -> p * m < p * n). +intros n1 m1 H2. apply (NZle_lt_add_lt n1 m1). +now apply NZlt_le_incl. do 2 rewrite <- NZmul_succ_l. now apply -> IH. +split; [apply LR |]. intro H2. apply -> NZlt_dne; intro H3. +apply <- NZle_ngt in H3. le_elim H3. +apply NZlt_asymm in H2. apply H2. now apply LR. +rewrite H3 in H2; false_hyp H2 NZlt_irrefl. +rewrite (NZmul_lt_pred p (S p)) by reflexivity. +rewrite H; do 2 rewrite NZmul_0_l; now do 2 rewrite NZadd_0_l. +Qed. + +Theorem NZmul_lt_mono_neg_r : forall p n m : NZ, p < 0 -> (n < m <-> m * p < n * p). +Proof. +intros p n m. +rewrite (NZmul_comm n p); rewrite (NZmul_comm m p). now apply NZmul_lt_mono_neg_l. +Qed. + +Theorem NZmul_le_mono_nonneg_l : forall n m p : NZ, 0 <= p -> n <= m -> p * n <= p * m. +Proof. +intros n m p H1 H2. le_elim H1. +le_elim H2. apply NZlt_le_incl. now apply -> NZmul_lt_mono_pos_l. +apply NZeq_le_incl; now rewrite H2. +apply NZeq_le_incl; rewrite <- H1; now do 2 rewrite NZmul_0_l. +Qed. + +Theorem NZmul_le_mono_nonpos_l : forall n m p : NZ, p <= 0 -> n <= m -> p * m <= p * n. +Proof. +intros n m p H1 H2. le_elim H1. +le_elim H2. apply NZlt_le_incl. now apply -> NZmul_lt_mono_neg_l. +apply NZeq_le_incl; now rewrite H2. +apply NZeq_le_incl; rewrite H1; now do 2 rewrite NZmul_0_l. +Qed. + +Theorem NZmul_le_mono_nonneg_r : forall n m p : NZ, 0 <= p -> n <= m -> n * p <= m * p. +Proof. +intros n m p H1 H2; rewrite (NZmul_comm n p); rewrite (NZmul_comm m p); +now apply NZmul_le_mono_nonneg_l. +Qed. + +Theorem NZmul_le_mono_nonpos_r : forall n m p : NZ, p <= 0 -> n <= m -> m * p <= n * p. +Proof. +intros n m p H1 H2; rewrite (NZmul_comm n p); rewrite (NZmul_comm m p); +now apply NZmul_le_mono_nonpos_l. +Qed. + +Theorem NZmul_cancel_l : forall n m p : NZ, p ~= 0 -> (p * n == p * m <-> n == m). +Proof. +intros n m p H; split; intro H1. +destruct (NZlt_trichotomy p 0) as [H2 | [H2 | H2]]. +apply -> NZeq_dne; intro H3. apply -> NZlt_gt_cases in H3. destruct H3 as [H3 | H3]. +assert (H4 : p * m < p * n); [now apply -> NZmul_lt_mono_neg_l |]. +rewrite H1 in H4; false_hyp H4 NZlt_irrefl. +assert (H4 : p * n < p * m); [now apply -> NZmul_lt_mono_neg_l |]. +rewrite H1 in H4; false_hyp H4 NZlt_irrefl. +false_hyp H2 H. +apply -> NZeq_dne; intro H3. apply -> NZlt_gt_cases in H3. destruct H3 as [H3 | H3]. +assert (H4 : p * n < p * m) by (now apply -> NZmul_lt_mono_pos_l). +rewrite H1 in H4; false_hyp H4 NZlt_irrefl. +assert (H4 : p * m < p * n) by (now apply -> NZmul_lt_mono_pos_l). +rewrite H1 in H4; false_hyp H4 NZlt_irrefl. +now rewrite H1. +Qed. + +Theorem NZmul_cancel_r : forall n m p : NZ, p ~= 0 -> (n * p == m * p <-> n == m). +Proof. +intros n m p. rewrite (NZmul_comm n p), (NZmul_comm m p); apply NZmul_cancel_l. +Qed. + +Theorem NZmul_id_l : forall n m : NZ, m ~= 0 -> (n * m == m <-> n == 1). +Proof. +intros n m H. +stepl (n * m == 1 * m) by now rewrite NZmul_1_l. now apply NZmul_cancel_r. +Qed. + +Theorem NZmul_id_r : forall n m : NZ, n ~= 0 -> (n * m == n <-> m == 1). +Proof. +intros n m; rewrite NZmul_comm; apply NZmul_id_l. +Qed. + +Theorem NZmul_le_mono_pos_l : forall n m p : NZ, 0 < p -> (n <= m <-> p * n <= p * m). +Proof. +intros n m p H; do 2 rewrite NZlt_eq_cases. +rewrite (NZmul_lt_mono_pos_l p n m) by assumption. +now rewrite -> (NZmul_cancel_l n m p) by +(intro H1; rewrite H1 in H; false_hyp H NZlt_irrefl). +Qed. + +Theorem NZmul_le_mono_pos_r : forall n m p : NZ, 0 < p -> (n <= m <-> n * p <= m * p). +Proof. +intros n m p. rewrite (NZmul_comm n p); rewrite (NZmul_comm m p); +apply NZmul_le_mono_pos_l. +Qed. + +Theorem NZmul_le_mono_neg_l : forall n m p : NZ, p < 0 -> (n <= m <-> p * m <= p * n). +Proof. +intros n m p H; do 2 rewrite NZlt_eq_cases. +rewrite (NZmul_lt_mono_neg_l p n m); [| assumption]. +rewrite -> (NZmul_cancel_l m n p) by (intro H1; rewrite H1 in H; false_hyp H NZlt_irrefl). +now setoid_replace (n == m) with (m == n) using relation iff by (split; now intro). +Qed. + +Theorem NZmul_le_mono_neg_r : forall n m p : NZ, p < 0 -> (n <= m <-> m * p <= n * p). +Proof. +intros n m p. rewrite (NZmul_comm n p); rewrite (NZmul_comm m p); +apply NZmul_le_mono_neg_l. +Qed. + +Theorem NZmul_lt_mono_nonneg : + forall n m p q : NZ, 0 <= n -> n < m -> 0 <= p -> p < q -> n * p < m * q. +Proof. +intros n m p q H1 H2 H3 H4. +apply NZle_lt_trans with (m * p). +apply NZmul_le_mono_nonneg_r; [assumption | now apply NZlt_le_incl]. +apply -> NZmul_lt_mono_pos_l; [assumption | now apply NZle_lt_trans with n]. +Qed. + +(* There are still many variants of the theorem above. One can assume 0 < n +or 0 < p or n <= m or p <= q. *) + +Theorem NZmul_le_mono_nonneg : + forall n m p q : NZ, 0 <= n -> n <= m -> 0 <= p -> p <= q -> n * p <= m * q. +Proof. +intros n m p q H1 H2 H3 H4. +le_elim H2; le_elim H4. +apply NZlt_le_incl; now apply NZmul_lt_mono_nonneg. +rewrite <- H4; apply NZmul_le_mono_nonneg_r; [assumption | now apply NZlt_le_incl]. +rewrite <- H2; apply NZmul_le_mono_nonneg_l; [assumption | now apply NZlt_le_incl]. +rewrite H2; rewrite H4; now apply NZeq_le_incl. +Qed. + +Theorem NZmul_pos_pos : forall n m : NZ, 0 < n -> 0 < m -> 0 < n * m. +Proof. +intros n m H1 H2. +rewrite <- (NZmul_0_l m). now apply -> NZmul_lt_mono_pos_r. +Qed. + +Theorem NZmul_neg_neg : forall n m : NZ, n < 0 -> m < 0 -> 0 < n * m. +Proof. +intros n m H1 H2. +rewrite <- (NZmul_0_l m). now apply -> NZmul_lt_mono_neg_r. +Qed. + +Theorem NZmul_pos_neg : forall n m : NZ, 0 < n -> m < 0 -> n * m < 0. +Proof. +intros n m H1 H2. +rewrite <- (NZmul_0_l m). now apply -> NZmul_lt_mono_neg_r. +Qed. + +Theorem NZmul_neg_pos : forall n m : NZ, n < 0 -> 0 < m -> n * m < 0. +Proof. +intros; rewrite NZmul_comm; now apply NZmul_pos_neg. +Qed. + +Theorem NZlt_1_mul_pos : forall n m : NZ, 1 < n -> 0 < m -> 1 < n * m. +Proof. +intros n m H1 H2. apply -> (NZmul_lt_mono_pos_r m) in H1. +rewrite NZmul_1_l in H1. now apply NZlt_1_l with m. +assumption. +Qed. + +Theorem NZeq_mul_0 : forall n m : NZ, n * m == 0 <-> n == 0 \/ m == 0. +Proof. +intros n m; split. +intro H; destruct (NZlt_trichotomy n 0) as [H1 | [H1 | H1]]; +destruct (NZlt_trichotomy m 0) as [H2 | [H2 | H2]]; +try (now right); try (now left). +elimtype False; now apply (NZlt_neq 0 (n * m)); [apply NZmul_neg_neg |]. +elimtype False; now apply (NZlt_neq (n * m) 0); [apply NZmul_neg_pos |]. +elimtype False; now apply (NZlt_neq (n * m) 0); [apply NZmul_pos_neg |]. +elimtype False; now apply (NZlt_neq 0 (n * m)); [apply NZmul_pos_pos |]. +intros [H | H]. now rewrite H, NZmul_0_l. now rewrite H, NZmul_0_r. +Qed. + +Theorem NZneq_mul_0 : forall n m : NZ, n ~= 0 /\ m ~= 0 <-> n * m ~= 0. +Proof. +intros n m; split; intro H. +intro H1; apply -> NZeq_mul_0 in H1. tauto. +split; intro H1; rewrite H1 in H; +(rewrite NZmul_0_l in H || rewrite NZmul_0_r in H); now apply H. +Qed. + +Theorem NZeq_square_0 : forall n : NZ, n * n == 0 <-> n == 0. +Proof. +intro n; rewrite NZeq_mul_0; tauto. +Qed. + +Theorem NZeq_mul_0_l : forall n m : NZ, n * m == 0 -> m ~= 0 -> n == 0. +Proof. +intros n m H1 H2. apply -> NZeq_mul_0 in H1. destruct H1 as [H1 | H1]. +assumption. false_hyp H1 H2. +Qed. + +Theorem NZeq_mul_0_r : forall n m : NZ, n * m == 0 -> n ~= 0 -> m == 0. +Proof. +intros n m H1 H2; apply -> NZeq_mul_0 in H1. destruct H1 as [H1 | H1]. +false_hyp H1 H2. assumption. +Qed. + +Theorem NZlt_0_mul : forall n m : NZ, 0 < n * m <-> (0 < n /\ 0 < m) \/ (m < 0 /\ n < 0). +Proof. +intros n m; split; [intro H | intros [[H1 H2] | [H1 H2]]]. +destruct (NZlt_trichotomy n 0) as [H1 | [H1 | H1]]; +[| rewrite H1 in H; rewrite NZmul_0_l in H; false_hyp H NZlt_irrefl |]; +(destruct (NZlt_trichotomy m 0) as [H2 | [H2 | H2]]; +[| rewrite H2 in H; rewrite NZmul_0_r in H; false_hyp H NZlt_irrefl |]); +try (left; now split); try (right; now split). +assert (H3 : n * m < 0) by now apply NZmul_neg_pos. +elimtype False; now apply (NZlt_asymm (n * m) 0). +assert (H3 : n * m < 0) by now apply NZmul_pos_neg. +elimtype False; now apply (NZlt_asymm (n * m) 0). +now apply NZmul_pos_pos. now apply NZmul_neg_neg. +Qed. + +Theorem NZsquare_lt_mono_nonneg : forall n m : NZ, 0 <= n -> n < m -> n * n < m * m. +Proof. +intros n m H1 H2. now apply NZmul_lt_mono_nonneg. +Qed. + +Theorem NZsquare_le_mono_nonneg : forall n m : NZ, 0 <= n -> n <= m -> n * n <= m * m. +Proof. +intros n m H1 H2. now apply NZmul_le_mono_nonneg. +Qed. + +(* The converse theorems require nonnegativity (or nonpositivity) of the +other variable *) + +Theorem NZsquare_lt_simpl_nonneg : forall n m : NZ, 0 <= m -> n * n < m * m -> n < m. +Proof. +intros n m H1 H2. destruct (NZlt_ge_cases n 0). +now apply NZlt_le_trans with 0. +destruct (NZlt_ge_cases n m). +assumption. assert (F : m * m <= n * n) by now apply NZsquare_le_mono_nonneg. +apply -> NZle_ngt in F. false_hyp H2 F. +Qed. + +Theorem NZsquare_le_simpl_nonneg : forall n m : NZ, 0 <= m -> n * n <= m * m -> n <= m. +Proof. +intros n m H1 H2. destruct (NZlt_ge_cases n 0). +apply NZlt_le_incl; now apply NZlt_le_trans with 0. +destruct (NZle_gt_cases n m). +assumption. assert (F : m * m < n * n) by now apply NZsquare_lt_mono_nonneg. +apply -> NZlt_nge in F. false_hyp H2 F. +Qed. + +Theorem NZmul_2_mono_l : forall n m : NZ, n < m -> 1 + (1 + 1) * n < (1 + 1) * m. +Proof. +intros n m H. apply <- NZle_succ_l in H. +apply -> (NZmul_le_mono_pos_l (S n) m (1 + 1)) in H. +repeat rewrite NZmul_add_distr_r in *; repeat rewrite NZmul_1_l in *. +repeat rewrite NZadd_succ_r in *. repeat rewrite NZadd_succ_l in *. rewrite NZadd_0_l. +now apply -> NZle_succ_l. +apply NZadd_pos_pos; now apply NZlt_succ_diag_r. +Qed. + +End NZMulOrderPropFunct. diff --git a/theories/Numbers/NatInt/NZOrder.v b/theories/Numbers/NatInt/NZOrder.v new file mode 100644 index 00000000..15004824 --- /dev/null +++ b/theories/Numbers/NatInt/NZOrder.v @@ -0,0 +1,666 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NZOrder.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Import NZAxioms. +Require Import NZMul. +Require Import Decidable. + +Module NZOrderPropFunct (Import NZOrdAxiomsMod : NZOrdAxiomsSig). +Module Export NZMulPropMod := NZMulPropFunct NZAxiomsMod. +Open Local Scope NatIntScope. + +Ltac le_elim H := rewrite NZlt_eq_cases in H; destruct H as [H | H]. + +Theorem NZlt_le_incl : forall n m : NZ, n < m -> n <= m. +Proof. +intros; apply <- NZlt_eq_cases; now left. +Qed. + +Theorem NZeq_le_incl : forall n m : NZ, n == m -> n <= m. +Proof. +intros; apply <- NZlt_eq_cases; now right. +Qed. + +Lemma NZlt_stepl : forall x y z : NZ, x < y -> x == z -> z < y. +Proof. +intros x y z H1 H2; now rewrite <- H2. +Qed. + +Lemma NZlt_stepr : forall x y z : NZ, x < y -> y == z -> x < z. +Proof. +intros x y z H1 H2; now rewrite <- H2. +Qed. + +Lemma NZle_stepl : forall x y z : NZ, x <= y -> x == z -> z <= y. +Proof. +intros x y z H1 H2; now rewrite <- H2. +Qed. + +Lemma NZle_stepr : forall x y z : NZ, x <= y -> y == z -> x <= z. +Proof. +intros x y z H1 H2; now rewrite <- H2. +Qed. + +Declare Left Step NZlt_stepl. +Declare Right Step NZlt_stepr. +Declare Left Step NZle_stepl. +Declare Right Step NZle_stepr. + +Theorem NZlt_neq : forall n m : NZ, n < m -> n ~= m. +Proof. +intros n m H1 H2; rewrite H2 in H1; false_hyp H1 NZlt_irrefl. +Qed. + +Theorem NZle_neq : forall n m : NZ, n < m <-> n <= m /\ n ~= m. +Proof. +intros n m; split; [intro H | intros [H1 H2]]. +split. now apply NZlt_le_incl. now apply NZlt_neq. +le_elim H1. assumption. false_hyp H1 H2. +Qed. + +Theorem NZle_refl : forall n : NZ, n <= n. +Proof. +intro; now apply NZeq_le_incl. +Qed. + +Theorem NZlt_succ_diag_r : forall n : NZ, n < S n. +Proof. +intro n. rewrite NZlt_succ_r. now apply NZeq_le_incl. +Qed. + +Theorem NZle_succ_diag_r : forall n : NZ, n <= S n. +Proof. +intro; apply NZlt_le_incl; apply NZlt_succ_diag_r. +Qed. + +Theorem NZlt_0_1 : 0 < 1. +Proof. +apply NZlt_succ_diag_r. +Qed. + +Theorem NZle_0_1 : 0 <= 1. +Proof. +apply NZle_succ_diag_r. +Qed. + +Theorem NZlt_lt_succ_r : forall n m : NZ, n < m -> n < S m. +Proof. +intros. rewrite NZlt_succ_r. now apply NZlt_le_incl. +Qed. + +Theorem NZle_le_succ_r : forall n m : NZ, n <= m -> n <= S m. +Proof. +intros n m H. rewrite <- NZlt_succ_r in H. now apply NZlt_le_incl. +Qed. + +Theorem NZle_succ_r : forall n m : NZ, n <= S m <-> n <= m \/ n == S m. +Proof. +intros n m; rewrite NZlt_eq_cases. now rewrite NZlt_succ_r. +Qed. + +(* The following theorem is a special case of neq_succ_iter_l below, +but we prove it separately *) + +Theorem NZneq_succ_diag_l : forall n : NZ, S n ~= n. +Proof. +intros n H. pose proof (NZlt_succ_diag_r n) as H1. rewrite H in H1. +false_hyp H1 NZlt_irrefl. +Qed. + +Theorem NZneq_succ_diag_r : forall n : NZ, n ~= S n. +Proof. +intro n; apply NZneq_symm; apply NZneq_succ_diag_l. +Qed. + +Theorem NZnlt_succ_diag_l : forall n : NZ, ~ S n < n. +Proof. +intros n H; apply NZlt_lt_succ_r in H. false_hyp H NZlt_irrefl. +Qed. + +Theorem NZnle_succ_diag_l : forall n : NZ, ~ S n <= n. +Proof. +intros n H; le_elim H. +false_hyp H NZnlt_succ_diag_l. false_hyp H NZneq_succ_diag_l. +Qed. + +Theorem NZle_succ_l : forall n m : NZ, S n <= m <-> n < m. +Proof. +intro n; NZinduct m n. +setoid_replace (n < n) with False using relation iff by + (apply -> neg_false; apply NZlt_irrefl). +now setoid_replace (S n <= n) with False using relation iff by + (apply -> neg_false; apply NZnle_succ_diag_l). +intro m. rewrite NZlt_succ_r. rewrite NZle_succ_r. +rewrite NZsucc_inj_wd. +rewrite (NZlt_eq_cases n m). +rewrite or_cancel_r. +reflexivity. +intros H1 H2; rewrite H2 in H1; false_hyp H1 NZnle_succ_diag_l. +apply NZlt_neq. +Qed. + +Theorem NZlt_succ_l : forall n m : NZ, S n < m -> n < m. +Proof. +intros n m H; apply -> NZle_succ_l; now apply NZlt_le_incl. +Qed. + +Theorem NZsucc_lt_mono : forall n m : NZ, n < m <-> S n < S m. +Proof. +intros n m. rewrite <- NZle_succ_l. symmetry. apply NZlt_succ_r. +Qed. + +Theorem NZsucc_le_mono : forall n m : NZ, n <= m <-> S n <= S m. +Proof. +intros n m. do 2 rewrite NZlt_eq_cases. +rewrite <- NZsucc_lt_mono; now rewrite NZsucc_inj_wd. +Qed. + +Theorem NZlt_asymm : forall n m, n < m -> ~ m < n. +Proof. +intros n m; NZinduct n m. +intros H _; false_hyp H NZlt_irrefl. +intro n; split; intros H H1 H2. +apply NZlt_succ_l in H1. apply -> NZlt_succ_r in H2. le_elim H2. +now apply H. rewrite H2 in H1; false_hyp H1 NZlt_irrefl. +apply NZlt_lt_succ_r in H2. apply <- NZle_succ_l in H1. le_elim H1. +now apply H. rewrite H1 in H2; false_hyp H2 NZlt_irrefl. +Qed. + +Theorem NZlt_trans : forall n m p : NZ, n < m -> m < p -> n < p. +Proof. +intros n m p; NZinduct p m. +intros _ H; false_hyp H NZlt_irrefl. +intro p. do 2 rewrite NZlt_succ_r. +split; intros H H1 H2. +apply NZlt_le_incl; le_elim H2; [now apply H | now rewrite H2 in H1]. +assert (n <= p) as H3. apply H. assumption. now apply NZlt_le_incl. +le_elim H3. assumption. rewrite <- H3 in H2. +elimtype False; now apply (NZlt_asymm n m). +Qed. + +Theorem NZle_trans : forall n m p : NZ, n <= m -> m <= p -> n <= p. +Proof. +intros n m p H1 H2; le_elim H1. +le_elim H2. apply NZlt_le_incl; now apply NZlt_trans with (m := m). +apply NZlt_le_incl; now rewrite <- H2. now rewrite H1. +Qed. + +Theorem NZle_lt_trans : forall n m p : NZ, n <= m -> m < p -> n < p. +Proof. +intros n m p H1 H2; le_elim H1. +now apply NZlt_trans with (m := m). now rewrite H1. +Qed. + +Theorem NZlt_le_trans : forall n m p : NZ, n < m -> m <= p -> n < p. +Proof. +intros n m p H1 H2; le_elim H2. +now apply NZlt_trans with (m := m). now rewrite <- H2. +Qed. + +Theorem NZle_antisymm : forall n m : NZ, n <= m -> m <= n -> n == m. +Proof. +intros n m H1 H2; now (le_elim H1; le_elim H2); +[elimtype False; apply (NZlt_asymm n m) | | |]. +Qed. + +Theorem NZlt_1_l : forall n m : NZ, 0 < n -> n < m -> 1 < m. +Proof. +intros n m H1 H2. apply <- NZle_succ_l in H1. now apply NZle_lt_trans with n. +Qed. + +(** Trichotomy, decidability, and double negation elimination *) + +Theorem NZlt_trichotomy : forall n m : NZ, n < m \/ n == m \/ m < n. +Proof. +intros n m; NZinduct n m. +right; now left. +intro n; rewrite NZlt_succ_r. stepr ((S n < m \/ S n == m) \/ m <= n) by tauto. +rewrite <- (NZlt_eq_cases (S n) m). +setoid_replace (n == m) with (m == n) using relation iff by now split. +stepl (n < m \/ m < n \/ m == n) by tauto. rewrite <- NZlt_eq_cases. +apply or_iff_compat_r. symmetry; apply NZle_succ_l. +Qed. + +(* Decidability of equality, even though true in each finite ring, does not +have a uniform proof. Otherwise, the proof for two fixed numbers would +reduce to a normal form that will say if the numbers are equal or not, +which cannot be true in all finite rings. Therefore, we prove decidability +in the presence of order. *) + +Theorem NZeq_dec : forall n m : NZ, decidable (n == m). +Proof. +intros n m; destruct (NZlt_trichotomy n m) as [H | [H | H]]. +right; intro H1; rewrite H1 in H; false_hyp H NZlt_irrefl. +now left. +right; intro H1; rewrite H1 in H; false_hyp H NZlt_irrefl. +Qed. + +(* DNE stands for double-negation elimination *) + +Theorem NZeq_dne : forall n m, ~ ~ n == m <-> n == m. +Proof. +intros n m; split; intro H. +destruct (NZeq_dec n m) as [H1 | H1]. +assumption. false_hyp H1 H. +intro H1; now apply H1. +Qed. + +Theorem NZlt_gt_cases : forall n m : NZ, n ~= m <-> n < m \/ n > m. +Proof. +intros n m; split. +pose proof (NZlt_trichotomy n m); tauto. +intros H H1; destruct H as [H | H]; rewrite H1 in H; false_hyp H NZlt_irrefl. +Qed. + +Theorem NZle_gt_cases : forall n m : NZ, n <= m \/ n > m. +Proof. +intros n m; destruct (NZlt_trichotomy n m) as [H | [H | H]]. +left; now apply NZlt_le_incl. left; now apply NZeq_le_incl. now right. +Qed. + +(* The following theorem is cleary redundant, but helps not to +remember whether one has to say le_gt_cases or lt_ge_cases *) + +Theorem NZlt_ge_cases : forall n m : NZ, n < m \/ n >= m. +Proof. +intros n m; destruct (NZle_gt_cases m n); try (now left); try (now right). +Qed. + +Theorem NZle_ge_cases : forall n m : NZ, n <= m \/ n >= m. +Proof. +intros n m; destruct (NZle_gt_cases n m) as [H | H]. +now left. right; now apply NZlt_le_incl. +Qed. + +Theorem NZle_ngt : forall n m : NZ, n <= m <-> ~ n > m. +Proof. +intros n m. split; intro H; [intro H1 |]. +eapply NZle_lt_trans in H; [| eassumption ..]. false_hyp H NZlt_irrefl. +destruct (NZle_gt_cases n m) as [H1 | H1]. +assumption. false_hyp H1 H. +Qed. + +(* Redundant but useful *) + +Theorem NZnlt_ge : forall n m : NZ, ~ n < m <-> n >= m. +Proof. +intros n m; symmetry; apply NZle_ngt. +Qed. + +Theorem NZlt_dec : forall n m : NZ, decidable (n < m). +Proof. +intros n m; destruct (NZle_gt_cases m n); +[right; now apply -> NZle_ngt | now left]. +Qed. + +Theorem NZlt_dne : forall n m, ~ ~ n < m <-> n < m. +Proof. +intros n m; split; intro H; +[destruct (NZlt_dec n m) as [H1 | H1]; [assumption | false_hyp H1 H] | +intro H1; false_hyp H H1]. +Qed. + +Theorem NZnle_gt : forall n m : NZ, ~ n <= m <-> n > m. +Proof. +intros n m. rewrite NZle_ngt. apply NZlt_dne. +Qed. + +(* Redundant but useful *) + +Theorem NZlt_nge : forall n m : NZ, n < m <-> ~ n >= m. +Proof. +intros n m; symmetry; apply NZnle_gt. +Qed. + +Theorem NZle_dec : forall n m : NZ, decidable (n <= m). +Proof. +intros n m; destruct (NZle_gt_cases n m); +[now left | right; now apply <- NZnle_gt]. +Qed. + +Theorem NZle_dne : forall n m : NZ, ~ ~ n <= m <-> n <= m. +Proof. +intros n m; split; intro H; +[destruct (NZle_dec n m) as [H1 | H1]; [assumption | false_hyp H1 H] | +intro H1; false_hyp H H1]. +Qed. + +Theorem NZnlt_succ_r : forall n m : NZ, ~ m < S n <-> n < m. +Proof. +intros n m; rewrite NZlt_succ_r; apply NZnle_gt. +Qed. + +(* The difference between integers and natural numbers is that for +every integer there is a predecessor, which is not true for natural +numbers. However, for both classes, every number that is bigger than +some other number has a predecessor. The proof of this fact by regular +induction does not go through, so we need to use strong +(course-of-value) induction. *) + +Lemma NZlt_exists_pred_strong : + forall z n m : NZ, z < m -> m <= n -> exists k : NZ, m == S k /\ z <= k. +Proof. +intro z; NZinduct n z. +intros m H1 H2; apply <- NZnle_gt in H1; false_hyp H2 H1. +intro n; split; intros IH m H1 H2. +apply -> NZle_succ_r in H2; destruct H2 as [H2 | H2]. +now apply IH. exists n. now split; [| rewrite <- NZlt_succ_r; rewrite <- H2]. +apply IH. assumption. now apply NZle_le_succ_r. +Qed. + +Theorem NZlt_exists_pred : + forall z n : NZ, z < n -> exists k : NZ, n == S k /\ z <= k. +Proof. +intros z n H; apply NZlt_exists_pred_strong with (z := z) (n := n). +assumption. apply NZle_refl. +Qed. + +(** A corollary of having an order is that NZ is infinite *) + +(* This section about infinity of NZ relies on the type nat and can be +safely removed *) + +Definition NZsucc_iter (n : nat) (m : NZ) := + nat_rect (fun _ => NZ) m (fun _ l => S l) n. + +Theorem NZlt_succ_iter_r : + forall (n : nat) (m : NZ), m < NZsucc_iter (Datatypes.S n) m. +Proof. +intros n m; induction n as [| n IH]; simpl in *. +apply NZlt_succ_diag_r. now apply NZlt_lt_succ_r. +Qed. + +Theorem NZneq_succ_iter_l : + forall (n : nat) (m : NZ), NZsucc_iter (Datatypes.S n) m ~= m. +Proof. +intros n m H. pose proof (NZlt_succ_iter_r n m) as H1. rewrite H in H1. +false_hyp H1 NZlt_irrefl. +Qed. + +(* End of the section about the infinity of NZ *) + +(** Stronger variant of induction with assumptions n >= 0 (n < 0) +in the induction step *) + +Section Induction. + +Variable A : NZ -> Prop. +Hypothesis A_wd : predicate_wd NZeq A. + +Add Morphism A with signature NZeq ==> iff as A_morph. +Proof. apply A_wd. Qed. + +Section Center. + +Variable z : NZ. (* A z is the basis of induction *) + +Section RightInduction. + +Let A' (n : NZ) := forall m : NZ, z <= m -> m < n -> A m. +Let right_step := forall n : NZ, z <= n -> A n -> A (S n). +Let right_step' := forall n : NZ, z <= n -> A' n -> A n. +Let right_step'' := forall n : NZ, A' n <-> A' (S n). + +Lemma NZrs_rs' : A z -> right_step -> right_step'. +Proof. +intros Az RS n H1 H2. +le_elim H1. apply NZlt_exists_pred in H1. destruct H1 as [k [H3 H4]]. +rewrite H3. apply RS; [assumption | apply H2; [assumption | rewrite H3; apply NZlt_succ_diag_r]]. +rewrite <- H1; apply Az. +Qed. + +Lemma NZrs'_rs'' : right_step' -> right_step''. +Proof. +intros RS' n; split; intros H1 m H2 H3. +apply -> NZlt_succ_r in H3; le_elim H3; +[now apply H1 | rewrite H3 in *; now apply RS']. +apply H1; [assumption | now apply NZlt_lt_succ_r]. +Qed. + +Lemma NZrbase : A' z. +Proof. +intros m H1 H2. apply -> NZle_ngt in H1. false_hyp H2 H1. +Qed. + +Lemma NZA'A_right : (forall n : NZ, A' n) -> forall n : NZ, z <= n -> A n. +Proof. +intros H1 n H2. apply H1 with (n := S n); [assumption | apply NZlt_succ_diag_r]. +Qed. + +Theorem NZstrong_right_induction: right_step' -> forall n : NZ, z <= n -> A n. +Proof. +intro RS'; apply NZA'A_right; unfold A'; NZinduct n z; +[apply NZrbase | apply NZrs'_rs''; apply RS']. +Qed. + +Theorem NZright_induction : A z -> right_step -> forall n : NZ, z <= n -> A n. +Proof. +intros Az RS; apply NZstrong_right_induction; now apply NZrs_rs'. +Qed. + +Theorem NZright_induction' : + (forall n : NZ, n <= z -> A n) -> right_step -> forall n : NZ, A n. +Proof. +intros L R n. +destruct (NZlt_trichotomy n z) as [H | [H | H]]. +apply L; now apply NZlt_le_incl. +apply L; now apply NZeq_le_incl. +apply NZright_induction. apply L; now apply NZeq_le_incl. assumption. now apply NZlt_le_incl. +Qed. + +Theorem NZstrong_right_induction' : + (forall n : NZ, n <= z -> A n) -> right_step' -> forall n : NZ, A n. +Proof. +intros L R n. +destruct (NZlt_trichotomy n z) as [H | [H | H]]. +apply L; now apply NZlt_le_incl. +apply L; now apply NZeq_le_incl. +apply NZstrong_right_induction. assumption. now apply NZlt_le_incl. +Qed. + +End RightInduction. + +Section LeftInduction. + +Let A' (n : NZ) := forall m : NZ, m <= z -> n <= m -> A m. +Let left_step := forall n : NZ, n < z -> A (S n) -> A n. +Let left_step' := forall n : NZ, n <= z -> A' (S n) -> A n. +Let left_step'' := forall n : NZ, A' n <-> A' (S n). + +Lemma NZls_ls' : A z -> left_step -> left_step'. +Proof. +intros Az LS n H1 H2. le_elim H1. +apply LS; [assumption | apply H2; [now apply <- NZle_succ_l | now apply NZeq_le_incl]]. +rewrite H1; apply Az. +Qed. + +Lemma NZls'_ls'' : left_step' -> left_step''. +Proof. +intros LS' n; split; intros H1 m H2 H3. +apply -> NZle_succ_l in H3. apply NZlt_le_incl in H3. now apply H1. +le_elim H3. +apply <- NZle_succ_l in H3. now apply H1. +rewrite <- H3 in *; now apply LS'. +Qed. + +Lemma NZlbase : A' (S z). +Proof. +intros m H1 H2. apply -> NZle_succ_l in H2. +apply -> NZle_ngt in H1. false_hyp H2 H1. +Qed. + +Lemma NZA'A_left : (forall n : NZ, A' n) -> forall n : NZ, n <= z -> A n. +Proof. +intros H1 n H2. apply H1 with (n := n); [assumption | now apply NZeq_le_incl]. +Qed. + +Theorem NZstrong_left_induction: left_step' -> forall n : NZ, n <= z -> A n. +Proof. +intro LS'; apply NZA'A_left; unfold A'; NZinduct n (S z); +[apply NZlbase | apply NZls'_ls''; apply LS']. +Qed. + +Theorem NZleft_induction : A z -> left_step -> forall n : NZ, n <= z -> A n. +Proof. +intros Az LS; apply NZstrong_left_induction; now apply NZls_ls'. +Qed. + +Theorem NZleft_induction' : + (forall n : NZ, z <= n -> A n) -> left_step -> forall n : NZ, A n. +Proof. +intros R L n. +destruct (NZlt_trichotomy n z) as [H | [H | H]]. +apply NZleft_induction. apply R. now apply NZeq_le_incl. assumption. now apply NZlt_le_incl. +rewrite H; apply R; now apply NZeq_le_incl. +apply R; now apply NZlt_le_incl. +Qed. + +Theorem NZstrong_left_induction' : + (forall n : NZ, z <= n -> A n) -> left_step' -> forall n : NZ, A n. +Proof. +intros R L n. +destruct (NZlt_trichotomy n z) as [H | [H | H]]. +apply NZstrong_left_induction; auto. now apply NZlt_le_incl. +rewrite H; apply R; now apply NZeq_le_incl. +apply R; now apply NZlt_le_incl. +Qed. + +End LeftInduction. + +Theorem NZorder_induction : + A z -> + (forall n : NZ, z <= n -> A n -> A (S n)) -> + (forall n : NZ, n < z -> A (S n) -> A n) -> + forall n : NZ, A n. +Proof. +intros Az RS LS n. +destruct (NZlt_trichotomy n z) as [H | [H | H]]. +now apply NZleft_induction; [| | apply NZlt_le_incl]. +now rewrite H. +now apply NZright_induction; [| | apply NZlt_le_incl]. +Qed. + +Theorem NZorder_induction' : + A z -> + (forall n : NZ, z <= n -> A n -> A (S n)) -> + (forall n : NZ, n <= z -> A n -> A (P n)) -> + forall n : NZ, A n. +Proof. +intros Az AS AP n; apply NZorder_induction; try assumption. +intros m H1 H2. apply AP in H2; [| now apply <- NZle_succ_l]. +unfold predicate_wd, fun_wd in A_wd; apply -> (A_wd (P (S m)) m); +[assumption | apply NZpred_succ]. +Qed. + +End Center. + +Theorem NZorder_induction_0 : + A 0 -> + (forall n : NZ, 0 <= n -> A n -> A (S n)) -> + (forall n : NZ, n < 0 -> A (S n) -> A n) -> + forall n : NZ, A n. +Proof (NZorder_induction 0). + +Theorem NZorder_induction'_0 : + A 0 -> + (forall n : NZ, 0 <= n -> A n -> A (S n)) -> + (forall n : NZ, n <= 0 -> A n -> A (P n)) -> + forall n : NZ, A n. +Proof (NZorder_induction' 0). + +(** Elimintation principle for < *) + +Theorem NZlt_ind : forall (n : NZ), + A (S n) -> + (forall m : NZ, n < m -> A m -> A (S m)) -> + forall m : NZ, n < m -> A m. +Proof. +intros n H1 H2 m H3. +apply NZright_induction with (S n); [assumption | | now apply <- NZle_succ_l]. +intros; apply H2; try assumption. now apply -> NZle_succ_l. +Qed. + +(** Elimintation principle for <= *) + +Theorem NZle_ind : forall (n : NZ), + A n -> + (forall m : NZ, n <= m -> A m -> A (S m)) -> + forall m : NZ, n <= m -> A m. +Proof. +intros n H1 H2 m H3. +now apply NZright_induction with n. +Qed. + +End Induction. + +Tactic Notation "NZord_induct" ident(n) := + induction_maker n ltac:(apply NZorder_induction_0). + +Tactic Notation "NZord_induct" ident(n) constr(z) := + induction_maker n ltac:(apply NZorder_induction with z). + +Section WF. + +Variable z : NZ. + +Let Rlt (n m : NZ) := z <= n /\ n < m. +Let Rgt (n m : NZ) := m < n /\ n <= z. + +Add Morphism Rlt with signature NZeq ==> NZeq ==> iff as Rlt_wd. +Proof. +intros x1 x2 H1 x3 x4 H2; unfold Rlt; rewrite H1; now rewrite H2. +Qed. + +Add Morphism Rgt with signature NZeq ==> NZeq ==> iff as Rgt_wd. +Proof. +intros x1 x2 H1 x3 x4 H2; unfold Rgt; rewrite H1; now rewrite H2. +Qed. + +Lemma NZAcc_lt_wd : predicate_wd NZeq (Acc Rlt). +Proof. +unfold predicate_wd, fun_wd. +intros x1 x2 H; split; intro H1; destruct H1 as [H2]; +constructor; intros; apply H2; now (rewrite H || rewrite <- H). +Qed. + +Lemma NZAcc_gt_wd : predicate_wd NZeq (Acc Rgt). +Proof. +unfold predicate_wd, fun_wd. +intros x1 x2 H; split; intro H1; destruct H1 as [H2]; +constructor; intros; apply H2; now (rewrite H || rewrite <- H). +Qed. + +Theorem NZlt_wf : well_founded Rlt. +Proof. +unfold well_founded. +apply NZstrong_right_induction' with (z := z). +apply NZAcc_lt_wd. +intros n H; constructor; intros y [H1 H2]. +apply <- NZnle_gt in H2. elim H2. now apply NZle_trans with z. +intros n H1 H2; constructor; intros m [H3 H4]. now apply H2. +Qed. + +Theorem NZgt_wf : well_founded Rgt. +Proof. +unfold well_founded. +apply NZstrong_left_induction' with (z := z). +apply NZAcc_gt_wd. +intros n H; constructor; intros y [H1 H2]. +apply <- NZnle_gt in H2. elim H2. now apply NZle_lt_trans with n. +intros n H1 H2; constructor; intros m [H3 H4]. +apply H2. assumption. now apply <- NZle_succ_l. +Qed. + +End WF. + +End NZOrderPropFunct. + diff --git a/theories/Numbers/Natural/Abstract/NAdd.v b/theories/Numbers/Natural/Abstract/NAdd.v new file mode 100644 index 00000000..f58b87d8 --- /dev/null +++ b/theories/Numbers/Natural/Abstract/NAdd.v @@ -0,0 +1,156 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NAdd.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export NBase. + +Module NAddPropFunct (Import NAxiomsMod : NAxiomsSig). +Module Export NBasePropMod := NBasePropFunct NAxiomsMod. + +Open Local Scope NatScope. + +Theorem add_wd : + forall n1 n2 : N, n1 == n2 -> forall m1 m2 : N, m1 == m2 -> n1 + m1 == n2 + m2. +Proof NZadd_wd. + +Theorem add_0_l : forall n : N, 0 + n == n. +Proof NZadd_0_l. + +Theorem add_succ_l : forall n m : N, (S n) + m == S (n + m). +Proof NZadd_succ_l. + +(** Theorems that are valid for both natural numbers and integers *) + +Theorem add_0_r : forall n : N, n + 0 == n. +Proof NZadd_0_r. + +Theorem add_succ_r : forall n m : N, n + S m == S (n + m). +Proof NZadd_succ_r. + +Theorem add_comm : forall n m : N, n + m == m + n. +Proof NZadd_comm. + +Theorem add_assoc : forall n m p : N, n + (m + p) == (n + m) + p. +Proof NZadd_assoc. + +Theorem add_shuffle1 : forall n m p q : N, (n + m) + (p + q) == (n + p) + (m + q). +Proof NZadd_shuffle1. + +Theorem add_shuffle2 : forall n m p q : N, (n + m) + (p + q) == (n + q) + (m + p). +Proof NZadd_shuffle2. + +Theorem add_1_l : forall n : N, 1 + n == S n. +Proof NZadd_1_l. + +Theorem add_1_r : forall n : N, n + 1 == S n. +Proof NZadd_1_r. + +Theorem add_cancel_l : forall n m p : N, p + n == p + m <-> n == m. +Proof NZadd_cancel_l. + +Theorem add_cancel_r : forall n m p : N, n + p == m + p <-> n == m. +Proof NZadd_cancel_r. + +(* Theorems that are valid for natural numbers but cannot be proved for Z *) + +Theorem eq_add_0 : forall n m : N, n + m == 0 <-> n == 0 /\ m == 0. +Proof. +intros n m; induct n. +(* The next command does not work with the axiom add_0_l from NAddSig *) +rewrite add_0_l. intuition reflexivity. +intros n IH. rewrite add_succ_l. +setoid_replace (S (n + m) == 0) with False using relation iff by + (apply -> neg_false; apply neq_succ_0). +setoid_replace (S n == 0) with False using relation iff by + (apply -> neg_false; apply neq_succ_0). tauto. +Qed. + +Theorem eq_add_succ : + forall n m : N, (exists p : N, n + m == S p) <-> + (exists n' : N, n == S n') \/ (exists m' : N, m == S m'). +Proof. +intros n m; cases n. +split; intro H. +destruct H as [p H]. rewrite add_0_l in H; right; now exists p. +destruct H as [[n' H] | [m' H]]. +symmetry in H; false_hyp H neq_succ_0. +exists m'; now rewrite add_0_l. +intro n; split; intro H. +left; now exists n. +exists (n + m); now rewrite add_succ_l. +Qed. + +Theorem eq_add_1 : forall n m : N, + n + m == 1 -> n == 1 /\ m == 0 \/ n == 0 /\ m == 1. +Proof. +intros n m H. +assert (H1 : exists p : N, n + m == S p) by now exists 0. +apply -> eq_add_succ in H1. destruct H1 as [[n' H1] | [m' H1]]. +left. rewrite H1 in H; rewrite add_succ_l in H; apply succ_inj in H. +apply -> eq_add_0 in H. destruct H as [H2 H3]; rewrite H2 in H1; now split. +right. rewrite H1 in H; rewrite add_succ_r in H; apply succ_inj in H. +apply -> eq_add_0 in H. destruct H as [H2 H3]; rewrite H3 in H1; now split. +Qed. + +Theorem succ_add_discr : forall n m : N, m ~= S (n + m). +Proof. +intro n; induct m. +apply neq_symm. apply neq_succ_0. +intros m IH H. apply succ_inj in H. rewrite add_succ_r in H. +unfold not in IH; now apply IH. +Qed. + +Theorem add_pred_l : forall n m : N, n ~= 0 -> P n + m == P (n + m). +Proof. +intros n m; cases n. +intro H; now elim H. +intros n IH; rewrite add_succ_l; now do 2 rewrite pred_succ. +Qed. + +Theorem add_pred_r : forall n m : N, m ~= 0 -> n + P m == P (n + m). +Proof. +intros n m H; rewrite (add_comm n (P m)); +rewrite (add_comm n m); now apply add_pred_l. +Qed. + +(* One could define n <= m as exists p : N, p + n == m. Then we have +dichotomy: + +forall n m : N, n <= m \/ m <= n, + +i.e., + +forall n m : N, (exists p : N, p + n == m) \/ (exists p : N, p + m == n) (1) + +We will need (1) in the proof of induction principle for integers +constructed as pairs of natural numbers. The formula (1) can be proved +using properties of order and truncated subtraction. Thus, p would be +m - n or n - m and (1) would hold by theorem sub_add from Sub.v +depending on whether n <= m or m <= n. However, in proving induction +for integers constructed from natural numbers we do not need to +require implementations of order and sub; it is enough to prove (1) +here. *) + +Theorem add_dichotomy : + forall n m : N, (exists p : N, p + n == m) \/ (exists p : N, p + m == n). +Proof. +intros n m; induct n. +left; exists m; apply add_0_r. +intros n IH. +destruct IH as [[p H] | [p H]]. +destruct (zero_or_succ p) as [H1 | [p' H1]]; rewrite H1 in H. +rewrite add_0_l in H. right; exists (S 0); rewrite H; rewrite add_succ_l; now rewrite add_0_l. +left; exists p'; rewrite add_succ_r; now rewrite add_succ_l in H. +right; exists (S p). rewrite add_succ_l; now rewrite H. +Qed. + +End NAddPropFunct. + diff --git a/theories/Numbers/Natural/Abstract/NAddOrder.v b/theories/Numbers/Natural/Abstract/NAddOrder.v new file mode 100644 index 00000000..7024fd00 --- /dev/null +++ b/theories/Numbers/Natural/Abstract/NAddOrder.v @@ -0,0 +1,114 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NAddOrder.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export NOrder. + +Module NAddOrderPropFunct (Import NAxiomsMod : NAxiomsSig). +Module Export NOrderPropMod := NOrderPropFunct NAxiomsMod. +Open Local Scope NatScope. + +Theorem add_lt_mono_l : forall n m p : N, n < m <-> p + n < p + m. +Proof NZadd_lt_mono_l. + +Theorem add_lt_mono_r : forall n m p : N, n < m <-> n + p < m + p. +Proof NZadd_lt_mono_r. + +Theorem add_lt_mono : forall n m p q : N, n < m -> p < q -> n + p < m + q. +Proof NZadd_lt_mono. + +Theorem add_le_mono_l : forall n m p : N, n <= m <-> p + n <= p + m. +Proof NZadd_le_mono_l. + +Theorem add_le_mono_r : forall n m p : N, n <= m <-> n + p <= m + p. +Proof NZadd_le_mono_r. + +Theorem add_le_mono : forall n m p q : N, n <= m -> p <= q -> n + p <= m + q. +Proof NZadd_le_mono. + +Theorem add_lt_le_mono : forall n m p q : N, n < m -> p <= q -> n + p < m + q. +Proof NZadd_lt_le_mono. + +Theorem add_le_lt_mono : forall n m p q : N, n <= m -> p < q -> n + p < m + q. +Proof NZadd_le_lt_mono. + +Theorem add_pos_pos : forall n m : N, 0 < n -> 0 < m -> 0 < n + m. +Proof NZadd_pos_pos. + +Theorem lt_add_pos_l : forall n m : N, 0 < n -> m < n + m. +Proof NZlt_add_pos_l. + +Theorem lt_add_pos_r : forall n m : N, 0 < n -> m < m + n. +Proof NZlt_add_pos_r. + +Theorem le_lt_add_lt : forall n m p q : N, n <= m -> p + m < q + n -> p < q. +Proof NZle_lt_add_lt. + +Theorem lt_le_add_lt : forall n m p q : N, n < m -> p + m <= q + n -> p < q. +Proof NZlt_le_add_lt. + +Theorem le_le_add_le : forall n m p q : N, n <= m -> p + m <= q + n -> p <= q. +Proof NZle_le_add_le. + +Theorem add_lt_cases : forall n m p q : N, n + m < p + q -> n < p \/ m < q. +Proof NZadd_lt_cases. + +Theorem add_le_cases : forall n m p q : N, n + m <= p + q -> n <= p \/ m <= q. +Proof NZadd_le_cases. + +Theorem add_pos_cases : forall n m : N, 0 < n + m -> 0 < n \/ 0 < m. +Proof NZadd_pos_cases. + +(* Theorems true for natural numbers *) + +Theorem le_add_r : forall n m : N, n <= n + m. +Proof. +intro n; induct m. +rewrite add_0_r; now apply eq_le_incl. +intros m IH. rewrite add_succ_r; now apply le_le_succ_r. +Qed. + +Theorem lt_lt_add_r : forall n m p : N, n < m -> n < m + p. +Proof. +intros n m p H; rewrite <- (add_0_r n). +apply add_lt_le_mono; [assumption | apply le_0_l]. +Qed. + +Theorem lt_lt_add_l : forall n m p : N, n < m -> n < p + m. +Proof. +intros n m p; rewrite add_comm; apply lt_lt_add_r. +Qed. + +Theorem add_pos_l : forall n m : N, 0 < n -> 0 < n + m. +Proof. +intros; apply NZadd_pos_nonneg. assumption. apply le_0_l. +Qed. + +Theorem add_pos_r : forall n m : N, 0 < m -> 0 < n + m. +Proof. +intros; apply NZadd_nonneg_pos. apply le_0_l. assumption. +Qed. + +(* The following property is used to prove the correctness of the +definition of order on integers constructed from pairs of natural numbers *) + +Theorem add_lt_repl_pair : forall n m n' m' u v : N, + n + u < m + v -> n + m' == n' + m -> n' + u < m' + v. +Proof. +intros n m n' m' u v H1 H2. +symmetry in H2. assert (H3 : n' + m <= n + m') by now apply eq_le_incl. +pose proof (add_lt_le_mono _ _ _ _ H1 H3) as H4. +rewrite (add_shuffle2 n u), (add_shuffle1 m v), (add_comm m n) in H4. +do 2 rewrite <- add_assoc in H4. do 2 apply <- add_lt_mono_l in H4. +now rewrite (add_comm n' u), (add_comm m' v). +Qed. + +End NAddOrderPropFunct. diff --git a/theories/Numbers/Natural/Abstract/NAxioms.v b/theories/Numbers/Natural/Abstract/NAxioms.v new file mode 100644 index 00000000..750cc977 --- /dev/null +++ b/theories/Numbers/Natural/Abstract/NAxioms.v @@ -0,0 +1,71 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NAxioms.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export NZAxioms. + +Set Implicit Arguments. + +Module Type NAxiomsSig. +Declare Module Export NZOrdAxiomsMod : NZOrdAxiomsSig. + +Delimit Scope NatScope with Nat. +Notation N := NZ. +Notation Neq := NZeq. +Notation N0 := NZ0. +Notation N1 := (NZsucc NZ0). +Notation S := NZsucc. +Notation P := NZpred. +Notation add := NZadd. +Notation mul := NZmul. +Notation sub := NZsub. +Notation lt := NZlt. +Notation le := NZle. +Notation min := NZmin. +Notation max := NZmax. +Notation "x == y" := (Neq x y) (at level 70) : NatScope. +Notation "x ~= y" := (~ Neq x y) (at level 70) : NatScope. +Notation "0" := NZ0 : NatScope. +Notation "1" := (NZsucc NZ0) : NatScope. +Notation "x + y" := (NZadd x y) : NatScope. +Notation "x - y" := (NZsub x y) : NatScope. +Notation "x * y" := (NZmul x y) : NatScope. +Notation "x < y" := (NZlt x y) : NatScope. +Notation "x <= y" := (NZle x y) : NatScope. +Notation "x > y" := (NZlt y x) (only parsing) : NatScope. +Notation "x >= y" := (NZle y x) (only parsing) : NatScope. + +Open Local Scope NatScope. + +Parameter Inline recursion : forall A : Type, A -> (N -> A -> A) -> N -> A. +Implicit Arguments recursion [A]. + +Axiom pred_0 : P 0 == 0. + +Axiom recursion_wd : forall (A : Type) (Aeq : relation A), + forall a a' : A, Aeq a a' -> + forall f f' : N -> A -> A, fun2_eq Neq Aeq Aeq f f' -> + forall x x' : N, x == x' -> + Aeq (recursion a f x) (recursion a' f' x'). + +Axiom recursion_0 : + forall (A : Type) (a : A) (f : N -> A -> A), recursion a f 0 = a. + +Axiom recursion_succ : + forall (A : Type) (Aeq : relation A) (a : A) (f : N -> A -> A), + Aeq a a -> fun2_wd Neq Aeq Aeq f -> + forall n : N, Aeq (recursion a f (S n)) (f n (recursion a f n)). + +(*Axiom dep_rec : + forall A : N -> Type, A 0 -> (forall n : N, A n -> A (S n)) -> forall n : N, A n.*) + +End NAxiomsSig. + diff --git a/theories/Numbers/Natural/Abstract/NBase.v b/theories/Numbers/Natural/Abstract/NBase.v new file mode 100644 index 00000000..3e4032b5 --- /dev/null +++ b/theories/Numbers/Natural/Abstract/NBase.v @@ -0,0 +1,288 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NBase.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export Decidable. +Require Export NAxioms. +Require Import NZMulOrder. (* The last property functor on NZ, which subsumes all others *) + +Module NBasePropFunct (Import NAxiomsMod : NAxiomsSig). + +Open Local Scope NatScope. + +(* We call the last property functor on NZ, which includes all the previous +ones, to get all properties of NZ at once. This way we will include them +only one time. *) + +Module Export NZMulOrderMod := NZMulOrderPropFunct NZOrdAxiomsMod. + +(* Here we probably need to re-prove all axioms declared in NAxioms.v to +make sure that the definitions like N, S and add are unfolded in them, +since unfolding is done only inside a functor. In fact, we'll do it in the +files that prove the corresponding properties. In those files, we will also +rename properties proved in NZ files by removing NZ from their names. In +this way, one only has to consult, for example, NAdd.v to see all +available properties for add, i.e., one does not have to go to NAxioms.v +for axioms and NZAdd.v for theorems. *) + +Theorem succ_wd : forall n1 n2 : N, n1 == n2 -> S n1 == S n2. +Proof NZsucc_wd. + +Theorem pred_wd : forall n1 n2 : N, n1 == n2 -> P n1 == P n2. +Proof NZpred_wd. + +Theorem pred_succ : forall n : N, P (S n) == n. +Proof NZpred_succ. + +Theorem pred_0 : P 0 == 0. +Proof pred_0. + +Theorem Neq_refl : forall n : N, n == n. +Proof (proj1 NZeq_equiv). + +Theorem Neq_symm : forall n m : N, n == m -> m == n. +Proof (proj2 (proj2 NZeq_equiv)). + +Theorem Neq_trans : forall n m p : N, n == m -> m == p -> n == p. +Proof (proj1 (proj2 NZeq_equiv)). + +Theorem neq_symm : forall n m : N, n ~= m -> m ~= n. +Proof NZneq_symm. + +Theorem succ_inj : forall n1 n2 : N, S n1 == S n2 -> n1 == n2. +Proof NZsucc_inj. + +Theorem succ_inj_wd : forall n1 n2 : N, S n1 == S n2 <-> n1 == n2. +Proof NZsucc_inj_wd. + +Theorem succ_inj_wd_neg : forall n m : N, S n ~= S m <-> n ~= m. +Proof NZsucc_inj_wd_neg. + +(* Decidability and stability of equality was proved only in NZOrder, but +since it does not mention order, we'll put it here *) + +Theorem eq_dec : forall n m : N, decidable (n == m). +Proof NZeq_dec. + +Theorem eq_dne : forall n m : N, ~ ~ n == m <-> n == m. +Proof NZeq_dne. + +(* Now we prove that the successor of a number is not zero by defining a +function (by recursion) that maps 0 to false and the successor to true *) + +Definition if_zero (A : Set) (a b : A) (n : N) : A := + recursion a (fun _ _ => b) n. + +Add Parametric Morphism (A : Set) : (if_zero A) with signature (@eq _ ==> @eq _ ==> Neq ==> @eq _) as if_zero_wd. +Proof. +intros; unfold if_zero. apply recursion_wd with (Aeq := (@eq A)). +reflexivity. unfold fun2_eq; now intros. assumption. +Qed. + +Theorem if_zero_0 : forall (A : Set) (a b : A), if_zero A a b 0 = a. +Proof. +unfold if_zero; intros; now rewrite recursion_0. +Qed. + +Theorem if_zero_succ : forall (A : Set) (a b : A) (n : N), if_zero A a b (S n) = b. +Proof. +intros; unfold if_zero. +now rewrite (@recursion_succ A (@eq A)); [| | unfold fun2_wd; now intros]. +Qed. + +Implicit Arguments if_zero [A]. + +Theorem neq_succ_0 : forall n : N, S n ~= 0. +Proof. +intros n H. +assert (true = false); [| discriminate]. +replace true with (if_zero false true (S n)) by apply if_zero_succ. +pattern false at 2; replace false with (if_zero false true 0) by apply if_zero_0. +now rewrite H. +Qed. + +Theorem neq_0_succ : forall n : N, 0 ~= S n. +Proof. +intro n; apply neq_symm; apply neq_succ_0. +Qed. + +(* Next, we show that all numbers are nonnegative and recover regular induction +from the bidirectional induction on NZ *) + +Theorem le_0_l : forall n : N, 0 <= n. +Proof. +NZinduct n. +now apply NZeq_le_incl. +intro n; split. +apply NZle_le_succ_r. +intro H; apply -> NZle_succ_r in H; destruct H as [H | H]. +assumption. +symmetry in H; false_hyp H neq_succ_0. +Qed. + +Theorem induction : + forall A : N -> Prop, predicate_wd Neq A -> + A 0 -> (forall n : N, A n -> A (S n)) -> forall n : N, A n. +Proof. +intros A A_wd A0 AS n; apply NZright_induction with 0; try assumption. +intros; auto; apply le_0_l. apply le_0_l. +Qed. + +(* The theorems NZinduction, NZcentral_induction and the tactic NZinduct +refer to bidirectional induction, which is not useful on natural +numbers. Therefore, we define a new induction tactic for natural numbers. +We do not have to call "Declare Left Step" and "Declare Right Step" +commands again, since the data for stepl and stepr tactics is inherited +from NZ. *) + +Ltac induct n := induction_maker n ltac:(apply induction). + +Theorem case_analysis : + forall A : N -> Prop, predicate_wd Neq A -> + A 0 -> (forall n : N, A (S n)) -> forall n : N, A n. +Proof. +intros; apply induction; auto. +Qed. + +Ltac cases n := induction_maker n ltac:(apply case_analysis). + +Theorem neq_0 : ~ forall n, n == 0. +Proof. +intro H; apply (neq_succ_0 0). apply H. +Qed. + +Theorem neq_0_r : forall n, n ~= 0 <-> exists m, n == S m. +Proof. +cases n. split; intro H; +[now elim H | destruct H as [m H]; symmetry in H; false_hyp H neq_succ_0]. +intro n; split; intro H; [now exists n | apply neq_succ_0]. +Qed. + +Theorem zero_or_succ : forall n, n == 0 \/ exists m, n == S m. +Proof. +cases n. +now left. +intro n; right; now exists n. +Qed. + +Theorem eq_pred_0 : forall n : N, P n == 0 <-> n == 0 \/ n == 1. +Proof. +cases n. +rewrite pred_0. setoid_replace (0 == 1) with False using relation iff. tauto. +split; intro H; [symmetry in H; false_hyp H neq_succ_0 | elim H]. +intro n. rewrite pred_succ. +setoid_replace (S n == 0) with False using relation iff by + (apply -> neg_false; apply neq_succ_0). +rewrite succ_inj_wd. tauto. +Qed. + +Theorem succ_pred : forall n : N, n ~= 0 -> S (P n) == n. +Proof. +cases n. +intro H; elimtype False; now apply H. +intros; now rewrite pred_succ. +Qed. + +Theorem pred_inj : forall n m : N, n ~= 0 -> m ~= 0 -> P n == P m -> n == m. +Proof. +intros n m; cases n. +intros H; elimtype False; now apply H. +intros n _; cases m. +intros H; elimtype False; now apply H. +intros m H2 H3. do 2 rewrite pred_succ in H3. now rewrite H3. +Qed. + +(* The following induction principle is useful for reasoning about, e.g., +Fibonacci numbers *) + +Section PairInduction. + +Variable A : N -> Prop. +Hypothesis A_wd : predicate_wd Neq A. + +Add Morphism A with signature Neq ==> iff as A_morph. +Proof. +exact A_wd. +Qed. + +Theorem pair_induction : + A 0 -> A 1 -> + (forall n, A n -> A (S n) -> A (S (S n))) -> forall n, A n. +Proof. +intros until 3. +assert (D : forall n, A n /\ A (S n)); [ |intro n; exact (proj1 (D n))]. +induct n; [ | intros n [IH1 IH2]]; auto. +Qed. + +End PairInduction. + +(*Ltac pair_induct n := induction_maker n ltac:(apply pair_induction).*) + +(* The following is useful for reasoning about, e.g., Ackermann function *) +Section TwoDimensionalInduction. + +Variable R : N -> N -> Prop. +Hypothesis R_wd : relation_wd Neq Neq R. + +Add Morphism R with signature Neq ==> Neq ==> iff as R_morph. +Proof. +exact R_wd. +Qed. + +Theorem two_dim_induction : + R 0 0 -> + (forall n m, R n m -> R n (S m)) -> + (forall n, (forall m, R n m) -> R (S n) 0) -> forall n m, R n m. +Proof. +intros H1 H2 H3. induct n. +induct m. +exact H1. exact (H2 0). +intros n IH. induct m. +now apply H3. exact (H2 (S n)). +Qed. + +End TwoDimensionalInduction. + +(*Ltac two_dim_induct n m := + try intros until n; + try intros until m; + pattern n, m; apply two_dim_induction; clear n m; + [solve_relation_wd | | | ].*) + +Section DoubleInduction. + +Variable R : N -> N -> Prop. +Hypothesis R_wd : relation_wd Neq Neq R. + +Add Morphism R with signature Neq ==> Neq ==> iff as R_morph1. +Proof. +exact R_wd. +Qed. + +Theorem double_induction : + (forall m : N, R 0 m) -> + (forall n : N, R (S n) 0) -> + (forall n m : N, R n m -> R (S n) (S m)) -> forall n m : N, R n m. +Proof. +intros H1 H2 H3; induct n; auto. +intros n H; cases m; auto. +Qed. + +End DoubleInduction. + +Ltac double_induct n m := + try intros until n; + try intros until m; + pattern n, m; apply double_induction; clear n m; + [solve_relation_wd | | | ]. + +End NBasePropFunct. + diff --git a/theories/Numbers/Natural/Abstract/NDefOps.v b/theories/Numbers/Natural/Abstract/NDefOps.v new file mode 100644 index 00000000..e15e4672 --- /dev/null +++ b/theories/Numbers/Natural/Abstract/NDefOps.v @@ -0,0 +1,298 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NDefOps.v 11039 2008-06-02 23:26:13Z letouzey $ i*) + +Require Import Bool. (* To get the orb and negb function *) +Require Export NStrongRec. + +Module NdefOpsPropFunct (Import NAxiomsMod : NAxiomsSig). +Module Export NStrongRecPropMod := NStrongRecPropFunct NAxiomsMod. +Open Local Scope NatScope. + +(*****************************************************) +(** Addition *) + +Definition def_add (x y : N) := recursion y (fun _ p => S p) x. + +Infix Local "++" := def_add (at level 50, left associativity). + +Add Morphism def_add with signature Neq ==> Neq ==> Neq as def_add_wd. +Proof. +unfold def_add. +intros x x' Exx' y y' Eyy'. +apply recursion_wd with (Aeq := Neq). +assumption. +unfold fun2_eq; intros _ _ _ p p' Epp'; now rewrite Epp'. +assumption. +Qed. + +Theorem def_add_0_l : forall y : N, 0 ++ y == y. +Proof. +intro y. unfold def_add. now rewrite recursion_0. +Qed. + +Theorem def_add_succ_l : forall x y : N, S x ++ y == S (x ++ y). +Proof. +intros x y; unfold def_add. +rewrite (@recursion_succ N Neq); try reflexivity. +unfold fun2_wd. intros _ _ _ m1 m2 H2. now rewrite H2. +Qed. + +Theorem def_add_add : forall n m : N, n ++ m == n + m. +Proof. +intros n m; induct n. +now rewrite def_add_0_l, add_0_l. +intros n H. now rewrite def_add_succ_l, add_succ_l, H. +Qed. + +(*****************************************************) +(** Multiplication *) + +Definition def_mul (x y : N) := recursion 0 (fun _ p => p ++ x) y. + +Infix Local "**" := def_mul (at level 40, left associativity). + +Lemma def_mul_step_wd : forall x : N, fun2_wd Neq Neq Neq (fun _ p => def_add p x). +Proof. +unfold fun2_wd. intros. now apply def_add_wd. +Qed. + +Lemma def_mul_step_equal : + forall x x' : N, x == x' -> + fun2_eq Neq Neq Neq (fun _ p => def_add p x) (fun x p => def_add p x'). +Proof. +unfold fun2_eq; intros; apply def_add_wd; assumption. +Qed. + +Add Morphism def_mul with signature Neq ==> Neq ==> Neq as def_mul_wd. +Proof. +unfold def_mul. +intros x x' Exx' y y' Eyy'. +apply recursion_wd with (Aeq := Neq). +reflexivity. apply def_mul_step_equal. assumption. assumption. +Qed. + +Theorem def_mul_0_r : forall x : N, x ** 0 == 0. +Proof. +intro. unfold def_mul. now rewrite recursion_0. +Qed. + +Theorem def_mul_succ_r : forall x y : N, x ** S y == x ** y ++ x. +Proof. +intros x y; unfold def_mul. +now rewrite (@recursion_succ N Neq); [| apply def_mul_step_wd |]. +Qed. + +Theorem def_mul_mul : forall n m : N, n ** m == n * m. +Proof. +intros n m; induct m. +now rewrite def_mul_0_r, mul_0_r. +intros m IH; now rewrite def_mul_succ_r, mul_succ_r, def_add_add, IH. +Qed. + +(*****************************************************) +(** Order *) + +Definition def_ltb (m : N) : N -> bool := +recursion + (if_zero false true) + (fun _ f => fun n => recursion false (fun n' _ => f n') n) + m. + +Infix Local "<<" := def_ltb (at level 70, no associativity). + +Lemma lt_base_wd : fun_wd Neq (@eq bool) (if_zero false true). +unfold fun_wd; intros; now apply if_zero_wd. +Qed. + +Lemma lt_step_wd : +fun2_wd Neq (fun_eq Neq (@eq bool)) (fun_eq Neq (@eq bool)) + (fun _ f => fun n => recursion false (fun n' _ => f n') n). +Proof. +unfold fun2_wd, fun_eq. +intros x x' Exx' f f' Eff' y y' Eyy'. +apply recursion_wd with (Aeq := @eq bool). +reflexivity. +unfold fun2_eq; intros; now apply Eff'. +assumption. +Qed. + +Lemma lt_curry_wd : + forall m m' : N, m == m' -> fun_eq Neq (@eq bool) (def_ltb m) (def_ltb m'). +Proof. +unfold def_ltb. +intros m m' Emm'. +apply recursion_wd with (Aeq := fun_eq Neq (@eq bool)). +apply lt_base_wd. +apply lt_step_wd. +assumption. +Qed. + +Add Morphism def_ltb with signature Neq ==> Neq ==> (@eq bool) as def_ltb_wd. +Proof. +intros; now apply lt_curry_wd. +Qed. + +Theorem def_ltb_base : forall n : N, 0 << n = if_zero false true n. +Proof. +intro n; unfold def_ltb; now rewrite recursion_0. +Qed. + +Theorem def_ltb_step : + forall m n : N, S m << n = recursion false (fun n' _ => m << n') n. +Proof. +intros m n; unfold def_ltb. +pose proof + (@recursion_succ + (N -> bool) + (fun_eq Neq (@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. +now rewrite H. +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)? *) + +Theorem def_ltb_0 : forall n : N, n << 0 = false. +Proof. +cases n. +rewrite def_ltb_base; now rewrite if_zero_0. +intro n; rewrite def_ltb_step. now rewrite recursion_0. +Qed. + +Theorem def_ltb_0_succ : forall n : N, 0 << S n = true. +Proof. +intro n; rewrite def_ltb_base; now rewrite if_zero_succ. +Qed. + +Theorem succ_def_ltb_mono : forall n m : N, (S n << S m) = (n << m). +Proof. +intros n m. +rewrite def_ltb_step. rewrite (@recursion_succ bool (@eq bool)); try reflexivity. +unfold fun2_wd; intros; now apply def_ltb_wd. +Qed. + +Theorem def_ltb_lt : forall n m : N, n << m = true <-> n < m. +Proof. +double_induct n m. +cases m. +rewrite def_ltb_0. split; intro H; [discriminate H | false_hyp H nlt_0_r]. +intro n. rewrite def_ltb_0_succ. split; intro; [apply lt_0_succ | reflexivity]. +intro n. rewrite def_ltb_0. split; intro H; [discriminate | false_hyp H nlt_0_r]. +intros n m. rewrite succ_def_ltb_mono. now rewrite <- succ_lt_mono. +Qed. + +(* +(*****************************************************) +(** Even *) + +Definition even (x : N) := recursion true (fun _ p => negb p) x. + +Lemma even_step_wd : fun2_wd Neq (@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 Neq ==> (@eq bool) as even_wd. +Proof. +unfold even; intros. +apply recursion_wd with (A := bool) (Aeq := (@eq bool)). +now unfold eq_bool. +unfold fun2_eq. 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 Neq Neq. + +Add Relation (prod N N) E2 +reflexivity proved by (prod_rel_refl N N Neq Neq E_equiv E_equiv) +symmetry proved by (prod_rel_symm N N Neq Neq E_equiv E_equiv) +transitivity proved by (prod_rel_trans N N Neq Neq E_equiv E_equiv) +as E2_rel. + +Lemma half_step_wd: fun2_wd Neq 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 Neq ==> Neq 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 (Aeq := E2); unfold E2. +unfold E2. +unfold prod_rel; simpl; now split. +unfold fun2_eq, 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 Neq ==> Neq as log_wd. +Proof. +intros x x' Exx'. unfold log. +apply strong_rec_wd with (Aeq := Neq); try (reflexivity || assumption). +unfold fun2_eq. 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. +*) +End NdefOpsPropFunct. + diff --git a/theories/Numbers/Natural/Abstract/NIso.v b/theories/Numbers/Natural/Abstract/NIso.v new file mode 100644 index 00000000..f6ccf3db --- /dev/null +++ b/theories/Numbers/Natural/Abstract/NIso.v @@ -0,0 +1,122 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NIso.v 10934 2008-05-15 21:58:20Z letouzey $ i*) + +Require Import NBase. + +Module Homomorphism (NAxiomsMod1 NAxiomsMod2 : NAxiomsSig). + +Module NBasePropMod2 := NBasePropFunct NAxiomsMod2. + +Notation Local N1 := NAxiomsMod1.N. +Notation Local N2 := NAxiomsMod2.N. +Notation Local Eq1 := NAxiomsMod1.Neq. +Notation Local Eq2 := NAxiomsMod2.Neq. +Notation Local O1 := NAxiomsMod1.N0. +Notation Local O2 := NAxiomsMod2.N0. +Notation Local S1 := NAxiomsMod1.S. +Notation Local S2 := NAxiomsMod2.S. +Notation Local "n == m" := (Eq2 n m) (at level 70, no associativity). + +Definition homomorphism (f : N1 -> N2) : Prop := + f O1 == O2 /\ forall n : N1, f (S1 n) == S2 (f n). + +Definition natural_isomorphism : N1 -> N2 := + NAxiomsMod1.recursion O2 (fun (n : N1) (p : N2) => S2 p). + +Add Morphism natural_isomorphism with signature Eq1 ==> Eq2 as natural_isomorphism_wd. +Proof. +unfold natural_isomorphism. +intros n m Eqxy. +apply NAxiomsMod1.recursion_wd with (Aeq := Eq2). +reflexivity. +unfold fun2_eq. intros _ _ _ y' y'' H. now apply NBasePropMod2.succ_wd. +assumption. +Qed. + +Theorem natural_isomorphism_0 : natural_isomorphism O1 == O2. +Proof. +unfold natural_isomorphism; now rewrite NAxiomsMod1.recursion_0. +Qed. + +Theorem natural_isomorphism_succ : + forall n : N1, natural_isomorphism (S1 n) == S2 (natural_isomorphism n). +Proof. +unfold natural_isomorphism. +intro n. now rewrite (@NAxiomsMod1.recursion_succ N2 NAxiomsMod2.Neq) ; +[ | | unfold fun2_wd; intros; apply NBasePropMod2.succ_wd]. +Qed. + +Theorem hom_nat_iso : homomorphism natural_isomorphism. +Proof. +unfold homomorphism, natural_isomorphism; split; +[exact natural_isomorphism_0 | exact natural_isomorphism_succ]. +Qed. + +End Homomorphism. + +Module Inverse (NAxiomsMod1 NAxiomsMod2 : NAxiomsSig). + +Module Import NBasePropMod1 := NBasePropFunct NAxiomsMod1. +(* This makes the tactic induct available. Since it is taken from +(NBasePropFunct NAxiomsMod1), it refers to induction on N1. *) + +Module Hom12 := Homomorphism NAxiomsMod1 NAxiomsMod2. +Module Hom21 := Homomorphism NAxiomsMod2 NAxiomsMod1. + +Notation Local N1 := NAxiomsMod1.N. +Notation Local N2 := NAxiomsMod2.N. +Notation Local h12 := Hom12.natural_isomorphism. +Notation Local h21 := Hom21.natural_isomorphism. + +Notation Local "n == m" := (NAxiomsMod1.Neq n m) (at level 70, no associativity). + +Lemma inverse_nat_iso : forall n : N1, h21 (h12 n) == n. +Proof. +induct n. +now rewrite Hom12.natural_isomorphism_0, Hom21.natural_isomorphism_0. +intros n IH. +now rewrite Hom12.natural_isomorphism_succ, Hom21.natural_isomorphism_succ, IH. +Qed. + +End Inverse. + +Module Isomorphism (NAxiomsMod1 NAxiomsMod2 : NAxiomsSig). + +Module Hom12 := Homomorphism NAxiomsMod1 NAxiomsMod2. +Module Hom21 := Homomorphism NAxiomsMod2 NAxiomsMod1. + +Module Inverse12 := Inverse NAxiomsMod1 NAxiomsMod2. +Module Inverse21 := Inverse NAxiomsMod2 NAxiomsMod1. + +Notation Local N1 := NAxiomsMod1.N. +Notation Local N2 := NAxiomsMod2.N. +Notation Local Eq1 := NAxiomsMod1.Neq. +Notation Local Eq2 := NAxiomsMod2.Neq. +Notation Local h12 := Hom12.natural_isomorphism. +Notation Local h21 := Hom21.natural_isomorphism. + +Definition isomorphism (f1 : N1 -> N2) (f2 : N2 -> N1) : Prop := + Hom12.homomorphism f1 /\ Hom21.homomorphism f2 /\ + forall n : N1, Eq1 (f2 (f1 n)) n /\ + forall n : N2, Eq2 (f1 (f2 n)) n. + +Theorem iso_nat_iso : isomorphism h12 h21. +Proof. +unfold isomorphism. +split. apply Hom12.hom_nat_iso. +split. apply Hom21.hom_nat_iso. +split. apply Inverse12.inverse_nat_iso. +apply Inverse21.inverse_nat_iso. +Qed. + +End Isomorphism. + diff --git a/theories/Numbers/Natural/Abstract/NMul.v b/theories/Numbers/Natural/Abstract/NMul.v new file mode 100644 index 00000000..0b00f689 --- /dev/null +++ b/theories/Numbers/Natural/Abstract/NMul.v @@ -0,0 +1,87 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NMul.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export NAdd. + +Module NMulPropFunct (Import NAxiomsMod : NAxiomsSig). +Module Export NAddPropMod := NAddPropFunct NAxiomsMod. +Open Local Scope NatScope. + +Theorem mul_wd : + forall n1 n2 : N, n1 == n2 -> forall m1 m2 : N, m1 == m2 -> n1 * m1 == n2 * m2. +Proof NZmul_wd. + +Theorem mul_0_l : forall n : N, 0 * n == 0. +Proof NZmul_0_l. + +Theorem mul_succ_l : forall n m : N, (S n) * m == n * m + m. +Proof NZmul_succ_l. + +(** Theorems that are valid for both natural numbers and integers *) + +Theorem mul_0_r : forall n, n * 0 == 0. +Proof NZmul_0_r. + +Theorem mul_succ_r : forall n m, n * (S m) == n * m + n. +Proof NZmul_succ_r. + +Theorem mul_comm : forall n m : N, n * m == m * n. +Proof NZmul_comm. + +Theorem mul_add_distr_r : forall n m p : N, (n + m) * p == n * p + m * p. +Proof NZmul_add_distr_r. + +Theorem mul_add_distr_l : forall n m p : N, n * (m + p) == n * m + n * p. +Proof NZmul_add_distr_l. + +Theorem mul_assoc : forall n m p : N, n * (m * p) == (n * m) * p. +Proof NZmul_assoc. + +Theorem mul_1_l : forall n : N, 1 * n == n. +Proof NZmul_1_l. + +Theorem mul_1_r : forall n : N, n * 1 == n. +Proof NZmul_1_r. + +(* Theorems that cannot be proved in NZMul *) + +(* In proving the correctness of the definition of multiplication on +integers constructed from pairs of natural numbers, we'll need the +following fact about natural numbers: + +a * n + u == a * m + v -> n + m' == n' + m -> a * n' + u = a * m' + v + +Here n + m' == n' + m expresses equality of integers (n, m) and (n', m'), +since a pair (a, b) of natural numbers represents the integer a - b. On +integers, the formula above could be proved by moving a * m to the left, +factoring out a and replacing n - m by n' - m'. However, the formula is +required in the process of constructing integers, so it has to be proved +for natural numbers, where terms cannot be moved from one side of an +equation to the other. The proof uses the cancellation laws add_cancel_l +and add_cancel_r. *) + +Theorem add_mul_repl_pair : forall a n m n' m' u v : N, + a * n + u == a * m + v -> n + m' == n' + m -> a * n' + u == a * m' + v. +Proof. +intros a n m n' m' u v H1 H2. +apply (@NZmul_wd a a) in H2; [| reflexivity]. +do 2 rewrite mul_add_distr_l in H2. symmetry in H2. +pose proof (NZadd_wd _ _ H1 _ _ H2) as H3. +rewrite (add_shuffle1 (a * m)), (add_comm (a * m) (a * n)) in H3. +do 2 rewrite <- add_assoc in H3. apply -> add_cancel_l in H3. +rewrite (add_assoc u), (add_comm (a * m)) in H3. +apply -> add_cancel_r in H3. +now rewrite (add_comm (a * n') u), (add_comm (a * m') v). +Qed. + +End NMulPropFunct. + diff --git a/theories/Numbers/Natural/Abstract/NMulOrder.v b/theories/Numbers/Natural/Abstract/NMulOrder.v new file mode 100644 index 00000000..aa21fb50 --- /dev/null +++ b/theories/Numbers/Natural/Abstract/NMulOrder.v @@ -0,0 +1,131 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NMulOrder.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export NAddOrder. + +Module NMulOrderPropFunct (Import NAxiomsMod : NAxiomsSig). +Module Export NAddOrderPropMod := NAddOrderPropFunct NAxiomsMod. +Open Local Scope NatScope. + +Theorem mul_lt_pred : + forall p q n m : N, S p == q -> (p * n < p * m <-> q * n + m < q * m + n). +Proof NZmul_lt_pred. + +Theorem mul_lt_mono_pos_l : forall p n m : N, 0 < p -> (n < m <-> p * n < p * m). +Proof NZmul_lt_mono_pos_l. + +Theorem mul_lt_mono_pos_r : forall p n m : N, 0 < p -> (n < m <-> n * p < m * p). +Proof NZmul_lt_mono_pos_r. + +Theorem mul_cancel_l : forall n m p : N, p ~= 0 -> (p * n == p * m <-> n == m). +Proof NZmul_cancel_l. + +Theorem mul_cancel_r : forall n m p : N, p ~= 0 -> (n * p == m * p <-> n == m). +Proof NZmul_cancel_r. + +Theorem mul_id_l : forall n m : N, m ~= 0 -> (n * m == m <-> n == 1). +Proof NZmul_id_l. + +Theorem mul_id_r : forall n m : N, n ~= 0 -> (n * m == n <-> m == 1). +Proof NZmul_id_r. + +Theorem mul_le_mono_pos_l : forall n m p : N, 0 < p -> (n <= m <-> p * n <= p * m). +Proof NZmul_le_mono_pos_l. + +Theorem mul_le_mono_pos_r : forall n m p : N, 0 < p -> (n <= m <-> n * p <= m * p). +Proof NZmul_le_mono_pos_r. + +Theorem mul_pos_pos : forall n m : N, 0 < n -> 0 < m -> 0 < n * m. +Proof NZmul_pos_pos. + +Theorem lt_1_mul_pos : forall n m : N, 1 < n -> 0 < m -> 1 < n * m. +Proof NZlt_1_mul_pos. + +Theorem eq_mul_0 : forall n m : N, n * m == 0 <-> n == 0 \/ m == 0. +Proof NZeq_mul_0. + +Theorem neq_mul_0 : forall n m : N, n ~= 0 /\ m ~= 0 <-> n * m ~= 0. +Proof NZneq_mul_0. + +Theorem eq_square_0 : forall n : N, n * n == 0 <-> n == 0. +Proof NZeq_square_0. + +Theorem eq_mul_0_l : forall n m : N, n * m == 0 -> m ~= 0 -> n == 0. +Proof NZeq_mul_0_l. + +Theorem eq_mul_0_r : forall n m : N, n * m == 0 -> n ~= 0 -> m == 0. +Proof NZeq_mul_0_r. + +Theorem square_lt_mono : forall n m : N, n < m <-> n * n < m * m. +Proof. +intros n m; split; intro; +[apply NZsquare_lt_mono_nonneg | apply NZsquare_lt_simpl_nonneg]; +try assumption; apply le_0_l. +Qed. + +Theorem square_le_mono : forall n m : N, n <= m <-> n * n <= m * m. +Proof. +intros n m; split; intro; +[apply NZsquare_le_mono_nonneg | apply NZsquare_le_simpl_nonneg]; +try assumption; apply le_0_l. +Qed. + +Theorem mul_2_mono_l : forall n m : N, n < m -> 1 + (1 + 1) * n < (1 + 1) * m. +Proof NZmul_2_mono_l. + +(* Theorems that are either not valid on Z or have different proofs on N and Z *) + +Theorem mul_le_mono_l : forall n m p : N, n <= m -> p * n <= p * m. +Proof. +intros; apply NZmul_le_mono_nonneg_l. apply le_0_l. assumption. +Qed. + +Theorem mul_le_mono_r : forall n m p : N, n <= m -> n * p <= m * p. +Proof. +intros; apply NZmul_le_mono_nonneg_r. apply le_0_l. assumption. +Qed. + +Theorem mul_lt_mono : forall n m p q : N, n < m -> p < q -> n * p < m * q. +Proof. +intros; apply NZmul_lt_mono_nonneg; try assumption; apply le_0_l. +Qed. + +Theorem mul_le_mono : forall n m p q : N, n <= m -> p <= q -> n * p <= m * q. +Proof. +intros; apply NZmul_le_mono_nonneg; try assumption; apply le_0_l. +Qed. + +Theorem lt_0_mul : forall n m : N, n * m > 0 <-> n > 0 /\ m > 0. +Proof. +intros n m; split; [intro H | intros [H1 H2]]. +apply -> NZlt_0_mul in H. destruct H as [[H1 H2] | [H1 H2]]. now split. false_hyp H1 nlt_0_r. +now apply NZmul_pos_pos. +Qed. + +Notation mul_pos := lt_0_mul (only parsing). + +Theorem eq_mul_1 : forall n m : N, n * m == 1 <-> n == 1 /\ m == 1. +Proof. +intros n m. +split; [| intros [H1 H2]; now rewrite H1, H2, mul_1_l]. +intro H; destruct (NZlt_trichotomy n 1) as [H1 | [H1 | H1]]. +apply -> lt_1_r in H1. rewrite H1, mul_0_l in H. false_hyp H neq_0_succ. +rewrite H1, mul_1_l in H; now split. +destruct (eq_0_gt_0_cases m) as [H2 | H2]. +rewrite H2, mul_0_r in H; false_hyp H neq_0_succ. +apply -> (mul_lt_mono_pos_r m) in H1; [| assumption]. rewrite mul_1_l in H1. +assert (H3 : 1 < n * m) by now apply (lt_1_l 0 m). +rewrite H in H3; false_hyp H3 lt_irrefl. +Qed. + +End NMulOrderPropFunct. + diff --git a/theories/Numbers/Natural/Abstract/NOrder.v b/theories/Numbers/Natural/Abstract/NOrder.v new file mode 100644 index 00000000..826ffa2c --- /dev/null +++ b/theories/Numbers/Natural/Abstract/NOrder.v @@ -0,0 +1,539 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NOrder.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export NMul. + +Module NOrderPropFunct (Import NAxiomsMod : NAxiomsSig). +Module Export NMulPropMod := NMulPropFunct NAxiomsMod. +Open Local Scope NatScope. + +(* The tactics le_less, le_equal and le_elim are inherited from NZOrder.v *) + +(* Axioms *) + +Theorem lt_wd : + forall n1 n2 : N, n1 == n2 -> forall m1 m2 : N, m1 == m2 -> (n1 < m1 <-> n2 < m2). +Proof NZlt_wd. + +Theorem le_wd : + forall n1 n2 : N, n1 == n2 -> forall m1 m2 : N, m1 == m2 -> (n1 <= m1 <-> n2 <= m2). +Proof NZle_wd. + +Theorem min_wd : + forall n1 n2 : N, n1 == n2 -> forall m1 m2 : N, m1 == m2 -> min n1 m1 == min n2 m2. +Proof NZmin_wd. + +Theorem max_wd : + forall n1 n2 : N, n1 == n2 -> forall m1 m2 : N, m1 == m2 -> max n1 m1 == max n2 m2. +Proof NZmax_wd. + +Theorem lt_eq_cases : forall n m : N, n <= m <-> n < m \/ n == m. +Proof NZlt_eq_cases. + +Theorem lt_irrefl : forall n : N, ~ n < n. +Proof NZlt_irrefl. + +Theorem lt_succ_r : forall n m : N, n < S m <-> n <= m. +Proof NZlt_succ_r. + +Theorem min_l : forall n m : N, n <= m -> min n m == n. +Proof NZmin_l. + +Theorem min_r : forall n m : N, m <= n -> min n m == m. +Proof NZmin_r. + +Theorem max_l : forall n m : N, m <= n -> max n m == n. +Proof NZmax_l. + +Theorem max_r : forall n m : N, n <= m -> max n m == m. +Proof NZmax_r. + +(* Renaming theorems from NZOrder.v *) + +Theorem lt_le_incl : forall n m : N, n < m -> n <= m. +Proof NZlt_le_incl. + +Theorem eq_le_incl : forall n m : N, n == m -> n <= m. +Proof NZeq_le_incl. + +Theorem lt_neq : forall n m : N, n < m -> n ~= m. +Proof NZlt_neq. + +Theorem le_neq : forall n m : N, n < m <-> n <= m /\ n ~= m. +Proof NZle_neq. + +Theorem le_refl : forall n : N, n <= n. +Proof NZle_refl. + +Theorem lt_succ_diag_r : forall n : N, n < S n. +Proof NZlt_succ_diag_r. + +Theorem le_succ_diag_r : forall n : N, n <= S n. +Proof NZle_succ_diag_r. + +Theorem lt_0_1 : 0 < 1. +Proof NZlt_0_1. + +Theorem le_0_1 : 0 <= 1. +Proof NZle_0_1. + +Theorem lt_lt_succ_r : forall n m : N, n < m -> n < S m. +Proof NZlt_lt_succ_r. + +Theorem le_le_succ_r : forall n m : N, n <= m -> n <= S m. +Proof NZle_le_succ_r. + +Theorem le_succ_r : forall n m : N, n <= S m <-> n <= m \/ n == S m. +Proof NZle_succ_r. + +Theorem neq_succ_diag_l : forall n : N, S n ~= n. +Proof NZneq_succ_diag_l. + +Theorem neq_succ_diag_r : forall n : N, n ~= S n. +Proof NZneq_succ_diag_r. + +Theorem nlt_succ_diag_l : forall n : N, ~ S n < n. +Proof NZnlt_succ_diag_l. + +Theorem nle_succ_diag_l : forall n : N, ~ S n <= n. +Proof NZnle_succ_diag_l. + +Theorem le_succ_l : forall n m : N, S n <= m <-> n < m. +Proof NZle_succ_l. + +Theorem lt_succ_l : forall n m : N, S n < m -> n < m. +Proof NZlt_succ_l. + +Theorem succ_lt_mono : forall n m : N, n < m <-> S n < S m. +Proof NZsucc_lt_mono. + +Theorem succ_le_mono : forall n m : N, n <= m <-> S n <= S m. +Proof NZsucc_le_mono. + +Theorem lt_asymm : forall n m : N, n < m -> ~ m < n. +Proof NZlt_asymm. + +Notation lt_ngt := lt_asymm (only parsing). + +Theorem lt_trans : forall n m p : N, n < m -> m < p -> n < p. +Proof NZlt_trans. + +Theorem le_trans : forall n m p : N, n <= m -> m <= p -> n <= p. +Proof NZle_trans. + +Theorem le_lt_trans : forall n m p : N, n <= m -> m < p -> n < p. +Proof NZle_lt_trans. + +Theorem lt_le_trans : forall n m p : N, n < m -> m <= p -> n < p. +Proof NZlt_le_trans. + +Theorem le_antisymm : forall n m : N, n <= m -> m <= n -> n == m. +Proof NZle_antisymm. + +(** Trichotomy, decidability, and double negation elimination *) + +Theorem lt_trichotomy : forall n m : N, n < m \/ n == m \/ m < n. +Proof NZlt_trichotomy. + +Notation lt_eq_gt_cases := lt_trichotomy (only parsing). + +Theorem lt_gt_cases : forall n m : N, n ~= m <-> n < m \/ n > m. +Proof NZlt_gt_cases. + +Theorem le_gt_cases : forall n m : N, n <= m \/ n > m. +Proof NZle_gt_cases. + +Theorem lt_ge_cases : forall n m : N, n < m \/ n >= m. +Proof NZlt_ge_cases. + +Theorem le_ge_cases : forall n m : N, n <= m \/ n >= m. +Proof NZle_ge_cases. + +Theorem le_ngt : forall n m : N, n <= m <-> ~ n > m. +Proof NZle_ngt. + +Theorem nlt_ge : forall n m : N, ~ n < m <-> n >= m. +Proof NZnlt_ge. + +Theorem lt_dec : forall n m : N, decidable (n < m). +Proof NZlt_dec. + +Theorem lt_dne : forall n m : N, ~ ~ n < m <-> n < m. +Proof NZlt_dne. + +Theorem nle_gt : forall n m : N, ~ n <= m <-> n > m. +Proof NZnle_gt. + +Theorem lt_nge : forall n m : N, n < m <-> ~ n >= m. +Proof NZlt_nge. + +Theorem le_dec : forall n m : N, decidable (n <= m). +Proof NZle_dec. + +Theorem le_dne : forall n m : N, ~ ~ n <= m <-> n <= m. +Proof NZle_dne. + +Theorem nlt_succ_r : forall n m : N, ~ m < S n <-> n < m. +Proof NZnlt_succ_r. + +Theorem lt_exists_pred : + forall z n : N, z < n -> exists k : N, n == S k /\ z <= k. +Proof NZlt_exists_pred. + +Theorem lt_succ_iter_r : + forall (n : nat) (m : N), m < NZsucc_iter (Datatypes.S n) m. +Proof NZlt_succ_iter_r. + +Theorem neq_succ_iter_l : + forall (n : nat) (m : N), NZsucc_iter (Datatypes.S n) m ~= m. +Proof NZneq_succ_iter_l. + +(** Stronger variant of induction with assumptions n >= 0 (n < 0) +in the induction step *) + +Theorem right_induction : + forall A : N -> Prop, predicate_wd Neq A -> + forall z : N, A z -> + (forall n : N, z <= n -> A n -> A (S n)) -> + forall n : N, z <= n -> A n. +Proof NZright_induction. + +Theorem left_induction : + forall A : N -> Prop, predicate_wd Neq A -> + forall z : N, A z -> + (forall n : N, n < z -> A (S n) -> A n) -> + forall n : N, n <= z -> A n. +Proof NZleft_induction. + +Theorem right_induction' : + forall A : N -> Prop, predicate_wd Neq A -> + forall z : N, + (forall n : N, n <= z -> A n) -> + (forall n : N, z <= n -> A n -> A (S n)) -> + forall n : N, A n. +Proof NZright_induction'. + +Theorem left_induction' : + forall A : N -> Prop, predicate_wd Neq A -> + forall z : N, + (forall n : N, z <= n -> A n) -> + (forall n : N, n < z -> A (S n) -> A n) -> + forall n : N, A n. +Proof NZleft_induction'. + +Theorem strong_right_induction : + forall A : N -> Prop, predicate_wd Neq A -> + forall z : N, + (forall n : N, z <= n -> (forall m : N, z <= m -> m < n -> A m) -> A n) -> + forall n : N, z <= n -> A n. +Proof NZstrong_right_induction. + +Theorem strong_left_induction : + forall A : N -> Prop, predicate_wd Neq A -> + forall z : N, + (forall n : N, n <= z -> (forall m : N, m <= z -> S n <= m -> A m) -> A n) -> + forall n : N, n <= z -> A n. +Proof NZstrong_left_induction. + +Theorem strong_right_induction' : + forall A : N -> Prop, predicate_wd Neq A -> + forall z : N, + (forall n : N, n <= z -> A n) -> + (forall n : N, z <= n -> (forall m : N, z <= m -> m < n -> A m) -> A n) -> + forall n : N, A n. +Proof NZstrong_right_induction'. + +Theorem strong_left_induction' : + forall A : N -> Prop, predicate_wd Neq A -> + forall z : N, + (forall n : N, z <= n -> A n) -> + (forall n : N, n <= z -> (forall m : N, m <= z -> S n <= m -> A m) -> A n) -> + forall n : N, A n. +Proof NZstrong_left_induction'. + +Theorem order_induction : + forall A : N -> Prop, predicate_wd Neq A -> + forall z : N, A z -> + (forall n : N, z <= n -> A n -> A (S n)) -> + (forall n : N, n < z -> A (S n) -> A n) -> + forall n : N, A n. +Proof NZorder_induction. + +Theorem order_induction' : + forall A : N -> Prop, predicate_wd Neq A -> + forall z : N, A z -> + (forall n : N, z <= n -> A n -> A (S n)) -> + (forall n : N, n <= z -> A n -> A (P n)) -> + forall n : N, A n. +Proof NZorder_induction'. + +(* We don't need order_induction_0 and order_induction'_0 (see NZOrder and +ZOrder) since they boil down to regular induction *) + +(** Elimintation principle for < *) + +Theorem lt_ind : + forall A : N -> Prop, predicate_wd Neq A -> + forall n : N, + A (S n) -> + (forall m : N, n < m -> A m -> A (S m)) -> + forall m : N, n < m -> A m. +Proof NZlt_ind. + +(** Elimintation principle for <= *) + +Theorem le_ind : + forall A : N -> Prop, predicate_wd Neq A -> + forall n : N, + A n -> + (forall m : N, n <= m -> A m -> A (S m)) -> + forall m : N, n <= m -> A m. +Proof NZle_ind. + +(** Well-founded relations *) + +Theorem lt_wf : forall z : N, well_founded (fun n m : N => z <= n /\ n < m). +Proof NZlt_wf. + +Theorem gt_wf : forall z : N, well_founded (fun n m : N => m < n /\ n <= z). +Proof NZgt_wf. + +Theorem lt_wf_0 : well_founded lt. +Proof. +assert (H : relations_eq lt (fun n m : N => 0 <= n /\ n < m)). +intros x y; split. +intro H; split; [apply le_0_l | assumption]. now intros [_ H]. +rewrite H; apply lt_wf. +(* does not work: +setoid_replace lt with (fun n m : N => 0 <= n /\ n < m) using relation relations_eq.*) +Qed. + +(* Theorems that are true for natural numbers but not for integers *) + +(* "le_0_l : forall n : N, 0 <= n" was proved in NBase.v *) + +Theorem nlt_0_r : forall n : N, ~ n < 0. +Proof. +intro n; apply -> le_ngt. apply le_0_l. +Qed. + +Theorem nle_succ_0 : forall n : N, ~ (S n <= 0). +Proof. +intros n H; apply -> le_succ_l in H; false_hyp H nlt_0_r. +Qed. + +Theorem le_0_r : forall n : N, n <= 0 <-> n == 0. +Proof. +intros n; split; intro H. +le_elim H; [false_hyp H nlt_0_r | assumption]. +now apply eq_le_incl. +Qed. + +Theorem lt_0_succ : forall n : N, 0 < S n. +Proof. +induct n; [apply lt_succ_diag_r | intros n H; now apply lt_lt_succ_r]. +Qed. + +Theorem neq_0_lt_0 : forall n : N, n ~= 0 <-> 0 < n. +Proof. +cases n. +split; intro H; [now elim H | intro; now apply lt_irrefl with 0]. +intro n; split; intro H; [apply lt_0_succ | apply neq_succ_0]. +Qed. + +Theorem eq_0_gt_0_cases : forall n : N, n == 0 \/ 0 < n. +Proof. +cases n. +now left. +intro; right; apply lt_0_succ. +Qed. + +Theorem zero_one : forall n : N, n == 0 \/ n == 1 \/ 1 < n. +Proof. +induct n. now left. +cases n. intros; right; now left. +intros n IH. destruct IH as [H | [H | H]]. +false_hyp H neq_succ_0. +right; right. rewrite H. apply lt_succ_diag_r. +right; right. now apply lt_lt_succ_r. +Qed. + +Theorem lt_1_r : forall n : N, n < 1 <-> n == 0. +Proof. +cases n. +split; intro; [reflexivity | apply lt_succ_diag_r]. +intros n. rewrite <- succ_lt_mono. +split; intro H; [false_hyp H nlt_0_r | false_hyp H neq_succ_0]. +Qed. + +Theorem le_1_r : forall n : N, n <= 1 <-> n == 0 \/ n == 1. +Proof. +cases n. +split; intro; [now left | apply le_succ_diag_r]. +intro n. rewrite <- succ_le_mono, le_0_r, succ_inj_wd. +split; [intro; now right | intros [H | H]; [false_hyp H neq_succ_0 | assumption]]. +Qed. + +Theorem lt_lt_0 : forall n m : N, n < m -> 0 < m. +Proof. +intros n m; induct n. +trivial. +intros n IH H. apply IH; now apply lt_succ_l. +Qed. + +Theorem lt_1_l : forall n m p : N, n < m -> m < p -> 1 < p. +Proof. +intros n m p H1 H2. +apply le_lt_trans with m. apply <- le_succ_l. apply le_lt_trans with n. +apply le_0_l. assumption. assumption. +Qed. + +(** Elimination principlies for < and <= for relations *) + +Section RelElim. + +(* FIXME: Variable R : relation N. -- does not work *) + +Variable R : N -> N -> Prop. +Hypothesis R_wd : relation_wd Neq Neq R. + +Add Morphism R with signature Neq ==> Neq ==> iff as R_morph2. +Proof. apply R_wd. Qed. + +Theorem le_ind_rel : + (forall m : N, R 0 m) -> + (forall n m : N, n <= m -> R n m -> R (S n) (S m)) -> + forall n m : N, n <= m -> R n m. +Proof. +intros Base Step; induct n. +intros; apply Base. +intros n IH m H. elim H using le_ind. +solve_predicate_wd. +apply Step; [| apply IH]; now apply eq_le_incl. +intros k H1 H2. apply -> le_succ_l in H1. apply lt_le_incl in H1. auto. +Qed. + +Theorem lt_ind_rel : + (forall m : N, R 0 (S m)) -> + (forall n m : N, n < m -> R n m -> R (S n) (S m)) -> + forall n m : N, n < m -> R n m. +Proof. +intros Base Step; induct n. +intros m H. apply lt_exists_pred in H; destruct H as [m' [H _]]. +rewrite H; apply Base. +intros n IH m H. elim H using lt_ind. +solve_predicate_wd. +apply Step; [| apply IH]; now apply lt_succ_diag_r. +intros k H1 H2. apply lt_succ_l in H1. auto. +Qed. + +End RelElim. + +(** Predecessor and order *) + +Theorem succ_pred_pos : forall n : N, 0 < n -> S (P n) == n. +Proof. +intros n H; apply succ_pred; intro H1; rewrite H1 in H. +false_hyp H lt_irrefl. +Qed. + +Theorem le_pred_l : forall n : N, P n <= n. +Proof. +cases n. +rewrite pred_0; now apply eq_le_incl. +intros; rewrite pred_succ; apply le_succ_diag_r. +Qed. + +Theorem lt_pred_l : forall n : N, n ~= 0 -> P n < n. +Proof. +cases n. +intro H; elimtype False; now apply H. +intros; rewrite pred_succ; apply lt_succ_diag_r. +Qed. + +Theorem le_le_pred : forall n m : N, n <= m -> P n <= m. +Proof. +intros n m H; apply le_trans with n. apply le_pred_l. assumption. +Qed. + +Theorem lt_lt_pred : forall n m : N, n < m -> P n < m. +Proof. +intros n m H; apply le_lt_trans with n. apply le_pred_l. assumption. +Qed. + +Theorem lt_le_pred : forall n m : N, n < m -> n <= P m. (* Converse is false for n == m == 0 *) +Proof. +intro n; cases m. +intro H; false_hyp H nlt_0_r. +intros m IH. rewrite pred_succ; now apply -> lt_succ_r. +Qed. + +Theorem lt_pred_le : forall n m : N, P n < m -> n <= m. (* Converse is false for n == m == 0 *) +Proof. +intros n m; cases n. +rewrite pred_0; intro H; now apply lt_le_incl. +intros n IH. rewrite pred_succ in IH. now apply <- le_succ_l. +Qed. + +Theorem lt_pred_lt : forall n m : N, n < P m -> n < m. +Proof. +intros n m H; apply lt_le_trans with (P m); [assumption | apply le_pred_l]. +Qed. + +Theorem le_pred_le : forall n m : N, n <= P m -> n <= m. +Proof. +intros n m H; apply le_trans with (P m); [assumption | apply le_pred_l]. +Qed. + +Theorem pred_le_mono : forall n m : N, n <= m -> P n <= P m. (* Converse is false for n == 1, m == 0 *) +Proof. +intros n m H; elim H using le_ind_rel. +solve_relation_wd. +intro; rewrite pred_0; apply le_0_l. +intros p q H1 _; now do 2 rewrite pred_succ. +Qed. + +Theorem pred_lt_mono : forall n m : N, n ~= 0 -> (n < m <-> P n < P m). +Proof. +intros n m H1; split; intro H2. +assert (m ~= 0). apply <- neq_0_lt_0. now apply lt_lt_0 with n. +now rewrite <- (succ_pred n) in H2; rewrite <- (succ_pred m) in H2 ; +[apply <- succ_lt_mono | | |]. +assert (m ~= 0). apply <- neq_0_lt_0. apply lt_lt_0 with (P n). +apply lt_le_trans with (P m). assumption. apply le_pred_l. +apply -> succ_lt_mono in H2. now do 2 rewrite succ_pred in H2. +Qed. + +Theorem lt_succ_lt_pred : forall n m : N, S n < m <-> n < P m. +Proof. +intros n m. rewrite pred_lt_mono by apply neq_succ_0. now rewrite pred_succ. +Qed. + +Theorem le_succ_le_pred : forall n m : N, S n <= m -> n <= P m. (* Converse is false for n == m == 0 *) +Proof. +intros n m H. apply lt_le_pred. now apply -> le_succ_l. +Qed. + +Theorem lt_pred_lt_succ : forall n m : N, P n < m -> n < S m. (* Converse is false for n == m == 0 *) +Proof. +intros n m H. apply <- lt_succ_r. now apply lt_pred_le. +Qed. + +Theorem le_pred_le_succ : forall n m : N, P n <= m <-> n <= S m. +Proof. +intros n m; cases n. +rewrite pred_0. split; intro H; apply le_0_l. +intro n. rewrite pred_succ. apply succ_le_mono. +Qed. + +End NOrderPropFunct. + diff --git a/theories/Numbers/Natural/Abstract/NStrongRec.v b/theories/Numbers/Natural/Abstract/NStrongRec.v new file mode 100644 index 00000000..031dbdea --- /dev/null +++ b/theories/Numbers/Natural/Abstract/NStrongRec.v @@ -0,0 +1,133 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NStrongRec.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +(** This file defined the strong (course-of-value, well-founded) recursion +and proves its properties *) + +Require Export NSub. + +Module NStrongRecPropFunct (Import NAxiomsMod : NAxiomsSig). +Module Export NSubPropMod := NSubPropFunct NAxiomsMod. +Open Local Scope NatScope. + +Section StrongRecursion. + +Variable A : Set. +Variable Aeq : relation A. + +Notation Local "x ==A y" := (Aeq x y) (at level 70, no associativity). + +Hypothesis Aeq_equiv : equiv A Aeq. + +Add Relation A Aeq + reflexivity proved by (proj1 Aeq_equiv) + symmetry proved by (proj2 (proj2 Aeq_equiv)) + transitivity proved by (proj1 (proj2 Aeq_equiv)) +as Aeq_rel. + +Definition strong_rec (a : A) (f : N -> (N -> A) -> A) (n : N) : A := +recursion + (fun _ : N => a) + (fun (m : N) (p : N -> A) (k : N) => f k p) + (S n) + n. + +Theorem strong_rec_wd : +forall a a' : A, a ==A a' -> + forall f f', fun2_eq Neq (fun_eq Neq Aeq) Aeq f f' -> + forall n n', n == n' -> + strong_rec a f n ==A strong_rec a' f' n'. +Proof. +intros a a' Eaa' f f' Eff' n n' Enn'. +(* First we prove that recursion (which is on type N -> A) returns +extensionally equal functions, and then we use the fact that n == n' *) +assert (H : fun_eq Neq Aeq + (recursion + (fun _ : N => a) + (fun (m : N) (p : N -> A) (k : N) => f k p) + (S n)) + (recursion + (fun _ : N => a') + (fun (m : N) (p : N -> A) (k : N) => f' k p) + (S n'))). +apply recursion_wd with (Aeq := fun_eq Neq Aeq). +unfold fun_eq; now intros. +unfold fun2_eq. intros y y' Eyy' p p' Epp'. unfold fun_eq. auto. +now rewrite Enn'. +unfold strong_rec. +now apply H. +Qed. + +(*Section FixPoint. + +Variable a : A. +Variable f : N -> (N -> A) -> A. + +Hypothesis f_wd : fun2_wd Neq (fun_eq Neq Aeq) Aeq f. + +Let g (n : N) : A := strong_rec a f n. + +Add Morphism g with signature Neq ==> Aeq as g_wd. +Proof. +intros n1 n2 H. unfold g. now apply strong_rec_wd. +Qed. + +Theorem NtoA_eq_symm : symmetric (N -> A) (fun_eq Neq Aeq). +Proof. +apply fun_eq_symm. +exact (proj2 (proj2 NZeq_equiv)). +exact (proj2 (proj2 Aeq_equiv)). +Qed. + +Theorem NtoA_eq_trans : transitive (N -> A) (fun_eq Neq Aeq). +Proof. +apply fun_eq_trans. +exact (proj1 NZeq_equiv). +exact (proj1 (proj2 NZeq_equiv)). +exact (proj1 (proj2 Aeq_equiv)). +Qed. + +Add Relation (N -> A) (fun_eq Neq Aeq) + symmetry proved by NtoA_eq_symm + transitivity proved by NtoA_eq_trans +as NtoA_eq_rel. + +Add Morphism f with signature Neq ==> (fun_eq Neq Aeq) ==> Aeq as f_morph. +Proof. +apply f_wd. +Qed. + +(* We need an assumption saying that for every n, the step function (f n h) +calls h only on the segment [0 ... n - 1]. This means that if h1 and h2 +coincide on values < n, then (f n h1) coincides with (f n h2) *) + +Hypothesis step_good : + forall (n : N) (h1 h2 : N -> A), + (forall m : N, m < n -> Aeq (h1 m) (h2 m)) -> Aeq (f n h1) (f n h2). + +(* Todo: +Theorem strong_rec_fixpoint : forall n : N, Aeq (g n) (f n g). +Proof. +apply induction. +unfold predicate_wd, fun_wd. +intros x y H. rewrite H. unfold fun_eq; apply g_wd. +reflexivity. +unfold g, strong_rec. +*) + +End FixPoint.*) +End StrongRecursion. + +Implicit Arguments strong_rec [A]. + +End NStrongRecPropFunct. + diff --git a/theories/Numbers/Natural/Abstract/NSub.v b/theories/Numbers/Natural/Abstract/NSub.v new file mode 100644 index 00000000..f67689dd --- /dev/null +++ b/theories/Numbers/Natural/Abstract/NSub.v @@ -0,0 +1,180 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NSub.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Export NMulOrder. + +Module NSubPropFunct (Import NAxiomsMod : NAxiomsSig). +Module Export NMulOrderPropMod := NMulOrderPropFunct NAxiomsMod. +Open Local Scope NatScope. + +Theorem sub_wd : + forall n1 n2 : N, n1 == n2 -> forall m1 m2 : N, m1 == m2 -> n1 - m1 == n2 - m2. +Proof NZsub_wd. + +Theorem sub_0_r : forall n : N, n - 0 == n. +Proof NZsub_0_r. + +Theorem sub_succ_r : forall n m : N, n - (S m) == P (n - m). +Proof NZsub_succ_r. + +Theorem sub_1_r : forall n : N, n - 1 == P n. +Proof. +intro n; rewrite sub_succ_r; now rewrite sub_0_r. +Qed. + +Theorem sub_0_l : forall n : N, 0 - n == 0. +Proof. +induct n. +apply sub_0_r. +intros n IH; rewrite sub_succ_r; rewrite IH. now apply pred_0. +Qed. + +Theorem sub_succ : forall n m : N, S n - S m == n - m. +Proof. +intro n; induct m. +rewrite sub_succ_r. do 2 rewrite sub_0_r. now rewrite pred_succ. +intros m IH. rewrite sub_succ_r. rewrite IH. now rewrite sub_succ_r. +Qed. + +Theorem sub_diag : forall n : N, n - n == 0. +Proof. +induct n. apply sub_0_r. intros n IH; rewrite sub_succ; now rewrite IH. +Qed. + +Theorem sub_gt : forall n m : N, n > m -> n - m ~= 0. +Proof. +intros n m H; elim H using lt_ind_rel; clear n m H. +solve_relation_wd. +intro; rewrite sub_0_r; apply neq_succ_0. +intros; now rewrite sub_succ. +Qed. + +Theorem add_sub_assoc : forall n m p : N, p <= m -> n + (m - p) == (n + m) - p. +Proof. +intros n m p; induct p. +intro; now do 2 rewrite sub_0_r. +intros p IH H. do 2 rewrite sub_succ_r. +rewrite <- IH by (apply lt_le_incl; now apply -> le_succ_l). +rewrite add_pred_r by (apply sub_gt; now apply -> le_succ_l). +reflexivity. +Qed. + +Theorem sub_succ_l : forall n m : N, n <= m -> S m - n == S (m - n). +Proof. +intros n m H. rewrite <- (add_1_l m). rewrite <- (add_1_l (m - n)). +symmetry; now apply add_sub_assoc. +Qed. + +Theorem add_sub : forall n m : N, (n + m) - m == n. +Proof. +intros n m. rewrite <- add_sub_assoc by (apply le_refl). +rewrite sub_diag; now rewrite add_0_r. +Qed. + +Theorem sub_add : forall n m : N, n <= m -> (m - n) + n == m. +Proof. +intros n m H. rewrite add_comm. rewrite add_sub_assoc by assumption. +rewrite add_comm. apply add_sub. +Qed. + +Theorem add_sub_eq_l : forall n m p : N, m + p == n -> n - m == p. +Proof. +intros n m p H. symmetry. +assert (H1 : m + p - m == n - m) by now rewrite H. +rewrite add_comm in H1. now rewrite add_sub in H1. +Qed. + +Theorem add_sub_eq_r : forall n m p : N, m + p == n -> n - p == m. +Proof. +intros n m p H; rewrite add_comm in H; now apply add_sub_eq_l. +Qed. + +(* This could be proved by adding m to both sides. Then the proof would +use add_sub_assoc and sub_0_le, which is proven below. *) + +Theorem add_sub_eq_nz : forall n m p : N, p ~= 0 -> n - m == p -> m + p == n. +Proof. +intros n m p H; double_induct n m. +intros m H1; rewrite sub_0_l in H1. symmetry in H1; false_hyp H1 H. +intro n; rewrite sub_0_r; now rewrite add_0_l. +intros n m IH H1. rewrite sub_succ in H1. apply IH in H1. +rewrite add_succ_l; now rewrite H1. +Qed. + +Theorem sub_add_distr : forall n m p : N, n - (m + p) == (n - m) - p. +Proof. +intros n m; induct p. +rewrite add_0_r; now rewrite sub_0_r. +intros p IH. rewrite add_succ_r; do 2 rewrite sub_succ_r. now rewrite IH. +Qed. + +Theorem add_sub_swap : forall n m p : N, p <= n -> n + m - p == n - p + m. +Proof. +intros n m p H. +rewrite (add_comm n m). +rewrite <- add_sub_assoc by assumption. +now rewrite (add_comm m (n - p)). +Qed. + +(** Sub and order *) + +Theorem le_sub_l : forall n m : N, n - m <= n. +Proof. +intro n; induct m. +rewrite sub_0_r; now apply eq_le_incl. +intros m IH. rewrite sub_succ_r. +apply le_trans with (n - m); [apply le_pred_l | assumption]. +Qed. + +Theorem sub_0_le : forall n m : N, n - m == 0 <-> n <= m. +Proof. +double_induct n m. +intro m; split; intro; [apply le_0_l | apply sub_0_l]. +intro m; rewrite sub_0_r; split; intro H; +[false_hyp H neq_succ_0 | false_hyp H nle_succ_0]. +intros n m H. rewrite <- succ_le_mono. now rewrite sub_succ. +Qed. + +(** Sub and mul *) + +Theorem mul_pred_r : forall n m : N, n * (P m) == n * m - n. +Proof. +intros n m; cases m. +now rewrite pred_0, mul_0_r, sub_0_l. +intro m; rewrite pred_succ, mul_succ_r, <- add_sub_assoc. +now rewrite sub_diag, add_0_r. +now apply eq_le_incl. +Qed. + +Theorem mul_sub_distr_r : forall n m p : N, (n - m) * p == n * p - m * p. +Proof. +intros n m p; induct n. +now rewrite sub_0_l, mul_0_l, sub_0_l. +intros n IH. destruct (le_gt_cases m n) as [H | H]. +rewrite sub_succ_l by assumption. do 2 rewrite mul_succ_l. +rewrite (add_comm ((n - m) * p) p), (add_comm (n * p) p). +rewrite <- (add_sub_assoc p (n * p) (m * p)) by now apply mul_le_mono_r. +now apply <- add_cancel_l. +assert (H1 : S n <= m); [now apply <- le_succ_l |]. +setoid_replace (S n - m) with 0 by now apply <- sub_0_le. +setoid_replace ((S n * p) - m * p) with 0 by (apply <- sub_0_le; now apply mul_le_mono_r). +apply mul_0_l. +Qed. + +Theorem mul_sub_distr_l : forall n m p : N, p * (n - m) == p * n - p * m. +Proof. +intros n m p; rewrite (mul_comm p (n - m)), (mul_comm p n), (mul_comm p m). +apply mul_sub_distr_r. +Qed. + +End NSubPropFunct. + diff --git a/theories/Numbers/Natural/BigN/BigN.v b/theories/Numbers/Natural/BigN/BigN.v new file mode 100644 index 00000000..0574c09f --- /dev/null +++ b/theories/Numbers/Natural/BigN/BigN.v @@ -0,0 +1,83 @@ +(************************************************************************) +(* 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: BigN.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +(** * Natural numbers in base 2^31 *) + +(** +Author: Arnaud Spiwack +*) + +Require Export Int31. +Require Import CyclicAxioms. +Require Import Cyclic31. +Require Import NSig. +Require Import NSigNAxioms. +Require Import NMake. +Require Import NSub. + +Module BigN <: NType := NMake.Make Int31Cyclic. + +(** Module [BigN] implements [NAxiomsSig] *) + +Module Export BigNAxiomsMod := NSig_NAxioms BigN. +Module Export BigNSubPropMod := NSubPropFunct BigNAxiomsMod. + +(** Notations about [BigN] *) + +Notation bigN := BigN.t. + +Delimit Scope bigN_scope with bigN. +Bind Scope bigN_scope with bigN. +Bind Scope bigN_scope with BigN.t. +Bind Scope bigN_scope with BigN.t_. + +Notation Local "0" := BigN.zero : bigN_scope. (* temporary notation *) +Infix "+" := BigN.add : bigN_scope. +Infix "-" := BigN.sub : bigN_scope. +Infix "*" := BigN.mul : bigN_scope. +Infix "/" := BigN.div : bigN_scope. +Infix "?=" := BigN.compare : bigN_scope. +Infix "==" := BigN.eq (at level 70, no associativity) : bigN_scope. +Infix "<" := BigN.lt : bigN_scope. +Infix "<=" := BigN.le : bigN_scope. +Notation "[ i ]" := (BigN.to_Z i) : bigN_scope. + +Open Scope bigN_scope. + +(** Example of reasoning about [BigN] *) + +Theorem succ_pred: forall q:bigN, + 0 < q -> BigN.succ (BigN.pred q) == q. +Proof. +intros; apply succ_pred. +intro H'; rewrite H' in H; discriminate. +Qed. + +(** [BigN] is a semi-ring *) + +Lemma BigNring : + semi_ring_theory BigN.zero BigN.one BigN.add BigN.mul BigN.eq. +Proof. +constructor. +exact add_0_l. +exact add_comm. +exact add_assoc. +exact mul_1_l. +exact mul_0_l. +exact mul_comm. +exact mul_assoc. +exact mul_add_distr_r. +Qed. + +Add Ring BigNr : BigNring. + +(** Todo: tactic translating from [BigN] to [Z] + omega *) + +(** Todo: micromega *) diff --git a/theories/Numbers/Natural/BigN/NMake_gen.ml b/theories/Numbers/Natural/BigN/NMake_gen.ml new file mode 100644 index 00000000..bd0fb5b1 --- /dev/null +++ b/theories/Numbers/Natural/BigN/NMake_gen.ml @@ -0,0 +1,3166 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NMake_gen.ml 11136 2008-06-18 10:41:34Z herbelin $ i*) + +(*S NMake_gen.ml : this file generates NMake.v *) + + +(*s The two parameters that control the generation: *) + +let size = 6 (* how many times should we repeat the Z/nZ --> Z/2nZ + process before relying on a generic construct *) +let gen_proof = true (* should we generate proofs ? *) + + +(*s Some utilities *) + +let t = "t" +let c = "N" +let pz n = if n == 0 then "w_0" else "W0" +let rec gen2 n = if n == 0 then "1" else if n == 1 then "2" + else "2 * " ^ (gen2 (n - 1)) +let rec genxO n s = + if n == 0 then s else " (xO" ^ (genxO (n - 1) s) ^ ")" + +(* NB: in ocaml >= 3.10, we could use Printf.ifprintf for printing to + /dev/null, but for being compatible with earlier ocaml and not + relying on system-dependent stuff like open_out "/dev/null", + let's use instead a magical hack *) + +(* Standard printer, with a final newline *) +let pr s = Printf.printf (s^^"\n") +(* Printing to /dev/null *) +let pn = (fun s -> Obj.magic (fun _ _ _ _ _ _ _ _ _ _ _ _ _ _ -> ()) + : ('a, out_channel, unit) format -> 'a) +(* Proof printer : prints iff gen_proof is true *) +let pp = if gen_proof then pr else pn +(* Printer for admitted parts : prints iff gen_proof is false *) +let pa = if not gen_proof then pr else pn +(* Same as before, but without the final newline *) +let pr0 = Printf.printf +let pp0 = if gen_proof then pr0 else pn + + +(*s The actual printing *) + +let _ = + + pr "(************************************************************************)"; + pr "(* v * The Coq Proof Assistant / The Coq Development Team *)"; + pr "(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)"; + pr "(* \\VV/ **************************************************************)"; + pr "(* // * This file is distributed under the terms of the *)"; + pr "(* * GNU Lesser General Public License Version 2.1 *)"; + pr "(************************************************************************)"; + pr "(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *)"; + pr "(************************************************************************)"; + pr ""; + pr "(** * NMake *)"; + pr ""; + pr "(** From a cyclic Z/nZ representation to arbitrary precision natural numbers.*)"; + pr ""; + pr "(** Remark: File automatically generated by NMake_gen.ml, DO NOT EDIT ! *)"; + pr ""; + pr "Require Import BigNumPrelude."; + pr "Require Import ZArith."; + pr "Require Import CyclicAxioms."; + pr "Require Import DoubleType."; + pr "Require Import DoubleMul."; + pr "Require Import DoubleDivn1."; + pr "Require Import DoubleCyclic."; + pr "Require Import Nbasic."; + pr "Require Import Wf_nat."; + pr "Require Import StreamMemo."; + pr "Require Import NSig."; + pr ""; + pr "Module Make (Import W0:CyclicType) <: NType."; + pr ""; + + pr " Definition w0 := W0.w."; + for i = 1 to size do + pr " Definition w%i := zn2z w%i." i (i-1) + done; + pr ""; + + pr " Definition w0_op := W0.w_op."; + for i = 1 to 3 do + pr " Definition w%i_op := mk_zn2z_op w%i_op." i (i-1) + done; + for i = 4 to size + 3 do + pr " Definition w%i_op := mk_zn2z_op_karatsuba w%i_op." i (i-1) + done; + pr ""; + + pr " Section Make_op."; + pr " Variable mk : forall w', znz_op w' -> znz_op (zn2z w')."; + pr ""; + pr " Fixpoint make_op_aux (n:nat) : znz_op (word w%i (S n)):=" size; + pr " match n return znz_op (word w%i (S n)) with" size; + pr " | O => w%i_op" (size+1); + pr " | S n1 =>"; + pr " match n1 return znz_op (word w%i (S (S n1))) with" size; + pr " | O => w%i_op" (size+2); + pr " | S n2 =>"; + pr " match n2 return znz_op (word w%i (S (S (S n2)))) with" size; + pr " | O => w%i_op" (size+3); + pr " | S n3 => mk _ (mk _ (mk _ (make_op_aux n3)))"; + pr " end"; + pr " end"; + pr " end."; + pr ""; + pr " End Make_op."; + pr ""; + pr " Definition omake_op := make_op_aux mk_zn2z_op_karatsuba."; + pr ""; + pr ""; + pr " Definition make_op_list := dmemo_list _ omake_op."; + pr ""; + pr " Definition make_op n := dmemo_get _ omake_op n make_op_list."; + pr ""; + pr " Lemma make_op_omake: forall n, make_op n = omake_op n."; + pr " intros n; unfold make_op, make_op_list."; + pr " refine (dmemo_get_correct _ _ _)."; + pr " Qed."; + pr ""; + + pr " Inductive %s_ :=" t; + for i = 0 to size do + pr " | %s%i : w%i -> %s_" c i i t + done; + pr " | %sn : forall n, word w%i (S n) -> %s_." c size t; + pr ""; + pr " Definition %s := %s_." t t; + pr ""; + + pr " Definition w_0 := w0_op.(znz_0)."; + pr ""; + + for i = 0 to size do + pr " Definition one%i := w%i_op.(znz_1)." i i + done; + pr ""; + + + pr " Definition zero := %s0 w_0." c; + pr " Definition one := %s0 one0." c; + pr ""; + + pr " Definition to_Z x :="; + pr " match x with"; + for i = 0 to size do + pr " | %s%i wx => w%i_op.(znz_to_Z) wx" c i i + done; + pr " | %sn n wx => (make_op n).(znz_to_Z) wx" c; + pr " end."; + pr ""; + + pr " Open Scope Z_scope."; + pr " Notation \"[ x ]\" := (to_Z x)."; + pr ""; + + pr " Definition to_N x := Zabs_N (to_Z x)."; + pr ""; + + pr " Definition eq x y := (to_Z x = to_Z y)."; + pr ""; + + pp " (* Regular make op (no karatsuba) *)"; + pp " Fixpoint nmake_op (ww:Type) (ww_op: znz_op ww) (n: nat) : "; + pp " znz_op (word ww n) :="; + pp " match n return znz_op (word ww n) with "; + pp " O => ww_op"; + pp " | S n1 => mk_zn2z_op (nmake_op ww ww_op n1) "; + pp " end."; + pp ""; + pp " (* Simplification by rewriting for nmake_op *)"; + pp " Theorem nmake_op_S: forall ww (w_op: znz_op ww) x, "; + pp " nmake_op _ w_op (S x) = mk_zn2z_op (nmake_op _ w_op x)."; + pp " auto."; + pp " Qed."; + pp ""; + + + pr " (* Eval and extend functions for each level *)"; + for i = 0 to size do + pp " Let nmake_op%i := nmake_op _ w%i_op." i i; + pp " Let eval%in n := znz_to_Z (nmake_op%i n)." i i; + if i == 0 then + pr " Let extend%i := DoubleBase.extend (WW w_0)." i + else + pr " Let extend%i := DoubleBase.extend (WW (W0: w%i))." i i; + done; + pr ""; + + + pp " Theorem digits_doubled:forall n ww (w_op: znz_op ww), "; + pp " znz_digits (nmake_op _ w_op n) = "; + pp " DoubleBase.double_digits (znz_digits w_op) n."; + pp " Proof."; + pp " intros n; elim n; auto; clear n."; + pp " intros n Hrec ww ww_op; simpl DoubleBase.double_digits."; + pp " rewrite <- Hrec; auto."; + pp " Qed."; + pp ""; + pp " Theorem nmake_double: forall n ww (w_op: znz_op ww), "; + pp " znz_to_Z (nmake_op _ w_op n) ="; + pp " @DoubleBase.double_to_Z _ (znz_digits w_op) (znz_to_Z w_op) n."; + pp " Proof."; + pp " intros n; elim n; auto; clear n."; + pp " intros n Hrec ww ww_op; simpl DoubleBase.double_to_Z; unfold zn2z_to_Z."; + pp " rewrite <- Hrec; auto."; + pp " unfold DoubleBase.double_wB; rewrite <- digits_doubled; auto."; + pp " Qed."; + pp ""; + + + pp " Theorem digits_nmake:forall n ww (w_op: znz_op ww), "; + pp " znz_digits (nmake_op _ w_op (S n)) = "; + pp " xO (znz_digits (nmake_op _ w_op n))."; + pp " Proof."; + pp " auto."; + pp " Qed."; + pp ""; + + + pp " Theorem znz_nmake_op: forall ww ww_op n xh xl,"; + pp " znz_to_Z (nmake_op ww ww_op (S n)) (WW xh xl) ="; + pp " znz_to_Z (nmake_op ww ww_op n) xh *"; + pp " base (znz_digits (nmake_op ww ww_op n)) +"; + pp " znz_to_Z (nmake_op ww ww_op n) xl."; + pp " Proof."; + pp " auto."; + pp " Qed."; + pp ""; + + pp " Theorem make_op_S: forall n,"; + pp " make_op (S n) = mk_zn2z_op_karatsuba (make_op n)."; + pp " intro n."; + pp " do 2 rewrite make_op_omake."; + pp " pattern n; apply lt_wf_ind; clear n."; + pp " intros n; case n; clear n."; + pp " intros _; unfold omake_op, make_op_aux, w%i_op; apply refl_equal." (size + 2); + pp " intros n; case n; clear n."; + pp " intros _; unfold omake_op, make_op_aux, w%i_op; apply refl_equal." (size + 3); + pp " intros n; case n; clear n."; + pp " intros _; unfold omake_op, make_op_aux, w%i_op, w%i_op; apply refl_equal." (size + 3) (size + 2); + pp " intros n Hrec."; + pp " change (omake_op (S (S (S (S n))))) with"; + pp " (mk_zn2z_op_karatsuba (mk_zn2z_op_karatsuba (mk_zn2z_op_karatsuba (omake_op (S n)))))."; + pp " change (omake_op (S (S (S n)))) with"; + pp " (mk_zn2z_op_karatsuba (mk_zn2z_op_karatsuba (mk_zn2z_op_karatsuba (omake_op n))))."; + pp " rewrite Hrec; auto with arith."; + pp " Qed."; + pp " "; + + + for i = 1 to size + 2 do + pp " Let znz_to_Z_%i: forall x y," i; + pp " znz_to_Z w%i_op (WW x y) = " i; + pp " znz_to_Z w%i_op x * base (znz_digits w%i_op) + znz_to_Z w%i_op y." (i-1) (i-1) (i-1); + pp " Proof."; + pp " auto."; + pp " Qed. "; + pp ""; + done; + + pp " Let znz_to_Z_n: forall n x y,"; + pp " znz_to_Z (make_op (S n)) (WW x y) = "; + pp " znz_to_Z (make_op n) x * base (znz_digits (make_op n)) + znz_to_Z (make_op n) y."; + pp " Proof."; + pp " intros n x y; rewrite make_op_S; auto."; + pp " Qed. "; + pp ""; + + pp " Let w0_spec: znz_spec w0_op := W0.w_spec."; + for i = 1 to 3 do + pp " Let w%i_spec: znz_spec w%i_op := mk_znz2_spec w%i_spec." i i (i-1) + done; + for i = 4 to size + 3 do + pp " Let w%i_spec : znz_spec w%i_op := mk_znz2_karatsuba_spec w%i_spec." i i (i-1) + done; + pp ""; + + pp " Let wn_spec: forall n, znz_spec (make_op n)."; + pp " intros n; elim n; clear n."; + pp " exact w%i_spec." (size + 1); + pp " intros n Hrec; rewrite make_op_S."; + pp " exact (mk_znz2_karatsuba_spec Hrec)."; + pp " Qed."; + pp ""; + + for i = 0 to size do + pr " Definition w%i_eq0 := w%i_op.(znz_eq0)." i i; + pr " Let spec_w%i_eq0: forall x, if w%i_eq0 x then [%s%i x] = 0 else True." i i c i; + pa " Admitted."; + pp " Proof."; + pp " intros x; unfold w%i_eq0, to_Z; generalize (spec_eq0 w%i_spec x);" i i; + pp " case znz_eq0; auto."; + pp " Qed."; + pr ""; + done; + pr ""; + + + for i = 0 to size do + pp " Theorem digits_w%i: znz_digits w%i_op = znz_digits (nmake_op _ w0_op %i)." i i i; + if i == 0 then + pp " auto." + else + pp " rewrite digits_nmake; rewrite <- digits_w%i; auto." (i - 1); + pp " Qed."; + pp ""; + pp " Let spec_double_eval%in: forall n, eval%in n = DoubleBase.double_to_Z (znz_digits w%i_op) (znz_to_Z w%i_op) n." i i i i; + pp " Proof."; + pp " intros n; exact (nmake_double n w%i w%i_op)." i i; + pp " Qed."; + pp ""; + done; + + for i = 0 to size do + for j = 0 to (size - i) do + pp " Theorem digits_w%in%i: znz_digits w%i_op = znz_digits (nmake_op _ w%i_op %i)." i j (i + j) i j; + pp " Proof."; + if j == 0 then + if i == 0 then + pp " auto." + else + begin + pp " apply trans_equal with (xO (znz_digits w%i_op))." (i + j -1); + pp " auto."; + pp " unfold nmake_op; auto."; + end + else + begin + pp " apply trans_equal with (xO (znz_digits w%i_op))." (i + j -1); + pp " auto."; + pp " rewrite digits_nmake."; + pp " rewrite digits_w%in%i." i (j - 1); + pp " auto."; + end; + pp " Qed."; + pp ""; + pp " Let spec_eval%in%i: forall x, [%s%i x] = eval%in %i x." i j c (i + j) i j; + pp " Proof."; + if j == 0 then + pp " intros x; rewrite spec_double_eval%in; unfold DoubleBase.double_to_Z, to_Z; auto." i + else + begin + pp " intros x; case x."; + pp " auto."; + pp " intros xh xl; unfold to_Z; rewrite znz_to_Z_%i." (i + j); + pp " rewrite digits_w%in%i." i (j - 1); + pp " generalize (spec_eval%in%i); unfold to_Z; intros HH; repeat rewrite HH." i (j - 1); + pp " unfold eval%in, nmake_op%i." i i; + pp " rewrite (znz_nmake_op _ w%i_op %i); auto." i (j - 1); + end; + pp " Qed."; + if i + j <> size then + begin + pp " Let spec_extend%in%i: forall x, [%s%i x] = [%s%i (extend%i %i x)]." i (i + j + 1) c i c (i + j + 1) i j; + if j == 0 then + begin + pp " intros x; change (extend%i 0 x) with (WW (znz_0 w%i_op) x)." i (i + j); + pp " unfold to_Z; rewrite znz_to_Z_%i." (i + j + 1); + pp " rewrite (spec_0 w%i_spec); auto." (i + j); + end + else + begin + pp " intros x; change (extend%i %i x) with (WW (znz_0 w%i_op) (extend%i %i x))." i j (i + j) i (j - 1); + pp " unfold to_Z; rewrite znz_to_Z_%i." (i + j + 1); + pp " rewrite (spec_0 w%i_spec)." (i + j); + pp " generalize (spec_extend%in%i x); unfold to_Z." i (i + j); + pp " intros HH; rewrite <- HH; auto."; + end; + pp " Qed."; + pp ""; + end; + done; + + pp " Theorem digits_w%in%i: znz_digits w%i_op = znz_digits (nmake_op _ w%i_op %i)." i (size - i + 1) (size + 1) i (size - i + 1); + pp " Proof."; + pp " apply trans_equal with (xO (znz_digits w%i_op))." size; + pp " auto."; + pp " rewrite digits_nmake."; + pp " rewrite digits_w%in%i." i (size - i); + pp " auto."; + pp " Qed."; + pp ""; + + pp " Let spec_eval%in%i: forall x, [%sn 0 x] = eval%in %i x." i (size - i + 1) c i (size - i + 1); + pp " Proof."; + pp " intros x; case x."; + pp " auto."; + pp " intros xh xl; unfold to_Z; rewrite znz_to_Z_%i." (size + 1); + pp " rewrite digits_w%in%i." i (size - i); + pp " generalize (spec_eval%in%i); unfold to_Z; intros HH; repeat rewrite HH." i (size - i); + pp " unfold eval%in, nmake_op%i." i i; + pp " rewrite (znz_nmake_op _ w%i_op %i); auto." i (size - i); + pp " Qed."; + pp ""; + + pp " Let spec_eval%in%i: forall x, [%sn 1 x] = eval%in %i x." i (size - i + 2) c i (size - i + 2); + pp " intros x; case x."; + pp " auto."; + pp " intros xh xl; unfold to_Z; rewrite znz_to_Z_%i." (size + 2); + pp " rewrite digits_w%in%i." i (size + 1 - i); + pp " generalize (spec_eval%in%i); unfold to_Z; change (make_op 0) with (w%i_op); intros HH; repeat rewrite HH." i (size + 1 - i) (size + 1); + pp " unfold eval%in, nmake_op%i." i i; + pp " rewrite (znz_nmake_op _ w%i_op %i); auto." i (size + 1 - i); + pp " Qed."; + pp ""; + done; + + pp " Let digits_w%in: forall n," size; + pp " znz_digits (make_op n) = znz_digits (nmake_op _ w%i_op (S n))." size; + pp " intros n; elim n; clear n."; + pp " change (znz_digits (make_op 0)) with (xO (znz_digits w%i_op))." size; + pp " rewrite nmake_op_S; apply sym_equal; auto."; + pp " intros n Hrec."; + pp " replace (znz_digits (make_op (S n))) with (xO (znz_digits (make_op n)))."; + pp " rewrite Hrec."; + pp " rewrite nmake_op_S; apply sym_equal; auto."; + pp " rewrite make_op_S; apply sym_equal; auto."; + pp " Qed."; + pp ""; + + pp " Let spec_eval%in: forall n x, [%sn n x] = eval%in (S n) x." size c size; + pp " intros n; elim n; clear n."; + pp " exact spec_eval%in1." size; + pp " intros n Hrec x; case x; clear x."; + pp " unfold to_Z, eval%in, nmake_op%i." size size; + pp " rewrite make_op_S; rewrite nmake_op_S; auto."; + pp " intros xh xl."; + pp " unfold to_Z in Hrec |- *."; + pp " rewrite znz_to_Z_n."; + pp " rewrite digits_w%in." size; + pp " repeat rewrite Hrec."; + pp " unfold eval%in, nmake_op%i." size size; + pp " apply sym_equal; rewrite nmake_op_S; auto."; + pp " Qed."; + pp ""; + + pp " Let spec_extend%in: forall n x, [%s%i x] = [%sn n (extend%i n x)]." size c size c size ; + pp " intros n; elim n; clear n."; + pp " intros x; change (extend%i 0 x) with (WW (znz_0 w%i_op) x)." size size; + pp " unfold to_Z."; + pp " change (make_op 0) with w%i_op." (size + 1); + pp " rewrite znz_to_Z_%i; rewrite (spec_0 w%i_spec); auto." (size + 1) size; + pp " intros n Hrec x."; + pp " change (extend%i (S n) x) with (WW W0 (extend%i n x))." size size; + pp " unfold to_Z in Hrec |- *; rewrite znz_to_Z_n; auto."; + pp " rewrite <- Hrec."; + pp " replace (znz_to_Z (make_op n) W0) with 0; auto."; + pp " case n; auto; intros; rewrite make_op_S; auto."; + pp " Qed."; + pp ""; + + pr " Theorem spec_pos: forall x, 0 <= [x]."; + pa " Admitted."; + pp " Proof."; + pp " intros x; case x; clear x."; + for i = 0 to size do + pp " intros x; case (spec_to_Z w%i_spec x); auto." i; + done; + pp " intros n x; case (spec_to_Z (wn_spec n) x); auto."; + pp " Qed."; + pr ""; + + pp " Let spec_extendn_0: forall n wx, [%sn n (extend n _ wx)] = [%sn 0 wx]." c c; + pp " intros n; elim n; auto."; + pp " intros n1 Hrec wx; simpl extend; rewrite <- Hrec; auto."; + pp " unfold to_Z."; + pp " case n1; auto; intros n2; repeat rewrite make_op_S; auto."; + pp " Qed."; + pp " Hint Rewrite spec_extendn_0: extr."; + pp ""; + pp " Let spec_extendn0_0: forall n wx, [%sn (S n) (WW W0 wx)] = [%sn n wx]." c c; + pp " Proof."; + pp " intros n x; unfold to_Z."; + pp " rewrite znz_to_Z_n."; + pp " rewrite <- (Zplus_0_l (znz_to_Z (make_op n) x))."; + pp " apply (f_equal2 Zplus); auto."; + pp " case n; auto."; + pp " intros n1; rewrite make_op_S; auto."; + pp " Qed."; + pp " Hint Rewrite spec_extendn_0: extr."; + pp ""; + pp " Let spec_extend_tr: forall m n (w: word _ (S n)),"; + pp " [%sn (m + n) (extend_tr w m)] = [%sn n w]." c c; + pp " Proof."; + pp " induction m; auto."; + pp " intros n x; simpl extend_tr."; + pp " simpl plus; rewrite spec_extendn0_0; auto."; + pp " Qed."; + pp " Hint Rewrite spec_extend_tr: extr."; + pp ""; + pp " Let spec_cast_l: forall n m x1,"; + pp " [%sn (Max.max n m)" c; + pp " (castm (diff_r n m) (extend_tr x1 (snd (diff n m))))] ="; + pp " [%sn n x1]." c; + pp " Proof."; + pp " intros n m x1; case (diff_r n m); simpl castm."; + pp " rewrite spec_extend_tr; auto."; + pp " Qed."; + pp " Hint Rewrite spec_cast_l: extr."; + pp ""; + pp " Let spec_cast_r: forall n m x1,"; + pp " [%sn (Max.max n m)" c; + pp " (castm (diff_l n m) (extend_tr x1 (fst (diff n m))))] ="; + pp " [%sn m x1]." c; + pp " Proof."; + pp " intros n m x1; case (diff_l n m); simpl castm."; + pp " rewrite spec_extend_tr; auto."; + pp " Qed."; + pp " Hint Rewrite spec_cast_r: extr."; + pp ""; + + + pr " Section LevelAndIter."; + pr ""; + pr " Variable res: Type."; + pr " Variable xxx: res."; + pr " Variable P: Z -> Z -> res -> Prop."; + pr " (* Abstraction function for each level *)"; + for i = 0 to size do + pr " Variable f%i: w%i -> w%i -> res." i i i; + pr " Variable f%in: forall n, w%i -> word w%i (S n) -> res." i i i; + pr " Variable fn%i: forall n, word w%i (S n) -> w%i -> res." i i i; + pp " Variable Pf%i: forall x y, P [%s%i x] [%s%i y] (f%i x y)." i c i c i i; + if i == size then + begin + pp " Variable Pf%in: forall n x y, P [%s%i x] (eval%in (S n) y) (f%in n x y)." i c i i i; + pp " Variable Pfn%i: forall n x y, P (eval%in (S n) x) [%s%i y] (fn%i n x y)." i i c i i; + end + else + begin + pp " Variable Pf%in: forall n x y, Z_of_nat n <= %i -> P [%s%i x] (eval%in (S n) y) (f%in n x y)." i (size - i) c i i i; + pp " Variable Pfn%i: forall n x y, Z_of_nat n <= %i -> P (eval%in (S n) x) [%s%i y] (fn%i n x y)." i (size - i) i c i i; + end; + pr ""; + done; + pr " Variable fnn: forall n, word w%i (S n) -> word w%i (S n) -> res." size size; + pp " Variable Pfnn: forall n x y, P [%sn n x] [%sn n y] (fnn n x y)." c c; + pr " Variable fnm: forall n m, word w%i (S n) -> word w%i (S m) -> res." size size; + pp " Variable Pfnm: forall n m x y, P [%sn n x] [%sn m y] (fnm n m x y)." c c; + pr ""; + pr " (* Special zero functions *)"; + pr " Variable f0t: t_ -> res."; + pp " Variable Pf0t: forall x, P 0 [x] (f0t x)."; + pr " Variable ft0: t_ -> res."; + pp " Variable Pft0: forall x, P [x] 0 (ft0 x)."; + pr ""; + + + pr " (* We level the two arguments before applying *)"; + pr " (* the functions at each leval *)"; + pr " Definition same_level (x y: t_): res :="; + pr0 " Eval lazy zeta beta iota delta ["; + for i = 0 to size do + pr0 "extend%i " i; + done; + pr ""; + pr " DoubleBase.extend DoubleBase.extend_aux"; + pr " ] in"; + pr " match x, y with"; + for i = 0 to size do + for j = 0 to i - 1 do + pr " | %s%i wx, %s%i wy => f%i wx (extend%i %i wy)" c i c j i j (i - j -1); + done; + pr " | %s%i wx, %s%i wy => f%i wx wy" c i c i i; + for j = i + 1 to size do + pr " | %s%i wx, %s%i wy => f%i (extend%i %i wx) wy" c i c j j i (j - i - 1); + done; + if i == size then + pr " | %s%i wx, %sn m wy => fnn m (extend%i m wx) wy" c size c size + else + pr " | %s%i wx, %sn m wy => fnn m (extend%i m (extend%i %i wx)) wy" c i c size i (size - i - 1); + done; + for i = 0 to size do + if i == size then + pr " | %sn n wx, %s%i wy => fnn n wx (extend%i n wy)" c c size size + else + pr " | %sn n wx, %s%i wy => fnn n wx (extend%i n (extend%i %i wy))" c c i size i (size - i - 1); + done; + pr " | %sn n wx, Nn m wy =>" c; + pr " let mn := Max.max n m in"; + pr " let d := diff n m in"; + pr " fnn mn"; + pr " (castm (diff_r n m) (extend_tr wx (snd d)))"; + pr " (castm (diff_l n m) (extend_tr wy (fst d)))"; + pr " end."; + pr ""; + + pp " Lemma spec_same_level: forall x y, P [x] [y] (same_level x y)."; + pp " Proof."; + pp " intros x; case x; clear x; unfold same_level."; + for i = 0 to size do + pp " intros x y; case y; clear y."; + for j = 0 to i - 1 do + pp " intros y; rewrite spec_extend%in%i; apply Pf%i." j i i; + done; + pp " intros y; apply Pf%i." i; + for j = i + 1 to size do + pp " intros y; rewrite spec_extend%in%i; apply Pf%i." i j j; + done; + if i == size then + pp " intros m y; rewrite (spec_extend%in m); apply Pfnn." size + else + pp " intros m y; rewrite spec_extend%in%i; rewrite (spec_extend%in m); apply Pfnn." i size size; + done; + pp " intros n x y; case y; clear y."; + for i = 0 to size do + if i == size then + pp " intros y; rewrite (spec_extend%in n); apply Pfnn." size + else + pp " intros y; rewrite spec_extend%in%i; rewrite (spec_extend%in n); apply Pfnn." i size size; + done; + pp " intros m y; rewrite <- (spec_cast_l n m x); "; + pp " rewrite <- (spec_cast_r n m y); apply Pfnn."; + pp " Qed."; + pp ""; + + pr " (* We level the two arguments before applying *)"; + pr " (* the functions at each level (special zero case) *)"; + pr " Definition same_level0 (x y: t_): res :="; + pr0 " Eval lazy zeta beta iota delta ["; + for i = 0 to size do + pr0 "extend%i " i; + done; + pr ""; + pr " DoubleBase.extend DoubleBase.extend_aux"; + pr " ] in"; + pr " match x with"; + for i = 0 to size do + pr " | %s%i wx =>" c i; + if i == 0 then + pr " if w0_eq0 wx then f0t y else"; + pr " match y with"; + for j = 0 to i - 1 do + pr " | %s%i wy =>" c j; + if j == 0 then + pr " if w0_eq0 wy then ft0 x else"; + pr " f%i wx (extend%i %i wy)" i j (i - j -1); + done; + pr " | %s%i wy => f%i wx wy" c i i; + for j = i + 1 to size do + pr " | %s%i wy => f%i (extend%i %i wx) wy" c j j i (j - i - 1); + done; + if i == size then + pr " | %sn m wy => fnn m (extend%i m wx) wy" c size + else + pr " | %sn m wy => fnn m (extend%i m (extend%i %i wx)) wy" c size i (size - i - 1); + pr" end"; + done; + pr " | %sn n wx =>" c; + pr " match y with"; + for i = 0 to size do + pr " | %s%i wy =>" c i; + if i == 0 then + pr " if w0_eq0 wy then ft0 x else"; + if i == size then + pr " fnn n wx (extend%i n wy)" size + else + pr " fnn n wx (extend%i n (extend%i %i wy))" size i (size - i - 1); + done; + pr " | %sn m wy =>" c; + pr " let mn := Max.max n m in"; + pr " let d := diff n m in"; + pr " fnn mn"; + pr " (castm (diff_r n m) (extend_tr wx (snd d)))"; + pr " (castm (diff_l n m) (extend_tr wy (fst d)))"; + pr " end"; + pr " end."; + pr ""; + + pp " Lemma spec_same_level0: forall x y, P [x] [y] (same_level0 x y)."; + pp " Proof."; + pp " intros x; case x; clear x; unfold same_level0."; + for i = 0 to size do + pp " intros x."; + if i == 0 then + begin + pp " generalize (spec_w0_eq0 x); case w0_eq0; intros H."; + pp " intros y; rewrite H; apply Pf0t."; + pp " clear H."; + end; + pp " intros y; case y; clear y."; + for j = 0 to i - 1 do + pp " intros y."; + if j == 0 then + begin + pp " generalize (spec_w0_eq0 y); case w0_eq0; intros H."; + pp " rewrite H; apply Pft0."; + pp " clear H."; + end; + pp " rewrite spec_extend%in%i; apply Pf%i." j i i; + done; + pp " intros y; apply Pf%i." i; + for j = i + 1 to size do + pp " intros y; rewrite spec_extend%in%i; apply Pf%i." i j j; + done; + if i == size then + pp " intros m y; rewrite (spec_extend%in m); apply Pfnn." size + else + pp " intros m y; rewrite spec_extend%in%i; rewrite (spec_extend%in m); apply Pfnn." i size size; + done; + pp " intros n x y; case y; clear y."; + for i = 0 to size do + pp " intros y."; + if i = 0 then + begin + pp " generalize (spec_w0_eq0 y); case w0_eq0; intros H."; + pp " rewrite H; apply Pft0."; + pp " clear H."; + end; + if i == size then + pp " rewrite (spec_extend%in n); apply Pfnn." size + else + pp " rewrite spec_extend%in%i; rewrite (spec_extend%in n); apply Pfnn." i size size; + done; + pp " intros m y; rewrite <- (spec_cast_l n m x); "; + pp " rewrite <- (spec_cast_r n m y); apply Pfnn."; + pp " Qed."; + pp ""; + + pr " (* We iter the smaller argument with the bigger *)"; + pr " Definition iter (x y: t_): res := "; + pr0 " Eval lazy zeta beta iota delta ["; + for i = 0 to size do + pr0 "extend%i " i; + done; + pr ""; + pr " DoubleBase.extend DoubleBase.extend_aux"; + pr " ] in"; + pr " match x, y with"; + for i = 0 to size do + for j = 0 to i - 1 do + pr " | %s%i wx, %s%i wy => fn%i %i wx wy" c i c j j (i - j - 1); + done; + pr " | %s%i wx, %s%i wy => f%i wx wy" c i c i i; + for j = i + 1 to size do + pr " | %s%i wx, %s%i wy => f%in %i wx wy" c i c j i (j - i - 1); + done; + if i == size then + pr " | %s%i wx, %sn m wy => f%in m wx wy" c size c size + else + pr " | %s%i wx, %sn m wy => f%in m (extend%i %i wx) wy" c i c size i (size - i - 1); + done; + for i = 0 to size do + if i == size then + pr " | %sn n wx, %s%i wy => fn%i n wx wy" c c size size + else + pr " | %sn n wx, %s%i wy => fn%i n wx (extend%i %i wy)" c c i size i (size - i - 1); + done; + pr " | %sn n wx, %sn m wy => fnm n m wx wy" c c; + pr " end."; + pr ""; + + pp " Ltac zg_tac := try"; + pp " (red; simpl Zcompare; auto;"; + pp " let t := fresh \"H\" in (intros t; discriminate t))."; + pp " Lemma spec_iter: forall x y, P [x] [y] (iter x y)."; + pp " Proof."; + pp " intros x; case x; clear x; unfold iter."; + for i = 0 to size do + pp " intros x y; case y; clear y."; + for j = 0 to i - 1 do + pp " intros y; rewrite spec_eval%in%i; apply (Pfn%i %i); zg_tac." j (i - j) j (i - j - 1); + done; + pp " intros y; apply Pf%i." i; + for j = i + 1 to size do + pp " intros y; rewrite spec_eval%in%i; apply (Pf%in %i); zg_tac." i (j - i) i (j - i - 1); + done; + if i == size then + pp " intros m y; rewrite spec_eval%in; apply Pf%in." size size + else + pp " intros m y; rewrite spec_extend%in%i; rewrite spec_eval%in; apply Pf%in." i size size size; + done; + pp " intros n x y; case y; clear y."; + for i = 0 to size do + if i == size then + pp " intros y; rewrite spec_eval%in; apply Pfn%i." size size + else + pp " intros y; rewrite spec_extend%in%i; rewrite spec_eval%in; apply Pfn%i." i size size size; + done; + pp " intros m y; apply Pfnm."; + pp " Qed."; + pp ""; + + + pr " (* We iter the smaller argument with the bigger (zero case) *)"; + pr " Definition iter0 (x y: t_): res :="; + pr0 " Eval lazy zeta beta iota delta ["; + for i = 0 to size do + pr0 "extend%i " i; + done; + pr ""; + pr " DoubleBase.extend DoubleBase.extend_aux"; + pr " ] in"; + pr " match x with"; + for i = 0 to size do + pr " | %s%i wx =>" c i; + if i == 0 then + pr " if w0_eq0 wx then f0t y else"; + pr " match y with"; + for j = 0 to i - 1 do + pr " | %s%i wy =>" c j; + if j == 0 then + pr " if w0_eq0 wy then ft0 x else"; + pr " fn%i %i wx wy" j (i - j - 1); + done; + pr " | %s%i wy => f%i wx wy" c i i; + for j = i + 1 to size do + pr " | %s%i wy => f%in %i wx wy" c j i (j - i - 1); + done; + if i == size then + pr " | %sn m wy => f%in m wx wy" c size + else + pr " | %sn m wy => f%in m (extend%i %i wx) wy" c size i (size - i - 1); + pr " end"; + done; + pr " | %sn n wx =>" c; + pr " match y with"; + for i = 0 to size do + pr " | %s%i wy =>" c i; + if i == 0 then + pr " if w0_eq0 wy then ft0 x else"; + if i == size then + pr " fn%i n wx wy" size + else + pr " fn%i n wx (extend%i %i wy)" size i (size - i - 1); + done; + pr " | %sn m wy => fnm n m wx wy" c; + pr " end"; + pr " end."; + pr ""; + + pp " Lemma spec_iter0: forall x y, P [x] [y] (iter0 x y)."; + pp " Proof."; + pp " intros x; case x; clear x; unfold iter0."; + for i = 0 to size do + pp " intros x."; + if i == 0 then + begin + pp " generalize (spec_w0_eq0 x); case w0_eq0; intros H."; + pp " intros y; rewrite H; apply Pf0t."; + pp " clear H."; + end; + pp " intros y; case y; clear y."; + for j = 0 to i - 1 do + pp " intros y."; + if j == 0 then + begin + pp " generalize (spec_w0_eq0 y); case w0_eq0; intros H."; + pp " rewrite H; apply Pft0."; + pp " clear H."; + end; + pp " rewrite spec_eval%in%i; apply (Pfn%i %i); zg_tac." j (i - j) j (i - j - 1); + done; + pp " intros y; apply Pf%i." i; + for j = i + 1 to size do + pp " intros y; rewrite spec_eval%in%i; apply (Pf%in %i); zg_tac." i (j - i) i (j - i - 1); + done; + if i == size then + pp " intros m y; rewrite spec_eval%in; apply Pf%in." size size + else + pp " intros m y; rewrite spec_extend%in%i; rewrite spec_eval%in; apply Pf%in." i size size size; + done; + pp " intros n x y; case y; clear y."; + for i = 0 to size do + pp " intros y."; + if i = 0 then + begin + pp " generalize (spec_w0_eq0 y); case w0_eq0; intros H."; + pp " rewrite H; apply Pft0."; + pp " clear H."; + end; + if i == size then + pp " rewrite spec_eval%in; apply Pfn%i." size size + else + pp " rewrite spec_extend%in%i; rewrite spec_eval%in; apply Pfn%i." i size size size; + done; + pp " intros m y; apply Pfnm."; + pp " Qed."; + pp ""; + + + pr " End LevelAndIter."; + pr ""; + + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Reduction *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + pr " Definition reduce_0 (x:w) := %s0 x." c; + pr " Definition reduce_1 :="; + pr " Eval lazy beta iota delta[reduce_n1] in"; + pr " reduce_n1 _ _ zero w0_eq0 %s0 %s1." c c; + for i = 2 to size do + pr " Definition reduce_%i :=" i; + pr " Eval lazy beta iota delta[reduce_n1] in"; + pr " reduce_n1 _ _ zero w%i_eq0 reduce_%i %s%i." + (i-1) (i-1) c i + done; + pr " Definition reduce_%i :=" (size+1); + pr " Eval lazy beta iota delta[reduce_n1] in"; + pr " reduce_n1 _ _ zero w%i_eq0 reduce_%i (%sn 0)." + size size c; + + pr " Definition reduce_n n := "; + pr " Eval lazy beta iota delta[reduce_n] in"; + pr " reduce_n _ _ zero reduce_%i %sn n." (size + 1) c; + pr ""; + + pp " Let spec_reduce_0: forall x, [reduce_0 x] = [%s0 x]." c; + pp " Proof."; + pp " intros x; unfold to_Z, reduce_0."; + pp " auto."; + pp " Qed."; + pp " "; + + for i = 1 to size + 1 do + if i == size + 1 then + pp " Let spec_reduce_%i: forall x, [reduce_%i x] = [%sn 0 x]." i i c + else + pp " Let spec_reduce_%i: forall x, [reduce_%i x] = [%s%i x]." i i c i; + pp " Proof."; + pp " intros x; case x; unfold reduce_%i." i; + pp " exact (spec_0 w0_spec)."; + pp " intros x1 y1."; + pp " generalize (spec_w%i_eq0 x1); " (i - 1); + pp " case w%i_eq0; intros H1; auto." (i - 1); + if i <> 1 then + pp " rewrite spec_reduce_%i." (i - 1); + pp " unfold to_Z; rewrite znz_to_Z_%i." i; + pp " unfold to_Z in H1; rewrite H1; auto."; + pp " Qed."; + pp " "; + done; + + pp " Let spec_reduce_n: forall n x, [reduce_n n x] = [%sn n x]." c; + pp " Proof."; + pp " intros n; elim n; simpl reduce_n."; + pp " intros x; rewrite <- spec_reduce_%i; auto." (size + 1); + pp " intros n1 Hrec x; case x."; + pp " unfold to_Z; rewrite make_op_S; auto."; + pp " exact (spec_0 w0_spec)."; + pp " intros x1 y1; case x1; auto."; + pp " rewrite Hrec."; + pp " rewrite spec_extendn0_0; auto."; + pp " Qed."; + pp " "; + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Successor *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + for i = 0 to size do + pr " Definition w%i_succ_c := w%i_op.(znz_succ_c)." i i + done; + pr ""; + + for i = 0 to size do + pr " Definition w%i_succ := w%i_op.(znz_succ)." i i + done; + pr ""; + + pr " Definition succ x :="; + pr " match x with"; + for i = 0 to size-1 do + pr " | %s%i wx =>" c i; + pr " match w%i_succ_c wx with" i; + pr " | C0 r => %s%i r" c i; + pr " | C1 r => %s%i (WW one%i r)" c (i+1) i; + pr " end"; + done; + pr " | %s%i wx =>" c size; + pr " match w%i_succ_c wx with" size; + pr " | C0 r => %s%i r" c size; + pr " | C1 r => %sn 0 (WW one%i r)" c size ; + pr " end"; + pr " | %sn n wx =>" c; + pr " let op := make_op n in"; + pr " match op.(znz_succ_c) wx with"; + pr " | C0 r => %sn n r" c; + pr " | C1 r => %sn (S n) (WW op.(znz_1) r)" c; + pr " end"; + pr " end."; + pr ""; + + pr " Theorem spec_succ: forall n, [succ n] = [n] + 1."; + pa " Admitted."; + pp " Proof."; + pp " intros n; case n; unfold succ, to_Z."; + for i = 0 to size do + pp " intros n1; generalize (spec_succ_c w%i_spec n1);" i; + pp " unfold succ, to_Z, w%i_succ_c; case znz_succ_c; auto." i; + pp " intros ww H; rewrite <- H."; + pp " (rewrite znz_to_Z_%i; unfold interp_carry;" (i + 1); + pp " apply f_equal2 with (f := Zplus); auto;"; + pp " apply f_equal2 with (f := Zmult); auto;"; + pp " exact (spec_1 w%i_spec))." i; + done; + pp " intros k n1; generalize (spec_succ_c (wn_spec k) n1)."; + pp " unfold succ, to_Z; case znz_succ_c; auto."; + pp " intros ww H; rewrite <- H."; + pp " (rewrite (znz_to_Z_n k); unfold interp_carry;"; + pp " apply f_equal2 with (f := Zplus); auto;"; + pp " apply f_equal2 with (f := Zmult); auto;"; + pp " exact (spec_1 (wn_spec k)))."; + pp " Qed."; + pr ""; + + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Adddition *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + for i = 0 to size do + pr " Definition w%i_add_c := znz_add_c w%i_op." i i; + pr " Definition w%i_add x y :=" i; + pr " match w%i_add_c x y with" i; + pr " | C0 r => %s%i r" c i; + if i == size then + pr " | C1 r => %sn 0 (WW one%i r)" c size + else + pr " | C1 r => %s%i (WW one%i r)" c (i + 1) i; + pr " end."; + pr ""; + done ; + pr " Definition addn n (x y : word w%i (S n)) :=" size; + pr " let op := make_op n in"; + pr " match op.(znz_add_c) x y with"; + pr " | C0 r => %sn n r" c; + pr " | C1 r => %sn (S n) (WW op.(znz_1) r) end." c; + pr ""; + + + for i = 0 to size do + pp " Let spec_w%i_add: forall x y, [w%i_add x y] = [%s%i x] + [%s%i y]." i i c i c i; + pp " Proof."; + pp " intros n m; unfold to_Z, w%i_add, w%i_add_c." i i; + pp " generalize (spec_add_c w%i_spec n m); case znz_add_c; auto." i; + pp " intros ww H; rewrite <- H."; + pp " rewrite znz_to_Z_%i; unfold interp_carry;" (i + 1); + pp " apply f_equal2 with (f := Zplus); auto;"; + pp " apply f_equal2 with (f := Zmult); auto;"; + pp " exact (spec_1 w%i_spec)." i; + pp " Qed."; + pp " Hint Rewrite spec_w%i_add: addr." i; + pp ""; + done; + pp " Let spec_wn_add: forall n x y, [addn n x y] = [%sn n x] + [%sn n y]." c c; + pp " Proof."; + pp " intros k n m; unfold to_Z, addn."; + pp " generalize (spec_add_c (wn_spec k) n m); case znz_add_c; auto."; + pp " intros ww H; rewrite <- H."; + pp " rewrite (znz_to_Z_n k); unfold interp_carry;"; + pp " apply f_equal2 with (f := Zplus); auto;"; + pp " apply f_equal2 with (f := Zmult); auto;"; + pp " exact (spec_1 (wn_spec k))."; + pp " Qed."; + pp " Hint Rewrite spec_wn_add: addr."; + + pr " Definition add := Eval lazy beta delta [same_level] in"; + pr0 " (same_level t_ "; + for i = 0 to size do + pr0 "w%i_add " i; + done; + pr "addn)."; + pr ""; + + pr " Theorem spec_add: forall x y, [add x y] = [x] + [y]."; + pa " Admitted."; + pp " Proof."; + pp " unfold add."; + pp " generalize (spec_same_level t_ (fun x y res => [res] = x + y))."; + pp " unfold same_level; intros HH; apply HH; clear HH."; + for i = 0 to size do + pp " exact spec_w%i_add." i; + done; + pp " exact spec_wn_add."; + pp " Qed."; + pr ""; + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Predecessor *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + for i = 0 to size do + pr " Definition w%i_pred_c := w%i_op.(znz_pred_c)." i i + done; + pr ""; + + pr " Definition pred x :="; + pr " match x with"; + for i = 0 to size do + pr " | %s%i wx =>" c i; + pr " match w%i_pred_c wx with" i; + pr " | C0 r => reduce_%i r" i; + pr " | C1 r => zero"; + pr " end"; + done; + pr " | %sn n wx =>" c; + pr " let op := make_op n in"; + pr " match op.(znz_pred_c) wx with"; + pr " | C0 r => reduce_n n r"; + pr " | C1 r => zero"; + pr " end"; + pr " end."; + pr ""; + + pr " Theorem spec_pred: forall x, 0 < [x] -> [pred x] = [x] - 1."; + pa " Admitted."; + pp " Proof."; + pp " intros x; case x; unfold pred."; + for i = 0 to size do + pp " intros x1 H1; unfold w%i_pred_c; " i; + pp " generalize (spec_pred_c w%i_spec x1); case znz_pred_c; intros y1." i; + pp " rewrite spec_reduce_%i; auto." i; + pp " unfold interp_carry; unfold to_Z."; + pp " case (spec_to_Z w%i_spec x1); intros HH1 HH2." i; + pp " case (spec_to_Z w%i_spec y1); intros HH3 HH4 HH5." i; + pp " assert (znz_to_Z w%i_op x1 - 1 < 0); auto with zarith." i; + pp " unfold to_Z in H1; auto with zarith."; + done; + pp " intros n x1 H1; "; + pp " generalize (spec_pred_c (wn_spec n) x1); case znz_pred_c; intros y1."; + pp " rewrite spec_reduce_n; auto."; + pp " unfold interp_carry; unfold to_Z."; + pp " case (spec_to_Z (wn_spec n) x1); intros HH1 HH2."; + pp " case (spec_to_Z (wn_spec n) y1); intros HH3 HH4 HH5."; + pp " assert (znz_to_Z (make_op n) x1 - 1 < 0); auto with zarith."; + pp " unfold to_Z in H1; auto with zarith."; + pp " Qed."; + pp " "; + + pp " Let spec_pred0: forall x, [x] = 0 -> [pred x] = 0."; + pp " Proof."; + pp " intros x; case x; unfold pred."; + for i = 0 to size do + pp " intros x1 H1; unfold w%i_pred_c; " i; + pp " generalize (spec_pred_c w%i_spec x1); case znz_pred_c; intros y1." i; + pp " unfold interp_carry; unfold to_Z."; + pp " unfold to_Z in H1; auto with zarith."; + pp " case (spec_to_Z w%i_spec y1); intros HH3 HH4; auto with zarith." i; + pp " intros; exact (spec_0 w0_spec)."; + done; + pp " intros n x1 H1; "; + pp " generalize (spec_pred_c (wn_spec n) x1); case znz_pred_c; intros y1."; + pp " unfold interp_carry; unfold to_Z."; + pp " unfold to_Z in H1; auto with zarith."; + pp " case (spec_to_Z (wn_spec n) y1); intros HH3 HH4; auto with zarith."; + pp " intros; exact (spec_0 w0_spec)."; + pp " Qed."; + pr " "; + + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Subtraction *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + for i = 0 to size do + pr " Definition w%i_sub_c := w%i_op.(znz_sub_c)." i i + done; + pr ""; + + for i = 0 to size do + pr " Definition w%i_sub x y :=" i; + pr " match w%i_sub_c x y with" i; + pr " | C0 r => reduce_%i r" i; + pr " | C1 r => zero"; + pr " end." + done; + pr ""; + + pr " Definition subn n (x y : word w%i (S n)) :=" size; + pr " let op := make_op n in"; + pr " match op.(znz_sub_c) x y with"; + pr " | C0 r => %sn n r" c; + pr " | C1 r => N0 w_0"; + pr " end."; + pr ""; + + for i = 0 to size do + pp " Let spec_w%i_sub: forall x y, [%s%i y] <= [%s%i x] -> [w%i_sub x y] = [%s%i x] - [%s%i y]." i c i c i i c i c i; + pp " Proof."; + pp " intros n m; unfold w%i_sub, w%i_sub_c." i i; + pp " generalize (spec_sub_c w%i_spec n m); case znz_sub_c; " i; + if i == 0 then + pp " intros x; auto." + else + pp " intros x; try rewrite spec_reduce_%i; auto." i; + pp " unfold interp_carry; unfold zero, w_0, to_Z."; + pp " rewrite (spec_0 w0_spec)."; + pp " case (spec_to_Z w%i_spec x); intros; auto with zarith." i; + pp " Qed."; + pp ""; + done; + + pp " Let spec_wn_sub: forall n x y, [%sn n y] <= [%sn n x] -> [subn n x y] = [%sn n x] - [%sn n y]." c c c c; + pp " Proof."; + pp " intros k n m; unfold subn."; + pp " generalize (spec_sub_c (wn_spec k) n m); case znz_sub_c; "; + pp " intros x; auto."; + pp " unfold interp_carry, to_Z."; + pp " case (spec_to_Z (wn_spec k) x); intros; auto with zarith."; + pp " Qed."; + pp ""; + + pr " Definition sub := Eval lazy beta delta [same_level] in"; + pr0 " (same_level t_ "; + for i = 0 to size do + pr0 "w%i_sub " i; + done; + pr "subn)."; + pr ""; + + pr " Theorem spec_sub: forall x y, [y] <= [x] -> [sub x y] = [x] - [y]."; + pa " Admitted."; + pp " Proof."; + pp " unfold sub."; + pp " generalize (spec_same_level t_ (fun x y res => y <= x -> [res] = x - y))."; + pp " unfold same_level; intros HH; apply HH; clear HH."; + for i = 0 to size do + pp " exact spec_w%i_sub." i; + done; + pp " exact spec_wn_sub."; + pp " Qed."; + pr ""; + + for i = 0 to size do + pp " Let spec_w%i_sub0: forall x y, [%s%i x] < [%s%i y] -> [w%i_sub x y] = 0." i c i c i i; + pp " Proof."; + pp " intros n m; unfold w%i_sub, w%i_sub_c." i i; + pp " generalize (spec_sub_c w%i_spec n m); case znz_sub_c; " i; + pp " intros x; unfold interp_carry."; + pp " unfold to_Z; case (spec_to_Z w%i_spec x); intros; auto with zarith." i; + pp " intros; unfold to_Z, zero, w_0; rewrite (spec_0 w0_spec); auto."; + pp " Qed."; + pp ""; + done; + + pp " Let spec_wn_sub0: forall n x y, [%sn n x] < [%sn n y] -> [subn n x y] = 0." c c; + pp " Proof."; + pp " intros k n m; unfold subn."; + pp " generalize (spec_sub_c (wn_spec k) n m); case znz_sub_c; "; + pp " intros x; unfold interp_carry."; + pp " unfold to_Z; case (spec_to_Z (wn_spec k) x); intros; auto with zarith."; + pp " intros; unfold to_Z, w_0; rewrite (spec_0 (w0_spec)); auto."; + pp " Qed."; + pp ""; + + pr " Theorem spec_sub0: forall x y, [x] < [y] -> [sub x y] = 0."; + pa " Admitted."; + pp " Proof."; + pp " unfold sub."; + pp " generalize (spec_same_level t_ (fun x y res => x < y -> [res] = 0))."; + pp " unfold same_level; intros HH; apply HH; clear HH."; + for i = 0 to size do + pp " exact spec_w%i_sub0." i; + done; + pp " exact spec_wn_sub0."; + pp " Qed."; + pr ""; + + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Comparison *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + for i = 0 to size do + pr " Definition compare_%i := w%i_op.(znz_compare)." i i; + pr " Definition comparen_%i :=" i; + pr " compare_mn_1 w%i w%i %s compare_%i (compare_%i %s) compare_%i." i i (pz i) i i (pz i) i + done; + pr ""; + + pr " Definition comparenm n m wx wy :="; + pr " let mn := Max.max n m in"; + pr " let d := diff n m in"; + pr " let op := make_op mn in"; + pr " op.(znz_compare)"; + pr " (castm (diff_r n m) (extend_tr wx (snd d)))"; + pr " (castm (diff_l n m) (extend_tr wy (fst d)))."; + pr ""; + + pr " Definition compare := Eval lazy beta delta [iter] in "; + pr " (iter _ "; + for i = 0 to size do + pr " compare_%i" i; + pr " (fun n x y => opp_compare (comparen_%i (S n) y x))" i; + pr " (fun n => comparen_%i (S n))" i; + done; + pr " comparenm)."; + pr ""; + + pr " Definition lt n m := compare n m = Lt."; + pr " Definition le n m := compare n m <> Gt."; + pr " Definition min n m := match compare n m with Gt => m | _ => n end."; + pr " Definition max n m := match compare n m with Lt => m | _ => n end."; + pr ""; + + for i = 0 to size do + pp " Let spec_compare_%i: forall x y," i; + pp " match compare_%i x y with " i; + pp " Eq => [%s%i x] = [%s%i y]" c i c i; + pp " | Lt => [%s%i x] < [%s%i y]" c i c i; + pp " | Gt => [%s%i x] > [%s%i y]" c i c i; + pp " end."; + pp " Proof."; + pp " unfold compare_%i, to_Z; exact (spec_compare w%i_spec)." i i; + pp " Qed."; + pp ""; + + pp " Let spec_comparen_%i:" i; + pp " forall (n : nat) (x : word w%i n) (y : w%i)," i i; + pp " match comparen_%i n x y with" i; + pp " | Eq => eval%in n x = [%s%i y]" i c i; + pp " | Lt => eval%in n x < [%s%i y]" i c i; + pp " | Gt => eval%in n x > [%s%i y]" i c i; + pp " end."; + pp " intros n x y."; + pp " unfold comparen_%i, to_Z; rewrite spec_double_eval%in." i i; + pp " apply spec_compare_mn_1."; + pp " exact (spec_0 w%i_spec)." i; + pp " intros x1; exact (spec_compare w%i_spec %s x1)." i (pz i); + pp " exact (spec_to_Z w%i_spec)." i; + pp " exact (spec_compare w%i_spec)." i; + pp " exact (spec_compare w%i_spec)." i; + pp " exact (spec_to_Z w%i_spec)." i; + pp " Qed."; + pp ""; + done; + + pp " Let spec_opp_compare: forall c (u v: Z),"; + pp " match c with Eq => u = v | Lt => u < v | Gt => u > v end ->"; + pp " match opp_compare c with Eq => v = u | Lt => v < u | Gt => v > u end."; + pp " Proof."; + pp " intros c u v; case c; unfold opp_compare; auto with zarith."; + pp " Qed."; + pp ""; + + + pr " Theorem spec_compare: forall x y,"; + pr " match compare x y with "; + pr " Eq => [x] = [y]"; + pr " | Lt => [x] < [y]"; + pr " | Gt => [x] > [y]"; + pr " end."; + pa " Admitted."; + pp " Proof."; + pp " refine (spec_iter _ (fun x y res => "; + pp " match res with "; + pp " Eq => x = y"; + pp " | Lt => x < y"; + pp " | Gt => x > y"; + pp " end)"; + for i = 0 to size do + pp " compare_%i" i; + pp " (fun n x y => opp_compare (comparen_%i (S n) y x))" i; + pp " (fun n => comparen_%i (S n)) _ _ _" i; + done; + pp " comparenm _)."; + + for i = 0 to size - 1 do + pp " exact spec_compare_%i." i; + pp " intros n x y H;apply spec_opp_compare; apply spec_comparen_%i." i; + pp " intros n x y H; exact (spec_comparen_%i (S n) x y)." i; + done; + pp " exact spec_compare_%i." size; + pp " intros n x y;apply spec_opp_compare; apply spec_comparen_%i." size; + pp " intros n; exact (spec_comparen_%i (S n))." size; + pp " intros n m x y; unfold comparenm."; + pp " rewrite <- (spec_cast_l n m x); rewrite <- (spec_cast_r n m y)."; + pp " unfold to_Z; apply (spec_compare (wn_spec (Max.max n m)))."; + pp " Qed."; + pr ""; + + pr " Definition eq_bool x y :="; + pr " match compare x y with"; + pr " | Eq => true"; + pr " | _ => false"; + pr " end."; + pr ""; + + + pr " Theorem spec_eq_bool: forall x y,"; + pr " if eq_bool x y then [x] = [y] else [x] <> [y]."; + pa " Admitted."; + pp " Proof."; + pp " intros x y; unfold eq_bool."; + pp " generalize (spec_compare x y); case compare; auto with zarith."; + pp " Qed."; + pr ""; + + + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Multiplication *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + for i = 0 to size do + pr " Definition w%i_mul_c := w%i_op.(znz_mul_c)." i i + done; + pr ""; + + for i = 0 to size do + pr " Definition w%i_mul_add :=" i; + pr " Eval lazy beta delta [w_mul_add] in"; + pr " @w_mul_add w%i %s w%i_succ w%i_add_c w%i_mul_c." i (pz i) i i i + done; + pr ""; + + for i = 0 to size do + pr " Definition w%i_0W := znz_0W w%i_op." i i + done; + pr ""; + + for i = 0 to size do + pr " Definition w%i_WW := znz_WW w%i_op." i i + done; + pr ""; + + for i = 0 to size do + pr " Definition w%i_mul_add_n1 :=" i; + pr " @double_mul_add_n1 w%i %s w%i_WW w%i_0W w%i_mul_add." i (pz i) i i i + done; + pr ""; + + for i = 0 to size - 1 do + pr " Let to_Z%i n :=" i; + pr " match n return word w%i (S n) -> t_ with" i; + for j = 0 to size - i do + if (i + j) == size then + begin + pr " | %i%s => fun x => %sn 0 x" j "%nat" c; + pr " | %i%s => fun x => %sn 1 x" (j + 1) "%nat" c + end + else + pr " | %i%s => fun x => %s%i x" j "%nat" c (i + j + 1) + done; + pr " | _ => fun _ => N0 w_0"; + pr " end."; + pr ""; + done; + + + for i = 0 to size - 1 do + pp "Theorem to_Z%i_spec:" i; + pp " forall n x, Z_of_nat n <= %i -> [to_Z%i n x] = znz_to_Z (nmake_op _ w%i_op (S n)) x." (size + 1 - i) i i; + for j = 1 to size + 2 - i do + pp " intros n; case n; clear n."; + pp " unfold to_Z%i." i; + pp " intros x H; rewrite spec_eval%in%i; auto." i j; + done; + pp " intros n x."; + pp " repeat rewrite inj_S; unfold Zsucc; auto with zarith."; + pp " Qed."; + pp ""; + done; + + + for i = 0 to size do + pr " Definition w%i_mul n x y :=" i; + pr " let (w,r) := w%i_mul_add_n1 (S n) x y %s in" i (pz i); + if i == size then + begin + pr " if w%i_eq0 w then %sn n r" i c; + pr " else %sn (S n) (WW (extend%i n w) r)." c i; + end + else + begin + pr " if w%i_eq0 w then to_Z%i n r" i i; + pr " else to_Z%i (S n) (WW (extend%i n w) r)." i i; + end; + pr ""; + done; + + pr " Definition mulnm n m x y :="; + pr " let mn := Max.max n m in"; + pr " let d := diff n m in"; + pr " let op := make_op mn in"; + pr " reduce_n (S mn) (op.(znz_mul_c)"; + pr " (castm (diff_r n m) (extend_tr x (snd d)))"; + pr " (castm (diff_l n m) (extend_tr y (fst d))))."; + pr ""; + + pr " Definition mul := Eval lazy beta delta [iter0] in "; + pr " (iter0 t_ "; + for i = 0 to size do + pr " (fun x y => reduce_%i (w%i_mul_c x y)) " (i + 1) i; + pr " (fun n x y => w%i_mul n y x)" i; + pr " w%i_mul" i; + done; + pr " mulnm"; + pr " (fun _ => N0 w_0)"; + pr " (fun _ => N0 w_0)"; + pr " )."; + pr ""; + for i = 0 to size do + pp " Let spec_w%i_mul_add: forall x y z," i; + pp " let (q,r) := w%i_mul_add x y z in" i; + pp " znz_to_Z w%i_op q * (base (znz_digits w%i_op)) + znz_to_Z w%i_op r =" i i i; + pp " znz_to_Z w%i_op x * znz_to_Z w%i_op y + znz_to_Z w%i_op z :=" i i i ; + pp " (spec_mul_add w%i_spec)." i; + pp ""; + done; + + for i = 0 to size do + pp " Theorem spec_w%i_mul_add_n1: forall n x y z," i; + pp " let (q,r) := w%i_mul_add_n1 n x y z in" i; + pp " znz_to_Z w%i_op q * (base (znz_digits (nmake_op _ w%i_op n))) +" i i; + pp " znz_to_Z (nmake_op _ w%i_op n) r =" i; + pp " znz_to_Z (nmake_op _ w%i_op n) x * znz_to_Z w%i_op y +" i i; + pp " znz_to_Z w%i_op z." i; + pp " Proof."; + pp " intros n x y z; unfold w%i_mul_add_n1." i; + pp " rewrite nmake_double."; + pp " rewrite digits_doubled."; + pp " change (base (DoubleBase.double_digits (znz_digits w%i_op) n)) with" i; + pp " (DoubleBase.double_wB (znz_digits w%i_op) n)." i; + pp " apply spec_double_mul_add_n1; auto."; + if i == 0 then pp " exact (spec_0 w%i_spec)." i; + pp " exact (spec_WW w%i_spec)." i; + pp " exact (spec_0W w%i_spec)." i; + pp " exact (spec_mul_add w%i_spec)." i; + pp " Qed."; + pp ""; + done; + + pp " Lemma nmake_op_WW: forall ww ww1 n x y,"; + pp " znz_to_Z (nmake_op ww ww1 (S n)) (WW x y) ="; + pp " znz_to_Z (nmake_op ww ww1 n) x * base (znz_digits (nmake_op ww ww1 n)) +"; + pp " znz_to_Z (nmake_op ww ww1 n) y."; + pp " auto."; + pp " Qed."; + pp ""; + + for i = 0 to size do + pp " Lemma extend%in_spec: forall n x1," i; + pp " znz_to_Z (nmake_op _ w%i_op (S n)) (extend%i n x1) = " i i; + pp " znz_to_Z w%i_op x1." i; + pp " Proof."; + pp " intros n1 x2; rewrite nmake_double."; + pp " unfold extend%i." i; + pp " rewrite DoubleBase.spec_extend; auto."; + if i == 0 then + pp " intros l; simpl; unfold w_0; rewrite (spec_0 w0_spec); ring."; + pp " Qed."; + pp ""; + done; + + pp " Lemma spec_muln:"; + pp " forall n (x: word _ (S n)) y,"; + pp " [%sn (S n) (znz_mul_c (make_op n) x y)] = [%sn n x] * [%sn n y]." c c c; + pp " Proof."; + pp " intros n x y; unfold to_Z."; + pp " rewrite <- (spec_mul_c (wn_spec n))."; + pp " rewrite make_op_S."; + pp " case znz_mul_c; auto."; + pp " Qed."; + + pr " Theorem spec_mul: forall x y, [mul x y] = [x] * [y]."; + pa " Admitted."; + pp " Proof."; + for i = 0 to size do + pp " assert(F%i: " i; + pp " forall n x y,"; + if i <> size then + pp0 " Z_of_nat n <= %i -> " (size - i); + pp " [w%i_mul n x y] = eval%in (S n) x * [%s%i y])." i i c i; + if i == size then + pp " intros n x y; unfold w%i_mul." i + else + pp " intros n x y H; unfold w%i_mul." i; + pp " generalize (spec_w%i_mul_add_n1 (S n) x y %s)." i (pz i); + pp " case w%i_mul_add_n1; intros x1 y1." i; + pp " change (znz_to_Z (nmake_op _ w%i_op (S n)) x) with (eval%in (S n) x)." i i; + pp " change (znz_to_Z w%i_op y) with ([%s%i y])." i c i; + if i == 0 then + pp " unfold w_0; rewrite (spec_0 w0_spec); rewrite Zplus_0_r." + else + pp " change (znz_to_Z w%i_op W0) with 0; rewrite Zplus_0_r." i; + pp " intros H1; rewrite <- H1; clear H1."; + pp " generalize (spec_w%i_eq0 x1); case w%i_eq0; intros HH." i i; + pp " unfold to_Z in HH; rewrite HH."; + if i == size then + begin + pp " rewrite spec_eval%in; unfold eval%in, nmake_op%i; auto." i i i; + pp " rewrite spec_eval%in; unfold eval%in, nmake_op%i." i i i + end + else + begin + pp " rewrite to_Z%i_spec; auto with zarith." i; + pp " rewrite to_Z%i_spec; try (rewrite inj_S; auto with zarith)." i + end; + pp " rewrite nmake_op_WW; rewrite extend%in_spec; auto." i; + done; + pp " refine (spec_iter0 t_ (fun x y res => [res] = x * y)"; + for i = 0 to size do + pp " (fun x y => reduce_%i (w%i_mul_c x y)) " (i + 1) i; + pp " (fun n x y => w%i_mul n y x)" i; + pp " w%i_mul _ _ _" i; + done; + pp " mulnm _"; + pp " (fun _ => N0 w_0) _"; + pp " (fun _ => N0 w_0) _"; + pp " )."; + for i = 0 to size do + pp " intros x y; rewrite spec_reduce_%i." (i + 1); + pp " unfold w%i_mul_c, to_Z." i; + pp " generalize (spec_mul_c w%i_spec x y)." i; + pp " intros HH; rewrite <- HH; clear HH; auto."; + if i == size then + begin + pp " intros n x y; rewrite F%i; auto with zarith." i; + pp " intros n x y; rewrite F%i; auto with zarith. " i; + end + else + begin + pp " intros n x y H; rewrite F%i; auto with zarith." i; + pp " intros n x y H; rewrite F%i; auto with zarith. " i; + end; + done; + pp " intros n m x y; unfold mulnm."; + pp " rewrite spec_reduce_n."; + pp " rewrite <- (spec_cast_l n m x)."; + pp " rewrite <- (spec_cast_r n m y)."; + pp " rewrite spec_muln; rewrite spec_cast_l; rewrite spec_cast_r; auto."; + pp " intros x; unfold to_Z, w_0; rewrite (spec_0 w0_spec); ring."; + pp " intros x; unfold to_Z, w_0; rewrite (spec_0 w0_spec); ring."; + pp " Qed."; + pr ""; + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Square *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + for i = 0 to size do + pr " Definition w%i_square_c := w%i_op.(znz_square_c)." i i + done; + pr ""; + + pr " Definition square x :="; + pr " match x with"; + pr " | %s0 wx => reduce_1 (w0_square_c wx)" c; + for i = 1 to size - 1 do + pr " | %s%i wx => %s%i (w%i_square_c wx)" c i c (i+1) i + done; + pr " | %s%i wx => %sn 0 (w%i_square_c wx)" c size c size; + pr " | %sn n wx =>" c; + pr " let op := make_op n in"; + pr " %sn (S n) (op.(znz_square_c) wx)" c; + pr " end."; + pr ""; + + pr " Theorem spec_square: forall x, [square x] = [x] * [x]."; + pa " Admitted."; + pp " Proof."; + pp " intros x; case x; unfold square; clear x."; + pp " intros x; rewrite spec_reduce_1; unfold to_Z."; + pp " exact (spec_square_c w%i_spec x)." 0; + for i = 1 to size do + pp " intros x; unfold to_Z."; + pp " exact (spec_square_c w%i_spec x)." i; + done; + pp " intros n x; unfold to_Z."; + pp " rewrite make_op_S."; + pp " exact (spec_square_c (wn_spec n) x)."; + pp "Qed."; + pr ""; + + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Power *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + pr " Fixpoint power_pos (x:%s) (p:positive) {struct p} : %s :=" t t; + pr " match p with"; + pr " | xH => x"; + pr " | xO p => square (power_pos x p)"; + pr " | xI p => mul (square (power_pos x p)) x"; + pr " end."; + pr ""; + + pr " Theorem spec_power_pos: forall x n, [power_pos x n] = [x] ^ Zpos n."; + pa " Admitted."; + pp " Proof."; + pp " intros x n; generalize x; elim n; clear n x; simpl power_pos."; + pp " intros; rewrite spec_mul; rewrite spec_square; rewrite H."; + pp " rewrite Zpos_xI; rewrite Zpower_exp; auto with zarith."; + pp " rewrite (Zmult_comm 2); rewrite Zpower_mult; auto with zarith."; + pp " rewrite Zpower_2; rewrite Zpower_1_r; auto."; + pp " intros; rewrite spec_square; rewrite H."; + pp " rewrite Zpos_xO; auto with zarith."; + pp " rewrite (Zmult_comm 2); rewrite Zpower_mult; auto with zarith."; + pp " rewrite Zpower_2; auto."; + pp " intros; rewrite Zpower_1_r; auto."; + pp " Qed."; + pp ""; + pr ""; + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Square root *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + for i = 0 to size do + pr " Definition w%i_sqrt := w%i_op.(znz_sqrt)." i i + done; + pr ""; + + pr " Definition sqrt x :="; + pr " match x with"; + for i = 0 to size do + pr " | %s%i wx => reduce_%i (w%i_sqrt wx)" c i i i; + done; + pr " | %sn n wx =>" c; + pr " let op := make_op n in"; + pr " reduce_n n (op.(znz_sqrt) wx)"; + pr " end."; + pr ""; + + pr " Theorem spec_sqrt: forall x, [sqrt x] ^ 2 <= [x] < ([sqrt x] + 1) ^ 2."; + pa " Admitted."; + pp " Proof."; + pp " intros x; unfold sqrt; case x; clear x."; + for i = 0 to size do + pp " intros x; rewrite spec_reduce_%i; exact (spec_sqrt w%i_spec x)." i i; + done; + pp " intros n x; rewrite spec_reduce_n; exact (spec_sqrt (wn_spec n) x)."; + pp " Qed."; + pr ""; + + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Division *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + for i = 0 to size do + pr " Definition w%i_div_gt := w%i_op.(znz_div_gt)." i i + done; + pr ""; + + pp " Let spec_divn1 ww (ww_op: znz_op ww) (ww_spec: znz_spec ww_op) := "; + pp " (spec_double_divn1 "; + pp " ww_op.(znz_zdigits) ww_op.(znz_0)"; + pp " (znz_WW ww_op) ww_op.(znz_head0)"; + pp " ww_op.(znz_add_mul_div) ww_op.(znz_div21)"; + pp " ww_op.(znz_compare) ww_op.(znz_sub) (znz_to_Z ww_op)"; + pp " (spec_to_Z ww_spec) "; + pp " (spec_zdigits ww_spec)"; + pp " (spec_0 ww_spec) (spec_WW ww_spec) (spec_head0 ww_spec)"; + pp " (spec_add_mul_div ww_spec) (spec_div21 ww_spec) "; + pp " (CyclicAxioms.spec_compare ww_spec) (CyclicAxioms.spec_sub ww_spec))."; + pp ""; + + for i = 0 to size do + pr " Definition w%i_divn1 n x y :=" i; + pr " let (u, v) :="; + pr " double_divn1 w%i_op.(znz_zdigits) w%i_op.(znz_0)" i i; + pr " (znz_WW w%i_op) w%i_op.(znz_head0)" i i; + pr " w%i_op.(znz_add_mul_div) w%i_op.(znz_div21)" i i; + pr " w%i_op.(znz_compare) w%i_op.(znz_sub) (S n) x y in" i i; + if i == size then + pr " (%sn _ u, %s%i v)." c c i + else + pr " (to_Z%i _ u, %s%i v)." i c i; + done; + pr ""; + + for i = 0 to size do + pp " Lemma spec_get_end%i: forall n x y," i; + pp " eval%in n x <= [%s%i y] -> " i c i; + pp " [%s%i (DoubleBase.get_low %s n x)] = eval%in n x." c i (pz i) i; + pp " Proof."; + pp " intros n x y H."; + pp " rewrite spec_double_eval%in; unfold to_Z." i; + pp " apply DoubleBase.spec_get_low."; + pp " exact (spec_0 w%i_spec)." i; + pp " exact (spec_to_Z w%i_spec)." i; + pp " apply Zle_lt_trans with [%s%i y]; auto." c i; + pp " rewrite <- spec_double_eval%in; auto." i; + pp " unfold to_Z; case (spec_to_Z w%i_spec y); auto." i; + pp " Qed."; + pp ""; + done; + + for i = 0 to size do + pr " Let div_gt%i x y := let (u,v) := (w%i_div_gt x y) in (reduce_%i u, reduce_%i v)." i i i i; + done; + pr ""; + + + pr " Let div_gtnm n m wx wy :="; + pr " let mn := Max.max n m in"; + pr " let d := diff n m in"; + pr " let op := make_op mn in"; + pr " let (q, r):= op.(znz_div_gt)"; + pr " (castm (diff_r n m) (extend_tr wx (snd d)))"; + pr " (castm (diff_l n m) (extend_tr wy (fst d))) in"; + pr " (reduce_n mn q, reduce_n mn r)."; + pr ""; + + pr " Definition div_gt := Eval lazy beta delta [iter] in"; + pr " (iter _ "; + for i = 0 to size do + pr " div_gt%i" i; + pr " (fun n x y => div_gt%i x (DoubleBase.get_low %s (S n) y))" i (pz i); + pr " w%i_divn1" i; + done; + pr " div_gtnm)."; + pr ""; + + pr " Theorem spec_div_gt: forall x y,"; + pr " [x] > [y] -> 0 < [y] ->"; + pr " let (q,r) := div_gt x y in"; + pr " [q] = [x] / [y] /\\ [r] = [x] mod [y]."; + pa " Admitted."; + pp " Proof."; + pp " assert (FO:"; + pp " forall x y, [x] > [y] -> 0 < [y] ->"; + pp " let (q,r) := div_gt x y in"; + pp " [x] = [q] * [y] + [r] /\\ 0 <= [r] < [y])."; + pp " refine (spec_iter (t_*t_) (fun x y res => x > y -> 0 < y ->"; + pp " let (q,r) := res in"; + pp " x = [q] * y + [r] /\\ 0 <= [r] < y)"; + for i = 0 to size do + pp " div_gt%i" i; + pp " (fun n x y => div_gt%i x (DoubleBase.get_low %s (S n) y))" i (pz i); + pp " w%i_divn1 _ _ _" i; + done; + pp " div_gtnm _)."; + for i = 0 to size do + pp " intros x y H1 H2; unfold div_gt%i, w%i_div_gt." i i; + pp " generalize (spec_div_gt w%i_spec x y H1 H2); case znz_div_gt." i; + pp " intros xx yy; repeat rewrite spec_reduce_%i; auto." i; + if i == size then + pp " intros n x y H2 H3; unfold div_gt%i, w%i_div_gt." i i + else + pp " intros n x y H1 H2 H3; unfold div_gt%i, w%i_div_gt." i i; + pp " generalize (spec_div_gt w%i_spec x " i; + pp " (DoubleBase.get_low %s (S n) y))." (pz i); + pp0 " "; + for j = 0 to i do + pp0 "unfold w%i; " (i-j); + done; + pp "case znz_div_gt."; + pp " intros xx yy H4; repeat rewrite spec_reduce_%i." i; + pp " generalize (spec_get_end%i (S n) y x); unfold to_Z; intros H5." i; + pp " unfold to_Z in H2; rewrite H5 in H4; auto with zarith."; + if i == size then + pp " intros n x y H2 H3." + else + pp " intros n x y H1 H2 H3."; + pp " generalize"; + pp " (spec_divn1 w%i w%i_op w%i_spec (S n) x y H3)." i i i; + pp0 " unfold w%i_divn1; " i; + for j = 0 to i do + pp0 "unfold w%i; " (i-j); + done; + pp "case double_divn1."; + pp " intros xx yy H4."; + if i == size then + begin + pp " repeat rewrite <- spec_double_eval%in in H4; auto." i; + pp " rewrite spec_eval%in; auto." i; + end + else + begin + pp " rewrite to_Z%i_spec; auto with zarith." i; + pp " repeat rewrite <- spec_double_eval%in in H4; auto." i; + end; + done; + pp " intros n m x y H1 H2; unfold div_gtnm."; + pp " generalize (spec_div_gt (wn_spec (Max.max n m))"; + pp " (castm (diff_r n m)"; + pp " (extend_tr x (snd (diff n m))))"; + pp " (castm (diff_l n m)"; + pp " (extend_tr y (fst (diff n m)))))."; + pp " case znz_div_gt."; + pp " intros xx yy HH."; + pp " repeat rewrite spec_reduce_n."; + pp " rewrite <- (spec_cast_l n m x)."; + pp " rewrite <- (spec_cast_r n m y)."; + pp " unfold to_Z; apply HH."; + pp " rewrite <- (spec_cast_l n m x) in H1; auto."; + pp " rewrite <- (spec_cast_r n m y) in H1; auto."; + pp " rewrite <- (spec_cast_r n m y) in H2; auto."; + pp " intros x y H1 H2; generalize (FO x y H1 H2); case div_gt."; + pp " intros q r (H3, H4); split."; + pp " apply (Zdiv_unique [x] [y] [q] [r]); auto."; + pp " rewrite Zmult_comm; auto."; + pp " apply (Zmod_unique [x] [y] [q] [r]); auto."; + pp " rewrite Zmult_comm; auto."; + pp " Qed."; + pr ""; + + pr " Definition div_eucl x y :="; + pr " match compare x y with"; + pr " | Eq => (one, zero)"; + pr " | Lt => (zero, x)"; + pr " | Gt => div_gt x y"; + pr " end."; + pr ""; + + pr " Theorem spec_div_eucl: forall x y,"; + pr " 0 < [y] ->"; + pr " let (q,r) := div_eucl x y in"; + pr " ([q], [r]) = Zdiv_eucl [x] [y]."; + pa " Admitted."; + pp " Proof."; + pp " assert (F0: [zero] = 0)."; + pp " exact (spec_0 w0_spec)."; + pp " assert (F1: [one] = 1)."; + pp " exact (spec_1 w0_spec)."; + pp " intros x y H; generalize (spec_compare x y);"; + pp " unfold div_eucl; case compare; try rewrite F0;"; + pp " try rewrite F1; intros; auto with zarith."; + pp " rewrite H0; generalize (Z_div_same [y] (Zlt_gt _ _ H))"; + pp " (Z_mod_same [y] (Zlt_gt _ _ H));"; + pp " unfold Zdiv, Zmod; case Zdiv_eucl; intros; subst; auto."; + pp " assert (F2: 0 <= [x] < [y])."; + pp " generalize (spec_pos x); auto."; + pp " generalize (Zdiv_small _ _ F2)"; + pp " (Zmod_small _ _ F2);"; + pp " unfold Zdiv, Zmod; case Zdiv_eucl; intros; subst; auto."; + pp " generalize (spec_div_gt _ _ H0 H); auto."; + pp " unfold Zdiv, Zmod; case Zdiv_eucl; case div_gt."; + pp " intros a b c d (H1, H2); subst; auto."; + pp " Qed."; + pr ""; + + pr " Definition div x y := fst (div_eucl x y)."; + pr ""; + + pr " Theorem spec_div:"; + pr " forall x y, 0 < [y] -> [div x y] = [x] / [y]."; + pa " Admitted."; + pp " Proof."; + pp " intros x y H1; unfold div; generalize (spec_div_eucl x y H1);"; + pp " case div_eucl; simpl fst."; + pp " intros xx yy; unfold Zdiv; case Zdiv_eucl; intros qq rr H; "; + pp " injection H; auto."; + pp " Qed."; + pr ""; + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Modulo *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + for i = 0 to size do + pr " Definition w%i_mod_gt := w%i_op.(znz_mod_gt)." i i + done; + pr ""; + + for i = 0 to size do + pr " Definition w%i_modn1 :=" i; + pr " double_modn1 w%i_op.(znz_zdigits) w%i_op.(znz_0)" i i; + pr " w%i_op.(znz_head0) w%i_op.(znz_add_mul_div) w%i_op.(znz_div21)" i i i; + pr " w%i_op.(znz_compare) w%i_op.(znz_sub)." i i; + done; + pr ""; + + pr " Let mod_gtnm n m wx wy :="; + pr " let mn := Max.max n m in"; + pr " let d := diff n m in"; + pr " let op := make_op mn in"; + pr " reduce_n mn (op.(znz_mod_gt)"; + pr " (castm (diff_r n m) (extend_tr wx (snd d)))"; + pr " (castm (diff_l n m) (extend_tr wy (fst d))))."; + pr ""; + + pr " Definition mod_gt := Eval lazy beta delta[iter] in"; + pr " (iter _ "; + for i = 0 to size do + pr " (fun x y => reduce_%i (w%i_mod_gt x y))" i i; + pr " (fun n x y => reduce_%i (w%i_mod_gt x (DoubleBase.get_low %s (S n) y)))" i i (pz i); + pr " (fun n x y => reduce_%i (w%i_modn1 (S n) x y))" i i; + done; + pr " mod_gtnm)."; + pr ""; + + pp " Let spec_modn1 ww (ww_op: znz_op ww) (ww_spec: znz_spec ww_op) := "; + pp " (spec_double_modn1 "; + pp " ww_op.(znz_zdigits) ww_op.(znz_0)"; + pp " (znz_WW ww_op) ww_op.(znz_head0)"; + pp " ww_op.(znz_add_mul_div) ww_op.(znz_div21)"; + pp " ww_op.(znz_compare) ww_op.(znz_sub) (znz_to_Z ww_op)"; + pp " (spec_to_Z ww_spec) "; + pp " (spec_zdigits ww_spec)"; + pp " (spec_0 ww_spec) (spec_WW ww_spec) (spec_head0 ww_spec)"; + pp " (spec_add_mul_div ww_spec) (spec_div21 ww_spec) "; + pp " (CyclicAxioms.spec_compare ww_spec) (CyclicAxioms.spec_sub ww_spec))."; + pp ""; + + pr " Theorem spec_mod_gt:"; + pr " forall x y, [x] > [y] -> 0 < [y] -> [mod_gt x y] = [x] mod [y]."; + pa " Admitted."; + pp " Proof."; + pp " refine (spec_iter _ (fun x y res => x > y -> 0 < y ->"; + pp " [res] = x mod y)"; + for i = 0 to size do + pp " (fun x y => reduce_%i (w%i_mod_gt x y))" i i; + pp " (fun n x y => reduce_%i (w%i_mod_gt x (DoubleBase.get_low %s (S n) y)))" i i (pz i); + pp " (fun n x y => reduce_%i (w%i_modn1 (S n) x y)) _ _ _" i i; + done; + pp " mod_gtnm _)."; + for i = 0 to size do + pp " intros x y H1 H2; rewrite spec_reduce_%i." i; + pp " exact (spec_mod_gt w%i_spec x y H1 H2)." i; + if i == size then + pp " intros n x y H2 H3; rewrite spec_reduce_%i." i + else + pp " intros n x y H1 H2 H3; rewrite spec_reduce_%i." i; + pp " unfold w%i_mod_gt." i; + pp " rewrite <- (spec_get_end%i (S n) y x); auto with zarith." i; + pp " unfold to_Z; apply (spec_mod_gt w%i_spec); auto." i; + pp " rewrite <- (spec_get_end%i (S n) y x) in H2; auto with zarith." i; + pp " rewrite <- (spec_get_end%i (S n) y x) in H3; auto with zarith." i; + if i == size then + pp " intros n x y H2 H3; rewrite spec_reduce_%i." i + else + pp " intros n x y H1 H2 H3; rewrite spec_reduce_%i." i; + pp " unfold w%i_modn1, to_Z; rewrite spec_double_eval%in." i i; + pp " apply (spec_modn1 _ _ w%i_spec); auto." i; + done; + pp " intros n m x y H1 H2; unfold mod_gtnm."; + pp " repeat rewrite spec_reduce_n."; + pp " rewrite <- (spec_cast_l n m x)."; + pp " rewrite <- (spec_cast_r n m y)."; + pp " unfold to_Z; apply (spec_mod_gt (wn_spec (Max.max n m)))."; + pp " rewrite <- (spec_cast_l n m x) in H1; auto."; + pp " rewrite <- (spec_cast_r n m y) in H1; auto."; + pp " rewrite <- (spec_cast_r n m y) in H2; auto."; + pp " Qed."; + pr ""; + + pr " Definition modulo x y := "; + pr " match compare x y with"; + pr " | Eq => zero"; + pr " | Lt => x"; + pr " | Gt => mod_gt x y"; + pr " end."; + pr ""; + + pr " Theorem spec_modulo:"; + pr " forall x y, 0 < [y] -> [modulo x y] = [x] mod [y]."; + pa " Admitted."; + pp " Proof."; + pp " assert (F0: [zero] = 0)."; + pp " exact (spec_0 w0_spec)."; + pp " assert (F1: [one] = 1)."; + pp " exact (spec_1 w0_spec)."; + pp " intros x y H; generalize (spec_compare x y);"; + pp " unfold modulo; case compare; try rewrite F0;"; + pp " try rewrite F1; intros; try split; auto with zarith."; + pp " rewrite H0; apply sym_equal; apply Z_mod_same; auto with zarith."; + pp " apply sym_equal; apply Zmod_small; auto with zarith."; + pp " generalize (spec_pos x); auto with zarith."; + pp " apply spec_mod_gt; auto."; + pp " Qed."; + pr ""; + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Gcd *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + pr " Definition digits x :="; + pr " match x with"; + for i = 0 to size do + pr " | %s%i _ => w%i_op.(znz_digits)" c i i; + done; + pr " | %sn n _ => (make_op n).(znz_digits)" c; + pr " end."; + pr ""; + + pr " Theorem spec_digits: forall x, 0 <= [x] < 2 ^ Zpos (digits x)."; + pa " Admitted."; + pp " Proof."; + pp " intros x; case x; clear x."; + for i = 0 to size do + pp " intros x; unfold to_Z, digits;"; + pp " generalize (spec_to_Z w%i_spec x); unfold base; intros H; exact H." i; + done; + pp " intros n x; unfold to_Z, digits;"; + pp " generalize (spec_to_Z (wn_spec n) x); unfold base; intros H; exact H."; + pp " Qed."; + pr ""; + + pr " Definition gcd_gt_body a b cont :="; + pr " match compare b zero with"; + pr " | Gt =>"; + pr " let r := mod_gt a b in"; + pr " match compare r zero with"; + pr " | Gt => cont r (mod_gt b r)"; + pr " | _ => b"; + pr " end"; + pr " | _ => a"; + pr " end."; + pr ""; + + pp " Theorem Zspec_gcd_gt_body: forall a b cont p,"; + pp " [a] > [b] -> [a] < 2 ^ p ->"; + pp " (forall a1 b1, [a1] < 2 ^ (p - 1) -> [a1] > [b1] ->"; + pp " Zis_gcd [a1] [b1] [cont a1 b1]) -> "; + pp " Zis_gcd [a] [b] [gcd_gt_body a b cont]."; + pp " Proof."; + pp " assert (F1: [zero] = 0)."; + pp " unfold zero, w_0, to_Z; rewrite (spec_0 w0_spec); auto."; + pp " intros a b cont p H2 H3 H4; unfold gcd_gt_body."; + pp " generalize (spec_compare b zero); case compare; try rewrite F1."; + pp " intros HH; rewrite HH; apply Zis_gcd_0."; + pp " intros HH; absurd (0 <= [b]); auto with zarith."; + pp " case (spec_digits b); auto with zarith."; + pp " intros H5; generalize (spec_compare (mod_gt a b) zero); "; + pp " case compare; try rewrite F1."; + pp " intros H6; rewrite <- (Zmult_1_r [b])."; + pp " rewrite (Z_div_mod_eq [a] [b]); auto with zarith."; + pp " rewrite <- spec_mod_gt; auto with zarith."; + pp " rewrite H6; rewrite Zplus_0_r."; + pp " apply Zis_gcd_mult; apply Zis_gcd_1."; + pp " intros; apply False_ind."; + pp " case (spec_digits (mod_gt a b)); auto with zarith."; + pp " intros H6; apply DoubleDiv.Zis_gcd_mod; auto with zarith."; + pp " apply DoubleDiv.Zis_gcd_mod; auto with zarith."; + pp " rewrite <- spec_mod_gt; auto with zarith."; + pp " assert (F2: [b] > [mod_gt a b])."; + pp " case (Z_mod_lt [a] [b]); auto with zarith."; + pp " repeat rewrite <- spec_mod_gt; auto with zarith."; + pp " assert (F3: [mod_gt a b] > [mod_gt b (mod_gt a b)])."; + pp " case (Z_mod_lt [b] [mod_gt a b]); auto with zarith."; + pp " rewrite <- spec_mod_gt; auto with zarith."; + pp " repeat rewrite <- spec_mod_gt; auto with zarith."; + pp " apply H4; auto with zarith."; + pp " apply Zmult_lt_reg_r with 2; auto with zarith."; + pp " apply Zle_lt_trans with ([b] + [mod_gt a b]); auto with zarith."; + pp " apply Zle_lt_trans with (([a]/[b]) * [b] + [mod_gt a b]); auto with zarith."; + pp " apply Zplus_le_compat_r."; + pp " pattern [b] at 1; rewrite <- (Zmult_1_l [b])."; + pp " apply Zmult_le_compat_r; auto with zarith."; + pp " case (Zle_lt_or_eq 0 ([a]/[b])); auto with zarith."; + pp " intros HH; rewrite (Z_div_mod_eq [a] [b]) in H2;"; + pp " try rewrite <- HH in H2; auto with zarith."; + pp " case (Z_mod_lt [a] [b]); auto with zarith."; + pp " rewrite Zmult_comm; rewrite spec_mod_gt; auto with zarith."; + pp " rewrite <- Z_div_mod_eq; auto with zarith."; + pp " pattern 2 at 2; rewrite <- (Zpower_1_r 2)."; + pp " rewrite <- Zpower_exp; auto with zarith."; + pp " ring_simplify (p - 1 + 1); auto."; + pp " case (Zle_lt_or_eq 0 p); auto with zarith."; + pp " generalize H3; case p; simpl Zpower; auto with zarith."; + pp " intros HH; generalize H3; rewrite <- HH; simpl Zpower; auto with zarith."; + pp " Qed."; + pp ""; + + pr " Fixpoint gcd_gt_aux (p:positive) (cont:t->t->t) (a b:t) {struct p} : t :="; + pr " gcd_gt_body a b"; + pr " (fun a b =>"; + pr " match p with"; + pr " | xH => cont a b"; + pr " | xO p => gcd_gt_aux p (gcd_gt_aux p cont) a b"; + pr " | xI p => gcd_gt_aux p (gcd_gt_aux p cont) a b"; + pr " end)."; + pr ""; + + pp " Theorem Zspec_gcd_gt_aux: forall p n a b cont,"; + pp " [a] > [b] -> [a] < 2 ^ (Zpos p + n) ->"; + pp " (forall a1 b1, [a1] < 2 ^ n -> [a1] > [b1] ->"; + pp " Zis_gcd [a1] [b1] [cont a1 b1]) ->"; + pp " Zis_gcd [a] [b] [gcd_gt_aux p cont a b]."; + pp " intros p; elim p; clear p."; + pp " intros p Hrec n a b cont H2 H3 H4."; + pp " unfold gcd_gt_aux; apply Zspec_gcd_gt_body with (Zpos (xI p) + n); auto."; + pp " intros a1 b1 H6 H7."; + pp " apply Hrec with (Zpos p + n); auto."; + pp " replace (Zpos p + (Zpos p + n)) with"; + pp " (Zpos (xI p) + n - 1); auto."; + pp " rewrite Zpos_xI; ring."; + pp " intros a2 b2 H9 H10."; + pp " apply Hrec with n; auto."; + pp " intros p Hrec n a b cont H2 H3 H4."; + pp " unfold gcd_gt_aux; apply Zspec_gcd_gt_body with (Zpos (xO p) + n); auto."; + pp " intros a1 b1 H6 H7."; + pp " apply Hrec with (Zpos p + n - 1); auto."; + pp " replace (Zpos p + (Zpos p + n - 1)) with"; + pp " (Zpos (xO p) + n - 1); auto."; + pp " rewrite Zpos_xO; ring."; + pp " intros a2 b2 H9 H10."; + pp " apply Hrec with (n - 1); auto."; + pp " replace (Zpos p + (n - 1)) with"; + pp " (Zpos p + n - 1); auto with zarith."; + pp " intros a3 b3 H12 H13; apply H4; auto with zarith."; + pp " apply Zlt_le_trans with (1 := H12)."; + pp " case (Zle_or_lt 1 n); intros HH."; + pp " apply Zpower_le_monotone; auto with zarith."; + pp " apply Zle_trans with 0; auto with zarith."; + pp " assert (HH1: n - 1 < 0); auto with zarith."; + pp " generalize HH1; case (n - 1); auto with zarith."; + pp " intros p1 HH2; discriminate."; + pp " intros n a b cont H H2 H3."; + pp " simpl gcd_gt_aux."; + pp " apply Zspec_gcd_gt_body with (n + 1); auto with zarith."; + pp " rewrite Zplus_comm; auto."; + pp " intros a1 b1 H5 H6; apply H3; auto."; + pp " replace n with (n + 1 - 1); auto; try ring."; + pp " Qed."; + pp ""; + + pr " Definition gcd_cont a b :="; + pr " match compare one b with"; + pr " | Eq => one"; + pr " | _ => a"; + pr " end."; + pr ""; + + pr " Definition gcd_gt a b := gcd_gt_aux (digits a) gcd_cont a b."; + pr ""; + + pr " Theorem spec_gcd_gt: forall a b,"; + pr " [a] > [b] -> [gcd_gt a b] = Zgcd [a] [b]."; + pa " Admitted."; + pp " Proof."; + pp " intros a b H2."; + pp " case (spec_digits (gcd_gt a b)); intros H3 H4."; + pp " case (spec_digits a); intros H5 H6."; + pp " apply sym_equal; apply Zis_gcd_gcd; auto with zarith."; + pp " unfold gcd_gt; apply Zspec_gcd_gt_aux with 0; auto with zarith."; + pp " intros a1 a2; rewrite Zpower_0_r."; + pp " case (spec_digits a2); intros H7 H8;"; + pp " intros; apply False_ind; auto with zarith."; + pp " Qed."; + pr ""; + + pr " Definition gcd a b :="; + pr " match compare a b with"; + pr " | Eq => a"; + pr " | Lt => gcd_gt b a"; + pr " | Gt => gcd_gt a b"; + pr " end."; + pr ""; + + pr " Theorem spec_gcd: forall a b, [gcd a b] = Zgcd [a] [b]."; + pa " Admitted."; + pp " Proof."; + pp " intros a b."; + pp " case (spec_digits a); intros H1 H2."; + pp " case (spec_digits b); intros H3 H4."; + pp " unfold gcd; generalize (spec_compare a b); case compare."; + pp " intros HH; rewrite HH; apply sym_equal; apply Zis_gcd_gcd; auto."; + pp " apply Zis_gcd_refl."; + pp " intros; apply trans_equal with (Zgcd [b] [a])."; + pp " apply spec_gcd_gt; auto with zarith."; + pp " apply Zis_gcd_gcd; auto with zarith."; + pp " apply Zgcd_is_pos."; + pp " apply Zis_gcd_sym; apply Zgcd_is_gcd."; + pp " intros; apply spec_gcd_gt; auto."; + pp " Qed."; + pr ""; + + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Conversion *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + pr " Definition pheight p := "; + pr " Peano.pred (nat_of_P (get_height w0_op.(znz_digits) (plength p)))."; + pr ""; + + pr " Theorem pheight_correct: forall p, "; + pr " Zpos p < 2 ^ (Zpos (znz_digits w0_op) * 2 ^ (Z_of_nat (pheight p)))."; + pr " Proof."; + pr " intros p; unfold pheight."; + pr " assert (F1: forall x, Z_of_nat (Peano.pred (nat_of_P x)) = Zpos x - 1)."; + pr " intros x."; + pr " assert (Zsucc (Z_of_nat (Peano.pred (nat_of_P x))) = Zpos x); auto with zarith."; + pr " rewrite <- inj_S."; + pr " rewrite <- (fun x => S_pred x 0); auto with zarith."; + pr " rewrite Zpos_eq_Z_of_nat_o_nat_of_P; auto."; + pr " apply lt_le_trans with 1%snat; auto with zarith." "%"; + pr " exact (le_Pmult_nat x 1)."; + pr " rewrite F1; clear F1."; + pr " assert (F2:= (get_height_correct (znz_digits w0_op) (plength p)))."; + pr " apply Zlt_le_trans with (Zpos (Psucc p))."; + pr " rewrite Zpos_succ_morphism; auto with zarith."; + pr " apply Zle_trans with (1 := plength_pred_correct (Psucc p))."; + pr " rewrite Ppred_succ."; + pr " apply Zpower_le_monotone; auto with zarith."; + pr " Qed."; + pr ""; + + pr " Definition of_pos x :="; + pr " let h := pheight x in"; + pr " match h with"; + for i = 0 to size do + pr " | %i%snat => reduce_%i (snd (w%i_op.(znz_of_pos) x))" i "%" i i; + done; + pr " | _ =>"; + pr " let n := minus h %i in" (size + 1); + pr " reduce_n n (snd ((make_op n).(znz_of_pos) x))"; + pr " end."; + pr ""; + + pr " Theorem spec_of_pos: forall x,"; + pr " [of_pos x] = Zpos x."; + pa " Admitted."; + pp " Proof."; + pp " assert (F := spec_more_than_1_digit w0_spec)."; + pp " intros x; unfold of_pos; case_eq (pheight x)."; + for i = 0 to size do + if i <> 0 then + pp " intros n; case n; clear n."; + pp " intros H1; rewrite spec_reduce_%i; unfold to_Z." i; + pp " apply (znz_of_pos_correct w%i_spec)." i; + pp " apply Zlt_le_trans with (1 := pheight_correct x)."; + pp " rewrite H1; simpl Z_of_nat; change (2^%i) with (%s)." i (gen2 i); + pp " unfold base."; + pp " apply Zpower_le_monotone; split; auto with zarith."; + if i <> 0 then + begin + pp " rewrite Zmult_comm; repeat rewrite <- Zmult_assoc."; + pp " repeat rewrite <- Zpos_xO."; + pp " refine (Zle_refl _)."; + end; + done; + pp " intros n."; + pp " intros H1; rewrite spec_reduce_n; unfold to_Z."; + pp " simpl minus; rewrite <- minus_n_O."; + pp " apply (znz_of_pos_correct (wn_spec n))."; + pp " apply Zlt_le_trans with (1 := pheight_correct x)."; + pp " unfold base."; + pp " apply Zpower_le_monotone; auto with zarith."; + pp " split; auto with zarith."; + pp " rewrite H1."; + pp " elim n; clear n H1."; + pp " simpl Z_of_nat; change (2^%i) with (%s)." (size + 1) (gen2 (size + 1)); + pp " rewrite Zmult_comm; repeat rewrite <- Zmult_assoc."; + pp " repeat rewrite <- Zpos_xO."; + pp " refine (Zle_refl _)."; + pp " intros n Hrec."; + pp " rewrite make_op_S."; + pp " change (@znz_digits (word _ (S (S n))) (mk_zn2z_op_karatsuba (make_op n))) with"; + pp " (xO (znz_digits (make_op n)))."; + pp " rewrite (fun x y => (Zpos_xO (@znz_digits x y)))."; + pp " rewrite inj_S; unfold Zsucc."; + pp " rewrite Zplus_comm; rewrite Zpower_exp; auto with zarith."; + pp " rewrite Zpower_1_r."; + pp " assert (tmp: forall x y z, x * (y * z) = y * (x * z));"; + pp " [intros; ring | rewrite tmp; clear tmp]."; + pp " apply Zmult_le_compat_l; auto with zarith."; + pp " Qed."; + pr ""; + + pr " Definition of_N x :="; + pr " match x with"; + pr " | BinNat.N0 => zero"; + pr " | Npos p => of_pos p"; + pr " end."; + pr ""; + + pr " Theorem spec_of_N: forall x,"; + pr " [of_N x] = Z_of_N x."; + pa " Admitted."; + pp " Proof."; + pp " intros x; case x."; + pp " simpl of_N."; + pp " unfold zero, w_0, to_Z; rewrite (spec_0 w0_spec); auto."; + pp " intros p; exact (spec_of_pos p)."; + pp " Qed."; + pr ""; + + pr " (***************************************************************)"; + pr " (* *)"; + pr " (* Shift *)"; + pr " (* *)"; + pr " (***************************************************************)"; + pr ""; + + (* Head0 *) + pr " Definition head0 w := match w with"; + for i = 0 to size do + pr " | %s%i w=> reduce_%i (w%i_op.(znz_head0) w)" c i i i; + done; + pr " | %sn n w=> reduce_n n ((make_op n).(znz_head0) w)" c; + pr " end."; + pr ""; + + pr " Theorem spec_head00: forall x, [x] = 0 ->[head0 x] = Zpos (digits x)."; + pa " Admitted."; + pp " Proof."; + pp " intros x; case x; unfold head0; clear x."; + for i = 0 to size do + pp " intros x; rewrite spec_reduce_%i; exact (spec_head00 w%i_spec x)." i i; + done; + pp " intros n x; rewrite spec_reduce_n; exact (spec_head00 (wn_spec n) x)."; + pp " Qed."; + pr " "; + + pr " Theorem spec_head0: forall x, 0 < [x] ->"; + pr " 2 ^ (Zpos (digits x) - 1) <= 2 ^ [head0 x] * [x] < 2 ^ Zpos (digits x)."; + pa " Admitted."; + pp " Proof."; + pp " assert (F0: forall x, (x - 1) + 1 = x)."; + pp " intros; ring. "; + pp " intros x; case x; unfold digits, head0; clear x."; + for i = 0 to size do + pp " intros x Hx; rewrite spec_reduce_%i." i; + pp " assert (F1:= spec_more_than_1_digit w%i_spec)." i; + pp " generalize (spec_head0 w%i_spec x Hx)." i; + pp " unfold base."; + pp " pattern (Zpos (znz_digits w%i_op)) at 1; " i; + pp " rewrite <- (fun x => (F0 (Zpos x)))."; + pp " rewrite Zpower_exp; auto with zarith."; + pp " rewrite Zpower_1_r; rewrite Z_div_mult; auto with zarith."; + done; + pp " intros n x Hx; rewrite spec_reduce_n."; + pp " assert (F1:= spec_more_than_1_digit (wn_spec n))."; + pp " generalize (spec_head0 (wn_spec n) x Hx)."; + pp " unfold base."; + pp " pattern (Zpos (znz_digits (make_op n))) at 1; "; + pp " rewrite <- (fun x => (F0 (Zpos x)))."; + pp " rewrite Zpower_exp; auto with zarith."; + pp " rewrite Zpower_1_r; rewrite Z_div_mult; auto with zarith."; + pp " Qed."; + pr ""; + + + (* Tail0 *) + pr " Definition tail0 w := match w with"; + for i = 0 to size do + pr " | %s%i w=> reduce_%i (w%i_op.(znz_tail0) w)" c i i i; + done; + pr " | %sn n w=> reduce_n n ((make_op n).(znz_tail0) w)" c; + pr " end."; + pr ""; + + + pr " Theorem spec_tail00: forall x, [x] = 0 ->[tail0 x] = Zpos (digits x)."; + pa " Admitted."; + pp " Proof."; + pp " intros x; case x; unfold tail0; clear x."; + for i = 0 to size do + pp " intros x; rewrite spec_reduce_%i; exact (spec_tail00 w%i_spec x)." i i; + done; + pp " intros n x; rewrite spec_reduce_n; exact (spec_tail00 (wn_spec n) x)."; + pp " Qed."; + pr " "; + + + pr " Theorem spec_tail0: forall x,"; + pr " 0 < [x] -> exists y, 0 <= y /\\ [x] = (2 * y + 1) * 2 ^ [tail0 x]."; + pa " Admitted."; + pp " Proof."; + pp " intros x; case x; clear x; unfold tail0."; + for i = 0 to size do + pp " intros x Hx; rewrite spec_reduce_%i; exact (spec_tail0 w%i_spec x Hx)." i i; + done; + pp " intros n x Hx; rewrite spec_reduce_n; exact (spec_tail0 (wn_spec n) x Hx)."; + pp " Qed."; + pr ""; + + + (* Number of digits *) + pr " Definition %sdigits x :=" c; + pr " match x with"; + pr " | %s0 _ => %s0 w0_op.(znz_zdigits)" c c; + for i = 1 to size do + pr " | %s%i _ => reduce_%i w%i_op.(znz_zdigits)" c i i i; + done; + pr " | %sn n _ => reduce_n n (make_op n).(znz_zdigits)" c; + pr " end."; + pr ""; + + pr " Theorem spec_Ndigits: forall x, [Ndigits x] = Zpos (digits x)."; + pa " Admitted."; + pp " Proof."; + pp " intros x; case x; clear x; unfold Ndigits, digits."; + for i = 0 to size do + pp " intros _; try rewrite spec_reduce_%i; exact (spec_zdigits w%i_spec)." i i; + done; + pp " intros n _; try rewrite spec_reduce_n; exact (spec_zdigits (wn_spec n))."; + pp " Qed."; + pr ""; + + + (* Shiftr *) + for i = 0 to size do + pr " Definition shiftr%i n x := w%i_op.(znz_add_mul_div) (w%i_op.(znz_sub) w%i_op.(znz_zdigits) n) w%i_op.(znz_0) x." i i i i i; + done; + pr " Definition shiftrn n p x := (make_op n).(znz_add_mul_div) ((make_op n).(znz_sub) (make_op n).(znz_zdigits) p) (make_op n).(znz_0) x."; + pr ""; + + pr " Definition shiftr := Eval lazy beta delta [same_level] in "; + pr " same_level _ (fun n x => %s0 (shiftr0 n x))" c; + for i = 1 to size do + pr " (fun n x => reduce_%i (shiftr%i n x))" i i; + done; + pr " (fun n p x => reduce_n n (shiftrn n p x))."; + pr ""; + + + pr " Theorem spec_shiftr: forall n x,"; + pr " [n] <= [Ndigits x] -> [shiftr n x] = [x] / 2 ^ [n]."; + pa " Admitted."; + pp " Proof."; + pp " assert (F0: forall x y, x - (x - y) = y)."; + pp " intros; ring."; + pp " assert (F2: forall x y z, 0 <= x -> 0 <= y -> x < z -> 0 <= x / 2 ^ y < z)."; + pp " intros x y z HH HH1 HH2."; + pp " split; auto with zarith."; + pp " apply Zle_lt_trans with (2 := HH2); auto with zarith."; + pp " apply Zdiv_le_upper_bound; auto with zarith."; + pp " pattern x at 1; replace x with (x * 2 ^ 0); auto with zarith."; + pp " apply Zmult_le_compat_l; auto."; + pp " apply Zpower_le_monotone; auto with zarith."; + pp " rewrite Zpower_0_r; ring."; + pp " assert (F3: forall x y, 0 <= y -> y <= x -> 0 <= x - y < 2 ^ x)."; + pp " intros xx y HH HH1."; + pp " split; auto with zarith."; + pp " apply Zle_lt_trans with xx; auto with zarith."; + pp " apply Zpower2_lt_lin; auto with zarith."; + pp " assert (F4: forall ww ww1 ww2 "; + pp " (ww_op: znz_op ww) (ww1_op: znz_op ww1) (ww2_op: znz_op ww2)"; + pp " xx yy xx1 yy1,"; + pp " znz_to_Z ww2_op yy <= znz_to_Z ww1_op (znz_zdigits ww1_op) ->"; + pp " znz_to_Z ww1_op (znz_zdigits ww1_op) <= znz_to_Z ww_op (znz_zdigits ww_op) ->"; + pp " znz_spec ww_op -> znz_spec ww1_op -> znz_spec ww2_op ->"; + pp " znz_to_Z ww_op xx1 = znz_to_Z ww1_op xx ->"; + pp " znz_to_Z ww_op yy1 = znz_to_Z ww2_op yy ->"; + pp " znz_to_Z ww_op"; + pp " (znz_add_mul_div ww_op (znz_sub ww_op (znz_zdigits ww_op) yy1)"; + pp " (znz_0 ww_op) xx1) = znz_to_Z ww1_op xx / 2 ^ znz_to_Z ww2_op yy)."; + pp " intros ww ww1 ww2 ww_op ww1_op ww2_op xx yy xx1 yy1 Hl Hl1 Hw Hw1 Hw2 Hx Hy."; + pp " case (spec_to_Z Hw xx1); auto with zarith; intros HH1 HH2."; + pp " case (spec_to_Z Hw yy1); auto with zarith; intros HH3 HH4."; + pp " rewrite <- Hx."; + pp " rewrite <- Hy."; + pp " generalize (spec_add_mul_div Hw"; + pp " (znz_0 ww_op) xx1"; + pp " (znz_sub ww_op (znz_zdigits ww_op) "; + pp " yy1)"; + pp " )."; + pp " rewrite (spec_0 Hw)."; + pp " rewrite Zmult_0_l; rewrite Zplus_0_l."; + pp " rewrite (CyclicAxioms.spec_sub Hw)."; + pp " rewrite Zmod_small; auto with zarith."; + pp " rewrite (spec_zdigits Hw)."; + pp " rewrite F0."; + pp " rewrite Zmod_small; auto with zarith."; + pp " unfold base; rewrite (spec_zdigits Hw) in Hl1 |- *;"; + pp " auto with zarith."; + pp " assert (F5: forall n m, (n <= m)%snat ->" "%"; + pp " Zpos (znz_digits (make_op n)) <= Zpos (znz_digits (make_op m)))."; + pp " intros n m HH; elim HH; clear m HH; auto with zarith."; + pp " intros m HH Hrec; apply Zle_trans with (1 := Hrec)."; + pp " rewrite make_op_S."; + pp " match goal with |- Zpos ?Y <= ?X => change X with (Zpos (xO Y)) end."; + pp " rewrite Zpos_xO."; + pp " assert (0 <= Zpos (znz_digits (make_op n))); auto with zarith."; + pp " assert (F6: forall n, Zpos (znz_digits w%i_op) <= Zpos (znz_digits (make_op n)))." size; + pp " intros n ; apply Zle_trans with (Zpos (znz_digits (make_op 0)))."; + pp " change (znz_digits (make_op 0)) with (xO (znz_digits w%i_op))." size; + pp " rewrite Zpos_xO."; + pp " assert (0 <= Zpos (znz_digits w%i_op)); auto with zarith." size; + pp " apply F5; auto with arith."; + pp " intros x; case x; clear x; unfold shiftr, same_level."; + for i = 0 to size do + pp " intros x y; case y; clear y."; + for j = 0 to i - 1 do + pp " intros y; unfold shiftr%i, Ndigits." i; + pp " repeat rewrite spec_reduce_%i; repeat rewrite spec_reduce_%i; unfold to_Z; intros H1." i j; + pp " apply F4 with (3:=w%i_spec)(4:=w%i_spec)(5:=w%i_spec); auto with zarith." i j i; + pp " rewrite (spec_zdigits w%i_spec)." i; + pp " rewrite (spec_zdigits w%i_spec)." j; + pp " change (znz_digits w%i_op) with %s." i (genxO (i - j) (" (znz_digits w"^(string_of_int j)^"_op)")); + pp " repeat rewrite (fun x => Zpos_xO (xO x))."; + pp " repeat rewrite (fun x y => Zpos_xO (@znz_digits x y))."; + pp " assert (0 <= Zpos (znz_digits w%i_op)); auto with zarith." j; + pp " try (apply sym_equal; exact (spec_extend%in%i y))." j i; + + done; + pp " intros y; unfold shiftr%i, Ndigits." i; + pp " repeat rewrite spec_reduce_%i; unfold to_Z; intros H1." i; + pp " apply F4 with (3:=w%i_spec)(4:=w%i_spec)(5:=w%i_spec); auto with zarith." i i i; + for j = i + 1 to size do + pp " intros y; unfold shiftr%i, Ndigits." j; + pp " repeat rewrite spec_reduce_%i; repeat rewrite spec_reduce_%i; unfold to_Z; intros H1." i j; + pp " apply F4 with (3:=w%i_spec)(4:=w%i_spec)(5:=w%i_spec); auto with zarith." j j i; + pp " try (apply sym_equal; exact (spec_extend%in%i x))." i j; + done; + if i == size then + begin + pp " intros m y; unfold shiftrn, Ndigits."; + pp " repeat rewrite spec_reduce_n; unfold to_Z; intros H1."; + pp " apply F4 with (3:=(wn_spec m))(4:=wn_spec m)(5:=w%i_spec); auto with zarith." size; + pp " try (apply sym_equal; exact (spec_extend%in m x))." size; + end + else + begin + pp " intros m y; unfold shiftrn, Ndigits."; + pp " repeat rewrite spec_reduce_n; unfold to_Z; intros H1."; + pp " apply F4 with (3:=(wn_spec m))(4:=wn_spec m)(5:=w%i_spec); auto with zarith." i; + pp " change ([Nn m (extend%i m (extend%i %i x))] = [N%i x])." size i (size - i - 1) i; + pp " rewrite <- (spec_extend%in m); rewrite <- spec_extend%in%i; auto." size i size; + end + done; + pp " intros n x y; case y; clear y;"; + pp " intros y; unfold shiftrn, Ndigits; try rewrite spec_reduce_n."; + for i = 0 to size do + pp " try rewrite spec_reduce_%i; unfold to_Z; intros H1." i; + pp " apply F4 with (3:=(wn_spec n))(4:=w%i_spec)(5:=wn_spec n); auto with zarith." i; + pp " rewrite (spec_zdigits w%i_spec)." i; + pp " rewrite (spec_zdigits (wn_spec n))."; + pp " apply Zle_trans with (2 := F6 n)."; + pp " change (znz_digits w%i_op) with %s." size (genxO (size - i) ("(znz_digits w" ^ (string_of_int i) ^ "_op)")); + pp " repeat rewrite (fun x => Zpos_xO (xO x))."; + pp " repeat rewrite (fun x y => Zpos_xO (@znz_digits x y))."; + pp " assert (H: 0 <= Zpos (znz_digits w%i_op)); auto with zarith." i; + if i == size then + pp " change ([Nn n (extend%i n y)] = [N%i y])." size i + else + pp " change ([Nn n (extend%i n (extend%i %i y))] = [N%i y])." size i (size - i - 1) i; + pp " rewrite <- (spec_extend%in n); auto." size; + if i <> size then + pp " try (rewrite <- spec_extend%in%i; auto)." i size; + done; + pp " generalize y; clear y; intros m y."; + pp " rewrite spec_reduce_n; unfold to_Z; intros H1."; + pp " apply F4 with (3:=(wn_spec (Max.max n m)))(4:=wn_spec m)(5:=wn_spec n); auto with zarith."; + pp " rewrite (spec_zdigits (wn_spec m))."; + pp " rewrite (spec_zdigits (wn_spec (Max.max n m)))."; + pp " apply F5; auto with arith."; + pp " exact (spec_cast_r n m y)."; + pp " exact (spec_cast_l n m x)."; + pp " Qed."; + pr ""; + + pr " Definition safe_shiftr n x := "; + pr " match compare n (Ndigits x) with"; + pr " | Lt => shiftr n x "; + pr " | _ => %s0 w_0" c; + pr " end."; + pr ""; + + + pr " Theorem spec_safe_shiftr: forall n x,"; + pr " [safe_shiftr n x] = [x] / 2 ^ [n]."; + pa " Admitted."; + pp " Proof."; + pp " intros n x; unfold safe_shiftr;"; + pp " generalize (spec_compare n (Ndigits x)); case compare; intros H."; + pp " apply trans_equal with (1 := spec_0 w0_spec)."; + pp " apply sym_equal; apply Zdiv_small; rewrite H."; + pp " rewrite spec_Ndigits; exact (spec_digits x)."; + pp " rewrite <- spec_shiftr; auto with zarith."; + pp " apply trans_equal with (1 := spec_0 w0_spec)."; + pp " apply sym_equal; apply Zdiv_small."; + pp " rewrite spec_Ndigits in H; case (spec_digits x); intros H1 H2."; + pp " split; auto."; + pp " apply Zlt_le_trans with (1 := H2)."; + pp " apply Zpower_le_monotone; auto with zarith."; + pp " Qed."; + pr ""; + + pr ""; + + (* Shiftl *) + for i = 0 to size do + pr " Definition shiftl%i n x := w%i_op.(znz_add_mul_div) n x w%i_op.(znz_0)." i i i + done; + pr " Definition shiftln n p x := (make_op n).(znz_add_mul_div) p x (make_op n).(znz_0)."; + pr " Definition shiftl := Eval lazy beta delta [same_level] in"; + pr " same_level _ (fun n x => %s0 (shiftl0 n x))" c; + for i = 1 to size do + pr " (fun n x => reduce_%i (shiftl%i n x))" i i; + done; + pr " (fun n p x => reduce_n n (shiftln n p x))."; + pr ""; + pr ""; + + + pr " Theorem spec_shiftl: forall n x,"; + pr " [n] <= [head0 x] -> [shiftl n x] = [x] * 2 ^ [n]."; + pa " Admitted."; + pp " Proof."; + pp " assert (F0: forall x y, x - (x - y) = y)."; + pp " intros; ring."; + pp " assert (F2: forall x y z, 0 <= x -> 0 <= y -> x < z -> 0 <= x / 2 ^ y < z)."; + pp " intros x y z HH HH1 HH2."; + pp " split; auto with zarith."; + pp " apply Zle_lt_trans with (2 := HH2); auto with zarith."; + pp " apply Zdiv_le_upper_bound; auto with zarith."; + pp " pattern x at 1; replace x with (x * 2 ^ 0); auto with zarith."; + pp " apply Zmult_le_compat_l; auto."; + pp " apply Zpower_le_monotone; auto with zarith."; + pp " rewrite Zpower_0_r; ring."; + pp " assert (F3: forall x y, 0 <= y -> y <= x -> 0 <= x - y < 2 ^ x)."; + pp " intros xx y HH HH1."; + pp " split; auto with zarith."; + pp " apply Zle_lt_trans with xx; auto with zarith."; + pp " apply Zpower2_lt_lin; auto with zarith."; + pp " assert (F4: forall ww ww1 ww2 "; + pp " (ww_op: znz_op ww) (ww1_op: znz_op ww1) (ww2_op: znz_op ww2)"; + pp " xx yy xx1 yy1,"; + pp " znz_to_Z ww2_op yy <= znz_to_Z ww1_op (znz_head0 ww1_op xx) ->"; + pp " znz_to_Z ww1_op (znz_zdigits ww1_op) <= znz_to_Z ww_op (znz_zdigits ww_op) ->"; + pp " znz_spec ww_op -> znz_spec ww1_op -> znz_spec ww2_op ->"; + pp " znz_to_Z ww_op xx1 = znz_to_Z ww1_op xx ->"; + pp " znz_to_Z ww_op yy1 = znz_to_Z ww2_op yy ->"; + pp " znz_to_Z ww_op"; + pp " (znz_add_mul_div ww_op yy1"; + pp " xx1 (znz_0 ww_op)) = znz_to_Z ww1_op xx * 2 ^ znz_to_Z ww2_op yy)."; + pp " intros ww ww1 ww2 ww_op ww1_op ww2_op xx yy xx1 yy1 Hl Hl1 Hw Hw1 Hw2 Hx Hy."; + pp " case (spec_to_Z Hw xx1); auto with zarith; intros HH1 HH2."; + pp " case (spec_to_Z Hw yy1); auto with zarith; intros HH3 HH4."; + pp " rewrite <- Hx."; + pp " rewrite <- Hy."; + pp " generalize (spec_add_mul_div Hw xx1 (znz_0 ww_op) yy1)."; + pp " rewrite (spec_0 Hw)."; + pp " assert (F1: znz_to_Z ww1_op (znz_head0 ww1_op xx) <= Zpos (znz_digits ww1_op))."; + pp " case (Zle_lt_or_eq _ _ HH1); intros HH5."; + pp " apply Zlt_le_weak."; + pp " case (CyclicAxioms.spec_head0 Hw1 xx)."; + pp " rewrite <- Hx; auto."; + pp " intros _ Hu; unfold base in Hu."; + pp " case (Zle_or_lt (Zpos (znz_digits ww1_op))"; + pp " (znz_to_Z ww1_op (znz_head0 ww1_op xx))); auto; intros H1."; + pp " absurd (2 ^ (Zpos (znz_digits ww1_op)) <= 2 ^ (znz_to_Z ww1_op (znz_head0 ww1_op xx)))."; + pp " apply Zlt_not_le."; + pp " case (spec_to_Z Hw1 xx); intros HHx3 HHx4."; + pp " rewrite <- (Zmult_1_r (2 ^ znz_to_Z ww1_op (znz_head0 ww1_op xx)))."; + pp " apply Zle_lt_trans with (2 := Hu)."; + pp " apply Zmult_le_compat_l; auto with zarith."; + pp " apply Zpower_le_monotone; auto with zarith."; + pp " rewrite (CyclicAxioms.spec_head00 Hw1 xx); auto with zarith."; + pp " rewrite Zdiv_0_l; auto with zarith."; + pp " rewrite Zplus_0_r."; + pp " case (Zle_lt_or_eq _ _ HH1); intros HH5."; + pp " rewrite Zmod_small; auto with zarith."; + pp " intros HH; apply HH."; + pp " rewrite Hy; apply Zle_trans with (1:= Hl)."; + pp " rewrite <- (spec_zdigits Hw). "; + pp " apply Zle_trans with (2 := Hl1); auto."; + pp " rewrite (spec_zdigits Hw1); auto with zarith."; + pp " split; auto with zarith ."; + pp " apply Zlt_le_trans with (base (znz_digits ww1_op))."; + pp " rewrite Hx."; + pp " case (CyclicAxioms.spec_head0 Hw1 xx); auto."; + pp " rewrite <- Hx; auto."; + pp " intros _ Hu; rewrite Zmult_comm in Hu."; + pp " apply Zle_lt_trans with (2 := Hu)."; + pp " apply Zmult_le_compat_l; auto with zarith."; + pp " apply Zpower_le_monotone; auto with zarith."; + pp " unfold base; apply Zpower_le_monotone; auto with zarith."; + pp " split; auto with zarith."; + pp " rewrite <- (spec_zdigits Hw); auto with zarith."; + pp " rewrite <- (spec_zdigits Hw1); auto with zarith."; + pp " rewrite <- HH5."; + pp " rewrite Zmult_0_l."; + pp " rewrite Zmod_small; auto with zarith."; + pp " intros HH; apply HH."; + pp " rewrite Hy; apply Zle_trans with (1 := Hl)."; + pp " rewrite (CyclicAxioms.spec_head00 Hw1 xx); auto with zarith."; + pp " rewrite <- (spec_zdigits Hw); auto with zarith."; + pp " rewrite <- (spec_zdigits Hw1); auto with zarith."; + pp " assert (F5: forall n m, (n <= m)%snat ->" "%"; + pp " Zpos (znz_digits (make_op n)) <= Zpos (znz_digits (make_op m)))."; + pp " intros n m HH; elim HH; clear m HH; auto with zarith."; + pp " intros m HH Hrec; apply Zle_trans with (1 := Hrec)."; + pp " rewrite make_op_S."; + pp " match goal with |- Zpos ?Y <= ?X => change X with (Zpos (xO Y)) end."; + pp " rewrite Zpos_xO."; + pp " assert (0 <= Zpos (znz_digits (make_op n))); auto with zarith."; + pp " assert (F6: forall n, Zpos (znz_digits w%i_op) <= Zpos (znz_digits (make_op n)))." size; + pp " intros n ; apply Zle_trans with (Zpos (znz_digits (make_op 0)))."; + pp " change (znz_digits (make_op 0)) with (xO (znz_digits w%i_op))." size; + pp " rewrite Zpos_xO."; + pp " assert (0 <= Zpos (znz_digits w%i_op)); auto with zarith." size; + pp " apply F5; auto with arith."; + pp " intros x; case x; clear x; unfold shiftl, same_level."; + for i = 0 to size do + pp " intros x y; case y; clear y."; + for j = 0 to i - 1 do + pp " intros y; unfold shiftl%i, head0." i; + pp " repeat rewrite spec_reduce_%i; repeat rewrite spec_reduce_%i; unfold to_Z; intros H1." i j; + pp " apply F4 with (3:=w%i_spec)(4:=w%i_spec)(5:=w%i_spec); auto with zarith." i j i; + pp " rewrite (spec_zdigits w%i_spec)." i; + pp " rewrite (spec_zdigits w%i_spec)." j; + pp " change (znz_digits w%i_op) with %s." i (genxO (i - j) (" (znz_digits w"^(string_of_int j)^"_op)")); + pp " repeat rewrite (fun x => Zpos_xO (xO x))."; + pp " repeat rewrite (fun x y => Zpos_xO (@znz_digits x y))."; + pp " assert (0 <= Zpos (znz_digits w%i_op)); auto with zarith." j; + pp " try (apply sym_equal; exact (spec_extend%in%i y))." j i; + done; + pp " intros y; unfold shiftl%i, head0." i; + pp " repeat rewrite spec_reduce_%i; unfold to_Z; intros H1." i; + pp " apply F4 with (3:=w%i_spec)(4:=w%i_spec)(5:=w%i_spec); auto with zarith." i i i; + for j = i + 1 to size do + pp " intros y; unfold shiftl%i, head0." j; + pp " repeat rewrite spec_reduce_%i; repeat rewrite spec_reduce_%i; unfold to_Z; intros H1." i j; + pp " apply F4 with (3:=w%i_spec)(4:=w%i_spec)(5:=w%i_spec); auto with zarith." j j i; + pp " try (apply sym_equal; exact (spec_extend%in%i x))." i j; + done; + if i == size then + begin + pp " intros m y; unfold shiftln, head0."; + pp " repeat rewrite spec_reduce_n; unfold to_Z; intros H1."; + pp " apply F4 with (3:=(wn_spec m))(4:=wn_spec m)(5:=w%i_spec); auto with zarith." size; + pp " try (apply sym_equal; exact (spec_extend%in m x))." size; + end + else + begin + pp " intros m y; unfold shiftln, head0."; + pp " repeat rewrite spec_reduce_n; unfold to_Z; intros H1."; + pp " apply F4 with (3:=(wn_spec m))(4:=wn_spec m)(5:=w%i_spec); auto with zarith." i; + pp " change ([Nn m (extend%i m (extend%i %i x))] = [N%i x])." size i (size - i - 1) i; + pp " rewrite <- (spec_extend%in m); rewrite <- spec_extend%in%i; auto." size i size; + end + done; + pp " intros n x y; case y; clear y;"; + pp " intros y; unfold shiftln, head0; try rewrite spec_reduce_n."; + for i = 0 to size do + pp " try rewrite spec_reduce_%i; unfold to_Z; intros H1." i; + pp " apply F4 with (3:=(wn_spec n))(4:=w%i_spec)(5:=wn_spec n); auto with zarith." i; + pp " rewrite (spec_zdigits w%i_spec)." i; + pp " rewrite (spec_zdigits (wn_spec n))."; + pp " apply Zle_trans with (2 := F6 n)."; + pp " change (znz_digits w%i_op) with %s." size (genxO (size - i) ("(znz_digits w" ^ (string_of_int i) ^ "_op)")); + pp " repeat rewrite (fun x => Zpos_xO (xO x))."; + pp " repeat rewrite (fun x y => Zpos_xO (@znz_digits x y))."; + pp " assert (H: 0 <= Zpos (znz_digits w%i_op)); auto with zarith." i; + if i == size then + pp " change ([Nn n (extend%i n y)] = [N%i y])." size i + else + pp " change ([Nn n (extend%i n (extend%i %i y))] = [N%i y])." size i (size - i - 1) i; + pp " rewrite <- (spec_extend%in n); auto." size; + if i <> size then + pp " try (rewrite <- spec_extend%in%i; auto)." i size; + done; + pp " generalize y; clear y; intros m y."; + pp " repeat rewrite spec_reduce_n; unfold to_Z; intros H1."; + pp " apply F4 with (3:=(wn_spec (Max.max n m)))(4:=wn_spec m)(5:=wn_spec n); auto with zarith."; + pp " rewrite (spec_zdigits (wn_spec m))."; + pp " rewrite (spec_zdigits (wn_spec (Max.max n m)))."; + pp " apply F5; auto with arith."; + pp " exact (spec_cast_r n m y)."; + pp " exact (spec_cast_l n m x)."; + pp " Qed."; + pr ""; + + (* Double size *) + pr " Definition double_size w := match w with"; + for i = 0 to size-1 do + pr " | %s%i x => %s%i (WW (znz_0 w%i_op) x)" c i c (i + 1) i; + done; + pr " | %s%i x => %sn 0 (WW (znz_0 w%i_op) x)" c size c size; + pr " | %sn n x => %sn (S n) (WW (znz_0 (make_op n)) x)" c c; + pr " end."; + pr ""; + + pr " Theorem spec_double_size_digits: "; + pr " forall x, digits (double_size x) = xO (digits x)."; + pa " Admitted."; + pp " Proof."; + pp " intros x; case x; unfold double_size, digits; clear x; auto."; + pp " intros n x; rewrite make_op_S; auto."; + pp " Qed."; + pr ""; + + + pr " Theorem spec_double_size: forall x, [double_size x] = [x]."; + pa " Admitted."; + pp " Proof."; + pp " intros x; case x; unfold double_size; clear x."; + for i = 0 to size do + pp " intros x; unfold to_Z, make_op; "; + pp " rewrite znz_to_Z_%i; rewrite (spec_0 w%i_spec); auto with zarith." (i + 1) i; + done; + pp " intros n x; unfold to_Z;"; + pp " generalize (znz_to_Z_n n); simpl word."; + pp " intros HH; rewrite HH; clear HH."; + pp " generalize (spec_0 (wn_spec n)); simpl word."; + pp " intros HH; rewrite HH; clear HH; auto with zarith."; + pp " Qed."; + pr ""; + + + pr " Theorem spec_double_size_head0: "; + pr " forall x, 2 * [head0 x] <= [head0 (double_size x)]."; + pa " Admitted."; + pp " Proof."; + pp " intros x."; + pp " assert (F1:= spec_pos (head0 x))."; + pp " assert (F2: 0 < Zpos (digits x))."; + pp " red; auto."; + pp " case (Zle_lt_or_eq _ _ (spec_pos x)); intros HH."; + pp " generalize HH; rewrite <- (spec_double_size x); intros HH1."; + pp " case (spec_head0 x HH); intros _ HH2."; + pp " case (spec_head0 _ HH1)."; + pp " rewrite (spec_double_size x); rewrite (spec_double_size_digits x)."; + pp " intros HH3 _."; + pp " case (Zle_or_lt ([head0 (double_size x)]) (2 * [head0 x])); auto; intros HH4."; + pp " absurd (2 ^ (2 * [head0 x] )* [x] < 2 ^ [head0 (double_size x)] * [x]); auto."; + pp " apply Zle_not_lt."; + pp " apply Zmult_le_compat_r; auto with zarith."; + pp " apply Zpower_le_monotone; auto; auto with zarith."; + pp " generalize (spec_pos (head0 (double_size x))); auto with zarith."; + pp " assert (HH5: 2 ^[head0 x] <= 2 ^(Zpos (digits x) - 1))."; + pp " case (Zle_lt_or_eq 1 [x]); auto with zarith; intros HH5."; + pp " apply Zmult_le_reg_r with (2 ^ 1); auto with zarith."; + pp " rewrite <- (fun x y z => Zpower_exp x (y - z)); auto with zarith."; + pp " assert (tmp: forall x, x - 1 + 1 = x); [intros; ring | rewrite tmp; clear tmp]."; + pp " apply Zle_trans with (2 := Zlt_le_weak _ _ HH2)."; + pp " apply Zmult_le_compat_l; auto with zarith."; + pp " rewrite Zpower_1_r; auto with zarith."; + pp " apply Zpower_le_monotone; auto with zarith."; + pp " split; auto with zarith. "; + pp " case (Zle_or_lt (Zpos (digits x)) [head0 x]); auto with zarith; intros HH6."; + pp " absurd (2 ^ Zpos (digits x) <= 2 ^ [head0 x] * [x]); auto with zarith."; + pp " rewrite <- HH5; rewrite Zmult_1_r."; + pp " apply Zpower_le_monotone; auto with zarith."; + pp " rewrite (Zmult_comm 2)."; + pp " rewrite Zpower_mult; auto with zarith."; + pp " rewrite Zpower_2."; + pp " apply Zlt_le_trans with (2 := HH3)."; + pp " rewrite <- Zmult_assoc."; + pp " replace (Zpos (xO (digits x)) - 1) with"; + pp " ((Zpos (digits x) - 1) + (Zpos (digits x)))."; + pp " rewrite Zpower_exp; auto with zarith."; + pp " apply Zmult_lt_compat2; auto with zarith."; + pp " split; auto with zarith."; + pp " apply Zmult_lt_0_compat; auto with zarith."; + pp " rewrite Zpos_xO; ring."; + pp " apply Zlt_le_weak; auto."; + pp " repeat rewrite spec_head00; auto."; + pp " rewrite spec_double_size_digits."; + pp " rewrite Zpos_xO; auto with zarith."; + pp " rewrite spec_double_size; auto."; + pp " Qed."; + pr ""; + + pr " Theorem spec_double_size_head0_pos: "; + pr " forall x, 0 < [head0 (double_size x)]."; + pa " Admitted."; + pp " Proof."; + pp " intros x."; + pp " assert (F: 0 < Zpos (digits x))."; + pp " red; auto."; + pp " case (Zle_lt_or_eq _ _ (spec_pos (head0 (double_size x)))); auto; intros F0."; + pp " case (Zle_lt_or_eq _ _ (spec_pos (head0 x))); intros F1."; + pp " apply Zlt_le_trans with (2 := (spec_double_size_head0 x)); auto with zarith."; + pp " case (Zle_lt_or_eq _ _ (spec_pos x)); intros F3."; + pp " generalize F3; rewrite <- (spec_double_size x); intros F4."; + pp " absurd (2 ^ (Zpos (xO (digits x)) - 1) < 2 ^ (Zpos (digits x)))."; + pp " apply Zle_not_lt."; + pp " apply Zpower_le_monotone; auto with zarith."; + pp " split; auto with zarith."; + pp " rewrite Zpos_xO; auto with zarith."; + pp " case (spec_head0 x F3)."; + pp " rewrite <- F1; rewrite Zpower_0_r; rewrite Zmult_1_l; intros _ HH."; + pp " apply Zle_lt_trans with (2 := HH)."; + pp " case (spec_head0 _ F4)."; + pp " rewrite (spec_double_size x); rewrite (spec_double_size_digits x)."; + pp " rewrite <- F0; rewrite Zpower_0_r; rewrite Zmult_1_l; auto."; + pp " generalize F1; rewrite (spec_head00 _ (sym_equal F3)); auto with zarith."; + pp " Qed."; + pr ""; + + + (* Safe shiftl *) + + pr " Definition safe_shiftl_aux_body cont n x :="; + pr " match compare n (head0 x) with"; + pr " Gt => cont n (double_size x)"; + pr " | _ => shiftl n x"; + pr " end."; + pr ""; + + pr " Theorem spec_safe_shift_aux_body: forall n p x cont,"; + pr " 2^ Zpos p <= [head0 x] ->"; + pr " (forall x, 2 ^ (Zpos p + 1) <= [head0 x]->"; + pr " [cont n x] = [x] * 2 ^ [n]) ->"; + pr " [safe_shiftl_aux_body cont n x] = [x] * 2 ^ [n]."; + pa " Admitted."; + pp " Proof."; + pp " intros n p x cont H1 H2; unfold safe_shiftl_aux_body."; + pp " generalize (spec_compare n (head0 x)); case compare; intros H."; + pp " apply spec_shiftl; auto with zarith."; + pp " apply spec_shiftl; auto with zarith."; + pp " rewrite H2."; + pp " rewrite spec_double_size; auto."; + pp " rewrite Zplus_comm; rewrite Zpower_exp; auto with zarith."; + pp " apply Zle_trans with (2 := spec_double_size_head0 x)."; + pp " rewrite Zpower_1_r; apply Zmult_le_compat_l; auto with zarith."; + pp " Qed."; + pr ""; + + pr " Fixpoint safe_shiftl_aux p cont n x {struct p} :="; + pr " safe_shiftl_aux_body "; + pr " (fun n x => match p with"; + pr " | xH => cont n x"; + pr " | xO p => safe_shiftl_aux p (safe_shiftl_aux p cont) n x"; + pr " | xI p => safe_shiftl_aux p (safe_shiftl_aux p cont) n x"; + pr " end) n x."; + pr ""; + + pr " Theorem spec_safe_shift_aux: forall p q n x cont,"; + pr " 2 ^ (Zpos q) <= [head0 x] ->"; + pr " (forall x, 2 ^ (Zpos p + Zpos q) <= [head0 x] ->"; + pr " [cont n x] = [x] * 2 ^ [n]) -> "; + pr " [safe_shiftl_aux p cont n x] = [x] * 2 ^ [n]."; + pa " Admitted."; + pp " Proof."; + pp " intros p; elim p; unfold safe_shiftl_aux; fold safe_shiftl_aux; clear p."; + pp " intros p Hrec q n x cont H1 H2."; + pp " apply spec_safe_shift_aux_body with (q); auto."; + pp " intros x1 H3; apply Hrec with (q + 1)%spositive; auto." "%"; + pp " intros x2 H4; apply Hrec with (p + q + 1)%spositive; auto." "%"; + pp " rewrite <- Pplus_assoc."; + pp " rewrite Zpos_plus_distr; auto."; + pp " intros x3 H5; apply H2."; + pp " rewrite Zpos_xI."; + pp " replace (2 * Zpos p + 1 + Zpos q) with (Zpos p + Zpos (p + q + 1));"; + pp " auto."; + pp " repeat rewrite Zpos_plus_distr; ring."; + pp " intros p Hrec q n x cont H1 H2."; + pp " apply spec_safe_shift_aux_body with (q); auto."; + pp " intros x1 H3; apply Hrec with (q); auto."; + pp " apply Zle_trans with (2 := H3); auto with zarith."; + pp " apply Zpower_le_monotone; auto with zarith."; + pp " intros x2 H4; apply Hrec with (p + q)%spositive; auto." "%"; + pp " intros x3 H5; apply H2."; + pp " rewrite (Zpos_xO p)."; + pp " replace (2 * Zpos p + Zpos q) with (Zpos p + Zpos (p + q));"; + pp " auto."; + pp " repeat rewrite Zpos_plus_distr; ring."; + pp " intros q n x cont H1 H2."; + pp " apply spec_safe_shift_aux_body with (q); auto."; + pp " rewrite Zplus_comm; auto."; + pp " Qed."; + pr ""; + + + pr " Definition safe_shiftl n x :="; + pr " safe_shiftl_aux_body"; + pr " (safe_shiftl_aux_body"; + pr " (safe_shiftl_aux (digits n) shiftl)) n x."; + pr ""; + + pr " Theorem spec_safe_shift: forall n x,"; + pr " [safe_shiftl n x] = [x] * 2 ^ [n]."; + pa " Admitted."; + pp " Proof."; + pp " intros n x; unfold safe_shiftl, safe_shiftl_aux_body."; + pp " generalize (spec_compare n (head0 x)); case compare; intros H."; + pp " apply spec_shiftl; auto with zarith."; + pp " apply spec_shiftl; auto with zarith."; + pp " rewrite <- (spec_double_size x)."; + pp " generalize (spec_compare n (head0 (double_size x))); case compare; intros H1."; + pp " apply spec_shiftl; auto with zarith."; + pp " apply spec_shiftl; auto with zarith."; + pp " rewrite <- (spec_double_size (double_size x))."; + pp " apply spec_safe_shift_aux with 1%spositive." "%"; + pp " apply Zle_trans with (2 := spec_double_size_head0 (double_size x))."; + pp " replace (2 ^ 1) with (2 * 1)."; + pp " apply Zmult_le_compat_l; auto with zarith."; + pp " generalize (spec_double_size_head0_pos x); auto with zarith."; + pp " rewrite Zpower_1_r; ring."; + pp " intros x1 H2; apply spec_shiftl."; + pp " apply Zle_trans with (2 := H2)."; + pp " apply Zle_trans with (2 ^ Zpos (digits n)); auto with zarith."; + pp " case (spec_digits n); auto with zarith."; + pp " apply Zpower_le_monotone; auto with zarith."; + pp " Qed."; + pr ""; + + (* even *) + pr " Definition is_even x :="; + pr " match x with"; + for i = 0 to size do + pr " | %s%i wx => w%i_op.(znz_is_even) wx" c i i + done; + pr " | %sn n wx => (make_op n).(znz_is_even) wx" c; + pr " end."; + pr ""; + + + pr " Theorem spec_is_even: forall x,"; + pr " if is_even x then [x] mod 2 = 0 else [x] mod 2 = 1."; + pa " Admitted."; + pp " Proof."; + pp " intros x; case x; unfold is_even, to_Z; clear x."; + for i = 0 to size do + pp " intros x; exact (spec_is_even w%i_spec x)." i; + done; + pp " intros n x; exact (spec_is_even (wn_spec n) x)."; + pp " Qed."; + pr ""; + + pr " Theorem spec_0: [zero] = 0."; + pa " Admitted."; + pp " Proof."; + pp " exact (spec_0 w0_spec)."; + pp " Qed."; + pr ""; + + pr " Theorem spec_1: [one] = 1."; + pa " Admitted."; + pp " Proof."; + pp " exact (spec_1 w0_spec)."; + pp " Qed."; + pr ""; + + pr "End Make."; + pr ""; + diff --git a/theories/Numbers/Natural/BigN/Nbasic.v b/theories/Numbers/Natural/BigN/Nbasic.v new file mode 100644 index 00000000..ae2cfd30 --- /dev/null +++ b/theories/Numbers/Natural/BigN/Nbasic.v @@ -0,0 +1,514 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: Nbasic.v 10964 2008-05-22 11:08:13Z letouzey $ i*) + +Require Import ZArith. +Require Import BigNumPrelude. +Require Import Max. +Require Import DoubleType. +Require Import DoubleBase. +Require Import CyclicAxioms. +Require Import DoubleCyclic. + +(* To compute the necessary height *) + +Fixpoint plength (p: positive) : positive := + match p with + xH => xH + | xO p1 => Psucc (plength p1) + | xI p1 => Psucc (plength p1) + end. + +Theorem plength_correct: forall p, (Zpos p < 2 ^ Zpos (plength p))%Z. +assert (F: (forall p, 2 ^ (Zpos (Psucc p)) = 2 * 2 ^ Zpos p)%Z). +intros p; replace (Zpos (Psucc p)) with (1 + Zpos p)%Z. +rewrite Zpower_exp; auto with zarith. +rewrite Zpos_succ_morphism; unfold Zsucc; auto with zarith. +intros p; elim p; simpl plength; auto. +intros p1 Hp1; rewrite F; repeat rewrite Zpos_xI. +assert (tmp: (forall p, 2 * p = p + p)%Z); + try repeat rewrite tmp; auto with zarith. +intros p1 Hp1; rewrite F; rewrite (Zpos_xO p1). +assert (tmp: (forall p, 2 * p = p + p)%Z); + try repeat rewrite tmp; auto with zarith. +rewrite Zpower_1_r; auto with zarith. +Qed. + +Theorem plength_pred_correct: forall p, (Zpos p <= 2 ^ Zpos (plength (Ppred p)))%Z. +intros p; case (Psucc_pred p); intros H1. +subst; simpl plength. +rewrite Zpower_1_r; auto with zarith. +pattern p at 1; rewrite <- H1. +rewrite Zpos_succ_morphism; unfold Zsucc; auto with zarith. +generalize (plength_correct (Ppred p)); auto with zarith. +Qed. + +Definition Pdiv p q := + match Zdiv (Zpos p) (Zpos q) with + Zpos q1 => match (Zpos p) - (Zpos q) * (Zpos q1) with + Z0 => q1 + | _ => (Psucc q1) + end + | _ => xH + end. + +Theorem Pdiv_le: forall p q, + Zpos p <= Zpos q * Zpos (Pdiv p q). +intros p q. +unfold Pdiv. +assert (H1: Zpos q > 0); auto with zarith. +assert (H1b: Zpos p >= 0); auto with zarith. +generalize (Z_div_ge0 (Zpos p) (Zpos q) H1 H1b). +generalize (Z_div_mod_eq (Zpos p) (Zpos q) H1); case Zdiv. + intros HH _; rewrite HH; rewrite Zmult_0_r; rewrite Zmult_1_r; simpl. +case (Z_mod_lt (Zpos p) (Zpos q) H1); auto with zarith. +intros q1 H2. +replace (Zpos p - Zpos q * Zpos q1) with (Zpos p mod Zpos q). + 2: pattern (Zpos p) at 2; rewrite H2; auto with zarith. +generalize H2 (Z_mod_lt (Zpos p) (Zpos q) H1); clear H2; + case Zmod. + intros HH _; rewrite HH; auto with zarith. + intros r1 HH (_,HH1); rewrite HH; rewrite Zpos_succ_morphism. + unfold Zsucc; rewrite Zmult_plus_distr_r; auto with zarith. + intros r1 _ (HH,_); case HH; auto. +intros q1 HH; rewrite HH. +unfold Zge; simpl Zcompare; intros HH1; case HH1; auto. +Qed. + +Definition is_one p := match p with xH => true | _ => false end. + +Theorem is_one_one: forall p, is_one p = true -> p = xH. +intros p; case p; auto; intros p1 H1; discriminate H1. +Qed. + +Definition get_height digits p := + let r := Pdiv p digits in + if is_one r then xH else Psucc (plength (Ppred r)). + +Theorem get_height_correct: + forall digits N, + Zpos N <= Zpos digits * (2 ^ (Zpos (get_height digits N) -1)). +intros digits N. +unfold get_height. +assert (H1 := Pdiv_le N digits). +case_eq (is_one (Pdiv N digits)); intros H2. +rewrite (is_one_one _ H2) in H1. +rewrite Zmult_1_r in H1. +change (2^(1-1))%Z with 1; rewrite Zmult_1_r; auto. +clear H2. +apply Zle_trans with (1 := H1). +apply Zmult_le_compat_l; auto with zarith. +rewrite Zpos_succ_morphism; unfold Zsucc. +rewrite Zplus_comm; rewrite Zminus_plus. +apply plength_pred_correct. +Qed. + +Definition zn2z_word_comm : forall w n, zn2z (word w n) = word (zn2z w) n. + fix zn2z_word_comm 2. + intros w n; case n. + reflexivity. + intros n0;simpl. + case (zn2z_word_comm w n0). + reflexivity. +Defined. + +Fixpoint extend (n:nat) {struct n} : forall w:Type, zn2z w -> word w (S n) := + match n return forall w:Type, zn2z w -> word w (S n) with + | O => fun w x => x + | S m => + let aux := extend m in + fun w x => WW W0 (aux w x) + end. + +Section ExtendMax. + +Open Scope nat_scope. + +Fixpoint plusnS (n m: nat) {struct n} : (n + S m = S (n + m))%nat := + match n return (n + S m = S (n + m))%nat with + | 0 => refl_equal (S m) + | S n1 => + let v := S (S n1 + m) in + eq_ind_r (fun n => S n = v) (refl_equal v) (plusnS n1 m) + end. + +Fixpoint plusn0 n : n + 0 = n := + match n return (n + 0 = n) with + | 0 => refl_equal 0 + | S n1 => + let v := S n1 in + eq_ind_r (fun n : nat => S n = v) (refl_equal v) (plusn0 n1) + end. + + Fixpoint diff (m n: nat) {struct m}: nat * nat := + match m, n with + O, n => (O, n) + | m, O => (m, O) + | S m1, S n1 => diff m1 n1 + end. + +Fixpoint diff_l (m n : nat) {struct m} : fst (diff m n) + n = max m n := + match m return fst (diff m n) + n = max m n with + | 0 => + match n return (n = max 0 n) with + | 0 => refl_equal _ + | S n0 => refl_equal _ + end + | S m1 => + match n return (fst (diff (S m1) n) + n = max (S m1) n) + with + | 0 => plusn0 _ + | S n1 => + let v := fst (diff m1 n1) + n1 in + let v1 := fst (diff m1 n1) + S n1 in + eq_ind v (fun n => v1 = S n) + (eq_ind v1 (fun n => v1 = n) (refl_equal v1) (S v) (plusnS _ _)) + _ (diff_l _ _) + end + end. + +Fixpoint diff_r (m n: nat) {struct m}: snd (diff m n) + m = max m n := + match m return (snd (diff m n) + m = max m n) with + | 0 => + match n return (snd (diff 0 n) + 0 = max 0 n) with + | 0 => refl_equal _ + | S _ => plusn0 _ + end + | S m => + match n return (snd (diff (S m) n) + S m = max (S m) n) with + | 0 => refl_equal (snd (diff (S m) 0) + S m) + | S n1 => + let v := S (max m n1) in + eq_ind_r (fun n => n = v) + (eq_ind_r (fun n => S n = v) + (refl_equal v) (diff_r _ _)) (plusnS _ _) + end + end. + + Variable w: Type. + + Definition castm (m n: nat) (H: m = n) (x: word w (S m)): + (word w (S n)) := + match H in (_ = y) return (word w (S y)) with + | refl_equal => x + end. + +Variable m: nat. +Variable v: (word w (S m)). + +Fixpoint extend_tr (n : nat) {struct n}: (word w (S (n + m))) := + match n return (word w (S (n + m))) with + | O => v + | S n1 => WW W0 (extend_tr n1) + end. + +End ExtendMax. + +Implicit Arguments extend_tr[w m]. +Implicit Arguments castm[w m n]. + + + +Section Reduce. + + Variable w : Type. + Variable nT : Type. + Variable N0 : nT. + Variable eq0 : w -> bool. + Variable reduce_n : w -> nT. + Variable zn2z_to_Nt : zn2z w -> nT. + + Definition reduce_n1 (x:zn2z w) := + match x with + | W0 => N0 + | WW xh xl => + if eq0 xh then reduce_n xl + else zn2z_to_Nt x + end. + +End Reduce. + +Section ReduceRec. + + Variable w : Type. + Variable nT : Type. + Variable N0 : nT. + Variable reduce_1n : zn2z w -> nT. + Variable c : forall n, word w (S n) -> nT. + + Fixpoint reduce_n (n:nat) : word w (S n) -> nT := + match n return word w (S n) -> nT with + | O => reduce_1n + | S m => fun x => + match x with + | W0 => N0 + | WW xh xl => + match xh with + | W0 => @reduce_n m xl + | _ => @c (S m) x + end + end + end. + +End ReduceRec. + +Definition opp_compare cmp := + match cmp with + | Lt => Gt + | Eq => Eq + | Gt => Lt + end. + +Section CompareRec. + + Variable wm w : Type. + Variable w_0 : w. + Variable compare : w -> w -> comparison. + Variable compare0_m : wm -> comparison. + Variable compare_m : wm -> w -> comparison. + + Fixpoint compare0_mn (n:nat) : word wm n -> comparison := + match n return word wm n -> comparison with + | O => compare0_m + | S m => fun x => + match x with + | W0 => Eq + | WW xh xl => + match compare0_mn m xh with + | Eq => compare0_mn m xl + | r => Lt + end + end + end. + + Variable wm_base: positive. + Variable wm_to_Z: wm -> Z. + Variable w_to_Z: w -> Z. + Variable w_to_Z_0: w_to_Z w_0 = 0. + Variable spec_compare0_m: forall x, + match compare0_m x with + Eq => w_to_Z w_0 = wm_to_Z x + | Lt => w_to_Z w_0 < wm_to_Z x + | Gt => w_to_Z w_0 > wm_to_Z x + end. + Variable wm_to_Z_pos: forall x, 0 <= wm_to_Z x < base wm_base. + + Let double_to_Z := double_to_Z wm_base wm_to_Z. + Let double_wB := double_wB wm_base. + + Lemma base_xO: forall n, base (xO n) = (base n)^2. + Proof. + intros n1; unfold base. + rewrite (Zpos_xO n1); rewrite Zmult_comm; rewrite Zpower_mult; auto with zarith. + Qed. + + Let double_to_Z_pos: forall n x, 0 <= double_to_Z n x < double_wB n := + (spec_double_to_Z wm_base wm_to_Z wm_to_Z_pos). + + + Lemma spec_compare0_mn: forall n x, + match compare0_mn n x with + Eq => 0 = double_to_Z n x + | Lt => 0 < double_to_Z n x + | Gt => 0 > double_to_Z n x + end. + Proof. + intros n; elim n; clear n; auto. + intros x; generalize (spec_compare0_m x); rewrite w_to_Z_0; auto. + intros n Hrec x; case x; unfold compare0_mn; fold compare0_mn; auto. + intros xh xl. + generalize (Hrec xh); case compare0_mn; auto. + generalize (Hrec xl); case compare0_mn; auto. + simpl double_to_Z; intros H1 H2; rewrite H1; rewrite <- H2; auto. + simpl double_to_Z; intros H1 H2; rewrite <- H2; auto. + case (double_to_Z_pos n xl); auto with zarith. + intros H1; simpl double_to_Z. + set (u := DoubleBase.double_wB wm_base n). + case (double_to_Z_pos n xl); intros H2 H3. + assert (0 < u); auto with zarith. + unfold u, DoubleBase.double_wB, base; auto with zarith. + change 0 with (0 + 0); apply Zplus_lt_le_compat; auto with zarith. + apply Zmult_lt_0_compat; auto with zarith. + case (double_to_Z_pos n xh); auto with zarith. + Qed. + + Fixpoint compare_mn_1 (n:nat) : word wm n -> w -> comparison := + match n return word wm n -> w -> comparison with + | O => compare_m + | S m => fun x y => + match x with + | W0 => compare w_0 y + | WW xh xl => + match compare0_mn m xh with + | Eq => compare_mn_1 m xl y + | r => Gt + end + end + end. + + Variable spec_compare: forall x y, + match compare x y with + Eq => w_to_Z x = w_to_Z y + | Lt => w_to_Z x < w_to_Z y + | Gt => w_to_Z x > w_to_Z y + end. + Variable spec_compare_m: forall x y, + match compare_m x y with + Eq => wm_to_Z x = w_to_Z y + | Lt => wm_to_Z x < w_to_Z y + | Gt => wm_to_Z x > w_to_Z y + end. + Variable wm_base_lt: forall x, + 0 <= w_to_Z x < base (wm_base). + + Let double_wB_lt: forall n x, + 0 <= w_to_Z x < (double_wB n). + Proof. + intros n x; elim n; simpl; auto; clear n. + intros n (H0, H); split; auto. + apply Zlt_le_trans with (1:= H). + unfold double_wB, DoubleBase.double_wB; simpl. + rewrite base_xO. + set (u := base (double_digits wm_base n)). + assert (0 < u). + unfold u, base; auto with zarith. + replace (u^2) with (u * u); simpl; auto with zarith. + apply Zle_trans with (1 * u); auto with zarith. + unfold Zpower_pos; simpl; ring. + Qed. + + + Lemma spec_compare_mn_1: forall n x y, + match compare_mn_1 n x y with + Eq => double_to_Z n x = w_to_Z y + | Lt => double_to_Z n x < w_to_Z y + | Gt => double_to_Z n x > w_to_Z y + end. + Proof. + intros n; elim n; simpl; auto; clear n. + intros n Hrec x; case x; clear x; auto. + intros y; generalize (spec_compare w_0 y); rewrite w_to_Z_0; case compare; auto. + intros xh xl y; simpl; generalize (spec_compare0_mn n xh); case compare0_mn; intros H1b. + rewrite <- H1b; rewrite Zmult_0_l; rewrite Zplus_0_l; auto. + apply Hrec. + apply Zlt_gt. + case (double_wB_lt n y); intros _ H0. + apply Zlt_le_trans with (1:= H0). + fold double_wB. + case (double_to_Z_pos n xl); intros H1 H2. + apply Zle_trans with (double_to_Z n xh * double_wB n); auto with zarith. + apply Zle_trans with (1 * double_wB n); auto with zarith. + case (double_to_Z_pos n xh); auto with zarith. + Qed. + +End CompareRec. + + +Section AddS. + + Variable w wm : Type. + Variable incr : wm -> carry wm. + Variable addr : w -> wm -> carry wm. + Variable injr : w -> zn2z wm. + + Variable w_0 u: w. + Fixpoint injs (n:nat): word w (S n) := + match n return (word w (S n)) with + O => WW w_0 u + | S n1 => (WW W0 (injs n1)) + end. + + Definition adds x y := + match y with + W0 => C0 (injr x) + | WW hy ly => match addr x ly with + C0 z => C0 (WW hy z) + | C1 z => match incr hy with + C0 z1 => C0 (WW z1 z) + | C1 z1 => C1 (WW z1 z) + end + end + end. + +End AddS. + + + Lemma spec_opp: forall u x y, + match u with + | Eq => y = x + | Lt => y < x + | Gt => y > x + end -> + match opp_compare u with + | Eq => x = y + | Lt => x < y + | Gt => x > y + end. + Proof. + intros u x y; case u; simpl; auto with zarith. + Qed. + + Fixpoint length_pos x := + match x with xH => O | xO x1 => S (length_pos x1) | xI x1 => S (length_pos x1) end. + + Theorem length_pos_lt: forall x y, + (length_pos x < length_pos y)%nat -> Zpos x < Zpos y. + Proof. + intros x; elim x; clear x; [intros x1 Hrec | intros x1 Hrec | idtac]; + intros y; case y; clear y; intros y1 H || intros H; simpl length_pos; + try (rewrite (Zpos_xI x1) || rewrite (Zpos_xO x1)); + try (rewrite (Zpos_xI y1) || rewrite (Zpos_xO y1)); + try (inversion H; fail); + try (assert (Zpos x1 < Zpos y1); [apply Hrec; apply lt_S_n | idtac]; auto with zarith); + assert (0 < Zpos y1); auto with zarith; red; auto. + Qed. + + Theorem cancel_app: forall A B (f g: A -> B) x, f = g -> f x = g x. + Proof. + intros A B f g x H; rewrite H; auto. + Qed. + + + Section SimplOp. + + Variable w: Type. + + Theorem digits_zop: forall w (x: znz_op w), + znz_digits (mk_zn2z_op x) = xO (znz_digits x). + intros ww x; auto. + Qed. + + Theorem digits_kzop: forall w (x: znz_op w), + znz_digits (mk_zn2z_op_karatsuba x) = xO (znz_digits x). + intros ww x; auto. + Qed. + + Theorem make_zop: forall w (x: znz_op w), + znz_to_Z (mk_zn2z_op x) = + fun z => match z with + W0 => 0 + | WW xh xl => znz_to_Z x xh * base (znz_digits x) + + znz_to_Z x xl + end. + intros ww x; auto. + Qed. + + Theorem make_kzop: forall w (x: znz_op w), + znz_to_Z (mk_zn2z_op_karatsuba x) = + fun z => match z with + W0 => 0 + | WW xh xl => znz_to_Z x xh * base (znz_digits x) + + znz_to_Z x xl + end. + intros ww x; auto. + Qed. + + End SimplOp. diff --git a/theories/Numbers/Natural/Binary/NBinDefs.v b/theories/Numbers/Natural/Binary/NBinDefs.v new file mode 100644 index 00000000..fc2bd2df --- /dev/null +++ b/theories/Numbers/Natural/Binary/NBinDefs.v @@ -0,0 +1,267 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NBinDefs.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Import BinPos. +Require Export BinNat. +Require Import NSub. + +Open Local Scope N_scope. + +(** Implementation of [NAxiomsSig] module type via [BinNat.N] *) + +Module NBinaryAxiomsMod <: NAxiomsSig. +Module Export NZOrdAxiomsMod <: NZOrdAxiomsSig. +Module Export NZAxiomsMod <: NZAxiomsSig. + +Definition NZ := N. +Definition NZeq := @eq N. +Definition NZ0 := N0. +Definition NZsucc := Nsucc. +Definition NZpred := Npred. +Definition NZadd := Nplus. +Definition NZsub := Nminus. +Definition NZmul := Nmult. + +Theorem NZeq_equiv : equiv N NZeq. +Proof (eq_equiv N). + +Add Relation N NZeq + reflexivity proved by (proj1 NZeq_equiv) + symmetry proved by (proj2 (proj2 NZeq_equiv)) + transitivity proved by (proj1 (proj2 NZeq_equiv)) +as NZeq_rel. + +Add Morphism NZsucc with signature NZeq ==> NZeq as NZsucc_wd. +Proof. +congruence. +Qed. + +Add Morphism NZpred with signature NZeq ==> NZeq as NZpred_wd. +Proof. +congruence. +Qed. + +Add Morphism NZadd with signature NZeq ==> NZeq ==> NZeq as NZadd_wd. +Proof. +congruence. +Qed. + +Add Morphism NZsub with signature NZeq ==> NZeq ==> NZeq as NZsub_wd. +Proof. +congruence. +Qed. + +Add Morphism NZmul with signature NZeq ==> NZeq ==> NZeq as NZmul_wd. +Proof. +congruence. +Qed. + +Theorem NZinduction : + forall A : NZ -> Prop, predicate_wd NZeq A -> + A N0 -> (forall n, A n <-> A (NZsucc n)) -> forall n : NZ, A n. +Proof. +intros A A_wd A0 AS. apply Nrect. assumption. intros; now apply -> AS. +Qed. + +Theorem NZpred_succ : forall n : NZ, NZpred (NZsucc n) = n. +Proof. +destruct n as [| p]; simpl. reflexivity. +case_eq (Psucc p); try (intros q H; rewrite <- H; now rewrite Ppred_succ). +intro H; false_hyp H Psucc_not_one. +Qed. + +Theorem NZadd_0_l : forall n : NZ, N0 + n = n. +Proof. +reflexivity. +Qed. + +Theorem NZadd_succ_l : forall n m : NZ, (NZsucc n) + m = NZsucc (n + m). +Proof. +destruct n; destruct m. +simpl in |- *; reflexivity. +unfold NZsucc, NZadd, Nsucc, Nplus. rewrite <- Pplus_one_succ_l; reflexivity. +simpl in |- *; reflexivity. +simpl in |- *; rewrite Pplus_succ_permute_l; reflexivity. +Qed. + +Theorem NZsub_0_r : forall n : NZ, n - N0 = n. +Proof. +now destruct n. +Qed. + +Theorem NZsub_succ_r : forall n m : NZ, n - (NZsucc m) = NZpred (n - m). +Proof. +destruct n as [| p]; destruct m as [| q]; try reflexivity. +now destruct p. +simpl. rewrite Pminus_mask_succ_r, Pminus_mask_carry_spec. +now destruct (Pminus_mask p q) as [| r |]; [| destruct r |]. +Qed. + +Theorem NZmul_0_l : forall n : NZ, N0 * n = N0. +Proof. +destruct n; reflexivity. +Qed. + +Theorem NZmul_succ_l : forall n m : NZ, (NZsucc n) * m = n * m + m. +Proof. +destruct n as [| n]; destruct m as [| m]; simpl; try reflexivity. +now rewrite Pmult_Sn_m, Pplus_comm. +Qed. + +End NZAxiomsMod. + +Definition NZlt := Nlt. +Definition NZle := Nle. +Definition NZmin := Nmin. +Definition NZmax := Nmax. + +Add Morphism NZlt with signature NZeq ==> NZeq ==> iff as NZlt_wd. +Proof. +unfold NZeq; intros x1 x2 H1 y1 y2 H2; rewrite H1; now rewrite H2. +Qed. + +Add Morphism NZle with signature NZeq ==> NZeq ==> iff as NZle_wd. +Proof. +unfold NZeq; intros x1 x2 H1 y1 y2 H2; rewrite H1; now rewrite H2. +Qed. + +Add Morphism NZmin with signature NZeq ==> NZeq ==> NZeq as NZmin_wd. +Proof. +congruence. +Qed. + +Add Morphism NZmax with signature NZeq ==> NZeq ==> NZeq as NZmax_wd. +Proof. +congruence. +Qed. + +Theorem NZlt_eq_cases : forall n m : N, n <= m <-> n < m \/ n = m. +Proof. +intros n m. unfold Nle, Nlt. rewrite <- Ncompare_eq_correct. +destruct (n ?= m); split; intro H1; (try discriminate); try (now left); try now right. +now elim H1. destruct H1; discriminate. +Qed. + +Theorem NZlt_irrefl : forall n : NZ, ~ n < n. +Proof. +intro n; unfold Nlt; now rewrite Ncompare_refl. +Qed. + +Theorem NZlt_succ_r : forall n m : NZ, n < (NZsucc m) <-> n <= m. +Proof. +intros n m; unfold Nlt, Nle; destruct n as [| p]; destruct m as [| q]; simpl; +split; intro H; try reflexivity; try discriminate. +destruct p; simpl; intros; discriminate. elimtype False; now apply H. +apply -> Pcompare_p_Sq in H. destruct H as [H | H]. +now rewrite H. now rewrite H, Pcompare_refl. +apply <- Pcompare_p_Sq. case_eq ((p ?= q)%positive Eq); intro H1. +right; now apply Pcompare_Eq_eq. now left. elimtype False; now apply H. +Qed. + +Theorem NZmin_l : forall n m : N, n <= m -> NZmin n m = n. +Proof. +unfold NZmin, Nmin, Nle; intros n m H. +destruct (n ?= m); try reflexivity. now elim H. +Qed. + +Theorem NZmin_r : forall n m : N, m <= n -> NZmin n m = m. +Proof. +unfold NZmin, Nmin, Nle; intros n m H. +case_eq (n ?= m); intro H1; try reflexivity. +now apply -> Ncompare_eq_correct. +rewrite <- Ncompare_antisym, H1 in H; elim H; auto. +Qed. + +Theorem NZmax_l : forall n m : N, m <= n -> NZmax n m = n. +Proof. +unfold NZmax, Nmax, Nle; intros n m H. +case_eq (n ?= m); intro H1; try reflexivity. +symmetry; now apply -> Ncompare_eq_correct. +rewrite <- Ncompare_antisym, H1 in H; elim H; auto. +Qed. + +Theorem NZmax_r : forall n m : N, n <= m -> NZmax n m = m. +Proof. +unfold NZmax, Nmax, Nle; intros n m H. +destruct (n ?= m); try reflexivity. now elim H. +Qed. + +End NZOrdAxiomsMod. + +Definition recursion (A : Type) (a : A) (f : N -> A -> A) (n : N) := + Nrect (fun _ => A) a f n. +Implicit Arguments recursion [A]. + +Theorem pred_0 : Npred N0 = N0. +Proof. +reflexivity. +Qed. + +Theorem recursion_wd : +forall (A : Type) (Aeq : relation A), + forall a a' : A, Aeq a a' -> + forall f f' : N -> A -> A, fun2_eq NZeq Aeq Aeq f f' -> + forall x x' : N, x = x' -> + Aeq (recursion a f x) (recursion a' f' x'). +Proof. +unfold fun2_wd, NZeq, fun2_eq. +intros A Aeq a a' Eaa' f f' Eff'. +intro x; pattern x; apply Nrect. +intros x' H; now rewrite <- H. +clear x. +intros x IH x' H; rewrite <- H. +unfold recursion in *. do 2 rewrite Nrect_step. +now apply Eff'; [| apply IH]. +Qed. + +Theorem recursion_0 : + forall (A : Type) (a : A) (f : N -> A -> A), recursion a f N0 = a. +Proof. +intros A a f; unfold recursion; now rewrite Nrect_base. +Qed. + +Theorem recursion_succ : + forall (A : Type) (Aeq : relation A) (a : A) (f : N -> A -> A), + Aeq a a -> fun2_wd NZeq Aeq Aeq f -> + forall n : N, Aeq (recursion a f (Nsucc n)) (f n (recursion a f n)). +Proof. +unfold NZeq, recursion, fun2_wd; intros A Aeq a f EAaa f_wd n; pattern n; apply Nrect. +rewrite Nrect_step; rewrite Nrect_base; now apply f_wd. +clear n; intro n; do 2 rewrite Nrect_step; intro IH. apply f_wd; [reflexivity|]. +now rewrite Nrect_step. +Qed. + +End NBinaryAxiomsMod. + +Module Export NBinarySubPropMod := NSubPropFunct NBinaryAxiomsMod. + +(* Some fun comparing the efficiency of the generic log defined +by strong (course-of-value) recursion and the log defined by recursion +on notation *) +(* Time Eval compute in (log 100000). *) (* 98 sec *) + +(* +Fixpoint binposlog (p : positive) : N := +match p with +| xH => 0 +| xO p' => Nsucc (binposlog p') +| xI p' => Nsucc (binposlog p') +end. + +Definition binlog (n : N) : N := +match n with +| 0 => 0 +| Npos p => binposlog p +end. +*) +(* Eval compute in (binlog 1000000000000000000). *) (* Works very fast *) + diff --git a/theories/IntMap/Allmaps.v b/theories/Numbers/Natural/Binary/NBinary.v index d5af8f80..2c99128d 100644 --- a/theories/IntMap/Allmaps.v +++ b/theories/Numbers/Natural/Binary/NBinary.v @@ -5,17 +5,11 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Allmaps.v 8733 2006-04-25 22:52:18Z letouzey $ i*) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NBinary.v 10934 2008-05-15 21:58:20Z letouzey $ i*) + +Require Export NBinDefs. +Require Export NArithRing. -Require Export Map. -Require Export Fset. -Require Export Mapaxioms. -Require Export Mapiter. -Require Export Mapsubset. -Require Export Lsort. -Require Export Mapfold. -Require Export Mapcard. -Require Export Mapcanon. -Require Export Mapc. -Require Export Maplists. -Require Export Adalloc.
\ No newline at end of file diff --git a/theories/Numbers/Natural/Peano/NPeano.v b/theories/Numbers/Natural/Peano/NPeano.v new file mode 100644 index 00000000..1c83da45 --- /dev/null +++ b/theories/Numbers/Natural/Peano/NPeano.v @@ -0,0 +1,220 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NPeano.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Import Arith. +Require Import Min. +Require Import Max. +Require Import NSub. + +Module NPeanoAxiomsMod <: NAxiomsSig. +Module Export NZOrdAxiomsMod <: NZOrdAxiomsSig. +Module Export NZAxiomsMod <: NZAxiomsSig. + +Definition NZ := nat. +Definition NZeq := (@eq nat). +Definition NZ0 := 0. +Definition NZsucc := S. +Definition NZpred := pred. +Definition NZadd := plus. +Definition NZsub := minus. +Definition NZmul := mult. + +Theorem NZeq_equiv : equiv nat NZeq. +Proof (eq_equiv nat). + +Add Relation nat NZeq + reflexivity proved by (proj1 NZeq_equiv) + symmetry proved by (proj2 (proj2 NZeq_equiv)) + transitivity proved by (proj1 (proj2 NZeq_equiv)) +as NZeq_rel. + +(* If we say "Add Relation nat (@eq nat)" instead of "Add Relation nat NZeq" +then the theorem generated for succ_wd below is forall x, succ x = succ x, +which does not match the axioms in NAxiomsSig *) + +Add Morphism NZsucc with signature NZeq ==> NZeq as NZsucc_wd. +Proof. +congruence. +Qed. + +Add Morphism NZpred with signature NZeq ==> NZeq as NZpred_wd. +Proof. +congruence. +Qed. + +Add Morphism NZadd with signature NZeq ==> NZeq ==> NZeq as NZadd_wd. +Proof. +congruence. +Qed. + +Add Morphism NZsub with signature NZeq ==> NZeq ==> NZeq as NZsub_wd. +Proof. +congruence. +Qed. + +Add Morphism NZmul with signature NZeq ==> NZeq ==> NZeq as NZmul_wd. +Proof. +congruence. +Qed. + +Theorem NZinduction : + forall A : nat -> Prop, predicate_wd (@eq nat) A -> + A 0 -> (forall n : nat, A n <-> A (S n)) -> forall n : nat, A n. +Proof. +intros A A_wd A0 AS. apply nat_ind. assumption. intros; now apply -> AS. +Qed. + +Theorem NZpred_succ : forall n : nat, pred (S n) = n. +Proof. +reflexivity. +Qed. + +Theorem NZadd_0_l : forall n : nat, 0 + n = n. +Proof. +reflexivity. +Qed. + +Theorem NZadd_succ_l : forall n m : nat, (S n) + m = S (n + m). +Proof. +reflexivity. +Qed. + +Theorem NZsub_0_r : forall n : nat, n - 0 = n. +Proof. +intro n; now destruct n. +Qed. + +Theorem NZsub_succ_r : forall n m : nat, n - (S m) = pred (n - m). +Proof. +intros n m; induction n m using nat_double_ind; simpl; auto. apply NZsub_0_r. +Qed. + +Theorem NZmul_0_l : forall n : nat, 0 * n = 0. +Proof. +reflexivity. +Qed. + +Theorem NZmul_succ_l : forall n m : nat, S n * m = n * m + m. +Proof. +intros n m; now rewrite plus_comm. +Qed. + +End NZAxiomsMod. + +Definition NZlt := lt. +Definition NZle := le. +Definition NZmin := min. +Definition NZmax := max. + +Add Morphism NZlt with signature NZeq ==> NZeq ==> iff as NZlt_wd. +Proof. +unfold NZeq; intros x1 x2 H1 y1 y2 H2; rewrite H1; now rewrite H2. +Qed. + +Add Morphism NZle with signature NZeq ==> NZeq ==> iff as NZle_wd. +Proof. +unfold NZeq; intros x1 x2 H1 y1 y2 H2; rewrite H1; now rewrite H2. +Qed. + +Add Morphism NZmin with signature NZeq ==> NZeq ==> NZeq as NZmin_wd. +Proof. +congruence. +Qed. + +Add Morphism NZmax with signature NZeq ==> NZeq ==> NZeq as NZmax_wd. +Proof. +congruence. +Qed. + +Theorem NZlt_eq_cases : forall n m : nat, n <= m <-> n < m \/ n = m. +Proof. +intros n m; split. +apply le_lt_or_eq. +intro H; destruct H as [H | H]. +now apply lt_le_weak. rewrite H; apply le_refl. +Qed. + +Theorem NZlt_irrefl : forall n : nat, ~ (n < n). +Proof. +exact lt_irrefl. +Qed. + +Theorem NZlt_succ_r : forall n m : nat, n < S m <-> n <= m. +Proof. +intros n m; split; [apply lt_n_Sm_le | apply le_lt_n_Sm]. +Qed. + +Theorem NZmin_l : forall n m : nat, n <= m -> NZmin n m = n. +Proof. +exact min_l. +Qed. + +Theorem NZmin_r : forall n m : nat, m <= n -> NZmin n m = m. +Proof. +exact min_r. +Qed. + +Theorem NZmax_l : forall n m : nat, m <= n -> NZmax n m = n. +Proof. +exact max_l. +Qed. + +Theorem NZmax_r : forall n m : nat, n <= m -> NZmax n m = m. +Proof. +exact max_r. +Qed. + +End NZOrdAxiomsMod. + +Definition recursion : forall A : Type, A -> (nat -> A -> A) -> nat -> A := + fun A : Type => nat_rect (fun _ => A). +Implicit Arguments recursion [A]. + +Theorem succ_neq_0 : forall n : nat, S n <> 0. +Proof. +intros; discriminate. +Qed. + +Theorem pred_0 : pred 0 = 0. +Proof. +reflexivity. +Qed. + +Theorem recursion_wd : forall (A : Type) (Aeq : relation A), + forall a a' : A, Aeq a a' -> + forall f f' : nat -> A -> A, fun2_eq (@eq nat) Aeq Aeq f f' -> + forall n n' : nat, n = n' -> + Aeq (recursion a f n) (recursion a' f' n'). +Proof. +unfold fun2_eq; induction n; intros n' Enn'; rewrite <- Enn' in *; simpl; auto. +Qed. + +Theorem recursion_0 : + forall (A : Type) (a : A) (f : nat -> A -> A), recursion a f 0 = a. +Proof. +reflexivity. +Qed. + +Theorem recursion_succ : + forall (A : Type) (Aeq : relation A) (a : A) (f : nat -> A -> A), + Aeq a a -> fun2_wd (@eq nat) Aeq Aeq f -> + forall n : nat, Aeq (recursion a f (S n)) (f n (recursion a f n)). +Proof. +induction n; simpl; auto. +Qed. + +End NPeanoAxiomsMod. + +(* Now we apply the largest property functor *) + +Module Export NPeanoSubPropMod := NSubPropFunct NPeanoAxiomsMod. + diff --git a/theories/Numbers/Natural/SpecViaZ/NSig.v b/theories/Numbers/Natural/SpecViaZ/NSig.v new file mode 100644 index 00000000..0275d1e1 --- /dev/null +++ b/theories/Numbers/Natural/SpecViaZ/NSig.v @@ -0,0 +1,115 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NSig.v 11027 2008-06-01 13:28:59Z letouzey $ i*) + +Require Import ZArith Znumtheory. + +Open Scope Z_scope. + +(** * NSig *) + +(** Interface of a rich structure about natural numbers. + Specifications are written via translation to Z. +*) + +Module Type NType. + + Parameter t : Type. + + Parameter to_Z : t -> Z. + Notation "[ x ]" := (to_Z x). + Parameter spec_pos: forall x, 0 <= [x]. + + Parameter of_N : N -> t. + Parameter spec_of_N: forall x, to_Z (of_N x) = Z_of_N x. + Definition to_N n := Zabs_N (to_Z n). + + Definition eq n m := ([n] = [m]). + + Parameter zero : t. + Parameter one : t. + + Parameter spec_0: [zero] = 0. + Parameter spec_1: [one] = 1. + + Parameter compare : t -> t -> comparison. + + Parameter spec_compare: forall x y, + match compare x y with + | Eq => [x] = [y] + | Lt => [x] < [y] + | Gt => [x] > [y] + end. + + Definition lt n m := compare n m = Lt. + Definition le n m := compare n m <> Gt. + Definition min n m := match compare n m with Gt => m | _ => n end. + Definition max n m := match compare n m with Lt => m | _ => n end. + + Parameter eq_bool : t -> t -> bool. + + Parameter spec_eq_bool: forall x y, + if eq_bool x y then [x] = [y] else [x] <> [y]. + + Parameter succ : t -> t. + + Parameter spec_succ: forall n, [succ n] = [n] + 1. + + Parameter add : t -> t -> t. + + Parameter spec_add: forall x y, [add x y] = [x] + [y]. + + Parameter pred : t -> t. + + Parameter spec_pred: forall x, 0 < [x] -> [pred x] = [x] - 1. + Parameter spec_pred0: forall x, [x] = 0 -> [pred x] = 0. + + Parameter sub : t -> t -> t. + + Parameter spec_sub: forall x y, [y] <= [x] -> [sub x y] = [x] - [y]. + Parameter spec_sub0: forall x y, [x] < [y]-> [sub x y] = 0. + + Parameter mul : t -> t -> t. + + Parameter spec_mul: forall x y, [mul x y] = [x] * [y]. + + Parameter square : t -> t. + + Parameter spec_square: forall x, [square x] = [x] * [x]. + + Parameter power_pos : t -> positive -> t. + + Parameter spec_power_pos: forall x n, [power_pos x n] = [x] ^ Zpos n. + + Parameter sqrt : t -> t. + + Parameter spec_sqrt: forall x, [sqrt x] ^ 2 <= [x] < ([sqrt x] + 1) ^ 2. + + Parameter div_eucl : t -> t -> t * t. + + Parameter spec_div_eucl: forall x y, + 0 < [y] -> + let (q,r) := div_eucl x y in ([q], [r]) = Zdiv_eucl [x] [y]. + + Parameter div : t -> t -> t. + + Parameter spec_div: forall x y, 0 < [y] -> [div x y] = [x] / [y]. + + Parameter modulo : t -> t -> t. + + Parameter spec_modulo: + forall x y, 0 < [y] -> [modulo x y] = [x] mod [y]. + + Parameter gcd : t -> t -> t. + + Parameter spec_gcd: forall a b, [gcd a b] = Zgcd (to_Z a) (to_Z b). + +End NType. diff --git a/theories/Numbers/Natural/SpecViaZ/NSigNAxioms.v b/theories/Numbers/Natural/SpecViaZ/NSigNAxioms.v new file mode 100644 index 00000000..fe068437 --- /dev/null +++ b/theories/Numbers/Natural/SpecViaZ/NSigNAxioms.v @@ -0,0 +1,356 @@ +(************************************************************************) +(* 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: NSigNAxioms.v 11040 2008-06-03 00:04:16Z letouzey $ i*) + +Require Import ZArith. +Require Import Nnat. +Require Import NAxioms. +Require Import NSig. + +(** * The interface [NSig.NType] implies the interface [NAxiomsSig] *) + +Module NSig_NAxioms (N:NType) <: NAxiomsSig. + +Delimit Scope IntScope with Int. +Bind Scope IntScope with N.t. +Open Local Scope IntScope. +Notation "[ x ]" := (N.to_Z x) : IntScope. +Infix "==" := N.eq (at level 70) : IntScope. +Notation "0" := N.zero : IntScope. +Infix "+" := N.add : IntScope. +Infix "-" := N.sub : IntScope. +Infix "*" := N.mul : IntScope. + +Module Export NZOrdAxiomsMod <: NZOrdAxiomsSig. +Module Export NZAxiomsMod <: NZAxiomsSig. + +Definition NZ := N.t. +Definition NZeq := N.eq. +Definition NZ0 := N.zero. +Definition NZsucc := N.succ. +Definition NZpred := N.pred. +Definition NZadd := N.add. +Definition NZsub := N.sub. +Definition NZmul := N.mul. + +Theorem NZeq_equiv : equiv N.t N.eq. +Proof. +repeat split; repeat red; intros; auto; congruence. +Qed. + +Add Relation N.t N.eq + reflexivity proved by (proj1 NZeq_equiv) + symmetry proved by (proj2 (proj2 NZeq_equiv)) + transitivity proved by (proj1 (proj2 NZeq_equiv)) + as NZeq_rel. + +Add Morphism NZsucc with signature N.eq ==> N.eq as NZsucc_wd. +Proof. +unfold N.eq; intros; rewrite 2 N.spec_succ; f_equal; auto. +Qed. + +Add Morphism NZpred with signature N.eq ==> N.eq as NZpred_wd. +Proof. +unfold N.eq; intros. +generalize (N.spec_pos y) (N.spec_pos x) (N.spec_eq_bool x 0). +destruct N.eq_bool; rewrite N.spec_0; intros. +rewrite 2 N.spec_pred0; congruence. +rewrite 2 N.spec_pred; f_equal; auto; try omega. +Qed. + +Add Morphism NZadd with signature N.eq ==> N.eq ==> N.eq as NZadd_wd. +Proof. +unfold N.eq; intros; rewrite 2 N.spec_add; f_equal; auto. +Qed. + +Add Morphism NZsub with signature N.eq ==> N.eq ==> N.eq as NZsub_wd. +Proof. +unfold N.eq; intros x x' Hx y y' Hy. +destruct (Z_lt_le_dec [x] [y]). +rewrite 2 N.spec_sub0; f_equal; congruence. +rewrite 2 N.spec_sub; f_equal; congruence. +Qed. + +Add Morphism NZmul with signature N.eq ==> N.eq ==> N.eq as NZmul_wd. +Proof. +unfold N.eq; intros; rewrite 2 N.spec_mul; f_equal; auto. +Qed. + +Theorem NZpred_succ : forall n, N.pred (N.succ n) == n. +Proof. +unfold N.eq; intros. +rewrite N.spec_pred; rewrite N.spec_succ. +omega. +generalize (N.spec_pos n); omega. +Qed. + +Definition N_of_Z z := N.of_N (Zabs_N z). + +Section Induction. + +Variable A : N.t -> Prop. +Hypothesis A_wd : predicate_wd N.eq A. +Hypothesis A0 : A 0. +Hypothesis AS : forall n, A n <-> A (N.succ n). + +Add Morphism A with signature N.eq ==> iff as A_morph. +Proof. apply A_wd. Qed. + +Let B (z : Z) := A (N_of_Z z). + +Lemma B0 : B 0. +Proof. +unfold B, N_of_Z; simpl. +rewrite <- (A_wd 0); auto. +red; rewrite N.spec_0, N.spec_of_N; auto. +Qed. + +Lemma BS : forall z : Z, (0 <= z)%Z -> B z -> B (z + 1). +Proof. +intros z H1 H2. +unfold B in *. apply -> AS in H2. +setoid_replace (N_of_Z (z + 1)) with (N.succ (N_of_Z z)); auto. +unfold N.eq. rewrite N.spec_succ. +unfold N_of_Z. +rewrite 2 N.spec_of_N, 2 Z_of_N_abs, 2 Zabs_eq; auto with zarith. +Qed. + +Lemma B_holds : forall z : Z, (0 <= z)%Z -> B z. +Proof. +exact (natlike_ind B B0 BS). +Qed. + +Theorem NZinduction : forall n, A n. +Proof. +intro n. setoid_replace n with (N_of_Z (N.to_Z n)). +apply B_holds. apply N.spec_pos. +red; unfold N_of_Z. +rewrite N.spec_of_N, Z_of_N_abs, Zabs_eq; auto. +apply N.spec_pos. +Qed. + +End Induction. + +Theorem NZadd_0_l : forall n, 0 + n == n. +Proof. +intros; red; rewrite N.spec_add, N.spec_0; auto with zarith. +Qed. + +Theorem NZadd_succ_l : forall n m, (N.succ n) + m == N.succ (n + m). +Proof. +intros; red; rewrite N.spec_add, 2 N.spec_succ, N.spec_add; auto with zarith. +Qed. + +Theorem NZsub_0_r : forall n, n - 0 == n. +Proof. +intros; red; rewrite N.spec_sub; rewrite N.spec_0; auto with zarith. +apply N.spec_pos. +Qed. + +Theorem NZsub_succ_r : forall n m, n - (N.succ m) == N.pred (n - m). +Proof. +intros; red. +destruct (Z_lt_le_dec [n] [N.succ m]) as [H|H]. +rewrite N.spec_sub0; auto. +rewrite N.spec_succ in H. +rewrite N.spec_pred0; auto. +destruct (Z_eq_dec [n] [m]). +rewrite N.spec_sub; auto with zarith. +rewrite N.spec_sub0; auto with zarith. + +rewrite N.spec_sub, N.spec_succ in *; auto. +rewrite N.spec_pred, N.spec_sub; auto with zarith. +rewrite N.spec_sub; auto with zarith. +Qed. + +Theorem NZmul_0_l : forall n, 0 * n == 0. +Proof. +intros; red. +rewrite N.spec_mul, N.spec_0; auto with zarith. +Qed. + +Theorem NZmul_succ_l : forall n m, (N.succ n) * m == n * m + m. +Proof. +intros; red. +rewrite N.spec_add, 2 N.spec_mul, N.spec_succ; ring. +Qed. + +End NZAxiomsMod. + +Definition NZlt := N.lt. +Definition NZle := N.le. +Definition NZmin := N.min. +Definition NZmax := N.max. + +Infix "<=" := N.le : IntScope. +Infix "<" := N.lt : IntScope. + +Lemma spec_compare_alt : forall x y, N.compare x y = ([x] ?= [y])%Z. +Proof. + intros; generalize (N.spec_compare x y). + destruct (N.compare x y); auto. + intros H; rewrite H; symmetry; apply Zcompare_refl. +Qed. + +Lemma spec_lt : forall x y, (x<y) <-> ([x]<[y])%Z. +Proof. + intros; unfold N.lt, Zlt; rewrite spec_compare_alt; intuition. +Qed. + +Lemma spec_le : forall x y, (x<=y) <-> ([x]<=[y])%Z. +Proof. + intros; unfold N.le, Zle; rewrite spec_compare_alt; intuition. +Qed. + +Lemma spec_min : forall x y, [N.min x y] = Zmin [x] [y]. +Proof. + intros; unfold N.min, Zmin. + rewrite spec_compare_alt; destruct Zcompare; auto. +Qed. + +Lemma spec_max : forall x y, [N.max x y] = Zmax [x] [y]. +Proof. + intros; unfold N.max, Zmax. + rewrite spec_compare_alt; destruct Zcompare; auto. +Qed. + +Add Morphism N.compare with signature N.eq ==> N.eq ==> (@eq comparison) as compare_wd. +Proof. +intros x x' Hx y y' Hy. +rewrite 2 spec_compare_alt; rewrite Hx, Hy; intuition. +Qed. + +Add Morphism N.lt with signature N.eq ==> N.eq ==> iff as NZlt_wd. +Proof. +intros x x' Hx y y' Hy; unfold N.lt; rewrite Hx, Hy; intuition. +Qed. + +Add Morphism N.le with signature N.eq ==> N.eq ==> iff as NZle_wd. +Proof. +intros x x' Hx y y' Hy; unfold N.le; rewrite Hx, Hy; intuition. +Qed. + +Add Morphism N.min with signature N.eq ==> N.eq ==> N.eq as NZmin_wd. +Proof. +intros; red; rewrite 2 spec_min; congruence. +Qed. + +Add Morphism N.max with signature N.eq ==> N.eq ==> N.eq as NZmax_wd. +Proof. +intros; red; rewrite 2 spec_max; congruence. +Qed. + +Theorem NZlt_eq_cases : forall n m, n <= m <-> n < m \/ n == m. +Proof. +intros. +unfold N.eq; rewrite spec_lt, spec_le; omega. +Qed. + +Theorem NZlt_irrefl : forall n, ~ n < n. +Proof. +intros; rewrite spec_lt; auto with zarith. +Qed. + +Theorem NZlt_succ_r : forall n m, n < (N.succ m) <-> n <= m. +Proof. +intros; rewrite spec_lt, spec_le, N.spec_succ; omega. +Qed. + +Theorem NZmin_l : forall n m, n <= m -> N.min n m == n. +Proof. +intros n m; unfold N.eq; rewrite spec_le, spec_min. +generalize (Zmin_spec [n] [m]); omega. +Qed. + +Theorem NZmin_r : forall n m, m <= n -> N.min n m == m. +Proof. +intros n m; unfold N.eq; rewrite spec_le, spec_min. +generalize (Zmin_spec [n] [m]); omega. +Qed. + +Theorem NZmax_l : forall n m, m <= n -> N.max n m == n. +Proof. +intros n m; unfold N.eq; rewrite spec_le, spec_max. +generalize (Zmax_spec [n] [m]); omega. +Qed. + +Theorem NZmax_r : forall n m, n <= m -> N.max n m == m. +Proof. +intros n m; unfold N.eq; rewrite spec_le, spec_max. +generalize (Zmax_spec [n] [m]); omega. +Qed. + +End NZOrdAxiomsMod. + +Theorem pred_0 : N.pred 0 == 0. +Proof. +red; rewrite N.spec_pred0; rewrite N.spec_0; auto. +Qed. + +Definition recursion (A : Type) (a : A) (f : N.t -> A -> A) (n : N.t) := + Nrect (fun _ => A) a (fun n a => f (N.of_N n) a) (N.to_N n). +Implicit Arguments recursion [A]. + +Theorem recursion_wd : +forall (A : Type) (Aeq : relation A), + forall a a' : A, Aeq a a' -> + forall f f' : N.t -> A -> A, fun2_eq N.eq Aeq Aeq f f' -> + forall x x' : N.t, x == x' -> + Aeq (recursion a f x) (recursion a' f' x'). +Proof. +unfold fun2_wd, N.eq, fun2_eq. +intros A Aeq a a' Eaa' f f' Eff' x x' Exx'. +unfold recursion. +unfold N.to_N. +rewrite <- Exx'; clear x' Exx'. +replace (Zabs_N [x]) with (N_of_nat (Zabs_nat [x])). +induction (Zabs_nat [x]). +simpl; auto. +rewrite N_of_S, 2 Nrect_step; auto. +destruct [x]; simpl; auto. +change (nat_of_P p) with (nat_of_N (Npos p)); apply N_of_nat_of_N. +change (nat_of_P p) with (nat_of_N (Npos p)); apply N_of_nat_of_N. +Qed. + +Theorem recursion_0 : + forall (A : Type) (a : A) (f : N.t -> A -> A), recursion a f 0 = a. +Proof. +intros A a f; unfold recursion, N.to_N; rewrite N.spec_0; simpl; auto. +Qed. + +Theorem recursion_succ : + forall (A : Type) (Aeq : relation A) (a : A) (f : N.t -> A -> A), + Aeq a a -> fun2_wd N.eq Aeq Aeq f -> + forall n, Aeq (recursion a f (N.succ n)) (f n (recursion a f n)). +Proof. +unfold N.eq, recursion, fun2_wd; intros A Aeq a f EAaa f_wd n. +replace (N.to_N (N.succ n)) with (Nsucc (N.to_N n)). +rewrite Nrect_step. +apply f_wd; auto. +unfold N.to_N. +rewrite N.spec_of_N, Z_of_N_abs, Zabs_eq; auto. + apply N.spec_pos. + +fold (recursion a f n). +apply recursion_wd; auto. +red; auto. +red; auto. +unfold N.to_N. + +rewrite N.spec_succ. +change ([n]+1)%Z with (Zsucc [n]). +apply Z_of_N_eq_rev. +rewrite Z_of_N_succ. +rewrite 2 Z_of_N_abs. +rewrite 2 Zabs_eq; auto. +generalize (N.spec_pos n); auto with zarith. +apply N.spec_pos; auto. +Qed. + +End NSig_NAxioms. diff --git a/theories/Numbers/NumPrelude.v b/theories/Numbers/NumPrelude.v new file mode 100644 index 00000000..fdccf214 --- /dev/null +++ b/theories/Numbers/NumPrelude.v @@ -0,0 +1,267 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Evgeny Makarov, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: NumPrelude.v 10943 2008-05-19 08:45:13Z letouzey $ i*) + +Require Export Setoid. + +Set Implicit Arguments. +(* +Contents: +- Coercion from bool to Prop +- Extension of the tactics stepl and stepr +- Extentional properties of predicates, relations and functions + (well-definedness and equality) +- Relations on cartesian product +- Miscellaneous +*) + +(** Coercion from bool to Prop *) + +(*Definition eq_bool := (@eq bool).*) + +(*Inductive eq_true : bool -> Prop := is_eq_true : eq_true true.*) +(* This has been added to theories/Datatypes.v *) +(*Coercion eq_true : bool >-> Sortclass.*) + +(*Theorem eq_true_unfold_pos : forall b : bool, b <-> b = true. +Proof. +intro b; split; intro H. now inversion H. now rewrite H. +Qed. + +Theorem eq_true_unfold_neg : forall b : bool, ~ b <-> b = false. +Proof. +intros b; destruct b; simpl; rewrite eq_true_unfold_pos. +split; intro H; [elim (H (refl_equal true)) | discriminate H]. +split; intro H; [reflexivity | discriminate]. +Qed. + +Theorem eq_true_or : forall b1 b2 : bool, b1 || b2 <-> b1 \/ b2. +Proof. +destruct b1; destruct b2; simpl; tauto. +Qed. + +Theorem eq_true_and : forall b1 b2 : bool, b1 && b2 <-> b1 /\ b2. +Proof. +destruct b1; destruct b2; simpl; tauto. +Qed. + +Theorem eq_true_neg : forall b : bool, negb b <-> ~ b. +Proof. +destruct b; simpl; rewrite eq_true_unfold_pos; rewrite eq_true_unfold_neg; +split; now intro. +Qed. + +Theorem eq_true_iff : forall b1 b2 : bool, b1 = b2 <-> (b1 <-> b2). +Proof. +intros b1 b2; split; intro H. +now rewrite H. +destruct b1; destruct b2; simpl; try reflexivity. +apply -> eq_true_unfold_neg. rewrite H. now intro. +symmetry; apply -> eq_true_unfold_neg. rewrite <- H; now intro. +Qed.*) + +(** Extension of the tactics stepl and stepr to make them +applicable to hypotheses *) + +Tactic Notation "stepl" constr(t1') "in" hyp(H) := +match (type of H) with +| ?R ?t1 ?t2 => + let H1 := fresh in + cut (R t1' t2); [clear H; intro H | stepl t1; [assumption |]] +| _ => fail 1 ": the hypothesis" H "does not have the form (R t1 t2)" +end. + +Tactic Notation "stepl" constr(t1') "in" hyp(H) "by" tactic(r) := stepl t1' in H; [| r]. + +Tactic Notation "stepr" constr(t2') "in" hyp(H) := +match (type of H) with +| ?R ?t1 ?t2 => + let H1 := fresh in + cut (R t1 t2'); [clear H; intro H | stepr t2; [assumption |]] +| _ => fail 1 ": the hypothesis" H "does not have the form (R t1 t2)" +end. + +Tactic Notation "stepr" constr(t2') "in" hyp(H) "by" tactic(r) := stepr t2' in H; [| r]. + +(** Extentional properties of predicates, relations and functions *) + +Definition predicate (A : Type) := A -> Prop. + +Section ExtensionalProperties. + +Variables A B C : Type. +Variable Aeq : relation A. +Variable Beq : relation B. +Variable Ceq : relation C. + +(* "wd" stands for "well-defined" *) + +Definition fun_wd (f : A -> B) := forall x y : A, Aeq x y -> Beq (f x) (f y). + +Definition fun2_wd (f : A -> B -> C) := + forall x x' : A, Aeq x x' -> forall y y' : B, Beq y y' -> Ceq (f x y) (f x' y'). + +Definition fun_eq : relation (A -> B) := + fun f f' => forall x x' : A, Aeq x x' -> Beq (f x) (f' x'). + +(* Note that reflexivity of fun_eq means that every function +is well-defined w.r.t. Aeq and Beq, i.e., +forall x x' : A, Aeq x x' -> Beq (f x) (f x') *) + +Definition fun2_eq (f f' : A -> B -> C) := + forall x x' : A, Aeq x x' -> forall y y' : B, Beq y y' -> Ceq (f x y) (f' x' y'). + +End ExtensionalProperties. + +(* The following definitions instantiate Beq or Ceq to iff; therefore, they +have to be outside the ExtensionalProperties section *) + +Definition predicate_wd (A : Type) (Aeq : relation A) := fun_wd Aeq iff. + +Definition relation_wd (A B : Type) (Aeq : relation A) (Beq : relation B) := + fun2_wd Aeq Beq iff. + +Definition relations_eq (A B : Type) (R1 R2 : A -> B -> Prop) := + forall (x : A) (y : B), R1 x y <-> R2 x y. + +Theorem relations_eq_equiv : + forall (A B : Type), equiv (A -> B -> Prop) (@relations_eq A B). +Proof. +intros A B; unfold equiv. split; [| split]; +unfold reflexive, symmetric, transitive, relations_eq. +reflexivity. +intros R1 R2 R3 H1 H2 x y; rewrite H1; apply H2. +now symmetry. +Qed. + +Add Parametric Relation (A B : Type) : (A -> B -> Prop) (@relations_eq A B) + reflexivity proved by (proj1 (relations_eq_equiv A B)) + symmetry proved by (proj2 (proj2 (relations_eq_equiv A B))) + transitivity proved by (proj1 (proj2 (relations_eq_equiv A B))) +as relations_eq_rel. + +Add Parametric Morphism (A : Type) : (@well_founded A) with signature (@relations_eq A A) ==> iff as well_founded_wd. +Proof. +unfold relations_eq, well_founded; intros R1 R2 H; +split; intros H1 a; induction (H1 a) as [x H2 H3]; constructor; +intros y H4; apply H3; [now apply <- H | now apply -> H]. +Qed. + +(* solve_predicate_wd solves the goal [predicate_wd P] for P consisting of +morhisms and quatifiers *) + +Ltac solve_predicate_wd := +unfold predicate_wd; +let x := fresh "x" in +let y := fresh "y" in +let H := fresh "H" in + intros x y H; setoid_rewrite H; reflexivity. + +(* solve_relation_wd solves the goal [relation_wd R] for R consisting of +morhisms and quatifiers *) + +Ltac solve_relation_wd := +unfold relation_wd, fun2_wd; +let x1 := fresh "x" in +let y1 := fresh "y" in +let H1 := fresh "H" in +let x2 := fresh "x" in +let y2 := fresh "y" in +let H2 := fresh "H" in + intros x1 y1 H1 x2 y2 H2; + rewrite H1; setoid_rewrite H2; reflexivity. + +(* The following tactic uses solve_predicate_wd to solve the goals +relating to well-defidedness that are produced by applying induction. +We declare it to take the tactic that applies the induction theorem +and not the induction theorem itself because the tactic may, for +example, supply additional arguments, as does NZinduct_center in +NZBase.v *) + +Ltac induction_maker n t := + try intros until n; + pattern n; t; clear n; + [solve_predicate_wd | ..]. + +(** Relations on cartesian product. Used in MiscFunct for defining +functions whose domain is a product of sets by primitive recursion *) + +Section RelationOnProduct. + +Variables A B : Set. +Variable Aeq : relation A. +Variable Beq : relation B. + +Hypothesis EA_equiv : equiv A Aeq. +Hypothesis EB_equiv : equiv B Beq. + +Definition prod_rel : relation (A * B) := + fun p1 p2 => Aeq (fst p1) (fst p2) /\ Beq (snd p1) (snd p2). + +Lemma prod_rel_refl : reflexive (A * B) prod_rel. +Proof. +unfold reflexive, prod_rel. +destruct x; split; [apply (proj1 EA_equiv) | apply (proj1 EB_equiv)]; simpl. +Qed. + +Lemma prod_rel_symm : symmetric (A * B) prod_rel. +Proof. +unfold symmetric, prod_rel. +destruct x; destruct y; +split; [apply (proj2 (proj2 EA_equiv)) | apply (proj2 (proj2 EB_equiv))]; simpl in *; tauto. +Qed. + +Lemma prod_rel_trans : transitive (A * B) prod_rel. +Proof. +unfold transitive, prod_rel. +destruct x; destruct y; destruct z; simpl. +intros; split; [apply (proj1 (proj2 EA_equiv)) with (y := a0) | +apply (proj1 (proj2 EB_equiv)) with (y := b0)]; tauto. +Qed. + +Theorem prod_rel_equiv : equiv (A * B) prod_rel. +Proof. +unfold equiv; split; [exact prod_rel_refl | split; [exact prod_rel_trans | exact prod_rel_symm]]. +Qed. + +End RelationOnProduct. + +Implicit Arguments prod_rel [A B]. +Implicit Arguments prod_rel_equiv [A B]. + +(** Miscellaneous *) + +(*Definition comp_bool (x y : comparison) : bool := +match x, y with +| Lt, Lt => true +| Eq, Eq => true +| Gt, Gt => true +| _, _ => false +end. + +Theorem comp_bool_correct : forall x y : comparison, + comp_bool x y <-> x = y. +Proof. +destruct x; destruct y; simpl; split; now intro. +Qed.*) + +Lemma eq_equiv : forall A : Set, equiv A (@eq A). +Proof. +intro A; unfold equiv, reflexive, symmetric, transitive. +repeat split; [exact (@trans_eq A) | exact (@sym_eq A)]. +(* It is interesting how the tactic split proves reflexivity *) +Qed. + +(*Add Relation (fun A : Set => A) LE_Set + reflexivity proved by (fun A : Set => (proj1 (eq_equiv A))) + symmetry proved by (fun A : Set => (proj2 (proj2 (eq_equiv A)))) + transitivity proved by (fun A : Set => (proj1 (proj2 (eq_equiv A)))) +as EA_rel.*) diff --git a/theories/Numbers/Rational/BigQ/BigQ.v b/theories/Numbers/Rational/BigQ/BigQ.v new file mode 100644 index 00000000..39e120f7 --- /dev/null +++ b/theories/Numbers/Rational/BigQ/BigQ.v @@ -0,0 +1,35 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: BigQ.v 11028 2008-06-01 17:34:19Z letouzey $ i*) + +Require Export QMake_base. +Require Import QpMake. +Require Import QvMake. +Require Import Q0Make. +Require Import QifMake. +Require Import QbiMake. + +(* We choose for Q the implemention with + multiple representation of 0: 0, 1/0, 2/0 etc *) + +Module BigQ <: QSig.QType := Q0. + +Notation bigQ := BigQ.t. + +Delimit Scope bigQ_scope with bigQ. +Bind Scope bigQ_scope with bigQ. +Bind Scope bigQ_scope with BigQ.t. + +Notation " i + j " := (BigQ.add i j) : bigQ_scope. +Notation " i - j " := (BigQ.sub i j) : bigQ_scope. +Notation " i * j " := (BigQ.mul i j) : bigQ_scope. +Notation " i / j " := (BigQ.div i j) : bigQ_scope. +Notation " i ?= j " := (BigQ.compare i j) : bigQ_scope. diff --git a/theories/Numbers/Rational/BigQ/Q0Make.v b/theories/Numbers/Rational/BigQ/Q0Make.v new file mode 100644 index 00000000..93f52c03 --- /dev/null +++ b/theories/Numbers/Rational/BigQ/Q0Make.v @@ -0,0 +1,1412 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: Q0Make.v 11028 2008-06-01 17:34:19Z letouzey $ i*) + +Require Import Bool. +Require Import ZArith. +Require Import Znumtheory. +Require Import BigNumPrelude. +Require Import Arith. +Require Export BigN. +Require Export BigZ. +Require Import QArith. +Require Import Qcanon. +Require Import Qpower. +Require Import QSig. +Require Import QMake_base. + +Module Q0 <: QType. + + Import BinInt Zorder. + + (** The notation of a rational number is either an integer x, + interpreted as itself or a pair (x,y) of an integer x and a natural + number y interpreted as x/y. The pairs (x,0) and (0,y) are all + interpreted as 0. *) + + Definition t := q_type. + + (** Specification with respect to [QArith] *) + + Open Local Scope Q_scope. + + Definition of_Z x: t := Qz (BigZ.of_Z x). + + Definition of_Q q: t := + match q with x # y => + Qq (BigZ.of_Z x) (BigN.of_N (Npos y)) + end. + + Definition to_Q (q: t) := + match q with + Qz x => BigZ.to_Z x # 1 + |Qq x y => if BigN.eq_bool y BigN.zero then 0 + else BigZ.to_Z x # Z2P (BigN.to_Z y) + end. + + Notation "[ x ]" := (to_Q x). + + Theorem strong_spec_of_Q: forall q: Q, [of_Q q] = q. + Proof. + intros (x,y); simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + rewrite BigN.spec_of_pos; intros HH; discriminate HH. + rewrite BigZ.spec_of_Z; simpl. + rewrite (BigN.spec_of_pos); auto. + Qed. + + Theorem spec_of_Q: forall q: Q, [of_Q q] == q. + Proof. + intros; rewrite strong_spec_of_Q; red; auto. + Qed. + + Definition eq x y := [x] == [y]. + + Definition zero: t := Qz BigZ.zero. + Definition one: t := Qz BigZ.one. + Definition minus_one: t := Qz BigZ.minus_one. + + Lemma spec_0: [zero] == 0. + Proof. + reflexivity. + Qed. + + Lemma spec_1: [one] == 1. + Proof. + reflexivity. + Qed. + + Lemma spec_m1: [minus_one] == -(1). + Proof. + reflexivity. + Qed. + + Definition opp (x: t): t := + match x with + | Qz zx => Qz (BigZ.opp zx) + | Qq nx dx => Qq (BigZ.opp nx) dx + end. + + Theorem strong_spec_opp: forall q, [opp q] = -[q]. + Proof. + intros [z | x y]; simpl. + rewrite BigZ.spec_opp; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + rewrite BigZ.spec_opp; auto. + Qed. + + Theorem spec_opp : forall q, [opp q] == -[q]. + Proof. + intros; rewrite strong_spec_opp; red; auto. + Qed. + + Definition compare (x y: t) := + match x, y with + | Qz zx, Qz zy => BigZ.compare zx zy + | Qz zx, Qq ny dy => + if BigN.eq_bool dy BigN.zero then BigZ.compare zx BigZ.zero + else BigZ.compare (BigZ.mul zx (BigZ.Pos dy)) ny + | Qq nx dx, Qz zy => + if BigN.eq_bool dx BigN.zero then BigZ.compare BigZ.zero zy + else BigZ.compare nx (BigZ.mul zy (BigZ.Pos dx)) + | Qq nx dx, Qq ny dy => + match BigN.eq_bool dx BigN.zero, BigN.eq_bool dy BigN.zero with + | true, true => Eq + | true, false => BigZ.compare BigZ.zero ny + | false, true => BigZ.compare nx BigZ.zero + | false, false => BigZ.compare (BigZ.mul nx (BigZ.Pos dy)) (BigZ.mul ny (BigZ.Pos dx)) + end + end. + + Theorem spec_compare: forall q1 q2, (compare q1 q2) = ([q1] ?= [q2]). + Proof. + intros [z1 | x1 y1] [z2 | x2 y2]; + unfold Qcompare, compare, to_Q, Qnum, Qden. + repeat rewrite Zmult_1_r. + generalize (BigZ.spec_compare z1 z2); case BigZ.compare; intros H; auto. + rewrite H; rewrite Zcompare_refl; auto. + rewrite Zmult_1_r. + generalize (BigN.spec_eq_bool y2 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + rewrite Zmult_1_r; generalize (BigZ.spec_compare z1 BigZ.zero); + case BigZ.compare; auto. + rewrite BigZ.spec_0; intros HH1; rewrite HH1; rewrite Zcompare_refl; auto. + rewrite Z2P_correct; auto with zarith. + 2: generalize (BigN.spec_pos y2); auto with zarith. + generalize (BigZ.spec_compare (z1 * BigZ.Pos y2) x2)%bigZ; case BigZ.compare; + rewrite BigZ.spec_mul; simpl; intros H; apply sym_equal; auto. + rewrite H; rewrite Zcompare_refl; auto. + generalize (BigN.spec_eq_bool y1 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + rewrite Zmult_0_l; rewrite Zmult_1_r. + generalize (BigZ.spec_compare BigZ.zero z2); + case BigZ.compare; auto. + rewrite BigZ.spec_0; intros HH1; rewrite <- HH1; rewrite Zcompare_refl; auto. + rewrite Z2P_correct; auto with zarith. + 2: generalize (BigN.spec_pos y1); auto with zarith. + rewrite Zmult_1_r. + generalize (BigZ.spec_compare x1 (z2 * BigZ.Pos y1))%bigZ; case BigZ.compare; + rewrite BigZ.spec_mul; simpl; intros H; apply sym_equal; auto. + rewrite H; rewrite Zcompare_refl; auto. + generalize (BigN.spec_eq_bool y1 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + generalize (BigN.spec_eq_bool y2 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + rewrite Zcompare_refl; auto. + rewrite Zmult_0_l; rewrite Zmult_1_r. + generalize (BigZ.spec_compare BigZ.zero x2); + case BigZ.compare; auto. + rewrite BigZ.spec_0; intros HH2; rewrite <- HH2; rewrite Zcompare_refl; auto. + generalize (BigN.spec_eq_bool y2 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + rewrite Zmult_0_l; rewrite Zmult_1_r. + generalize (BigZ.spec_compare x1 BigZ.zero)%bigZ; case BigZ.compare; + auto; rewrite BigZ.spec_0. + intros HH2; rewrite <- HH2; rewrite Zcompare_refl; auto. + repeat rewrite Z2P_correct. + 2: generalize (BigN.spec_pos y1); auto with zarith. + 2: generalize (BigN.spec_pos y2); auto with zarith. + generalize (BigZ.spec_compare (x1 * BigZ.Pos y2) + (x2 * BigZ.Pos y1))%bigZ; case BigZ.compare; + repeat rewrite BigZ.spec_mul; simpl; intros H; apply sym_equal; auto. + rewrite H; rewrite Zcompare_refl; auto. + Qed. + + Definition lt n m := compare n m = Lt. + Definition le n m := compare n m <> Gt. + Definition min n m := match compare n m with Gt => m | _ => n end. + Definition max n m := match compare n m with Lt => m | _ => n end. + +(* Je pense que cette fonction normalise bien ... *) + Definition norm n d: t := + let gcd := BigN.gcd (BigZ.to_N n) d in + match BigN.compare BigN.one gcd with + | Lt => + let n := BigZ.div n (BigZ.Pos gcd) in + let d := BigN.div d gcd in + match BigN.compare d BigN.one with + | Gt => Qq n d + | Eq => Qz n + | Lt => zero + end + | Eq => Qq n d + | Gt => zero (* gcd = 0 => both numbers are 0 *) + end. + + Theorem spec_norm: forall n q, [norm n q] == [Qq n q]. + Proof. + intros p q; unfold norm. + assert (Hp := BigN.spec_pos (BigZ.to_N p)). + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; auto; rewrite BigN.spec_1; rewrite BigN.spec_gcd; intros H1. + apply Qeq_refl. + generalize (BigN.spec_pos (q / BigN.gcd (BigZ.to_N p) q)%bigN). + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; auto; rewrite BigN.spec_1; rewrite BigN.spec_div; + rewrite BigN.spec_gcd; auto with zarith; intros H2 HH. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H3; simpl; + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; + auto with zarith. + generalize H2; rewrite H3; + rewrite Zdiv_0_l; auto with zarith. + generalize H1 H2 H3 (BigN.spec_pos q); clear H1 H2 H3. + rewrite spec_to_N. + set (a := (BigN.to_Z (BigZ.to_N p))). + set (b := (BigN.to_Z q)). + intros H1 H2 H3 H4; rewrite Z2P_correct; auto with zarith. + rewrite Zgcd_div_swap; auto with zarith. + rewrite H2; ring. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H3; simpl. + case H3. + generalize H1 H2 H3 HH; clear H1 H2 H3 HH. + set (a := (BigN.to_Z (BigZ.to_N p))). + set (b := (BigN.to_Z q)). + intros H1 H2 H3 HH. + rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto with zarith. + case (Zle_lt_or_eq _ _ HH); auto with zarith. + intros HH1; rewrite <- HH1; ring. + generalize (Zgcd_is_gcd a b); intros HH1; inversion HH1; auto. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_div; + rewrite BigN.spec_gcd; auto with zarith; intros H3. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H4. + case H3; rewrite H4; rewrite Zdiv_0_l; auto with zarith. + simpl. + assert (FF := BigN.spec_pos q). + rewrite Z2P_correct; auto with zarith. + rewrite <- BigN.spec_gcd; rewrite <- BigN.spec_div; auto with zarith. + rewrite Z2P_correct; auto with zarith. + rewrite BigN.spec_div; rewrite BigN.spec_gcd; auto with zarith. + simpl; rewrite BigZ.spec_div; simpl. + rewrite BigN.spec_gcd; auto with zarith. + generalize H1 H2 H3 H4 HH FF; clear H1 H2 H3 H4 HH FF. + set (a := (BigN.to_Z (BigZ.to_N p))). + set (b := (BigN.to_Z q)). + intros H1 H2 H3 H4 HH FF. + rewrite spec_to_N; fold a. + rewrite Zgcd_div_swap; auto with zarith. + rewrite BigN.spec_gcd; auto with zarith. + rewrite BigN.spec_div; + rewrite BigN.spec_gcd; auto with zarith. + rewrite BigN.spec_gcd; auto with zarith. + case (Zle_lt_or_eq _ _ + (BigN.spec_pos (BigN.gcd (BigZ.to_N p) q))); + rewrite BigN.spec_gcd; auto with zarith. + intros; apply False_ind; auto with zarith. + intros HH2; assert (FF1 := Zgcd_inv_0_l _ _ (sym_equal HH2)). + assert (FF2 := Zgcd_inv_0_l _ _ (sym_equal HH2)). + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H2; simpl. + rewrite spec_to_N. + rewrite FF2; ring. + Qed. + + + Definition add (x y: t): t := + match x with + | Qz zx => + match y with + | Qz zy => Qz (BigZ.add zx zy) + | Qq ny dy => + if BigN.eq_bool dy BigN.zero then x + else Qq (BigZ.add (BigZ.mul zx (BigZ.Pos dy)) ny) dy + end + | Qq nx dx => + if BigN.eq_bool dx BigN.zero then y + else match y with + | Qz zy => Qq (BigZ.add nx (BigZ.mul zy (BigZ.Pos dx))) dx + | Qq ny dy => + if BigN.eq_bool dy BigN.zero then x + else + let n := BigZ.add (BigZ.mul nx (BigZ.Pos dy)) (BigZ.mul ny (BigZ.Pos dx)) in + let d := BigN.mul dx dy in + Qq n d + end + end. + + Theorem spec_add : forall x y, [add x y] == [x] + [y]. + Proof. + intros [x | nx dx] [y | ny dy]; unfold Qplus; simpl. + rewrite BigZ.spec_add; repeat rewrite Zmult_1_r; auto. + intros; apply Qeq_refl; auto. + assert (F1:= BigN.spec_pos dy). + rewrite Zmult_1_r; red; simpl. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; + rewrite BigN.spec_0; intros HH; simpl; try ring. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; + rewrite BigN.spec_0; intros HH1; simpl; try ring. + case HH; auto. + rewrite Z2P_correct; auto with zarith. + rewrite BigZ.spec_add; rewrite BigZ.spec_mul; simpl; auto. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool; + rewrite BigN.spec_0; intros HH; simpl; try ring. + rewrite Zmult_1_r; apply Qeq_refl. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool; + rewrite BigN.spec_0; intros HH1; simpl; try ring. + case HH; auto. + rewrite Z2P_correct; auto with zarith. + rewrite BigZ.spec_add; rewrite BigZ.spec_mul; simpl; auto. + rewrite Zmult_1_r; rewrite Pmult_1_r. + apply Qeq_refl. + assert (F1:= BigN.spec_pos dx); auto with zarith. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + simpl. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH2. + apply Qeq_refl. + case HH2; auto. + simpl. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH2. + case HH2; auto. + case HH1; auto. + rewrite Zmult_1_r; apply Qeq_refl. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + simpl. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH2. + case HH; auto. + rewrite Zmult_1_r; rewrite Zplus_0_r; rewrite Pmult_1_r. + apply Qeq_refl. + simpl. + generalize (BigN.spec_eq_bool (dx * dy)%bigN BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_mul; + rewrite BigN.spec_0; intros HH2. + (case (Zmult_integral _ _ HH2); intros HH3); + [case HH| case HH1]; auto. + rewrite BigZ.spec_add; repeat rewrite BigZ.spec_mul; simpl. + assert (Fx: (0 < BigN.to_Z dx)%Z). + generalize (BigN.spec_pos dx); auto with zarith. + assert (Fy: (0 < BigN.to_Z dy)%Z). + generalize (BigN.spec_pos dy); auto with zarith. + red; simpl; rewrite Zpos_mult_morphism. + repeat rewrite Z2P_correct; auto with zarith. + apply Zmult_lt_0_compat; auto. + Qed. + + Definition add_norm (x y: t): t := + match x with + | Qz zx => + match y with + | Qz zy => Qz (BigZ.add zx zy) + | Qq ny dy => + if BigN.eq_bool dy BigN.zero then x + else norm (BigZ.add (BigZ.mul zx (BigZ.Pos dy)) ny) dy + end + | Qq nx dx => + if BigN.eq_bool dx BigN.zero then y + else match y with + | Qz zy => norm (BigZ.add nx (BigZ.mul zy (BigZ.Pos dx))) dx + | Qq ny dy => + if BigN.eq_bool dy BigN.zero then x + else + let n := BigZ.add (BigZ.mul nx (BigZ.Pos dy)) (BigZ.mul ny (BigZ.Pos dx)) in + let d := BigN.mul dx dy in + norm n d + end + end. + + Theorem spec_add_norm : forall x y, [add_norm x y] == [x] + [y]. + Proof. + intros x y; rewrite <- spec_add; auto. + case x; case y; clear x y; unfold add_norm, add. + intros; apply Qeq_refl. + intros p1 n p2. + generalize (BigN.spec_eq_bool n BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + apply Qeq_refl. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end. + simpl. + generalize (BigN.spec_eq_bool n BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + apply Qeq_refl. + apply Qeq_refl. + intros p1 p2 n. + generalize (BigN.spec_eq_bool n BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + apply Qeq_refl. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end. + apply Qeq_refl. + intros p1 q1 p2 q2. + generalize (BigN.spec_eq_bool q2 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + apply Qeq_refl. + generalize (BigN.spec_eq_bool q1 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH2. + apply Qeq_refl. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end. + apply Qeq_refl. + Qed. + + Definition sub x y := add x (opp y). + + Theorem spec_sub : forall x y, [sub x y] == [x] - [y]. + Proof. + intros x y; unfold sub; rewrite spec_add; auto. + rewrite spec_opp; ring. + Qed. + + Definition sub_norm x y := add_norm x (opp y). + + Theorem spec_sub_norm : forall x y, [sub_norm x y] == [x] - [y]. + Proof. + intros x y; unfold sub_norm; rewrite spec_add_norm; auto. + rewrite spec_opp; ring. + Qed. + + Definition mul (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.mul zx zy) + | Qz zx, Qq ny dy => Qq (BigZ.mul zx ny) dy + | Qq nx dx, Qz zy => Qq (BigZ.mul nx zy) dx + | Qq nx dx, Qq ny dy => Qq (BigZ.mul nx ny) (BigN.mul dx dy) + end. + + Theorem spec_mul : forall x y, [mul x y] == [x] * [y]. + Proof. + intros [x | nx dx] [y | ny dy]; unfold Qmult; simpl. + rewrite BigZ.spec_mul; repeat rewrite Zmult_1_r; auto. + intros; apply Qeq_refl; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH1. + red; simpl; ring. + rewrite BigZ.spec_mul; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH1. + red; simpl; ring. + rewrite BigZ.spec_mul; rewrite Pmult_1_r. + apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; rewrite BigN.spec_mul; + intros HH1. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH2. + red; simpl; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH3. + red; simpl; ring. + case (Zmult_integral _ _ HH1); intros HH. + case HH2; auto. + case HH3; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH2. + case HH1; rewrite HH2; ring. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH3. + case HH1; rewrite HH3; ring. + rewrite BigZ.spec_mul. + assert (tmp: + (forall a b, 0 < a -> 0 < b -> Z2P (a * b) = (Z2P a * Z2P b)%positive)%Z). + intros [|a|a] [|b|b]; simpl; auto; intros; apply False_ind; auto with zarith. + rewrite tmp; auto. + apply Qeq_refl. + generalize (BigN.spec_pos dx); auto with zarith. + generalize (BigN.spec_pos dy); auto with zarith. + Qed. + +Definition mul_norm (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.mul zx zy) + | Qz zx, Qq ny dy => + if BigZ.eq_bool zx BigZ.zero then zero + else + let gcd := BigN.gcd (BigZ.to_N zx) dy in + match BigN.compare gcd BigN.one with + Gt => + let zx := BigZ.div zx (BigZ.Pos gcd) in + let d := BigN.div dy gcd in + if BigN.eq_bool d BigN.one then Qz (BigZ.mul zx ny) + else Qq (BigZ.mul zx ny) d + | _ => Qq (BigZ.mul zx ny) dy + end + | Qq nx dx, Qz zy => + if BigZ.eq_bool zy BigZ.zero then zero + else + let gcd := BigN.gcd (BigZ.to_N zy) dx in + match BigN.compare gcd BigN.one with + Gt => + let zy := BigZ.div zy (BigZ.Pos gcd) in + let d := BigN.div dx gcd in + if BigN.eq_bool d BigN.one then Qz (BigZ.mul zy nx) + else Qq (BigZ.mul zy nx) d + | _ => Qq (BigZ.mul zy nx) dx + end + | Qq nx dx, Qq ny dy => + let (nx, dy) := + let gcd := BigN.gcd (BigZ.to_N nx) dy in + match BigN.compare gcd BigN.one with + Gt => (BigZ.div nx (BigZ.Pos gcd), BigN.div dy gcd) + | _ => (nx, dy) + end in + let (ny, dx) := + let gcd := BigN.gcd (BigZ.to_N ny) dx in + match BigN.compare gcd BigN.one with + Gt => (BigZ.div ny (BigZ.Pos gcd), BigN.div dx gcd) + | _ => (ny, dx) + end in + let d := (BigN.mul dx dy) in + if BigN.eq_bool d BigN.one then Qz (BigZ.mul ny nx) + else Qq (BigZ.mul ny nx) d + end. + + Theorem spec_mul_norm : forall x y, [mul_norm x y] == [x] * [y]. + Proof. + intros x y; rewrite <- spec_mul; auto. + unfold mul_norm, mul; case x; case y; clear x y. + intros; apply Qeq_refl. + intros p1 n p2. + set (a := BigN.to_Z (BigZ.to_N p2)). + set (b := BigN.to_Z n). + match goal with |- context[BigZ.eq_bool ?X ?Y] => + generalize (BigZ.spec_eq_bool X Y); case BigZ.eq_bool + end; unfold zero, to_Q; repeat rewrite BigZ.spec_0; intros H. + case BigN.eq_bool; try apply Qeq_refl. + rewrite BigZ.spec_mul; rewrite H. + red; simpl; ring. + assert (F: (0 < a)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos (BigZ.to_N p2))); auto. + intros H1; case H; rewrite spec_to_N; rewrite <- H1; ring. + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; rewrite BigN.spec_1; rewrite BigN.spec_gcd; + fold a b; intros H1. + apply Qeq_refl. + apply Qeq_refl. + assert (F0 : (0 < (Zgcd a b))%Z). + apply Zlt_trans with 1%Z. + red; auto. + apply Zgt_lt; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1; rewrite BigN.spec_div; + rewrite BigN.spec_gcd; auto with zarith; + fold a b; intros H2. + assert (F1: b = Zgcd a b). + pattern b at 1; rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); + auto with zarith. + rewrite H2; ring. + assert (FF := Zgcd_is_gcd a b); inversion FF; auto. + assert (F2: (0 < b)%Z). + rewrite F1; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; fold b; intros H3. + rewrite H3 in F2; discriminate F2. + rewrite BigZ.spec_mul. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; + fold a b; auto with zarith. + rewrite BigZ.spec_mul. + red; simpl; rewrite Z2P_correct; auto. + rewrite Zmult_1_r; rewrite spec_to_N; fold a b. + repeat rewrite <- Zmult_assoc. + rewrite (Zmult_comm (BigZ.to_Z p1)). + repeat rewrite Zmult_assoc. + rewrite Zgcd_div_swap; auto with zarith. + rewrite H2; ring. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; rewrite BigN.spec_div; + rewrite BigN.spec_gcd; fold a b; auto; intros H3. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H4. + apply Qeq_refl. + case H4; fold b. + rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto. + rewrite H3; ring. + assert (FF := Zgcd_is_gcd a b); inversion FF; auto. + simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; fold b; intros H4. + case H3; rewrite H4; rewrite Zdiv_0_l; auto. + rewrite BigZ.spec_mul; rewrite BigZ.spec_div; simpl; + rewrite BigN.spec_gcd; fold a b; auto with zarith. + assert (F1: (0 < b)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos n)); fold b; auto with zarith. + red; simpl. + rewrite BigZ.spec_mul. + repeat rewrite Z2P_correct; auto. + rewrite spec_to_N; fold a. + repeat rewrite <- Zmult_assoc. + rewrite (Zmult_comm (BigZ.to_Z p1)). + repeat rewrite Zmult_assoc. + rewrite Zgcd_div_swap; auto with zarith. + ring. + apply Zgcd_div_pos; auto. + intros p1 p2 n. + set (a := BigN.to_Z (BigZ.to_N p1)). + set (b := BigN.to_Z n). + match goal with |- context[BigZ.eq_bool ?X ?Y] => + generalize (BigZ.spec_eq_bool X Y); case BigZ.eq_bool + end; unfold zero, to_Q; repeat rewrite BigZ.spec_0; intros H. + case BigN.eq_bool; try apply Qeq_refl. + rewrite BigZ.spec_mul; rewrite H. + red; simpl; ring. + assert (F: (0 < a)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos (BigZ.to_N p1))); auto. + intros H1; case H; rewrite spec_to_N; rewrite <- H1; ring. + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; rewrite BigN.spec_1; rewrite BigN.spec_gcd; + fold a b; intros H1. + repeat rewrite BigZ.spec_mul; rewrite Zmult_comm. + apply Qeq_refl. + repeat rewrite BigZ.spec_mul; rewrite Zmult_comm. + apply Qeq_refl. + assert (F0 : (0 < (Zgcd a b))%Z). + apply Zlt_trans with 1%Z. + red; auto. + apply Zgt_lt; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1; rewrite BigN.spec_div; + rewrite BigN.spec_gcd; auto with zarith; + fold a b; intros H2. + assert (F1: b = Zgcd a b). + pattern b at 1; rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); + auto with zarith. + rewrite H2; ring. + assert (FF := Zgcd_is_gcd a b); inversion FF; auto. + assert (F2: (0 < b)%Z). + rewrite F1; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; fold b; intros H3. + rewrite H3 in F2; discriminate F2. + rewrite BigZ.spec_mul. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; + fold a b; auto with zarith. + rewrite BigZ.spec_mul. + red; simpl; rewrite Z2P_correct; auto. + rewrite Zmult_1_r; rewrite spec_to_N; fold a b. + repeat rewrite <- Zmult_assoc. + rewrite (Zmult_comm (BigZ.to_Z p2)). + repeat rewrite Zmult_assoc. + rewrite Zgcd_div_swap; auto with zarith. + rewrite H2; ring. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; rewrite BigN.spec_div; + rewrite BigN.spec_gcd; fold a b; auto; intros H3. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H4. + apply Qeq_refl. + case H4; fold b. + rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto. + rewrite H3; ring. + assert (FF := Zgcd_is_gcd a b); inversion FF; auto. + simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; fold b; intros H4. + case H3; rewrite H4; rewrite Zdiv_0_l; auto. + rewrite BigZ.spec_mul; rewrite BigZ.spec_div; simpl; + rewrite BigN.spec_gcd; fold a b; auto with zarith. + assert (F1: (0 < b)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos n)); fold b; auto with zarith. + red; simpl. + rewrite BigZ.spec_mul. + repeat rewrite Z2P_correct; auto. + rewrite spec_to_N; fold a. + repeat rewrite <- Zmult_assoc. + rewrite (Zmult_comm (BigZ.to_Z p2)). + repeat rewrite Zmult_assoc. + rewrite Zgcd_div_swap; auto with zarith. + ring. + apply Zgcd_div_pos; auto. + set (f := fun p t => + match (BigN.gcd (BigZ.to_N p) t ?= BigN.one)%bigN with + | Eq => (p, t) + | Lt => (p, t) + | Gt => + ((p / BigZ.Pos (BigN.gcd (BigZ.to_N p) t))%bigZ, + (t / BigN.gcd (BigZ.to_N p) t)%bigN) + end). + assert (F: forall p t, + let (n, d) := f p t in [Qq p t] == [Qq n d]). + intros p t1; unfold f. + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; rewrite BigN.spec_1; rewrite BigN.spec_gcd; intros H1. + apply Qeq_refl. + apply Qeq_refl. + set (a := BigN.to_Z (BigZ.to_N p)). + set (b := BigN.to_Z t1). + fold a b in H1. + assert (F0 : (0 < (Zgcd a b))%Z). + apply Zlt_trans with 1%Z. + red; auto. + apply Zgt_lt; auto. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; fold b; intros HH1. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; fold b; intros HH2. + simpl; ring. + case HH2. + rewrite BigN.spec_div; rewrite BigN.spec_gcd; fold a b; auto. + rewrite HH1; rewrite Zdiv_0_l; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; + rewrite BigN.spec_div; rewrite BigN.spec_gcd; fold a b; auto; + intros HH2. + case HH1. + rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto. + rewrite HH2; ring. + assert (FF := Zgcd_is_gcd a b); inversion FF; auto. + simpl. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; fold a b; auto with zarith. + assert (F1: (0 < b)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos t1)); fold b; auto with zarith. + intros HH; case HH1; auto. + repeat rewrite Z2P_correct; auto. + rewrite spec_to_N; fold a. + rewrite Zgcd_div_swap; auto. + apply Zgcd_div_pos; auto. + intros HH; rewrite HH in F0; discriminate F0. + intros p1 n1 p2 n2. + change ([let (nx , dy) := f p2 n1 in + let (ny, dx) := f p1 n2 in + if BigN.eq_bool (dx * dy)%bigN BigN.one + then Qz (ny * nx) + else Qq (ny * nx) (dx * dy)] == [Qq (p2 * p1) (n2 * n1)]). + generalize (F p2 n1) (F p1 n2). + case f; case f. + intros u1 u2 v1 v2 Hu1 Hv1. + apply Qeq_trans with [mul (Qq p2 n1) (Qq p1 n2)]. + rewrite spec_mul; rewrite Hu1; rewrite Hv1. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1; rewrite BigN.spec_mul; intros HH1. + assert (F1: BigN.to_Z u2 = 1%Z). + case (Zmult_1_inversion_l _ _ HH1); auto. + generalize (BigN.spec_pos u2); auto with zarith. + assert (F2: BigN.to_Z v2 = 1%Z). + rewrite Zmult_comm in HH1. + case (Zmult_1_inversion_l _ _ HH1); auto. + generalize (BigN.spec_pos v2); auto with zarith. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1. + rewrite H1 in F2; discriminate F2. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2. + rewrite H2 in F1; discriminate F1. + simpl; rewrite BigZ.spec_mul. + rewrite F1; rewrite F2; simpl; ring. + rewrite Qmult_comm; rewrite <- spec_mul. + apply Qeq_refl. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; rewrite BigN.spec_mul; + rewrite Zmult_comm; intros H1. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; rewrite BigN.spec_mul; intros H2; auto. + case H2; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; rewrite BigN.spec_mul; intros H2; auto. + case H1; auto. + Qed. + + +Definition inv (x: t): t := + match x with + | Qz (BigZ.Pos n) => Qq BigZ.one n + | Qz (BigZ.Neg n) => Qq BigZ.minus_one n + | Qq (BigZ.Pos n) d => Qq (BigZ.Pos d) n + | Qq (BigZ.Neg n) d => Qq (BigZ.Neg d) n + end. + + Theorem spec_inv : forall x, [inv x] == /[x]. + Proof. + intros [ [x | x] | [nx | nx] dx]; unfold inv, Qinv; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; auto. + rewrite H1; apply Qeq_refl. + generalize H1 (BigN.spec_pos x); case (BigN.to_Z x); auto. + intros HH; case HH; auto. + intros; red; simpl; auto. + intros p _ HH; case HH; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; auto. + rewrite H1; apply Qeq_refl. + generalize H1 (BigN.spec_pos x); case (BigN.to_Z x); simpl; + auto. + intros HH; case HH; auto. + intros; red; simpl; auto. + intros p _ HH; case HH; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; simpl; auto. + apply Qeq_refl. + rewrite H1; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; simpl; auto. + rewrite H2; red; simpl; auto. + generalize H1 (BigN.spec_pos nx); case (BigN.to_Z nx); simpl; + auto. + intros HH; case HH; auto. + intros; red; simpl. + rewrite Zpos_mult_morphism. + rewrite Z2P_correct; auto. + generalize (BigN.spec_pos dx); auto with zarith. + intros p _ HH; case HH; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; simpl; auto. + apply Qeq_refl. + rewrite H1; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; simpl; auto. + rewrite H2; red; simpl; auto. + generalize H1 (BigN.spec_pos nx); case (BigN.to_Z nx); simpl; + auto. + intros HH; case HH; auto. + intros; red; simpl. + assert (tmp: forall x, Zneg x = Zopp (Zpos x)); auto. + rewrite tmp. + rewrite Zpos_mult_morphism. + rewrite Z2P_correct; auto. + ring. + generalize (BigN.spec_pos dx); auto with zarith. + intros p _ HH; case HH; auto. + Qed. + +Definition inv_norm (x: t): t := + match x with + | Qz (BigZ.Pos n) => + match BigN.compare n BigN.one with + Gt => Qq BigZ.one n + | _ => x + end + | Qz (BigZ.Neg n) => + match BigN.compare n BigN.one with + Gt => Qq BigZ.minus_one n + | _ => x + end + | Qq (BigZ.Pos n) d => + match BigN.compare n BigN.one with + Gt => Qq (BigZ.Pos d) n + | Eq => Qz (BigZ.Pos d) + | Lt => Qz (BigZ.zero) + end + | Qq (BigZ.Neg n) d => + match BigN.compare n BigN.one with + Gt => Qq (BigZ.Neg d) n + | Eq => Qz (BigZ.Neg d) + | Lt => Qz (BigZ.zero) + end + end. + + Theorem spec_inv_norm : forall x, [inv_norm x] == /[x]. + Proof. + intros [ [x | x] | [nx | nx] dx]; unfold inv_norm, Qinv. + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; rewrite BigN.spec_1; intros H. + simpl; rewrite H; apply Qeq_refl. + case (Zle_lt_or_eq _ _ (BigN.spec_pos x)); simpl. + generalize H; case BigN.to_Z. + intros _ HH; discriminate HH. + intros p; case p; auto. + intros p1 HH; discriminate HH. + intros p1 HH; discriminate HH. + intros HH; discriminate HH. + intros p _ HH; discriminate HH. + intros HH; rewrite <- HH. + apply Qeq_refl. + generalize H; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1. + rewrite H1; intros HH; discriminate. + generalize H; case BigN.to_Z. + intros HH; discriminate HH. + intros; red; simpl; auto. + intros p HH; discriminate HH. + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; rewrite BigN.spec_1; intros H. + simpl; rewrite H; apply Qeq_refl. + case (Zle_lt_or_eq _ _ (BigN.spec_pos x)); simpl. + generalize H; case BigN.to_Z. + intros _ HH; discriminate HH. + intros p; case p; auto. + intros p1 HH; discriminate HH. + intros p1 HH; discriminate HH. + intros HH; discriminate HH. + intros p _ HH; discriminate HH. + intros HH; rewrite <- HH. + apply Qeq_refl. + generalize H; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1. + rewrite H1; intros HH; discriminate. + generalize H; case BigN.to_Z. + intros HH; discriminate HH. + intros; red; simpl; auto. + intros p HH; discriminate HH. + simpl Qnum. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; simpl. + case BigN.compare; red; simpl; auto. + rewrite H1; auto. + case BigN.eq_bool; auto. + simpl; rewrite H1; auto. + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; rewrite BigN.spec_1; intros H2. + rewrite H2. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H3. + case H1; auto. + red; simpl. + rewrite Zmult_1_r; rewrite Pmult_1_r; rewrite Z2P_correct; auto. + generalize (BigN.spec_pos dx); auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H3. + case H1; auto. + generalize H2 (BigN.spec_pos nx); case (BigN.to_Z nx). + intros; apply Qeq_refl. + intros p; case p; clear p. + intros p HH; discriminate HH. + intros p HH; discriminate HH. + intros HH; discriminate HH. + intros p _ HH; case HH; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H3. + case H1; auto. + simpl; generalize H2; case (BigN.to_Z nx). + intros HH; discriminate HH. + intros p Hp. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H4. + rewrite H4 in H2; discriminate H2. + red; simpl. + rewrite Zpos_mult_morphism. + rewrite Z2P_correct; auto. + generalize (BigN.spec_pos dx); auto with zarith. + intros p HH; discriminate HH. + simpl Qnum. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; simpl. + case BigN.compare; red; simpl; auto. + rewrite H1; auto. + case BigN.eq_bool; auto. + simpl; rewrite H1; auto. + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; rewrite BigN.spec_1; intros H2. + rewrite H2. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H3. + case H1; auto. + red; simpl. + assert (tmp: forall x, Zneg x = Zopp (Zpos x)); auto. + rewrite tmp. + rewrite Zmult_1_r; rewrite Pmult_1_r; rewrite Z2P_correct; auto. + generalize (BigN.spec_pos dx); auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H3. + case H1; auto. + generalize H2 (BigN.spec_pos nx); case (BigN.to_Z nx). + intros; apply Qeq_refl. + intros p; case p; clear p. + intros p HH; discriminate HH. + intros p HH; discriminate HH. + intros HH; discriminate HH. + intros p _ HH; case HH; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H3. + case H1; auto. + simpl; generalize H2; case (BigN.to_Z nx). + intros HH; discriminate HH. + intros p Hp. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H4. + rewrite H4 in H2; discriminate H2. + red; simpl. + assert (tmp: forall x, Zneg x = Zopp (Zpos x)); auto. + rewrite tmp. + rewrite Zpos_mult_morphism. + rewrite Z2P_correct; auto. + ring. + generalize (BigN.spec_pos dx); auto with zarith. + intros p HH; discriminate HH. + Qed. + + Definition div x y := mul x (inv y). + + Theorem spec_div x y: [div x y] == [x] / [y]. + Proof. + intros x y; unfold div; rewrite spec_mul; auto. + unfold Qdiv; apply Qmult_comp. + apply Qeq_refl. + apply spec_inv; auto. + Qed. + + Definition div_norm x y := mul_norm x (inv y). + + Theorem spec_div_norm x y: [div_norm x y] == [x] / [y]. + Proof. + intros x y; unfold div_norm; rewrite spec_mul_norm; auto. + unfold Qdiv; apply Qmult_comp. + apply Qeq_refl. + apply spec_inv; auto. + Qed. + + Definition square (x: t): t := + match x with + | Qz zx => Qz (BigZ.square zx) + | Qq nx dx => Qq (BigZ.square nx) (BigN.square dx) + end. + + Theorem spec_square : forall x, [square x] == [x] ^ 2. + Proof. + intros [ x | nx dx]; unfold square. + red; simpl; rewrite BigZ.spec_square; auto with zarith. + simpl Qpower. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H. + red; simpl. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_square; + intros H1. + case H1; rewrite H; auto. + red; simpl. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_square; + intros H1. + case H; case (Zmult_integral _ _ H1); auto. + simpl. + rewrite BigZ.spec_square. + rewrite Zpos_mult_morphism. + assert (tmp: + (forall a b, 0 < a -> 0 < b -> Z2P (a * b) = (Z2P a * Z2P b)%positive)%Z). + intros [|a|a] [|b|b]; simpl; auto; intros; apply False_ind; auto with zarith. + rewrite tmp; auto. + generalize (BigN.spec_pos dx); auto with zarith. + generalize (BigN.spec_pos dx); auto with zarith. + Qed. + + Definition power_pos (x: t) p: t := + match x with + | Qz zx => Qz (BigZ.power_pos zx p) + | Qq nx dx => Qq (BigZ.power_pos nx p) (BigN.power_pos dx p) + end. + + Theorem spec_power_pos : forall x p, [power_pos x p] == [x] ^ Zpos p. + Proof. + intros [x | nx dx] p; unfold power_pos. + unfold power_pos; red; simpl. + generalize (Qpower_decomp p (BigZ.to_Z x) 1). + unfold Qeq; simpl. + rewrite Zpower_pos_1_l; simpl Z2P. + rewrite Zmult_1_r. + intros H; rewrite H. + rewrite BigZ.spec_power_pos; simpl; ring. + simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_power_pos; intros H1. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H2. + elim p; simpl. + intros; red; simpl; auto. + intros p1 Hp1; rewrite <- Hp1; red; simpl; auto. + apply Qeq_refl. + case H2; generalize H1. + elim p; simpl. + intros p1 Hrec. + change (xI p1) with (1 + (xO p1))%positive. + rewrite Zpower_pos_is_exp; rewrite Zpower_pos_1_r. + intros HH; case (Zmult_integral _ _ HH); auto. + rewrite <- Pplus_diag. + rewrite Zpower_pos_is_exp. + intros HH1; case (Zmult_integral _ _ HH1); auto. + intros p1 Hrec. + rewrite <- Pplus_diag. + rewrite Zpower_pos_is_exp. + intros HH1; case (Zmult_integral _ _ HH1); auto. + rewrite Zpower_pos_1_r; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H2. + case H1; rewrite H2; auto. + simpl; rewrite Zpower_pos_0_l; auto. + assert (F1: (0 < BigN.to_Z dx)%Z). + generalize (BigN.spec_pos dx); auto with zarith. + assert (F2: (0 < BigN.to_Z dx ^ ' p)%Z). + unfold Zpower; apply Zpower_pos_pos; auto. + unfold power_pos; red; simpl. + generalize (Qpower_decomp p (BigZ.to_Z nx) + (Z2P (BigN.to_Z dx))). + unfold Qeq; simpl. + repeat rewrite Z2P_correct; auto. + unfold Qeq; simpl; intros HH. + rewrite HH. + rewrite BigZ.spec_power_pos; simpl; ring. + Qed. + + (** Interaction with [Qcanon.Qc] *) + + Open Scope Qc_scope. + + Definition of_Qc q := of_Q (this q). + + Definition to_Qc q := !!(to_Q q). + + Notation "[[ x ]]" := (to_Qc x). + + Theorem spec_of_Qc: forall q, [[of_Qc q]] = q. + Proof. + intros (x, Hx); unfold of_Qc, to_Qc; simpl. + apply Qc_decomp; simpl. + intros. + rewrite <- H0 at 2; apply Qred_complete. + apply spec_of_Q. + Qed. + + Theorem spec_oppc: forall q, [[opp q]] = -[[q]]. + Proof. + intros q; unfold Qcopp, to_Qc, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + rewrite spec_opp. + rewrite <- Qred_opp. + rewrite Qred_correct; red; auto. + Qed. + + Theorem spec_comparec: forall q1 q2, + compare q1 q2 = ([[q1]] ?= [[q2]]). + Proof. + unfold Qccompare, to_Qc. + intros q1 q2; rewrite spec_compare; simpl; auto. + apply Qcompare_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Theorem spec_addc x y: + [[add x y]] = [[x]] + [[y]]. + Proof. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] + [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_add; auto. + unfold Qcplus, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qplus_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Theorem spec_add_normc x y: + [[add_norm x y]] = [[x]] + [[y]]. + Proof. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] + [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_add_norm; auto. + unfold Qcplus, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qplus_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Theorem spec_subc x y: [[sub x y]] = [[x]] - [[y]]. + Proof. + intros x y; unfold sub; rewrite spec_addc; auto. + rewrite spec_oppc; ring. + Qed. + + Theorem spec_sub_normc x y: + [[sub_norm x y]] = [[x]] - [[y]]. + intros x y; unfold sub_norm; rewrite spec_add_normc; auto. + rewrite spec_oppc; ring. + Qed. + + Theorem spec_mulc x y: + [[mul x y]] = [[x]] * [[y]]. + Proof. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] * [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_mul; auto. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Theorem spec_mul_normc x y: + [[mul_norm x y]] = [[x]] * [[y]]. + Proof. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] * [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_mul_norm; auto. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Theorem spec_invc x: + [[inv x]] = /[[x]]. + Proof. + intros x; unfold to_Qc. + apply trans_equal with (!! (/[x])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_inv; auto. + unfold Qcinv, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qinv_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Theorem spec_inv_normc x: + [[inv_norm x]] = /[[x]]. + Proof. + intros x; unfold to_Qc. + apply trans_equal with (!! (/[x])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_inv_norm; auto. + unfold Qcinv, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qinv_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Theorem spec_divc x y: [[div x y]] = [[x]] / [[y]]. + Proof. + intros x y; unfold div; rewrite spec_mulc; auto. + unfold Qcdiv; apply f_equal2 with (f := Qcmult); auto. + apply spec_invc; auto. + Qed. + + Theorem spec_div_normc x y: [[div_norm x y]] = [[x]] / [[y]]. + Proof. + intros x y; unfold div_norm; rewrite spec_mul_normc; auto. + unfold Qcdiv; apply f_equal2 with (f := Qcmult); auto. + apply spec_invc; auto. + Qed. + + Theorem spec_squarec x: [[square x]] = [[x]]^2. + Proof. + intros x; unfold to_Qc. + apply trans_equal with (!! ([x]^2)). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_square; auto. + simpl Qcpower. + replace (!! [x] * 1) with (!![x]); try ring. + simpl. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Theorem spec_power_posc x p: + [[power_pos x p]] = [[x]] ^ nat_of_P p. + Proof. + intros x p; unfold to_Qc. + apply trans_equal with (!! ([x]^Zpos p)). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_power_pos; auto. + pattern p; apply Pind; clear p. + simpl; ring. + intros p Hrec. + rewrite nat_of_P_succ_morphism; simpl Qcpower. + rewrite <- Hrec. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; + unfold this. + apply Qred_complete. + assert (F: [x] ^ ' Psucc p == [x] * [x] ^ ' p). + simpl; case x; simpl; clear x Hrec. + intros x; simpl; repeat rewrite Qpower_decomp; simpl. + red; simpl; repeat rewrite Zpower_pos_1_l; simpl Z2P. + rewrite Pplus_one_succ_l. + rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r; auto. + intros nx dx. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + unfold Qpower_positive. + assert (tmp: forall p, pow_pos Qmult 0%Q p = 0%Q). + intros p1; elim p1; simpl; auto; clear p1. + intros p1 Hp1; rewrite Hp1; auto. + intros p1 Hp1; rewrite Hp1; auto. + repeat rewrite tmp; intros; red; simpl; auto. + intros H1. + assert (F1: (0 < BigN.to_Z dx)%Z). + generalize (BigN.spec_pos dx); auto with zarith. + simpl; repeat rewrite Qpower_decomp; simpl. + red; simpl; repeat rewrite Zpower_pos_1_l; simpl Z2P. + rewrite Pplus_one_succ_l. + rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r; auto. + repeat rewrite Zpos_mult_morphism. + repeat rewrite Z2P_correct; auto. + 2: apply Zpower_pos_pos; auto. + 2: apply Zpower_pos_pos; auto. + rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r; auto. + rewrite F. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + +End Q0. diff --git a/theories/Numbers/Rational/BigQ/QMake_base.v b/theories/Numbers/Rational/BigQ/QMake_base.v new file mode 100644 index 00000000..547e74b7 --- /dev/null +++ b/theories/Numbers/Rational/BigQ/QMake_base.v @@ -0,0 +1,34 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(* $Id: QMake_base.v 10964 2008-05-22 11:08:13Z letouzey $ *) + +(** * An implementation of rational numbers based on big integers *) + +Require Export BigN. +Require Export BigZ. + +(* Basic type for Q: a Z or a pair of a Z and an N *) + +Inductive q_type := + | Qz : BigZ.t -> q_type + | Qq : BigZ.t -> BigN.t -> q_type. + +Definition print_type x := + match x with + | Qz _ => Z + | _ => (Z*Z)%type + end. + +Definition print x := + match x return print_type x with + | Qz zx => BigZ.to_Z zx + | Qq nx dx => (BigZ.to_Z nx, BigN.to_Z dx) + end. diff --git a/theories/Numbers/Rational/BigQ/QbiMake.v b/theories/Numbers/Rational/BigQ/QbiMake.v new file mode 100644 index 00000000..699f383e --- /dev/null +++ b/theories/Numbers/Rational/BigQ/QbiMake.v @@ -0,0 +1,1066 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: QbiMake.v 11027 2008-06-01 13:28:59Z letouzey $ i*) + +Require Import Bool. +Require Import ZArith. +Require Import Znumtheory. +Require Import BigNumPrelude. +Require Import Arith. +Require Export BigN. +Require Export BigZ. +Require Import QArith. +Require Import Qcanon. +Require Import Qpower. +Require Import QMake_base. + +Module Qbi. + + Import BinInt Zorder. + Open Local Scope Q_scope. + Open Local Scope Qc_scope. + + (** The notation of a rational number is either an integer x, + interpreted as itself or a pair (x,y) of an integer x and a naturel + number y interpreted as x/y. The pairs (x,0) and (0,y) are all + interpreted as 0. *) + + Definition t := q_type. + + Definition zero: t := Qz BigZ.zero. + Definition one: t := Qz BigZ.one. + Definition minus_one: t := Qz BigZ.minus_one. + + Definition of_Z x: t := Qz (BigZ.of_Z x). + + + Definition of_Q q: t := + match q with x # y => + Qq (BigZ.of_Z x) (BigN.of_N (Npos y)) + end. + + Definition of_Qc q := of_Q (this q). + + Definition to_Q (q: t) := + match q with + Qz x => BigZ.to_Z x # 1 + |Qq x y => if BigN.eq_bool y BigN.zero then 0%Q + else BigZ.to_Z x # Z2P (BigN.to_Z y) + end. + + Definition to_Qc q := !!(to_Q q). + + Notation "[[ x ]]" := (to_Qc x). + + Notation "[ x ]" := (to_Q x). + + Theorem spec_to_Q: forall q: Q, [of_Q q] = q. + intros (x,y); simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + rewrite BigN.spec_of_pos; intros HH; discriminate HH. + rewrite BigZ.spec_of_Z; simpl. + rewrite (BigN.spec_of_pos); auto. + Qed. + + Theorem spec_to_Qc: forall q, [[of_Qc q]] = q. + intros (x, Hx); unfold of_Qc, to_Qc; simpl. + apply Qc_decomp; simpl. + intros; rewrite spec_to_Q; auto. + Qed. + + Definition opp (x: t): t := + match x with + | Qz zx => Qz (BigZ.opp zx) + | Qq nx dx => Qq (BigZ.opp nx) dx + end. + + Theorem spec_opp: forall q, ([opp q] = -[q])%Q. + intros [z | x y]; simpl. + rewrite BigZ.spec_opp; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + rewrite BigZ.spec_opp; auto. + Qed. + + Theorem spec_oppc: forall q, [[opp q]] = -[[q]]. + intros q; unfold Qcopp, to_Qc, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + rewrite spec_opp. + rewrite <- Qred_opp. + rewrite Qred_involutive; auto. + Qed. + + + Definition compare (x y: t) := + match x, y with + | Qz zx, Qz zy => BigZ.compare zx zy + | Qz zx, Qq ny dy => + if BigN.eq_bool dy BigN.zero then BigZ.compare zx BigZ.zero + else + match BigZ.cmp_sign zx ny with + | Lt => Lt + | Gt => Gt + | Eq => BigZ.compare (BigZ.mul zx (BigZ.Pos dy)) ny + end + | Qq nx dx, Qz zy => + if BigN.eq_bool dx BigN.zero then BigZ.compare BigZ.zero zy + else + match BigZ.cmp_sign nx zy with + | Lt => Lt + | Gt => Gt + | Eq => BigZ.compare nx (BigZ.mul zy (BigZ.Pos dx)) + end + | Qq nx dx, Qq ny dy => + match BigN.eq_bool dx BigN.zero, BigN.eq_bool dy BigN.zero with + | true, true => Eq + | true, false => BigZ.compare BigZ.zero ny + | false, true => BigZ.compare nx BigZ.zero + | false, false => + match BigZ.cmp_sign nx ny with + | Lt => Lt + | Gt => Gt + | Eq => BigZ.compare (BigZ.mul nx (BigZ.Pos dy)) (BigZ.mul ny (BigZ.Pos dx)) + end + end + end. + + Theorem spec_compare: forall q1 q2, + compare q1 q2 = ([q1] ?= [q2])%Q. + intros [z1 | x1 y1] [z2 | x2 y2]; + unfold Qcompare, compare, to_Q, Qnum, Qden. + repeat rewrite Zmult_1_r. + generalize (BigZ.spec_compare z1 z2); case BigZ.compare; intros H; auto. + rewrite H; rewrite Zcompare_refl; auto. + rewrite Zmult_1_r. + generalize (BigN.spec_eq_bool y2 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + rewrite Zmult_1_r; generalize (BigZ.spec_compare z1 BigZ.zero); + case BigZ.compare; auto. + rewrite BigZ.spec_0; intros HH1; rewrite HH1; rewrite Zcompare_refl; auto. + set (a := BigZ.to_Z z1); set (b := BigZ.to_Z x2); + set (c := BigN.to_Z y2); fold c in HH. + assert (F: (0 < c)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos y2)); fold c; auto. + intros H1; case HH; rewrite <- H1; auto. + rewrite Z2P_correct; auto with zarith. + generalize (BigZ.spec_cmp_sign z1 x2); case BigZ.cmp_sign; fold a b c. + intros _; generalize (BigZ.spec_compare (z1 * BigZ.Pos y2)%bigZ x2); + case BigZ.compare; rewrite BigZ.spec_mul; simpl; fold a b c; auto. + intros H1; rewrite H1; rewrite Zcompare_refl; auto. + intros (H1, H2); apply sym_equal; change (a * c < b)%Z. + apply Zlt_le_trans with (2 := H2). + change 0%Z with (0 * c)%Z. + apply Zmult_lt_compat_r; auto with zarith. + intros (H1, H2); apply sym_equal; change (a * c > b)%Z. + apply Zlt_gt. + apply Zlt_le_trans with (1 := H2). + change 0%Z with (0 * c)%Z. + apply Zmult_le_compat_r; auto with zarith. + generalize (BigN.spec_eq_bool y1 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + rewrite Zmult_0_l; rewrite Zmult_1_r. + generalize (BigZ.spec_compare BigZ.zero z2); + case BigZ.compare; auto. + rewrite BigZ.spec_0; intros HH1; rewrite <- HH1; rewrite Zcompare_refl; auto. + set (a := BigZ.to_Z z2); set (b := BigZ.to_Z x1); + set (c := BigN.to_Z y1); fold c in HH. + assert (F: (0 < c)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos y1)); fold c; auto. + intros H1; case HH; rewrite <- H1; auto. + rewrite Zmult_1_r; rewrite Z2P_correct; auto with zarith. + generalize (BigZ.spec_cmp_sign x1 z2); case BigZ.cmp_sign; fold a b c. + intros _; generalize (BigZ.spec_compare x1 (z2 * BigZ.Pos y1)%bigZ); + case BigZ.compare; rewrite BigZ.spec_mul; simpl; fold a b c; auto. + intros H1; rewrite H1; rewrite Zcompare_refl; auto. + intros (H1, H2); apply sym_equal; change (b < a * c)%Z. + apply Zlt_le_trans with (1 := H1). + change 0%Z with (0 * c)%Z. + apply Zmult_le_compat_r; auto with zarith. + intros (H1, H2); apply sym_equal; change (b > a * c)%Z. + apply Zlt_gt. + apply Zlt_le_trans with (2 := H1). + change 0%Z with (0 * c)%Z. + apply Zmult_lt_compat_r; auto with zarith. + generalize (BigN.spec_eq_bool y1 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + generalize (BigN.spec_eq_bool y2 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + rewrite Zcompare_refl; auto. + rewrite Zmult_0_l; rewrite Zmult_1_r. + generalize (BigZ.spec_compare BigZ.zero x2); + case BigZ.compare; auto. + rewrite BigZ.spec_0; intros HH2; rewrite <- HH2; rewrite Zcompare_refl; auto. + generalize (BigN.spec_eq_bool y2 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + rewrite Zmult_0_l; rewrite Zmult_1_r. + generalize (BigZ.spec_compare x1 BigZ.zero)%bigZ; case BigZ.compare; + auto; rewrite BigZ.spec_0. + intros HH2; rewrite <- HH2; rewrite Zcompare_refl; auto. + set (a := BigZ.to_Z x1); set (b := BigZ.to_Z x2); + set (c1 := BigN.to_Z y1); set (c2 := BigN.to_Z y2). + fold c1 in HH; fold c2 in HH1. + assert (F1: (0 < c1)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos y1)); fold c1; auto. + intros H1; case HH; rewrite <- H1; auto. + assert (F2: (0 < c2)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos y2)); fold c2; auto. + intros H1; case HH1; rewrite <- H1; auto. + repeat rewrite Z2P_correct; auto. + generalize (BigZ.spec_cmp_sign x1 x2); case BigZ.cmp_sign. + intros _; generalize (BigZ.spec_compare (x1 * BigZ.Pos y2)%bigZ + (x2 * BigZ.Pos y1)%bigZ); + case BigZ.compare; rewrite BigZ.spec_mul; simpl; fold a b c1 c2; auto. + rewrite BigZ.spec_mul; simpl; fold a b c1; intros HH2; rewrite HH2; + rewrite Zcompare_refl; auto. + rewrite BigZ.spec_mul; simpl; auto. + rewrite BigZ.spec_mul; simpl; auto. + fold a b; intros (H1, H2); apply sym_equal; change (a * c2 < b * c1)%Z. + apply Zlt_le_trans with 0%Z. + change 0%Z with (0 * c2)%Z. + apply Zmult_lt_compat_r; auto with zarith. + apply Zmult_le_0_compat; auto with zarith. + fold a b; intros (H1, H2); apply sym_equal; change (a * c2 > b * c1)%Z. + apply Zlt_gt; apply Zlt_le_trans with 0%Z. + change 0%Z with (0 * c1)%Z. + apply Zmult_lt_compat_r; auto with zarith. + apply Zmult_le_0_compat; auto with zarith. + Qed. + + + Definition do_norm_n n := + match n with + | BigN.N0 _ => false + | BigN.N1 _ => false + | BigN.N2 _ => false + | BigN.N3 _ => false + | BigN.N4 _ => false + | BigN.N5 _ => false + | BigN.N6 _ => false + | _ => true + end. + + Definition do_norm_z z := + match z with + | BigZ.Pos n => do_norm_n n + | BigZ.Neg n => do_norm_n n + end. + +(* Je pense que cette fonction normalise bien ... *) + Definition norm n d: t := + if andb (do_norm_z n) (do_norm_n d) then + let gcd := BigN.gcd (BigZ.to_N n) d in + match BigN.compare BigN.one gcd with + | Lt => + let n := BigZ.div n (BigZ.Pos gcd) in + let d := BigN.div d gcd in + match BigN.compare d BigN.one with + | Gt => Qq n d + | Eq => Qz n + | Lt => zero + end + | Eq => Qq n d + | Gt => zero (* gcd = 0 => both numbers are 0 *) + end + else Qq n d. + + Theorem spec_norm: forall n q, + ([norm n q] == [Qq n q])%Q. + intros p q; unfold norm. + case do_norm_z; simpl andb. + 2: apply Qeq_refl. + case do_norm_n. + 2: apply Qeq_refl. + assert (Hp := BigN.spec_pos (BigZ.to_N p)). + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; auto; rewrite BigN.spec_1; rewrite BigN.spec_gcd; intros H1. + apply Qeq_refl. + generalize (BigN.spec_pos (q / BigN.gcd (BigZ.to_N p) q)%bigN). + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; auto; rewrite BigN.spec_1; rewrite BigN.spec_div; + rewrite BigN.spec_gcd; auto with zarith; intros H2 HH. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H3; simpl; + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; + auto with zarith. + generalize H2; rewrite H3; + rewrite Zdiv_0_l; auto with zarith. + generalize H1 H2 H3 (BigN.spec_pos q); clear H1 H2 H3. + rewrite spec_to_N. + set (a := (BigN.to_Z (BigZ.to_N p))). + set (b := (BigN.to_Z q)). + intros H1 H2 H3 H4; rewrite Z2P_correct; auto with zarith. + rewrite Zgcd_div_swap; auto with zarith. + rewrite H2; ring. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H3; simpl. + case H3. + generalize H1 H2 H3 HH; clear H1 H2 H3 HH. + set (a := (BigN.to_Z (BigZ.to_N p))). + set (b := (BigN.to_Z q)). + intros H1 H2 H3 HH. + rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto with zarith. + case (Zle_lt_or_eq _ _ HH); auto with zarith. + intros HH1; rewrite <- HH1; ring. + generalize (Zgcd_is_gcd a b); intros HH1; inversion HH1; auto. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_div; + rewrite BigN.spec_gcd; auto with zarith; intros H3. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H4. + case H3; rewrite H4; rewrite Zdiv_0_l; auto with zarith. + simpl. + assert (FF := BigN.spec_pos q). + rewrite Z2P_correct; auto with zarith. + rewrite <- BigN.spec_gcd; rewrite <- BigN.spec_div; auto with zarith. + rewrite Z2P_correct; auto with zarith. + rewrite BigN.spec_div; rewrite BigN.spec_gcd; auto with zarith. + simpl; rewrite BigZ.spec_div; simpl. + rewrite BigN.spec_gcd; auto with zarith. + generalize H1 H2 H3 H4 HH FF; clear H1 H2 H3 H4 HH FF. + set (a := (BigN.to_Z (BigZ.to_N p))). + set (b := (BigN.to_Z q)). + intros H1 H2 H3 H4 HH FF. + rewrite spec_to_N; fold a. + rewrite Zgcd_div_swap; auto with zarith. + rewrite BigN.spec_gcd; auto with zarith. + rewrite BigN.spec_div; + rewrite BigN.spec_gcd; auto with zarith. + rewrite BigN.spec_gcd; auto with zarith. + case (Zle_lt_or_eq _ _ + (BigN.spec_pos (BigN.gcd (BigZ.to_N p) q))); + rewrite BigN.spec_gcd; auto with zarith. + intros; apply False_ind; auto with zarith. + intros HH2; assert (FF1 := Zgcd_inv_0_l _ _ (sym_equal HH2)). + assert (FF2 := Zgcd_inv_0_l _ _ (sym_equal HH2)). + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H2; simpl. + rewrite spec_to_N. + rewrite FF2; ring. + Qed. + + Definition add (x y: t): t := + match x with + | Qz zx => + match y with + | Qz zy => Qz (BigZ.add zx zy) + | Qq ny dy => + if BigN.eq_bool dy BigN.zero then x + else Qq (BigZ.add (BigZ.mul zx (BigZ.Pos dy)) ny) dy + end + | Qq nx dx => + if BigN.eq_bool dx BigN.zero then y + else match y with + | Qz zy => Qq (BigZ.add nx (BigZ.mul zy (BigZ.Pos dx))) dx + | Qq ny dy => + if BigN.eq_bool dy BigN.zero then x + else + if BigN.eq_bool dx dy then + let n := BigZ.add nx ny in + Qq n dx + else + let n := BigZ.add (BigZ.mul nx (BigZ.Pos dy)) (BigZ.mul ny (BigZ.Pos dx)) in + let d := BigN.mul dx dy in + Qq n d + end + end. + + + + Theorem spec_add x y: + ([add x y] == [x] + [y])%Q. + intros [x | nx dx] [y | ny dy]; unfold Qplus; simpl. + rewrite BigZ.spec_add; repeat rewrite Zmult_1_r; auto. + intros; apply Qeq_refl; auto. + assert (F1:= BigN.spec_pos dy). + rewrite Zmult_1_r; red; simpl. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; + rewrite BigN.spec_0; intros HH; simpl; try ring. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; + rewrite BigN.spec_0; intros HH1; simpl; try ring. + case HH; auto. + rewrite Z2P_correct; auto with zarith. + rewrite BigZ.spec_add; rewrite BigZ.spec_mul; simpl; auto. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool; + rewrite BigN.spec_0; intros HH; simpl; try ring. + rewrite Zmult_1_r; apply Qeq_refl. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool; + rewrite BigN.spec_0; intros HH1; simpl; try ring. + case HH; auto. + rewrite Z2P_correct; auto with zarith. + rewrite BigZ.spec_add; rewrite BigZ.spec_mul; simpl; auto. + rewrite Zmult_1_r; rewrite Pmult_1_r. + apply Qeq_refl. + assert (F1:= BigN.spec_pos dx); auto with zarith. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + simpl. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH2. + apply Qeq_refl. + case HH2; auto. + simpl. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH2. + case HH2; auto. + case HH1; auto. + rewrite Zmult_1_r; apply Qeq_refl. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + simpl. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH2. + case HH; auto. + rewrite Zmult_1_r; rewrite Zplus_0_r; rewrite Pmult_1_r. + apply Qeq_refl. + simpl. + generalize (BigN.spec_eq_bool (dx * dy)%bigN BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_mul; + rewrite BigN.spec_0; intros HH2. + (case (Zmult_integral _ _ HH2); intros HH3); + [case HH| case HH1]; auto. + generalize (BigN.spec_eq_bool dx dy); + case BigN.eq_bool; intros HH3. + rewrite <- HH3. + assert (Fx: (0 < BigN.to_Z dx)%Z). + generalize (BigN.spec_pos dx); auto with zarith. + red; simpl. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH4. + case HH; auto. + simpl; rewrite Zpos_mult_morphism. + repeat rewrite Z2P_correct; auto with zarith. + rewrite BigZ.spec_add; repeat rewrite BigZ.spec_mul; simpl. + ring. + assert (Fx: (0 < BigN.to_Z dx)%Z). + generalize (BigN.spec_pos dx); auto with zarith. + assert (Fy: (0 < BigN.to_Z dy)%Z). + generalize (BigN.spec_pos dy); auto with zarith. + red; simpl; rewrite Zpos_mult_morphism. + repeat rewrite Z2P_correct; auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_mul; + rewrite BigN.spec_0; intros H3; simpl. + absurd (0 < 0)%Z; auto with zarith. + rewrite BigZ.spec_add; repeat rewrite BigZ.spec_mul; simpl. + repeat rewrite Z2P_correct; auto with zarith. + apply Zmult_lt_0_compat; auto. + Qed. + + Theorem spec_addc x y: + [[add x y]] = [[x]] + [[y]]. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] + [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_add; auto. + unfold Qcplus, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qplus_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition add_norm (x y: t): t := + match x with + | Qz zx => + match y with + | Qz zy => Qz (BigZ.add zx zy) + | Qq ny dy => + if BigN.eq_bool dy BigN.zero then x + else + norm (BigZ.add (BigZ.mul zx (BigZ.Pos dy)) ny) dy + end + | Qq nx dx => + if BigN.eq_bool dx BigN.zero then y + else match y with + | Qz zy => norm (BigZ.add nx (BigZ.mul zy (BigZ.Pos dx))) dx + | Qq ny dy => + if BigN.eq_bool dy BigN.zero then x + else + if BigN.eq_bool dx dy then + let n := BigZ.add nx ny in + norm n dx + else + let n := BigZ.add (BigZ.mul nx (BigZ.Pos dy)) (BigZ.mul ny (BigZ.Pos dx)) in + let d := BigN.mul dx dy in + norm n d + end + end. + + Theorem spec_add_norm x y: + ([add_norm x y] == [x] + [y])%Q. + intros x y; rewrite <- spec_add; auto. + case x; case y; clear x y; unfold add_norm, add. + intros; apply Qeq_refl. + intros p1 n p2. + generalize (BigN.spec_eq_bool n BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + apply Qeq_refl. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end. + simpl. + generalize (BigN.spec_eq_bool n BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + apply Qeq_refl. + apply Qeq_refl. + intros p1 p2 n. + generalize (BigN.spec_eq_bool n BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + apply Qeq_refl. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end. + apply Qeq_refl. + intros p1 q1 p2 q2. + generalize (BigN.spec_eq_bool q2 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + apply Qeq_refl. + generalize (BigN.spec_eq_bool q1 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH2. + apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; intros HH3; + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end; apply Qeq_refl. + Qed. + + Theorem spec_add_normc x y: + [[add_norm x y]] = [[x]] + [[y]]. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] + [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_add_norm; auto. + unfold Qcplus, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qplus_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition sub x y := add x (opp y). + + Theorem spec_sub x y: + ([sub x y] == [x] - [y])%Q. + intros x y; unfold sub; rewrite spec_add; auto. + rewrite spec_opp; ring. + Qed. + + Theorem spec_subc x y: [[sub x y]] = [[x]] - [[y]]. + intros x y; unfold sub; rewrite spec_addc; auto. + rewrite spec_oppc; ring. + Qed. + + Definition sub_norm x y := add_norm x (opp y). + + Theorem spec_sub_norm x y: + ([sub_norm x y] == [x] - [y])%Q. + intros x y; unfold sub_norm; rewrite spec_add_norm; auto. + rewrite spec_opp; ring. + Qed. + + Theorem spec_sub_normc x y: + [[sub_norm x y]] = [[x]] - [[y]]. + intros x y; unfold sub_norm; rewrite spec_add_normc; auto. + rewrite spec_oppc; ring. + Qed. + + Definition mul (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.mul zx zy) + | Qz zx, Qq ny dy => Qq (BigZ.mul zx ny) dy + | Qq nx dx, Qz zy => Qq (BigZ.mul nx zy) dx + | Qq nx dx, Qq ny dy => Qq (BigZ.mul nx ny) (BigN.mul dx dy) + end. + + Theorem spec_mul x y: ([mul x y] == [x] * [y])%Q. + intros [x | nx dx] [y | ny dy]; unfold Qmult; simpl. + rewrite BigZ.spec_mul; repeat rewrite Zmult_1_r; auto. + intros; apply Qeq_refl; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH1. + red; simpl; ring. + rewrite BigZ.spec_mul; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH1. + red; simpl; ring. + rewrite BigZ.spec_mul; rewrite Pmult_1_r. + apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; rewrite BigN.spec_mul; + intros HH1. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH2. + red; simpl; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH3. + red; simpl; ring. + case (Zmult_integral _ _ HH1); intros HH. + case HH2; auto. + case HH3; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH2. + case HH1; rewrite HH2; ring. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH3. + case HH1; rewrite HH3; ring. + rewrite BigZ.spec_mul. + assert (tmp: + (forall a b, 0 < a -> 0 < b -> Z2P (a * b) = (Z2P a * Z2P b)%positive)%Z). + intros [|a|a] [|b|b]; simpl; auto; intros; apply False_ind; auto with zarith. + rewrite tmp; auto. + apply Qeq_refl. + generalize (BigN.spec_pos dx); auto with zarith. + generalize (BigN.spec_pos dy); auto with zarith. + Qed. + + Theorem spec_mulc x y: + [[mul x y]] = [[x]] * [[y]]. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] * [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_mul; auto. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition mul_norm (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.mul zx zy) + | Qz zx, Qq ny dy => mul (Qz ny) (norm zx dy) + | Qq nx dx, Qz zy => mul (Qz nx) (norm zy dx) + | Qq nx dx, Qq ny dy => mul (norm nx dy) (norm ny dx) + end. + + Theorem spec_mul_norm x y: + ([mul_norm x y] == [x] * [y])%Q. + intros x y; rewrite <- spec_mul; auto. + unfold mul_norm; case x; case y; clear x y. + intros; apply Qeq_refl. + intros p1 n p2. + repeat rewrite spec_mul. + match goal with |- ?Z == _ => + match Z with context id [norm ?X ?Y] => + let y := context id [Qq X Y] in + apply Qeq_trans with y; [repeat apply Qmult_comp; + repeat apply Qplus_comp; repeat apply Qeq_refl; + apply spec_norm | idtac] + end + end. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH; simpl; ring. + intros p1 p2 n. + repeat rewrite spec_mul. + match goal with |- ?Z == _ => + match Z with context id [norm ?X ?Y] => + let y := context id [Qq X Y] in + apply Qeq_trans with y; [repeat apply Qmult_comp; + repeat apply Qplus_comp; repeat apply Qeq_refl; + apply spec_norm | idtac] + end + end. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH; simpl; try ring. + rewrite Pmult_1_r; auto. + intros p1 n1 p2 n2. + repeat rewrite spec_mul. + repeat match goal with |- ?Z == _ => + match Z with context id [norm ?X ?Y] => + let y := context id [Qq X Y] in + apply Qeq_trans with y; [repeat apply Qmult_comp; + repeat apply Qplus_comp; repeat apply Qeq_refl; + apply spec_norm | idtac] + end + end. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; simpl; try ring. + repeat rewrite Zpos_mult_morphism; ring. + Qed. + + Theorem spec_mul_normc x y: + [[mul_norm x y]] = [[x]] * [[y]]. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] * [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_mul_norm; auto. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition inv (x: t): t := + match x with + | Qz (BigZ.Pos n) => Qq BigZ.one n + | Qz (BigZ.Neg n) => Qq BigZ.minus_one n + | Qq (BigZ.Pos n) d => Qq (BigZ.Pos d) n + | Qq (BigZ.Neg n) d => Qq (BigZ.Neg d) n + end. + + + Theorem spec_inv x: + ([inv x] == /[x])%Q. + intros [ [x | x] | [nx | nx] dx]; unfold inv, Qinv; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; auto. + rewrite H1; apply Qeq_refl. + generalize H1 (BigN.spec_pos x); case (BigN.to_Z x); auto. + intros HH; case HH; auto. + intros; red; simpl; auto. + intros p _ HH; case HH; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; auto. + rewrite H1; apply Qeq_refl. + generalize H1 (BigN.spec_pos x); case (BigN.to_Z x); simpl; + auto. + intros HH; case HH; auto. + intros; red; simpl; auto. + intros p _ HH; case HH; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; simpl; auto. + apply Qeq_refl. + rewrite H1; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; simpl; auto. + rewrite H2; red; simpl; auto. + generalize H1 (BigN.spec_pos nx); case (BigN.to_Z nx); simpl; + auto. + intros HH; case HH; auto. + intros; red; simpl. + rewrite Zpos_mult_morphism. + rewrite Z2P_correct; auto. + generalize (BigN.spec_pos dx); auto with zarith. + intros p _ HH; case HH; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; simpl; auto. + apply Qeq_refl. + rewrite H1; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; simpl; auto. + rewrite H2; red; simpl; auto. + generalize H1 (BigN.spec_pos nx); case (BigN.to_Z nx); simpl; + auto. + intros HH; case HH; auto. + intros; red; simpl. + assert (tmp: forall x, Zneg x = Zopp (Zpos x)); auto. + rewrite tmp. + rewrite Zpos_mult_morphism. + rewrite Z2P_correct; auto. + ring. + generalize (BigN.spec_pos dx); auto with zarith. + intros p _ HH; case HH; auto. + Qed. + + Theorem spec_invc x: + [[inv x]] = /[[x]]. + intros x; unfold to_Qc. + apply trans_equal with (!! (/[x])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_inv; auto. + unfold Qcinv, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qinv_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition inv_norm (x: t): t := + match x with + | Qz (BigZ.Pos n) => + if BigN.eq_bool n BigN.zero then zero else Qq BigZ.one n + | Qz (BigZ.Neg n) => + if BigN.eq_bool n BigN.zero then zero else Qq BigZ.minus_one n + | Qq (BigZ.Pos n) d => + if BigN.eq_bool n BigN.zero then zero else Qq (BigZ.Pos d) n + | Qq (BigZ.Neg n) d => + if BigN.eq_bool n BigN.zero then zero else Qq (BigZ.Neg d) n + end. + + Theorem spec_inv_norm x: ([inv_norm x] == /[x])%Q. + intros x; rewrite <- spec_inv; generalize x; clear x. + intros [ [x | x] | [nx | nx] dx]; unfold inv_norm, inv; + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; try apply Qeq_refl; + red; simpl; + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; auto; + case H2; auto. + Qed. + + Theorem spec_inv_normc x: + [[inv_norm x]] = /[[x]]. + intros x; unfold to_Qc. + apply trans_equal with (!! (/[x])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_inv_norm; auto. + unfold Qcinv, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qinv_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + + Definition div x y := mul x (inv y). + + Theorem spec_div x y: ([div x y] == [x] / [y])%Q. + intros x y; unfold div; rewrite spec_mul; auto. + unfold Qdiv; apply Qmult_comp. + apply Qeq_refl. + apply spec_inv; auto. + Qed. + + Theorem spec_divc x y: [[div x y]] = [[x]] / [[y]]. + intros x y; unfold div; rewrite spec_mulc; auto. + unfold Qcdiv; apply f_equal2 with (f := Qcmult); auto. + apply spec_invc; auto. + Qed. + + Definition div_norm x y := mul_norm x (inv y). + + Theorem spec_div_norm x y: ([div_norm x y] == [x] / [y])%Q. + intros x y; unfold div_norm; rewrite spec_mul_norm; auto. + unfold Qdiv; apply Qmult_comp. + apply Qeq_refl. + apply spec_inv; auto. + Qed. + + Theorem spec_div_normc x y: [[div_norm x y]] = [[x]] / [[y]]. + intros x y; unfold div_norm; rewrite spec_mul_normc; auto. + unfold Qcdiv; apply f_equal2 with (f := Qcmult); auto. + apply spec_invc; auto. + Qed. + + + Definition square (x: t): t := + match x with + | Qz zx => Qz (BigZ.square zx) + | Qq nx dx => Qq (BigZ.square nx) (BigN.square dx) + end. + + + Theorem spec_square x: ([square x] == [x] ^ 2)%Q. + intros [ x | nx dx]; unfold square. + red; simpl; rewrite BigZ.spec_square; auto with zarith. + simpl Qpower. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H. + red; simpl. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_square; + intros H1. + case H1; rewrite H; auto. + red; simpl. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_square; + intros H1. + case H; case (Zmult_integral _ _ H1); auto. + simpl. + rewrite BigZ.spec_square. + rewrite Zpos_mult_morphism. + assert (tmp: + (forall a b, 0 < a -> 0 < b -> Z2P (a * b) = (Z2P a * Z2P b)%positive)%Z). + intros [|a|a] [|b|b]; simpl; auto; intros; apply False_ind; auto with zarith. + rewrite tmp; auto. + generalize (BigN.spec_pos dx); auto with zarith. + generalize (BigN.spec_pos dx); auto with zarith. + Qed. + + Theorem spec_squarec x: [[square x]] = [[x]]^2. + intros x; unfold to_Qc. + apply trans_equal with (!! ([x]^2)). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_square; auto. + simpl Qcpower. + replace (!! [x] * 1) with (!![x]); try ring. + simpl. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition power_pos (x: t) p: t := + match x with + | Qz zx => Qz (BigZ.power_pos zx p) + | Qq nx dx => Qq (BigZ.power_pos nx p) (BigN.power_pos dx p) + end. + + Theorem spec_power_pos x p: ([power_pos x p] == [x] ^ Zpos p)%Q. + Proof. + intros [x | nx dx] p; unfold power_pos. + unfold power_pos; red; simpl. + generalize (Qpower_decomp p (BigZ.to_Z x) 1). + unfold Qeq; simpl. + rewrite Zpower_pos_1_l; simpl Z2P. + rewrite Zmult_1_r. + intros H; rewrite H. + rewrite BigZ.spec_power_pos; simpl; ring. + simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_power_pos; intros H1. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H2. + elim p; simpl. + intros; red; simpl; auto. + intros p1 Hp1; rewrite <- Hp1; red; simpl; auto. + apply Qeq_refl. + case H2; generalize H1. + elim p; simpl. + intros p1 Hrec. + change (xI p1) with (1 + (xO p1))%positive. + rewrite Zpower_pos_is_exp; rewrite Zpower_pos_1_r. + intros HH; case (Zmult_integral _ _ HH); auto. + rewrite <- Pplus_diag. + rewrite Zpower_pos_is_exp. + intros HH1; case (Zmult_integral _ _ HH1); auto. + intros p1 Hrec. + rewrite <- Pplus_diag. + rewrite Zpower_pos_is_exp. + intros HH1; case (Zmult_integral _ _ HH1); auto. + rewrite Zpower_pos_1_r; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H2. + case H1; rewrite H2; auto. + simpl; rewrite Zpower_pos_0_l; auto. + assert (F1: (0 < BigN.to_Z dx)%Z). + generalize (BigN.spec_pos dx); auto with zarith. + assert (F2: (0 < BigN.to_Z dx ^ ' p)%Z). + unfold Zpower; apply Zpower_pos_pos; auto. + unfold power_pos; red; simpl. + generalize (Qpower_decomp p (BigZ.to_Z nx) + (Z2P (BigN.to_Z dx))). + unfold Qeq; simpl. + repeat rewrite Z2P_correct; auto. + unfold Qeq; simpl; intros HH. + rewrite HH. + rewrite BigZ.spec_power_pos; simpl; ring. + Qed. + + Theorem spec_power_posc x p: + [[power_pos x p]] = [[x]] ^ nat_of_P p. + intros x p; unfold to_Qc. + apply trans_equal with (!! ([x]^Zpos p)). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_power_pos; auto. + pattern p; apply Pind; clear p. + simpl; ring. + intros p Hrec. + rewrite nat_of_P_succ_morphism; simpl Qcpower. + rewrite <- Hrec. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; + unfold this. + apply Qred_complete. + assert (F: [x] ^ ' Psucc p == [x] * [x] ^ ' p). + simpl; case x; simpl; clear x Hrec. + intros x; simpl; repeat rewrite Qpower_decomp; simpl. + red; simpl; repeat rewrite Zpower_pos_1_l; simpl Z2P. + rewrite Pplus_one_succ_l. + rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r; auto. + intros nx dx. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + unfold Qpower_positive. + assert (tmp: forall p, pow_pos Qmult 0%Q p = 0%Q). + intros p1; elim p1; simpl; auto; clear p1. + intros p1 Hp1; rewrite Hp1; auto. + intros p1 Hp1; rewrite Hp1; auto. + repeat rewrite tmp; intros; red; simpl; auto. + intros H1. + assert (F1: (0 < BigN.to_Z dx)%Z). + generalize (BigN.spec_pos dx); auto with zarith. + simpl; repeat rewrite Qpower_decomp; simpl. + red; simpl; repeat rewrite Zpower_pos_1_l; simpl Z2P. + rewrite Pplus_one_succ_l. + rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r; auto. + repeat rewrite Zpos_mult_morphism. + repeat rewrite Z2P_correct; auto. + 2: apply Zpower_pos_pos; auto. + 2: apply Zpower_pos_pos; auto. + rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r; auto. + rewrite F. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + +End Qbi. diff --git a/theories/Numbers/Rational/BigQ/QifMake.v b/theories/Numbers/Rational/BigQ/QifMake.v new file mode 100644 index 00000000..1d8ecc94 --- /dev/null +++ b/theories/Numbers/Rational/BigQ/QifMake.v @@ -0,0 +1,979 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: QifMake.v 11027 2008-06-01 13:28:59Z letouzey $ i*) + +Require Import Bool. +Require Import ZArith. +Require Import Znumtheory. +Require Import BigNumPrelude. +Require Import Arith. +Require Export BigN. +Require Export BigZ. +Require Import QArith. +Require Import Qcanon. +Require Import Qpower. +Require Import QMake_base. + +Module Qif. + + Import BinInt. + Open Local Scope Q_scope. + Open Local Scope Qc_scope. + + (** The notation of a rational number is either an integer x, + interpreted as itself or a pair (x,y) of an integer x and a naturel + number y interpreted as x/y. The pairs (x,0) and (0,y) are all + interpreted as 0. *) + + Definition t := q_type. + + Definition zero: t := Qz BigZ.zero. + Definition one: t := Qz BigZ.one. + Definition minus_one: t := Qz BigZ.minus_one. + + Definition of_Z x: t := Qz (BigZ.of_Z x). + + Definition of_Q q: t := + match q with x # y => + Qq (BigZ.of_Z x) (BigN.of_N (Npos y)) + end. + + Definition of_Qc q := of_Q (this q). + + Definition to_Q (q: t) := + match q with + Qz x => BigZ.to_Z x # 1 + |Qq x y => if BigN.eq_bool y BigN.zero then 0%Q + else BigZ.to_Z x # Z2P (BigN.to_Z y) + end. + + Definition to_Qc q := !!(to_Q q). + + Notation "[[ x ]]" := (to_Qc x). + + Notation "[ x ]" := (to_Q x). + + Theorem spec_to_Q: forall q: Q, [of_Q q] = q. + intros (x,y); simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + rewrite BigN.spec_of_pos; intros HH; discriminate HH. + rewrite BigZ.spec_of_Z; simpl. + rewrite (BigN.spec_of_pos); auto. + Qed. + + Theorem spec_to_Qc: forall q, [[of_Qc q]] = q. + intros (x, Hx); unfold of_Qc, to_Qc; simpl. + apply Qc_decomp; simpl. + intros; rewrite spec_to_Q; auto. + Qed. + + Definition opp (x: t): t := + match x with + | Qz zx => Qz (BigZ.opp zx) + | Qq nx dx => Qq (BigZ.opp nx) dx + end. + + Theorem spec_opp: forall q, ([opp q] = -[q])%Q. + intros [z | x y]; simpl. + rewrite BigZ.spec_opp; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + rewrite BigZ.spec_opp; auto. + Qed. + + Theorem spec_oppc: forall q, [[opp q]] = -[[q]]. + intros q; unfold Qcopp, to_Qc, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + rewrite spec_opp. + rewrite <- Qred_opp. + rewrite Qred_involutive; auto. + Qed. + + Definition compare (x y: t) := + match x, y with + | Qz zx, Qz zy => BigZ.compare zx zy + | Qz zx, Qq ny dy => + if BigN.eq_bool dy BigN.zero then BigZ.compare zx BigZ.zero + else BigZ.compare (BigZ.mul zx (BigZ.Pos dy)) ny + | Qq nx dx, Qz zy => + if BigN.eq_bool dx BigN.zero then BigZ.compare BigZ.zero zy + else BigZ.compare nx (BigZ.mul zy (BigZ.Pos dx)) + | Qq nx dx, Qq ny dy => + match BigN.eq_bool dx BigN.zero, BigN.eq_bool dy BigN.zero with + | true, true => Eq + | true, false => BigZ.compare BigZ.zero ny + | false, true => BigZ.compare nx BigZ.zero + | false, false => BigZ.compare (BigZ.mul nx (BigZ.Pos dy)) (BigZ.mul ny (BigZ.Pos dx)) + end + end. + + Theorem spec_compare: forall q1 q2, + compare q1 q2 = ([q1] ?= [q2])%Q. + intros [z1 | x1 y1] [z2 | x2 y2]; + unfold Qcompare, compare, to_Q, Qnum, Qden. + repeat rewrite Zmult_1_r. + generalize (BigZ.spec_compare z1 z2); case BigZ.compare; intros H; auto. + rewrite H; rewrite Zcompare_refl; auto. + rewrite Zmult_1_r. + generalize (BigN.spec_eq_bool y2 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + rewrite Zmult_1_r; generalize (BigZ.spec_compare z1 BigZ.zero); + case BigZ.compare; auto. + rewrite BigZ.spec_0; intros HH1; rewrite HH1; rewrite Zcompare_refl; auto. + rewrite Z2P_correct; auto with zarith. + 2: generalize (BigN.spec_pos y2); auto with zarith. + generalize (BigZ.spec_compare (z1 * BigZ.Pos y2) x2)%bigZ; case BigZ.compare; + rewrite BigZ.spec_mul; simpl; intros H; apply sym_equal; auto. + rewrite H; rewrite Zcompare_refl; auto. + generalize (BigN.spec_eq_bool y1 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + rewrite Zmult_0_l; rewrite Zmult_1_r. + generalize (BigZ.spec_compare BigZ.zero z2); + case BigZ.compare; auto. + rewrite BigZ.spec_0; intros HH1; rewrite <- HH1; rewrite Zcompare_refl; auto. + rewrite Z2P_correct; auto with zarith. + 2: generalize (BigN.spec_pos y1); auto with zarith. + rewrite Zmult_1_r. + generalize (BigZ.spec_compare x1 (z2 * BigZ.Pos y1))%bigZ; case BigZ.compare; + rewrite BigZ.spec_mul; simpl; intros H; apply sym_equal; auto. + rewrite H; rewrite Zcompare_refl; auto. + generalize (BigN.spec_eq_bool y1 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + generalize (BigN.spec_eq_bool y2 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + rewrite Zcompare_refl; auto. + rewrite Zmult_0_l; rewrite Zmult_1_r. + generalize (BigZ.spec_compare BigZ.zero x2); + case BigZ.compare; auto. + rewrite BigZ.spec_0; intros HH2; rewrite <- HH2; rewrite Zcompare_refl; auto. + generalize (BigN.spec_eq_bool y2 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + rewrite Zmult_0_l; rewrite Zmult_1_r. + generalize (BigZ.spec_compare x1 BigZ.zero)%bigZ; case BigZ.compare; + auto; rewrite BigZ.spec_0. + intros HH2; rewrite <- HH2; rewrite Zcompare_refl; auto. + repeat rewrite Z2P_correct. + 2: generalize (BigN.spec_pos y1); auto with zarith. + 2: generalize (BigN.spec_pos y2); auto with zarith. + generalize (BigZ.spec_compare (x1 * BigZ.Pos y2) + (x2 * BigZ.Pos y1))%bigZ; case BigZ.compare; + repeat rewrite BigZ.spec_mul; simpl; intros H; apply sym_equal; auto. + rewrite H; rewrite Zcompare_refl; auto. + Qed. + + Definition do_norm_n n := + match n with + | BigN.N0 _ => false + | BigN.N1 _ => false + | BigN.N2 _ => false + | BigN.N3 _ => false + | BigN.N4 _ => false + | BigN.N5 _ => false + | BigN.N6 _ => false + | _ => true + end. + + Definition do_norm_z z := + match z with + | BigZ.Pos n => do_norm_n n + | BigZ.Neg n => do_norm_n n + end. + +(* Je pense que cette fonction normalise bien ... *) + Definition norm n d: t := + if andb (do_norm_z n) (do_norm_n d) then + let gcd := BigN.gcd (BigZ.to_N n) d in + match BigN.compare BigN.one gcd with + | Lt => + let n := BigZ.div n (BigZ.Pos gcd) in + let d := BigN.div d gcd in + match BigN.compare d BigN.one with + | Gt => Qq n d + | Eq => Qz n + | Lt => zero + end + | Eq => Qq n d + | Gt => zero (* gcd = 0 => both numbers are 0 *) + end + else Qq n d. + + Theorem spec_norm: forall n q, + ([norm n q] == [Qq n q])%Q. + intros p q; unfold norm. + case do_norm_z; simpl andb. + 2: apply Qeq_refl. + case do_norm_n. + 2: apply Qeq_refl. + assert (Hp := BigN.spec_pos (BigZ.to_N p)). + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; auto; rewrite BigN.spec_1; rewrite BigN.spec_gcd; intros H1. + apply Qeq_refl. + generalize (BigN.spec_pos (q / BigN.gcd (BigZ.to_N p) q)%bigN). + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; auto; rewrite BigN.spec_1; rewrite BigN.spec_div; + rewrite BigN.spec_gcd; auto with zarith; intros H2 HH. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H3; simpl; + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; + auto with zarith. + generalize H2; rewrite H3; + rewrite Zdiv_0_l; auto with zarith. + generalize H1 H2 H3 (BigN.spec_pos q); clear H1 H2 H3. + rewrite spec_to_N. + set (a := (BigN.to_Z (BigZ.to_N p))). + set (b := (BigN.to_Z q)). + intros H1 H2 H3 H4; rewrite Z2P_correct; auto with zarith. + rewrite Zgcd_div_swap; auto with zarith. + rewrite H2; ring. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H3; simpl. + case H3. + generalize H1 H2 H3 HH; clear H1 H2 H3 HH. + set (a := (BigN.to_Z (BigZ.to_N p))). + set (b := (BigN.to_Z q)). + intros H1 H2 H3 HH. + rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto with zarith. + case (Zle_lt_or_eq _ _ HH); auto with zarith. + intros HH1; rewrite <- HH1; ring. + generalize (Zgcd_is_gcd a b); intros HH1; inversion HH1; auto. + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_div; + rewrite BigN.spec_gcd; auto with zarith; intros H3. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H4. + case H3; rewrite H4; rewrite Zdiv_0_l; auto with zarith. + simpl. + assert (FF := BigN.spec_pos q). + rewrite Z2P_correct; auto with zarith. + rewrite <- BigN.spec_gcd; rewrite <- BigN.spec_div; auto with zarith. + rewrite Z2P_correct; auto with zarith. + rewrite BigN.spec_div; rewrite BigN.spec_gcd; auto with zarith. + simpl; rewrite BigZ.spec_div; simpl. + rewrite BigN.spec_gcd; auto with zarith. + generalize H1 H2 H3 H4 HH FF; clear H1 H2 H3 H4 HH FF. + set (a := (BigN.to_Z (BigZ.to_N p))). + set (b := (BigN.to_Z q)). + intros H1 H2 H3 H4 HH FF. + rewrite spec_to_N; fold a. + rewrite Zgcd_div_swap; auto with zarith. + rewrite BigN.spec_gcd; auto with zarith. + rewrite BigN.spec_div; + rewrite BigN.spec_gcd; auto with zarith. + rewrite BigN.spec_gcd; auto with zarith. + case (Zle_lt_or_eq _ _ + (BigN.spec_pos (BigN.gcd (BigZ.to_N p) q))); + rewrite BigN.spec_gcd; auto with zarith. + intros; apply False_ind; auto with zarith. + intros HH2; assert (FF1 := Zgcd_inv_0_l _ _ (sym_equal HH2)). + assert (FF2 := Zgcd_inv_0_l _ _ (sym_equal HH2)). + red; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H2; simpl. + rewrite spec_to_N. + rewrite FF2; ring. + Qed. + + + Definition add (x y: t): t := + match x with + | Qz zx => + match y with + | Qz zy => Qz (BigZ.add zx zy) + | Qq ny dy => + if BigN.eq_bool dy BigN.zero then x + else Qq (BigZ.add (BigZ.mul zx (BigZ.Pos dy)) ny) dy + end + | Qq nx dx => + if BigN.eq_bool dx BigN.zero then y + else match y with + | Qz zy => Qq (BigZ.add nx (BigZ.mul zy (BigZ.Pos dx))) dx + | Qq ny dy => + if BigN.eq_bool dy BigN.zero then x + else + let n := BigZ.add (BigZ.mul nx (BigZ.Pos dy)) (BigZ.mul ny (BigZ.Pos dx)) in + let d := BigN.mul dx dy in + Qq n d + end + end. + + + Theorem spec_add x y: + ([add x y] == [x] + [y])%Q. + intros [x | nx dx] [y | ny dy]; unfold Qplus; simpl. + rewrite BigZ.spec_add; repeat rewrite Zmult_1_r; auto. + intros; apply Qeq_refl; auto. + assert (F1:= BigN.spec_pos dy). + rewrite Zmult_1_r; red; simpl. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; + rewrite BigN.spec_0; intros HH; simpl; try ring. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; + rewrite BigN.spec_0; intros HH1; simpl; try ring. + case HH; auto. + rewrite Z2P_correct; auto with zarith. + rewrite BigZ.spec_add; rewrite BigZ.spec_mul; simpl; auto. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool; + rewrite BigN.spec_0; intros HH; simpl; try ring. + rewrite Zmult_1_r; apply Qeq_refl. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool; + rewrite BigN.spec_0; intros HH1; simpl; try ring. + case HH; auto. + rewrite Z2P_correct; auto with zarith. + rewrite BigZ.spec_add; rewrite BigZ.spec_mul; simpl; auto. + rewrite Zmult_1_r; rewrite Pmult_1_r. + apply Qeq_refl. + assert (F1:= BigN.spec_pos dx); auto with zarith. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + simpl. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH2. + apply Qeq_refl. + case HH2; auto. + simpl. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH2. + case HH2; auto. + case HH1; auto. + rewrite Zmult_1_r; apply Qeq_refl. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + simpl. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH2. + case HH; auto. + rewrite Zmult_1_r; rewrite Zplus_0_r; rewrite Pmult_1_r. + apply Qeq_refl. + simpl. + generalize (BigN.spec_eq_bool (dx * dy)%bigN BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_mul; + rewrite BigN.spec_0; intros HH2. + (case (Zmult_integral _ _ HH2); intros HH3); + [case HH| case HH1]; auto. + rewrite BigZ.spec_add; repeat rewrite BigZ.spec_mul; simpl. + assert (Fx: (0 < BigN.to_Z dx)%Z). + generalize (BigN.spec_pos dx); auto with zarith. + assert (Fy: (0 < BigN.to_Z dy)%Z). + generalize (BigN.spec_pos dy); auto with zarith. + red; simpl; rewrite Zpos_mult_morphism. + repeat rewrite Z2P_correct; auto with zarith. + apply Zmult_lt_0_compat; auto. + Qed. + + Theorem spec_addc x y: + [[add x y]] = [[x]] + [[y]]. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] + [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_add; auto. + unfold Qcplus, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qplus_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition add_norm (x y: t): t := + match x with + | Qz zx => + match y with + | Qz zy => Qz (BigZ.add zx zy) + | Qq ny dy => + if BigN.eq_bool dy BigN.zero then x + else norm (BigZ.add (BigZ.mul zx (BigZ.Pos dy)) ny) dy + end + | Qq nx dx => + if BigN.eq_bool dx BigN.zero then y + else match y with + | Qz zy => norm (BigZ.add nx (BigZ.mul zy (BigZ.Pos dx))) dx + | Qq ny dy => + if BigN.eq_bool dy BigN.zero then x + else + let n := BigZ.add (BigZ.mul nx (BigZ.Pos dy)) (BigZ.mul ny (BigZ.Pos dx)) in + let d := BigN.mul dx dy in + norm n d + end + end. + + Theorem spec_add_norm x y: + ([add_norm x y] == [x] + [y])%Q. + intros x y; rewrite <- spec_add; auto. + case x; case y; clear x y; unfold add_norm, add. + intros; apply Qeq_refl. + intros p1 n p2. + generalize (BigN.spec_eq_bool n BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + apply Qeq_refl. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end. + simpl. + generalize (BigN.spec_eq_bool n BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + apply Qeq_refl. + apply Qeq_refl. + intros p1 p2 n. + generalize (BigN.spec_eq_bool n BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH. + apply Qeq_refl. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end. + apply Qeq_refl. + intros p1 q1 p2 q2. + generalize (BigN.spec_eq_bool q2 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH1. + apply Qeq_refl. + generalize (BigN.spec_eq_bool q1 BigN.zero); + case BigN.eq_bool; rewrite BigN.spec_0; intros HH2. + apply Qeq_refl. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end. + apply Qeq_refl. + Qed. + + Theorem spec_add_normc x y: + [[add_norm x y]] = [[x]] + [[y]]. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] + [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_add_norm; auto. + unfold Qcplus, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qplus_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition sub x y := add x (opp y). + + + Theorem spec_sub x y: + ([sub x y] == [x] - [y])%Q. + intros x y; unfold sub; rewrite spec_add; auto. + rewrite spec_opp; ring. + Qed. + + Theorem spec_subc x y: [[sub x y]] = [[x]] - [[y]]. + intros x y; unfold sub; rewrite spec_addc; auto. + rewrite spec_oppc; ring. + Qed. + + Definition sub_norm x y := add_norm x (opp y). + + Theorem spec_sub_norm x y: + ([sub_norm x y] == [x] - [y])%Q. + intros x y; unfold sub_norm; rewrite spec_add_norm; auto. + rewrite spec_opp; ring. + Qed. + + Theorem spec_sub_normc x y: + [[sub_norm x y]] = [[x]] - [[y]]. + intros x y; unfold sub_norm; rewrite spec_add_normc; auto. + rewrite spec_oppc; ring. + Qed. + + Definition mul (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.mul zx zy) + | Qz zx, Qq ny dy => Qq (BigZ.mul zx ny) dy + | Qq nx dx, Qz zy => Qq (BigZ.mul nx zy) dx + | Qq nx dx, Qq ny dy => Qq (BigZ.mul nx ny) (BigN.mul dx dy) + end. + + + Theorem spec_mul x y: ([mul x y] == [x] * [y])%Q. + intros [x | nx dx] [y | ny dy]; unfold Qmult; simpl. + rewrite BigZ.spec_mul; repeat rewrite Zmult_1_r; auto. + intros; apply Qeq_refl; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH1. + red; simpl; ring. + rewrite BigZ.spec_mul; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH1. + red; simpl; ring. + rewrite BigZ.spec_mul; rewrite Pmult_1_r. + apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; rewrite BigN.spec_mul; + intros HH1. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH2. + red; simpl; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH3. + red; simpl; ring. + case (Zmult_integral _ _ HH1); intros HH. + case HH2; auto. + case HH3; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH2. + case HH1; rewrite HH2; ring. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros HH3. + case HH1; rewrite HH3; ring. + rewrite BigZ.spec_mul. + assert (tmp: + (forall a b, 0 < a -> 0 < b -> Z2P (a * b) = (Z2P a * Z2P b)%positive)%Z). + intros [|a|a] [|b|b]; simpl; auto; intros; apply False_ind; auto with zarith. + rewrite tmp; auto. + apply Qeq_refl. + generalize (BigN.spec_pos dx); auto with zarith. + generalize (BigN.spec_pos dy); auto with zarith. + Qed. + + Theorem spec_mulc x y: + [[mul x y]] = [[x]] * [[y]]. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] * [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_mul; auto. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + + Definition mul_norm (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.mul zx zy) + | Qz zx, Qq ny dy => norm (BigZ.mul zx ny) dy + | Qq nx dx, Qz zy => norm (BigZ.mul nx zy) dx + | Qq nx dx, Qq ny dy => norm (BigZ.mul nx ny) (BigN.mul dx dy) + end. + + Theorem spec_mul_norm x y: + ([mul_norm x y] == [x] * [y])%Q. + intros x y; rewrite <- spec_mul; auto. + unfold mul_norm, mul; case x; case y; clear x y. + intros; apply Qeq_refl. + intros p1 n p2. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end; apply Qeq_refl. + intros p1 p2 n. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end; apply Qeq_refl. + intros p1 n1 p2 n2. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end; apply Qeq_refl. + Qed. + + Theorem spec_mul_normc x y: + [[mul_norm x y]] = [[x]] * [[y]]. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] * [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_mul_norm; auto. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + + + Definition inv (x: t): t := + match x with + | Qz (BigZ.Pos n) => Qq BigZ.one n + | Qz (BigZ.Neg n) => Qq BigZ.minus_one n + | Qq (BigZ.Pos n) d => Qq (BigZ.Pos d) n + | Qq (BigZ.Neg n) d => Qq (BigZ.Neg d) n + end. + + Theorem spec_inv x: + ([inv x] == /[x])%Q. + intros [ [x | x] | [nx | nx] dx]; unfold inv, Qinv; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; auto. + rewrite H1; apply Qeq_refl. + generalize H1 (BigN.spec_pos x); case (BigN.to_Z x); auto. + intros HH; case HH; auto. + intros; red; simpl; auto. + intros p _ HH; case HH; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; auto. + rewrite H1; apply Qeq_refl. + generalize H1 (BigN.spec_pos x); case (BigN.to_Z x); simpl; + auto. + intros HH; case HH; auto. + intros; red; simpl; auto. + intros p _ HH; case HH; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; simpl; auto. + apply Qeq_refl. + rewrite H1; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; simpl; auto. + rewrite H2; red; simpl; auto. + generalize H1 (BigN.spec_pos nx); case (BigN.to_Z nx); simpl; + auto. + intros HH; case HH; auto. + intros; red; simpl. + rewrite Zpos_mult_morphism. + rewrite Z2P_correct; auto. + generalize (BigN.spec_pos dx); auto with zarith. + intros p _ HH; case HH; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; simpl; auto. + apply Qeq_refl. + rewrite H1; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H2; simpl; auto. + rewrite H2; red; simpl; auto. + generalize H1 (BigN.spec_pos nx); case (BigN.to_Z nx); simpl; + auto. + intros HH; case HH; auto. + intros; red; simpl. + assert (tmp: forall x, Zneg x = Zopp (Zpos x)); auto. + rewrite tmp. + rewrite Zpos_mult_morphism. + rewrite Z2P_correct; auto. + ring. + generalize (BigN.spec_pos dx); auto with zarith. + intros p _ HH; case HH; auto. + Qed. + + Theorem spec_invc x: + [[inv x]] = /[[x]]. + intros x; unfold to_Qc. + apply trans_equal with (!! (/[x])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_inv; auto. + unfold Qcinv, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qinv_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + +Definition inv_norm (x: t): t := + match x with + | Qz (BigZ.Pos n) => + match BigN.compare n BigN.one with + Gt => Qq BigZ.one n + | _ => x + end + | Qz (BigZ.Neg n) => + match BigN.compare n BigN.one with + Gt => Qq BigZ.minus_one n + | _ => x + end + | Qq (BigZ.Pos n) d => + match BigN.compare n BigN.one with + Gt => Qq (BigZ.Pos d) n + | Eq => Qz (BigZ.Pos d) + | Lt => Qz (BigZ.zero) + end + | Qq (BigZ.Neg n) d => + match BigN.compare n BigN.one with + Gt => Qq (BigZ.Neg d) n + | Eq => Qz (BigZ.Neg d) + | Lt => Qz (BigZ.zero) + end + end. + + Theorem spec_inv_norm x: ([inv_norm x] == /[x])%Q. + intros [ [x | x] | [nx | nx] dx]; unfold inv_norm, Qinv. + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; rewrite BigN.spec_1; intros H. + simpl; rewrite H; apply Qeq_refl. + case (Zle_lt_or_eq _ _ (BigN.spec_pos x)); simpl. + generalize H; case BigN.to_Z. + intros _ HH; discriminate HH. + intros p; case p; auto. + intros p1 HH; discriminate HH. + intros p1 HH; discriminate HH. + intros HH; discriminate HH. + intros p _ HH; discriminate HH. + intros HH; rewrite <- HH. + apply Qeq_refl. + generalize H; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1. + rewrite H1; intros HH; discriminate. + generalize H; case BigN.to_Z. + intros HH; discriminate HH. + intros; red; simpl; auto. + intros p HH; discriminate HH. + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; rewrite BigN.spec_1; intros H. + simpl; rewrite H; apply Qeq_refl. + case (Zle_lt_or_eq _ _ (BigN.spec_pos x)); simpl. + generalize H; case BigN.to_Z. + intros _ HH; discriminate HH. + intros p; case p; auto. + intros p1 HH; discriminate HH. + intros p1 HH; discriminate HH. + intros HH; discriminate HH. + intros p _ HH; discriminate HH. + intros HH; rewrite <- HH. + apply Qeq_refl. + generalize H; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1. + rewrite H1; intros HH; discriminate. + generalize H; case BigN.to_Z. + intros HH; discriminate HH. + intros; red; simpl; auto. + intros p HH; discriminate HH. + simpl Qnum. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; simpl. + case BigN.compare; red; simpl; auto. + rewrite H1; auto. + case BigN.eq_bool; auto. + simpl; rewrite H1; auto. + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; rewrite BigN.spec_1; intros H2. + rewrite H2. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H3. + case H1; auto. + red; simpl. + rewrite Zmult_1_r; rewrite Pmult_1_r; rewrite Z2P_correct; auto. + generalize (BigN.spec_pos dx); auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H3. + case H1; auto. + generalize H2 (BigN.spec_pos nx); case (BigN.to_Z nx). + intros; apply Qeq_refl. + intros p; case p; clear p. + intros p HH; discriminate HH. + intros p HH; discriminate HH. + intros HH; discriminate HH. + intros p _ HH; case HH; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H3. + case H1; auto. + simpl; generalize H2; case (BigN.to_Z nx). + intros HH; discriminate HH. + intros p Hp. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H4. + rewrite H4 in H2; discriminate H2. + red; simpl. + rewrite Zpos_mult_morphism. + rewrite Z2P_correct; auto. + generalize (BigN.spec_pos dx); auto with zarith. + intros p HH; discriminate HH. + simpl Qnum. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1; simpl. + case BigN.compare; red; simpl; auto. + rewrite H1; auto. + case BigN.eq_bool; auto. + simpl; rewrite H1; auto. + match goal with |- context[BigN.compare ?X ?Y] => + generalize (BigN.spec_compare X Y); case BigN.compare + end; rewrite BigN.spec_1; intros H2. + rewrite H2. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H3. + case H1; auto. + red; simpl. + assert (tmp: forall x, Zneg x = Zopp (Zpos x)); auto. + rewrite tmp. + rewrite Zmult_1_r; rewrite Pmult_1_r; rewrite Z2P_correct; auto. + generalize (BigN.spec_pos dx); auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H3. + case H1; auto. + generalize H2 (BigN.spec_pos nx); case (BigN.to_Z nx). + intros; apply Qeq_refl. + intros p; case p; clear p. + intros p HH; discriminate HH. + intros p HH; discriminate HH. + intros HH; discriminate HH. + intros p _ HH; case HH; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H3. + case H1; auto. + simpl; generalize H2; case (BigN.to_Z nx). + intros HH; discriminate HH. + intros p Hp. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H4. + rewrite H4 in H2; discriminate H2. + red; simpl. + assert (tmp: forall x, Zneg x = Zopp (Zpos x)); auto. + rewrite tmp. + rewrite Zpos_mult_morphism. + rewrite Z2P_correct; auto. + ring. + generalize (BigN.spec_pos dx); auto with zarith. + intros p HH; discriminate HH. + Qed. + + Theorem spec_inv_normc x: + [[inv_norm x]] = /[[x]]. + intros x; unfold to_Qc. + apply trans_equal with (!! (/[x])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_inv_norm; auto. + unfold Qcinv, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qinv_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + + Definition div x y := mul x (inv y). + + Theorem spec_div x y: ([div x y] == [x] / [y])%Q. + intros x y; unfold div; rewrite spec_mul; auto. + unfold Qdiv; apply Qmult_comp. + apply Qeq_refl. + apply spec_inv; auto. + Qed. + + Theorem spec_divc x y: [[div x y]] = [[x]] / [[y]]. + intros x y; unfold div; rewrite spec_mulc; auto. + unfold Qcdiv; apply f_equal2 with (f := Qcmult); auto. + apply spec_invc; auto. + Qed. + + Definition div_norm x y := mul_norm x (inv y). + + Theorem spec_div_norm x y: ([div_norm x y] == [x] / [y])%Q. + intros x y; unfold div_norm; rewrite spec_mul_norm; auto. + unfold Qdiv; apply Qmult_comp. + apply Qeq_refl. + apply spec_inv; auto. + Qed. + + Theorem spec_div_normc x y: [[div_norm x y]] = [[x]] / [[y]]. + intros x y; unfold div_norm; rewrite spec_mul_normc; auto. + unfold Qcdiv; apply f_equal2 with (f := Qcmult); auto. + apply spec_invc; auto. + Qed. + + + Definition square (x: t): t := + match x with + | Qz zx => Qz (BigZ.square zx) + | Qq nx dx => Qq (BigZ.square nx) (BigN.square dx) + end. + + Theorem spec_square x: ([square x] == [x] ^ 2)%Q. + intros [ x | nx dx]; unfold square. + red; simpl; rewrite BigZ.spec_square; auto with zarith. + simpl Qpower. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; intros H. + red; simpl. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_square; + intros H1. + case H1; rewrite H; auto. + red; simpl. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_square; + intros H1. + case H; case (Zmult_integral _ _ H1); auto. + simpl. + rewrite BigZ.spec_square. + rewrite Zpos_mult_morphism. + assert (tmp: + (forall a b, 0 < a -> 0 < b -> Z2P (a * b) = (Z2P a * Z2P b)%positive)%Z). + intros [|a|a] [|b|b]; simpl; auto; intros; apply False_ind; auto with zarith. + rewrite tmp; auto. + generalize (BigN.spec_pos dx); auto with zarith. + generalize (BigN.spec_pos dx); auto with zarith. + Qed. + + Theorem spec_squarec x: [[square x]] = [[x]]^2. + intros x; unfold to_Qc. + apply trans_equal with (!! ([x]^2)). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_square; auto. + simpl Qcpower. + replace (!! [x] * 1) with (!![x]); try ring. + simpl. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + +End Qif. diff --git a/theories/Numbers/Rational/BigQ/QpMake.v b/theories/Numbers/Rational/BigQ/QpMake.v new file mode 100644 index 00000000..ac3ca47a --- /dev/null +++ b/theories/Numbers/Rational/BigQ/QpMake.v @@ -0,0 +1,901 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: QpMake.v 11027 2008-06-01 13:28:59Z letouzey $ i*) + +Require Import Bool. +Require Import ZArith. +Require Import Znumtheory. +Require Import BigNumPrelude. +Require Import Arith. +Require Export BigN. +Require Export BigZ. +Require Import QArith. +Require Import Qcanon. +Require Import Qpower. +Require Import QMake_base. + +Notation Nspec_lt := BigNAxiomsMod.NZOrdAxiomsMod.spec_lt. +Notation Nspec_le := BigNAxiomsMod.NZOrdAxiomsMod.spec_le. + +Module Qp. + + (** The notation of a rational number is either an integer x, + interpreted as itself or a pair (x,y) of an integer x and a naturel + number y interpreted as x/(y+1). *) + + Definition t := q_type. + + Definition zero: t := Qz BigZ.zero. + Definition one: t := Qz BigZ.one. + Definition minus_one: t := Qz BigZ.minus_one. + + Definition of_Z x: t := Qz (BigZ.of_Z x). + + Definition d_to_Z d := BigZ.Pos (BigN.succ d). + + Definition of_Q q: t := + match q with x # y => + Qq (BigZ.of_Z x) (BigN.pred (BigN.of_N (Npos y))) + end. + + Definition of_Qc q := of_Q (this q). + + Definition to_Q (q: t) := + match q with + Qz x => BigZ.to_Z x # 1 + |Qq x y => BigZ.to_Z x # Z2P (BigN.to_Z (BigN.succ y)) + end. + + Definition to_Qc q := !!(to_Q q). + + Notation "[[ x ]]" := (to_Qc x). + + Notation "[ x ]" := (to_Q x). + + Theorem spec_to_Q: forall q: Q, [of_Q q] = q. + intros (x,y); simpl. + rewrite BigZ.spec_of_Z; auto. + rewrite BigN.spec_succ; simpl. simpl. + rewrite BigN.spec_pred; rewrite (BigN.spec_of_pos). + replace (Zpos y - 1 + 1)%Z with (Zpos y); auto; ring. + red; auto. + Qed. + + Theorem spec_to_Qc: forall q, [[of_Qc q]] = q. + intros (x, Hx); unfold of_Qc, to_Qc; simpl. + apply Qc_decomp; simpl. + intros; rewrite spec_to_Q; auto. + Qed. + + Definition opp (x: t): t := + match x with + | Qz zx => Qz (BigZ.opp zx) + | Qq nx dx => Qq (BigZ.opp nx) dx + end. + + + Theorem spec_opp: forall q, ([opp q] = -[q])%Q. + intros [z | x y]; simpl. + rewrite BigZ.spec_opp; auto. + rewrite BigZ.spec_opp; auto. + Qed. + + + Theorem spec_oppc: forall q, [[opp q]] = -[[q]]. + intros q; unfold Qcopp, to_Qc, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + rewrite spec_opp. + rewrite <- Qred_opp. + rewrite Qred_involutive; auto. + Qed. + + Definition compare (x y: t) := + match x, y with + | Qz zx, Qz zy => BigZ.compare zx zy + | Qz zx, Qq ny dy => BigZ.compare (BigZ.mul zx (d_to_Z dy)) ny + | Qq nx dy, Qz zy => BigZ.compare nx (BigZ.mul zy (d_to_Z dy)) + | Qq nx dx, Qq ny dy => + BigZ.compare (BigZ.mul nx (d_to_Z dy)) (BigZ.mul ny (d_to_Z dx)) + end. + + Theorem spec_compare: forall q1 q2, + compare q1 q2 = ([q1] ?= [q2])%Q. + intros [z1 | x1 y1] [z2 | x2 y2]; unfold Qcompare; simpl. + repeat rewrite Zmult_1_r. + generalize (BigZ.spec_compare z1 z2); case BigZ.compare; intros H; auto. + rewrite H; rewrite Zcompare_refl; auto. + rewrite Zmult_1_r. + rewrite BigN.spec_succ. + rewrite Z2P_correct; auto with zarith. + 2: generalize (BigN.spec_pos y2); auto with zarith. + generalize (BigZ.spec_compare (z1 * d_to_Z y2) x2)%bigZ; case BigZ.compare; + intros H; rewrite <- H. + rewrite BigZ.spec_mul; unfold d_to_Z; simpl. + rewrite BigN.spec_succ. + rewrite Zcompare_refl; auto. + rewrite BigZ.spec_mul; unfold d_to_Z; simpl. + rewrite BigN.spec_succ; auto. + rewrite BigZ.spec_mul; unfold d_to_Z; simpl. + rewrite BigN.spec_succ; auto. + rewrite Zmult_1_r. + rewrite BigN.spec_succ. + rewrite Z2P_correct; auto with zarith. + 2: generalize (BigN.spec_pos y1); auto with zarith. + generalize (BigZ.spec_compare x1 (z2 * d_to_Z y1))%bigZ; case BigZ.compare; + rewrite BigZ.spec_mul; unfold d_to_Z; simpl; + rewrite BigN.spec_succ; intros H; auto. + rewrite H; rewrite Zcompare_refl; auto. + repeat rewrite BigN.spec_succ; auto. + repeat rewrite Z2P_correct; auto with zarith. + 2: generalize (BigN.spec_pos y1); auto with zarith. + 2: generalize (BigN.spec_pos y2); auto with zarith. + generalize (BigZ.spec_compare (x1 * d_to_Z y2) + (x2 * d_to_Z y1))%bigZ; case BigZ.compare; + repeat rewrite BigZ.spec_mul; unfold d_to_Z; simpl; + repeat rewrite BigN.spec_succ; intros H; auto. + rewrite H; auto. + rewrite Zcompare_refl; auto. + Qed. + + + Theorem spec_comparec: forall q1 q2, + compare q1 q2 = ([[q1]] ?= [[q2]]). + unfold Qccompare, to_Qc. + intros q1 q2; rewrite spec_compare; simpl. + apply Qcompare_comp; apply Qeq_sym; apply Qred_correct. + Qed. + +(* Inv d > 0, Pour la forme normal unique on veut d > 1 *) + Definition norm n d: t := + if BigZ.eq_bool n BigZ.zero then zero + else + let gcd := BigN.gcd (BigZ.to_N n) d in + if BigN.eq_bool gcd BigN.one then Qq n (BigN.pred d) + else + let n := BigZ.div n (BigZ.Pos gcd) in + let d := BigN.div d gcd in + if BigN.eq_bool d BigN.one then Qz n + else Qq n (BigN.pred d). + + Theorem spec_norm: forall n q, + ((0 < BigN.to_Z q)%Z -> [norm n q] == [Qq n (BigN.pred q)])%Q. + intros p q; unfold norm; intros Hq. + assert (Hp := BigN.spec_pos (BigZ.to_N p)). + match goal with |- context[BigZ.eq_bool ?X ?Y] => + generalize (BigZ.spec_eq_bool X Y); case BigZ.eq_bool + end; auto; rewrite BigZ.spec_0; intros H1. + red; simpl; rewrite H1; ring. + case (Zle_lt_or_eq _ _ Hp); clear Hp; intros Hp. + case (Zle_lt_or_eq _ _ + (Zgcd_is_pos (BigN.to_Z (BigZ.to_N p)) (BigN.to_Z q))); intros H4. + 2: generalize Hq; rewrite (Zgcd_inv_0_r _ _ (sym_equal H4)); auto with zarith. + 2: red; simpl; auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_1; intros H2. + apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_1. + red; simpl. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + rewrite BigN.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + rewrite Zmult_1_r. + rewrite BigN.succ_pred by (rewrite Nspec_lt, BigN.spec_0; auto). + rewrite Z2P_correct; auto with zarith. + rewrite spec_to_N; intros; rewrite Zgcd_div_swap; auto. + rewrite H; ring. + intros H3. + red; simpl. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + rewrite BigN.succ_pred by (rewrite Nspec_lt, BigN.spec_0; auto). + assert (F: (0 < BigN.to_Z (q / BigN.gcd (BigZ.to_N p) q)%bigN)%Z). + rewrite BigN.spec_div; auto with zarith. + rewrite BigN.spec_gcd. + apply Zgcd_div_pos; auto. + rewrite BigN.spec_gcd; auto. + rewrite BigN.succ_pred by (rewrite Nspec_lt, BigN.spec_0; auto). + rewrite Z2P_correct; auto. + rewrite Z2P_correct; auto. + rewrite BigN.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + rewrite spec_to_N; apply Zgcd_div_swap; auto. + case H1; rewrite spec_to_N; rewrite <- Hp; ring. + Qed. + + Theorem spec_normc: forall n q, + (0 < BigN.to_Z q)%Z -> [[norm n q]] = [[Qq n (BigN.pred q)]]. + intros n q H; unfold to_Qc, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_norm; auto. + Qed. + + Definition add (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.add zx zy) + | Qz zx, Qq ny dy => Qq (BigZ.add (BigZ.mul zx (d_to_Z dy)) ny) dy + | Qq nx dx, Qz zy => Qq (BigZ.add nx (BigZ.mul zy (d_to_Z dx))) dx + | Qq nx dx, Qq ny dy => + let dx' := BigN.succ dx in + let dy' := BigN.succ dy in + let n := BigZ.add (BigZ.mul nx (BigZ.Pos dy')) (BigZ.mul ny (BigZ.Pos dx')) in + let d := BigN.pred (BigN.mul dx' dy') in + Qq n d + end. + + Theorem spec_d_to_Z: forall dy, + (BigZ.to_Z (d_to_Z dy) = BigN.to_Z dy + 1)%Z. + intros dy; unfold d_to_Z; simpl. + rewrite BigN.spec_succ; auto. + Qed. + + Theorem spec_succ_pos: forall p, + (0 < BigN.to_Z (BigN.succ p))%Z. + intros p; rewrite BigN.spec_succ; + generalize (BigN.spec_pos p); auto with zarith. + Qed. + + Theorem spec_add x y: ([add x y] == [x] + [y])%Q. + intros [x | nx dx] [y | ny dy]; unfold Qplus; simpl. + rewrite BigZ.spec_add; repeat rewrite Zmult_1_r; auto. + apply Qeq_refl; auto. + assert (F1:= BigN.spec_pos dy). + rewrite Zmult_1_r. + simpl; rewrite Z2P_correct; rewrite BigN.spec_succ; auto with zarith. + rewrite BigZ.spec_add; rewrite BigZ.spec_mul. + rewrite spec_d_to_Z; apply Qeq_refl. + assert (F1:= BigN.spec_pos dx). + rewrite Zmult_1_r; rewrite Pmult_1_r. + simpl; rewrite Z2P_correct; rewrite BigN.spec_succ; auto with zarith. + rewrite BigZ.spec_add; rewrite BigZ.spec_mul. + rewrite spec_d_to_Z; apply Qeq_refl. + repeat rewrite BigN.spec_succ. + assert (Fx: (0 < BigN.to_Z dx + 1)%Z). + generalize (BigN.spec_pos dx); auto with zarith. + assert (Fy: (0 < BigN.to_Z dy + 1)%Z). + generalize (BigN.spec_pos dy); auto with zarith. + repeat rewrite BigN.spec_pred. + rewrite BigZ.spec_add; repeat rewrite BigN.spec_mul; + repeat rewrite BigN.spec_succ. + assert (tmp: forall x, (x-1+1 = x)%Z); [intros; ring | rewrite tmp; clear tmp]. + repeat rewrite Z2P_correct; auto. + repeat rewrite BigZ.spec_mul; simpl. + repeat rewrite BigN.spec_succ. + assert (tmp: + (forall a b, 0 < a -> 0 < b -> Z2P (a * b) = (Z2P a * Z2P b)%positive)%Z). + intros [|a|a] [|b|b]; simpl; auto; intros; apply False_ind; auto with zarith. + rewrite tmp; auto; apply Qeq_refl. + rewrite BigN.spec_mul; repeat rewrite BigN.spec_succ; auto with zarith. + apply Zmult_lt_0_compat; auto. + Qed. + + Theorem spec_addc x y: [[add x y]] = [[x]] + [[y]]. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] + [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_add. + unfold Qcplus, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qplus_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition add_norm (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.add zx zy) + | Qz zx, Qq ny dy => + let d := BigN.succ dy in + norm (BigZ.add (BigZ.mul zx (BigZ.Pos d)) ny) d + | Qq nx dx, Qz zy => + let d := BigN.succ dx in + norm (BigZ.add (BigZ.mul zy (BigZ.Pos d)) nx) d + | Qq nx dx, Qq ny dy => + let dx' := BigN.succ dx in + let dy' := BigN.succ dy in + let n := BigZ.add (BigZ.mul nx (BigZ.Pos dy')) (BigZ.mul ny (BigZ.Pos dx')) in + let d := BigN.mul dx' dy' in + norm n d + end. + + Theorem spec_add_norm x y: ([add_norm x y] == [x] + [y])%Q. + intros x y; rewrite <- spec_add. + unfold add_norm, add; case x; case y. + intros; apply Qeq_refl. + intros p1 n p2. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X (BigN.pred Y)]); + [apply spec_norm | idtac] + end. + rewrite BigN.spec_succ; generalize (BigN.spec_pos n); auto with zarith. + simpl. + repeat rewrite BigZ.spec_add. + repeat rewrite BigZ.spec_mul; simpl. + rewrite BigN.succ_pred; try apply Qeq_refl; apply lt_0_succ. + intros p1 n p2. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X (BigN.pred Y)]); + [apply spec_norm | idtac] + end. + rewrite BigN.spec_succ; generalize (BigN.spec_pos p2); auto with zarith. + simpl. + repeat rewrite BigZ.spec_add. + repeat rewrite BigZ.spec_mul; simpl. + rewrite BinInt.Zplus_comm. + rewrite BigN.succ_pred; try apply Qeq_refl; apply lt_0_succ. + intros p1 q1 p2 q2. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X (BigN.pred Y)]); + [apply spec_norm | idtac] + end; try apply Qeq_refl. + rewrite BigN.spec_mul. + apply Zmult_lt_0_compat; apply spec_succ_pos. + Qed. + + Theorem spec_add_normc x y: [[add_norm x y]] = [[x]] + [[y]]. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] + [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_add_norm. + unfold Qcplus, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qplus_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition sub (x y: t): t := add x (opp y). + + Theorem spec_sub x y: ([sub x y] == [x] - [y])%Q. + intros x y; unfold sub; rewrite spec_add. + rewrite spec_opp; ring. + Qed. + + Theorem spec_subc x y: [[sub x y]] = [[x]] - [[y]]. + intros x y; unfold sub; rewrite spec_addc. + rewrite spec_oppc; ring. + Qed. + + Definition sub_norm x y := add_norm x (opp y). + + Theorem spec_sub_norm x y: ([sub_norm x y] == [x] - [y])%Q. + intros x y; unfold sub_norm; rewrite spec_add_norm. + rewrite spec_opp; ring. + Qed. + + Theorem spec_sub_normc x y: [[sub_norm x y]] = [[x]] - [[y]]. + intros x y; unfold sub_norm; rewrite spec_add_normc. + rewrite spec_oppc; ring. + Qed. + + + Definition mul (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.mul zx zy) + | Qz zx, Qq ny dy => Qq (BigZ.mul zx ny) dy + | Qq nx dx, Qz zy => Qq (BigZ.mul nx zy) dx + | Qq nx dx, Qq ny dy => + Qq (BigZ.mul nx ny) (BigN.pred (BigN.mul (BigN.succ dx) (BigN.succ dy))) + end. + + Theorem spec_mul x y: ([mul x y] == [x] * [y])%Q. + intros [x | nx dx] [y | ny dy]; unfold Qmult; simpl. + rewrite BigZ.spec_mul; repeat rewrite Zmult_1_r; auto. + apply Qeq_refl; auto. + rewrite BigZ.spec_mul; apply Qeq_refl. + rewrite BigZ.spec_mul; rewrite Pmult_1_r; auto. + apply Qeq_refl; auto. + assert (F1:= spec_succ_pos dx). + assert (F2:= spec_succ_pos dy). + rewrite BigN.succ_pred. + rewrite BigN.spec_mul; rewrite BigZ.spec_mul. + assert (tmp: + (forall a b, 0 < a -> 0 < b -> Z2P (a * b) = (Z2P a * Z2P b)%positive)%Z). + intros [|a|a] [|b|b]; simpl; auto; intros; apply False_ind; auto with zarith. + rewrite tmp; auto; apply Qeq_refl. + rewrite Nspec_lt, BigN.spec_0, BigN.spec_mul; auto. + apply Zmult_lt_0_compat; apply spec_succ_pos. + Qed. + + Theorem spec_mulc x y: [[mul x y]] = [[x]] * [[y]]. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] * [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_mul. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition mul_norm (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.mul zx zy) + | Qz zx, Qq ny dy => + if BigZ.eq_bool zx BigZ.zero then zero + else + let d := BigN.succ dy in + let gcd := BigN.gcd (BigZ.to_N zx) d in + if BigN.eq_bool gcd BigN.one then Qq (BigZ.mul zx ny) dy + else + let zx := BigZ.div zx (BigZ.Pos gcd) in + let d := BigN.div d gcd in + if BigN.eq_bool d BigN.one then Qz (BigZ.mul zx ny) + else Qq (BigZ.mul zx ny) (BigN.pred d) + | Qq nx dx, Qz zy => + if BigZ.eq_bool zy BigZ.zero then zero + else + let d := BigN.succ dx in + let gcd := BigN.gcd (BigZ.to_N zy) d in + if BigN.eq_bool gcd BigN.one then Qq (BigZ.mul zy nx) dx + else + let zy := BigZ.div zy (BigZ.Pos gcd) in + let d := BigN.div d gcd in + if BigN.eq_bool d BigN.one then Qz (BigZ.mul zy nx) + else Qq (BigZ.mul zy nx) (BigN.pred d) + | Qq nx dx, Qq ny dy => + norm (BigZ.mul nx ny) (BigN.mul (BigN.succ dx) (BigN.succ dy)) + end. + + Theorem spec_mul_norm x y: ([mul_norm x y] == [x] * [y])%Q. + intros x y; rewrite <- spec_mul. + unfold mul_norm, mul; case x; case y. + intros; apply Qeq_refl. + intros p1 n p2. + match goal with |- context[BigZ.eq_bool ?X ?Y] => + generalize (BigZ.spec_eq_bool X Y); case BigZ.eq_bool + end; unfold zero, to_Q; repeat rewrite BigZ.spec_0; intros H. + rewrite BigZ.spec_mul; rewrite H; red; auto. + assert (F: (0 < BigN.to_Z (BigZ.to_N p2))%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos (BigZ.to_N p2))); auto. + intros H1; case H; rewrite spec_to_N; rewrite <- H1; ring. + assert (F1: (0 < BigN.to_Z (BigN.succ n))%Z). + rewrite BigN.spec_succ; generalize (BigN.spec_pos n); auto with zarith. + assert (F2: (0 < Zgcd (BigN.to_Z (BigZ.to_N p2)) (BigN.to_Z (BigN.succ n)))%Z). + case (Zle_lt_or_eq _ _ (Zgcd_is_pos (BigN.to_Z (BigZ.to_N p2)) + (BigN.to_Z (BigN.succ n)))); intros H3; auto. + generalize F; rewrite (Zgcd_inv_0_l _ _ (sym_equal H3)); auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1; intros H1. + intros; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1. + rewrite BigN.spec_div; rewrite BigN.spec_gcd; + auto with zarith. + intros H2. + red; simpl. + repeat rewrite BigZ.spec_mul. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + rewrite Z2P_correct; auto with zarith. + rewrite spec_to_N. + rewrite Zmult_1_r; repeat rewrite <- Zmult_assoc. + rewrite (Zmult_comm (BigZ.to_Z p1)). + repeat rewrite Zmult_assoc. + rewrite Zgcd_div_swap; auto with zarith. + rewrite H2; ring. + intros H2. + red; simpl. + repeat rewrite BigZ.spec_mul. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + rewrite Z2P_correct; auto with zarith. + rewrite (spec_to_N p2). + case (Zle_lt_or_eq _ _ + (BigN.spec_pos (BigN.succ n / + BigN.gcd (BigZ.to_N p2) + (BigN.succ n)))%bigN); intros F3. + rewrite BigN.succ_pred; auto with zarith. + rewrite Z2P_correct; auto with zarith. + rewrite BigN.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + repeat rewrite <- Zmult_assoc. + rewrite (Zmult_comm (BigZ.to_Z p1)). + repeat rewrite Zmult_assoc. + rewrite Zgcd_div_swap; auto; try ring. + rewrite Nspec_lt, BigN.spec_0; auto. + apply False_ind; generalize F1. + rewrite (Zdivide_Zdiv_eq + (Zgcd (BigN.to_Z (BigZ.to_N p2)) (BigN.to_Z (BigN.succ n))) + (BigN.to_Z (BigN.succ n))); auto. + generalize F3; rewrite BigN.spec_div; rewrite BigN.spec_gcd; + auto with zarith. + intros HH; rewrite <- HH; auto with zarith. + assert (FF:= Zgcd_is_gcd (BigN.to_Z (BigZ.to_N p2)) + (BigN.to_Z (BigN.succ n))); inversion FF; auto. + intros p1 p2 n. + match goal with |- context[BigZ.eq_bool ?X ?Y] => + generalize (BigZ.spec_eq_bool X Y); case BigZ.eq_bool + end; unfold zero, to_Q; repeat rewrite BigZ.spec_0; intros H. + rewrite BigZ.spec_mul; rewrite H; red; simpl; ring. + assert (F: (0 < BigN.to_Z (BigZ.to_N p1))%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos (BigZ.to_N p1))); auto. + intros H1; case H; rewrite spec_to_N; rewrite <- H1; ring. + assert (F1: (0 < BigN.to_Z (BigN.succ n))%Z). + rewrite BigN.spec_succ; generalize (BigN.spec_pos n); auto with zarith. + assert (F2: (0 < Zgcd (BigN.to_Z (BigZ.to_N p1)) (BigN.to_Z (BigN.succ n)))%Z). + case (Zle_lt_or_eq _ _ (Zgcd_is_pos (BigN.to_Z (BigZ.to_N p1)) + (BigN.to_Z (BigN.succ n)))); intros H3; auto. + generalize F; rewrite (Zgcd_inv_0_l _ _ (sym_equal H3)); auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1; intros H1. + intros; repeat rewrite BigZ.spec_mul; rewrite Zmult_comm; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1. + rewrite BigN.spec_div; rewrite BigN.spec_gcd; + auto with zarith. + intros H2. + red; simpl. + repeat rewrite BigZ.spec_mul. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + rewrite Z2P_correct; auto with zarith. + rewrite spec_to_N. + rewrite Zmult_1_r; repeat rewrite <- Zmult_assoc. + rewrite (Zmult_comm (BigZ.to_Z p2)). + repeat rewrite Zmult_assoc. + rewrite Zgcd_div_swap; auto with zarith. + rewrite H2; ring. + intros H2. + red; simpl. + repeat rewrite BigZ.spec_mul. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + rewrite Z2P_correct; auto with zarith. + rewrite (spec_to_N p1). + case (Zle_lt_or_eq _ _ + (BigN.spec_pos (BigN.succ n / + BigN.gcd (BigZ.to_N p1) + (BigN.succ n)))%bigN); intros F3. + rewrite BigN.succ_pred; auto with zarith. + rewrite Z2P_correct; auto with zarith. + rewrite BigN.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + repeat rewrite <- Zmult_assoc. + rewrite (Zmult_comm (BigZ.to_Z p2)). + repeat rewrite Zmult_assoc. + rewrite Zgcd_div_swap; auto; try ring. + rewrite Nspec_lt, BigN.spec_0; auto. + apply False_ind; generalize F1. + rewrite (Zdivide_Zdiv_eq + (Zgcd (BigN.to_Z (BigZ.to_N p1)) (BigN.to_Z (BigN.succ n))) + (BigN.to_Z (BigN.succ n))); auto. + generalize F3; rewrite BigN.spec_div; rewrite BigN.spec_gcd; + auto with zarith. + intros HH; rewrite <- HH; auto with zarith. + assert (FF:= Zgcd_is_gcd (BigN.to_Z (BigZ.to_N p1)) + (BigN.to_Z (BigN.succ n))); inversion FF; auto. + intros p1 n1 p2 n2. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X (BigN.pred Y)]); + [apply spec_norm | idtac] + end; try apply Qeq_refl. + rewrite BigN.spec_mul. + apply Zmult_lt_0_compat; rewrite BigN.spec_succ; + generalize (BigN.spec_pos n1) (BigN.spec_pos n2); auto with zarith. + Qed. + + Theorem spec_mul_normc x y: [[mul_norm x y]] = [[x]] * [[y]]. + intros x y; unfold to_Qc. + apply trans_equal with (!! ([x] * [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_mul_norm. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition inv (x: t): t := + match x with + | Qz (BigZ.Pos n) => + if BigN.eq_bool n BigN.zero then zero else Qq BigZ.one (BigN.pred n) + | Qz (BigZ.Neg n) => + if BigN.eq_bool n BigN.zero then zero else Qq BigZ.minus_one (BigN.pred n) + | Qq (BigZ.Pos n) d => + if BigN.eq_bool n BigN.zero then zero else Qq (BigZ.Pos (BigN.succ d)) (BigN.pred n) + | Qq (BigZ.Neg n) d => + if BigN.eq_bool n BigN.zero then zero else Qq (BigZ.Neg (BigN.succ d)) (BigN.pred n) + end. + + Theorem spec_inv x: ([inv x] == /[x])%Q. + intros [ [x | x] | [nx | nx] dx]; unfold inv. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H. + unfold zero, to_Q; rewrite BigZ.spec_0. + unfold BigZ.to_Z; rewrite H; apply Qeq_refl. + assert (F: (0 < BigN.to_Z x)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos x)); auto with zarith. + unfold to_Q; rewrite BigZ.spec_1. + rewrite BigN.succ_pred by (rewrite Nspec_lt, BigN.spec_0; auto). + red; unfold Qinv; simpl. + generalize F; case BigN.to_Z; auto with zarith. + intros p Hp; discriminate Hp. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H. + unfold zero, to_Q; rewrite BigZ.spec_0. + unfold BigZ.to_Z; rewrite H; apply Qeq_refl. + assert (F: (0 < BigN.to_Z x)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos x)); auto with zarith. + red; unfold Qinv; simpl. + rewrite BigN.succ_pred by (rewrite Nspec_lt, BigN.spec_0; auto). + generalize F; case BigN.to_Z; simpl; auto with zarith. + intros p Hp; discriminate Hp. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H. + unfold zero, to_Q; rewrite BigZ.spec_0. + unfold BigZ.to_Z; rewrite H; apply Qeq_refl. + assert (F: (0 < BigN.to_Z nx)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos nx)); auto with zarith. + red; unfold Qinv; simpl. + rewrite BigN.succ_pred by (rewrite Nspec_lt, BigN.spec_0; auto). + rewrite BigN.spec_succ; rewrite Z2P_correct; auto with zarith. + generalize F; case BigN.to_Z; auto with zarith. + intros p Hp; discriminate Hp. + generalize (BigN.spec_pos dx); auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H. + unfold zero, to_Q; rewrite BigZ.spec_0. + unfold BigZ.to_Z; rewrite H; apply Qeq_refl. + assert (F: (0 < BigN.to_Z nx)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos nx)); auto with zarith. + red; unfold Qinv; simpl. + rewrite BigN.succ_pred by (rewrite Nspec_lt, BigN.spec_0; auto). + rewrite BigN.spec_succ; rewrite Z2P_correct; auto with zarith. + generalize F; case BigN.to_Z; auto with zarith. + simpl; intros. + match goal with |- (?X = Zneg ?Y)%Z => + replace (Zneg Y) with (-(Zpos Y))%Z; + try rewrite Z2P_correct; auto with zarith + end. + rewrite Zpos_mult_morphism; + rewrite Z2P_correct; auto with zarith; try ring. + generalize (BigN.spec_pos dx); auto with zarith. + intros p Hp; discriminate Hp. + generalize (BigN.spec_pos dx); auto with zarith. + Qed. + + Theorem spec_invc x: [[inv x]] = /[[x]]. + intros x; unfold to_Qc. + apply trans_equal with (!! (/[x])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_inv. + unfold Qcinv, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qinv_comp; apply Qeq_sym; apply Qred_correct. + Qed. + +Definition inv_norm x := + match x with + | Qz (BigZ.Pos n) => + if BigN.eq_bool n BigN.zero then zero else + if BigN.eq_bool n BigN.one then x else Qq BigZ.one (BigN.pred n) + | Qz (BigZ.Neg n) => + if BigN.eq_bool n BigN.zero then zero else + if BigN.eq_bool n BigN.one then x else Qq BigZ.minus_one (BigN.pred n) + | Qq (BigZ.Pos n) d => let d := BigN.succ d in + if BigN.eq_bool n BigN.zero then zero else + if BigN.eq_bool n BigN.one then Qz (BigZ.Pos d) + else Qq (BigZ.Pos d) (BigN.pred n) + | Qq (BigZ.Neg n) d => let d := BigN.succ d in + if BigN.eq_bool n BigN.zero then zero else + if BigN.eq_bool n BigN.one then Qz (BigZ.Neg d) + else Qq (BigZ.Neg d) (BigN.pred n) + end. + + Theorem spec_inv_norm x: ([inv_norm x] == /[x])%Q. + intros x; rewrite <- spec_inv. + (case x; clear x); [intros [x | x] | intros nx dx]; + unfold inv_norm, inv. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H. + apply Qeq_refl. + assert (F: (0 < BigN.to_Z x)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos x)); auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1; intros H1. + red; simpl. + rewrite BigN.succ_pred by (rewrite Nspec_lt, BigN.spec_0; auto). + rewrite Z2P_correct; try rewrite H1; auto with zarith. + apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H. + apply Qeq_refl. + assert (F: (0 < BigN.to_Z x)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos x)); auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1; intros H1. + red; simpl. + rewrite BigN.succ_pred by (rewrite Nspec_lt, BigN.spec_0; auto). + rewrite Z2P_correct; try rewrite H1; auto with zarith. + apply Qeq_refl. + case nx; clear nx; intros nx. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H. + apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1; intros H1. + red; simpl. + rewrite BigN.succ_pred; try rewrite H1; auto with zarith. + rewrite Nspec_lt, BigN.spec_0, H1; auto with zarith. + apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H. + apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1; intros H1. + red; simpl. + rewrite BigN.succ_pred; try rewrite H1; auto with zarith. + rewrite Nspec_lt, BigN.spec_0, H1; auto with zarith. + apply Qeq_refl. + Qed. + + + Definition div x y := mul x (inv y). + + Theorem spec_div x y: ([div x y] == [x] / [y])%Q. + intros x y; unfold div; rewrite spec_mul; auto. + unfold Qdiv; apply Qmult_comp. + apply Qeq_refl. + apply spec_inv; auto. + Qed. + + Theorem spec_divc x y: [[div x y]] = [[x]] / [[y]]. + intros x y; unfold div; rewrite spec_mulc; auto. + unfold Qcdiv; apply f_equal2 with (f := Qcmult); auto. + apply spec_invc; auto. + Qed. + + Definition div_norm x y := mul_norm x (inv y). + + Theorem spec_div_norm x y: ([div_norm x y] == [x] / [y])%Q. + intros x y; unfold div_norm; rewrite spec_mul_norm; auto. + unfold Qdiv; apply Qmult_comp. + apply Qeq_refl. + apply spec_inv; auto. + Qed. + + Theorem spec_div_normc x y: [[div_norm x y]] = [[x]] / [[y]]. + intros x y; unfold div_norm; rewrite spec_mul_normc; auto. + unfold Qcdiv; apply f_equal2 with (f := Qcmult); auto. + apply spec_invc; auto. + Qed. + + + Definition square (x: t): t := + match x with + | Qz zx => Qz (BigZ.square zx) + | Qq nx dx => Qq (BigZ.square nx) (BigN.pred (BigN.square (BigN.succ dx))) + end. + + Theorem spec_square x: ([square x] == [x] ^ 2)%Q. + intros [ x | nx dx]; unfold square. + red; simpl; rewrite BigZ.spec_square; auto with zarith. + red; simpl; rewrite BigZ.spec_square; auto with zarith. + assert (F: (0 < BigN.to_Z (BigN.succ dx))%Z). + rewrite BigN.spec_succ; + case (Zle_lt_or_eq _ _ (BigN.spec_pos dx)); auto with zarith. + assert (F1 : (0 < BigN.to_Z (BigN.square (BigN.succ dx)))%Z). + rewrite BigN.spec_square; apply Zmult_lt_0_compat; + auto with zarith. + rewrite BigN.succ_pred by (rewrite Nspec_lt, BigN.spec_0; auto). + rewrite Zpos_mult_morphism. + repeat rewrite Z2P_correct; auto with zarith. + repeat rewrite BigN.spec_succ; auto with zarith. + rewrite BigN.spec_square; auto with zarith. + repeat rewrite BigN.spec_succ; auto with zarith. + Qed. + + Theorem spec_squarec x: [[square x]] = [[x]]^2. + intros x; unfold to_Qc. + apply trans_equal with (!! ([x]^2)). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_square. + simpl Qcpower. + replace (!! [x] * 1) with (!![x]); try ring. + simpl. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition power_pos (x: t) p: t := + match x with + | Qz zx => Qz (BigZ.power_pos zx p) + | Qq nx dx => Qq (BigZ.power_pos nx p) (BigN.pred (BigN.power_pos (BigN.succ dx) p)) + end. + + + Theorem spec_power_pos x p: ([power_pos x p] == [x] ^ Zpos p)%Q. + Proof. + intros [x | nx dx] p; unfold power_pos. + unfold power_pos; red; simpl. + generalize (Qpower_decomp p (BigZ.to_Z x) 1). + unfold Qeq; simpl. + rewrite Zpower_pos_1_l; simpl Z2P. + rewrite Zmult_1_r. + intros H; rewrite H. + rewrite BigZ.spec_power_pos; simpl; ring. + assert (F1: (0 < BigN.to_Z (BigN.succ dx))%Z). + rewrite BigN.spec_succ; + generalize (BigN.spec_pos dx); auto with zarith. + assert (F2: (0 < BigN.to_Z (BigN.succ dx) ^ ' p)%Z). + unfold Zpower; apply Zpower_pos_pos; auto. + unfold power_pos; red; simpl. + rewrite BigN.succ_pred, BigN.spec_power_pos. + rewrite Z2P_correct; auto. + generalize (Qpower_decomp p (BigZ.to_Z nx) + (Z2P (BigN.to_Z (BigN.succ dx)))). + unfold Qeq; simpl. + repeat rewrite Z2P_correct; auto. + unfold Qeq; simpl; intros HH. + rewrite HH. + rewrite BigZ.spec_power_pos; simpl; ring. + rewrite Nspec_lt, BigN.spec_0, BigN.spec_power_pos; auto. + Qed. + + Theorem spec_power_posc x p: [[power_pos x p]] = [[x]] ^ nat_of_P p. + intros x p; unfold to_Qc. + apply trans_equal with (!! ([x]^Zpos p)). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_power_pos. + pattern p; apply Pind; clear p. + simpl; ring. + intros p Hrec. + rewrite nat_of_P_succ_morphism; simpl Qcpower. + rewrite <- Hrec. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; + unfold this. + apply Qred_complete. + assert (F: [x] ^ ' Psucc p == [x] * [x] ^ ' p). + simpl; case x; simpl; clear x Hrec. + intros x; simpl; repeat rewrite Qpower_decomp; simpl. + red; simpl; repeat rewrite Zpower_pos_1_l; simpl Z2P. + rewrite Pplus_one_succ_l. + rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r; auto. + intros nx dx; simpl; repeat rewrite Qpower_decomp; simpl. + red; simpl; repeat rewrite Zpower_pos_1_l; simpl Z2P. + rewrite Pplus_one_succ_l. + rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r; auto. + assert (F1: (0 < BigN.to_Z (BigN.succ dx))%Z). + rewrite BigN.spec_succ; generalize (BigN.spec_pos dx); + auto with zarith. + repeat rewrite Zpos_mult_morphism. + repeat rewrite Z2P_correct; auto. + 2: apply Zpower_pos_pos; auto. + 2: apply Zpower_pos_pos; auto. + rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r; auto. + rewrite F. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + +End Qp. diff --git a/theories/Numbers/Rational/BigQ/QvMake.v b/theories/Numbers/Rational/BigQ/QvMake.v new file mode 100644 index 00000000..4523e241 --- /dev/null +++ b/theories/Numbers/Rational/BigQ/QvMake.v @@ -0,0 +1,1151 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) +(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *) +(************************************************************************) + +(*i $Id: QvMake.v 11027 2008-06-01 13:28:59Z letouzey $ i*) + +Require Import Bool. +Require Import ZArith. +Require Import Znumtheory. +Require Import BigNumPrelude. +Require Import Arith. +Require Export BigN. +Require Export BigZ. +Require Import QArith. +Require Import Qcanon. +Require Import Qpower. +Require Import QMake_base. + +Module Qv. + + Import BinInt Zorder. + Open Local Scope Q_scope. + Open Local Scope Qc_scope. + + (** The notation of a rational number is either an integer x, + interpreted as itself or a pair (x,y) of an integer x and a naturel + number y interpreted as x/y. All functions maintain the invariant + that y is never zero. *) + + Definition t := q_type. + + Definition zero: t := Qz BigZ.zero. + Definition one: t := Qz BigZ.one. + Definition minus_one: t := Qz BigZ.minus_one. + + Definition of_Z x: t := Qz (BigZ.of_Z x). + + Definition wf x := + match x with + | Qz _ => True + | Qq n d => if BigN.eq_bool d BigN.zero then False else True + end. + + Definition of_Q q: t := + match q with x # y => + Qq (BigZ.of_Z x) (BigN.of_N (Npos y)) + end. + + Definition of_Qc q := of_Q (this q). + + Definition to_Q (q: t) := + match q with + Qz x => BigZ.to_Z x # 1 + |Qq x y => BigZ.to_Z x # Z2P (BigN.to_Z y) + end. + + Definition to_Qc q := !!(to_Q q). + + Notation "[[ x ]]" := (to_Qc x). + + Notation "[ x ]" := (to_Q x). + + Theorem spec_to_Q: forall q: Q, [of_Q q] = q. + intros (x,y); simpl. + rewrite BigZ.spec_of_Z; simpl. + rewrite (BigN.spec_of_pos); auto. + Qed. + + Theorem spec_to_Qc: forall q, [[of_Qc q]] = q. + intros (x, Hx); unfold of_Qc, to_Qc; simpl. + apply Qc_decomp; simpl. + intros; rewrite spec_to_Q; auto. + Qed. + + Definition opp (x: t): t := + match x with + | Qz zx => Qz (BigZ.opp zx) + | Qq nx dx => Qq (BigZ.opp nx) dx + end. + + Theorem wf_opp: forall x, wf x -> wf (opp x). + intros [zx | nx dx]; unfold opp, wf; auto. + Qed. + + Theorem spec_opp: forall q, ([opp q] = -[q])%Q. + intros [z | x y]; simpl. + rewrite BigZ.spec_opp; auto. + rewrite BigZ.spec_opp; auto. + Qed. + + Theorem spec_oppc: forall q, [[opp q]] = -[[q]]. + intros q; unfold Qcopp, to_Qc, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + rewrite spec_opp. + rewrite <- Qred_opp. + rewrite Qred_involutive; auto. + Qed. + + (* Les fonctions doivent assurer que si leur arguments sont valides alors + le resultat est correct et valide (si c'est un Q) + *) + + Definition compare (x y: t) := + match x, y with + | Qz zx, Qz zy => BigZ.compare zx zy + | Qz zx, Qq ny dy => BigZ.compare (BigZ.mul zx (BigZ.Pos dy)) ny + | Qq nx dx, Qz zy => BigZ.compare nx (BigZ.mul zy (BigZ.Pos dx)) + | Qq nx dx, Qq ny dy => BigZ.compare (BigZ.mul nx (BigZ.Pos dy)) (BigZ.mul ny (BigZ.Pos dx)) + end. + + Theorem spec_compare: forall q1 q2, wf q1 -> wf q2 -> + compare q1 q2 = ([q1] ?= [q2])%Q. + intros [z1 | x1 y1] [z2 | x2 y2]; + unfold Qcompare, compare, to_Q, Qnum, Qden, wf. + repeat rewrite Zmult_1_r. + generalize (BigZ.spec_compare z1 z2); case BigZ.compare; intros H; auto. + rewrite H; rewrite Zcompare_refl; auto. + rewrite Zmult_1_r. + generalize (BigN.spec_eq_bool y2 BigN.zero); + case BigN.eq_bool. + intros _ _ HH; case HH. + rewrite BigN.spec_0; intros HH _ _. + rewrite Z2P_correct; auto with zarith. + 2: generalize (BigN.spec_pos y2); auto with zarith. + generalize (BigZ.spec_compare (z1 * BigZ.Pos y2) x2)%bigZ; case BigZ.compare; + rewrite BigZ.spec_mul; simpl; intros H; apply sym_equal; auto. + rewrite H; rewrite Zcompare_refl; auto. + generalize (BigN.spec_eq_bool y1 BigN.zero); + case BigN.eq_bool. + intros _ HH; case HH. + rewrite BigN.spec_0; intros HH _ _. + rewrite Z2P_correct; auto with zarith. + 2: generalize (BigN.spec_pos y1); auto with zarith. + rewrite Zmult_1_r. + generalize (BigZ.spec_compare x1 (z2 * BigZ.Pos y1))%bigZ; case BigZ.compare; + rewrite BigZ.spec_mul; simpl; intros H; apply sym_equal; auto. + rewrite H; rewrite Zcompare_refl; auto. + generalize (BigN.spec_eq_bool y1 BigN.zero); + case BigN.eq_bool. + intros _ HH; case HH. + rewrite BigN.spec_0; intros HH1. + generalize (BigN.spec_eq_bool y2 BigN.zero); + case BigN.eq_bool. + intros _ _ HH; case HH. + rewrite BigN.spec_0; intros HH2 _ _. + repeat rewrite Z2P_correct. + 2: generalize (BigN.spec_pos y1); auto with zarith. + 2: generalize (BigN.spec_pos y2); auto with zarith. + generalize (BigZ.spec_compare (x1 * BigZ.Pos y2) + (x2 * BigZ.Pos y1))%bigZ; case BigZ.compare; + repeat rewrite BigZ.spec_mul; simpl; intros H; apply sym_equal; auto. + rewrite H; rewrite Zcompare_refl; auto. + Qed. + + Theorem spec_comparec: forall q1 q2, wf q1 -> wf q2 -> + compare q1 q2 = ([[q1]] ?= [[q2]]). + unfold Qccompare, to_Qc. + intros q1 q2 Hq1 Hq2; rewrite spec_compare; simpl; auto. + apply Qcompare_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition norm n d: t := + if BigZ.eq_bool n BigZ.zero then zero + else + let gcd := BigN.gcd (BigZ.to_N n) d in + if BigN.eq_bool gcd BigN.one then Qq n d + else + let n := BigZ.div n (BigZ.Pos gcd) in + let d := BigN.div d gcd in + if BigN.eq_bool d BigN.one then Qz n + else Qq n d. + + Theorem wf_norm: forall n q, + (BigN.to_Z q <> 0)%Z -> wf (norm n q). + intros p q; unfold norm, wf; intros Hq. + assert (Hp := BigN.spec_pos (BigZ.to_N p)). + match goal with |- context[BigZ.eq_bool ?X ?Y] => + generalize (BigZ.spec_eq_bool X Y); case BigZ.eq_bool + end; auto; rewrite BigZ.spec_0; intros H1. + simpl; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_1. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_1. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + set (a := BigN.to_Z (BigZ.to_N p)). + set (b := (BigN.to_Z q)). + assert (F: (0 < Zgcd a b)%Z). + case (Zle_lt_or_eq _ _ (Zgcd_is_pos a b)); auto. + intros HH1; case Hq; apply (Zgcd_inv_0_r _ _ (sym_equal HH1)). + rewrite BigN.spec_div; rewrite BigN.spec_gcd; auto; fold a; fold b. + intros H; case Hq; fold b. + rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto. + rewrite H; auto with zarith. + assert (F1:= Zgcd_is_gcd a b); inversion F1; auto. + Qed. + + Theorem spec_norm: forall n q, + ((0 < BigN.to_Z q)%Z -> [norm n q] == [Qq n q])%Q. + intros p q; unfold norm; intros Hq. + assert (Hp := BigN.spec_pos (BigZ.to_N p)). + match goal with |- context[BigZ.eq_bool ?X ?Y] => + generalize (BigZ.spec_eq_bool X Y); case BigZ.eq_bool + end; auto; rewrite BigZ.spec_0; intros H1. + red; simpl; rewrite H1; ring. + case (Zle_lt_or_eq _ _ Hp); clear Hp; intros Hp. + case (Zle_lt_or_eq _ _ + (Zgcd_is_pos (BigN.to_Z (BigZ.to_N p)) (BigN.to_Z q))); intros H4. + 2: generalize Hq; rewrite (Zgcd_inv_0_r _ _ (sym_equal H4)); auto with zarith. + 2: red; simpl; auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_1; intros H2. + apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_1. + red; simpl. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + rewrite BigN.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + rewrite Zmult_1_r. + rewrite Z2P_correct; auto with zarith. + rewrite spec_to_N; intros; rewrite Zgcd_div_swap; auto. + rewrite H; ring. + intros H3. + red; simpl. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + assert (F: (0 < BigN.to_Z (q / BigN.gcd (BigZ.to_N p) q)%bigN)%Z). + rewrite BigN.spec_div; auto with zarith. + rewrite BigN.spec_gcd. + apply Zgcd_div_pos; auto. + rewrite BigN.spec_gcd; auto. + rewrite Z2P_correct; auto. + rewrite Z2P_correct; auto. + rewrite BigN.spec_div; simpl; rewrite BigN.spec_gcd; auto with zarith. + rewrite spec_to_N; apply Zgcd_div_swap; auto. + case H1; rewrite spec_to_N; rewrite <- Hp; ring. + Qed. + + Theorem spec_normc: forall n q, + (0 < BigN.to_Z q)%Z -> [[norm n q]] = [[Qq n q]]. + intros n q H; unfold to_Qc, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_norm; auto. + Qed. + + Definition add (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.add zx zy) + | Qz zx, Qq ny dy => Qq (BigZ.add (BigZ.mul zx (BigZ.Pos dy)) ny) dy + | Qq nx dx, Qz zy => Qq (BigZ.add nx (BigZ.mul zy (BigZ.Pos dx))) dx + | Qq nx dx, Qq ny dy => + let n := BigZ.add (BigZ.mul nx (BigZ.Pos dy)) (BigZ.mul ny (BigZ.Pos dx)) in + let d := BigN.mul dx dy in + Qq n d + end. + + Theorem wf_add: forall x y, wf x -> wf y -> wf (add x y). + intros [zx | nx dx] [zy | ny dy]; unfold add, wf; auto. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_mul. + intros H1 H2 H3. + case (Zmult_integral _ _ H1); auto with zarith. + Qed. + + Theorem spec_add x y: wf x -> wf y -> + ([add x y] == [x] + [y])%Q. + intros [x | nx dx] [y | ny dy]; unfold Qplus; simpl. + rewrite BigZ.spec_add; repeat rewrite Zmult_1_r; auto. + intros; apply Qeq_refl; auto. + assert (F1:= BigN.spec_pos dy). + rewrite Zmult_1_r. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool. + intros _ _ HH; case HH. + rewrite BigN.spec_0; intros HH _ _. + rewrite Z2P_correct; auto with zarith. + rewrite BigZ.spec_add; rewrite BigZ.spec_mul. + simpl; apply Qeq_refl. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool. + intros _ HH; case HH. + rewrite BigN.spec_0; intros HH _ _. + assert (F1:= BigN.spec_pos dx). + rewrite Zmult_1_r; rewrite Pmult_1_r. + simpl; rewrite Z2P_correct; auto with zarith. + rewrite BigZ.spec_add; rewrite BigZ.spec_mul; simpl. + apply Qeq_refl. + generalize (BigN.spec_eq_bool dx BigN.zero); + case BigN.eq_bool. + intros _ HH; case HH. + rewrite BigN.spec_0; intros HH1. + generalize (BigN.spec_eq_bool dy BigN.zero); + case BigN.eq_bool. + intros _ _ HH; case HH. + rewrite BigN.spec_0; intros HH2 _ _. + assert (Fx: (0 < BigN.to_Z dx)%Z). + generalize (BigN.spec_pos dx); auto with zarith. + assert (Fy: (0 < BigN.to_Z dy)%Z). + generalize (BigN.spec_pos dy); auto with zarith. + rewrite BigZ.spec_add; repeat rewrite BigN.spec_mul. + red; simpl. + rewrite Zpos_mult_morphism. + repeat rewrite Z2P_correct; auto. + repeat rewrite BigZ.spec_mul; simpl; auto. + apply Zmult_lt_0_compat; auto. + Qed. + + Theorem spec_addc x y: wf x -> wf y -> + [[add x y]] = [[x]] + [[y]]. + intros x y H1 H2; unfold to_Qc. + apply trans_equal with (!! ([x] + [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_add; auto. + unfold Qcplus, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qplus_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition add_norm (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.add zx zy) + | Qz zx, Qq ny dy => + norm (BigZ.add (BigZ.mul zx (BigZ.Pos dy)) ny) dy + | Qq nx dx, Qz zy => + norm (BigZ.add (BigZ.mul zy (BigZ.Pos dx)) nx) dx + | Qq nx dx, Qq ny dy => + let n := BigZ.add (BigZ.mul nx (BigZ.Pos dy)) (BigZ.mul ny (BigZ.Pos dx)) in + let d := BigN.mul dx dy in + norm n d + end. + + Theorem wf_add_norm: forall x y, wf x -> wf y -> wf (add_norm x y). + intros [zx | nx dx] [zy | ny dy]; unfold add_norm; auto. + intros HH1 HH2; apply wf_norm. + generalize HH2; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + intros HH1 HH2; apply wf_norm. + generalize HH1; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + intros HH1 HH2; apply wf_norm. + rewrite BigN.spec_mul; intros HH3. + case (Zmult_integral _ _ HH3). + generalize HH1; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + generalize HH2; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + Qed. + + Theorem spec_add_norm x y: wf x -> wf y -> + ([add_norm x y] == [x] + [y])%Q. + intros x y H1 H2; rewrite <- spec_add; auto. + generalize H1 H2; unfold add_norm, add, wf; case x; case y; clear H1 H2. + intros; apply Qeq_refl. + intros p1 n p2 _. + generalize (BigN.spec_eq_bool n BigN.zero); + case BigN.eq_bool. + intros _ HH; case HH. + rewrite BigN.spec_0; intros HH _. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end. + generalize (BigN.spec_pos n); auto with zarith. + simpl. + repeat rewrite BigZ.spec_add. + repeat rewrite BigZ.spec_mul; simpl. + apply Qeq_refl. + intros p1 n p2. + generalize (BigN.spec_eq_bool p2 BigN.zero); + case BigN.eq_bool. + intros _ HH; case HH. + rewrite BigN.spec_0; intros HH _ _. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end. + generalize (BigN.spec_pos p2); auto with zarith. + simpl. + repeat rewrite BigZ.spec_add. + repeat rewrite BigZ.spec_mul; simpl. + rewrite Zplus_comm. + apply Qeq_refl. + intros p1 q1 p2 q2. + generalize (BigN.spec_eq_bool q2 BigN.zero); + case BigN.eq_bool. + intros _ HH; case HH. + rewrite BigN.spec_0; intros HH1 _. + generalize (BigN.spec_eq_bool q1 BigN.zero); + case BigN.eq_bool. + intros _ HH; case HH. + rewrite BigN.spec_0; intros HH2 _. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end; try apply Qeq_refl. + rewrite BigN.spec_mul. + apply Zmult_lt_0_compat. + generalize (BigN.spec_pos q2); auto with zarith. + generalize (BigN.spec_pos q1); auto with zarith. + Qed. + + Theorem spec_add_normc x y: wf x -> wf y -> + [[add_norm x y]] = [[x]] + [[y]]. + intros x y Hx Hy; unfold to_Qc. + apply trans_equal with (!! ([x] + [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_add_norm; auto. + unfold Qcplus, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qplus_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition sub x y := add x (opp y). + + Theorem wf_sub x y: wf x -> wf y -> wf (sub x y). + intros x y Hx Hy; unfold sub; apply wf_add; auto. + apply wf_opp; auto. + Qed. + + Theorem spec_sub x y: wf x -> wf y -> + ([sub x y] == [x] - [y])%Q. + intros x y Hx Hy; unfold sub; rewrite spec_add; auto. + rewrite spec_opp; ring. + apply wf_opp; auto. + Qed. + + Theorem spec_subc x y: wf x -> wf y -> + [[sub x y]] = [[x]] - [[y]]. + intros x y Hx Hy; unfold sub; rewrite spec_addc; auto. + rewrite spec_oppc; ring. + apply wf_opp; auto. + Qed. + + Definition sub_norm x y := add_norm x (opp y). + + Theorem wf_sub_norm x y: wf x -> wf y -> wf (sub_norm x y). + intros x y Hx Hy; unfold sub_norm; apply wf_add_norm; auto. + apply wf_opp; auto. + Qed. + + Theorem spec_sub_norm x y: wf x -> wf y -> + ([sub_norm x y] == [x] - [y])%Q. + intros x y Hx Hy; unfold sub_norm; rewrite spec_add_norm; auto. + rewrite spec_opp; ring. + apply wf_opp; auto. + Qed. + + Theorem spec_sub_normc x y: wf x -> wf y -> + [[sub_norm x y]] = [[x]] - [[y]]. + intros x y Hx Hy; unfold sub_norm; rewrite spec_add_normc; auto. + rewrite spec_oppc; ring. + apply wf_opp; auto. + Qed. + + Definition mul (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.mul zx zy) + | Qz zx, Qq ny dy => Qq (BigZ.mul zx ny) dy + | Qq nx dx, Qz zy => Qq (BigZ.mul nx zy) dx + | Qq nx dx, Qq ny dy => + Qq (BigZ.mul nx ny) (BigN.mul dx dy) + end. + + Theorem wf_mul: forall x y, wf x -> wf y -> wf (mul x y). + intros [zx | nx dx] [zy | ny dy]; unfold mul, wf; auto. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_mul. + intros H1 H2 H3. + case (Zmult_integral _ _ H1); auto with zarith. + Qed. + + Theorem spec_mul x y: wf x -> wf y -> ([mul x y] == [x] * [y])%Q. + intros [x | nx dx] [y | ny dy]; unfold Qmult; simpl. + rewrite BigZ.spec_mul; repeat rewrite Zmult_1_r; auto. + intros; apply Qeq_refl; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + intros _ _ HH; case HH. + rewrite BigN.spec_0; intros HH1 _ _. + rewrite BigZ.spec_mul; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + intros _ HH; case HH. + rewrite BigN.spec_0; intros HH1 _ _. + rewrite BigZ.spec_mul; rewrite Pmult_1_r. + apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + intros _ HH; case HH. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + intros _ _ _ HH; case HH. + rewrite BigN.spec_0; intros H1 H2 _ _. + rewrite BigZ.spec_mul; rewrite BigN.spec_mul. + assert (tmp: + (forall a b, 0 < a -> 0 < b -> Z2P (a * b) = (Z2P a * Z2P b)%positive)%Z). + intros [|a|a] [|b|b]; simpl; auto; intros; apply False_ind; auto with zarith. + rewrite tmp; auto. + apply Qeq_refl. + generalize (BigN.spec_pos dx); auto with zarith. + generalize (BigN.spec_pos dy); auto with zarith. + Qed. + + Theorem spec_mulc x y: wf x -> wf y -> + [[mul x y]] = [[x]] * [[y]]. + intros x y Hx Hy; unfold to_Qc. + apply trans_equal with (!! ([x] * [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_mul; auto. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition mul_norm (x y: t): t := + match x, y with + | Qz zx, Qz zy => Qz (BigZ.mul zx zy) + | Qz zx, Qq ny dy => + if BigZ.eq_bool zx BigZ.zero then zero + else + let gcd := BigN.gcd (BigZ.to_N zx) dy in + if BigN.eq_bool gcd BigN.one then Qq (BigZ.mul zx ny) dy + else + let zx := BigZ.div zx (BigZ.Pos gcd) in + let d := BigN.div dy gcd in + if BigN.eq_bool d BigN.one then Qz (BigZ.mul zx ny) + else Qq (BigZ.mul zx ny) d + | Qq nx dx, Qz zy => + if BigZ.eq_bool zy BigZ.zero then zero + else + let gcd := BigN.gcd (BigZ.to_N zy) dx in + if BigN.eq_bool gcd BigN.one then Qq (BigZ.mul zy nx) dx + else + let zy := BigZ.div zy (BigZ.Pos gcd) in + let d := BigN.div dx gcd in + if BigN.eq_bool d BigN.one then Qz (BigZ.mul zy nx) + else Qq (BigZ.mul zy nx) d + | Qq nx dx, Qq ny dy => norm (BigZ.mul nx ny) (BigN.mul dx dy) + end. + + Theorem wf_mul_norm: forall x y, wf x -> wf y -> wf (mul_norm x y). + intros [zx | nx dx] [zy | ny dy]; unfold mul_norm; auto. + intros HH1 HH2. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; + match goal with |- context[BigZ.eq_bool ?X ?Y] => + generalize (BigZ.spec_eq_bool X Y); case BigZ.eq_bool + end; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + rewrite BigN.spec_1; rewrite BigZ.spec_0. + intros H1 H2; unfold wf. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + rewrite BigN.spec_0. + set (a := BigN.to_Z (BigZ.to_N zx)). + set (b := (BigN.to_Z dy)). + assert (F: (0 < Zgcd a b)%Z). + case (Zle_lt_or_eq _ _ (Zgcd_is_pos a b)); auto. + intros HH3; case H2; rewrite spec_to_N; fold a. + rewrite (Zgcd_inv_0_l _ _ (sym_equal HH3)); try ring. + rewrite BigN.spec_div; rewrite BigN.spec_gcd; fold a; fold b; auto. + intros H. + generalize HH2; simpl wf. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + rewrite BigN.spec_0; intros HH; case HH; fold b. + rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto. + rewrite H; auto with zarith. + assert (F1:= Zgcd_is_gcd a b); inversion F1; auto. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + rewrite BigN.spec_1; rewrite BigN.spec_gcd. + intros HH1 H1 H2. + match goal with |- context[BigZ.eq_bool ?X ?Y] => + generalize (BigZ.spec_eq_bool X Y); case BigZ.eq_bool + end; auto. + rewrite BigN.spec_1; rewrite BigN.spec_gcd. + intros HH1 H1 H2. + match goal with |- context[BigZ.eq_bool ?X ?Y] => + generalize (BigZ.spec_eq_bool X Y); case BigZ.eq_bool + end; auto. + rewrite BigZ.spec_0. + intros HH2. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + set (a := BigN.to_Z (BigZ.to_N zy)). + set (b := (BigN.to_Z dx)). + assert (F: (0 < Zgcd a b)%Z). + case (Zle_lt_or_eq _ _ (Zgcd_is_pos a b)); auto. + intros HH3; case HH2; rewrite spec_to_N; fold a. + rewrite (Zgcd_inv_0_l _ _ (sym_equal HH3)); try ring. + rewrite BigN.spec_div; rewrite BigN.spec_gcd; fold a; fold b; auto. + intros H; unfold wf. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + rewrite BigN.spec_0. + rewrite BigN.spec_div; rewrite BigN.spec_gcd; fold a; fold b; auto. + intros HH; generalize H1; simpl wf. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + rewrite BigN.spec_0. + intros HH3; case HH3; fold b. + rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto. + rewrite HH; auto with zarith. + assert (F1:= Zgcd_is_gcd a b); inversion F1; auto. + intros HH1 HH2; apply wf_norm. + rewrite BigN.spec_mul; intros HH3. + case (Zmult_integral _ _ HH3). + generalize HH1; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + generalize HH2; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + Qed. + + Theorem spec_mul_norm x y: wf x -> wf y -> + ([mul_norm x y] == [x] * [y])%Q. + intros x y Hx Hy; rewrite <- spec_mul; auto. + unfold mul_norm, mul; generalize Hx Hy; case x; case y; clear Hx Hy. + intros; apply Qeq_refl. + intros p1 n p2 Hx Hy. + match goal with |- context[BigZ.eq_bool ?X ?Y] => + generalize (BigZ.spec_eq_bool X Y); case BigZ.eq_bool + end; unfold zero, to_Q; repeat rewrite BigZ.spec_0; intros H. + rewrite BigZ.spec_mul; rewrite H; red; auto. + assert (F: (0 < BigN.to_Z (BigZ.to_N p2))%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos (BigZ.to_N p2))); auto. + intros H1; case H; rewrite spec_to_N; rewrite <- H1; ring. + assert (F1: (0 < BigN.to_Z n)%Z). + generalize Hy; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto. + intros _ HH; case HH. + rewrite BigN.spec_0; generalize (BigN.spec_pos n); auto with zarith. + set (a := BigN.to_Z (BigZ.to_N p2)). + set (b := BigN.to_Z n). + assert (F2: (0 < Zgcd a b )%Z). + case (Zle_lt_or_eq _ _ (Zgcd_is_pos a b)); intros H3; auto. + generalize F; fold a; rewrite (Zgcd_inv_0_l _ _ (sym_equal H3)); auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1; try rewrite BigN.spec_gcd; + fold a b; intros H1. + intros; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1. + rewrite BigN.spec_div; rewrite BigN.spec_gcd; + auto with zarith; fold a b; intros H2. + red; simpl. + repeat rewrite BigZ.spec_mul. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; + fold a b; auto with zarith. + rewrite Z2P_correct; auto with zarith. + rewrite spec_to_N; fold a; fold b. + rewrite Zmult_1_r; repeat rewrite <- Zmult_assoc. + rewrite (Zmult_comm (BigZ.to_Z p1)). + repeat rewrite Zmult_assoc. + rewrite Zgcd_div_swap; auto with zarith. + rewrite H2; ring. + repeat rewrite BigZ.spec_mul. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; + fold a b; auto with zarith. + rewrite BigN.spec_div; simpl; rewrite BigN.spec_gcd; + fold a b; auto with zarith. + intros H2; red; simpl. + repeat rewrite BigZ.spec_mul. + rewrite Z2P_correct; auto with zarith. + rewrite (spec_to_N p2); fold a b. + rewrite Z2P_correct; auto with zarith. + repeat rewrite <- Zmult_assoc. + rewrite (Zmult_comm (BigZ.to_Z p1)). + repeat rewrite Zmult_assoc. + rewrite Zgcd_div_swap; auto; try ring. + case (Zle_lt_or_eq _ _ + (BigN.spec_pos (n / + BigN.gcd (BigZ.to_N p2) + n))%bigN); + rewrite BigN.spec_div; simpl; rewrite BigN.spec_gcd; + fold a b; auto with zarith. + intros H3. + apply False_ind; generalize F1. + generalize Hy; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; auto with zarith. + intros HH; case HH; fold b. + rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto. + rewrite <- H3; ring. + assert (FF:= Zgcd_is_gcd a b); inversion FF; auto. + intros p1 p2 n Hx Hy. + match goal with |- context[BigZ.eq_bool ?X ?Y] => + generalize (BigZ.spec_eq_bool X Y); case BigZ.eq_bool + end; unfold zero, to_Q; repeat rewrite BigZ.spec_0; intros H. + rewrite BigZ.spec_mul; rewrite H; red; simpl; ring. + set (a := BigN.to_Z (BigZ.to_N p1)). + set (b := BigN.to_Z n). + assert (F: (0 < a)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos (BigZ.to_N p1))); auto. + intros H1; case H; rewrite spec_to_N; rewrite <- H1; ring. + assert (F1: (0 < b)%Z). + generalize Hx; unfold wf. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; auto with zarith. + generalize (BigN.spec_pos n); fold b; auto with zarith. + assert (F2: (0 < Zgcd a b)%Z). + case (Zle_lt_or_eq _ _ (Zgcd_is_pos a b)); intros H3; auto. + generalize F; rewrite (Zgcd_inv_0_l _ _ (sym_equal H3)); auto with zarith. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1; rewrite BigN.spec_gcd; fold a b; intros H1. + intros; repeat rewrite BigZ.spec_mul; rewrite Zmult_comm; apply Qeq_refl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_1. + rewrite BigN.spec_div; rewrite BigN.spec_gcd; + auto with zarith. + fold a b; intros H2. + red; simpl. + repeat rewrite BigZ.spec_mul. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; + fold a b; auto with zarith. + rewrite Z2P_correct; auto with zarith. + rewrite spec_to_N; fold a b. + rewrite Zmult_1_r; repeat rewrite <- Zmult_assoc. + rewrite (Zmult_comm (BigZ.to_Z p2)). + repeat rewrite Zmult_assoc. + rewrite Zgcd_div_swap; auto with zarith. + rewrite H2; ring. + intros H2. + red; simpl. + repeat rewrite BigZ.spec_mul. + rewrite BigZ.spec_div; simpl; rewrite BigN.spec_gcd; + fold a b; auto with zarith. + rewrite Z2P_correct; auto with zarith. + rewrite (spec_to_N p1); fold a b. + case (Zle_lt_or_eq _ _ + (BigN.spec_pos (n / BigN.gcd (BigZ.to_N p1) n))%bigN); intros F3. + rewrite Z2P_correct; auto with zarith. + rewrite BigN.spec_div; simpl; rewrite BigN.spec_gcd; + fold a b; auto with zarith. + repeat rewrite <- Zmult_assoc. + rewrite (Zmult_comm (BigZ.to_Z p2)). + repeat rewrite Zmult_assoc. + rewrite Zgcd_div_swap; auto; try ring. + apply False_ind; generalize F1. + rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto. + generalize F3; rewrite BigN.spec_div; rewrite BigN.spec_gcd; fold a b; + auto with zarith. + intros HH; rewrite <- HH; auto with zarith. + assert (FF:= Zgcd_is_gcd a b); inversion FF; auto. + intros p1 n1 p2 n2 Hn1 Hn2. + match goal with |- [norm ?X ?Y] == _ => + apply Qeq_trans with ([Qq X Y]); + [apply spec_norm | idtac] + end; try apply Qeq_refl. + rewrite BigN.spec_mul. + apply Zmult_lt_0_compat. + generalize Hn1; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; auto with zarith. + generalize (BigN.spec_pos n1) (BigN.spec_pos n2); auto with zarith. + generalize Hn2; simpl. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; auto with zarith. + generalize (BigN.spec_pos n1) (BigN.spec_pos n2); auto with zarith. + Qed. + + Theorem spec_mul_normc x y: wf x -> wf y -> + [[mul_norm x y]] = [[x]] * [[y]]. + intros x y Hx Hy; unfold to_Qc. + apply trans_equal with (!! ([x] * [y])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_mul_norm; auto. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + Definition inv (x: t): t := + match x with + | Qz (BigZ.Pos n) => + if BigN.eq_bool n BigN.zero then zero else Qq BigZ.one n + | Qz (BigZ.Neg n) => + if BigN.eq_bool n BigN.zero then zero else Qq BigZ.minus_one n + | Qq (BigZ.Pos n) d => + if BigN.eq_bool n BigN.zero then zero else Qq (BigZ.Pos d) n + | Qq (BigZ.Neg n) d => + if BigN.eq_bool n BigN.zero then zero else Qq (BigZ.Neg d) n + end. + + + Theorem wf_inv: forall x, wf x -> wf (inv x). + intros [ zx | nx dx]; unfold inv, wf; auto. + case zx; clear zx. + intros nx. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_mul. + intros nx. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0; rewrite BigN.spec_mul. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + intros _ HH; case HH. + intros H1 _. + case nx; clear nx. + intros nx. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; simpl; auto. + intros nx. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; simpl; auto. + Qed. + + Theorem spec_inv x: wf x -> + ([inv x] == /[x])%Q. + intros [ [x | x] _ | [nx | nx] dx]; unfold inv. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H. + unfold zero, to_Q; rewrite BigZ.spec_0. + unfold BigZ.to_Z; rewrite H; apply Qeq_refl. + assert (F: (0 < BigN.to_Z x)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos x)); auto with zarith. + unfold to_Q; rewrite BigZ.spec_1. + red; unfold Qinv; simpl. + generalize F; case BigN.to_Z; auto with zarith. + intros p Hp; discriminate Hp. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H. + unfold zero, to_Q; rewrite BigZ.spec_0. + unfold BigZ.to_Z; rewrite H; apply Qeq_refl. + assert (F: (0 < BigN.to_Z x)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos x)); auto with zarith. + red; unfold Qinv; simpl. + generalize F; case BigN.to_Z; simpl; auto with zarith. + intros p Hp; discriminate Hp. + simpl wf. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1. + intros HH; case HH. + intros _. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H. + unfold zero, to_Q; rewrite BigZ.spec_0. + unfold BigZ.to_Z; rewrite H; apply Qeq_refl. + assert (F: (0 < BigN.to_Z nx)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos nx)); auto with zarith. + red; unfold Qinv; simpl. + rewrite Z2P_correct; auto with zarith. + generalize F; case BigN.to_Z; auto with zarith. + intros p Hp; discriminate Hp. + generalize (BigN.spec_pos dx); auto with zarith. + simpl wf. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H1. + intros HH; case HH. + intros _. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; rewrite BigN.spec_0; intros H. + unfold zero, to_Q; rewrite BigZ.spec_0. + unfold BigZ.to_Z; rewrite H; apply Qeq_refl. + assert (F: (0 < BigN.to_Z nx)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos nx)); auto with zarith. + red; unfold Qinv; simpl. + rewrite Z2P_correct; auto with zarith. + generalize F; case BigN.to_Z; auto with zarith. + simpl; intros. + match goal with |- (?X = Zneg ?Y)%Z => + replace (Zneg Y) with (Zopp (Zpos Y)); + try rewrite Z2P_correct; auto with zarith + end. + rewrite Zpos_mult_morphism; + rewrite Z2P_correct; auto with zarith; try ring. + generalize (BigN.spec_pos dx); auto with zarith. + intros p Hp; discriminate Hp. + generalize (BigN.spec_pos dx); auto with zarith. + Qed. + + Theorem spec_invc x: wf x -> + [[inv x]] = /[[x]]. + intros x Hx; unfold to_Qc. + apply trans_equal with (!! (/[x])). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_inv; auto. + unfold Qcinv, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qinv_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + + Definition div x y := mul x (inv y). + + Theorem wf_div x y: wf x -> wf y -> wf (div x y). + intros x y Hx Hy; unfold div; apply wf_mul; auto. + apply wf_inv; auto. + Qed. + + Theorem spec_div x y: wf x -> wf y -> + ([div x y] == [x] / [y])%Q. + intros x y Hx Hy; unfold div; rewrite spec_mul; auto. + unfold Qdiv; apply Qmult_comp. + apply Qeq_refl. + apply spec_inv; auto. + apply wf_inv; auto. + Qed. + + Theorem spec_divc x y: wf x -> wf y -> + [[div x y]] = [[x]] / [[y]]. + intros x y Hx Hy; unfold div; rewrite spec_mulc; auto. + unfold Qcdiv; apply f_equal2 with (f := Qcmult); auto. + apply spec_invc; auto. + apply wf_inv; auto. + Qed. + + Definition div_norm x y := mul_norm x (inv y). + + Theorem wf_div_norm x y: wf x -> wf y -> wf (div_norm x y). + intros x y Hx Hy; unfold div_norm; apply wf_mul_norm; auto. + apply wf_inv; auto. + Qed. + + Theorem spec_div_norm x y: wf x -> wf y -> + ([div_norm x y] == [x] / [y])%Q. + intros x y Hx Hy; unfold div_norm; rewrite spec_mul_norm; auto. + unfold Qdiv; apply Qmult_comp. + apply Qeq_refl. + apply spec_inv; auto. + apply wf_inv; auto. + Qed. + + Theorem spec_div_normc x y: wf x -> wf y -> + [[div_norm x y]] = [[x]] / [[y]]. + intros x y Hx Hy; unfold div_norm; rewrite spec_mul_normc; auto. + unfold Qcdiv; apply f_equal2 with (f := Qcmult); auto. + apply spec_invc; auto. + apply wf_inv; auto. + Qed. + + Definition square (x: t): t := + match x with + | Qz zx => Qz (BigZ.square zx) + | Qq nx dx => Qq (BigZ.square nx) (BigN.square dx) + end. + + Theorem wf_square: forall x, wf x -> wf (square x). + intros [ zx | nx dx]; unfold square, wf; auto. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + rewrite BigN.spec_square; intros H1 H2; case H2. + case (Zmult_integral _ _ H1); auto. + Qed. + + Theorem spec_square x: wf x -> ([square x] == [x] ^ 2)%Q. + intros [ x | nx dx]; unfold square. + intros _. + red; simpl; rewrite BigZ.spec_square; auto with zarith. + unfold wf. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + intros _ HH; case HH. + intros H1 _. + red; simpl; rewrite BigZ.spec_square; auto with zarith. + assert (F: (0 < BigN.to_Z dx)%Z). + case (Zle_lt_or_eq _ _ (BigN.spec_pos dx)); auto with zarith. + assert (F1 : (0 < BigN.to_Z (BigN.square dx))%Z). + rewrite BigN.spec_square; apply Zmult_lt_0_compat; + auto with zarith. + rewrite Zpos_mult_morphism. + repeat rewrite Z2P_correct; auto with zarith. + rewrite BigN.spec_square; auto with zarith. + Qed. + + Theorem spec_squarec x: wf x -> [[square x]] = [[x]]^2. + intros x Hx; unfold to_Qc. + apply trans_equal with (!! ([x]^2)). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_square; auto. + simpl Qcpower. + replace (!! [x] * 1) with (!![x]); try ring. + simpl. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + + + Definition power_pos (x: t) p: t := + match x with + | Qz zx => Qz (BigZ.power_pos zx p) + | Qq nx dx => Qq (BigZ.power_pos nx p) (BigN.power_pos dx p) + end. + + Theorem wf_power_pos: forall x p, wf x -> wf (power_pos x p). + intros [ zx | nx dx] p; unfold power_pos, wf; auto. + repeat match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + rewrite BigN.spec_power_pos; simpl. + intros H1 H2 _. + case (Zle_lt_or_eq _ _ (BigN.spec_pos dx)); auto with zarith. + intros H3; generalize (Zpower_pos_pos _ p H3); auto with zarith. + Qed. + + Theorem spec_power_pos x p: wf x -> ([power_pos x p] == [x] ^ Zpos p)%Q. + Proof. + intros [x | nx dx] p; unfold power_pos. + intros _; unfold power_pos; red; simpl. + generalize (Qpower_decomp p (BigZ.to_Z x) 1). + unfold Qeq; simpl. + rewrite Zpower_pos_1_l; simpl Z2P. + rewrite Zmult_1_r. + intros H; rewrite H. + rewrite BigZ.spec_power_pos; simpl; ring. + unfold wf. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + intros _ HH; case HH. + intros H1 _. + assert (F1: (0 < BigN.to_Z dx)%Z). + generalize (BigN.spec_pos dx); auto with zarith. + assert (F2: (0 < BigN.to_Z dx ^ ' p)%Z). + unfold Zpower; apply Zpower_pos_pos; auto. + unfold power_pos; red; simpl. + rewrite Z2P_correct; rewrite BigN.spec_power_pos; auto. + generalize (Qpower_decomp p (BigZ.to_Z nx) + (Z2P (BigN.to_Z dx))). + unfold Qeq; simpl. + repeat rewrite Z2P_correct; auto. + unfold Qeq; simpl; intros HH. + rewrite HH. + rewrite BigZ.spec_power_pos; simpl; ring. + Qed. + + Theorem spec_power_posc x p: wf x -> + [[power_pos x p]] = [[x]] ^ nat_of_P p. + intros x p Hx; unfold to_Qc. + apply trans_equal with (!! ([x]^Zpos p)). + unfold Q2Qc. + apply Qc_decomp; intros _ _; unfold this. + apply Qred_complete; apply spec_power_pos; auto. + pattern p; apply Pind; clear p. + simpl; ring. + intros p Hrec. + rewrite nat_of_P_succ_morphism; simpl Qcpower. + rewrite <- Hrec. + unfold Qcmult, Q2Qc. + apply Qc_decomp; intros _ _; + unfold this. + apply Qred_complete. + assert (F: [x] ^ ' Psucc p == [x] * [x] ^ ' p). + simpl; generalize Hx; case x; simpl; clear x Hx Hrec. + intros x _; simpl; repeat rewrite Qpower_decomp; simpl. + red; simpl; repeat rewrite Zpower_pos_1_l; simpl Z2P. + rewrite Pplus_one_succ_l. + rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r; auto. + intros nx dx. + match goal with |- context[BigN.eq_bool ?X ?Y] => + generalize (BigN.spec_eq_bool X Y); case BigN.eq_bool + end; auto; rewrite BigN.spec_0. + intros _ HH; case HH. + intros H1 _. + assert (F1: (0 < BigN.to_Z dx)%Z). + generalize (BigN.spec_pos dx); auto with zarith. + simpl; repeat rewrite Qpower_decomp; simpl. + red; simpl; repeat rewrite Zpower_pos_1_l; simpl Z2P. + rewrite Pplus_one_succ_l. + rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r; auto. + repeat rewrite Zpos_mult_morphism. + repeat rewrite Z2P_correct; auto. + 2: apply Zpower_pos_pos; auto. + 2: apply Zpower_pos_pos; auto. + rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r; auto. + rewrite F. + apply Qmult_comp; apply Qeq_sym; apply Qred_correct. + Qed. + +End Qv. + diff --git a/theories/Numbers/Rational/SpecViaQ/QSig.v b/theories/Numbers/Rational/SpecViaQ/QSig.v new file mode 100644 index 00000000..a488c7c6 --- /dev/null +++ b/theories/Numbers/Rational/SpecViaQ/QSig.v @@ -0,0 +1,84 @@ +(************************************************************************) +(* 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: QSig.v 11028 2008-06-01 17:34:19Z letouzey $ i*) + +Require Import QArith Qpower. + +Open Scope Q_scope. + +(** * QSig *) + +(** Interface of a rich structure about rational numbers. + Specifications are written via translation to Q. +*) + +Module Type QType. + + Parameter t : Type. + + Parameter to_Q : t -> Q. + Notation "[ x ]" := (to_Q x). + + Definition eq x y := [x] == [y]. + + Parameter of_Q : Q -> t. + Parameter spec_of_Q: forall x, to_Q (of_Q x) == x. + + Parameter zero : t. + Parameter one : t. + Parameter minus_one : t. + + Parameter spec_0: [zero] == 0. + Parameter spec_1: [one] == 1. + Parameter spec_m1: [minus_one] == -(1). + + Parameter compare : t -> t -> comparison. + + Parameter spec_compare: forall x y, compare x y = ([x] ?= [y]). + + Definition lt n m := compare n m = Lt. + Definition le n m := compare n m <> Gt. + Definition min n m := match compare n m with Gt => m | _ => n end. + Definition max n m := match compare n m with Lt => m | _ => n end. + + Parameter add : t -> t -> t. + + Parameter spec_add: forall x y, [add x y] == [x] + [y]. + + Parameter sub : t -> t -> t. + + Parameter spec_sub: forall x y, [sub x y] == [x] - [y]. + + Parameter opp : t -> t. + + Parameter spec_opp: forall x, [opp x] == - [x]. + + Parameter mul : t -> t -> t. + + Parameter spec_mul: forall x y, [mul x y] == [x] * [y]. + + Parameter square : t -> t. + + Parameter spec_square: forall x, [square x] == [x] ^ 2. + + Parameter inv : t -> t. + + Parameter spec_inv : forall x, [inv x] == / [x]. + + Parameter div : t -> t -> t. + + Parameter spec_div: forall x y, [div x y] == [x] / [y]. + + Parameter power_pos : t -> positive -> t. + + Parameter spec_power_pos: forall x n, [power_pos x n] == [x] ^ Zpos n. + +End QType. + +(* TODO: add norm function and variants, add eq_bool, what about Qc ? *)
\ No newline at end of file diff --git a/theories/Program/Basics.v b/theories/Program/Basics.v new file mode 100644 index 00000000..a1a78acc --- /dev/null +++ b/theories/Program/Basics.v @@ -0,0 +1,57 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Standard functions and combinators. + * Proofs about them require functional extensionality and can be found in [Combinators]. + * + * Author: Matthieu Sozeau + * Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + * 91405 Orsay, France *) + +(* $Id: Basics.v 11046 2008-06-03 22:48:06Z msozeau $ *) + +(** The polymorphic identity function. *) + +Definition id {A} := fun x : A => x. + +(** Function composition. *) + +Definition compose {A B C} (g : B -> C) (f : A -> B) := + fun x : A => g (f x). + +Hint Unfold compose. + +Notation " g ∘ f " := (compose g f) + (at level 40, left associativity) : program_scope. + +Open Local Scope program_scope. + +(** The non-dependent function space between [A] and [B]. *) + +Definition arrow (A B : Type) := A -> B. + +(** Logical implication. *) + +Definition impl (A B : Prop) : Prop := A -> B. + +(** The constant function [const a] always returns [a]. *) + +Definition const {A B} (a : A) := fun _ : B => a. + +(** The [flip] combinator reverses the first two arguments of a function. *) + +Definition flip {A B C} (f : A -> B -> C) x y := f y x. + +(** Application as a combinator. *) + +Definition apply {A B} (f : A -> B) (x : A) := f x. + +(** Curryfication of [prod] is defined in [Logic.Datatypes]. *) + +Implicit Arguments prod_curry [[A] [B] [C]]. +Implicit Arguments prod_uncurry [[A] [B] [C]]. diff --git a/theories/Program/Combinators.v b/theories/Program/Combinators.v new file mode 100644 index 00000000..e267fbbe --- /dev/null +++ b/theories/Program/Combinators.v @@ -0,0 +1,71 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Proofs about standard combinators, exports functional extensionality. + * + * Author: Matthieu Sozeau + * Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + * 91405 Orsay, France *) + +Require Import Coq.Program.Basics. +Require Export Coq.Program.FunctionalExtensionality. + +Open Scope program_scope. + +(** Composition has [id] for neutral element and is associative. *) + +Lemma compose_id_left : forall A B (f : A -> B), id ∘ f = f. +Proof. + intros. + unfold id, compose. + symmetry. apply eta_expansion. +Qed. + +Lemma compose_id_right : forall A B (f : A -> B), f ∘ id = f. +Proof. + intros. + unfold id, compose. + symmetry ; apply eta_expansion. +Qed. + +Lemma compose_assoc : forall A B C D (f : A -> B) (g : B -> C) (h : C -> D), + h ∘ g ∘ f = h ∘ (g ∘ f). +Proof. + intros. + reflexivity. +Qed. + +Hint Rewrite @compose_id_left @compose_id_right @compose_assoc : core. + +(** [flip] is involutive. *) + +Lemma flip_flip : forall A B C, @flip A B C ∘ flip = id. +Proof. + unfold flip, compose. + intros. + extensionality x ; extensionality y ; extensionality z. + reflexivity. +Qed. + +(** [prod_curry] and [prod_uncurry] are each others inverses. *) + +Lemma prod_uncurry_curry : forall A B C, @prod_uncurry A B C ∘ prod_curry = id. +Proof. + simpl ; intros. + unfold prod_uncurry, prod_curry, compose. + extensionality x ; extensionality y ; extensionality z. + reflexivity. +Qed. + +Lemma prod_curry_uncurry : forall A B C, @prod_curry A B C ∘ prod_uncurry = id. +Proof. + simpl ; intros. + unfold prod_uncurry, prod_curry, compose. + extensionality x ; extensionality p. + destruct p ; simpl ; reflexivity. +Qed. diff --git a/theories/Program/Equality.v b/theories/Program/Equality.v new file mode 100644 index 00000000..d19f29c3 --- /dev/null +++ b/theories/Program/Equality.v @@ -0,0 +1,264 @@ +(* -*- coq-prog-args: ("-emacs-U") -*- *) +(************************************************************************) +(* 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: Equality.v 11023 2008-05-30 11:08:39Z msozeau $ i*) + +(** Tactics related to (dependent) equality and proof irrelevance. *) + +Require Export ProofIrrelevance. +Require Export JMeq. + +Require Import Coq.Program.Tactics. + +(** Notation for heterogenous equality. *) + +Notation " [ x : X ] = [ y : Y ] " := (@JMeq X x Y y) (at level 0, X at next level, Y at next level). + +(** Do something on an heterogeneous equality appearing in the context. *) + +Ltac on_JMeq tac := + match goal with + | [ H : @JMeq ?x ?X ?y ?Y |- _ ] => tac H + end. + +(** Try to apply [JMeq_eq] to get back a regular equality when the two types are equal. *) + +Ltac simpl_one_JMeq := + on_JMeq ltac:(fun H => replace_hyp H (JMeq_eq H)). + +(** Repeat it for every possible hypothesis. *) + +Ltac simpl_JMeq := repeat simpl_one_JMeq. + +(** Just simplify an h.eq. without clearing it. *) + +Ltac simpl_one_dep_JMeq := + on_JMeq + ltac:(fun H => let H' := fresh "H" in + assert (H' := JMeq_eq H)). + +Require Import Eqdep. + +(** Simplify dependent equality using sigmas to equality of the second projections if possible. + Uses UIP. *) + +Ltac simpl_existT := + match goal with + [ H : existT _ ?x _ = existT _ ?x _ |- _ ] => + let Hi := fresh H in assert(Hi:=inj_pairT2 _ _ _ _ _ H) ; clear H + end. + +Ltac simpl_existTs := repeat simpl_existT. + +(** Tries to eliminate a call to [eq_rect] (the substitution principle) by any means available. *) + +Ltac elim_eq_rect := + match goal with + | [ |- ?t ] => + match t with + | context [ @eq_rect _ _ _ _ _ ?p ] => + let P := fresh "P" in + set (P := p); simpl in P ; + ((case P ; clear P) || (clearbody P; rewrite (UIP_refl _ _ P); clear P)) + | context [ @eq_rect _ _ _ _ _ ?p _ ] => + let P := fresh "P" in + set (P := p); simpl in P ; + ((case P ; clear P) || (clearbody P; rewrite (UIP_refl _ _ P); clear P)) + end + end. + +(** Rewrite using uniqueness of indentity proofs [H = refl_equal X]. *) + +Ltac simpl_uip := + match goal with + [ H : ?X = ?X |- _ ] => rewrite (UIP_refl _ _ H) in *; clear H + end. + +(** Simplify equalities appearing in the context and goal. *) + +Ltac simpl_eq := simpl ; repeat (elim_eq_rect ; simpl) ; repeat (simpl_uip ; simpl). + +(** Try to abstract a proof of equality, if no proof of the same equality is present in the context. *) + +Ltac abstract_eq_hyp H' p := + let ty := type of p in + let tyred := eval simpl in ty in + match tyred with + ?X = ?Y => + match goal with + | [ H : X = Y |- _ ] => fail 1 + | _ => set (H':=p) ; try (change p with H') ; clearbody H' ; simpl in H' + end + end. + +(** Apply the tactic tac to proofs of equality appearing as coercion arguments. + Just redefine this tactic (using [Ltac on_coerce_proof tac ::=]) to handle custom coercion operators. + *) + +Ltac on_coerce_proof tac T := + match T with + | context [ eq_rect _ _ _ _ ?p ] => tac p + end. + +Ltac on_coerce_proof_gl tac := + match goal with + [ |- ?T ] => on_coerce_proof tac T + end. + +(** Abstract proofs of equalities of coercions. *) + +Ltac abstract_eq_proof := on_coerce_proof_gl ltac:(fun p => let H := fresh "eqH" in abstract_eq_hyp H p). + +Ltac abstract_eq_proofs := repeat abstract_eq_proof. + +(** Factorize proofs, by using proof irrelevance so that two proofs of the same equality + in the goal become convertible. *) + +Ltac pi_eq_proof_hyp p := + let ty := type of p in + let tyred := eval simpl in ty in + match tyred with + ?X = ?Y => + match goal with + | [ H : X = Y |- _ ] => + match p with + | H => fail 2 + | _ => rewrite (proof_irrelevance (X = Y) p H) + end + | _ => fail " No hypothesis with same type " + end + end. + +(** Factorize proofs of equality appearing as coercion arguments. *) + +Ltac pi_eq_proof := on_coerce_proof_gl pi_eq_proof_hyp. + +Ltac pi_eq_proofs := repeat pi_eq_proof. + +(** The two preceding tactics in sequence. *) + +Ltac clear_eq_proofs := + abstract_eq_proofs ; pi_eq_proofs. + +Hint Rewrite <- eq_rect_eq : refl_id. + +(** The refl_id database should be populated with lemmas of the form + [coerce_* t (refl_equal _) = t]. *) + +Ltac rewrite_refl_id := autorewrite with refl_id. + +(** Clear the context and goal of equality proofs. *) + +Ltac clear_eq_ctx := + rewrite_refl_id ; clear_eq_proofs. + +(** Reapeated elimination of [eq_rect] applications. + Abstracting equalities makes it run much faster than an naive implementation. *) + +Ltac simpl_eqs := + repeat (elim_eq_rect ; simpl ; clear_eq_ctx). + +(** Clear unused reflexivity proofs. *) + +Ltac clear_refl_eq := + match goal with [ H : ?X = ?X |- _ ] => clear H end. +Ltac clear_refl_eqs := repeat clear_refl_eq. + +(** Clear unused equality proofs. *) + +Ltac clear_eq := + match goal with [ H : _ = _ |- _ ] => clear H end. +Ltac clear_eqs := repeat clear_eq. + +(** Combine all the tactics to simplify goals containing coercions. *) + +Ltac simplify_eqs := + simpl ; simpl_eqs ; clear_eq_ctx ; clear_refl_eqs ; + try subst ; simpl ; repeat simpl_uip ; rewrite_refl_id. + +(** A tactic that tries to remove trivial equality guards in induction hypotheses coming + from [dependent induction]/[generalize_eqs] invocations. *) + + +Ltac simpl_IH_eq H := + match type of H with + | @JMeq _ ?x _ _ -> _ => + refine_hyp (H (JMeq_refl x)) + | _ -> @JMeq _ ?x _ _ -> _ => + refine_hyp (H _ (JMeq_refl x)) + | _ -> _ -> @JMeq _ ?x _ _ -> _ => + refine_hyp (H _ _ (JMeq_refl x)) + | _ -> _ -> _ -> @JMeq _ ?x _ _ -> _ => + refine_hyp (H _ _ _ (JMeq_refl x)) + | _ -> _ -> _ -> _ -> @JMeq _ ?x _ _ -> _ => + refine_hyp (H _ _ _ _ (JMeq_refl x)) + | _ -> _ -> _ -> _ -> _ -> @JMeq _ ?x _ _ -> _ => + refine_hyp (H _ _ _ _ _ (JMeq_refl x)) + | ?x = _ -> _ => + refine_hyp (H (refl_equal x)) + | _ -> ?x = _ -> _ => + refine_hyp (H _ (refl_equal x)) + | _ -> _ -> ?x = _ -> _ => + refine_hyp (H _ _ (refl_equal x)) + | _ -> _ -> _ -> ?x = _ -> _ => + refine_hyp (H _ _ _ (refl_equal x)) + | _ -> _ -> _ -> _ -> ?x = _ -> _ => + refine_hyp (H _ _ _ _ (refl_equal x)) + | _ -> _ -> _ -> _ -> _ -> ?x = _ -> _ => + refine_hyp (H _ _ _ _ _ (refl_equal x)) + end. + +Ltac simpl_IH_eqs H := repeat simpl_IH_eq H. + +Ltac do_simpl_IHs_eqs := + match goal with + | [ H : context [ @JMeq _ _ _ _ -> _ ] |- _ ] => progress (simpl_IH_eqs H) + | [ H : context [ _ = _ -> _ ] |- _ ] => progress (simpl_IH_eqs H) + end. + +Ltac simpl_IHs_eqs := repeat do_simpl_IHs_eqs. + +Ltac simpl_depind := subst* ; autoinjections ; try discriminates ; + simpl_JMeq ; simpl_existTs ; simpl_IHs_eqs. + +(** The following tactics allow to do induction on an already instantiated inductive predicate + by first generalizing it and adding the proper equalities to the context, in a maner similar to + the BasicElim tactic of "Elimination with a motive" by Conor McBride. *) + +(** The [do_depind] higher-order tactic takes an induction tactic as argument and an hypothesis + and starts a dependent induction using this tactic. *) + +Ltac do_depind tac H := + generalize_eqs H ; tac H ; repeat progress simpl_depind. + +(** Calls [destruct] on the generalized hypothesis, results should be similar to inversion. *) + +Tactic Notation "dependent" "destruction" ident(H) := + do_depind ltac:(fun H => destruct H ; intros) H ; subst*. + +Tactic Notation "dependent" "destruction" ident(H) "using" constr(c) := + do_depind ltac:(fun H => destruct H using c ; intros) H. + +(** Then we have wrappers for usual calls to induction. One can customize the induction tactic by + writting another wrapper calling do_depind. *) + +Tactic Notation "dependent" "induction" ident(H) := + do_depind ltac:(fun H => induction H ; intros) H. + +Tactic Notation "dependent" "induction" ident(H) "using" constr(c) := + do_depind ltac:(fun H => induction H using c ; intros) H. + +(** This tactic also generalizes the goal by the given variables before the induction. *) + +Tactic Notation "dependent" "induction" ident(H) "generalizing" ne_hyp_list(l) := + do_depind ltac:(fun H => generalize l ; clear l ; induction H ; intros) H. + +Tactic Notation "dependent" "induction" ident(H) "generalizing" ne_hyp_list(l) "using" constr(c) := + do_depind ltac:(fun H => generalize l ; clear l ; induction H using c ; intros) H. + diff --git a/theories/Program/FunctionalExtensionality.v b/theories/Program/FunctionalExtensionality.v new file mode 100644 index 00000000..b5ad5b4d --- /dev/null +++ b/theories/Program/FunctionalExtensionality.v @@ -0,0 +1,109 @@ +(* -*- coq-prog-args: ("-emacs-U" "-nois") -*- *) +(************************************************************************) +(* 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: FunctionalExtensionality.v 10739 2008-04-01 14:45:20Z herbelin $ i*) + +(** This module states the axiom of (dependent) functional extensionality and (dependent) eta-expansion. + It introduces a tactic [extensionality] to apply the axiom of extensionality to an equality goal. + + It also defines two lemmas for expansion of fixpoint defs using extensionnality and proof-irrelevance + to avoid a side condition on the functionals. *) + +Require Import Coq.Program.Utils. +Require Import Coq.Program.Wf. +Require Import Coq.Program.Equality. + +Set Implicit Arguments. +Unset Strict Implicit. + +(** The converse of functional equality. *) + +Lemma equal_f : forall A B : Type, forall (f g : A -> B), + f = g -> forall x, f x = g x. +Proof. + intros. + rewrite H. + auto. +Qed. + +(** Statements of functional equality for simple and dependent functions. *) + +Axiom fun_extensionality_dep : forall A, forall B : (A -> Type), + forall (f g : forall x : A, B x), + (forall x, f x = g x) -> f = g. + +Lemma fun_extensionality : forall A B (f g : A -> B), + (forall x, f x = g x) -> f = g. +Proof. + intros ; apply fun_extensionality_dep. + assumption. +Qed. + +Hint Resolve fun_extensionality fun_extensionality_dep : program. + +(** Apply [fun_extensionality], introducing variable x. *) + +Tactic Notation "extensionality" ident(x) := + match goal with + [ |- ?X = ?Y ] => apply (@fun_extensionality _ _ X Y) || apply (@fun_extensionality_dep _ _ X Y) ; intro x + end. + +(** Eta expansion follows from extensionality. *) + +Lemma eta_expansion_dep : forall A (B : A -> Type) (f : forall x : A, B x), + f = fun x => f x. +Proof. + intros. + extensionality x. + reflexivity. +Qed. + +Lemma eta_expansion : forall A B (f : A -> B), + f = fun x => f x. +Proof. + intros ; apply eta_expansion_dep. +Qed. + +(** The two following lemmas allow to unfold a well-founded fixpoint definition without + restriction using the functional extensionality axiom. *) + +(** For a function defined with Program using a well-founded order. *) + +Program Lemma fix_sub_eq_ext : + forall (A : Set) (R : A -> A -> Prop) (Rwf : well_founded R) + (P : A -> Set) + (F_sub : forall x : A, (forall (y : A | R y x), P y) -> P x), + forall x : A, + Fix_sub A R Rwf P F_sub x = + F_sub x (fun (y : A | R y x) => Fix A R Rwf P F_sub y). +Proof. + intros ; apply Fix_eq ; auto. + intros. + assert(f = g). + extensionality y ; apply H. + rewrite H0 ; auto. +Qed. + +(** For a function defined with Program using a measure. *) + +Program Lemma fix_sub_measure_eq_ext : + forall (A : Type) (f : A -> nat) (P : A -> Type) + (F_sub : forall x : A, (forall (y : A | f y < f x), P y) -> P x), + forall x : A, + Fix_measure_sub A f P F_sub x = + F_sub x (fun (y : A | f y < f x) => Fix_measure_sub A f P F_sub y). +Proof. + intros ; apply Fix_measure_eq ; auto. + intros. + assert(f0 = g). + extensionality y ; apply H. + rewrite H0 ; auto. +Qed. + + diff --git a/theories/Program/Program.v b/theories/Program/Program.v new file mode 100644 index 00000000..b6c3031e --- /dev/null +++ b/theories/Program/Program.v @@ -0,0 +1,7 @@ +Require Export Coq.Program.Utils. +Require Export Coq.Program.Wf. +Require Export Coq.Program.Equality. +Require Export Coq.Program.Subset. +Require Export Coq.Program.Basics. +Require Export Coq.Program.Combinators. +Require Export Coq.Program.Syntax.
\ No newline at end of file diff --git a/theories/Program/Subset.v b/theories/Program/Subset.v new file mode 100644 index 00000000..d021326a --- /dev/null +++ b/theories/Program/Subset.v @@ -0,0 +1,116 @@ +(************************************************************************) +(* 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 Coq.Program.Utils. +Require Import Coq.Program.Equality. + +Open Local Scope program_scope. + +(** Tactics related to subsets and proof irrelevance. *) + +(** The following tactics implement a poor-man's solution for proof-irrelevance: it tries to + factorize every proof of the same proposition in a goal so that equality of such proofs becomes trivial. *) + +Ltac on_subset_proof_aux tac T := + match T with + | context [ exist ?P _ ?p ] => try on_subset_proof_aux tac P ; tac p + end. + +Ltac on_subset_proof tac := + match goal with + [ |- ?T ] => on_subset_proof_aux tac T + end. + +Ltac abstract_any_hyp H' p := + match type of p with + ?X => + match goal with + | [ H : X |- _ ] => fail 1 + | _ => set (H':=p) ; try (change p with H') ; clearbody H' + end + end. + +Ltac abstract_subset_proof := + on_subset_proof ltac:(fun p => let H := fresh "eqH" in abstract_any_hyp H p ; simpl in H). + +Ltac abstract_subset_proofs := repeat abstract_subset_proof. + +Ltac pi_subset_proof_hyp p := + match type of p with + ?X => + match goal with + | [ H : X |- _ ] => + match p with + | H => fail 2 + | _ => rewrite (proof_irrelevance X p H) + end + | _ => fail " No hypothesis with same type " + end + end. + +Ltac pi_subset_proof := on_subset_proof pi_subset_proof_hyp. + +Ltac pi_subset_proofs := repeat pi_subset_proof. + +(** The two preceding tactics in sequence. *) + +Ltac clear_subset_proofs := + abstract_subset_proofs ; simpl in * |- ; pi_subset_proofs ; clear_dups. + +Ltac pi := repeat progress f_equal ; apply proof_irrelevance. + +Lemma subset_eq : forall A (P : A -> Prop) (n m : sig P), n = m <-> `n = `m. +Proof. + induction n. + induction m. + simpl. + split ; intros ; subst. + + inversion H. + reflexivity. + + pi. +Qed. + +(* Somewhat trivial definition, but not unfolded automatically hence we can match on [match_eq ?A ?B ?x ?f] + in tactics. *) + +Definition match_eq (A B : Type) (x : A) (fn : forall (y : A | y = x), B) : B := + fn (exist _ x (refl_equal x)). + +(* This is what we want to be able to do: replace the originaly matched object by a new, + propositionally equal one. If [fn] works on [x] it should work on any [y | y = x]. *) + +Lemma match_eq_rewrite : forall (A B : Type) (x : A) (fn : forall (y : A | y = x), B) + (y : A | y = x), + match_eq A B x fn = fn y. +Proof. + intros. + unfold match_eq. + f_equal. + destruct y. + (* uses proof-irrelevance *) + apply <- subset_eq. + symmetry. assumption. +Qed. + +(** Now we make a tactic to be able to rewrite a term [t] which is applied to a [match_eq] using an arbitrary + equality [t = u], and [u] is now the subject of the [match]. *) + +Ltac rewrite_match_eq H := + match goal with + [ |- ?T ] => + match T with + context [ match_eq ?A ?B ?t ?f ] => + rewrite (match_eq_rewrite A B t f (exist _ _ (sym_eq H))) + end + end. + +(** Otherwise we can simply unfold [match_eq] and the term trivially reduces to the original definition. *) + +Ltac simpl_match_eq := unfold match_eq ; simpl. diff --git a/theories/Program/Syntax.v b/theories/Program/Syntax.v new file mode 100644 index 00000000..6cd75257 --- /dev/null +++ b/theories/Program/Syntax.v @@ -0,0 +1,59 @@ +(* -*- coq-prog-args: ("-emacs-U") -*- *) +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Custom notations and implicits for Coq prelude definitions. + * + * Author: Matthieu Sozeau + * Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud + * 91405 Orsay, France *) + +(** Notations for the unit type and value. *) + +Notation " () " := Datatypes.unit : type_scope. +Notation " () " := tt. + +(** Set maximally inserted implicit arguments for standard definitions. *) + +Implicit Arguments eq [[A]]. + +Implicit Arguments Some [[A]]. +Implicit Arguments None [[A]]. + +Implicit Arguments inl [[A] [B]]. +Implicit Arguments inr [[A] [B]]. + +Implicit Arguments left [[A] [B]]. +Implicit Arguments right [[A] [B]]. + +Require Import Coq.Lists.List. + +Implicit Arguments nil [[A]]. +Implicit Arguments cons [[A]]. + +(** Standard notations for lists. *) + +Notation " [ ] " := nil : list_scope. +Notation " [ x ] " := (cons x nil) : list_scope. +Notation " [ x ; .. ; y ] " := (cons x .. (cons y nil) ..) : list_scope. + +(** n-ary exists *) + +Notation " 'exists' x y , p" := (ex (fun x => (ex (fun y => p)))) + (at level 200, x ident, y ident, right associativity) : type_scope. + +Notation " 'exists' x y z , p" := (ex (fun x => (ex (fun y => (ex (fun z => p)))))) + (at level 200, x ident, y ident, z ident, right associativity) : type_scope. + +Notation " 'exists' x y z w , p" := (ex (fun x => (ex (fun y => (ex (fun z => (ex (fun w => p)))))))) + (at level 200, x ident, y ident, z ident, w ident, right associativity) : type_scope. + +Tactic Notation "exist" constr(x) := exists x. +Tactic Notation "exist" constr(x) constr(y) := exists x ; exists y. +Tactic Notation "exist" constr(x) constr(y) constr(z) := exists x ; exists y ; exists z. +Tactic Notation "exist" constr(x) constr(y) constr(z) constr(w) := exists x ; exists y ; exists z ; exists w. diff --git a/theories/Program/Tactics.v b/theories/Program/Tactics.v new file mode 100644 index 00000000..41b170c9 --- /dev/null +++ b/theories/Program/Tactics.v @@ -0,0 +1,234 @@ +(************************************************************************) +(* 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: Tactics.v 11122 2008-06-13 14:18:44Z msozeau $ i*) + +(** This module implements various tactics used to simplify the goals produced by Program, + which are also generally useful. *) + +(** Destructs one pair, without care regarding naming. *) + +Ltac destruct_one_pair := + match goal with + | [H : (_ /\ _) |- _] => destruct H + | [H : prod _ _ |- _] => destruct H + end. + +(** Repeateadly destruct pairs. *) + +Ltac destruct_pairs := repeat (destruct_one_pair). + +(** Destruct one existential package, keeping the name of the hypothesis for the first component. *) + +Ltac destruct_one_ex := + let tac H := let ph := fresh "H" in (destruct H as [H ph]) in + let tacT H := let ph := fresh "X" in (destruct H as [H ph]) in + match goal with + | [H : (ex _) |- _] => tac H + | [H : (sig ?P) |- _ ] => tac H + | [H : (sigT ?P) |- _ ] => tacT H + | [H : (ex2 _) |- _] => tac H + end. + +(** Repeateadly destruct existentials. *) + +Ltac destruct_exists := repeat (destruct_one_ex). + +(** Repeateadly destruct conjunctions and existentials. *) + +Ltac destruct_conjs := repeat (destruct_one_pair || destruct_one_ex). + +(** Destruct an existential hypothesis [t] keeping its name for the first component + and using [Ht] for the second *) + +Tactic Notation "destruct" "exist" ident(t) ident(Ht) := destruct t as [t Ht]. + +(** Destruct a disjunction keeping its name in both subgoals. *) + +Tactic Notation "destruct" "or" ident(H) := destruct H as [H|H]. + +(** Discriminate that also work on a [x <> x] hypothesis. *) + +Ltac discriminates := + match goal with + | [ H : ?x <> ?x |- _ ] => elim H ; reflexivity + | _ => discriminate + end. + +(** Revert the last hypothesis. *) + +Ltac revert_last := + match goal with + [ H : _ |- _ ] => revert H + end. + +(** Reapeateadly reverse the last hypothesis, putting everything in the goal. *) + +Ltac reverse := repeat revert_last. + +(** Clear duplicated hypotheses *) + +Ltac clear_dup := + match goal with + | [ H : ?X |- _ ] => + match goal with + | [ H' : X |- _ ] => + match H' with + | H => fail 2 + | _ => clear H' || clear H + end + end + end. + +Ltac clear_dups := repeat clear_dup. + +(** A non-failing subst that substitutes as much as possible. *) + +Ltac subst_no_fail := + repeat (match goal with + [ H : ?X = ?Y |- _ ] => subst X || subst Y + end). + +Tactic Notation "subst" "*" := subst_no_fail. + +Ltac on_application f tac T := + match T with + | context [f ?x ?y ?z ?w ?v ?u ?a ?b ?c] => tac (f x y z w v u a b c) + | context [f ?x ?y ?z ?w ?v ?u ?a ?b] => tac (f x y z w v u a b) + | context [f ?x ?y ?z ?w ?v ?u ?a] => tac (f x y z w v u a) + | context [f ?x ?y ?z ?w ?v ?u] => tac (f x y z w v u) + | context [f ?x ?y ?z ?w ?v] => tac (f x y z w v) + | context [f ?x ?y ?z ?w] => tac (f x y z w) + | context [f ?x ?y ?z] => tac (f x y z) + | context [f ?x ?y] => tac (f x y) + | context [f ?x] => tac (f x) + end. + +(** Tactical [on_call f tac] applies [tac] on any application of [f] in the hypothesis or goal. *) + +Ltac on_call f tac := + match goal with + | |- ?T => on_application f tac T + | H : ?T |- _ => on_application f tac T + end. + +(* Destructs calls to f in hypothesis or conclusion, useful if f creates a subset object. *) + +Ltac destruct_call f := + let tac t := (destruct t) in on_call f tac. + +Ltac destruct_calls f := repeat destruct_call f. + +Ltac destruct_call_in f H := + let tac t := (destruct t) in + let T := type of H in + on_application f tac T. + +Ltac destruct_call_as f l := + let tac t := (destruct t as l) in on_call f tac. + +Ltac destruct_call_as_in f l H := + let tac t := (destruct t as l) in + let T := type of H in + on_application f tac T. + +Tactic Notation "destruct_call" constr(f) := destruct_call f. + +(** Permit to name the results of destructing the call to [f]. *) + +Tactic Notation "destruct_call" constr(f) "as" simple_intropattern(l) := + destruct_call_as f l. + +(** Specify the hypothesis in which the call occurs as well. *) + +Tactic Notation "destruct_call" constr(f) "in" hyp(id) := + destruct_call_in f id. + +Tactic Notation "destruct_call" constr(f) "as" simple_intropattern(l) "in" hyp(id) := + destruct_call_as_in f l id. + +(** Try to inject any potential constructor equality hypothesis. *) + +Ltac autoinjection := + let tac H := progress (inversion H ; subst ; clear_dups) ; clear H in + match goal with + | [ H : ?f ?a = ?f' ?a' |- _ ] => tac H + | [ H : ?f ?a ?b = ?f' ?a' ?b' |- _ ] => tac H + | [ H : ?f ?a ?b ?c = ?f' ?a' ?b' ?c' |- _ ] => tac H + | [ H : ?f ?a ?b ?c ?d= ?f' ?a' ?b' ?c' ?d' |- _ ] => tac H + | [ H : ?f ?a ?b ?c ?d ?e= ?f' ?a' ?b' ?c' ?d' ?e' |- _ ] => tac H + | [ H : ?f ?a ?b ?c ?d ?e ?g= ?f' ?a' ?b' ?c' ?d' ?e' ?g' |- _ ] => tac H + | [ H : ?f ?a ?b ?c ?d ?e ?g ?h= ?f' ?a' ?b' ?c' ?d' ?e'?g' ?h' |- _ ] => tac H + | [ H : ?f ?a ?b ?c ?d ?e ?g ?h ?i = ?f' ?a' ?b' ?c' ?d' ?e'?g' ?h' ?i' |- _ ] => tac H + | [ H : ?f ?a ?b ?c ?d ?e ?g ?h ?i ?j = ?f' ?a' ?b' ?c' ?d' ?e'?g' ?h' ?i' ?j' |- _ ] => tac H + end. + +Ltac autoinjections := repeat autoinjection. + +(** Destruct an hypothesis by first copying it to avoid dependencies. *) + +Ltac destruct_nondep H := let H0 := fresh "H" in assert(H0 := H); destruct H0. + +(** If bang appears in the goal, it means that we have a proof of False and the goal is solved. *) + +Ltac bang := + match goal with + | |- ?x => + match x with + | context [False_rect _ ?p] => elim p + end + end. + +(** A tactic to show contradiction by first asserting an automatically provable hypothesis. *) +Tactic Notation "contradiction" "by" constr(t) := + let H := fresh in assert t as H by auto with * ; contradiction. + +(** A tactic that adds [H:=p:typeof(p)] to the context if no hypothesis of the same type appears in the goal. + Useful to do saturation using tactics. *) + +Ltac add_hypothesis H' p := + match type of p with + ?X => + match goal with + | [ H : X |- _ ] => fail 1 + | _ => set (H':=p) ; try (change p with H') ; clearbody H' + end + end. + +(** A tactic to replace an hypothesis by another term. *) + +Ltac replace_hyp H c := + let H' := fresh "H" in + assert(H' := c) ; clear H ; rename H' into H. + +(** A tactic to refine an hypothesis by supplying some of its arguments. *) + +Ltac refine_hyp c := + let tac H := replace_hyp H c in + match c with + | ?H _ => tac H + | ?H _ _ => tac H + | ?H _ _ _ => tac H + | ?H _ _ _ _ => tac H + | ?H _ _ _ _ _ => tac H + | ?H _ _ _ _ _ _ => tac H + | ?H _ _ _ _ _ _ _ => tac H + | ?H _ _ _ _ _ _ _ _ => tac H + end. + +(** The default simplification tactic used by Program is defined by [program_simpl], sometimes [auto] + is not enough, better rebind using [Obligations Tactic := tac] in this case, + possibly using [program_simplify] to use standard goal-cleaning tactics. *) + +Ltac program_simplify := + simpl ; intros ; destruct_conjs ; simpl proj1_sig in * ; subst* ; autoinjections ; try discriminates ; + try (solve [ red ; intros ; destruct_conjs ; autoinjections ; discriminates ]). + +Ltac program_simpl := program_simplify ; auto. + +Ltac obligations_tactic := program_simpl. diff --git a/theories/Program/Utils.v b/theories/Program/Utils.v new file mode 100644 index 00000000..21eee0ca --- /dev/null +++ b/theories/Program/Utils.v @@ -0,0 +1,56 @@ +(************************************************************************) +(* 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: Utils.v 10919 2008-05-11 22:04:26Z msozeau $ i*) + +Require Export Coq.Program.Tactics. + +Set Implicit Arguments. + +(** A simpler notation for subsets defined on a cartesian product. *) + +Notation "{ ( x , y ) : A | P }" := + (sig (fun anonymous : A => let (x,y) := anonymous in P)) + (x ident, y ident, at level 10) : type_scope. + +(** Generates an obligation to prove False. *) + +Notation " ! " := (False_rect _ _) : program_scope. + +Delimit Scope program_scope with prg. + +(** Abbreviation for first projection and hiding of proofs of subset objects. *) + +Notation " ` t " := (proj1_sig t) (at level 10, t at next level) : program_scope. + +(** Coerces objects to their support before comparing them. *) + +Notation " x '`=' y " := ((x :>) = (y :>)) (at level 70) : program_scope. + +Require Import Coq.Bool.Sumbool. + +(** Construct a dependent disjunction from a boolean. *) + +Notation dec := sumbool_of_bool. + +(** The notations [in_right] and [in_left] construct objects of a dependent disjunction. *) + +(** Hide proofs and generates obligations when put in a term. *) + +Notation "'in_left'" := (@left _ _ _) : program_scope. +Notation "'in_right'" := (@right _ _ _) : program_scope. + +(** Extraction directives *) +(* +Extraction Inline proj1_sig. +Extract Inductive unit => "unit" [ "()" ]. +Extract Inductive bool => "bool" [ "true" "false" ]. +Extract Inductive sumbool => "bool" [ "true" "false" ]. +(* Extract Inductive prod "'a" "'b" => " 'a * 'b " [ "(,)" ]. *) +(* Extract Inductive sigT => "prod" [ "" ]. *) +*)
\ No newline at end of file diff --git a/theories/Program/Wf.v b/theories/Program/Wf.v new file mode 100644 index 00000000..b6ba5d44 --- /dev/null +++ b/theories/Program/Wf.v @@ -0,0 +1,148 @@ +Require Import Coq.Init.Wf. +Require Import Coq.Program.Utils. +Require Import ProofIrrelevance. + +Open Local Scope program_scope. + +Implicit Arguments Acc_inv [A R x y]. + +(** Reformulation of the Wellfounded module using subsets where possible. *) + +Section Well_founded. + Variable A : Type. + Variable R : A -> A -> Prop. + Hypothesis Rwf : well_founded R. + + Section Acc. + + Variable P : A -> Type. + + Variable F_sub : forall x:A, (forall y: { y : A | R y x }, P (proj1_sig y)) -> P x. + + Fixpoint Fix_F_sub (x : A) (r : Acc R x) {struct r} : P x := + F_sub x (fun y: { y : A | R y x} => Fix_F_sub (proj1_sig y) + (Acc_inv r (proj2_sig y))). + + Definition Fix_sub (x : A) := Fix_F_sub x (Rwf x). + End Acc. + + Section FixPoint. + Variable P : A -> Type. + + Variable F_sub : forall x:A, (forall y: { y : A | R y x }, P (proj1_sig y)) -> P x. + + Notation Fix_F := (Fix_F_sub P F_sub) (only parsing). (* alias *) + + Definition Fix (x:A) := Fix_F_sub P F_sub x (Rwf x). + + Hypothesis + F_ext : + forall (x:A) (f g:forall y:{y:A | R y x}, P (`y)), + (forall (y : A | R y x), f y = g y) -> F_sub x f = F_sub x g. + + Lemma Fix_F_eq : + forall (x:A) (r:Acc R x), + F_sub x (fun (y:A|R y x) => Fix_F (`y) (Acc_inv r (proj2_sig y))) = Fix_F x r. + Proof. + destruct r using Acc_inv_dep; auto. + Qed. + + Lemma Fix_F_inv : forall (x:A) (r s:Acc R x), Fix_F x r = Fix_F x s. + Proof. + intro x; induction (Rwf x); intros. + rewrite (proof_irrelevance (Acc R x) r s) ; auto. + Qed. + + Lemma Fix_eq : forall x:A, Fix x = F_sub x (fun (y:A|R y x) => Fix (proj1_sig y)). + Proof. + intro x; unfold Fix in |- *. + rewrite <- (Fix_F_eq ). + apply F_ext; intros. + apply Fix_F_inv. + Qed. + + Lemma fix_sub_eq : + forall x : A, + Fix_sub P F_sub x = + let f_sub := F_sub in + f_sub x (fun (y : A | R y x) => Fix (`y)). + exact Fix_eq. + Qed. + + End FixPoint. + +End Well_founded. + +Extraction Inline Fix_F_sub Fix_sub. + +Require Import Wf_nat. +Require Import Lt. + +Section Well_founded_measure. + Variable A : Type. + Variable m : A -> nat. + + Section Acc. + + Variable P : A -> Type. + + Variable F_sub : forall x:A, (forall y: { y : A | m y < m x }, P (proj1_sig y)) -> P x. + + Program Fixpoint Fix_measure_F_sub (x : A) (r : Acc lt (m x)) {struct r} : P x := + F_sub x (fun (y : A | m y < m x) => Fix_measure_F_sub y + (@Acc_inv _ _ _ r (m y) (proj2_sig y))). + + Definition Fix_measure_sub (x : A) := Fix_measure_F_sub x (lt_wf (m x)). + + End Acc. + + Section FixPoint. + Variable P : A -> Type. + + Program Variable F_sub : forall x:A, (forall (y : A | m y < m x), P y) -> P x. + + Notation Fix_F := (Fix_measure_F_sub P F_sub) (only parsing). (* alias *) + + Definition Fix_measure (x:A) := Fix_measure_F_sub P F_sub x (lt_wf (m x)). + + Hypothesis + F_ext : + forall (x:A) (f g:forall y : { y : A | m y < m x}, P (`y)), + (forall y : { y : A | m y < m x}, f y = g y) -> F_sub x f = F_sub x g. + + Program Lemma Fix_measure_F_eq : + forall (x:A) (r:Acc lt (m x)), + F_sub x (fun (y:A | m y < m x) => Fix_F y (Acc_inv r (proj2_sig y))) = Fix_F x r. + Proof. + intros x. + set (y := m x). + unfold Fix_measure_F_sub. + intros r ; case r ; auto. + Qed. + + Lemma Fix_measure_F_inv : forall (x:A) (r s:Acc lt (m x)), Fix_F x r = Fix_F x s. + Proof. + intros x r s. + rewrite (proof_irrelevance (Acc lt (m x)) r s) ; auto. + Qed. + + Lemma Fix_measure_eq : forall x:A, Fix_measure x = F_sub x (fun (y:{y:A| m y < m x}) => Fix_measure (proj1_sig y)). + Proof. + intro x; unfold Fix_measure in |- *. + rewrite <- (Fix_measure_F_eq ). + apply F_ext; intros. + apply Fix_measure_F_inv. + Qed. + + Lemma fix_measure_sub_eq : forall x : A, + Fix_measure_sub P F_sub x = + let f_sub := F_sub in + f_sub x (fun (y : A | m y < m x) => Fix_measure (`y)). + exact Fix_measure_eq. + Qed. + + End FixPoint. + +End Well_founded_measure. + +Extraction Inline Fix_measure_F_sub Fix_measure_sub. diff --git a/theories/QArith/QArith.v b/theories/QArith/QArith.v index 03935e2b..2af65320 100644 --- a/theories/QArith/QArith.v +++ b/theories/QArith/QArith.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: QArith.v 8883 2006-05-31 21:56:37Z letouzey $ i*) +(*i $Id: QArith.v 10739 2008-04-01 14:45:20Z herbelin $ i*) Require Export QArith_base. Require Export Qring. diff --git a/theories/QArith/QArith_base.v b/theories/QArith/QArith_base.v index fc92c678..304fbf77 100644 --- a/theories/QArith/QArith_base.v +++ b/theories/QArith/QArith_base.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: QArith_base.v 9932 2007-07-02 14:31:33Z notin $ i*) +(*i $Id: QArith_base.v 10765 2008-04-08 16:15:23Z msozeau $ i*) Require Export ZArith. Require Export ZArithRing. @@ -79,9 +79,9 @@ Qed. Lemma Qge_alt : forall p q, (p>=q) <-> (p?=q <> Lt). Proof. unfold Qle, Qcompare, Zle. -split; intros; swap H. +split; intros; contradict H. rewrite Zcompare_Gt_Lt_antisym; auto. -rewrite Zcompare_Gt_Lt_antisym in H0; auto. +rewrite Zcompare_Gt_Lt_antisym in H; auto. Qed. Hint Unfold Qeq Qlt Qle: qarith. @@ -121,7 +121,7 @@ Defined. Definition Q_Setoid : Setoid_Theory Q Qeq. Proof. - split; unfold Qeq in |- *; auto; apply Qeq_trans. + split; red; unfold Qeq in |- *; auto; apply Qeq_trans. Qed. Add Setoid Q Qeq Q_Setoid as Qsetoid. @@ -130,6 +130,12 @@ Hint Resolve (Seq_refl Q Qeq Q_Setoid): qarith. Hint Resolve (Seq_sym Q Qeq Q_Setoid): qarith. Hint Resolve (Seq_trans Q Qeq Q_Setoid): qarith. +Theorem Qnot_eq_sym : forall x y, ~x == y -> ~y == x. +Proof. + auto with qarith. +Qed. + +Hint Resolve Qnot_eq_sym : qarith. (** * Addition, multiplication and opposite *) @@ -165,6 +171,13 @@ Infix "/" := Qdiv : Q_scope. Notation " ' x " := (Zpos x) (at level 20, no associativity) : Z_scope. +Lemma Qmake_Qdiv : forall a b, a#b==inject_Z a/inject_Z ('b). +Proof. +intros a b. +unfold Qeq. +simpl. +ring. +Qed. (** * Setoid compatibility results *) @@ -187,7 +200,7 @@ Proof. unfold Qeq, Qopp; simpl. Open Scope Z_scope. intros. - replace (- Qnum x1 * ' Qden x2) with (- (Qnum x1 * ' Qden x2)) by ring. + replace (- Qnum x * ' Qden y) with (- (Qnum x * ' Qden y)) by ring. rewrite H in |- *; ring. Close Scope Z_scope. Qed. @@ -416,6 +429,11 @@ Qed. (** * Inverse and division. *) +Lemma Qinv_involutive : forall q, (/ / q) == q. +Proof. +intros [[|n|n] d]; red; simpl; reflexivity. +Qed. + Theorem Qmult_inv_r : forall x, ~ x == 0 -> x*(/x) == 1. Proof. intros (x1, x2); unfold Qeq, Qdiv, Qmult; case x1; simpl; @@ -474,6 +492,8 @@ Proof. Close Scope Z_scope. Qed. +Hint Resolve Qle_trans : qarith. + Lemma Qlt_not_eq : forall x y, x<y -> ~ x==y. Proof. unfold Qlt, Qeq; auto with zarith. @@ -552,6 +572,9 @@ Proof. unfold Qle, Qlt, Qeq; intros; apply Zle_lt_or_eq; auto. Qed. +Hint Resolve Qle_not_lt Qlt_not_le Qnot_le_lt Qnot_lt_le + Qlt_le_weak Qlt_not_eq Qle_antisym Qle_refl: qartih. + (** Some decidability results about orders. *) Lemma Q_dec : forall x y, {x<y} + {y<x} + {x==y}. @@ -574,6 +597,8 @@ Proof. do 2 rewrite <- Zopp_mult_distr_l; omega. Qed. +Hint Resolve Qopp_le_compat : qarith. + Lemma Qle_minus_iff : forall p q, p <= q <-> 0 <= q+-p. Proof. intros (x1,x2) (y1,y2); unfold Qle; simpl. @@ -641,50 +666,136 @@ Proof. Close Scope Z_scope. Qed. -(** * Rational to the n-th power *) +Lemma Qmult_le_0_compat : forall a b, 0 <= a -> 0 <= b -> 0 <= a*b. +Proof. +intros a b Ha Hb. +unfold Qle in *. +simpl in *. +auto with *. +Qed. -Fixpoint Qpower (q:Q)(n:nat) { struct n } : Q := - match n with - | O => 1 - | S n => q * (Qpower q n) - end. +Lemma Qinv_le_0_compat : forall a, 0 <= a -> 0 <= /a. +Proof. +intros [[|n|n] d] Ha; assumption. +Qed. -Notation " q ^ n " := (Qpower q n) : Q_scope. +Lemma Qle_shift_div_l : forall a b c, + 0 < c -> a*c <= b -> a <= b/c. +Proof. +intros a b c Hc H. +apply Qmult_lt_0_le_reg_r with (c). + assumption. +setoid_replace (b/c*c) with (c*(b/c)) by apply Qmult_comm. +rewrite Qmult_div_r; try assumption. +auto with *. +Qed. -Lemma Qpower_1 : forall n, 1^n == 1. +Lemma Qle_shift_inv_l : forall a c, + 0 < c -> a*c <= 1 -> a <= /c. Proof. - induction n; simpl; auto with qarith. - rewrite IHn; auto with qarith. +intros a c Hc H. +setoid_replace (/c) with (1*/c) by (symmetry; apply Qmult_1_l). +change (a <= 1/c). +apply Qle_shift_div_l; assumption. Qed. -Lemma Qpower_0 : forall n, n<>O -> 0^n == 0. +Lemma Qle_shift_div_r : forall a b c, + 0 < b -> a <= c*b -> a/b <= c. Proof. - destruct n; simpl. - destruct 1; auto. - intros. - compute; auto. +intros a b c Hc H. +apply Qmult_lt_0_le_reg_r with b. + assumption. +setoid_replace (a/b*b) with (b*(a/b)) by apply Qmult_comm. +rewrite Qmult_div_r; try assumption. +auto with *. Qed. -Lemma Qpower_pos : forall p n, 0 <= p -> 0 <= p^n. +Lemma Qle_shift_inv_r : forall b c, + 0 < b -> 1 <= c*b -> /b <= c. Proof. - induction n; simpl; auto with qarith. - intros; compute; intro; discriminate. - intros. - apply Qle_trans with (0*(p^n)). - compute; intro; discriminate. - apply Qmult_le_compat_r; auto. +intros b c Hc H. +setoid_replace (/b) with (1*/b) by (symmetry; apply Qmult_1_l). +change (1/b <= c). +apply Qle_shift_div_r; assumption. Qed. -Lemma Qinv_power_n : forall n p, (1#p)^n == /(inject_Z ('p))^n. +Lemma Qinv_lt_0_compat : forall a, 0 < a -> 0 < /a. Proof. - induction n. - compute; auto. - simpl. - intros; rewrite IHn; clear IHn. - unfold Qdiv; rewrite Qinv_mult_distr. - setoid_replace (1#p) with (/ inject_Z ('p)). - apply Qeq_refl. - compute; auto. +intros [[|n|n] d] Ha; assumption. +Qed. + +Lemma Qlt_shift_div_l : forall a b c, + 0 < c -> a*c < b -> a < b/c. +Proof. +intros a b c Hc H. +apply Qnot_le_lt. +intros H0. +apply (Qlt_not_le _ _ H). +apply Qmult_lt_0_le_reg_r with (/c). + apply Qinv_lt_0_compat. + assumption. +setoid_replace (a*c/c) with (a) by (apply Qdiv_mult_l; auto with *). +assumption. +Qed. + +Lemma Qlt_shift_inv_l : forall a c, + 0 < c -> a*c < 1 -> a < /c. +Proof. +intros a c Hc H. +setoid_replace (/c) with (1*/c) by (symmetry; apply Qmult_1_l). +change (a < 1/c). +apply Qlt_shift_div_l; assumption. +Qed. + +Lemma Qlt_shift_div_r : forall a b c, + 0 < b -> a < c*b -> a/b < c. +Proof. +intros a b c Hc H. +apply Qnot_le_lt. +intros H0. +apply (Qlt_not_le _ _ H). +apply Qmult_lt_0_le_reg_r with (/b). + apply Qinv_lt_0_compat. + assumption. +setoid_replace (c*b/b) with (c) by (apply Qdiv_mult_l; auto with *). +assumption. +Qed. + +Lemma Qlt_shift_inv_r : forall b c, + 0 < b -> 1 < c*b -> /b < c. +Proof. +intros b c Hc H. +setoid_replace (/b) with (1*/b) by (symmetry; apply Qmult_1_l). +change (1/b < c). +apply Qlt_shift_div_r; assumption. Qed. +(** * Rational to the n-th power *) + +Definition Qpower_positive (q:Q)(p:positive) : Q := + pow_pos Qmult q p. +Add Morphism Qpower_positive with signature Qeq ==> @eq _ ==> Qeq as Qpower_positive_comp. +Proof. +intros x1 x2 Hx y. +unfold Qpower_positive. +induction y; simpl; +try rewrite IHy; +try rewrite Hx; +reflexivity. +Qed. + +Definition Qpower (q:Q) (z:Z) := + match z with + | Zpos p => Qpower_positive q p + | Z0 => 1 + | Zneg p => /Qpower_positive q p + end. + +Notation " q ^ z " := (Qpower q z) : Q_scope. + +Add Morphism Qpower with signature Qeq ==> @eq _ ==> Qeq as Qpower_comp. +Proof. +intros x1 x2 Hx [|y|y]; try reflexivity; +simpl; rewrite Hx; reflexivity. +Qed. diff --git a/theories/QArith/Qabs.v b/theories/QArith/Qabs.v new file mode 100644 index 00000000..e672016e --- /dev/null +++ b/theories/QArith/Qabs.v @@ -0,0 +1,124 @@ +(************************************************************************) +(* 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 Export QArith. +Require Export Qreduction. + +Hint Resolve Qlt_le_weak : qarith. + +Definition Qabs (x:Q) := let (n,d):=x in (Zabs n#d). + +Lemma Qabs_case : forall (x:Q) (P : Q -> Type), (0 <= x -> P x) -> (x <= 0 -> P (- x)) -> P (Qabs x). +Proof. +intros x P H1 H2. +destruct x as [[|xn|xn] xd]; +[apply H1|apply H1|apply H2]; +abstract (compute; discriminate). +Defined. + +Add Morphism Qabs with signature Qeq ==> Qeq as Qabs_wd. +intros [xn xd] [yn yd] H. +simpl. +unfold Qeq in *. +simpl in *. +change (' yd)%Z with (Zabs (' yd)). +change (' xd)%Z with (Zabs (' xd)). +repeat rewrite <- Zabs_Zmult. +congruence. +Qed. + +Lemma Qabs_pos : forall x, 0 <= x -> Qabs x == x. +Proof. +intros x H. +apply Qabs_case. +reflexivity. +intros H0. +setoid_replace x with 0. +reflexivity. +apply Qle_antisym; assumption. +Qed. + +Lemma Qabs_neg : forall x, x <= 0 -> Qabs x == - x. +Proof. +intros x H. +apply Qabs_case. +intros H0. +setoid_replace x with 0. +reflexivity. +apply Qle_antisym; assumption. +reflexivity. +Qed. + +Lemma Qabs_nonneg : forall x, 0 <= (Qabs x). +intros x. +apply Qabs_case. +auto. +apply (Qopp_le_compat x 0). +Qed. + +Lemma Zabs_Qabs : forall n d, (Zabs n#d)==Qabs (n#d). +Proof. +intros [|n|n]; reflexivity. +Qed. + +Lemma Qabs_opp : forall x, Qabs (-x) == Qabs x. +Proof. +intros x. +do 2 apply Qabs_case; try (intros; ring); +(intros H0 H1; +setoid_replace x with 0;[reflexivity|]; +apply Qle_antisym);try assumption; +rewrite Qle_minus_iff in *; +ring_simplify; +ring_simplify in H1; +assumption. +Qed. + +Lemma Qabs_triangle : forall x y, Qabs (x+y) <= Qabs x + Qabs y. +Proof. +intros [xn xd] [yn yd]. +unfold Qplus. +unfold Qle. +simpl. +apply Zmult_le_compat_r;auto with *. +change (' yd)%Z with (Zabs (' yd)). +change (' xd)%Z with (Zabs (' xd)). +repeat rewrite <- Zabs_Zmult. +apply Zabs_triangle. +Qed. + +Lemma Qabs_Qmult : forall a b, Qabs (a*b) == (Qabs a)*(Qabs b). +Proof. +intros [an ad] [bn bd]. +simpl. +rewrite Zabs_Zmult. +reflexivity. +Qed. + +Lemma Qle_Qabs : forall a, a <= Qabs a. +Proof. +intros a. +apply Qabs_case; auto with *. +intros H. +apply Qle_trans with 0; try assumption. +change 0 with (-0). +apply Qopp_le_compat. +assumption. +Qed. + +Lemma Qabs_triangle_reverse : forall x y, Qabs x - Qabs y <= Qabs (x - y). +Proof. +intros x y. +rewrite Qle_minus_iff. +setoid_replace (Qabs (x - y) + - (Qabs x - Qabs y)) with ((Qabs (x - y) + Qabs y) + - Qabs x) by ring. +rewrite <- Qle_minus_iff. +setoid_replace (Qabs x) with (Qabs (x-y+y)). +apply Qabs_triangle. +apply Qabs_wd. +ring. +Qed. diff --git a/theories/QArith/Qcanon.v b/theories/QArith/Qcanon.v index 98c5ff9e..42522468 100644 --- a/theories/QArith/Qcanon.v +++ b/theories/QArith/Qcanon.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Qcanon.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Qcanon.v 10739 2008-04-01 14:45:20Z herbelin $ i*) Require Import Field. Require Import QArith. @@ -101,6 +101,7 @@ Infix "<=" := Qcle : Qc_scope. Infix ">" := Qcgt : Qc_scope. Infix ">=" := Qcge : Qc_scope. Notation "x <= y <= z" := (x<=y/\y<=z) : Qc_scope. +Notation "x < y < z" := (x<y/\y<z) : Qc_scope. Definition Qccompare (p q : Qc) := (Qcompare p q). Notation "p ?= q" := (Qccompare p q) : Qc_scope. @@ -139,7 +140,7 @@ Theorem Qc_eq_dec : forall x y:Qc, {x=y} + {x<>y}. Proof. intros. destruct (Qeq_dec x y) as [H|H]; auto. - right; swap H; subst; auto with qarith. + right; contradict H; subst; auto with qarith. Defined. (** The addition, multiplication and opposite are defined @@ -347,7 +348,7 @@ Proof. unfold Qcle, Qclt; intros; eapply Qlt_le_trans; eauto. Qed. -Lemma Qlt_trans : forall x y z, x<y -> y<z -> x<z. +Lemma Qclt_trans : forall x y z, x<y -> y<z -> x<z. Proof. unfold Qclt; intros; eapply Qlt_trans; eauto. Qed. @@ -472,7 +473,7 @@ Proof. compute; auto. Qed. -Lemma Qpower_pos : forall p n, 0 <= p -> 0 <= p^n. +Lemma Qcpower_pos : forall p n, 0 <= p -> 0 <= p^n. Proof. induction n; simpl; auto with qarith. intros; compute; intro; discriminate. @@ -495,23 +496,6 @@ Proof. intros _ H; inversion H. Qed. -(* -Definition Qcrt : Ring_Theory Qcplus Qcmult 1 0 Qcopp Qc_eq_bool. -Proof. -constructor. -exact Qcplus_comm. -exact Qcplus_assoc. -exact Qcmult_comm. -exact Qcmult_assoc. -exact Qcplus_0_l. -exact Qcmult_1_l. -exact Qcplus_opp_r. -exact Qcmult_plus_distr_l. -unfold Is_true; intros x y; generalize (Qc_eq_bool_correct x y); - case (Qc_eq_bool x y); auto. -Qed. -Add Ring Qc Qcplus Qcmult 1 0 Qcopp Qc_eq_bool Qcrt [ Qcmake ]. -*) Definition Qcrt : ring_theory 0 1 Qcplus Qcmult Qcminus Qcopp (eq(A:=Qc)). Proof. constructor. @@ -547,4 +531,14 @@ auto. Qed. - +Theorem Qc_decomp: forall x y: Qc, + (Qred x = x -> Qred y = y -> (x:Q) = y)-> x = y. +Proof. + intros (q, Hq) (q', Hq'); simpl; intros H. + assert (H1 := H Hq Hq'). + subst q'. + assert (Hq = Hq'). + apply Eqdep_dec.eq_proofs_unicity; auto; intros. + repeat decide equality. + congruence. +Qed. diff --git a/theories/QArith/Qfield.v b/theories/QArith/Qfield.v new file mode 100644 index 00000000..5d548aea --- /dev/null +++ b/theories/QArith/Qfield.v @@ -0,0 +1,153 @@ +(************************************************************************) +(* 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: Qfield.v 10739 2008-04-01 14:45:20Z herbelin $ i*) + +Require Export Field. +Require Export QArith_base. +Require Import NArithRing. + +(** * field and ring tactics for rational numbers *) + +Definition Qeq_bool (x y : Q) := + if Qeq_dec x y then true else false. + +Lemma Qeq_bool_correct : forall x y : Q, Qeq_bool x y = true -> x==y. +Proof. + intros x y; unfold Qeq_bool in |- *; case (Qeq_dec x y); simpl in |- *; auto. + intros _ H; inversion H. +Qed. + +Lemma Qeq_bool_complete : forall x y : Q, x==y -> Qeq_bool x y = true. +Proof. + intros x y; unfold Qeq_bool in |- *; case (Qeq_dec x y); simpl in |- *; auto. +Qed. + +Definition Qsft : field_theory 0 1 Qplus Qmult Qminus Qopp Qdiv Qinv Qeq. +Proof. + constructor. + constructor. + exact Qplus_0_l. + exact Qplus_comm. + exact Qplus_assoc. + exact Qmult_1_l. + exact Qmult_comm. + exact Qmult_assoc. + exact Qmult_plus_distr_l. + reflexivity. + exact Qplus_opp_r. + discriminate. + reflexivity. + intros p Hp. + rewrite Qmult_comm. + apply Qmult_inv_r. + exact Hp. +Qed. + +Lemma Qpower_theory : power_theory 1 Qmult Qeq Z_of_N Qpower. +Proof. +constructor. +intros r [|n]; +reflexivity. +Qed. + +Ltac isQcst t := + match t with + | inject_Z ?z => isZcst z + | Qmake ?n ?d => + match isZcst n with + true => isPcst d + | _ => false + end + | _ => false + end. + +Ltac Qcst t := + match isQcst t with + true => t + | _ => NotConstant + end. + +Ltac Qpow_tac t := + match t with + | Z0 => N0 + | Zpos ?n => Ncst (Npos n) + | Z_of_N ?n => Ncst n + | NtoZ ?n => Ncst n + | _ => NotConstant + end. + +Add Field Qfield : Qsft + (decidable Qeq_bool_correct, + completeness Qeq_bool_complete, + constants [Qcst], + power_tac Qpower_theory [Qpow_tac]). + +(** Exemple of use: *) + +Section Examples. + +Let ex1 : forall x y z : Q, (x+y)*z == (x*z)+(y*z). + intros. + ring. +Qed. + +Let ex2 : forall x y : Q, x+y == y+x. + intros. + ring. +Qed. + +Let ex3 : forall x y z : Q, (x+y)+z == x+(y+z). + intros. + ring. +Qed. + +Let ex4 : (inject_Z 1)+(inject_Z 1)==(inject_Z 2). + ring. +Qed. + +Let ex5 : 1+1 == 2#1. + ring. +Qed. + +Let ex6 : (1#1)+(1#1) == 2#1. + ring. +Qed. + +Let ex7 : forall x : Q, x-x== 0. + intro. + ring. +Qed. + +Let ex8 : forall x : Q, x^1 == x. + intro. + ring. +Qed. + +Let ex9 : forall x : Q, x^0 == 1. + intro. + ring. +Qed. + +Let ex10 : forall x y : Q, ~(y==0) -> (x/y)*y == x. +intros. +field. +auto. +Qed. + +End Examples. + +Lemma Qopp_plus : forall a b, -(a+b) == -a + -b. +Proof. + intros; ring. +Qed. + +Lemma Qopp_opp : forall q, - -q==q. +Proof. + intros; ring. +Qed. diff --git a/theories/QArith/Qpower.v b/theories/QArith/Qpower.v new file mode 100644 index 00000000..8672592d --- /dev/null +++ b/theories/QArith/Qpower.v @@ -0,0 +1,239 @@ +(************************************************************************) +(* 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 Zpow_facts Qfield Qreduction. + +Lemma Qpower_positive_1 : forall n, Qpower_positive 1 n == 1. +Proof. +induction n; +simpl; try rewrite IHn; reflexivity. +Qed. + +Lemma Qpower_1 : forall n, 1^n == 1. +Proof. + intros [|n|n]; simpl; try rewrite Qpower_positive_1; reflexivity. +Qed. + +Lemma Qpower_positive_0 : forall n, Qpower_positive 0 n == 0. +Proof. +induction n; +simpl; try rewrite IHn; reflexivity. +Qed. + +Lemma Qpower_0 : forall n, (n<>0)%Z -> 0^n == 0. +Proof. + intros [|n|n] Hn; try (elim Hn; reflexivity); simpl; + rewrite Qpower_positive_0; reflexivity. +Qed. + +Lemma Qpower_not_0_positive : forall a n, ~a==0 -> ~Qpower_positive a n == 0. +Proof. +intros a n X H. +apply X; clear X. +induction n; simpl in *; try assumption; +destruct (Qmult_integral _ _ H); +try destruct (Qmult_integral _ _ H0); auto. +Qed. + +Lemma Qpower_pos_positive : forall p n, 0 <= p -> 0 <= Qpower_positive p n. +intros p n Hp. +induction n; simpl; repeat apply Qmult_le_0_compat;assumption. +Qed. + +Lemma Qpower_pos : forall p n, 0 <= p -> 0 <= p^n. +Proof. + intros p [|n|n] Hp; simpl; try discriminate; + try apply Qinv_le_0_compat; apply Qpower_pos_positive; assumption. +Qed. + +Lemma Qmult_power_positive : forall a b n, Qpower_positive (a*b) n == (Qpower_positive a n)*(Qpower_positive b n). +Proof. +induction n; +simpl; repeat rewrite IHn; ring. +Qed. + +Lemma Qmult_power : forall a b n, (a*b)^n == a^n*b^n. +Proof. + intros a b [|n|n]; simpl; + try rewrite Qmult_power_positive; + try rewrite Qinv_mult_distr; + reflexivity. +Qed. + +Lemma Qinv_power_positive : forall a n, Qpower_positive (/a) n == /(Qpower_positive a n). +Proof. +induction n; +simpl; repeat (rewrite IHn || rewrite Qinv_mult_distr); reflexivity. +Qed. + +Lemma Qinv_power : forall a n, (/a)^n == /a^n. +Proof. + intros a [|n|n]; simpl; + try rewrite Qinv_power_positive; + reflexivity. +Qed. + +Lemma Qdiv_power : forall a b n, (a/b)^n == (a^n/b^n). +Proof. +unfold Qdiv. +intros a b n. +rewrite Qmult_power. +rewrite Qinv_power. +reflexivity. +Qed. + +Lemma Qinv_power_n : forall n p, (1#p)^n == /(inject_Z ('p))^n. +Proof. +intros n p. +rewrite Qmake_Qdiv. +rewrite Qdiv_power. +rewrite Qpower_1. +unfold Qdiv. +ring. +Qed. + +Lemma Qpower_plus_positive : forall a n m, Qpower_positive a (n+m) == (Qpower_positive a n)*(Qpower_positive a m). +Proof. +intros a n m. +unfold Qpower_positive. +apply pow_pos_Pplus. +apply Q_Setoid. +apply Qmult_comp. +apply Qmult_comm. +apply Qmult_assoc. +Qed. + +Lemma Qpower_opp : forall a n, a^(-n) == /a^n. +Proof. +intros a [|n|n]; simpl; try reflexivity. +symmetry; apply Qinv_involutive. +Qed. + +Lemma Qpower_minus_positive : forall a (n m:positive), (Pcompare n m Eq=Gt)%positive -> Qpower_positive a (n-m)%positive == (Qpower_positive a n)/(Qpower_positive a m). +Proof. +intros a n m H. +destruct (Qeq_dec a 0). + rewrite q. + repeat rewrite Qpower_positive_0. + reflexivity. +rewrite <- (Qdiv_mult_l (Qpower_positive a (n - m)) (Qpower_positive a m)) by + (apply Qpower_not_0_positive; assumption). +apply Qdiv_comp;[|reflexivity]. +rewrite Qmult_comm. +rewrite <- Qpower_plus_positive. +rewrite Pplus_minus. +reflexivity. +assumption. +Qed. + +Lemma Qpower_plus : forall a n m, ~a==0 -> a^(n+m) == a^n*a^m. +Proof. +intros a [|n|n] [|m|m] H; simpl; try ring; +try rewrite Qpower_plus_positive; +try apply Qinv_mult_distr; try reflexivity; +case_eq ((n ?= m)%positive Eq); intros H0; simpl; + try rewrite Qpower_minus_positive; + try rewrite (Pcompare_Eq_eq _ _ H0); + try (field; try split; apply Qpower_not_0_positive); + try assumption; + apply ZC2; + assumption. +Qed. + +Lemma Qpower_plus' : forall a n m, (n+m <> 0)%Z -> a^(n+m) == a^n*a^m. +Proof. +intros a n m H. +destruct (Qeq_dec a 0)as [X|X]. +rewrite X. +rewrite Qpower_0 by assumption. +destruct n; destruct m; try (elim H; reflexivity); + simpl; repeat rewrite Qpower_positive_0; ring_simplify; + reflexivity. +apply Qpower_plus. +assumption. +Qed. + +Lemma Qpower_mult_positive : forall a n m, Qpower_positive a (n*m) == Qpower_positive (Qpower_positive a n) m. +Proof. +intros a n m. +induction n using Pind. + reflexivity. +rewrite Pmult_Sn_m. +rewrite Pplus_one_succ_l. +do 2 rewrite Qpower_plus_positive. +rewrite IHn. +rewrite Qmult_power_positive. +reflexivity. +Qed. + +Lemma Qpower_mult : forall a n m, a^(n*m) == (a^n)^m. +Proof. +intros a [|n|n] [|m|m]; simpl; + try rewrite Qpower_positive_1; + try rewrite Qpower_mult_positive; + try rewrite Qinv_power_positive; + try rewrite Qinv_involutive; + try reflexivity. +Qed. + +Lemma Zpower_Qpower : forall (a n:Z), (0<=n)%Z -> inject_Z (a^n) == (inject_Z a)^n. +Proof. +intros a [|n|n] H;[reflexivity| |elim H; reflexivity]. +induction n using Pind. + replace (a^1)%Z with a by ring. + ring. +rewrite Zpos_succ_morphism. +unfold Zsucc. +rewrite Zpower_exp; auto with *; try discriminate. +rewrite Qpower_plus' by discriminate. +rewrite <- IHn by discriminate. +replace (a^'n*a^1)%Z with (a^'n*a)%Z by ring. +ring_simplify. +reflexivity. +Qed. + +Lemma Qsqr_nonneg : forall a, 0 <= a^2. +Proof. +intros a. +destruct (Qlt_le_dec 0 a) as [A|A]. +apply (Qmult_le_0_compat a a); + (apply Qlt_le_weak; assumption). +setoid_replace (a^2) with ((-a)*(-a)) by ring. +rewrite Qle_minus_iff in A. +setoid_replace (0+ - a) with (-a) in A by ring. +apply Qmult_le_0_compat; assumption. +Qed. + +Theorem Qpower_decomp: forall p x y, + Qpower_positive (x #y) p == x ^ Zpos p # (Z2P ((Zpos y) ^ Zpos p)). +Proof. +induction p; intros; unfold Qmult; simpl. +(* xI *) +rewrite IHp, xI_succ_xO, <-Pplus_diag, Pplus_one_succ_l. +repeat rewrite Zpower_pos_is_exp. +red; unfold Qmult, Qnum, Qden, Zpower. +repeat rewrite Zpos_mult_morphism. +repeat rewrite Z2P_correct. +repeat rewrite Zpower_pos_1_r; ring. +apply Zpower_pos_pos; red; auto. +repeat apply Zmult_lt_0_compat; auto; + apply Zpower_pos_pos; red; auto. +(* xO *) +rewrite IHp, <-Pplus_diag. +repeat rewrite Zpower_pos_is_exp. +red; unfold Qmult, Qnum, Qden, Zpower. +repeat rewrite Zpos_mult_morphism. +repeat rewrite Z2P_correct; try ring. +apply Zpower_pos_pos; red; auto. +repeat apply Zmult_lt_0_compat; auto; + apply Zpower_pos_pos; red; auto. +(* xO *) +unfold Qmult; simpl. +red; simpl; rewrite Zpower_pos_1_r; + rewrite Zpos_mult_morphism; ring. +Qed. diff --git a/theories/QArith/Qreals.v b/theories/QArith/Qreals.v index 6bd161f3..c98cef3f 100644 --- a/theories/QArith/Qreals.v +++ b/theories/QArith/Qreals.v @@ -6,24 +6,20 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Qreals.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Qreals.v 10739 2008-04-01 14:45:20Z herbelin $ i*) Require Export Rbase. Require Export QArith_base. -(** A field tactic for rational numbers. *) +(** Injection of rational numbers into real numbers. *) -(** Since field cannot operate on setoid datatypes (yet?), - we translate Q goals into reals before applying field. *) +Definition Q2R (x : Q) : R := (IZR (Qnum x) * / IZR (QDen x))%R. Lemma IZR_nz : forall p : positive, IZR (Zpos p) <> 0%R. intros; apply not_O_IZR; auto with qarith. Qed. -Hint Immediate IZR_nz. -Hint Resolve Rmult_integral_contrapositive. - -Definition Q2R (x : Q) : R := (IZR (Qnum x) * / IZR (QDen x))%R. +Hint Resolve IZR_nz Rmult_integral_contrapositive. Lemma eqR_Qeq : forall x y : Q, Q2R x = Q2R y -> x==y. Proof. @@ -171,7 +167,7 @@ Lemma Q2R_minus : forall x y : Q, Q2R (x-y) = (Q2R x - Q2R y)%R. unfold Qminus in |- *; intros; rewrite Q2R_plus; rewrite Q2R_opp; auto. Qed. -Lemma Q2R_inv : forall x : Q, ~ x==0#1 -> Q2R (/x) = (/ Q2R x)%R. +Lemma Q2R_inv : forall x : Q, ~ x==0 -> Q2R (/x) = (/ Q2R x)%R. Proof. unfold Qinv, Q2R, Qeq in |- *; intros (x1, x2); unfold Qden, Qnum in |- *. case x1. @@ -185,7 +181,7 @@ intros; Qed. Lemma Q2R_div : - forall x y : Q, ~ y==0#1 -> Q2R (x/y) = (Q2R x / Q2R y)%R. + forall x y : Q, ~ y==0 -> Q2R (x/y) = (Q2R x / Q2R y)%R. Proof. unfold Qdiv, Rdiv in |- *. intros; rewrite Q2R_mult. @@ -194,16 +190,24 @@ Qed. Hint Rewrite Q2R_plus Q2R_mult Q2R_opp Q2R_minus Q2R_inv Q2R_div : q2r_simpl. +Section LegacyQField. + +(** In the past, the field tactic was not able to deal with setoid datatypes, + so translating from Q to R and applying field on reals was a workaround. + See now Qfield for a direct field tactic on Q. *) + Ltac QField := apply eqR_Qeq; autorewrite with q2r_simpl; try field; auto. (** Examples of use: *) -Goal forall x y z : Q, (x+y)*z == (x*z)+(y*z). +Let ex1 : forall x y z : Q, (x+y)*z == (x*z)+(y*z). intros; QField. -Abort. +Qed. -Goal forall x y : Q, ~ y==0#1 -> (x/y)*y == x. +Let ex2 : forall x y : Q, ~ y==0 -> (x/y)*y == x. intros; QField. intro; apply H; apply eqR_Qeq. rewrite H0; unfold Q2R in |- *; simpl in |- *; field; auto with real. -Abort. +Qed. + +End LegacyQField.
\ No newline at end of file diff --git a/theories/QArith/Qreduction.v b/theories/QArith/Qreduction.v index 340cac83..9c522f09 100644 --- a/theories/QArith/Qreduction.v +++ b/theories/QArith/Qreduction.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Qreduction.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Qreduction.v 10739 2008-04-01 14:45:20Z herbelin $ i*) (** Normalisation functions for rational numbers. *) @@ -145,6 +145,7 @@ Qed. Definition Qplus' (p q : Q) := Qred (Qplus p q). Definition Qmult' (p q : Q) := Qred (Qmult p q). +Definition Qminus' x y := Qred (Qminus x y). Lemma Qplus'_correct : forall p q : Q, (Qplus' p q)==(Qplus p q). Proof. @@ -156,6 +157,11 @@ Proof. intros; unfold Qmult' in |- *; apply Qred_correct; auto. Qed. +Lemma Qminus'_correct : forall p q : Q, (Qminus' p q)==(Qminus p q). +Proof. + intros; unfold Qminus' in |- *; apply Qred_correct; auto. +Qed. + Add Morphism Qplus' : Qplus'_comp. Proof. intros; unfold Qplus' in |- *. @@ -167,3 +173,21 @@ Add Morphism Qmult' : Qmult'_comp. rewrite H; rewrite H0; auto with qarith. Qed. +Add Morphism Qminus' : Qminus'_comp. + intros; unfold Qminus' in |- *. + rewrite H; rewrite H0; auto with qarith. +Qed. + +Lemma Qred_opp: forall q, Qred (-q) = - (Qred q). +Proof. + intros (x, y); unfold Qred; simpl. + rewrite Zggcd_opp; case Zggcd; intros p1 (p2, p3); simpl. + unfold Qopp; auto. +Qed. + +Theorem Qred_compare: forall x y, + Qcompare x y = Qcompare (Qred x) (Qred y). +Proof. + intros x y; apply Qcompare_comp; apply Qeq_sym; apply Qred_correct. +Qed. + diff --git a/theories/QArith/Qring.v b/theories/QArith/Qring.v index f9aa3e50..2d45d537 100644 --- a/theories/QArith/Qring.v +++ b/theories/QArith/Qring.v @@ -6,99 +6,6 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Qring.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) - -Require Export Ring. -Require Export QArith_base. - -(** * A ring tactic for rational numbers *) - -Definition Qeq_bool (x y : Q) := - if Qeq_dec x y then true else false. - -Lemma Qeq_bool_correct : forall x y : Q, Qeq_bool x y = true -> x==y. -Proof. - intros x y; unfold Qeq_bool in |- *; case (Qeq_dec x y); simpl in |- *; auto. - intros _ H; inversion H. -Qed. - -Definition Qsrt : ring_theory 0 1 Qplus Qmult Qminus Qopp Qeq. -Proof. - constructor. - exact Qplus_0_l. - exact Qplus_comm. - exact Qplus_assoc. - exact Qmult_1_l. - exact Qmult_comm. - exact Qmult_assoc. - exact Qmult_plus_distr_l. - reflexivity. - exact Qplus_opp_r. -Qed. - -Ltac isQcst t := - match t with - | inject_Z ?z => isZcst z - | Qmake ?n ?d => - match isZcst n with - true => isPcst d - | _ => false - end - | _ => false - end. - -Ltac Qcst t := - match isQcst t with - true => t - | _ => NotConstant - end. - -Add Ring Qring : Qsrt (decidable Qeq_bool_correct, constants [Qcst]). -(** Exemple of use: *) - -Section Examples. - -Let ex1 : forall x y z : Q, (x+y)*z == (x*z)+(y*z). - intros. - ring. -Qed. - -Let ex2 : forall x y : Q, x+y == y+x. - intros. - ring. -Qed. - -Let ex3 : forall x y z : Q, (x+y)+z == x+(y+z). - intros. - ring. -Qed. - -Let ex4 : (inject_Z 1)+(inject_Z 1)==(inject_Z 2). - ring. -Qed. - -Let ex5 : 1+1 == 2#1. - ring. -Qed. - -Let ex6 : (1#1)+(1#1) == 2#1. - ring. -Qed. - -Let ex7 : forall x : Q, x-x== 0#1. - intro. - ring. -Qed. - -End Examples. - -Lemma Qopp_plus : forall a b, -(a+b) == -a + -b. -Proof. - intros; ring. -Qed. - -Lemma Qopp_opp : forall q, - -q==q. -Proof. - intros; ring. -Qed. +(*i $Id: Qring.v 10739 2008-04-01 14:45:20Z herbelin $ i*) +Require Export Qfield. diff --git a/theories/QArith/Qround.v b/theories/QArith/Qround.v new file mode 100644 index 00000000..3f191c75 --- /dev/null +++ b/theories/QArith/Qround.v @@ -0,0 +1,139 @@ +(************************************************************************) +(* 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 QArith. + +Lemma Qopp_lt_compat: forall p q : Q, p < q -> - q < - p. +Proof. +intros (a1,a2) (b1,b2); unfold Qle, Qlt; simpl. +do 2 rewrite <- Zopp_mult_distr_l; omega. +Qed. + +Hint Resolve Qopp_lt_compat : qarith. + +(************) + +Coercion Local inject_Z : Z >-> Q. + +Definition Qfloor (x:Q) := let (n,d) := x in Zdiv n (Zpos d). +Definition Qceiling (x:Q) := (-(Qfloor (-x)))%Z. + +Lemma Qfloor_Z : forall z:Z, Qfloor z = z. +Proof. +intros z. +simpl. +auto with *. +Qed. + +Lemma Qceiling_Z : forall z:Z, Qceiling z = z. +Proof. +intros z. +unfold Qceiling. +simpl. +rewrite Zdiv_1_r. +auto with *. +Qed. + +Lemma Qfloor_le : forall x, Qfloor x <= x. +Proof. +intros [n d]. +simpl. +unfold Qle. +simpl. +replace (n*1)%Z with n by ring. +rewrite Zmult_comm. +apply Z_mult_div_ge. +auto with *. +Qed. + +Hint Resolve Qfloor_le : qarith. + +Lemma Qle_ceiling : forall x, x <= Qceiling x. +Proof. +intros x. +apply Qle_trans with (- - x). + rewrite Qopp_involutive. + auto with *. +change (Qceiling x:Q) with (-(Qfloor(-x))). +auto with *. +Qed. + +Hint Resolve Qle_ceiling : qarith. + +Lemma Qle_floor_ceiling : forall x, Qfloor x <= Qceiling x. +Proof. +eauto with qarith. +Qed. + +Lemma Qlt_floor : forall x, x < (Qfloor x+1)%Z. +Proof. +intros [n d]. +simpl. +unfold Qlt. +simpl. +replace (n*1)%Z with n by ring. +ring_simplify. +replace (n / ' d * ' d + ' d)%Z with + (('d * (n / 'd) + n mod 'd) + 'd - n mod 'd)%Z by ring. +rewrite <- Z_div_mod_eq; auto with*. +rewrite <- Zlt_plus_swap. +destruct (Z_mod_lt n ('d)); auto with *. +Qed. + +Hint Resolve Qlt_floor : qarith. + +Lemma Qceiling_lt : forall x, (Qceiling x-1)%Z < x. +Proof. +intros x. +unfold Qceiling. +replace (- Qfloor (- x) - 1)%Z with (-(Qfloor (-x) + 1))%Z by ring. +change ((- (Qfloor (- x) + 1))%Z:Q) with (-(Qfloor (- x) + 1)%Z). +apply Qlt_le_trans with (- - x); auto with *. +rewrite Qopp_involutive. +auto with *. +Qed. + +Hint Resolve Qceiling_lt : qarith. + +Lemma Qfloor_resp_le : forall x y, x <= y -> (Qfloor x <= Qfloor y)%Z. +Proof. +intros [xn xd] [yn yd] Hxy. +unfold Qle in *. +simpl in *. +rewrite <- (Zdiv_mult_cancel_r xn ('xd) ('yd)); auto with *. +rewrite <- (Zdiv_mult_cancel_r yn ('yd) ('xd)); auto with *. +rewrite (Zmult_comm ('yd) ('xd)). +apply Z_div_le; auto with *. +Qed. + +Hint Resolve Qfloor_resp_le : qarith. + +Lemma Qceiling_resp_le : forall x y, x <= y -> (Qceiling x <= Qceiling y)%Z. +Proof. +intros x y Hxy. +unfold Qceiling. +cut (Qfloor (-y) <= Qfloor (-x))%Z; auto with *. +Qed. + +Hint Resolve Qceiling_resp_le : qarith. + +Add Morphism Qfloor with signature Qeq ==> @eq _ as Qfloor_comp. +Proof. +intros x y H. +apply Zle_antisym. + auto with *. +symmetry in H; auto with *. +Qed. + +Add Morphism Qceiling with signature Qeq ==> @eq _ as Qceiling_comp. +Proof. +intros x y H. +apply Zle_antisym. + auto with *. +symmetry in H; auto with *. +Qed.
\ No newline at end of file diff --git a/theories/Reals/Alembert.v b/theories/Reals/Alembert.v index 802bfa71..7625cce6 100644 --- a/theories/Reals/Alembert.v +++ b/theories/Reals/Alembert.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Alembert.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Alembert.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -25,12 +25,12 @@ Lemma Alembert_C1 : forall An:nat -> R, (forall n:nat, 0 < An n) -> Un_cv (fun n:nat => Rabs (An (S n) / An n)) 0 -> - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 An N) l). + { l:R | Un_cv (fun N:nat => sum_f_R0 An N) l }. Proof. intros An H H0. cut - (sigT (fun l:R => is_lub (EUn (fun N:nat => sum_f_R0 An N)) l) -> - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 An N) l)). + ({ l:R | is_lub (EUn (fun N:nat => sum_f_R0 An N)) l } -> + { l:R | Un_cv (fun N:nat => sum_f_R0 An N) l }). intro X; apply X. apply completeness. unfold Un_cv in H0; unfold bound in |- *; cut (0 < / 2); @@ -109,18 +109,18 @@ Proof. symmetry in |- *; apply tech2; assumption. exists (sum_f_R0 An 0); unfold EUn in |- *; exists 0%nat; reflexivity. intro X; elim X; intros. - apply existT with x; apply tech10; + exists x; apply tech10; [ unfold Un_growing in |- *; intro; rewrite tech5; pattern (sum_f_R0 An n) at 1 in |- *; rewrite <- Rplus_0_r; apply Rplus_le_compat_l; left; apply H | apply p ]. -Qed. +Defined. Lemma Alembert_C2 : forall An:nat -> R, (forall n:nat, An n <> 0) -> Un_cv (fun n:nat => Rabs (An (S n) / An n)) 0 -> - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 An N) l). + { l:R | Un_cv (fun N:nat => sum_f_R0 An N) l }. Proof. intros. set (Vn := fun i:nat => (2 * Rabs (An i) + An i) / 2). @@ -133,7 +133,7 @@ Proof. assert (H6 := Alembert_C1 Wn H2 H4). elim H5; intros. elim H6; intros. - apply existT with (x - x0); unfold Un_cv in |- *; unfold Un_cv in p; + exists (x - x0); unfold Un_cv in |- *; unfold Un_cv in p; unfold Un_cv in p0; intros; cut (0 < eps / 2). intro; elim (p (eps / 2) H8); clear p; intros. elim (p0 (eps / 2) H8); clear p0; intros. @@ -334,21 +334,21 @@ Proof. rewrite <- Rabs_Ropp; apply RRle_abs. rewrite double; pattern (Rabs (An n)) at 1 in |- *; rewrite <- Rplus_0_r; apply Rplus_lt_compat_l; apply Rabs_pos_lt; apply H. -Qed. +Defined. Lemma AlembertC3_step1 : forall (An:nat -> R) (x:R), x <> 0 -> (forall n:nat, An n <> 0) -> Un_cv (fun n:nat => Rabs (An (S n) / An n)) 0 -> - sigT (fun l:R => Pser An x l). + { l:R | Pser An x l }. Proof. intros; set (Bn := fun i:nat => An i * x ^ i). cut (forall n:nat, Bn n <> 0). intro; cut (Un_cv (fun n:nat => Rabs (Bn (S n) / Bn n)) 0). intro; assert (H4 := Alembert_C2 Bn H2 H3). elim H4; intros. - apply existT with x0; unfold Bn in p; apply tech12; assumption. + exists x0; unfold Bn in p; apply tech12; assumption. unfold Un_cv in |- *; intros; unfold Un_cv in H1; cut (0 < eps / Rabs x). intro; elim (H1 (eps / Rabs x) H4); intros. exists x0; intros; unfold R_dist in |- *; unfold Rminus in |- *; @@ -379,13 +379,13 @@ Proof. [ assumption | apply Rinv_0_lt_compat; apply Rabs_pos_lt; assumption ]. intro; unfold Bn in |- *; apply prod_neq_R0; [ apply H0 | apply pow_nonzero; assumption ]. -Qed. +Defined. Lemma AlembertC3_step2 : - forall (An:nat -> R) (x:R), x = 0 -> sigT (fun l:R => Pser An x l). + forall (An:nat -> R) (x:R), x = 0 -> { l:R | Pser An x l }. Proof. - intros; apply existT with (An 0%nat). - unfold Pser in |- *; unfold infinit_sum in |- *; intros; exists 0%nat; intros; + intros; exists (An 0%nat). + unfold Pser in |- *; unfold infinite_sum in |- *; intros; exists 0%nat; intros; replace (sum_f_R0 (fun n0:nat => An n0 * x ^ n0) n) with (An 0%nat). unfold R_dist in |- *; unfold Rminus in |- *; rewrite Rplus_opp_r; rewrite Rabs_R0; assumption. @@ -395,12 +395,12 @@ Proof. [ rewrite H; simpl in |- *; ring | unfold ge in |- *; apply le_O_n ]. Qed. -(** An useful criterion of convergence for power series *) +(** A useful criterion of convergence for power series *) Theorem Alembert_C3 : forall (An:nat -> R) (x:R), (forall n:nat, An n <> 0) -> Un_cv (fun n:nat => Rabs (An (S n) / An n)) 0 -> - sigT (fun l:R => Pser An x l). + { l:R | Pser An x l }. Proof. intros; case (total_order_T x 0); intro. elim s; intro. @@ -411,19 +411,19 @@ Proof. cut (x <> 0). intro; apply AlembertC3_step1; assumption. red in |- *; intro; rewrite H1 in r; elim (Rlt_irrefl _ r). -Qed. +Defined. Lemma Alembert_C4 : forall (An:nat -> R) (k:R), 0 <= k < 1 -> (forall n:nat, 0 < An n) -> Un_cv (fun n:nat => Rabs (An (S n) / An n)) k -> - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 An N) l). + { l:R | Un_cv (fun N:nat => sum_f_R0 An N) l }. Proof. intros An k Hyp H H0. cut - (sigT (fun l:R => is_lub (EUn (fun N:nat => sum_f_R0 An N)) l) -> - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 An N) l)). + ({ l:R | is_lub (EUn (fun N:nat => sum_f_R0 An N)) l } -> + { l:R | Un_cv (fun N:nat => sum_f_R0 An N) l }). intro X; apply X. apply completeness. assert (H1 := tech13 _ _ Hyp H0). @@ -524,7 +524,7 @@ Proof. symmetry in |- *; apply tech2; assumption. exists (sum_f_R0 An 0); unfold EUn in |- *; exists 0%nat; reflexivity. intro X; elim X; intros. - apply existT with x; apply tech10; + exists x; apply tech10; [ unfold Un_growing in |- *; intro; rewrite tech5; pattern (sum_f_R0 An n) at 1 in |- *; rewrite <- Rplus_0_r; apply Rplus_le_compat_l; left; apply H @@ -536,21 +536,19 @@ Lemma Alembert_C5 : 0 <= k < 1 -> (forall n:nat, An n <> 0) -> Un_cv (fun n:nat => Rabs (An (S n) / An n)) k -> - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 An N) l). + { l:R | Un_cv (fun N:nat => sum_f_R0 An N) l }. Proof. intros. cut - (sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 An N) l) -> - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 An N) l)). + ({ l:R | Un_cv (fun N:nat => sum_f_R0 An N) l } -> + { l:R | Un_cv (fun N:nat => sum_f_R0 An N) l }). intro Hyp0; apply Hyp0. apply cv_cauchy_2. apply cauchy_abs. apply cv_cauchy_1. cut - (sigT - (fun l:R => Un_cv (fun N:nat => sum_f_R0 (fun i:nat => Rabs (An i)) N) l) -> - sigT - (fun l:R => Un_cv (fun N:nat => sum_f_R0 (fun i:nat => Rabs (An i)) N) l)). + ({ l:R | Un_cv (fun N:nat => sum_f_R0 (fun i:nat => Rabs (An i)) N) l } -> + { l:R | Un_cv (fun N:nat => sum_f_R0 (fun i:nat => Rabs (An i)) N) l }). intro Hyp; apply Hyp. apply (Alembert_C4 (fun i:nat => Rabs (An i)) k). assumption. @@ -568,11 +566,11 @@ Proof. apply H0. intro X. elim X; intros. - apply existT with x. + exists x. assumption. intro X. elim X; intros. - apply existT with x. + exists x. assumption. Qed. @@ -583,14 +581,12 @@ Lemma Alembert_C6 : 0 < k -> (forall n:nat, An n <> 0) -> Un_cv (fun n:nat => Rabs (An (S n) / An n)) k -> - Rabs x < / k -> sigT (fun l:R => Pser An x l). + Rabs x < / k -> { l:R | Pser An x l }. intros. - cut - (sigT - (fun l:R => Un_cv (fun N:nat => sum_f_R0 (fun i:nat => An i * x ^ i) N) l)). + cut { l:R | Un_cv (fun N:nat => sum_f_R0 (fun i:nat => An i * x ^ i) N) l }. intro X. elim X; intros. - apply existT with x0. + exists x0. apply tech12; assumption. case (total_order_T x 0); intro. elim s; intro. @@ -655,7 +651,7 @@ Lemma Alembert_C6 : assumption. apply Rinv_0_lt_compat; apply Rabs_pos_lt. red in |- *; intro H7; rewrite H7 in a; elim (Rlt_irrefl _ a). - apply existT with (An 0%nat). + exists (An 0%nat). unfold Un_cv in |- *. intros. exists 0%nat. diff --git a/theories/Reals/AltSeries.v b/theories/Reals/AltSeries.v index 581c181f..5c4bbd6a 100644 --- a/theories/Reals/AltSeries.v +++ b/theories/Reals/AltSeries.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) - (*i $Id: AltSeries.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) + (*i $Id: AltSeries.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -153,14 +153,14 @@ Lemma CV_ALT : Un_decreasing Un -> positivity_seq Un -> Un_cv Un 0 -> - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 (tg_alt Un) N) l). + { l:R | Un_cv (fun N:nat => sum_f_R0 (tg_alt Un) N) l }. Proof. intros. assert (H2 := CV_ALT_step0 _ H). assert (H3 := CV_ALT_step4 _ H H0). assert (X := growing_cv _ H2 H3). elim X; intros. - apply existT with x. + exists x. unfold Un_cv in |- *; unfold R_dist in |- *; unfold Un_cv in H1; unfold R_dist in H1; unfold Un_cv in p; unfold R_dist in p. intros; cut (0 < eps / 2); @@ -220,7 +220,7 @@ Theorem alternated_series : forall Un:nat -> R, Un_decreasing Un -> Un_cv Un 0 -> - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 (tg_alt Un) N) l). + { l:R | Un_cv (fun N:nat => sum_f_R0 (tg_alt Un) N) l }. Proof. intros; apply CV_ALT. assumption. @@ -408,7 +408,7 @@ Proof. Qed. Lemma exist_PI : - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 (tg_alt PI_tg) N) l). + { l:R | Un_cv (fun N:nat => sum_f_R0 (tg_alt PI_tg) N) l }. Proof. apply alternated_series. apply PI_tg_decreasing. @@ -416,9 +416,7 @@ Proof. Qed. (** Now, PI is defined *) -Definition PI : R := 4 * match exist_PI with - | existT a b => a - end. +Definition PI : R := 4 * (let (a,_) := exist_PI in a). (** We can get an approximation of PI with the following inequality *) Lemma PI_ineq : diff --git a/theories/Reals/ArithProp.v b/theories/Reals/ArithProp.v index 7dbbd605..7327c64c 100644 --- a/theories/Reals/ArithProp.v +++ b/theories/Reals/ArithProp.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) - (*i $Id: ArithProp.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) + (*i $Id: ArithProp.v 9454 2006-12-15 15:30:59Z bgregoir $ i*) Require Import Rbase. Require Import Rbasic_fun. diff --git a/theories/Reals/Cos_plus.v b/theories/Reals/Cos_plus.v index 10965951..0de639e8 100644 --- a/theories/Reals/Cos_plus.v +++ b/theories/Reals/Cos_plus.v @@ -6,14 +6,16 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) - (*i $Id: Cos_plus.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) + (*i $Id: Cos_plus.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. Require Import SeqSeries. Require Import Rtrigo_def. Require Import Cos_rel. -Require Import Max. Open Local Scope nat_scope. Open Local Scope R_scope. +Require Import Max. +Open Local Scope nat_scope. +Open Local Scope R_scope. Definition Majxy (x y:R) (n:nat) : R := Rmax 1 (Rmax (Rabs x) (Rabs y)) ^ (4 * S n) / INR (fact n). diff --git a/theories/Reals/Cos_rel.v b/theories/Reals/Cos_rel.v index d410e14a..aed481c7 100644 --- a/theories/Reals/Cos_rel.v +++ b/theories/Reals/Cos_rel.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Cos_rel.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: Cos_rel.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -263,7 +263,7 @@ assert (H := exist_cos (x * x)). elim H; intros. assert (p_i := p). unfold cos_in in p. -unfold cos_n, infinit_sum in p. +unfold cos_n, infinite_sum in p. unfold R_dist in p. cut (cos x = x0). intro. @@ -295,7 +295,7 @@ assert (H := exist_cos ((x + y) * (x + y))). elim H; intros. assert (p_i := p). unfold cos_in in p. -unfold cos_n, infinit_sum in p. +unfold cos_n, infinite_sum in p. unfold R_dist in p. cut (cos (x + y) = x0). intro. @@ -344,7 +344,7 @@ assert (H0 := exist_sin (x * x)). elim H0; intros. assert (p_i := p). unfold sin_in in p. -unfold sin_n, infinit_sum in p. +unfold sin_n, infinite_sum in p. unfold R_dist in p. cut (sin x = x * x0). intro. diff --git a/theories/Reals/DiscrR.v b/theories/Reals/DiscrR.v index a16af05c..22a52e67 100644 --- a/theories/Reals/DiscrR.v +++ b/theories/Reals/DiscrR.v @@ -6,10 +6,11 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: DiscrR.v 9178 2006-09-26 11:18:22Z barras $ i*) +(*i $Id: DiscrR.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import RIneq. -Require Import Omega. Open Local Scope R_scope. +Require Import Omega. +Open Local Scope R_scope. Lemma Rlt_R0_R2 : 0 < 2. change 2 with (INR 2); apply lt_INR_0; apply lt_O_Sn. diff --git a/theories/Reals/Exp_prop.v b/theories/Reals/Exp_prop.v index beb4b744..bf729526 100644 --- a/theories/Reals/Exp_prop.v +++ b/theories/Reals/Exp_prop.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Exp_prop.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: Exp_prop.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -27,7 +27,7 @@ Lemma E1_cvg : forall x:R, Un_cv (E1 x) (exp x). Proof. intro; unfold exp in |- *; unfold projT1 in |- *. case (exist_exp x); intro. - unfold exp_in, Un_cv in |- *; unfold infinit_sum, E1 in |- *; trivial. + unfold exp_in, Un_cv in |- *; unfold infinite_sum, E1 in |- *; trivial. Qed. Definition Reste_E (x y:R) (N:nat) : R := @@ -734,7 +734,7 @@ Proof. apply Rinv_0_lt_compat; apply INR_fact_lt_0. apply (pow_lt _ n H). unfold exp in |- *; unfold projT1 in |- *; case (exist_exp x); intro. - unfold exp_in in |- *; unfold infinit_sum, Un_cv in |- *; trivial. + unfold exp_in in |- *; unfold infinite_sum, Un_cv in |- *; trivial. Qed. (**********) @@ -769,7 +769,7 @@ Proof. unfold derivable_pt_lim in |- *; intros. set (fn := fun (N:nat) (x:R) => x ^ N / INR (fact (S N))). cut (CVN_R fn). - intro; cut (forall x:R, sigT (fun l:R => Un_cv (fun N:nat => SP fn N x) l)). + intro; cut (forall x:R, { l:R | Un_cv (fun N:nat => SP fn N x) l }). intro cv; cut (forall n:nat, continuity (fn n)). intro; cut (continuity (SFL fn cv)). intro; unfold continuity in H1. @@ -809,13 +809,12 @@ Proof. unfold Rdiv in |- *; rewrite Rinv_1; rewrite Rmult_1_r; reflexivity. apply lt_le_trans with 1%nat; [ apply lt_n_Sn | apply H9 ]. unfold SFL, exp in |- *. - unfold projT1 in |- *. - case (cv h); case (exist_exp h); intros. + case (cv h); case (exist_exp h); simpl; intros. eapply UL_sequence. apply u. unfold Un_cv in |- *; intros. unfold exp_in in e. - unfold infinit_sum in e. + unfold infinite_sum in e. cut (0 < eps0 * Rabs h). intro; elim (e _ H9); intros N0 H10. exists N0; intros. @@ -871,13 +870,12 @@ Proof. assert (H0 := Alembert_exp). unfold CVN_R in |- *. intro; unfold CVN_r in |- *. - apply existT with (fun N:nat => r ^ N / INR (fact (S N))). + exists (fun N:nat => r ^ N / INR (fact (S N))). cut - (sigT - (fun l:R => + { l:R | Un_cv (fun n:nat => - sum_f_R0 (fun k:nat => Rabs (r ^ k / INR (fact (S k)))) n) l)). + sum_f_R0 (fun k:nat => Rabs (r ^ k / INR (fact (S k)))) n) l }. intro X. elim X; intros. exists x; intros. diff --git a/theories/Reals/LegacyRfield.v b/theories/Reals/LegacyRfield.v index b33274af..3f76e77a 100644 --- a/theories/Reals/LegacyRfield.v +++ b/theories/Reals/LegacyRfield.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id$ i*) +(*i $Id: LegacyRfield.v 10739 2008-04-01 14:45:20Z herbelin $ i*) Require Export Raxioms. Require Export LegacyField. diff --git a/theories/Reals/MVT.v b/theories/Reals/MVT.v index 8bb9298a..f22e49e1 100644 --- a/theories/Reals/MVT.v +++ b/theories/Reals/MVT.v @@ -6,12 +6,13 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: MVT.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: MVT.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. Require Import Ranalysis1. -Require Import Rtopology. Open Local Scope R_scope. +Require Import Rtopology. +Open Local Scope R_scope. (* The Mean Value Theorem *) Theorem MVT : @@ -189,7 +190,7 @@ Proof. intros; apply derivable_pt_id. intros; apply derivable_continuous_pt; apply X; assumption. intros; elim H1; intros; apply X; split; left; assumption. - intros; unfold derivable_pt in |- *; apply existT with (f' c); apply H0; + intros; unfold derivable_pt in |- *; exists (f' c); apply H0; apply H1. Qed. @@ -695,11 +696,11 @@ Proof. unfold antiderivative in |- *; intros; elim H; clear H; intros; elim H0; clear H0; intros H0 _; exists (g1 a - g2 a); intros; assert (H3 : forall x:R, a <= x <= b -> derivable_pt g1 x). - intros; unfold derivable_pt in |- *; apply existT with (f x0); elim (H x0 H3); + intros; unfold derivable_pt in |- *; exists (f x0); elim (H x0 H3); intros; eapply derive_pt_eq_1; symmetry in |- *; apply H4. assert (H4 : forall x:R, a <= x <= b -> derivable_pt g2 x). - intros; unfold derivable_pt in |- *; apply existT with (f x0); + intros; unfold derivable_pt in |- *; exists (f x0); elim (H0 x0 H4); intros; eapply derive_pt_eq_1; symmetry in |- *; apply H5. assert (H5 : forall x:R, a < x < b -> derivable_pt (g1 - g2) x). diff --git a/theories/Reals/NewtonInt.v b/theories/Reals/NewtonInt.v index 306d5ac4..47ae149e 100644 --- a/theories/Reals/NewtonInt.v +++ b/theories/Reals/NewtonInt.v @@ -6,32 +6,31 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: NewtonInt.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: NewtonInt.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. Require Import SeqSeries. Require Import Rtrigo. -Require Import Ranalysis. Open Local Scope R_scope. +Require Import Ranalysis. +Open Local Scope R_scope. (*******************************************) (* Newton's Integral *) (*******************************************) Definition Newton_integrable (f:R -> R) (a b:R) : Type := - sigT (fun g:R -> R => antiderivative f g a b \/ antiderivative f g b a). + { g:R -> R | antiderivative f g a b \/ antiderivative f g b a }. Definition NewtonInt (f:R -> R) (a b:R) (pr:Newton_integrable f a b) : R := - let g := match pr with - | existT a b => a - end in g b - g a. + let (g,_) := pr in g b - g a. (* If f is differentiable, then f' is Newton integrable (Tautology ?) *) Lemma FTCN_step1 : forall (f:Differential) (a b:R), Newton_integrable (fun x:R => derive_pt f x (cond_diff f x)) a b. Proof. - intros f a b; unfold Newton_integrable in |- *; apply existT with (d1 f); + intros f a b; unfold Newton_integrable in |- *; exists (d1 f); unfold antiderivative in |- *; intros; case (Rle_dec a b); intro; [ left; split; [ intros; exists (cond_diff f x); reflexivity | assumption ] @@ -52,7 +51,7 @@ Qed. Lemma NewtonInt_P1 : forall (f:R -> R) (a:R), Newton_integrable f a a. Proof. intros f a; unfold Newton_integrable in |- *; - apply existT with (fct_cte (f a) * id)%F; left; + exists (fct_cte (f a) * id)%F; left; unfold antiderivative in |- *; split. intros; assert (H1 : derivable_pt (fct_cte (f a) * id) x). apply derivable_pt_mult. @@ -82,7 +81,7 @@ Lemma NewtonInt_P3 : Newton_integrable f b a. Proof. unfold Newton_integrable in |- *; intros; elim X; intros g H; - apply existT with g; tauto. + exists g; tauto. Defined. (* $\int_a^b f = -\int_b^a f$ *) @@ -94,7 +93,7 @@ Proof. unfold NewtonInt in |- *; case (NewtonInt_P3 f a b - (existT + (exist (fun g:R -> R => antiderivative f g a b \/ antiderivative f g b a) x p)). intros; elim o; intro. @@ -112,7 +111,7 @@ Proof. unfold NewtonInt in |- *; case (NewtonInt_P3 f a b - (existT + (exist (fun g:R -> R => antiderivative f g a b \/ antiderivative f g b a) x p)); intros; elim o; intro. assert (H1 := antiderivative_Ucte f x x0 b a H H0); elim H1; intros; @@ -325,7 +324,7 @@ Proof. | left _ => F0 x | right _ => F1 x + (F0 b - F1 b) end) x). - unfold derivable_pt in |- *; apply existT with (f x); apply H7. + unfold derivable_pt in |- *; exists (f x); apply H7. exists H8; symmetry in |- *; apply derive_pt_eq_0; apply H7. assert (H5 : a <= x <= b). split; [ assumption | right; assumption ]. @@ -370,7 +369,7 @@ Proof. | left _ => F0 x | right _ => F1 x + (F0 b - F1 b) end) x). - unfold derivable_pt in |- *; apply existT with (f x); apply H13. + unfold derivable_pt in |- *; exists (f x); apply H13. exists H14; symmetry in |- *; apply derive_pt_eq_0; apply H13. assert (H5 : b <= x <= c). split; [ left; assumption | assumption ]. @@ -417,7 +416,7 @@ Proof. | left _ => F0 x | right _ => F1 x + (F0 b - F1 b) end) x). - unfold derivable_pt in |- *; apply existT with (f x); apply H7. + unfold derivable_pt in |- *; exists (f x); apply H7. exists H8; symmetry in |- *; apply derive_pt_eq_0; apply H7. Qed. @@ -482,7 +481,7 @@ Proof. match Rle_dec x b with | left _ => F0 x | right _ => F1 x + (F0 b - F1 b) - end); apply existT with g; left; unfold g in |- *; + end); exists g; left; unfold g in |- *; apply antiderivative_P2. elim H0; intro. assumption. @@ -508,7 +507,7 @@ Proof. elim s0; intro. (* a<b & b<c *) unfold Newton_integrable in |- *; - apply existT with + exists (fun x:R => match Rle_dec x b with | left _ => F0 x @@ -526,7 +525,7 @@ Proof. (* a<b & b>c *) case (total_order_T a c); intro. elim s0; intro. - unfold Newton_integrable in |- *; apply existT with F0. + unfold Newton_integrable in |- *; exists F0. left. elim H1; intro. unfold antiderivative in H; elim H; clear H; intros _ H. @@ -540,7 +539,7 @@ Proof. unfold antiderivative in H2; elim H2; clear H2; intros _ H2. elim (Rlt_irrefl _ (Rle_lt_trans _ _ _ H2 a0)). rewrite b0; apply NewtonInt_P1. - unfold Newton_integrable in |- *; apply existT with F1. + unfold Newton_integrable in |- *; exists F1. right. elim H1; intro. unfold antiderivative in H; elim H; clear H; intros _ H. @@ -560,7 +559,7 @@ Proof. (* a>b & b<c *) case (total_order_T a c); intro. elim s0; intro. - unfold Newton_integrable in |- *; apply existT with F1. + unfold Newton_integrable in |- *; exists F1. left. elim H1; intro. (*****************) @@ -575,7 +574,7 @@ Proof. unfold antiderivative in H; elim H; clear H; intros _ H. elim (Rlt_irrefl _ (Rle_lt_trans _ _ _ H a0)). rewrite b0; apply NewtonInt_P1. - unfold Newton_integrable in |- *; apply existT with F0. + unfold Newton_integrable in |- *; exists F0. right. elim H0; intro. unfold antiderivative in H; elim H; clear H; intros _ H. diff --git a/theories/Reals/PSeries_reg.v b/theories/Reals/PSeries_reg.v index 64b8e0af..e122a26a 100644 --- a/theories/Reals/PSeries_reg.v +++ b/theories/Reals/PSeries_reg.v @@ -6,14 +6,15 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: PSeries_reg.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: PSeries_reg.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. Require Import SeqSeries. Require Import Ranalysis1. Require Import Max. -Require Import Even. Open Local Scope R_scope. +Require Import Even. +Open Local Scope R_scope. Definition Boule (x:R) (r:posreal) (y:R) : Prop := Rabs (y - x) < r. @@ -28,25 +29,21 @@ Definition CVU (fn:nat -> R -> R) (f:R -> R) (x:R) (** Normal convergence *) Definition CVN_r (fn:nat -> R -> R) (r:posreal) : Type := - sigT - (fun An:nat -> R => - sigT - (fun l:R => + { An:nat -> R & + { l:R | Un_cv (fun n:nat => sum_f_R0 (fun k:nat => Rabs (An k)) n) l /\ - (forall (n:nat) (y:R), Boule 0 r y -> Rabs (fn n y) <= An n))). + (forall (n:nat) (y:R), Boule 0 r y -> Rabs (fn n y) <= An n) } }. Definition CVN_R (fn:nat -> R -> R) : Type := forall r:posreal, CVN_r fn r. Definition SFL (fn:nat -> R -> R) - (cv:forall x:R, sigT (fun l:R => Un_cv (fun N:nat => SP fn N x) l)) - (y:R) : R := match cv y with - | existT a b => a - end. + (cv:forall x:R, { l:R | Un_cv (fun N:nat => SP fn N x) l }) + (y:R) : R := let (a,_) := cv y in a. (** In a complete space, normal convergence implies uniform convergence *) Lemma CVN_CVU : forall (fn:nat -> R -> R) - (cv:forall x:R, sigT (fun l:R => Un_cv (fun N:nat => SP fn N x) l)) + (cv:forall x:R, {l:R | Un_cv (fun N:nat => SP fn N x) l }) (r:posreal), CVN_r fn r -> CVU (fun n:nat => SP fn n) (SFL fn cv) 0 r. Proof. intros; unfold CVU in |- *; intros. @@ -193,7 +190,7 @@ Qed. (** Continuity and normal convergence *) Lemma SFL_continuity_pt : forall (fn:nat -> R -> R) - (cv:forall x:R, sigT (fun l:R => Un_cv (fun N:nat => SP fn N x) l)) + (cv:forall x:R, { l:R | Un_cv (fun N:nat => SP fn N x) l }) (r:posreal), CVN_r fn r -> (forall (n:nat) (y:R), Boule 0 r y -> continuity_pt (fn n) y) -> @@ -210,7 +207,7 @@ Qed. Lemma SFL_continuity : forall (fn:nat -> R -> R) - (cv:forall x:R, sigT (fun l:R => Un_cv (fun N:nat => SP fn N x) l)), + (cv:forall x:R, { l:R | Un_cv (fun N:nat => SP fn N x) l }), CVN_R fn -> (forall n:nat, continuity (fn n)) -> continuity (SFL fn cv). Proof. intros; unfold continuity in |- *; intro. @@ -229,7 +226,7 @@ Qed. (** As R is complete, normal convergence implies that (fn) is simply-uniformly convergent *) Lemma CVN_R_CVS : forall fn:nat -> R -> R, - CVN_R fn -> forall x:R, sigT (fun l:R => Un_cv (fun N:nat => SP fn N x) l). + CVN_R fn -> forall x:R, { l:R | Un_cv (fun N:nat => SP fn N x) l }. Proof. intros; apply R_complete. unfold SP in |- *; set (An := fun N:nat => fn N x). @@ -248,7 +245,7 @@ Proof. rewrite Rminus_0_r. pattern (Rabs x) at 1 in |- *; rewrite <- Rplus_0_r; apply Rplus_lt_compat_l; apply Rlt_0_1. - apply existT with l. + exists l. cut (forall n:nat, 0 <= Bn n). intro; unfold Un_cv in H3; unfold Un_cv in |- *; intros. elim (H3 _ H6); intros. diff --git a/theories/Reals/PartSum.v b/theories/Reals/PartSum.v index a8f72302..d5ae2aca 100644 --- a/theories/Reals/PartSum.v +++ b/theories/Reals/PartSum.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: PartSum.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: PartSum.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -153,7 +153,7 @@ Lemma tech12 : Un_cv (fun N:nat => sum_f_R0 (fun i:nat => An i * x ^ i) N) l -> Pser An x l. Proof. - intros; unfold Pser in |- *; unfold infinit_sum in |- *; unfold Un_cv in H; + intros; unfold Pser in |- *; unfold infinite_sum in |- *; unfold Un_cv in H; assumption. Qed. @@ -218,9 +218,9 @@ Qed. (* Unicity of the limit defined by convergent series *) Lemma uniqueness_sum : forall (An:nat -> R) (l1 l2:R), - infinit_sum An l1 -> infinit_sum An l2 -> l1 = l2. + infinite_sum An l1 -> infinite_sum An l2 -> l1 = l2. Proof. - unfold infinit_sum in |- *; intros. + unfold infinite_sum in |- *; intros. case (Req_dec l1 l2); intro. assumption. cut (0 < Rabs ((l1 - l2) / 2)); [ intro | apply Rabs_pos_lt ]. @@ -450,7 +450,7 @@ Qed. (**********) Lemma cv_cauchy_1 : forall An:nat -> R, - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 An N) l) -> + { l:R | Un_cv (fun N:nat => sum_f_R0 An N) l } -> Cauchy_crit_series An. Proof. intros An X. @@ -481,7 +481,7 @@ Qed. Lemma cv_cauchy_2 : forall An:nat -> R, Cauchy_crit_series An -> - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 An N) l). + { l:R | Un_cv (fun N:nat => sum_f_R0 An N) l }. Proof. intros. apply R_complete. diff --git a/theories/Reals/RIneq.v b/theories/Reals/RIneq.v index 7d98a844..19bdeccd 100644 --- a/theories/Reals/RIneq.v +++ b/theories/Reals/RIneq.v @@ -6,11 +6,11 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: RIneq.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: RIneq.v 10762 2008-04-06 16:57:31Z herbelin $ i*) -(***************************************************************************) -(** Basic lemmas for the classical reals numbers *) -(***************************************************************************) +(*********************************************************) +(** * Basic lemmas for the classical real numbers *) +(*********************************************************) Require Export Raxioms. Require Import Rpow_def. @@ -24,21 +24,32 @@ Open Local Scope R_scope. Implicit Type r : R. -(**************************************************************************) -(** * Relation between orders and equality *) -(**************************************************************************) +(*********************************************************) +(** ** Relation between orders and equality *) +(*********************************************************) + +(** Reflexivity of the large order *) + +Lemma Rle_refl : forall r, r <= r. +Proof. + intro; right; reflexivity. +Qed. +Hint Immediate Rle_refl: rorders. + +Lemma Rge_refl : forall r, r <= r. +Proof. exact Rle_refl. Qed. +Hint Immediate Rge_refl: rorders. + +(** Irreflexivity of the strict order *) -(**********) Lemma Rlt_irrefl : forall r, ~ r < r. Proof. generalize Rlt_asym. intuition eauto. Qed. Hint Resolve Rlt_irrefl: real. -Lemma Rle_refl : forall r, r <= r. -Proof. - intro; right; reflexivity. -Qed. +Lemma Rgt_irrefl : forall r, ~ r > r. +Proof. exact Rlt_irrefl. Qed. Lemma Rlt_not_eq : forall r1 r2, r1 < r2 -> r1 <> r2. Proof. @@ -58,7 +69,7 @@ Proof. Qed. Hint Resolve Rlt_dichotomy_converse: real. -(** Reasoning by case on equalities and order *) +(** Reasoning by case on equality and order *) (**********) Lemma Req_dec : forall r1 r2, r1 = r2 \/ r1 <> r2. @@ -80,58 +91,104 @@ Proof. intros; generalize (total_order_T r1 r2); tauto. Qed. +(*********************************************************) +(** ** Relating [<], [>], [<=] and [>=] *) +(*********************************************************) -(*********************************************************************************) -(** * Order Lemma : relating [<], [>], [<=] and [>=] *) -(*********************************************************************************) +(*********************************************************) +(** ** Order *) +(*********************************************************) + +(** *** Relating strict and large orders *) -(**********) Lemma Rlt_le : forall r1 r2, r1 < r2 -> r1 <= r2. Proof. intros; red in |- *; tauto. Qed. Hint Resolve Rlt_le: real. +Lemma Rgt_ge : forall r1 r2, r1 > r2 -> r1 >= r2. +Proof. + intros; red; tauto. +Qed. + (**********) Lemma Rle_ge : forall r1 r2, r1 <= r2 -> r2 >= r1. Proof. destruct 1; red in |- *; auto with real. Qed. - Hint Immediate Rle_ge: real. +Hint Resolve Rle_ge: rorders. -(**********) Lemma Rge_le : forall r1 r2, r1 >= r2 -> r2 <= r1. Proof. destruct 1; red in |- *; auto with real. Qed. - Hint Resolve Rge_le: real. +Hint Immediate Rge_le: rorders. (**********) +Lemma Rlt_gt : forall r1 r2, r1 < r2 -> r2 > r1. +Proof. + trivial. +Qed. +Hint Resolve Rlt_gt: rorders. + +Lemma Rgt_lt : forall r1 r2, r1 > r2 -> r2 < r1. +Proof. + trivial. +Qed. +Hint Immediate Rgt_lt: rorders. + +(**********) + Lemma Rnot_le_lt : forall r1 r2, ~ r1 <= r2 -> r2 < r1. Proof. intros r1 r2; generalize (Rtotal_order r1 r2); unfold Rle in |- *; tauto. Qed. - Hint Immediate Rnot_le_lt: real. +Lemma Rnot_ge_gt : forall r1 r2, ~ r1 >= r2 -> r2 > r1. +Proof. intros; red; apply Rnot_le_lt. auto with real. Qed. + +Lemma Rnot_le_gt : forall r1 r2, ~ r1 <= r2 -> r1 > r2. +Proof. intros; red; apply Rnot_le_lt. auto with real. Qed. + Lemma Rnot_ge_lt : forall r1 r2, ~ r1 >= r2 -> r1 < r2. +Proof. intros; apply Rnot_le_lt. auto with real. Qed. + +Lemma Rnot_lt_le : forall r1 r2, ~ r1 < r2 -> r2 <= r1. Proof. - intros; apply Rnot_le_lt; auto with real. + intros r1 r2 H; destruct (Rtotal_order r1 r2) as [ | [ H0 | H0 ] ]. + contradiction. subst; auto with rorders. auto with real. Qed. +Lemma Rnot_gt_le : forall r1 r2, ~ r1 > r2 -> r1 <= r2. +Proof. auto using Rnot_lt_le with real. Qed. + +Lemma Rnot_gt_ge : forall r1 r2, ~ r1 > r2 -> r2 >= r1. +Proof. intros; eauto using Rnot_lt_le with rorders. Qed. + +Lemma Rnot_lt_ge : forall r1 r2, ~ r1 < r2 -> r1 >= r2. +Proof. eauto using Rnot_gt_ge with rorders. Qed. + (**********) Lemma Rlt_not_le : forall r1 r2, r2 < r1 -> ~ r1 <= r2. Proof. generalize Rlt_asym Rlt_dichotomy_converse; unfold Rle in |- *. intuition eauto 3. Qed. +Hint Immediate Rlt_not_le: real. Lemma Rgt_not_le : forall r1 r2, r1 > r2 -> ~ r1 <= r2. -Proof Rlt_not_le. +Proof. exact Rlt_not_le. Qed. -Hint Immediate Rlt_not_le: real. +Lemma Rlt_not_ge : forall r1 r2, r1 < r2 -> ~ r1 >= r2. +Proof. red; intros; eapply Rlt_not_le; eauto with real. Qed. +Hint Immediate Rlt_not_ge: real. + +Lemma Rgt_not_ge : forall r1 r2, r2 > r1 -> ~ r1 >= r2. +Proof. exact Rlt_not_ge. Qed. Lemma Rle_not_lt : forall r1 r2, r2 <= r1 -> ~ r1 < r2. Proof. @@ -139,13 +196,14 @@ Proof. unfold Rle in |- *; intuition. Qed. -(**********) -Lemma Rlt_not_ge : forall r1 r2, r1 < r2 -> ~ r1 >= r2. -Proof. - generalize Rlt_not_le. unfold Rle, Rge in |- *. intuition eauto 3. -Qed. +Lemma Rge_not_lt : forall r1 r2, r1 >= r2 -> ~ r1 < r2. +Proof. intros; apply Rle_not_lt; auto with real. Qed. -Hint Immediate Rlt_not_ge: real. +Lemma Rle_not_gt : forall r1 r2, r1 <= r2 -> ~ r1 > r2. +Proof. do 2 intro; apply Rle_not_lt. Qed. + +Lemma Rge_not_gt : forall r1 r2, r2 >= r1 -> ~ r1 > r2. +Proof. do 2 intro; apply Rge_not_lt. Qed. (**********) Lemma Req_le : forall r1 r2, r1 = r2 -> r1 <= r2. @@ -172,25 +230,51 @@ Proof. Qed. Hint Immediate Req_ge_sym: real. +(** *** Asymmetry *) + +(** Remark: [Rlt_asym] is an axiom *) + +Lemma Rgt_asym : forall r1 r2:R, r1 > r2 -> ~ r2 > r1. +Proof. do 2 intro; apply Rlt_asym. Qed. + +(** *** Antisymmetry *) + Lemma Rle_antisym : forall r1 r2, r1 <= r2 -> r2 <= r1 -> r1 = r2. Proof. intros r1 r2; generalize (Rlt_asym r1 r2); unfold Rle in |- *; intuition. Qed. Hint Resolve Rle_antisym: real. +Lemma Rge_antisym : forall r1 r2, r1 >= r2 -> r2 >= r1 -> r1 = r2. +Proof. auto with real. Qed. + (**********) Lemma Rle_le_eq : forall r1 r2, r1 <= r2 /\ r2 <= r1 <-> r1 = r2. Proof. intuition. Qed. +Lemma Rge_ge_eq : forall r1 r2, r1 >= r2 /\ r2 >= r1 <-> r1 = r2. +Proof. + intuition. +Qed. + +(** *** Compatibility with equality *) + Lemma Rlt_eq_compat : forall r1 r2 r3 r4, r1 = r2 -> r2 < r4 -> r4 = r3 -> r1 < r3. Proof. intros x x' y y'; intros; replace x with x'; replace y with y'; assumption. Qed. -(**********) +Lemma Rgt_eq_compat : + forall r1 r2 r3 r4, r1 = r2 -> r2 > r4 -> r4 = r3 -> r1 > r3. +Proof. intros; red; apply Rlt_eq_compat with (r2:=r4) (r4:=r2); auto. Qed. + +(** *** Transitivity *) + +(** Remark: [Rlt_trans] is an axiom *) + Lemma Rle_trans : forall r1 r2 r3, r1 <= r2 -> r2 <= r3 -> r1 <= r3. Proof. generalize trans_eq Rlt_trans Rlt_eq_compat. @@ -198,6 +282,12 @@ Proof. intuition eauto 2. Qed. +Lemma Rge_trans : forall r1 r2 r3, r1 >= r2 -> r2 >= r3 -> r1 >= r3. +Proof. eauto using Rle_trans with rorders. Qed. + +Lemma Rgt_trans : forall r1 r2 r3, r1 > r2 -> r2 > r3 -> r1 > r3. +Proof. eauto using Rlt_trans with rorders. Qed. + (**********) Lemma Rle_lt_trans : forall r1 r2 r3, r1 <= r2 -> r2 < r3 -> r1 < r3. Proof. @@ -206,21 +296,25 @@ Proof. intuition eauto 2. Qed. -(**********) Lemma Rlt_le_trans : forall r1 r2 r3, r1 < r2 -> r2 <= r3 -> r1 < r3. Proof. generalize Rlt_trans Rlt_eq_compat; unfold Rle in |- *; intuition eauto 2. Qed. +Lemma Rge_gt_trans : forall r1 r2 r3, r1 >= r2 -> r2 > r3 -> r1 > r3. +Proof. eauto using Rlt_le_trans with rorders. Qed. + +Lemma Rgt_ge_trans : forall r1 r2 r3, r1 > r2 -> r2 >= r3 -> r1 > r3. +Proof. eauto using Rle_lt_trans with rorders. Qed. + +(** *** (Classical) decidability *) -(** Decidability of the order *) Lemma Rlt_dec : forall r1 r2, {r1 < r2} + {~ r1 < r2}. Proof. intros; generalize (total_order_T r1 r2) (Rlt_dichotomy_converse r1 r2); intuition. Qed. -(**********) Lemma Rle_dec : forall r1 r2, {r1 <= r2} + {~ r1 <= r2}. Proof. intros r1 r2. @@ -228,28 +322,44 @@ Proof. intuition eauto 4 with real. Qed. -(**********) Lemma Rgt_dec : forall r1 r2, {r1 > r2} + {~ r1 > r2}. -Proof. - intros; unfold Rgt in |- *; intros; apply Rlt_dec. -Qed. +Proof. do 2 intro; apply Rlt_dec. Qed. -(**********) Lemma Rge_dec : forall r1 r2, {r1 >= r2} + {~ r1 >= r2}. +Proof. intros; edestruct Rle_dec; [left|right]; eauto with rorders. Qed. + +Lemma Rlt_le_dec : forall r1 r2, {r1 < r2} + {r2 <= r1}. Proof. - intros; generalize (Rle_dec r2 r1); intuition. + intros; generalize (total_order_T r1 r2); intuition. Qed. -Lemma Rlt_le_dec : forall r1 r2, {r1 < r2} + {r2 <= r1}. +Lemma Rgt_ge_dec : forall r1 r2, {r1 > r2} + {r2 >= r1}. +Proof. intros; edestruct Rlt_le_dec; [left|right]; eauto with rorders. Qed. + +Lemma Rle_lt_dec : forall r1 r2, {r1 <= r2} + {r2 < r1}. Proof. intros; generalize (total_order_T r1 r2); intuition. Qed. +Lemma Rge_gt_dec : forall r1 r2, {r1 >= r2} + {r2 > r1}. +Proof. intros; edestruct Rle_lt_dec; [left|right]; eauto with rorders. Qed. + +Lemma Rlt_or_le : forall r1 r2, r1 < r2 \/ r2 <= r1. +Proof. + intros n m; elim (Rle_lt_dec m n); auto with real. +Qed. + +Lemma Rgt_or_ge : forall r1 r2, r1 > r2 \/ r2 >= r1. +Proof. intros; edestruct Rlt_or_le; [left|right]; eauto with rorders. Qed. + Lemma Rle_or_lt : forall r1 r2, r1 <= r2 \/ r2 < r1. Proof. intros n m; elim (Rlt_le_dec m n); auto with real. Qed. +Lemma Rge_or_gt : forall r1 r2, r1 >= r2 \/ r2 > r1. +Proof. intros; edestruct Rle_or_lt; [left|right]; eauto with rorders. Qed. + Lemma Rle_lt_or_eq_dec : forall r1 r2, r1 <= r2 -> {r1 < r2} + {r1 = r2}. Proof. intros r1 r2 H; generalize (total_order_T r1 r2); intuition. @@ -262,19 +372,11 @@ Proof. intros n m p q; intros; generalize (Rlt_le_dec m q); intuition. Qed. -(****************************************************************) -(** * Field Lemmas *) -(* This part contains lemma involving the Fields operations *) -(****************************************************************) (*********************************************************) -(** ** Addition *) +(** ** Addition *) (*********************************************************) -Lemma Rplus_ne : forall r, r + 0 = r /\ 0 + r = r. -Proof. - split; ring. -Qed. -Hint Resolve Rplus_ne: real v62. +(** Remark: [Rplus_0_l] is an axiom *) Lemma Rplus_0_r : forall r, r + 0 = r. Proof. @@ -282,14 +384,22 @@ Proof. Qed. Hint Resolve Rplus_0_r: real. +Lemma Rplus_ne : forall r, r + 0 = r /\ 0 + r = r. +Proof. + split; ring. +Qed. +Hint Resolve Rplus_ne: real v62. + (**********) + +(** Remark: [Rplus_opp_r] is an axiom *) + Lemma Rplus_opp_l : forall r, - r + r = 0. Proof. intro; ring. Qed. Hint Resolve Rplus_opp_l: real. - (**********) Lemma Rplus_opp_r_uniq : forall r1 r2, r1 + r2 = 0 -> r2 = - r1. Proof. @@ -298,7 +408,6 @@ Proof. rewrite Rplus_assoc; rewrite H; ring. Qed. -(*i New i*) Hint Resolve (f_equal (A:=R)): real. Lemma Rplus_eq_compat_l : forall r r1 r2, r1 = r2 -> r + r1 = r + r2. @@ -325,9 +434,31 @@ Proof. intros r b; pattern r at 2 in |- *; replace r with (r + 0); eauto with real. Qed. -(***********************************************************) -(** ** Multiplication *) -(***********************************************************) +(***********) +Lemma Rplus_eq_0_l : + forall r1 r2, 0 <= r1 -> 0 <= r2 -> r1 + r2 = 0 -> r1 = 0. +Proof. + intros a b H [H0| H0] H1; auto with real. + absurd (0 < a + b). + rewrite H1; auto with real. + apply Rle_lt_trans with (a + 0). + rewrite Rplus_0_r in |- *; assumption. + auto using Rplus_lt_compat_l with real. + rewrite <- H0, Rplus_0_r in H1; assumption. +Qed. + +Lemma Rplus_eq_R0 : + forall r1 r2, 0 <= r1 -> 0 <= r2 -> r1 + r2 = 0 -> r1 = 0 /\ r2 = 0. +Proof. + intros a b; split. + apply Rplus_eq_0_l with b; auto with real. + apply Rplus_eq_0_l with a; auto with real. + rewrite Rplus_comm; auto with real. +Qed. + +(*********************************************************) +(** ** Multiplication *) +(*********************************************************) (**********) Lemma Rinv_r : forall r, r <> 0 -> r * / r = 1. @@ -340,13 +471,13 @@ Lemma Rinv_l_sym : forall r, r <> 0 -> 1 = / r * r. Proof. intros; field; trivial. Qed. +Hint Resolve Rinv_l_sym: real. Lemma Rinv_r_sym : forall r, r <> 0 -> 1 = r * / r. Proof. intros; field; trivial. Qed. -Hint Resolve Rinv_l_sym Rinv_r_sym: real. - +Hint Resolve Rinv_r_sym: real. (**********) Lemma Rmult_0_r : forall r, r * 0 = 0. @@ -382,7 +513,7 @@ Proof. auto with real. Qed. -(*i OLD i*)Hint Resolve Rmult_eq_compat_l: v62. +(*i Old i*)Hint Resolve Rmult_eq_compat_l: v62. (**********) Lemma Rmult_eq_reg_l : forall r r1 r2, r * r1 = r * r2 -> r <> 0 -> r1 = r2. @@ -423,7 +554,6 @@ Proof. auto with real. Qed. - (**********) Lemma Rmult_neq_0_reg : forall r1 r2, r1 * r2 <> 0 -> r1 <> 0 /\ r2 <> 0. Proof. @@ -439,6 +569,10 @@ Proof. Qed. Hint Resolve Rmult_integral_contrapositive: real. +Lemma Rmult_integral_contrapositive_currified : + forall r1 r2, r1 <> 0 -> r2 <> 0 -> r1 * r2 <> 0. +Proof. auto using Rmult_integral_contrapositive. Qed. + (**********) Lemma Rmult_plus_distr_r : forall r1 r2 r3, (r1 + r2) * r3 = r1 * r3 + r2 * r3. @@ -446,11 +580,15 @@ Proof. intros; ring. Qed. -(** ** Square function *) +(*********************************************************) +(** ** Square function *) +(*********************************************************) (***********) Definition Rsqr r : R := r * r. +Notation "r ²" := (Rsqr r) (at level 1, format "r ²") : R_scope. + (***********) Lemma Rsqr_0 : Rsqr 0 = 0. unfold Rsqr in |- *; auto with real. @@ -462,7 +600,7 @@ Lemma Rsqr_0_uniq : forall r, Rsqr r = 0 -> r = 0. Qed. (*********************************************************) -(** ** Opposite *) +(** ** Opposite *) (*********************************************************) (**********) @@ -509,8 +647,9 @@ Proof. Qed. Hint Resolve Ropp_plus_distr: real. - -(** ** Opposite and multiplication *) +(*********************************************************) +(** ** Opposite and multiplication *) +(*********************************************************) Lemma Ropp_mult_distr_l_reverse : forall r1 r2, - r1 * r2 = - (r1 * r2). Proof. @@ -530,7 +669,9 @@ Proof. intros; ring. Qed. -(** ** Substraction *) +(*********************************************************) +(** ** Substraction *) +(*********************************************************) Lemma Rminus_0_r : forall r, r - 0 = r. Proof. @@ -555,7 +696,6 @@ Lemma Ropp_minus_distr' : forall r1 r2, - (r2 - r1) = r1 - r2. Proof. intros; ring. Qed. -Hint Resolve Ropp_minus_distr': real. (**********) Lemma Rminus_diag_eq : forall r1 r2, r1 = r2 -> r1 - r2 = 0. @@ -605,7 +745,6 @@ Proof. Qed. Hint Resolve Rminus_not_eq_right: real. - (**********) Lemma Rmult_minus_distr_l : forall r1 r2 r3, r1 * (r2 - r3) = r1 * r2 - r1 * r3. @@ -613,7 +752,10 @@ Proof. intros; ring. Qed. -(** ** Inverse *) +(*********************************************************) +(** ** Inverse *) +(*********************************************************) + Lemma Rinv_1 : / 1 = 1. Proof. field. @@ -677,28 +819,28 @@ Proof. ring. Qed. -(** * Field operations and order *) +(*********************************************************) +(** ** Order and addition *) +(*********************************************************) + +(** *** Compatibility *) -(** ** Order and addition *) +(** Remark: [Rplus_lt_compat_l] is an axiom *) +Lemma Rplus_gt_compat_l : forall r r1 r2, r1 > r2 -> r + r1 > r + r2. +Proof. eauto using Rplus_lt_compat_l with rorders. Qed. +Hint Resolve Rplus_gt_compat_l: real. + +(**********) Lemma Rplus_lt_compat_r : forall r r1 r2, r1 < r2 -> r1 + r < r2 + r. Proof. intros. rewrite (Rplus_comm r1 r); rewrite (Rplus_comm r2 r); auto with real. Qed. - Hint Resolve Rplus_lt_compat_r: real. -(**********) -Lemma Rplus_lt_reg_r : forall r r1 r2, r + r1 < r + r2 -> r1 < r2. -Proof. - intros; cut (- r + r + r1 < - r + r + r2). - rewrite Rplus_opp_l. - elim (Rplus_ne r1); elim (Rplus_ne r2); intros; rewrite <- H3; rewrite <- H1; - auto with zarith real. - rewrite Rplus_assoc; rewrite Rplus_assoc; - apply (Rplus_lt_compat_l (- r) (r + r1) (r + r2) H). -Qed. +Lemma Rplus_gt_compat_r : forall r r1 r2, r1 > r2 -> r1 + r > r2 + r. +Proof. do 3 intro; apply Rplus_lt_compat_r. Qed. (**********) Lemma Rplus_le_compat_l : forall r r1 r2, r1 <= r2 -> r + r1 <= r + r2. @@ -708,6 +850,10 @@ Proof. right; rewrite <- H0; auto with zarith real. Qed. +Lemma Rplus_ge_compat_l : forall r r1 r2, r1 >= r2 -> r + r1 >= r + r2. +Proof. auto using Rplus_le_compat_l with rorders. Qed. +Hint Resolve Rplus_ge_compat_l: real. + (**********) Lemma Rplus_le_compat_r : forall r r1 r2, r1 <= r2 -> r1 + r <= r2 + r. Proof. @@ -718,23 +864,8 @@ Qed. Hint Resolve Rplus_le_compat_l Rplus_le_compat_r: real. -(**********) -Lemma Rplus_le_reg_l : forall r r1 r2, r + r1 <= r + r2 -> r1 <= r2. -Proof. - unfold Rle in |- *; intros; elim H; intro. - left; apply (Rplus_lt_reg_r r r1 r2 H0). - right; apply (Rplus_eq_reg_l r r1 r2 H0). -Qed. - -(**********) -Lemma sum_inequa_Rle_lt : - forall a x b c y d:R, - a <= x -> x < b -> c < y -> y <= d -> a + c < x + y < b + d. -Proof. - intros; split. - apply Rlt_le_trans with (a + y); auto with real. - apply Rlt_le_trans with (b + y); auto with real. -Qed. +Lemma Rplus_ge_compat_r : forall r r1 r2, r1 >= r2 -> r1 + r >= r2 + r. +Proof. auto using Rplus_le_compat_r with rorders. Qed. (*********) Lemma Rplus_lt_compat : @@ -742,12 +873,22 @@ Lemma Rplus_lt_compat : Proof. intros; apply Rlt_trans with (r2 + r3); auto with real. Qed. +Hint Immediate Rplus_lt_compat: real. Lemma Rplus_le_compat : forall r1 r2 r3 r4, r1 <= r2 -> r3 <= r4 -> r1 + r3 <= r2 + r4. Proof. intros; apply Rle_trans with (r2 + r3); auto with real. Qed. +Hint Immediate Rplus_le_compat: real. + +Lemma Rplus_gt_compat : + forall r1 r2 r3 r4, r1 > r2 -> r3 > r4 -> r1 + r3 > r2 + r4. +Proof. auto using Rplus_lt_compat with rorders. Qed. + +Lemma Rplus_ge_compat : + forall r1 r2 r3 r4, r1 >= r2 -> r3 >= r4 -> r1 + r3 >= r2 + r4. +Proof. auto using Rplus_le_compat with rorders. Qed. (*********) Lemma Rplus_lt_le_compat : @@ -756,19 +897,133 @@ Proof. intros; apply Rlt_le_trans with (r2 + r3); auto with real. Qed. -(*********) Lemma Rplus_le_lt_compat : forall r1 r2 r3 r4, r1 <= r2 -> r3 < r4 -> r1 + r3 < r2 + r4. Proof. intros; apply Rle_lt_trans with (r2 + r3); auto with real. Qed. -Hint Immediate Rplus_lt_compat Rplus_le_compat Rplus_lt_le_compat - Rplus_le_lt_compat: real. +Hint Immediate Rplus_lt_le_compat Rplus_le_lt_compat: real. + +Lemma Rplus_gt_ge_compat : + forall r1 r2 r3 r4, r1 > r2 -> r3 >= r4 -> r1 + r3 > r2 + r4. +Proof. auto using Rplus_lt_le_compat with rorders. Qed. + +Lemma Rplus_ge_gt_compat : + forall r1 r2 r3 r4, r1 >= r2 -> r3 > r4 -> r1 + r3 > r2 + r4. +Proof. auto using Rplus_le_lt_compat with rorders. Qed. + +(**********) +Lemma Rplus_lt_0_compat : forall r1 r2, 0 < r1 -> 0 < r2 -> 0 < r1 + r2. +Proof. + intros x y; intros; apply Rlt_trans with x; + [ assumption + | pattern x at 1 in |- *; rewrite <- (Rplus_0_r x); apply Rplus_lt_compat_l; + assumption ]. +Qed. + +Lemma Rplus_le_lt_0_compat : forall r1 r2, 0 <= r1 -> 0 < r2 -> 0 < r1 + r2. +Proof. + intros x y; intros; apply Rle_lt_trans with x; + [ assumption + | pattern x at 1 in |- *; rewrite <- (Rplus_0_r x); apply Rplus_lt_compat_l; + assumption ]. +Qed. + +Lemma Rplus_lt_le_0_compat : forall r1 r2, 0 < r1 -> 0 <= r2 -> 0 < r1 + r2. +Proof. + intros x y; intros; rewrite <- Rplus_comm; apply Rplus_le_lt_0_compat; + assumption. +Qed. -(** ** Order and Opposite *) +Lemma Rplus_le_le_0_compat : forall r1 r2, 0 <= r1 -> 0 <= r2 -> 0 <= r1 + r2. +Proof. + intros x y; intros; apply Rle_trans with x; + [ assumption + | pattern x at 1 in |- *; rewrite <- (Rplus_0_r x); apply Rplus_le_compat_l; + assumption ]. +Qed. (**********) +Lemma sum_inequa_Rle_lt : + forall a x b c y d:R, + a <= x -> x < b -> c < y -> y <= d -> a + c < x + y < b + d. +Proof. + intros; split. + apply Rlt_le_trans with (a + y); auto with real. + apply Rlt_le_trans with (b + y); auto with real. +Qed. + +(** *** Cancellation *) + +Lemma Rplus_lt_reg_r : forall r r1 r2, r + r1 < r + r2 -> r1 < r2. +Proof. + intros; cut (- r + r + r1 < - r + r + r2). + rewrite Rplus_opp_l. + elim (Rplus_ne r1); elim (Rplus_ne r2); intros; rewrite <- H3; rewrite <- H1; + auto with zarith real. + rewrite Rplus_assoc; rewrite Rplus_assoc; + apply (Rplus_lt_compat_l (- r) (r + r1) (r + r2) H). +Qed. + +Lemma Rplus_le_reg_l : forall r r1 r2, r + r1 <= r + r2 -> r1 <= r2. +Proof. + unfold Rle in |- *; intros; elim H; intro. + left; apply (Rplus_lt_reg_r r r1 r2 H0). + right; apply (Rplus_eq_reg_l r r1 r2 H0). +Qed. + +Lemma Rplus_gt_reg_l : forall r r1 r2, r + r1 > r + r2 -> r1 > r2. +Proof. + unfold Rgt in |- *; intros; apply (Rplus_lt_reg_r r r2 r1 H). +Qed. + +Lemma Rplus_ge_reg_l : forall r r1 r2, r + r1 >= r + r2 -> r1 >= r2. +Proof. + intros; apply Rle_ge; apply Rplus_le_reg_l with r; auto with real. +Qed. + +(**********) +Lemma Rplus_le_reg_pos_r : + forall r1 r2 r3, 0 <= r2 -> r1 + r2 <= r3 -> r1 <= r3. +Proof. + intros x y z; intros; apply Rle_trans with (x + y); + [ pattern x at 1; rewrite <- (Rplus_0_r x); apply Rplus_le_compat_l; + assumption + | assumption ]. +Qed. + +Lemma Rplus_lt_reg_pos_r : forall r1 r2 r3, 0 <= r2 -> r1 + r2 < r3 -> r1 < r3. +Proof. + intros x y z; intros; apply Rle_lt_trans with (x + y); + [ pattern x at 1; rewrite <- (Rplus_0_r x); apply Rplus_le_compat_l; + assumption + | assumption ]. +Qed. + +Lemma Rplus_ge_reg_neg_r : + forall r1 r2 r3, 0 >= r2 -> r1 + r2 >= r3 -> r1 >= r3. +Proof. + intros x y z; intros; apply Rge_trans with (x + y); + [ pattern x at 1; rewrite <- (Rplus_0_r x); apply Rplus_ge_compat_l; + assumption + | assumption ]. +Qed. + +Lemma Rplus_gt_reg_neg_r : forall r1 r2 r3, 0 >= r2 -> r1 + r2 > r3 -> r1 > r3. +Proof. + intros x y z; intros; apply Rge_gt_trans with (x + y); + [ pattern x at 1; rewrite <- (Rplus_0_r x); apply Rplus_ge_compat_l; + assumption + | assumption ]. +Qed. + +(*********************************************************) +(** ** Order and opposite *) +(*********************************************************) + +(** *** Contravariant compatibility *) + Lemma Ropp_gt_lt_contravar : forall r1 r2, r1 > r2 -> - r1 < - r2. Proof. unfold Rgt in |- *; intros. @@ -781,55 +1036,44 @@ Proof. Qed. Hint Resolve Ropp_gt_lt_contravar. -(**********) Lemma Ropp_lt_gt_contravar : forall r1 r2, r1 < r2 -> - r1 > - r2. Proof. unfold Rgt in |- *; auto with real. Qed. Hint Resolve Ropp_lt_gt_contravar: real. -Lemma Ropp_lt_cancel : forall r1 r2, - r2 < - r1 -> r1 < r2. -Proof. - intros x y H'. - rewrite <- (Ropp_involutive x); rewrite <- (Ropp_involutive y); - auto with real. -Qed. -Hint Immediate Ropp_lt_cancel: real. - +(**********) Lemma Ropp_lt_contravar : forall r1 r2, r2 < r1 -> - r1 < - r2. Proof. auto with real. Qed. Hint Resolve Ropp_lt_contravar: real. +Lemma Ropp_gt_contravar : forall r1 r2, r2 > r1 -> - r1 > - r2. +Proof. auto with real. Qed. + (**********) Lemma Ropp_le_ge_contravar : forall r1 r2, r1 <= r2 -> - r1 >= - r2. Proof. - unfold Rge in |- *; intros r1 r2 [H| H]; auto with real. + unfold Rge; intros r1 r2 [H| H]; auto with real. Qed. Hint Resolve Ropp_le_ge_contravar: real. -Lemma Ropp_le_cancel : forall r1 r2, - r2 <= - r1 -> r1 <= r2. +Lemma Ropp_ge_le_contravar : forall r1 r2, r1 >= r2 -> - r1 <= - r2. Proof. - intros x y H. - elim H; auto with real. - intro H1; rewrite <- (Ropp_involutive x); rewrite <- (Ropp_involutive y); - rewrite H1; auto with real. + unfold Rle; intros r1 r2 [H| H]; auto with real. Qed. -Hint Immediate Ropp_le_cancel: real. +Hint Resolve Ropp_ge_le_contravar: real. +(**********) Lemma Ropp_le_contravar : forall r1 r2, r2 <= r1 -> - r1 <= - r2. Proof. intros r1 r2 H; elim H; auto with real. Qed. Hint Resolve Ropp_le_contravar: real. -(**********) -Lemma Ropp_ge_le_contravar : forall r1 r2, r1 >= r2 -> - r1 <= - r2. -Proof. - unfold Rge in |- *; intros r1 r2 [H| H]; auto with real. -Qed. -Hint Resolve Ropp_ge_le_contravar: real. +Lemma Ropp_ge_contravar : forall r1 r2, r2 >= r1 -> - r1 >= - r2. +Proof. auto using Ropp_le_contravar with real. Qed. (**********) Lemma Ropp_0_lt_gt_contravar : forall r, 0 < r -> 0 > - r. @@ -838,7 +1082,6 @@ Proof. Qed. Hint Resolve Ropp_0_lt_gt_contravar: real. -(**********) Lemma Ropp_0_gt_lt_contravar : forall r, 0 > r -> 0 < - r. Proof. intros; replace 0 with (-0); auto with real. @@ -850,13 +1093,13 @@ Lemma Ropp_lt_gt_0_contravar : forall r, r > 0 -> - r < 0. Proof. intros; rewrite <- Ropp_0; auto with real. Qed. +Hint Resolve Ropp_lt_gt_0_contravar: real. -(**********) Lemma Ropp_gt_lt_0_contravar : forall r, r < 0 -> - r > 0. Proof. intros; rewrite <- Ropp_0; auto with real. Qed. -Hint Resolve Ropp_lt_gt_0_contravar Ropp_gt_lt_0_contravar: real. +Hint Resolve Ropp_gt_lt_0_contravar: real. (**********) Lemma Ropp_0_le_ge_contravar : forall r, 0 <= r -> 0 >= - r. @@ -865,40 +1108,56 @@ Proof. Qed. Hint Resolve Ropp_0_le_ge_contravar: real. -(**********) Lemma Ropp_0_ge_le_contravar : forall r, 0 >= r -> 0 <= - r. Proof. intros; replace 0 with (-0); auto with real. Qed. Hint Resolve Ropp_0_ge_le_contravar: real. -(** ** Order and multiplication *) +(** *** Cancellation *) -Lemma Rmult_lt_compat_r : forall r r1 r2, 0 < r -> r1 < r2 -> r1 * r < r2 * r. +Lemma Ropp_lt_cancel : forall r1 r2, - r2 < - r1 -> r1 < r2. Proof. - intros; rewrite (Rmult_comm r1 r); rewrite (Rmult_comm r2 r); auto with real. + intros x y H'. + rewrite <- (Ropp_involutive x); rewrite <- (Ropp_involutive y); + auto with real. Qed. -Hint Resolve Rmult_lt_compat_r. +Hint Immediate Ropp_lt_cancel: real. -Lemma Rmult_lt_reg_l : forall r r1 r2, 0 < r -> r * r1 < r * r2 -> r1 < r2. +Lemma Ropp_gt_cancel : forall r1 r2, - r2 > - r1 -> r1 > r2. +Proof. auto using Ropp_lt_cancel with rorders. Qed. + +Lemma Ropp_le_cancel : forall r1 r2, - r2 <= - r1 -> r1 <= r2. Proof. - intros z x y H H0. - case (Rtotal_order x y); intros Eq0; auto; elim Eq0; clear Eq0; intros Eq0. - rewrite Eq0 in H0; elimtype False; apply (Rlt_irrefl (z * y)); auto. - generalize (Rmult_lt_compat_l z y x H Eq0); intro; elimtype False; - generalize (Rlt_trans (z * x) (z * y) (z * x) H0 H1); - intro; apply (Rlt_irrefl (z * x)); auto. + intros x y H. + elim H; auto with real. + intro H1; rewrite <- (Ropp_involutive x); rewrite <- (Ropp_involutive y); + rewrite H1; auto with real. Qed. +Hint Immediate Ropp_le_cancel: real. +Lemma Ropp_ge_cancel : forall r1 r2, - r2 >= - r1 -> r1 >= r2. +Proof. auto using Ropp_le_cancel with rorders. Qed. -Lemma Rmult_lt_gt_compat_neg_l : - forall r r1 r2, r < 0 -> r1 < r2 -> r * r1 > r * r2. +(*********************************************************) +(** ** Order and multiplication *) +(*********************************************************) + +(** Remark: [Rmult_lt_compat_l] is an axiom *) + +(** *** Covariant compatibility *) + +Lemma Rmult_lt_compat_r : forall r r1 r2, 0 < r -> r1 < r2 -> r1 * r < r2 * r. Proof. - intros; replace r with (- - r); auto with real. - rewrite (Ropp_mult_distr_l_reverse (- r)); - rewrite (Ropp_mult_distr_l_reverse (- r)). - apply Ropp_lt_gt_contravar; auto with real. + intros; rewrite (Rmult_comm r1 r); rewrite (Rmult_comm r2 r); auto with real. Qed. +Hint Resolve Rmult_lt_compat_r. + +Lemma Rmult_gt_compat_r : forall r r1 r2, r > 0 -> r1 > r2 -> r1 * r > r2 * r. +Proof. eauto using Rmult_lt_compat_r with rorders. Qed. + +Lemma Rmult_gt_compat_l : forall r r1 r2, r > 0 -> r1 > r2 -> r * r1 > r * r2. +Proof. eauto using Rmult_lt_compat_l with rorders. Qed. (**********) Lemma Rmult_le_compat_l : @@ -918,18 +1177,59 @@ Proof. Qed. Hint Resolve Rmult_le_compat_r: real. -Lemma Rmult_le_reg_l : forall r r1 r2, 0 < r -> r * r1 <= r * r2 -> r1 <= r2. +Lemma Rmult_ge_compat_l : + forall r r1 r2, r >= 0 -> r1 >= r2 -> r * r1 >= r * r2. +Proof. eauto using Rmult_le_compat_l with rorders. Qed. + +Lemma Rmult_ge_compat_r : + forall r r1 r2, r >= 0 -> r1 >= r2 -> r1 * r >= r2 * r. +Proof. eauto using Rmult_le_compat_r with rorders. Qed. + +(**********) +Lemma Rmult_le_compat : + forall r1 r2 r3 r4, + 0 <= r1 -> 0 <= r3 -> r1 <= r2 -> r3 <= r4 -> r1 * r3 <= r2 * r4. Proof. - intros z x y H H0; case H0; auto with real. - intros H1; apply Rlt_le. - apply Rmult_lt_reg_l with (r := z); auto. - intros H1; replace x with (/ z * (z * x)); auto with real. - replace y with (/ z * (z * y)). - rewrite H1; auto with real. - rewrite <- Rmult_assoc; rewrite Rinv_l; auto with real. - rewrite <- Rmult_assoc; rewrite Rinv_l; auto with real. + intros x y z t H' H'0 H'1 H'2. + apply Rle_trans with (r2 := x * t); auto with real. + repeat rewrite (fun x => Rmult_comm x t). + apply Rmult_le_compat_l; auto. + apply Rle_trans with z; auto. +Qed. +Hint Resolve Rmult_le_compat: real. + +Lemma Rmult_ge_compat : + forall r1 r2 r3 r4, + 0 <= r1 -> 0 <= r3 -> r1 <= r2 -> r3 <= r4 -> r1 * r3 <= r2 * r4. +Proof. auto with real rorders. Qed. + +Lemma Rmult_gt_0_lt_compat : + forall r1 r2 r3 r4, + r3 > 0 -> r2 > 0 -> r1 < r2 -> r3 < r4 -> r1 * r3 < r2 * r4. +Proof. + intros; apply Rlt_trans with (r2 * r3); auto with real. +Qed. + +(*********) +Lemma Rmult_le_0_lt_compat : + forall r1 r2 r3 r4, + 0 <= r1 -> 0 <= r3 -> r1 < r2 -> r3 < r4 -> r1 * r3 < r2 * r4. +Proof. + intros; apply Rle_lt_trans with (r2 * r3); + [ apply Rmult_le_compat_r; [ assumption | left; assumption ] + | apply Rmult_lt_compat_l; + [ apply Rle_lt_trans with r1; assumption | assumption ] ]. Qed. +(*********) +Lemma Rmult_lt_0_compat : forall r1 r2, 0 < r1 -> 0 < r2 -> 0 < r1 * r2. +Proof. intros; replace 0 with (0 * r2); auto with real. Qed. + +Lemma Rmult_gt_0_compat : forall r1 r2, r1 > 0 -> r2 > 0 -> r1 * r2 > 0. +Proof Rmult_lt_0_compat. + +(** *** Contravariant compatibility *) + Lemma Rmult_le_compat_neg_l : forall r r1 r2, r <= 0 -> r1 <= r2 -> r * r2 <= r * r1. Proof. @@ -946,35 +1246,45 @@ Proof. Qed. Hint Resolve Rmult_le_ge_compat_neg_l: real. -Lemma Rmult_le_compat : - forall r1 r2 r3 r4, - 0 <= r1 -> 0 <= r3 -> r1 <= r2 -> r3 <= r4 -> r1 * r3 <= r2 * r4. +Lemma Rmult_lt_gt_compat_neg_l : + forall r r1 r2, r < 0 -> r1 < r2 -> r * r1 > r * r2. Proof. - intros x y z t H' H'0 H'1 H'2. - apply Rle_trans with (r2 := x * t); auto with real. - repeat rewrite (fun x => Rmult_comm x t). - apply Rmult_le_compat_l; auto. - apply Rle_trans with z; auto. + intros; replace r with (- - r); auto with real. + rewrite (Ropp_mult_distr_l_reverse (- r)); + rewrite (Ropp_mult_distr_l_reverse (- r)). + apply Ropp_lt_gt_contravar; auto with real. Qed. -Hint Resolve Rmult_le_compat: real. -Lemma Rmult_gt_0_lt_compat : - forall r1 r2 r3 r4, - r3 > 0 -> r2 > 0 -> r1 < r2 -> r3 < r4 -> r1 * r3 < r2 * r4. +(** *** Cancellation *) + +Lemma Rmult_lt_reg_l : forall r r1 r2, 0 < r -> r * r1 < r * r2 -> r1 < r2. Proof. - intros; apply Rlt_trans with (r2 * r3); auto with real. + intros z x y H H0. + case (Rtotal_order x y); intros Eq0; auto; elim Eq0; clear Eq0; intros Eq0. + rewrite Eq0 in H0; elimtype False; apply (Rlt_irrefl (z * y)); auto. + generalize (Rmult_lt_compat_l z y x H Eq0); intro; elimtype False; + generalize (Rlt_trans (z * x) (z * y) (z * x) H0 H1); + intro; apply (Rlt_irrefl (z * x)); auto. Qed. -(*********) -Lemma Rmult_ge_0_gt_0_lt_compat : - forall r1 r2 r3 r4, - r3 >= 0 -> r2 > 0 -> r1 < r2 -> r3 < r4 -> r1 * r3 < r2 * r4. +Lemma Rmult_gt_reg_l : forall r r1 r2, 0 < r -> r * r1 < r * r2 -> r1 < r2. +Proof. eauto using Rmult_lt_reg_l with rorders. Qed. + +Lemma Rmult_le_reg_l : forall r r1 r2, 0 < r -> r * r1 <= r * r2 -> r1 <= r2. Proof. - intros; apply Rle_lt_trans with (r2 * r3); auto with real. + intros z x y H H0; case H0; auto with real. + intros H1; apply Rlt_le. + apply Rmult_lt_reg_l with (r := z); auto. + intros H1; replace x with (/ z * (z * x)); auto with real. + replace y with (/ z * (z * y)). + rewrite H1; auto with real. + rewrite <- Rmult_assoc; rewrite Rinv_l; auto with real. + rewrite <- Rmult_assoc; rewrite Rinv_l; auto with real. Qed. - -(** ** Order and Substractions *) +(*********************************************************) +(** ** Order and substraction *) +(*********************************************************) Lemma Rlt_minus : forall r1 r2, r1 < r2 -> r1 - r2 < 0. Proof. @@ -985,12 +1295,27 @@ Proof. Qed. Hint Resolve Rlt_minus: real. +Lemma Rgt_minus : forall r1 r2, r1 > r2 -> r1 - r2 > 0. +Proof. + intros; apply (Rplus_lt_reg_r r2). + replace (r2 + (r1 - r2)) with r1. + replace (r2 + 0) with r2; auto with real. + ring. +Qed. + (**********) Lemma Rle_minus : forall r1 r2, r1 <= r2 -> r1 - r2 <= 0. Proof. destruct 1; unfold Rle in |- *; auto with real. Qed. +Lemma Rge_minus : forall r1 r2, r1 >= r2 -> r1 - r2 >= 0. +Proof. + destruct 1. + auto using Rgt_minus, Rgt_ge. + right; auto using Rminus_diag_eq with rorders. +Qed. + (**********) Lemma Rminus_lt : forall r1 r2, r1 - r2 < 0 -> r1 < r2. Proof. @@ -999,6 +1324,14 @@ Proof. ring. Qed. +Lemma Rminus_gt : forall r1 r2, r1 - r2 > 0 -> r1 > r2. +Proof. + intros; replace r2 with (0 + r2); auto with real. + replace r1 with (r1 - r2 + r2). + apply Rplus_gt_compat_r; assumption. + ring. +Qed. + (**********) Lemma Rminus_le : forall r1 r2, r1 - r2 <= 0 -> r1 <= r2. Proof. @@ -1007,6 +1340,14 @@ Proof. ring. Qed. +Lemma Rminus_ge : forall r1 r2, r1 - r2 >= 0 -> r1 >= r2. +Proof. + intros; replace r2 with (0 + r2); auto with real. + replace r1 with (r1 - r2 + r2). + apply Rplus_ge_compat_r; assumption. + ring. +Qed. + (**********) Lemma tech_Rplus : forall r (s:R), 0 <= r -> 0 < s -> r + s <> 0. Proof. @@ -1015,8 +1356,9 @@ Proof. Qed. Hint Immediate tech_Rplus: real. - -(** ** Order and the square function *) +(*********************************************************) +(** ** Order and square function *) +(*********************************************************) Lemma Rle_0_sqr : forall r, 0 <= Rsqr r. Proof. @@ -1036,7 +1378,26 @@ Proof. Qed. Hint Resolve Rle_0_sqr Rlt_0_sqr: real. -(** ** Zero is less than one *) +(***********) +Lemma Rplus_sqr_eq_0_l : forall r1 r2, Rsqr r1 + Rsqr r2 = 0 -> r1 = 0. +Proof. + intros a b; intros; apply Rsqr_0_uniq; apply Rplus_eq_0_l with (Rsqr b); + auto with real. +Qed. + +Lemma Rplus_sqr_eq_0 : + forall r1 r2, Rsqr r1 + Rsqr r2 = 0 -> r1 = 0 /\ r2 = 0. +Proof. + intros a b; split. + apply Rplus_sqr_eq_0_l with b; auto with real. + apply Rplus_sqr_eq_0_l with a; auto with real. + rewrite Rplus_comm; auto with real. +Qed. + +(*********************************************************) +(** ** Zero is less than one *) +(*********************************************************) + Lemma Rlt_0_1 : 0 < 1. Proof. replace 1 with (Rsqr 1); auto with real. @@ -1050,7 +1411,10 @@ Proof. exact Rlt_0_1. Qed. -(** ** Order and inverse *) +(*********************************************************) +(** ** Order and inverse *) +(*********************************************************) + Lemma Rinv_0_lt_compat : forall r, 0 < r -> 0 < / r. Proof. intros; apply Rnot_le_lt; red in |- *; intros. @@ -1099,68 +1463,9 @@ Proof. Qed. Hint Resolve Rinv_1_lt_contravar: real. -(********************************************************) -(** * Greater *) -(********************************************************) - -(**********) -Lemma Rge_antisym : forall r1 r2, r1 >= r2 -> r2 >= r1 -> r1 = r2. -Proof. - intros; apply Rle_antisym; auto with real. -Qed. - -(**********) -Lemma Rnot_lt_ge : forall r1 r2, ~ r1 < r2 -> r1 >= r2. -Proof. - intros; unfold Rge in |- *; elim (Rtotal_order r1 r2); intro. - absurd (r1 < r2); trivial. - case H0; auto. -Qed. - -(**********) -Lemma Rnot_lt_le : forall r1 r2, ~ r1 < r2 -> r2 <= r1. -Proof. - intros; apply Rge_le; apply Rnot_lt_ge; assumption. -Qed. - -(**********) -Lemma Rnot_gt_le : forall r1 r2, ~ r1 > r2 -> r1 <= r2. -Proof. - intros r1 r2 H; apply Rge_le. - exact (Rnot_lt_ge r2 r1 H). -Qed. - -(**********) -Lemma Rgt_ge : forall r1 r2, r1 > r2 -> r1 >= r2. -Proof. - red in |- *; auto with real. -Qed. - - -(**********) -Lemma Rge_gt_trans : forall r1 r2 r3, r1 >= r2 -> r2 > r3 -> r1 > r3. -Proof. - unfold Rgt in |- *; intros; apply Rlt_le_trans with r2; auto with real. -Qed. - -(**********) -Lemma Rgt_ge_trans : forall r1 r2 r3, r1 > r2 -> r2 >= r3 -> r1 > r3. -Proof. - unfold Rgt in |- *; intros; apply Rle_lt_trans with r2; auto with real. -Qed. - -(**********) -Lemma Rgt_trans : forall r1 r2 r3, r1 > r2 -> r2 > r3 -> r1 > r3. -Proof. - unfold Rgt in |- *; intros; apply Rlt_trans with r2; auto with real. -Qed. - -(**********) -Lemma Rge_trans : forall r1 r2 r3, r1 >= r2 -> r2 >= r3 -> r1 >= r3. -Proof. - intros; apply Rle_ge. - apply Rle_trans with r2; auto with real. -Qed. +(*********************************************************) +(** ** Miscellaneous *) +(*********************************************************) (**********) Lemma Rle_lt_0_plus_1 : forall r, 0 <= r -> 0 < r + 1. @@ -1186,121 +1491,9 @@ Proof. pattern r1 at 2 in |- *; replace r1 with (r1 + 0); auto with real. Qed. -(***********) -Lemma Rplus_gt_compat_l : forall r r1 r2, r1 > r2 -> r + r1 > r + r2. -Proof. - unfold Rgt in |- *; auto with real. -Qed. -Hint Resolve Rplus_gt_compat_l: real. - -(***********) -Lemma Rplus_gt_reg_l : forall r r1 r2, r + r1 > r + r2 -> r1 > r2. -Proof. - unfold Rgt in |- *; intros; apply (Rplus_lt_reg_r r r2 r1 H). -Qed. - -(***********) -Lemma Rplus_ge_compat_l : forall r r1 r2, r1 >= r2 -> r + r1 >= r + r2. -Proof. - intros; apply Rle_ge; auto with real. -Qed. -Hint Resolve Rplus_ge_compat_l: real. - -(***********) -Lemma Rplus_ge_reg_l : forall r r1 r2, r + r1 >= r + r2 -> r1 >= r2. -Proof. - intros; apply Rle_ge; apply Rplus_le_reg_l with r; auto with real. -Qed. - -(***********) -Lemma Rmult_ge_compat_r : - forall r r1 r2, r >= 0 -> r1 >= r2 -> r1 * r >= r2 * r. -Proof. - intros; apply Rle_ge; apply Rmult_le_compat_r; apply Rge_le; assumption. -Qed. - -(***********) -Lemma Rgt_minus : forall r1 r2, r1 > r2 -> r1 - r2 > 0. -Proof. - intros; replace 0 with (r2 - r2); auto with real. - unfold Rgt, Rminus in |- *; auto with real. -Qed. - -(*********) -Lemma minus_Rgt : forall r1 r2, r1 - r2 > 0 -> r1 > r2. -Proof. - intros; replace r2 with (r2 + 0); auto with real. - intros; replace r1 with (r2 + (r1 - r2)); auto with real. -Qed. - -(**********) -Lemma Rge_minus : forall r1 r2, r1 >= r2 -> r1 - r2 >= 0. -Proof. - unfold Rge in |- *; intros; elim H; intro. - left; apply (Rgt_minus r1 r2 H0). - right; apply (Rminus_diag_eq r1 r2 H0). -Qed. - -(*********) -Lemma minus_Rge : forall r1 r2, r1 - r2 >= 0 -> r1 >= r2. -Proof. - intros; replace r2 with (r2 + 0); auto with real. - intros; replace r1 with (r2 + (r1 - r2)); auto with real. -Qed. - - -(*********) -Lemma Rmult_gt_0_compat : forall r1 r2, r1 > 0 -> r2 > 0 -> r1 * r2 > 0. -Proof. - unfold Rgt in |- *; intros. - replace 0 with (0 * r2); auto with real. -Qed. - -(*********) -Lemma Rmult_lt_0_compat : forall r1 r2, 0 < r1 -> 0 < r2 -> 0 < r1 * r2. -Proof Rmult_gt_0_compat. - -(***********) -Lemma Rplus_eq_0_l : - forall r1 r2, 0 <= r1 -> 0 <= r2 -> r1 + r2 = 0 -> r1 = 0. -Proof. - intros a b [H| H] H0 H1; auto with real. - absurd (0 < a + b). - rewrite H1; auto with real. - replace 0 with (0 + 0); auto with real. -Qed. - - -Lemma Rplus_eq_R0 : - forall r1 r2, 0 <= r1 -> 0 <= r2 -> r1 + r2 = 0 -> r1 = 0 /\ r2 = 0. -Proof. - intros a b; split. - apply Rplus_eq_0_l with b; auto with real. - apply Rplus_eq_0_l with a; auto with real. - rewrite Rplus_comm; auto with real. -Qed. - - -(***********) -Lemma Rplus_sqr_eq_0_l : forall r1 r2, Rsqr r1 + Rsqr r2 = 0 -> r1 = 0. -Proof. - intros a b; intros; apply Rsqr_0_uniq; apply Rplus_eq_0_l with (Rsqr b); - auto with real. -Qed. - -Lemma Rplus_sqr_eq_0 : - forall r1 r2, Rsqr r1 + Rsqr r2 = 0 -> r1 = 0 /\ r2 = 0. -Proof. - intros a b; split. - apply Rplus_sqr_eq_0_l with b; auto with real. - apply Rplus_sqr_eq_0_l with a; auto with real. - rewrite Rplus_comm; auto with real. -Qed. - - -(**********************************************************) -(** * Injection from [N] to [R] *) -(**********************************************************) +(*********************************************************) +(** ** Injection from [N] to [R] *) +(*********************************************************) (**********) Lemma S_INR : forall n:nat, INR (S n) = INR n + 1. @@ -1323,6 +1516,7 @@ Proof. repeat rewrite S_INR. rewrite Hrecn; ring. Qed. +Hint Resolve plus_INR: real. (**********) Lemma minus_INR : forall n m:nat, (m <= n)%nat -> INR (n - m) = INR n - INR m. @@ -1332,6 +1526,7 @@ Proof. intros; repeat rewrite S_INR; simpl in |- *. rewrite H0; ring. Qed. +Hint Resolve minus_INR: real. (*********) Lemma mult_INR : forall n m:nat, INR (n * m) = INR n * INR m. @@ -1341,16 +1536,15 @@ Proof. intros; repeat rewrite S_INR; simpl in |- *. rewrite plus_INR; rewrite Hrecn; ring. Qed. - -Hint Resolve plus_INR minus_INR mult_INR: real. +Hint Resolve mult_INR: real. (*********) -Lemma lt_INR_0 : forall n:nat, (0 < n)%nat -> 0 < INR n. +Lemma lt_0_INR : forall n:nat, (0 < n)%nat -> 0 < INR n. Proof. simple induction 1; intros; auto with real. rewrite S_INR; auto with real. Qed. -Hint Resolve lt_INR_0: real. +Hint Resolve lt_0_INR: real. Lemma lt_INR : forall n m:nat, (n < m)%nat -> INR n < INR m. Proof. @@ -1360,20 +1554,20 @@ Proof. Qed. Hint Resolve lt_INR: real. -Lemma INR_lt_1 : forall n:nat, (1 < n)%nat -> 1 < INR n. +Lemma lt_1_INR : forall n:nat, (1 < n)%nat -> 1 < INR n. Proof. intros; replace 1 with (INR 1); auto with real. Qed. -Hint Resolve INR_lt_1: real. +Hint Resolve lt_1_INR: real. (**********) -Lemma INR_pos : forall p:positive, 0 < INR (nat_of_P p). +Lemma pos_INR_nat_of_P : forall p:positive, 0 < INR (nat_of_P p). Proof. - intro; apply lt_INR_0. + intro; apply lt_0_INR. simpl in |- *; auto with real. apply lt_O_nat_of_P. Qed. -Hint Resolve INR_pos: real. +Hint Resolve pos_INR_nat_of_P: real. (**********) Lemma pos_INR : forall n:nat, 0 <= INR n. @@ -1410,25 +1604,25 @@ Qed. Hint Resolve le_INR: real. (**********) -Lemma not_INR_O : forall n:nat, INR n <> 0 -> n <> 0%nat. +Lemma INR_not_0 : forall n:nat, INR n <> 0 -> n <> 0%nat. Proof. red in |- *; intros n H H1. apply H. rewrite H1; trivial. Qed. -Hint Immediate not_INR_O: real. +Hint Immediate INR_not_0: real. (**********) -Lemma not_O_INR : forall n:nat, n <> 0%nat -> INR n <> 0. +Lemma not_0_INR : forall n:nat, n <> 0%nat -> INR n <> 0. Proof. intro n; case n. intro; absurd (0%nat = 0%nat); trivial. intros; rewrite S_INR. apply Rgt_not_eq; red in |- *; auto with real. Qed. -Hint Resolve not_O_INR: real. +Hint Resolve not_0_INR: real. -Lemma not_nm_INR : forall n m:nat, n <> m -> INR n <> INR m. +Lemma not_INR : forall n m:nat, n <> m -> INR n <> INR m. Proof. intros n m H; case (le_or_lt n m); intros H1. case (le_lt_or_eq _ _ H1); intros H2. @@ -1436,17 +1630,17 @@ Proof. elimtype False; auto. apply sym_not_eq; apply Rlt_dichotomy_converse; auto with real. Qed. -Hint Resolve not_nm_INR: real. +Hint Resolve not_INR: real. Lemma INR_eq : forall n m:nat, INR n = INR m -> n = m. Proof. intros; case (le_or_lt n m); intros H1. case (le_lt_or_eq _ _ H1); intros H2; auto. cut (n <> m). - intro H3; generalize (not_nm_INR n m H3); intro H4; elimtype False; auto. + intro H3; generalize (not_INR n m H3); intro H4; elimtype False; auto. omega. symmetry in |- *; cut (m <> n). - intro H3; generalize (not_nm_INR m n H3); intro H4; elimtype False; auto. + intro H3; generalize (not_INR m n H3); intro H4; elimtype False; auto. omega. Qed. Hint Resolve INR_eq: real. @@ -1465,9 +1659,9 @@ Proof. Qed. Hint Resolve not_1_INR: real. -(**********************************************************) -(** * Injection from [Z] to [R] *) -(**********************************************************) +(*********************************************************) +(** ** Injection from [Z] to [R] *) +(*********************************************************) (**********) @@ -1541,6 +1735,12 @@ Proof. Qed. (**********) +Lemma succ_IZR : forall n:Z, IZR (Zsucc n) = IZR n + 1. +Proof. + intro; change 1 with (IZR 1); unfold Zsucc; apply plus_IZR. +Qed. + +(**********) Lemma Ropp_Ropp_IZR : forall n:Z, IZR (- n) = - IZR n. Proof. intro z; case z; simpl in |- *; auto with real. @@ -1554,7 +1754,7 @@ Proof. Qed. (**********) -Lemma lt_O_IZR : forall n:Z, 0 < IZR n -> (0 < n)%Z. +Lemma lt_0_IZR : forall n:Z, 0 < IZR n -> (0 < n)%Z. Proof. intro z; case z; simpl in |- *; intros. absurd (0 < 0); auto with real. @@ -1567,7 +1767,7 @@ Qed. Lemma lt_IZR : forall n m:Z, IZR n < IZR m -> (n < m)%Z. Proof. intros z1 z2 H; apply Zlt_0_minus_lt. - apply lt_O_IZR. + apply lt_0_IZR. rewrite <- Z_R_minus. exact (Rgt_minus (IZR z2) (IZR z1) H). Qed. @@ -1578,7 +1778,7 @@ Proof. intro z; destruct z; simpl in |- *; intros; auto with zarith. case (Rlt_not_eq 0 (INR (nat_of_P p))); auto with real. case (Rlt_not_eq (- INR (nat_of_P p)) 0); auto with real. - apply Ropp_lt_gt_0_contravar. unfold Rgt in |- *; apply INR_pos. + apply Ropp_lt_gt_0_contravar. unfold Rgt in |- *; apply pos_INR_nat_of_P. Qed. (**********) @@ -1590,17 +1790,17 @@ Proof. Qed. (**********) -Lemma not_O_IZR : forall n:Z, n <> 0%Z -> IZR n <> 0. +Lemma not_0_IZR : forall n:Z, n <> 0%Z -> IZR n <> 0. Proof. intros z H; red in |- *; intros H0; case H. apply eq_IZR; auto. Qed. (*********) -Lemma le_O_IZR : forall n:Z, 0 <= IZR n -> (0 <= n)%Z. +Lemma le_0_IZR : forall n:Z, 0 <= IZR n -> (0 <= n)%Z. Proof. unfold Rle in |- *; intros z [H| H]. - red in |- *; intro; apply (Zlt_le_weak 0 z (lt_O_IZR z H)); assumption. + red in |- *; intro; apply (Zlt_le_weak 0 z (lt_0_IZR z H)); assumption. rewrite (eq_IZR_R0 z); auto with zarith real. Qed. @@ -1685,32 +1885,6 @@ Proof. apply H3; apply single_z_r_R1 with r; trivial. Qed. -(*****************************************************************) -(** * Definitions of new types *) -(*****************************************************************) - -Record nonnegreal : Type := mknonnegreal - {nonneg :> R; cond_nonneg : 0 <= nonneg}. - -Record posreal : Type := mkposreal {pos :> R; cond_pos : 0 < pos}. - -Record nonposreal : Type := mknonposreal - {nonpos :> R; cond_nonpos : nonpos <= 0}. - -Record negreal : Type := mknegreal {neg :> R; cond_neg : neg < 0}. - -Record nonzeroreal : Type := mknonzeroreal - {nonzero :> R; cond_nonzero : nonzero <> 0}. - -(**********) -Lemma prod_neq_R0 : forall r1 r2, r1 <> 0 -> r2 <> 0 -> r1 * r2 <> 0. -Proof. - intros x y; intros; red in |- *; intro; generalize (Rmult_integral x y H1); - intro; elim H2; intro; - [ rewrite H3 in H; elim H | rewrite H3 in H0; elim H0 ]; - reflexivity. -Qed. - (*********) Lemma Rmult_le_pos : forall r1 r2, 0 <= r1 -> 0 <= r2 -> 0 <= r1 * r2. Proof. @@ -1728,67 +1902,18 @@ Proof. intro; rewrite <- double; unfold Rdiv in |- *; rewrite <- Rmult_assoc; symmetry in |- *; apply Rinv_r_simpl_m. replace 2 with (INR 2); - [ apply not_O_INR; discriminate | unfold INR in |- *; ring ]. -Qed. - -(**********************************************************) -(** * Other rules about < and <= *) -(**********************************************************) - -Lemma Rplus_lt_0_compat : forall r1 r2, 0 < r1 -> 0 < r2 -> 0 < r1 + r2. -Proof. - intros x y; intros; apply Rlt_trans with x; - [ assumption - | pattern x at 1 in |- *; rewrite <- (Rplus_0_r x); apply Rplus_lt_compat_l; - assumption ]. -Qed. - -Lemma Rplus_le_lt_0_compat : forall r1 r2, 0 <= r1 -> 0 < r2 -> 0 < r1 + r2. -Proof. - intros x y; intros; apply Rle_lt_trans with x; - [ assumption - | pattern x at 1 in |- *; rewrite <- (Rplus_0_r x); apply Rplus_lt_compat_l; - assumption ]. -Qed. - -Lemma Rplus_lt_le_0_compat : forall r1 r2, 0 < r1 -> 0 <= r2 -> 0 < r1 + r2. -Proof. - intros x y; intros; rewrite <- Rplus_comm; apply Rplus_le_lt_0_compat; - assumption. -Qed. - -Lemma Rplus_le_le_0_compat : forall r1 r2, 0 <= r1 -> 0 <= r2 -> 0 <= r1 + r2. -Proof. - intros x y; intros; apply Rle_trans with x; - [ assumption - | pattern x at 1 in |- *; rewrite <- (Rplus_0_r x); apply Rplus_le_compat_l; - assumption ]. -Qed. - -Lemma plus_le_is_le : forall r1 r2 r3, 0 <= r2 -> r1 + r2 <= r3 -> r1 <= r3. -Proof. - intros x y z; intros; apply Rle_trans with (x + y); - [ pattern x at 1 in |- *; rewrite <- (Rplus_0_r x); apply Rplus_le_compat_l; - assumption - | assumption ]. + [ apply not_0_INR; discriminate | unfold INR in |- *; ring ]. Qed. -Lemma plus_lt_is_lt : forall r1 r2 r3, 0 <= r2 -> r1 + r2 < r3 -> r1 < r3. -Proof. - intros x y z; intros; apply Rle_lt_trans with (x + y); - [ pattern x at 1 in |- *; rewrite <- (Rplus_0_r x); apply Rplus_le_compat_l; - assumption - | assumption ]. -Qed. +(*********************************************************) +(** ** Other rules about < and <= *) +(*********************************************************) -Lemma Rmult_le_0_lt_compat : +Lemma Rmult_ge_0_gt_0_lt_compat : forall r1 r2 r3 r4, - 0 <= r1 -> 0 <= r3 -> r1 < r2 -> r3 < r4 -> r1 * r3 < r2 * r4. + r3 >= 0 -> r2 > 0 -> r1 < r2 -> r3 < r4 -> r1 * r3 < r2 * r4. Proof. - intros; apply Rle_lt_trans with (r2 * r3); - [ apply Rmult_le_compat_r; [ assumption | left; assumption ] - | apply Rmult_lt_compat_l; - [ apply Rle_lt_trans with r1; assumption | assumption ] ]. + intros; apply Rle_lt_trans with (r2 * r3); auto with real. Qed. Lemma le_epsilon : @@ -1811,7 +1936,7 @@ Proof. rewrite Rmult_1_r; replace (2 * x) with (x + x). rewrite (Rplus_comm y); intro H5; apply Rplus_le_reg_l with x; assumption. ring. - replace 2 with (INR 2); [ apply not_O_INR; discriminate | reflexivity ]. + replace 2 with (INR 2); [ apply not_0_INR; discriminate | reflexivity ]. pattern y at 2 in |- *; replace y with (y / 2 + y / 2). unfold Rminus, Rdiv in |- *. repeat rewrite Rmult_plus_distr_r. @@ -1822,12 +1947,12 @@ Proof. unfold Rdiv in |- *. rewrite <- Rmult_assoc; apply Rinv_r_simpl_m. replace 2 with (INR 2). - apply not_O_INR. + apply not_0_INR. discriminate. unfold INR in |- *; reflexivity. intro; ring. cut (0%nat <> 2%nat); - [ intro H0; generalize (lt_INR_0 2 (neq_O_lt 2 H0)); unfold INR in |- *; + [ intro H0; generalize (lt_0_INR 2 (neq_O_lt 2 H0)); unfold INR in |- *; intro; assumption | discriminate ]. Qed. @@ -1839,3 +1964,37 @@ Lemma completeness_weak : Proof. intros; elim (completeness E H H0); intros; split with x; assumption. Qed. + +(*********************************************************) +(** * Definitions of new types *) +(*********************************************************) + +Record nonnegreal : Type := mknonnegreal + {nonneg :> R; cond_nonneg : 0 <= nonneg}. + +Record posreal : Type := mkposreal {pos :> R; cond_pos : 0 < pos}. + +Record nonposreal : Type := mknonposreal + {nonpos :> R; cond_nonpos : nonpos <= 0}. + +Record negreal : Type := mknegreal {neg :> R; cond_neg : neg < 0}. + +Record nonzeroreal : Type := mknonzeroreal + {nonzero :> R; cond_nonzero : nonzero <> 0}. + +(** Compatibility *) + +Notation prod_neq_R0 := Rmult_integral_contrapositive_currified (only parsing). +Notation minus_Rgt := Rminus_gt (only parsing). +Notation minus_Rge := Rminus_ge (only parsing). +Notation plus_le_is_le := Rplus_le_reg_pos_r (only parsing). +Notation plus_lt_is_lt := Rplus_lt_reg_pos_r (only parsing). +Notation INR_lt_1 := lt_1_INR (only parsing). +Notation lt_INR_0 := lt_0_INR (only parsing). +Notation not_nm_INR := not_INR (only parsing). +Notation INR_pos := pos_INR_nat_of_P (only parsing). +Notation not_INR_O := INR_not_0 (only parsing). +Notation not_O_INR := not_0_INR (only parsing). +Notation not_O_IZR := not_0_IZR (only parsing). +Notation le_O_IZR := le_0_IZR (only parsing). +Notation lt_O_IZR := lt_0_IZR (only parsing). diff --git a/theories/Reals/R_sqr.v b/theories/Reals/R_sqr.v index 270ea6da..17b6c60d 100644 --- a/theories/Reals/R_sqr.v +++ b/theories/Reals/R_sqr.v @@ -6,10 +6,11 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: R_sqr.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: R_sqr.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. -Require Import Rbasic_fun. Open Local Scope R_scope. +Require Import Rbasic_fun. +Open Local Scope R_scope. (****************************************************) (** Rsqr : some results *) diff --git a/theories/Reals/R_sqrt.v b/theories/Reals/R_sqrt.v index 736365a0..63b8940b 100644 --- a/theories/Reals/R_sqrt.v +++ b/theories/Reals/R_sqrt.v @@ -6,11 +6,12 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: R_sqrt.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: R_sqrt.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. -Require Import Rsqrt_def. Open Local Scope R_scope. +Require Import Rsqrt_def. +Open Local Scope R_scope. (** * Continuous extension of Rsqrt on R *) Definition sqrt (x:R) : R := diff --git a/theories/Reals/Ranalysis.v b/theories/Reals/Ranalysis.v index d712f74b..f48ce563 100644 --- a/theories/Reals/Ranalysis.v +++ b/theories/Reals/Ranalysis.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Ranalysis.v 9319 2006-10-30 12:41:21Z barras $ i*) +(*i $Id: Ranalysis.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -27,7 +27,8 @@ Require Export Rgeom. Require Export RList. Require Export Sqrt_reg. Require Export Ranalysis4. -Require Export Rpower. Open Local Scope R_scope. +Require Export Rpower. +Open Local Scope R_scope. Axiom AppVar : R. diff --git a/theories/Reals/Ranalysis1.v b/theories/Reals/Ranalysis1.v index 93a66e70..9414f7c9 100644 --- a/theories/Reals/Ranalysis1.v +++ b/theories/Reals/Ranalysis1.v @@ -6,12 +6,13 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Ranalysis1.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Ranalysis1.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. Require Export Rlimit. -Require Export Rderiv. Open Local Scope R_scope. +Require Export Rderiv. +Open Local Scope R_scope. Implicit Type f : R -> R. (****************************************************) @@ -269,10 +270,10 @@ Definition derivable_pt_lim f (x l:R) : Prop := Definition derivable_pt_abs f (x l:R) : Prop := derivable_pt_lim f x l. -Definition derivable_pt f (x:R) := sigT (derivable_pt_abs f x). +Definition derivable_pt f (x:R) := { l:R | derivable_pt_abs f x l }. Definition derivable f := forall x:R, derivable_pt f x. -Definition derive_pt f (x:R) (pr:derivable_pt f x) := projT1 pr. +Definition derive_pt f (x:R) (pr:derivable_pt f x) := proj1_sig pr. Definition derive f (pr:derivable f) (x:R) := derive_pt f x (pr x). Arguments Scope derivable_pt_lim [Rfun_scope R_scope]. @@ -380,9 +381,9 @@ Lemma derive_pt_eq : derive_pt f x pr = l <-> derivable_pt_lim f x l. Proof. intros; split. - intro; assert (H1 := projT2 pr); unfold derive_pt in H; rewrite H in H1; + intro; assert (H1 := proj2_sig pr); unfold derive_pt in H; rewrite H in H1; assumption. - intro; assert (H1 := projT2 pr); unfold derivable_pt_abs in H1. + intro; assert (H1 := proj2_sig pr); unfold derivable_pt_abs in H1. assert (H2 := uniqueness_limite _ _ _ _ H H1). unfold derive_pt in |- *; unfold derivable_pt_abs in |- *. symmetry in |- *; assumption. @@ -486,7 +487,7 @@ Qed. Lemma derivable_derive : forall f (x:R) (pr:derivable_pt f x), exists l : R, derive_pt f x pr = l. Proof. - intros; exists (projT1 pr). + intros; exists (proj1_sig pr). unfold derive_pt in |- *; reflexivity. Qed. @@ -714,7 +715,7 @@ Proof. unfold derivable_pt in |- *; intros f1 f2 x X X0. elim X; intros. elim X0; intros. - apply existT with (x0 + x1). + exists (x0 + x1). apply derivable_pt_lim_plus; assumption. Qed. @@ -723,7 +724,7 @@ Lemma derivable_pt_opp : Proof. unfold derivable_pt in |- *; intros f x X. elim X; intros. - apply existT with (- x0). + exists (- x0). apply derivable_pt_lim_opp; assumption. Qed. @@ -734,7 +735,7 @@ Proof. unfold derivable_pt in |- *; intros f1 f2 x X X0. elim X; intros. elim X0; intros. - apply existT with (x0 - x1). + exists (x0 - x1). apply derivable_pt_lim_minus; assumption. Qed. @@ -745,14 +746,14 @@ Proof. unfold derivable_pt in |- *; intros f1 f2 x X X0. elim X; intros. elim X0; intros. - apply existT with (x0 * f2 x + f1 x * x1). + exists (x0 * f2 x + f1 x * x1). apply derivable_pt_lim_mult; assumption. Qed. Lemma derivable_pt_const : forall a x:R, derivable_pt (fct_cte a) x. Proof. intros; unfold derivable_pt in |- *. - apply existT with 0. + exists 0. apply derivable_pt_lim_const. Qed. @@ -761,7 +762,7 @@ Lemma derivable_pt_scal : Proof. unfold derivable_pt in |- *; intros f1 a x X. elim X; intros. - apply existT with (a * x0). + exists (a * x0). apply derivable_pt_lim_scal; assumption. Qed. @@ -774,7 +775,7 @@ Qed. Lemma derivable_pt_Rsqr : forall x:R, derivable_pt Rsqr x. Proof. - unfold derivable_pt in |- *; intro; apply existT with (2 * x). + unfold derivable_pt in |- *; intro; exists (2 * x). apply derivable_pt_lim_Rsqr. Qed. @@ -785,7 +786,7 @@ Proof. unfold derivable_pt in |- *; intros f1 f2 x X X0. elim X; intros. elim X0; intros. - apply existT with (x1 * x0). + exists (x1 * x0). apply derivable_pt_lim_comp; assumption. Qed. @@ -860,9 +861,9 @@ Proof. elim H0; clear H0; intros l2 H0. elim H1; clear H1; intros l H1. rewrite H; rewrite H0; apply derive_pt_eq_0. - assert (H3 := projT2 pr1). + assert (H3 := proj2_sig pr1). unfold derive_pt in H; rewrite H in H3. - assert (H4 := projT2 pr2). + assert (H4 := proj2_sig pr2). unfold derive_pt in H0; rewrite H0 in H4. apply derivable_pt_lim_plus; assumption. Qed. @@ -877,7 +878,7 @@ Proof. elim H; clear H; intros l1 H. elim H0; clear H0; intros l2 H0. rewrite H; apply derive_pt_eq_0. - assert (H3 := projT2 pr1). + assert (H3 := proj2_sig pr1). unfold derive_pt in H; rewrite H in H3. apply derivable_pt_lim_opp; assumption. Qed. @@ -896,9 +897,9 @@ Proof. elim H0; clear H0; intros l2 H0. elim H1; clear H1; intros l H1. rewrite H; rewrite H0; apply derive_pt_eq_0. - assert (H3 := projT2 pr1). + assert (H3 := proj2_sig pr1). unfold derive_pt in H; rewrite H in H3. - assert (H4 := projT2 pr2). + assert (H4 := proj2_sig pr2). unfold derive_pt in H0; rewrite H0 in H4. apply derivable_pt_lim_minus; assumption. Qed. @@ -917,9 +918,9 @@ Proof. elim H0; clear H0; intros l2 H0. elim H1; clear H1; intros l H1. rewrite H; rewrite H0; apply derive_pt_eq_0. - assert (H3 := projT2 pr1). + assert (H3 := proj2_sig pr1). unfold derive_pt in H; rewrite H in H3. - assert (H4 := projT2 pr2). + assert (H4 := proj2_sig pr2). unfold derive_pt in H0; rewrite H0 in H4. apply derivable_pt_lim_mult; assumption. Qed. @@ -944,7 +945,7 @@ Proof. elim H; clear H; intros l1 H. elim H0; clear H0; intros l2 H0. rewrite H; apply derive_pt_eq_0. - assert (H3 := projT2 pr). + assert (H3 := proj2_sig pr). unfold derive_pt in H; rewrite H in H3. apply derivable_pt_lim_scal; assumption. Qed. @@ -978,9 +979,9 @@ Proof. elim H0; clear H0; intros l2 H0. elim H1; clear H1; intros l H1. rewrite H; rewrite H0; apply derive_pt_eq_0. - assert (H3 := projT2 pr1). + assert (H3 := proj2_sig pr1). unfold derive_pt in H; rewrite H in H3. - assert (H4 := projT2 pr2). + assert (H4 := proj2_sig pr2). unfold derive_pt in H0; rewrite H0 in H4. apply derivable_pt_lim_comp; assumption. Qed. @@ -1046,7 +1047,7 @@ Lemma derivable_pt_pow : forall (n:nat) (x:R), derivable_pt (fun y:R => y ^ n) x. Proof. intros; unfold derivable_pt in |- *. - apply existT with (INR n * x ^ pred n). + exists (INR n * x ^ pred n). apply derivable_pt_lim_pow. Qed. diff --git a/theories/Reals/Ranalysis2.v b/theories/Reals/Ranalysis2.v index fb89da67..54801eb7 100644 --- a/theories/Reals/Ranalysis2.v +++ b/theories/Reals/Ranalysis2.v @@ -6,11 +6,12 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Ranalysis2.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Ranalysis2.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. -Require Import Ranalysis1. Open Local Scope R_scope. +Require Import Ranalysis1. +Open Local Scope R_scope. (**********) Lemma formule : diff --git a/theories/Reals/Ranalysis3.v b/theories/Reals/Ranalysis3.v index f50aa2ad..180cf9d6 100644 --- a/theories/Reals/Ranalysis3.v +++ b/theories/Reals/Ranalysis3.v @@ -6,12 +6,13 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Ranalysis3.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Ranalysis3.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. Require Import Ranalysis1. -Require Import Ranalysis2. Open Local Scope R_scope. +Require Import Ranalysis2. +Open Local Scope R_scope. (** Division *) Theorem derivable_pt_lim_div : @@ -23,7 +24,7 @@ Theorem derivable_pt_lim_div : Proof. intros f1 f2 x l1 l2 H H0 H1. cut (derivable_pt f2 x); - [ intro X | unfold derivable_pt in |- *; apply existT with l2; exact H0 ]. + [ intro X | unfold derivable_pt in |- *; exists l2; exact H0 ]. assert (H2 := continuous_neq_0 _ _ (derivable_continuous_pt _ _ X) H1). elim H2; clear H2; intros eps_f2 H2. unfold div_fct in |- *. @@ -761,7 +762,7 @@ Proof. intros f1 f2 x X X0 H. elim X; intros. elim X0; intros. - apply existT with ((x0 * f2 x - x1 * f1 x) / Rsqr (f2 x)). + exists ((x0 * f2 x - x1 * f1 x) / Rsqr (f2 x)). apply derivable_pt_lim_div; assumption. Qed. @@ -789,9 +790,9 @@ Proof. elim H0; clear H0; intros l2 H0. elim H1; clear H1; intros l H1. rewrite H; rewrite H0; apply derive_pt_eq_0. - assert (H3 := projT2 pr1). + assert (H3 := proj2_sig pr1). unfold derive_pt in H; rewrite H in H3. - assert (H4 := projT2 pr2). + assert (H4 := proj2_sig pr2). unfold derive_pt in H0; rewrite H0 in H4. apply derivable_pt_lim_div; assumption. Qed. diff --git a/theories/Reals/Ranalysis4.v b/theories/Reals/Ranalysis4.v index 205c06b4..95f6d27e 100644 --- a/theories/Reals/Ranalysis4.v +++ b/theories/Reals/Ranalysis4.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Ranalysis4.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Ranalysis4.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -14,7 +14,8 @@ Require Import SeqSeries. Require Import Rtrigo. Require Import Ranalysis1. Require Import Ranalysis3. -Require Import Exp_prop. Open Local Scope R_scope. +Require Import Exp_prop. +Open Local Scope R_scope. (**********) Lemma derivable_pt_inv : @@ -28,7 +29,7 @@ Proof. assumption. assumption. unfold div_fct, inv_fct, fct_cte in |- *; intro X0; elim X0; intros; - unfold derivable_pt in |- *; apply existT with x0; + unfold derivable_pt in |- *; exists x0; unfold derivable_pt_abs in |- *; unfold derivable_pt_lim in |- *; unfold derivable_pt_abs in p; unfold derivable_pt_lim in p; intros; elim (p eps H0); intros; exists x1; intros; @@ -164,10 +165,10 @@ Proof. intros. case (total_order_T x 0); intro. elim s; intro. - unfold derivable_pt in |- *; apply existT with (-1). + unfold derivable_pt in |- *; exists (-1). apply (Rabs_derive_2 x a). elim H; exact b. - unfold derivable_pt in |- *; apply existT with 1. + unfold derivable_pt in |- *; exists 1. apply (Rabs_derive_1 x r). Qed. @@ -294,8 +295,8 @@ Proof. unfold derivable_pt in |- *. assert (H := derivable_pt_lim_finite_sum An x N). induction N as [| N HrecN]. - apply existT with 0; apply H. - apply existT with + exists 0; apply H. + exists (sum_f_R0 (fun k:nat => INR (S k) * An (S k) * x ^ k) (pred (S N))); apply H. Qed. @@ -352,7 +353,7 @@ Lemma derivable_pt_exp : forall x:R, derivable_pt exp x. Proof. intro. unfold derivable_pt in |- *. - apply existT with (exp x). + exists (exp x). apply derivable_pt_lim_exp. Qed. @@ -360,7 +361,7 @@ Lemma derivable_pt_cosh : forall x:R, derivable_pt cosh x. Proof. intro. unfold derivable_pt in |- *. - apply existT with (sinh x). + exists (sinh x). apply derivable_pt_lim_cosh. Qed. @@ -368,7 +369,7 @@ Lemma derivable_pt_sinh : forall x:R, derivable_pt sinh x. Proof. intro. unfold derivable_pt in |- *. - apply existT with (cosh x). + exists (cosh x). apply derivable_pt_lim_sinh. Qed. diff --git a/theories/Reals/Raxioms.v b/theories/Reals/Raxioms.v index aaea59f4..6667d2ec 100644 --- a/theories/Reals/Raxioms.v +++ b/theories/Reals/Raxioms.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Raxioms.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Raxioms.v 10710 2008-03-23 09:24:09Z herbelin $ i*) (*********************************************************) (** Axiomatisation of the classical reals *) @@ -130,7 +130,7 @@ Definition IZR (z:Z) : R := Arguments Scope IZR [Z_scope]. (**********************************************************) -(** * [R] Archimedian *) +(** * [R] Archimedean *) (**********************************************************) (**********) @@ -154,4 +154,4 @@ Definition is_lub (E:R -> Prop) (m:R) := Axiom completeness : forall E:R -> Prop, - bound E -> (exists x : R, E x) -> sigT (fun m:R => is_lub E m). + bound E -> (exists x : R, E x) -> { m:R | is_lub E m }. diff --git a/theories/Reals/Rbasic_fun.v b/theories/Reals/Rbasic_fun.v index 98bd607b..a5cc9f19 100644 --- a/theories/Reals/Rbasic_fun.v +++ b/theories/Reals/Rbasic_fun.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rbasic_fun.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Rbasic_fun.v 10710 2008-03-23 09:24:09Z herbelin $ i*) (*********************************************************) (** Complements for the real numbers *) @@ -15,7 +15,8 @@ Require Import Rbase. Require Import R_Ifp. -Require Import Fourier. Open Local Scope R_scope. +Require Import Fourier. +Open Local Scope R_scope. Implicit Type r : R. diff --git a/theories/Reals/Rcomplete.v b/theories/Reals/Rcomplete.v index 16e12d7f..d7fee9c5 100644 --- a/theories/Reals/Rcomplete.v +++ b/theories/Reals/Rcomplete.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rcomplete.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Rcomplete.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -24,7 +24,7 @@ Open Local Scope R_scope. (****************************************************) Theorem R_complete : - forall Un:nat -> R, Cauchy_crit Un -> sigT (fun l:R => Un_cv Un l). + forall Un:nat -> R, Cauchy_crit Un -> { l:R | Un_cv Un l } . Proof. intros. set (Vn := sequence_minorant Un (cauchy_min Un H)). @@ -37,7 +37,7 @@ Proof. elim H1; intros. cut (x = x0). intros. - apply existT with x. + exists x. rewrite <- H2 in p0. unfold Un_cv in |- *. intros. diff --git a/theories/Reals/Rdefinitions.v b/theories/Reals/Rdefinitions.v index 330c0042..002ce8d6 100644 --- a/theories/Reals/Rdefinitions.v +++ b/theories/Reals/Rdefinitions.v @@ -5,7 +5,7 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rdefinitions.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: Rdefinitions.v 10751 2008-04-04 10:23:35Z herbelin $ i*) (*********************************************************) @@ -22,6 +22,8 @@ Delimit Scope R_scope with R. (* Automatically open scope R_scope for arguments of type R *) Bind Scope R_scope with R. +Open Local Scope R_scope. + Parameter R0 : R. Parameter R1 : R. Parameter Rplus : R -> R -> R. @@ -38,33 +40,33 @@ Notation "/ x" := (Rinv x) : R_scope. Infix "<" := Rlt : R_scope. -(*i*******************************************************i*) +(***********************************************************) (**********) -Definition Rgt (r1 r2:R) : Prop := (r2 < r1)%R. +Definition Rgt (r1 r2:R) : Prop := r2 < r1. (**********) -Definition Rle (r1 r2:R) : Prop := (r1 < r2)%R \/ r1 = r2. +Definition Rle (r1 r2:R) : Prop := r1 < r2 \/ r1 = r2. (**********) Definition Rge (r1 r2:R) : Prop := Rgt r1 r2 \/ r1 = r2. (**********) -Definition Rminus (r1 r2:R) : R := (r1 + - r2)%R. +Definition Rminus (r1 r2:R) : R := r1 + - r2. (**********) -Definition Rdiv (r1 r2:R) : R := (r1 * / r2)%R. +Definition Rdiv (r1 r2:R) : R := r1 * / r2. (**********) Infix "-" := Rminus : R_scope. -Infix "/" := Rdiv : R_scope. +Infix "/" := Rdiv : R_scope. Infix "<=" := Rle : R_scope. Infix ">=" := Rge : R_scope. -Infix ">" := Rgt : R_scope. +Infix ">" := Rgt : R_scope. -Notation "x <= y <= z" := ((x <= y)%R /\ (y <= z)%R) : R_scope. -Notation "x <= y < z" := ((x <= y)%R /\ (y < z)%R) : R_scope. -Notation "x < y < z" := ((x < y)%R /\ (y < z)%R) : R_scope. -Notation "x < y <= z" := ((x < y)%R /\ (y <= z)%R) : R_scope. +Notation "x <= y <= z" := (x <= y /\ y <= z) : R_scope. +Notation "x <= y < z" := (x <= y /\ y < z) : R_scope. +Notation "x < y < z" := (x < y /\ y < z) : R_scope. +Notation "x < y <= z" := (x < y /\ y <= z) : R_scope. diff --git a/theories/Reals/Rderiv.v b/theories/Reals/Rderiv.v index e2fd2efe..ba42bad9 100644 --- a/theories/Reals/Rderiv.v +++ b/theories/Reals/Rderiv.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rderiv.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Rderiv.v 10710 2008-03-23 09:24:09Z herbelin $ i*) (*********************************************************) (** Definition of the derivative,continuity *) @@ -19,7 +19,8 @@ Require Import Rlimit. Require Import Fourier. Require Import Classical_Prop. Require Import Classical_Pred_Type. -Require Import Omega. Open Local Scope R_scope. +Require Import Omega. +Open Local Scope R_scope. (*********) Definition D_x (D:R -> Prop) (y x:R) : Prop := D x /\ y <> x. diff --git a/theories/Reals/Rfunctions.v b/theories/Reals/Rfunctions.v index 3d1c0375..b9aec1ea 100644 --- a/theories/Reals/Rfunctions.v +++ b/theories/Reals/Rfunctions.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rfunctions.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: Rfunctions.v 10762 2008-04-06 16:57:31Z herbelin $ i*) (*i Some properties about pow and sum have been made with John Harrison i*) (*i Some Lemmas (about pow and powerRZ) have been done by Laurent Thery i*) @@ -349,8 +349,7 @@ Proof. rewrite Rabs_Rinv; auto. rewrite <- Rinv_pow; auto. rewrite RPow_abs; auto. - rewrite H'0; rewrite Rabs_right; auto with real. - apply Rle_ge; auto with real. + rewrite H'0; rewrite Rabs_right; auto with real rorders. apply Rlt_pow; auto with arith. rewrite Rabs_Rinv; auto. apply Rmult_lt_reg_l with (r := Rabs r). @@ -786,11 +785,14 @@ Proof. Qed. (*******************************) -(** * Infinit Sum *) +(** * Infinite Sum *) (*******************************) (*********) -Definition infinit_sum (s:nat -> R) (l:R) : Prop := +Definition infinite_sum (s:nat -> R) (l:R) : Prop := forall eps:R, eps > 0 -> exists N : nat, (forall n:nat, (n >= N)%nat -> R_dist (sum_f_R0 s n) l < eps). + +(** Compatibility with previous versions *) +Notation infinit_sum := infinite_sum (only parsing). diff --git a/theories/Reals/Rgeom.v b/theories/Reals/Rgeom.v index 8ac9c07f..c96ae5d6 100644 --- a/theories/Reals/Rgeom.v +++ b/theories/Reals/Rgeom.v @@ -6,13 +6,14 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rgeom.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Rgeom.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. Require Import SeqSeries. Require Import Rtrigo. -Require Import R_sqrt. Open Local Scope R_scope. +Require Import R_sqrt. +Open Local Scope R_scope. (** * Distance *) diff --git a/theories/Reals/RiemannInt.v b/theories/Reals/RiemannInt.v index 1cba821e..8d069e2d 100644 --- a/theories/Reals/RiemannInt.v +++ b/theories/Reals/RiemannInt.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: RiemannInt.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: RiemannInt.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rfunctions. Require Import SeqSeries. @@ -15,7 +15,8 @@ Require Import Rbase. Require Import RiemannInt_SF. Require Import Classical_Prop. Require Import Classical_Pred_Type. -Require Import Max. Open Local Scope R_scope. +Require Import Max. +Open Local Scope R_scope. Set Implicit Arguments. @@ -25,13 +26,11 @@ Set Implicit Arguments. Definition Riemann_integrable (f:R -> R) (a b:R) : Type := forall eps:posreal, - sigT - (fun phi:StepFun a b => - sigT - (fun psi:StepFun a b => + { phi:StepFun a b & + { psi:StepFun a b | (forall t:R, Rmin a b <= t <= Rmax a b -> Rabs (f t - phi t) <= psi t) /\ - Rabs (RiemannInt_SF psi) < eps)). + Rabs (RiemannInt_SF psi) < eps } }. Definition phi_sequence (un:nat -> posreal) (f:R -> R) (a b:R) (pr:Riemann_integrable f a b) (n:nat) := @@ -40,12 +39,11 @@ Definition phi_sequence (un:nat -> posreal) (f:R -> R) Lemma phi_sequence_prop : forall (un:nat -> posreal) (f:R -> R) (a b:R) (pr:Riemann_integrable f a b) (N:nat), - sigT - (fun psi:StepFun a b => + { psi:StepFun a b | (forall t:R, Rmin a b <= t <= Rmax a b -> Rabs (f t - phi_sequence un pr N t) <= psi t) /\ - Rabs (RiemannInt_SF psi) < un N). + Rabs (RiemannInt_SF psi) < un N }. Proof. intros; apply (projT2 (pr (un N))). Qed. @@ -55,8 +53,8 @@ Lemma RiemannInt_P1 : Riemann_integrable f a b -> Riemann_integrable f b a. Proof. unfold Riemann_integrable in |- *; intros; elim (X eps); clear X; intros; - elim p; clear p; intros; apply existT with (mkStepFun (StepFun_P6 (pre x))); - apply existT with (mkStepFun (StepFun_P6 (pre x0))); + elim p; clear p; intros; exists (mkStepFun (StepFun_P6 (pre x))); + exists (mkStepFun (StepFun_P6 (pre x0))); elim p; clear p; intros; split. intros; apply (H t); elim H1; clear H1; intros; split; [ apply Rle_trans with (Rmin b a); try assumption; right; @@ -90,7 +88,7 @@ Lemma RiemannInt_P2 : (forall n:nat, (forall t:R, Rmin a b <= t <= Rmax a b -> Rabs (f t - vn n t) <= wn n t) /\ Rabs (RiemannInt_SF (wn n)) < un n) -> - sigT (fun l:R => Un_cv (fun N:nat => RiemannInt_SF (vn N)) l). + { l:R | Un_cv (fun N:nat => RiemannInt_SF (vn N)) l }. Proof. intros; apply R_complete; unfold Un_cv in H; unfold Cauchy_crit in |- *; intros; assert (H3 : 0 < eps / 2). @@ -143,7 +141,7 @@ Lemma RiemannInt_P3 : (forall n:nat, (forall t:R, Rmin a b <= t <= Rmax a b -> Rabs (f t - vn n t) <= wn n t) /\ Rabs (RiemannInt_SF (wn n)) < un n) -> - sigT (fun l:R => Un_cv (fun N:nat => RiemannInt_SF (vn N)) l). + { l:R | Un_cv (fun N:nat => RiemannInt_SF (vn N)) l }. Proof. intros; case (Rle_dec a b); intro. apply RiemannInt_P2 with f un wn; assumption. @@ -181,7 +179,7 @@ Proof. rewrite Rabs_Ropp in H4; apply H4. apply H4. assert (H3 := RiemannInt_P2 _ _ _ _ H H1 H2); elim H3; intros; - apply existT with (- x); unfold Un_cv in |- *; unfold Un_cv in p; + exists (- x); unfold Un_cv in |- *; unfold Un_cv in p; intros; elim (p _ H4); intros; exists x0; intros; generalize (H5 _ H6); unfold R_dist, RiemannInt_SF in |- *; case (Rle_dec b a); case (Rle_dec a b); intros. @@ -205,13 +203,12 @@ Lemma RiemannInt_exists : forall (f:R -> R) (a b:R) (pr:Riemann_integrable f a b) (un:nat -> posreal), Un_cv un 0 -> - sigT - (fun l:R => Un_cv (fun N:nat => RiemannInt_SF (phi_sequence un pr N)) l). + { l:R | Un_cv (fun N:nat => RiemannInt_SF (phi_sequence un pr N)) l }. Proof. intros f; intros; apply RiemannInt_P3 with - f un (fun n:nat => projT1 (phi_sequence_prop un pr n)); - [ apply H | intro; apply (projT2 (phi_sequence_prop un pr n)) ]. + f un (fun n:nat => proj1_sig (phi_sequence_prop un pr n)); + [ apply H | intro; apply (proj2_sig (phi_sequence_prop un pr n)) ]. Qed. Lemma RiemannInt_P4 : @@ -411,9 +408,7 @@ Qed. (**********) Definition RiemannInt (f:R -> R) (a b:R) (pr:Riemann_integrable f a b) : R := - match RiemannInt_exists pr RinvN RinvN_cv with - | existT a' b' => a' - end. + let (a,_) := RiemannInt_exists pr RinvN RinvN_cv in a. Lemma RiemannInt_P5 : forall (f:R -> R) (a b:R) (pr1 pr2:Riemann_integrable f a b), @@ -433,8 +428,7 @@ Qed. Lemma maxN : forall (a b:R) (del:posreal), - a < b -> - sigT (fun n:nat => a + INR n * del < b /\ b <= a + INR (S n) * del). + a < b -> { n:nat | a + INR n * del < b /\ b <= a + INR (S n) * del }. Proof. intros; set (I := fun n:nat => a + INR n * del < b); assert (H0 : exists n : nat, I n). @@ -478,9 +472,7 @@ Fixpoint SubEquiN (N:nat) (x y:R) (del:posreal) {struct N} : Rlist := end. Definition max_N (a b:R) (del:posreal) (h:a < b) : nat := - match maxN del h with - | existT N H0 => N - end. + let (N,_) := maxN del h in N. Definition SubEqui (a b:R) (del:posreal) (h:a < b) : Rlist := SubEquiN (S (max_N del h)) a b del. @@ -490,12 +482,11 @@ Lemma Heine_cor1 : a < b -> (forall x:R, a <= x <= b -> continuity_pt f x) -> forall eps:posreal, - sigT - (fun delta:posreal => + { delta:posreal | delta <= b - a /\ (forall x y:R, a <= x <= b -> - a <= y <= b -> Rabs (x - y) < delta -> Rabs (f x - f y) < eps)). + a <= y <= b -> Rabs (x - y) < delta -> Rabs (f x - f y) < eps) }. Proof. intro f; intros; set @@ -520,7 +511,7 @@ Proof. | intros; apply H3; try assumption; apply Rlt_le_trans with (Rmin x (b - a)); [ assumption | apply Rmin_l ] ]. assert (H3 := completeness E H1 H2); elim H3; intros; cut (0 < x <= b - a). - intro; elim H4; clear H4; intros; apply existT with (mkposreal _ H4); split. + intro; elim H4; clear H4; intros; exists (mkposreal _ H4); split. apply H5. unfold is_lub in p; elim p; intros; unfold is_upper_bound in H6; set (D := Rabs (x0 - y)); elim (classic (exists y : R, D < y /\ E y)); @@ -549,22 +540,21 @@ Lemma Heine_cor2 : forall (f:R -> R) (a b:R), (forall x:R, a <= x <= b -> continuity_pt f x) -> forall eps:posreal, - sigT - (fun delta:posreal => + { delta:posreal | forall x y:R, a <= x <= b -> - a <= y <= b -> Rabs (x - y) < delta -> Rabs (f x - f y) < eps). + a <= y <= b -> Rabs (x - y) < delta -> Rabs (f x - f y) < eps }. Proof. intro f; intros; case (total_order_T a b); intro. elim s; intro. - assert (H0 := Heine_cor1 a0 H eps); elim H0; intros; apply existT with x; + assert (H0 := Heine_cor1 a0 H eps); elim H0; intros; exists x; elim p; intros; apply H2; assumption. - apply existT with (mkposreal _ Rlt_0_1); intros; assert (H3 : x = y); + exists (mkposreal _ Rlt_0_1); intros; assert (H3 : x = y); [ elim H0; elim H1; intros; rewrite b0 in H3; rewrite b0 in H5; apply Rle_antisym; apply Rle_trans with b; assumption | rewrite H3; unfold Rminus in |- *; rewrite Rplus_opp_r; rewrite Rabs_R0; apply (cond_pos eps) ]. - apply existT with (mkposreal _ Rlt_0_1); intros; elim H0; intros; + exists (mkposreal _ Rlt_0_1); intros; elim H0; intros; elim (Rlt_irrefl _ (Rle_lt_trans _ _ _ (Rle_trans _ _ _ H3 H4) r)). Qed. @@ -664,15 +654,14 @@ Qed. Lemma SubEqui_P9 : forall (a b:R) (del:posreal) (f:R -> R) (h:a < b), - sigT - (fun g:StepFun a b => + { g:StepFun a b | g b = f b /\ (forall i:nat, (i < pred (Rlength (SubEqui del h)))%nat -> constant_D_eq g (co_interval (pos_Rl (SubEqui del h) i) (pos_Rl (SubEqui del h) (S i))) - (f (pos_Rl (SubEqui del h) i)))). + (f (pos_Rl (SubEqui del h) i))) }. Proof. intros; apply StepFun_P38; [ apply SubEqui_P7 | apply SubEqui_P1 | apply SubEqui_P2 ]. @@ -1003,11 +992,11 @@ Proof. do 2 rewrite (Rmult_comm 3); repeat rewrite Rmult_assoc; rewrite <- Rinv_l_sym; [ ring | discrR ] | discrR ]. - split with (fun n:nat => projT1 (phi_sequence_prop RinvN pr2 n)); intro; + split with (fun n:nat => proj1_sig (phi_sequence_prop RinvN pr2 n)); intro; rewrite Rmin_comm; rewrite RmaxSym; - apply (projT2 (phi_sequence_prop RinvN pr2 n)). - split with (fun n:nat => projT1 (phi_sequence_prop RinvN pr1 n)); intro; - apply (projT2 (phi_sequence_prop RinvN pr1 n)). + apply (proj2_sig (phi_sequence_prop RinvN pr2 n)). + split with (fun n:nat => proj1_sig (phi_sequence_prop RinvN pr1 n)); intro; + apply (proj2_sig (phi_sequence_prop RinvN pr1 n)). Qed. Lemma RiemannInt_P9 : @@ -1272,11 +1261,11 @@ Proof. case (RiemannInt_exists pr1 RinvN RinvN_cv); intros; eapply UL_sequence; [ apply u0 - | set (psi1 := fun n:nat => projT1 (phi_sequence_prop RinvN pr1 n)); - set (psi2 := fun n:nat => projT1 (phi_sequence_prop RinvN pr3 n)); + | set (psi1 := fun n:nat => proj1_sig (phi_sequence_prop RinvN pr1 n)); + set (psi2 := fun n:nat => proj1_sig (phi_sequence_prop RinvN pr3 n)); apply RiemannInt_P11 with f RinvN (phi_sequence RinvN pr1) psi1 psi2; [ apply RinvN_cv - | intro; apply (projT2 (phi_sequence_prop RinvN pr1 n)) + | intro; apply (proj2_sig (phi_sequence_prop RinvN pr1 n)) | intro; assert (H1 : @@ -1284,7 +1273,7 @@ Proof. Rmin a b <= t /\ t <= Rmax a b -> Rabs (f t + l * g t - phi_sequence RinvN pr3 n t) <= psi2 n t) /\ Rabs (RiemannInt_SF (psi2 n)) < RinvN n); - [ apply (projT2 (phi_sequence_prop RinvN pr3 n)) + [ apply (proj2_sig (phi_sequence_prop RinvN pr3 n)) | elim H1; intros; split; try assumption; intros; replace (f t) with (f t + l * g t); [ apply H2; assumption | rewrite H0; ring ] ] @@ -1360,8 +1349,8 @@ Proof. Rmin a b <= t /\ t <= Rmax a b -> Rabs (f t - phi_sequence RinvN pr1 n t) <= psi1 n t) /\ Rabs (RiemannInt_SF (psi1 n)) < RinvN n)). - split with (fun n:nat => projT1 (phi_sequence_prop RinvN pr1 n)); intro; - apply (projT2 (phi_sequence_prop RinvN pr1 n0)). + split with (fun n:nat => proj1_sig (phi_sequence_prop RinvN pr1 n)); intro; + apply (proj2_sig (phi_sequence_prop RinvN pr1 n0)). assert (H8 : exists psi2 : nat -> StepFun a b, @@ -1370,8 +1359,8 @@ Proof. Rmin a b <= t /\ t <= Rmax a b -> Rabs (g t - phi_sequence RinvN pr2 n t) <= psi2 n t) /\ Rabs (RiemannInt_SF (psi2 n)) < RinvN n)). - split with (fun n:nat => projT1 (phi_sequence_prop RinvN pr2 n)); intro; - apply (projT2 (phi_sequence_prop RinvN pr2 n0)). + split with (fun n:nat => proj1_sig (phi_sequence_prop RinvN pr2 n)); intro; + apply (proj2_sig (phi_sequence_prop RinvN pr2 n0)). assert (H9 : exists psi3 : nat -> StepFun a b, @@ -1380,8 +1369,8 @@ Proof. Rmin a b <= t /\ t <= Rmax a b -> Rabs (f t + l * g t - phi_sequence RinvN pr3 n t) <= psi3 n t) /\ Rabs (RiemannInt_SF (psi3 n)) < RinvN n)). - split with (fun n:nat => projT1 (phi_sequence_prop RinvN pr3 n)); intro; - apply (projT2 (phi_sequence_prop RinvN pr3 n0)). + split with (fun n:nat => proj1_sig (phi_sequence_prop RinvN pr3 n)); intro; + apply (proj2_sig (phi_sequence_prop RinvN pr3 n0)). elim H7; clear H7; intros psi1 H7; elim H8; clear H8; intros psi2 H8; elim H9; clear H9; intros psi3 H9; replace @@ -1552,8 +1541,8 @@ Proof. Rmin a b <= t /\ t <= Rmax a b -> Rabs (f t - phi_sequence RinvN pr n t) <= psi1 n t) /\ Rabs (RiemannInt_SF (psi1 n)) < RinvN n)). - split with (fun n:nat => projT1 (phi_sequence_prop RinvN pr n)); intro; - apply (projT2 (phi_sequence_prop RinvN pr n)). + split with (fun n:nat => proj1_sig (phi_sequence_prop RinvN pr n)); intro; + apply (proj2_sig (phi_sequence_prop RinvN pr n)). elim H1; clear H1; intros psi1 H1; set (phi2 := fun n:nat => mkStepFun (StepFun_P4 a b c)); set (psi2 := fun n:nat => mkStepFun (StepFun_P4 a b 0)); @@ -1647,8 +1636,8 @@ Proof. Rmin a b <= t /\ t <= Rmax a b -> Rabs (Rabs (f t) - phi3 n t) <= psi3 n t) /\ Rabs (RiemannInt_SF (psi3 n)) < RinvN n)). - split with (fun n:nat => projT1 (phi_sequence_prop RinvN pr2 n)); intro; - apply (projT2 (phi_sequence_prop RinvN pr2 n)). + split with (fun n:nat => proj1_sig (phi_sequence_prop RinvN pr2 n)); intro; + apply (proj2_sig (phi_sequence_prop RinvN pr2 n)). assert (H1 : exists psi2 : nat -> StepFun a b, @@ -1664,8 +1653,8 @@ Proof. (forall t:R, Rmin a b <= t /\ t <= Rmax a b -> Rabs (f t - phi1 n t) <= psi2 n t) /\ Rabs (RiemannInt_SF (psi2 n)) < RinvN n)). - split with (fun n:nat => projT1 (phi_sequence_prop RinvN pr1 n)); intro; - apply (projT2 (phi_sequence_prop RinvN pr1 n)). + split with (fun n:nat => proj1_sig (phi_sequence_prop RinvN pr1 n)); intro; + apply (proj2_sig (phi_sequence_prop RinvN pr1 n)). elim H1; clear H1; intros psi2 H1; split with psi2; intros; elim (H1 n); clear H1; intros; split; try assumption. intros; unfold phi2 in |- *; simpl in |- *; @@ -1698,8 +1687,8 @@ Proof. Rmin a b <= t /\ t <= Rmax a b -> Rabs (f t - phi1 n t) <= psi1 n t) /\ Rabs (RiemannInt_SF (psi1 n)) < RinvN n)). - split with (fun n:nat => projT1 (phi_sequence_prop RinvN pr1 n)); intro; - apply (projT2 (phi_sequence_prop RinvN pr1 n)). + split with (fun n:nat => proj1_sig (phi_sequence_prop RinvN pr1 n)); intro; + apply (proj2_sig (phi_sequence_prop RinvN pr1 n)). elim H1; clear H1; intros psi1 H1; set (phi2 := fun N:nat => phi_sequence RinvN pr2 N). set @@ -1722,8 +1711,8 @@ Proof. (forall t:R, Rmin a b <= t /\ t <= Rmax a b -> Rabs (g t - phi2 n t) <= psi2 n t) /\ Rabs (RiemannInt_SF (psi2 n)) < RinvN n)). - split with (fun n:nat => projT1 (phi_sequence_prop RinvN pr2 n)); intro; - apply (projT2 (phi_sequence_prop RinvN pr2 n)). + split with (fun n:nat => proj1_sig (phi_sequence_prop RinvN pr2 n)); intro; + apply (proj2_sig (phi_sequence_prop RinvN pr2 n)). elim H2; clear H2; intros psi2 H2; apply RiemannInt_P11 with f RinvN phi2_m psi2 psi1; try assumption. @@ -2378,8 +2367,8 @@ Proof. Rmin a b <= t /\ t <= Rmax a b -> Rabs (f t - phi_sequence RinvN pr1 n t) <= psi1 n t) /\ Rabs (RiemannInt_SF (psi1 n)) < RinvN n)). - split with (fun n:nat => projT1 (phi_sequence_prop RinvN pr1 n)); intro; - apply (projT2 (phi_sequence_prop RinvN pr1 n)). + split with (fun n:nat => proj1_sig (phi_sequence_prop RinvN pr1 n)); intro; + apply (proj2_sig (phi_sequence_prop RinvN pr1 n)). assert (H2 : exists psi2 : nat -> StepFun b c, @@ -2388,8 +2377,8 @@ Proof. Rmin b c <= t /\ t <= Rmax b c -> Rabs (f t - phi_sequence RinvN pr2 n t) <= psi2 n t) /\ Rabs (RiemannInt_SF (psi2 n)) < RinvN n)). - split with (fun n:nat => projT1 (phi_sequence_prop RinvN pr2 n)); intro; - apply (projT2 (phi_sequence_prop RinvN pr2 n)). + split with (fun n:nat => proj1_sig (phi_sequence_prop RinvN pr2 n)); intro; + apply (proj2_sig (phi_sequence_prop RinvN pr2 n)). assert (H3 : exists psi3 : nat -> StepFun a c, @@ -2398,8 +2387,8 @@ Proof. Rmin a c <= t /\ t <= Rmax a c -> Rabs (f t - phi_sequence RinvN pr3 n t) <= psi3 n t) /\ Rabs (RiemannInt_SF (psi3 n)) < RinvN n)). - split with (fun n:nat => projT1 (phi_sequence_prop RinvN pr3 n)); intro; - apply (projT2 (phi_sequence_prop RinvN pr3 n)). + split with (fun n:nat => proj1_sig (phi_sequence_prop RinvN pr3 n)); intro; + apply (proj2_sig (phi_sequence_prop RinvN pr3 n)). elim H1; clear H1; intros psi1 H1; elim H2; clear H2; intros psi2 H2; elim H3; clear H3; intros psi3 H3; assert (H := RinvN_cv); unfold Un_cv in |- *; intros; assert (H4 : 0 < eps / 3). @@ -3259,7 +3248,7 @@ Lemma RiemannInt_P30 : forall (f:R -> R) (a b:R), a <= b -> (forall x:R, a <= x <= b -> continuity_pt f x) -> - sigT (fun g:R -> R => antiderivative f g a b). + { g:R -> R | antiderivative f g a b }. Proof. intros; split with (primitive H (FTC_P1 H H0)); apply RiemannInt_P29. Qed. diff --git a/theories/Reals/RiemannInt_SF.v b/theories/Reals/RiemannInt_SF.v index 0f91d006..7a02544e 100644 --- a/theories/Reals/RiemannInt_SF.v +++ b/theories/Reals/RiemannInt_SF.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: RiemannInt_SF.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: RiemannInt_SF.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -31,7 +31,7 @@ Qed. Lemma Nzorn : forall I:nat -> Prop, (exists n : nat, I n) -> - Nbound I -> sigT (fun n:nat => I n /\ (forall i:nat, I i -> (i <= n)%nat)). + Nbound I -> { n:nat | I n /\ (forall i:nat, I i -> (i <= n)%nat) }. Proof. intros I H H0; set (E := fun x:R => exists i : nat, I i /\ INR i = x); assert (H1 : bound E). @@ -133,10 +133,10 @@ Definition adapted_couple_opt (f:R -> R) (a b:R) (l lf:Rlist) := (forall i:nat, (i < pred (Rlength l))%nat -> pos_Rl l i <> pos_Rl l (S i)). Definition is_subdivision (f:R -> R) (a b:R) (l:Rlist) : Type := - sigT (fun l0:Rlist => adapted_couple f a b l l0). + { l0:Rlist & adapted_couple f a b l l0 }. Definition IsStepFun (f:R -> R) (a b:R) : Type := - sigT (fun l:Rlist => is_subdivision f a b l). + { l:Rlist & is_subdivision f a b l }. (** ** Class of step functions *) Record StepFun (a b:R) : Type := mkStepFun @@ -1779,13 +1779,12 @@ Lemma StepFun_P38 : ordered_Rlist l -> pos_Rl l 0 = a -> pos_Rl l (pred (Rlength l)) = b -> - sigT - (fun g:StepFun a b => + { g:StepFun a b | g b = f b /\ (forall i:nat, (i < pred (Rlength l))%nat -> constant_D_eq g (co_interval (pos_Rl l i) (pos_Rl l (S i))) - (f (pos_Rl l i)))). + (f (pos_Rl l i))) }. Proof. intros l a b f; generalize a; clear a; induction l. intros a H H0 H1; simpl in H0; simpl in H1; @@ -2206,21 +2205,10 @@ Lemma StepFun_P43 : RiemannInt_SF (mkStepFun pr1) + RiemannInt_SF (mkStepFun pr2) = RiemannInt_SF (mkStepFun pr3). Proof. - intros f; intros; - assert - (H1 : - sigT (fun l:Rlist => sigT (fun l0:Rlist => adapted_couple f a b l l0))). - apply pr1. - assert - (H2 : - sigT (fun l:Rlist => sigT (fun l0:Rlist => adapted_couple f b c l l0))). - apply pr2. - assert - (H3 : - sigT (fun l:Rlist => sigT (fun l0:Rlist => adapted_couple f a c l l0))). - apply pr3. - elim H1; clear H1; intros l1 [lf1 H1]; elim H2; clear H2; intros l2 [lf2 H2]; - elim H3; clear H3; intros l3 [lf3 H3]. + intros f; intros. + pose proof pr1 as (l1,(lf1,H1)). + pose proof pr2 as (l2,(lf2,H2)). + pose proof pr3 as (l3,(lf3,H3)). replace (RiemannInt_SF (mkStepFun pr1)) with match Rle_dec a b with | left _ => Int_SF lf1 l1 @@ -2462,7 +2450,7 @@ Proof. (forall (l1 lf1:Rlist) (a b c:R) (f:R -> R), adapted_couple f a b l1 lf1 -> a <= c <= b -> - sigT (fun l:Rlist => sigT (fun l0:Rlist => adapted_couple f a c l l0))). + { l:Rlist & { l0:Rlist & adapted_couple f a c l l0 } }). intro X; unfold IsStepFun in |- *; unfold is_subdivision in |- *; eapply X. apply H2. split; assumption. @@ -2578,7 +2566,7 @@ Proof. (forall (l1 lf1:Rlist) (a b c:R) (f:R -> R), adapted_couple f a b l1 lf1 -> a <= c <= b -> - sigT (fun l:Rlist => sigT (fun l0:Rlist => adapted_couple f c b l l0))). + { l:Rlist & { l0:Rlist & adapted_couple f c b l l0 } }). intro X; unfold IsStepFun in |- *; unfold is_subdivision in |- *; eapply X; [ apply H2 | split; assumption ]. clear f a b c H0 H H1 H2 l1 lf1; simple induction l1. diff --git a/theories/Reals/Rlimit.v b/theories/Reals/Rlimit.v index 76579ccb..1a2fa03a 100644 --- a/theories/Reals/Rlimit.v +++ b/theories/Reals/Rlimit.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rlimit.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Rlimit.v 10710 2008-03-23 09:24:09Z herbelin $ i*) (*********************************************************) (** Definition of the limit *) @@ -16,7 +16,8 @@ Require Import Rbase. Require Import Rfunctions. Require Import Classical_Prop. -Require Import Fourier. Open Local Scope R_scope. +Require Import Fourier. +Open Local Scope R_scope. (*******************************) (** * Calculus *) @@ -560,9 +561,9 @@ Proof. | apply Rlt_le_trans with (Rmin delta1 delta2); [ assumption | apply Rmin_l ] ]. change (0 < eps * (Rsqr l / 2)) in |- *; unfold Rdiv in |- *; - repeat rewrite Rmult_assoc; repeat apply Rmult_lt_0_compat. + repeat rewrite Rmult_assoc; apply Rmult_lt_0_compat. assumption. - apply Rsqr_pos_lt; assumption. + apply Rmult_lt_0_compat. apply Rsqr_pos_lt; assumption. apply Rinv_0_lt_compat; cut (0%nat <> 2%nat); [ intro H3; generalize (lt_INR_0 2 (neq_O_lt 2 H3)); unfold INR in |- *; intro; assumption diff --git a/theories/Reals/Rlogic.v b/theories/Reals/Rlogic.v new file mode 100644 index 00000000..8aadf8f5 --- /dev/null +++ b/theories/Reals/Rlogic.v @@ -0,0 +1,293 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) + +(** * This module proves some logical properties of the axiomatics of Reals + +1. Decidablity of arithmetical statements from + the axiom that the order of the real numbers is decidable. + +2. Derivability of the archimedean "axiom" +*) + +(** 1- Proof of the decidablity of arithmetical statements from +excluded middle and the axiom that the order of the real numbers is +decidable. *) + +(** Assuming a decidable predicate [P n], A series is constructed whose +[n]th term is 1/2^n if [P n] holds and 0 otherwise. This sum reaches 2 +only if [P n] holds for all [n], otherwise the sum is less than 2. +Comparing the sum to 2 decides if [forall n, P n] or [~forall n, P n] *) + +(** One can iterate this lemma and use classical logic to decide any +statement in the arithmetical hierarchy. *) + +(** Contributed by Cezary Kaliszyk and Russell O'Connor *) + +Require Import ConstructiveEpsilon. +Require Import Rfunctions. +Require Import PartSum. +Require Import SeqSeries. +Require Import RiemannInt. +Require Import Fourier. + +Section Arithmetical_dec. + +Variable P : nat -> Prop. +Hypothesis HP : forall n, {P n} + {~P n}. + +Let ge_fun_sums_ge_lemma : (forall (m n : nat) (f : nat -> R), (lt m n) -> (forall i : nat, 0 <= f i) -> sum_f_R0 f m <= sum_f_R0 f n). +intros m n f mn fpos. +replace (sum_f_R0 f m) with (sum_f_R0 f m + 0) by ring. +rewrite (tech2 f m n mn). +apply Rplus_le_compat_l. + induction (n - S m)%nat; simpl in *. + apply fpos. +replace 0 with (0 + 0) by ring. +apply (Rplus_le_compat _ _ _ _ IHn0 (fpos (S (m + S n0)%nat))). +Qed. + +Let ge_fun_sums_ge : (forall (m n : nat) (f : nat -> R), (le m n) -> (forall i : nat, 0 <= f i) -> sum_f_R0 f m <= sum_f_R0 f n). +intros m n f mn pos. + elim (le_lt_or_eq _ _ mn). + intro; apply ge_fun_sums_ge_lemma; assumption. +intro H; rewrite H; auto with *. +Qed. + +Let f:=fun n => (if HP n then (1/2)^n else 0)%R. + +Lemma cauchy_crit_geometric_dec_fun : Cauchy_crit_series f. +intros e He. +assert (X:(Pser (fun n:nat => 1) (1/2) (/ (1 - (1/2))))%R). + apply GP_infinite. + apply Rabs_def1; fourier. +assert (He':e/2 > 0) by fourier. +destruct (X _ He') as [N HN]. +clear X. +exists N. +intros n m Hn Hm. +replace e with (e/2 + e/2)%R by field. +set (g:=(fun n0 : nat => 1 * (1 / 2) ^ n0)) in *. +assert (R_dist (sum_f_R0 g n) (sum_f_R0 g m) < e / 2 + e / 2). + apply Rle_lt_trans with (R_dist (sum_f_R0 g n) 2+R_dist 2 (sum_f_R0 g m))%R. + apply R_dist_tri. + replace (/(1 - 1/2)) with 2 in HN by field. + cut (forall n, (n >= N)%nat -> R_dist (sum_f_R0 g n) 2 < e/2)%R. + intros Z. + apply Rplus_lt_compat. + apply Z; assumption. + rewrite R_dist_sym. + apply Z; assumption. + clear - HN He. + intros n Hn. + apply HN. + auto. +eapply Rle_lt_trans;[|apply H]. +clear -ge_fun_sums_ge n. +cut (forall n m, (m <= n)%nat -> R_dist (sum_f_R0 f n) (sum_f_R0 f m) <= R_dist (sum_f_R0 g n) (sum_f_R0 g m)). + intros H. + destruct (le_lt_dec m n). + apply H; assumption. + rewrite R_dist_sym. + rewrite (R_dist_sym (sum_f_R0 g n)). + apply H; auto with *. +clear n m. +intros n m Hnm. +unfold R_dist. +cut (forall i : nat, (1 / 2) ^ i >= 0). intro RPosPow. +rewrite Rabs_pos_eq. + rewrite Rabs_pos_eq. + cut (sum_f_R0 g m - sum_f_R0 f m <= sum_f_R0 g n - sum_f_R0 f n). + intros; fourier. + do 2 rewrite <- minus_sum. + apply (ge_fun_sums_ge m n (fun i : nat => g i - f i) Hnm). + intro i. + unfold f, g. + elim (HP i); intro; ring_simplify; auto with *. + cut (sum_f_R0 g m <= sum_f_R0 g n). + intro; fourier. + apply (ge_fun_sums_ge m n g Hnm). + intro. unfold g. + ring_simplify. + apply Rge_le. + apply RPosPow. + cut (sum_f_R0 f m <= sum_f_R0 f n). + intro; fourier. + apply (ge_fun_sums_ge m n f Hnm). + intro; unfold f. + elim (HP i); intro; simpl. + apply Rge_le. + apply RPosPow. + auto with *. +intro i. +apply Rle_ge. +apply pow_le. +fourier. +Qed. + +Lemma forall_dec : {forall n, P n} + {~forall n, P n}. +Proof. +destruct (cv_cauchy_2 _ cauchy_crit_geometric_dec_fun). + cut (2 <= x <-> forall n : nat, P n). + intro H. + elim (Rle_dec 2 x); intro X. + left; tauto. + right; tauto. +assert (A:Rabs(1/2) < 1) by (apply Rabs_def1; fourier). +assert (A0:=(GP_infinite (1/2) A)). +symmetry. + split; intro. + replace 2 with (/ (1 - (1 / 2))) by field. + unfold Pser, infinite_sum in A0. + eapply Rle_cv_lim;[|unfold Un_cv; apply A0 |apply u]. + intros n. + clear -n H. + induction n; unfold f;simpl. + destruct (HP 0); auto with *. + elim n; auto. + apply Rplus_le_compat; auto. + destruct (HP (S n)); auto with *. + elim n0; auto. +intros n. +destruct (HP n); auto. +elim (RIneq.Rle_not_lt _ _ H). +assert (B:0< (1/2)^n). + apply pow_lt. + fourier. +apply Rle_lt_trans with (2-(1/2)^n);[|fourier]. +replace (/(1-1/2))%R with 2 in A0 by field. +set (g:= fun m => if (eq_nat_dec m n) then (1/2)^n else 0). +assert (Z: Un_cv (fun N : nat => sum_f_R0 g N) ((1/2)^n)). + intros e He. + exists n. + intros a Ha. + replace (sum_f_R0 g a) with ((1/2)^n). + rewrite (R_dist_eq); assumption. + symmetry. + cut (forall a : nat, ((a >= n)%nat -> sum_f_R0 g a = (1 / 2) ^ n) /\ ((a < n)%nat -> sum_f_R0 g a = 0))%R. + intros H0. + destruct (H0 a). + auto. + clear - g. + induction a. + split; + intros H; + simpl; unfold g; + destruct (eq_nat_dec 0 n); try reflexivity. + elim f; auto with *. + elimtype False; omega. + destruct IHa as [IHa0 IHa1]. + split; + intros H; + simpl; unfold g at 2; + destruct (eq_nat_dec (S a) n). + rewrite IHa1. + ring. + omega. + ring_simplify. + apply IHa0. + omega. + elimtype False; omega. + ring_simplify. + apply IHa1. + omega. +assert (C:=CV_minus _ _ _ _ A0 Z). +eapply Rle_cv_lim;[|apply u |apply C]. +clear - n0 B. +intros m. +simpl. +induction m. + simpl. + unfold f, g. + destruct (eq_nat_dec 0 n). + destruct (HP 0). + elim n0. + congruence. + clear -n. + induction n; simpl; fourier. + destruct (HP); simpl; fourier. +cut (f (S m) <= 1 * ((1 / 2) ^ (S m)) - g (S m)). + intros L. + eapply Rle_trans. + simpl. + apply Rplus_le_compat. + apply IHm. + apply L. + simpl; fourier. +unfold f, g. +destruct (eq_nat_dec (S m) n). + destruct (HP (S m)). + elim n0. + congruence. + rewrite e. + fourier. +destruct (HP (S m)). + fourier. +ring_simplify. +apply pow_le. +fourier. +Qed. + +Lemma sig_forall_dec : {n | ~P n}+{forall n, P n}. +destruct forall_dec. + right; assumption. +left. +apply constructive_indefinite_description_nat; auto. + clear - HP. + firstorder. +apply Classical_Pred_Type.not_all_ex_not. +assumption. +Qed. + +End Arithmetical_dec. + +(** 2- Derivability of the Archimedean axiom *) + +(* This is a standard proof (it has been taken from PlanetMath). It is +formulated negatively so as to avoid the need for classical +logic. Using a proof of {n | ~P n}+{forall n, P n} (the one above or a +variant of it that does not need classical axioms) , we can in +principle also derive [up] and its [specification] *) + +Theorem not_not_archimedean : + forall r : R, ~ (forall n : nat, (INR n <= r)%R). +intros r H. +set (E := fun r => exists n : nat, r = INR n). +assert (exists x : R, E x) by + (exists 0%R; simpl; red; exists 0%nat; reflexivity). +assert (bound E) by (exists r; intros x (m,H2); rewrite H2; apply H). +destruct (completeness E) as (M,(H3,H4)); try assumption. +set (M' := (M + -1)%R). +assert (H2 : ~ is_upper_bound E M'). + intro H5. + assert (M <= M')%R by (apply H4; exact H5). + apply (Rlt_not_le M M'). + unfold M' in |- *. + pattern M at 2 in |- *. + rewrite <- Rplus_0_l. + pattern (0 + M)%R in |- *. + rewrite Rplus_comm. + rewrite <- (Rplus_opp_r 1). + apply Rplus_lt_compat_l. + rewrite Rplus_comm. + apply Rlt_plus_1. + assumption. +apply H2. +intros N (n,H7). +rewrite H7. +unfold M' in |- *. +assert (H5 : (INR (S n) <= M)%R) by (apply H3; exists (S n); reflexivity). +rewrite S_INR in H5. +assert (H6 : (INR n + 1 + -1 <= M + -1)%R). + apply Rplus_le_compat_r. + assumption. +rewrite Rplus_assoc in H6. +rewrite Rplus_opp_r in H6. +rewrite (Rplus_comm (INR n) 0) in H6. +rewrite Rplus_0_l in H6. +assumption. +Qed. diff --git a/theories/Reals/Rpow_def.v b/theories/Reals/Rpow_def.v index 5bdbb76b..90ea9726 100644 --- a/theories/Reals/Rpow_def.v +++ b/theories/Reals/Rpow_def.v @@ -1,3 +1,13 @@ +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* $Id: Rpow_def.v 10923 2008-05-12 18:25:06Z herbelin $ *) + Require Import Rdefinitions. Fixpoint pow (r:R) (n:nat) {struct n} : R := diff --git a/theories/Reals/Rpower.v b/theories/Reals/Rpower.v index cb6c59d5..adf53ef9 100644 --- a/theories/Reals/Rpower.v +++ b/theories/Reals/Rpower.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rpower.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Rpower.v 10710 2008-03-23 09:24:09Z herbelin $ i*) (*i Due to L.Thery i*) (************************************************************) @@ -22,7 +22,8 @@ Require Import Exp_prop. Require Import Rsqrt_def. Require Import R_sqrt. Require Import MVT. -Require Import Ranalysis4. Open Local Scope R_scope. +Require Import Ranalysis4. +Open Local Scope R_scope. Lemma P_Rmin : forall (P:R -> Prop) (x y:R), P x -> P y -> P (Rmin x y). Proof. @@ -90,7 +91,7 @@ Proof. replace (/ INR (fact n)) with (1 ^ n / INR (fact n)). apply (H2 _ H3). unfold Rdiv in |- *; rewrite pow1; rewrite Rmult_1_l; reflexivity. - unfold infinit_sum in e; unfold Un_cv, tg_alt in |- *; intros; elim (e _ H0); + unfold infinite_sum in e; unfold Un_cv, tg_alt in |- *; intros; elim (e _ H0); intros; exists x0; intros; replace (sum_f_R0 (fun i:nat => (-1) ^ i * / INR (fact i)) n) with (sum_f_R0 (fun i:nat => / INR (fact i) * (-1) ^ i) n). @@ -150,62 +151,59 @@ Proof. symmetry in |- *; apply derive_pt_eq_0; apply derivable_pt_lim_exp. Qed. -Lemma ln_exists1 : forall y:R, 0 < y -> 1 <= y -> sigT (fun z:R => y = exp z). +Lemma ln_exists1 : forall y:R, 1 <= y -> { z:R | y = exp z }. Proof. - intros; set (f := fun x:R => exp x - y); cut (f 0 <= 0). - intro; cut (continuity f). - intro; cut (0 <= f y). - intro; cut (f 0 * f y <= 0). - intro; assert (X := IVT_cor f 0 y H2 (Rlt_le _ _ H) H4); elim X; intros t H5; - apply existT with t; elim H5; intros; unfold f in H7; - apply Rminus_diag_uniq_sym; exact H7. + intros; set (f := fun x:R => exp x - y). + assert (H0 : 0 < y) by (apply Rlt_le_trans with 1; auto with real). + cut (f 0 <= 0); [intro H1|]. + cut (continuity f); [intro H2|]. + cut (0 <= f y); [intro H3|]. + cut (f 0 * f y <= 0); [intro H4|]. + pose proof (IVT_cor f 0 y H2 (Rlt_le _ _ H0) H4) as (t,(_,H7)); + exists t; unfold f in H7; apply Rminus_diag_uniq_sym; exact H7. pattern 0 at 2 in |- *; rewrite <- (Rmult_0_r (f y)); rewrite (Rmult_comm (f 0)); apply Rmult_le_compat_l; assumption. unfold f in |- *; apply Rplus_le_reg_l with y; left; apply Rlt_trans with (1 + y). rewrite <- (Rplus_comm y); apply Rplus_lt_compat_l; apply Rlt_0_1. - replace (y + (exp y - y)) with (exp y); [ apply (exp_ineq1 y H) | ring ]. + replace (y + (exp y - y)) with (exp y); [ apply (exp_ineq1 y H0) | ring ]. unfold f in |- *; change (continuity (exp - fct_cte y)) in |- *; apply continuity_minus; [ apply derivable_continuous; apply derivable_exp | apply derivable_continuous; apply derivable_const ]. unfold f in |- *; rewrite exp_0; apply Rplus_le_reg_l with y; - rewrite Rplus_0_r; replace (y + (1 - y)) with 1; [ apply H0 | ring ]. + rewrite Rplus_0_r; replace (y + (1 - y)) with 1; [ apply H | ring ]. Qed. (**********) -Lemma ln_exists : forall y:R, 0 < y -> sigT (fun z:R => y = exp z). +Lemma ln_exists : forall y:R, 0 < y -> { z:R | y = exp z }. Proof. intros; case (Rle_dec 1 y); intro. - apply (ln_exists1 _ H r). + apply (ln_exists1 _ r). assert (H0 : 1 <= / y). apply Rmult_le_reg_l with y. apply H. rewrite <- Rinv_r_sym. rewrite Rmult_1_r; left; apply (Rnot_le_lt _ _ n). red in |- *; intro; rewrite H0 in H; elim (Rlt_irrefl _ H). - assert (H1 : 0 < / y). - apply Rinv_0_lt_compat; apply H. - assert (H2 := ln_exists1 _ H1 H0); elim H2; intros; apply existT with (- x); + destruct (ln_exists1 _ H0) as (x,p); exists (- x); apply Rmult_eq_reg_l with (exp x / y). unfold Rdiv in |- *; rewrite Rmult_assoc; rewrite <- Rinv_l_sym. rewrite Rmult_1_r; rewrite <- (Rmult_comm (/ y)); rewrite Rmult_assoc; rewrite <- exp_plus; rewrite Rplus_opp_r; rewrite exp_0; rewrite Rmult_1_r; symmetry in |- *; apply p. - red in |- *; intro; rewrite H3 in H; elim (Rlt_irrefl _ H). + red in |- *; intro H3; rewrite H3 in H; elim (Rlt_irrefl _ H). unfold Rdiv in |- *; apply prod_neq_R0. - assert (H3 := exp_pos x); red in |- *; intro; rewrite H4 in H3; + assert (H3 := exp_pos x); red in |- *; intro H4; rewrite H4 in H3; elim (Rlt_irrefl _ H3). - apply Rinv_neq_0_compat; red in |- *; intro; rewrite H3 in H; + apply Rinv_neq_0_compat; red in |- *; intro H3; rewrite H3 in H; elim (Rlt_irrefl _ H). Qed. (* Definition of log R+* -> R *) Definition Rln (y:posreal) : R := - match ln_exists (pos y) (cond_pos y) with - | existT a b => a - end. + let (a,_) := ln_exists (pos y) (cond_pos y) in a. (* Extension on R *) Definition ln (x:R) : R := @@ -403,6 +401,16 @@ Infix Local "^R" := Rpower (at level 30, right associativity) : R_scope. (** * Properties of Rpower *) (******************************************************************) +(** Note: [Rpower] is prolongated to [1] on negative real numbers and + it thus does not extend integer power. The next two lemmas, which + hold for integer power, accidentally hold on negative real numbers + as a side effect of the default value taken on negative real + numbers. Contrastingly, the lemmas that do not hold for the + integer power of a negative number are stated for [Rpower] on the + positive numbers only (even if they accidentally hold due to the + default value of [Rpower] on the negative side, as it is the case + for [Rpower_O]). *) + Theorem Rpower_plus : forall x y z:R, z ^R (x + y) = z ^R x * z ^R y. Proof. intros x y z; unfold Rpower in |- *. @@ -420,7 +428,7 @@ Qed. Theorem Rpower_O : forall x:R, 0 < x -> x ^R 0 = 1. Proof. - intros x H; unfold Rpower in |- *. + intros x _; unfold Rpower in |- *. rewrite Rmult_0_l; apply exp_0. Qed. diff --git a/theories/Reals/Rprod.v b/theories/Reals/Rprod.v index a84d5149..2113cc8f 100644 --- a/theories/Reals/Rprod.v +++ b/theories/Reals/Rprod.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rprod.v 9298 2006-10-27 13:05:29Z notin $ i*) +(*i $Id: Rprod.v 10146 2007-09-27 12:28:12Z herbelin $ i*) Require Import Compare. Require Import Rbase. @@ -16,41 +16,42 @@ Require Import PartSum. Require Import Binomial. Open Local Scope R_scope. -(** TT Ak; 1<=k<=N *) -Boxed Fixpoint prod_f_SO (An:nat -> R) (N:nat) {struct N} : R := +(** TT Ak; 0<=k<=N *) +Boxed Fixpoint prod_f_R0 (f:nat -> R) (N:nat) {struct N} : R := match N with - | O => 1 - | S p => prod_f_SO An p * An (S p) + | O => f O + | S p => prod_f_R0 f p * f (S p) end. +Notation prod_f_SO := (fun An N => prod_f_R0 (fun n => An (S n)) N). + (**********) Lemma prod_SO_split : forall (An:nat -> R) (n k:nat), - (k <= n)%nat -> - prod_f_SO An n = - prod_f_SO An k * prod_f_SO (fun l:nat => An (k + l)%nat) (n - k). + (k < n)%nat -> + prod_f_R0 An n = + prod_f_R0 An k * prod_f_R0 (fun l:nat => An (k +1+l)%nat) (n - k -1). Proof. intros; induction n as [| n Hrecn]. - cut (k = 0%nat); - [ intro; rewrite H0; simpl in |- *; ring | inversion H; reflexivity ]. - cut (k = S n \/ (k <= n)%nat). - intro; elim H0; intro. - rewrite H1; simpl in |- *; rewrite <- minus_n_n; simpl in |- *; ring. - replace (S n - k)%nat with (S (n - k)). + absurd (k < 0)%nat; omega. + cut (k = n \/ (k < n)%nat);[intro; elim H0; intro|omega]. + replace (S n - k - 1)%nat with O; [rewrite H1; simpl|omega]. + replace (n+1+0)%nat with (S n); ring. + replace (S n - k-1)%nat with (S (n - k-1));[idtac|omega]. simpl in |- *; replace (k + S (n - k))%nat with (S n). + replace (k + 1 + S (n - k - 1))%nat with (S n). rewrite Hrecn; [ ring | assumption ]. omega. omega. - omega. -Qed. +Qed. (**********) Lemma prod_SO_pos : forall (An:nat -> R) (N:nat), - (forall n:nat, (n <= N)%nat -> 0 <= An n) -> 0 <= prod_f_SO An N. + (forall n:nat, (n <= N)%nat -> 0 <= An n) -> 0 <= prod_f_R0 An N. Proof. intros; induction N as [| N HrecN]. - simpl in |- *; left; apply Rlt_0_1. + simpl in |- *; apply H; trivial. simpl in |- *; apply Rmult_le_pos. apply HrecN; intros; apply H; apply le_trans with N; [ assumption | apply le_n_Sn ]. @@ -61,11 +62,11 @@ Qed. Lemma prod_SO_Rle : forall (An Bn:nat -> R) (N:nat), (forall n:nat, (n <= N)%nat -> 0 <= An n <= Bn n) -> - prod_f_SO An N <= prod_f_SO Bn N. + prod_f_R0 An N <= prod_f_R0 Bn N. Proof. intros; induction N as [| N HrecN]. - right; reflexivity. - simpl in |- *; apply Rle_trans with (prod_f_SO An N * Bn (S N)). + elim H with O; trivial. + simpl in |- *; apply Rle_trans with (prod_f_R0 An N * Bn (S N)). apply Rmult_le_compat_l. apply prod_SO_pos; intros; elim (H n (le_trans _ _ _ H0 (le_n_Sn N))); intros; assumption. @@ -79,12 +80,17 @@ Qed. (** Application to factorial *) Lemma fact_prodSO : - forall n:nat, INR (fact n) = prod_f_SO (fun k:nat => INR k) n. + forall n:nat, INR (fact n) = prod_f_R0 (fun k:nat => + (match (eq_nat_dec k 0) with + | left _ => 1%R + | right _ => INR k + end)) n. Proof. intro; induction n as [| n Hrecn]. reflexivity. - change (INR (S n * fact n) = prod_f_SO (fun k:nat => INR k) (S n)) in |- *. - rewrite mult_INR; rewrite Rmult_comm; rewrite Hrecn; reflexivity. + simpl; rewrite <- Hrecn. + case n; auto with real. + intros; repeat rewrite plus_INR;rewrite mult_INR;ring. Qed. Lemma le_n_2n : forall n:nat, (n <= 2 * n)%nat. @@ -104,40 +110,58 @@ Lemma RfactN_fact2N_factk : (k <= 2 * N)%nat -> Rsqr (INR (fact N)) <= INR (fact (2 * N - k)) * INR (fact k). Proof. + assert (forall (n:nat), 0 <= (if eq_nat_dec n 0 then 1 else INR n)). + intros; case (eq_nat_dec n 0); auto with real. + assert (forall (n:nat), (0 < n)%nat -> + (if eq_nat_dec n 0 then 1 else INR n) = INR n). + intros n; case (eq_nat_dec n 0); auto with real. + intros; absurd (0 < n)%nat; omega. intros; unfold Rsqr in |- *; repeat rewrite fact_prodSO. - cut ((k <= N)%nat \/ (N <= k)%nat). - intro; elim H0; intro. - rewrite (prod_SO_split (fun l:nat => INR l) (2 * N - k) N). + cut ((k=N)%nat \/ (k < N)%nat \/ (N < k)%nat). + intro H2; elim H2; intro H3. + rewrite H3; replace (2*N-N)%nat with N;[right; ring|omega]. + case H3; intro; clear H2 H3. + rewrite (prod_SO_split (fun l:nat => if eq_nat_dec l 0 then 1 else INR l) (2 * N - k) N). rewrite Rmult_assoc; apply Rmult_le_compat_l. - apply prod_SO_pos; intros; apply pos_INR. - replace (2 * N - k - N)%nat with (N - k)%nat. - rewrite Rmult_comm; rewrite (prod_SO_split (fun l:nat => INR l) N k). + apply prod_SO_pos; intros; auto. + replace (2 * N - k - N-1)%nat with (N - k-1)%nat. + rewrite Rmult_comm; rewrite (prod_SO_split + (fun l:nat => if eq_nat_dec l 0 then 1 else INR l) N k). apply Rmult_le_compat_l. - apply prod_SO_pos; intros; apply pos_INR. - apply prod_SO_Rle; intros; split. - apply pos_INR. - apply le_INR; apply plus_le_compat_r; assumption. + apply prod_SO_pos; intros; auto. + apply prod_SO_Rle; intros; split; auto. + rewrite H0. + rewrite H0. + apply le_INR; omega. + omega. + omega. assumption. omega. omega. - rewrite <- (Rmult_comm (prod_f_SO (fun l:nat => INR l) k)); - rewrite (prod_SO_split (fun l:nat => INR l) k N). + rewrite <- (Rmult_comm (prod_f_R0 (fun l:nat => + if eq_nat_dec l 0 then 1 else INR l) k)); + rewrite (prod_SO_split (fun l:nat => + if eq_nat_dec l 0 then 1 else INR l) k N). rewrite Rmult_assoc; apply Rmult_le_compat_l. - apply prod_SO_pos; intros; apply pos_INR. + apply prod_SO_pos; intros; auto. rewrite Rmult_comm; - rewrite (prod_SO_split (fun l:nat => INR l) N (2 * N - k)). + rewrite (prod_SO_split (fun l:nat => + if eq_nat_dec l 0 then 1 else INR l) N (2 * N - k)). apply Rmult_le_compat_l. - apply prod_SO_pos; intros; apply pos_INR. - replace (N - (2 * N - k))%nat with (k - N)%nat. - apply prod_SO_Rle; intros; split. - apply pos_INR. - apply le_INR; apply plus_le_compat_r. + apply prod_SO_pos; intros; auto. + replace (N - (2 * N - k)-1)%nat with (k - N-1)%nat. + apply prod_SO_Rle; intros; split; auto. + rewrite H0. + rewrite H0. + apply le_INR; omega. + omega. omega. omega. omega. assumption. omega. -Qed. +Qed. + (**********) Lemma INR_fact_lt_0 : forall n:nat, 0 < INR (fact n). diff --git a/theories/Reals/Rseries.v b/theories/Reals/Rseries.v index 38c39bae..702aafa4 100644 --- a/theories/Reals/Rseries.v +++ b/theories/Reals/Rseries.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rseries.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Rseries.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -194,14 +194,14 @@ Section Isequence. Variable An : nat -> R. (*********) - Definition Pser (x l:R) : Prop := infinit_sum (fun n:nat => An n * x ^ n) l. + Definition Pser (x l:R) : Prop := infinite_sum (fun n:nat => An n * x ^ n) l. End Isequence. Lemma GP_infinite : forall x:R, Rabs x < 1 -> Pser (fun n:nat => 1) x (/ (1 - x)). Proof. - intros; unfold Pser in |- *; unfold infinit_sum in |- *; intros; + intros; unfold Pser in |- *; unfold infinite_sum in |- *; intros; elim (Req_dec x 0). intros; exists 0%nat; intros; rewrite H1; rewrite Rminus_0_r; rewrite Rinv_1; cut (sum_f_R0 (fun n0:nat => 1 * 0 ^ n0) n = 1). diff --git a/theories/Reals/Rsigma.v b/theories/Reals/Rsigma.v index cb31d3b2..7cdd4d02 100644 --- a/theories/Reals/Rsigma.v +++ b/theories/Reals/Rsigma.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rsigma.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: Rsigma.v 9454 2006-12-15 15:30:59Z bgregoir $ i*) Require Import Rbase. Require Import Rfunctions. diff --git a/theories/Reals/Rsqrt_def.v b/theories/Reals/Rsqrt_def.v index 0a9f7754..0a3af6ca 100644 --- a/theories/Reals/Rsqrt_def.v +++ b/theories/Reals/Rsqrt_def.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rsqrt_def.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: Rsqrt_def.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Sumbool. Require Import Rbase. @@ -192,7 +192,7 @@ Qed. Lemma dicho_lb_cv : forall (x y:R) (P:R -> bool), - x <= y -> sigT (fun l:R => Un_cv (dicho_lb x y P) l). + x <= y -> { l:R | Un_cv (dicho_lb x y P) l }. Proof. intros. apply growing_cv. @@ -202,7 +202,7 @@ Qed. Lemma dicho_up_cv : forall (x y:R) (P:R -> bool), - x <= y -> sigT (fun l:R => Un_cv (dicho_up x y P) l). + x <= y -> { l:R | Un_cv (dicho_up x y P) l }. Proof. intros. apply decreasing_cv. @@ -466,7 +466,7 @@ Qed. Lemma IVT : forall (f:R -> R) (x y:R), continuity f -> - x < y -> f x < 0 -> 0 < f y -> sigT (fun z:R => x <= z <= y /\ f z = 0). + x < y -> f x < 0 -> 0 < f y -> { z:R | x <= z <= y /\ f z = 0 }. Proof. intros. cut (x <= y). @@ -478,7 +478,7 @@ Proof. elim X0; intros. assert (H4 := cv_dicho _ _ _ _ _ H3 p0 p). rewrite H4 in p0. - apply existT with x0. + exists x0. split. split. apply Rle_trans with (dicho_lb x y (fun z:R => cond_positivity (f z)) 0). @@ -602,7 +602,7 @@ Qed. Lemma IVT_cor : forall (f:R -> R) (x y:R), continuity f -> - x <= y -> f x * f y <= 0 -> sigT (fun z:R => x <= z <= y /\ f z = 0). + x <= y -> f x * f y <= 0 -> { z:R | x <= z <= y /\ f z = 0 }. Proof. intros. case (total_order_T 0 (f x)); intro. @@ -628,7 +628,7 @@ Proof. cut (0 < (- f)%F y). intros. elim (H3 H5 H4); intros. - apply existT with x0. + exists x0. elim p; intros. split. assumption. @@ -643,7 +643,7 @@ Proof. assumption. rewrite H2 in a. elim (Rlt_irrefl _ (Rlt_trans _ _ _ r a)). - apply existT with x. + exists x. split. split; [ right; reflexivity | assumption ]. symmetry in |- *; assumption. @@ -656,7 +656,7 @@ Proof. assumption. rewrite H2 in r. elim (Rlt_irrefl _ (Rlt_trans _ _ _ r a)). - apply existT with y. + exists y. split. split; [ assumption | right; reflexivity ]. symmetry in |- *; assumption. @@ -670,7 +670,7 @@ Qed. (** We can now define the square root function as the reciprocal transformation of the square root function *) Lemma Rsqrt_exists : - forall y:R, 0 <= y -> sigT (fun z:R => 0 <= z /\ y = Rsqr z). + forall y:R, 0 <= y -> { z:R | 0 <= z /\ y = Rsqr z }. Proof. intros. set (f := fun x:R => Rsqr x - y). @@ -686,7 +686,7 @@ Proof. intro. assert (X := IVT_cor f 0 1 H1 (Rlt_le _ _ Rlt_0_1) H3). elim X; intros t H4. - apply existT with t. + exists t. elim H4; intros. split. elim H5; intros; assumption. @@ -700,7 +700,7 @@ Proof. rewrite Rplus_0_r; rewrite Rplus_comm; unfold Rminus in |- *; rewrite Rplus_assoc; rewrite Rplus_opp_l; rewrite Rplus_0_r; left; assumption. - apply existT with 1. + exists 1. split. left; apply Rlt_0_1. rewrite b; symmetry in |- *; apply Rsqr_1. @@ -710,7 +710,7 @@ Proof. intro. assert (X := IVT_cor f 0 y H1 H H3). elim X; intros t H4. - apply existT with t. + exists t. elim H4; intros. split. elim H5; intros; assumption. @@ -739,9 +739,7 @@ Qed. (* Definition of the square root: R+->R *) Definition Rsqrt (y:nonnegreal) : R := - match Rsqrt_exists (nonneg y) (cond_nonneg y) with - | existT a b => a - end. + let (a,_) := Rsqrt_exists (nonneg y) (cond_nonneg y) in a. (**********) Lemma Rsqrt_positivity : forall x:nonnegreal, 0 <= Rsqrt x. diff --git a/theories/Reals/Rtopology.v b/theories/Reals/Rtopology.v index aa47d72f..9501bc1e 100644 --- a/theories/Reals/Rtopology.v +++ b/theories/Reals/Rtopology.v @@ -6,15 +6,15 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rtopology.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Rtopology.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. Require Import Ranalysis1. Require Import RList. Require Import Classical_Prop. -Require Import Classical_Pred_Type. Open Local Scope R_scope. - +Require Import Classical_Pred_Type. +Open Local Scope R_scope. (** * General definitions and propositions *) diff --git a/theories/Reals/Rtrigo.v b/theories/Reals/Rtrigo.v index b744c788..0baece39 100644 --- a/theories/Reals/Rtrigo.v +++ b/theories/Reals/Rtrigo.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rtrigo.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: Rtrigo.v 9454 2006-12-15 15:30:59Z bgregoir $ i*) Require Import Rbase. Require Import Rfunctions. diff --git a/theories/Reals/Rtrigo_alt.v b/theories/Reals/Rtrigo_alt.v index 89ee1745..d82bafc6 100644 --- a/theories/Reals/Rtrigo_alt.v +++ b/theories/Reals/Rtrigo_alt.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rtrigo_alt.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: Rtrigo_alt.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -137,7 +137,7 @@ Proof. ring. assert (X := exist_sin (Rsqr a)); elim X; intros. cut (x = sin a / a). - intro; rewrite H3 in p; unfold sin_in in p; unfold infinit_sum in p; + intro; rewrite H3 in p; unfold sin_in in p; unfold infinite_sum in p; unfold R_dist in p; unfold Un_cv in |- *; unfold R_dist in |- *; intros. cut (0 < eps / Rabs a). @@ -327,7 +327,7 @@ Proof. apply (fun m n p:nat => mult_le_compat_l p n m); apply le_n_S; assumption. assert (X := exist_cos (Rsqr a0)); elim X; intros. cut (x = cos a0). - intro; rewrite H4 in p; unfold cos_in in p; unfold infinit_sum in p; + intro; rewrite H4 in p; unfold cos_in in p; unfold infinite_sum in p; unfold R_dist in p; unfold Un_cv in |- *; unfold R_dist in |- *; intros. elim (p _ H5); intros N H6. diff --git a/theories/Reals/Rtrigo_def.v b/theories/Reals/Rtrigo_def.v index b2aeb766..e94d7448 100644 --- a/theories/Reals/Rtrigo_def.v +++ b/theories/Reals/Rtrigo_def.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rtrigo_def.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Rtrigo_def.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -19,7 +19,7 @@ Open Local Scope R_scope. (** * Definition of exponential *) (********************************) Definition exp_in (x l:R) : Prop := - infinit_sum (fun i:nat => / INR (fact i) * x ^ i) l. + infinite_sum (fun i:nat => / INR (fact i) * x ^ i) l. Lemma exp_cof_no_R0 : forall n:nat, / INR (fact n) <> 0. Proof. @@ -28,7 +28,7 @@ Proof. apply INR_fact_neq_0. Qed. -Lemma exist_exp : forall x:R, sigT (fun l:R => exp_in x l). +Lemma exist_exp : forall x:R, { l:R | exp_in x l }. Proof. intro; generalize @@ -37,7 +37,7 @@ Proof. trivial. Defined. -Definition exp (x:R) : R := projT1 (exist_exp x). +Definition exp (x:R) : R := proj1_sig (exist_exp x). Lemma pow_i : forall i:nat, (0 < i)%nat -> 0 ^ i = 0. Proof. @@ -45,11 +45,10 @@ Proof. red in |- *; intro; rewrite H0 in H; elim (lt_irrefl _ H). Qed. -(*i Calculus of $e^0$ *) -Lemma exist_exp0 : sigT (fun l:R => exp_in 0 l). +Lemma exist_exp0 : { l:R | exp_in 0 l }. Proof. - apply existT with 1. - unfold exp_in in |- *; unfold infinit_sum in |- *; intros. + exists 1. + unfold exp_in in |- *; unfold infinite_sum in |- *; intros. exists 0%nat. intros; replace (sum_f_R0 (fun i:nat => / INR (fact i) * 0 ^ i) n) with 1. unfold R_dist in |- *; replace (1 - 1) with 0; @@ -63,6 +62,7 @@ Proof. unfold ge in |- *; apply le_O_n. Defined. +(* Value of [exp 0] *) Lemma exp_0 : exp 0 = 1. Proof. cut (exp_in 0 (exp 0)). @@ -70,8 +70,8 @@ Proof. unfold exp_in in |- *; intros; eapply uniqueness_sum. apply H0. apply H. - exact (projT2 exist_exp0). - exact (projT2 (exist_exp 0)). + exact (proj2_sig exist_exp0). + exact (proj2_sig (exist_exp 0)). Qed. (*****************************************) @@ -235,21 +235,17 @@ Qed. (**********) Definition cos_in (x l:R) : Prop := - infinit_sum (fun i:nat => cos_n i * x ^ i) l. + infinite_sum (fun i:nat => cos_n i * x ^ i) l. (**********) -Lemma exist_cos : forall x:R, sigT (fun l:R => cos_in x l). +Lemma exist_cos : forall x:R, { l:R | cos_in x l }. intro; generalize (Alembert_C3 cos_n x cosn_no_R0 Alembert_cos). unfold Pser, cos_in in |- *; trivial. Qed. (** Definition of cosinus *) -Definition cos (x:R) : R := - match exist_cos (Rsqr x) with - | existT a b => a - end. - +Definition cos (x:R) : R := let (a,_) := exist_cos (Rsqr x) in a. Definition sin_n (n:nat) : R := (-1) ^ n / INR (fact (2 * n + 1)). @@ -348,7 +344,7 @@ Proof. apply INR_eq; repeat rewrite S_INR; rewrite plus_INR; repeat rewrite mult_INR; rewrite plus_INR; rewrite mult_INR; repeat rewrite S_INR; replace (INR 0) with 0; [ ring | reflexivity ]. -Qed. +Defined. Lemma sin_no_R0 : forall n:nat, sin_n n <> 0. Proof. @@ -359,21 +355,18 @@ Qed. (**********) Definition sin_in (x l:R) : Prop := - infinit_sum (fun i:nat => sin_n i * x ^ i) l. + infinite_sum (fun i:nat => sin_n i * x ^ i) l. (**********) -Lemma exist_sin : forall x:R, sigT (fun l:R => sin_in x l). +Lemma exist_sin : forall x:R, { l:R | sin_in x l }. Proof. intro; generalize (Alembert_C3 sin_n x sin_no_R0 Alembert_sin). unfold Pser, sin_n in |- *; trivial. -Qed. +Defined. (***********************) (* Definition of sinus *) -Definition sin (x:R) : R := - match exist_sin (Rsqr x) with - | existT a b => x * a - end. +Definition sin (x:R) : R := let (a,_) := exist_sin (Rsqr x) in x * a. (*********************************************) (** * Properties *) @@ -399,10 +392,10 @@ Proof. intros; ring. Qed. -Lemma exist_cos0 : sigT (fun l:R => cos_in 0 l). +Lemma exist_cos0 : { l:R | cos_in 0 l }. Proof. - apply existT with 1. - unfold cos_in in |- *; unfold infinit_sum in |- *; intros; exists 0%nat. + exists 1. + unfold cos_in in |- *; unfold infinite_sum in |- *; intros; exists 0%nat. intros. unfold R_dist in |- *. induction n as [| n Hrecn]. @@ -417,7 +410,7 @@ Proof. simpl in |- *; ring. Defined. -(* Calculus of (cos 0) *) +(* Value of [cos 0] *) Lemma cos_0 : cos 0 = 1. Proof. cut (cos_in 0 (cos 0)). @@ -425,7 +418,7 @@ Proof. unfold cos_in in |- *; intros; eapply uniqueness_sum. apply H0. apply H. - exact (projT2 exist_cos0). - assert (H := projT2 (exist_cos (Rsqr 0))); unfold cos in |- *; + exact (proj2_sig exist_cos0). + assert (H := proj2_sig (exist_cos (Rsqr 0))); unfold cos in |- *; pattern 0 at 1 in |- *; replace 0 with (Rsqr 0); [ exact H | apply Rsqr_0 ]. Qed. diff --git a/theories/Reals/Rtrigo_fun.v b/theories/Reals/Rtrigo_fun.v index 78ef847f..6eec0329 100644 --- a/theories/Reals/Rtrigo_fun.v +++ b/theories/Reals/Rtrigo_fun.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rtrigo_fun.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Rtrigo_fun.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -15,8 +15,7 @@ Open Local Scope R_scope. (*****************************************************************) (** To define transcendental functions *) -(** for exponential function *) -(* *) +(** and exponential function *) (*****************************************************************) (*********) diff --git a/theories/Reals/Rtrigo_reg.v b/theories/Reals/Rtrigo_reg.v index b105ca69..139563bf 100644 --- a/theories/Reals/Rtrigo_reg.v +++ b/theories/Reals/Rtrigo_reg.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rtrigo_reg.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: Rtrigo_reg.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -25,16 +25,15 @@ Proof. unfold CVN_R in |- *; intros. cut ((r:R) <> 0). intro hyp_r; unfold CVN_r in |- *. - apply existT with (fun n:nat => / INR (fact (2 * n)) * r ^ (2 * n)). + exists (fun n:nat => / INR (fact (2 * n)) * r ^ (2 * n)). cut - (sigT - (fun l:R => + { l:R | Un_cv (fun n:nat => sum_f_R0 (fun k:nat => Rabs (/ INR (fact (2 * k)) * r ^ (2 * k))) - n) l)). + n) l }. intro X; elim X; intros. - apply existT with x. + exists x. split. apply p. intros; rewrite H; unfold Rdiv in |- *; do 2 rewrite Rabs_mult. @@ -124,7 +123,7 @@ Lemma continuity_cos : continuity cos. Proof. set (fn := fun (N:nat) (x:R) => (-1) ^ N / INR (fact (2 * N)) * x ^ (2 * N)). cut (CVN_R fn). - intro; cut (forall x:R, sigT (fun l:R => Un_cv (fun N:nat => SP fn N x) l)). + intro; cut (forall x:R, { l:R | Un_cv (fun N:nat => SP fn N x) l }). intro cv; cut (forall n:nat, continuity (fn n)). intro; cut (forall x:R, cos x = SFL fn cv x). intro; cut (continuity (SFL fn cv) -> continuity cos). @@ -144,7 +143,7 @@ Proof. case (cv x); case (exist_cos (Rsqr x)); intros. symmetry in |- *; eapply UL_sequence. apply u. - unfold cos_in in c; unfold infinit_sum in c; unfold Un_cv in |- *; intros. + unfold cos_in in c; unfold infinite_sum in c; unfold Un_cv in |- *; intros. elim (c _ H0); intros N0 H1. exists N0; intros. unfold R_dist in H1; unfold R_dist, SP in |- *. @@ -200,17 +199,16 @@ Lemma CVN_R_sin : CVN_R fn. Proof. unfold CVN_R in |- *; unfold CVN_r in |- *; intros fn H r. - apply existT with (fun n:nat => / INR (fact (2 * n + 1)) * r ^ (2 * n)). + exists (fun n:nat => / INR (fact (2 * n + 1)) * r ^ (2 * n)). cut - (sigT - (fun l:R => + { l:R | Un_cv (fun n:nat => sum_f_R0 (fun k:nat => Rabs (/ INR (fact (2 * k + 1)) * r ^ (2 * k))) n) - l)). + l }. intro X; elim X; intros. - apply existT with x. + exists x. split. apply p. intros; rewrite H; unfold Rdiv in |- *; do 2 rewrite Rabs_mult; @@ -305,7 +303,7 @@ Proof. set (fn := fun (N:nat) (x:R) => (-1) ^ N / INR (fact (2 * N + 1)) * x ^ (2 * N)). cut (CVN_R fn). - intro; cut (forall x:R, sigT (fun l:R => Un_cv (fun N:nat => SP fn N x) l)). + intro; cut (forall x:R, { l:R | Un_cv (fun N:nat => SP fn N x) l }). intro cv. set (r := mkposreal _ Rlt_0_1). cut (CVN_r fn r). @@ -331,7 +329,7 @@ Proof. unfold Rdiv in |- *; rewrite (Rinv_r_simpl_m h x0 H6). eapply UL_sequence. apply u. - unfold sin_in in s; unfold sin_n, infinit_sum in s; + unfold sin_in in s; unfold sin_n, infinite_sum in s; unfold SP, fn, Un_cv in |- *; intros. elim (s _ H10); intros N0 H11. exists N0; intros. @@ -584,14 +582,14 @@ Qed. Lemma derivable_pt_sin : forall x:R, derivable_pt sin x. Proof. unfold derivable_pt in |- *; intro. - apply existT with (cos x). + exists (cos x). apply derivable_pt_lim_sin. Qed. Lemma derivable_pt_cos : forall x:R, derivable_pt cos x. Proof. unfold derivable_pt in |- *; intro. - apply existT with (- sin x). + exists (- sin x). apply derivable_pt_lim_cos. Qed. diff --git a/theories/Reals/SeqProp.v b/theories/Reals/SeqProp.v index 96351618..56088a2e 100644 --- a/theories/Reals/SeqProp.v +++ b/theories/Reals/SeqProp.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: SeqProp.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: SeqProp.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -15,6 +15,10 @@ Require Import Classical. Require Import Max. Open Local Scope R_scope. +(*****************************************************************) +(** Convergence properties of sequences *) +(*****************************************************************) + Definition Un_decreasing (Un:nat -> R) : Prop := forall n:nat, Un (S n) <= Un n. Definition opp_seq (Un:nat -> R) (n:nat) : R := - Un n. @@ -23,8 +27,7 @@ Definition has_lb (Un:nat -> R) : Prop := bound (EUn (opp_seq Un)). (**********) Lemma growing_cv : - forall Un:nat -> R, - Un_growing Un -> has_ub Un -> sigT (fun l:R => Un_cv Un l). + forall Un:nat -> R, Un_growing Un -> has_ub Un -> { l:R | Un_cv Un l }. Proof. unfold Un_growing, Un_cv in |- *; intros; destruct (completeness (EUn Un) H0 (EUn_noempty Un)) as [x [H2 H3]]. @@ -64,11 +67,10 @@ Proof. Qed. Lemma decreasing_cv : - forall Un:nat -> R, - Un_decreasing Un -> has_lb Un -> sigT (fun l:R => Un_cv Un l). + forall Un:nat -> R, Un_decreasing Un -> has_lb Un -> { l:R | Un_cv Un l }. Proof. intros. - cut (sigT (fun l:R => Un_cv (opp_seq Un) l) -> sigT (fun l:R => Un_cv Un l)). + cut ({ l:R | Un_cv (opp_seq Un) l } -> { l:R | Un_cv Un l }). intro X. apply X. apply growing_cv. @@ -76,7 +78,7 @@ Proof. exact H0. intro X. elim X; intros. - apply existT with (- x). + exists (- x). unfold Un_cv in p. unfold R_dist in p. unfold opp_seq in p. @@ -91,8 +93,8 @@ Proof. Qed. (***********) -Lemma maj_sup : - forall Un:nat -> R, has_ub Un -> sigT (fun l:R => is_lub (EUn Un) l). +Lemma ub_to_lub : + forall Un:nat -> R, has_ub Un -> { l:R | is_lub (EUn Un) l }. Proof. intros. unfold has_ub in H. @@ -104,9 +106,8 @@ Proof. Qed. (**********) -Lemma min_inf : - forall Un:nat -> R, - has_lb Un -> sigT (fun l:R => is_lub (EUn (opp_seq Un)) l). +Lemma lb_to_glb : + forall Un:nat -> R, has_lb Un -> { l:R | is_lub (EUn (opp_seq Un)) l }. Proof. intros; unfold has_lb in H. apply completeness. @@ -116,15 +117,17 @@ Proof. reflexivity. Qed. -Definition majorant (Un:nat -> R) (pr:has_ub Un) : R := - match maj_sup Un pr with - | existT a b => a - end. +Definition lub (Un:nat -> R) (pr:has_ub Un) : R := + let (a,_) := ub_to_lub Un pr in a. -Definition minorant (Un:nat -> R) (pr:has_lb Un) : R := - match min_inf Un pr with - | existT a b => - a - end. +Definition glb (Un:nat -> R) (pr:has_lb Un) : R := + let (a,_) := lb_to_glb Un pr in - a. + +(* Compatibility with previous unappropriate terminology *) +Notation maj_sup := ub_to_lub (only parsing). +Notation min_inf := lb_to_glb (only parsing). +Notation majorant := lub (only parsing). +Notation minorant := glb (only parsing). Lemma maj_ss : forall (Un:nat -> R) (k:nat), @@ -162,26 +165,30 @@ Proof. exists (k + x1)%nat; assumption. Qed. -Definition sequence_majorant (Un:nat -> R) (pr:has_ub Un) - (i:nat) : R := majorant (fun k:nat => Un (i + k)%nat) (maj_ss Un i pr). +Definition sequence_ub (Un:nat -> R) (pr:has_ub Un) + (i:nat) : R := lub (fun k:nat => Un (i + k)%nat) (maj_ss Un i pr). + +Definition sequence_lb (Un:nat -> R) (pr:has_lb Un) + (i:nat) : R := glb (fun k:nat => Un (i + k)%nat) (min_ss Un i pr). -Definition sequence_minorant (Un:nat -> R) (pr:has_lb Un) - (i:nat) : R := minorant (fun k:nat => Un (i + k)%nat) (min_ss Un i pr). +(* Compatibility *) +Notation sequence_majorant := sequence_ub (only parsing). +Notation sequence_minorant := sequence_lb (only parsing). Lemma Wn_decreasing : - forall (Un:nat -> R) (pr:has_ub Un), Un_decreasing (sequence_majorant Un pr). + forall (Un:nat -> R) (pr:has_ub Un), Un_decreasing (sequence_ub Un pr). Proof. intros. unfold Un_decreasing in |- *. intro. - unfold sequence_majorant in |- *. - assert (H := maj_sup (fun k:nat => Un (S n + k)%nat) (maj_ss Un (S n) pr)). - assert (H0 := maj_sup (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr)). + unfold sequence_ub in |- *. + assert (H := ub_to_lub (fun k:nat => Un (S n + k)%nat) (maj_ss Un (S n) pr)). + assert (H0 := ub_to_lub (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr)). elim H; intros. elim H0; intros. - cut (majorant (fun k:nat => Un (S n + k)%nat) (maj_ss Un (S n) pr) = x); + cut (lub (fun k:nat => Un (S n + k)%nat) (maj_ss Un (S n) pr) = x); [ intro Maj1; rewrite Maj1 | idtac ]. - cut (majorant (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr) = x0); + cut (lub (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr) = x0); [ intro Maj2; rewrite Maj2 | idtac ]. unfold is_lub in p. unfold is_lub in p0. @@ -199,47 +206,47 @@ Proof. replace (S n) with (1 + n)%nat; [ ring | ring ]. cut (is_lub (EUn (fun k:nat => Un (n + k)%nat)) - (majorant (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr))). + (lub (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr))). intro. unfold is_lub in p0; unfold is_lub in H1. elim p0; intros; elim H1; intros. assert (H6 := H5 x0 H2). assert - (H7 := H3 (majorant (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr)) H4). + (H7 := H3 (lub (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr)) H4). apply Rle_antisym; assumption. - unfold majorant in |- *. - case (maj_sup (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr)). + unfold lub in |- *. + case (ub_to_lub (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr)). trivial. cut (is_lub (EUn (fun k:nat => Un (S n + k)%nat)) - (majorant (fun k:nat => Un (S n + k)%nat) (maj_ss Un (S n) pr))). + (lub (fun k:nat => Un (S n + k)%nat) (maj_ss Un (S n) pr))). intro. unfold is_lub in p; unfold is_lub in H1. elim p; intros; elim H1; intros. assert (H6 := H5 x H2). assert (H7 := - H3 (majorant (fun k:nat => Un (S n + k)%nat) (maj_ss Un (S n) pr)) H4). + H3 (lub (fun k:nat => Un (S n + k)%nat) (maj_ss Un (S n) pr)) H4). apply Rle_antisym; assumption. - unfold majorant in |- *. - case (maj_sup (fun k:nat => Un (S n + k)%nat) (maj_ss Un (S n) pr)). + unfold lub in |- *. + case (ub_to_lub (fun k:nat => Un (S n + k)%nat) (maj_ss Un (S n) pr)). trivial. Qed. Lemma Vn_growing : - forall (Un:nat -> R) (pr:has_lb Un), Un_growing (sequence_minorant Un pr). + forall (Un:nat -> R) (pr:has_lb Un), Un_growing (sequence_lb Un pr). Proof. intros. unfold Un_growing in |- *. intro. - unfold sequence_minorant in |- *. - assert (H := min_inf (fun k:nat => Un (S n + k)%nat) (min_ss Un (S n) pr)). - assert (H0 := min_inf (fun k:nat => Un (n + k)%nat) (min_ss Un n pr)). + unfold sequence_lb in |- *. + assert (H := lb_to_glb (fun k:nat => Un (S n + k)%nat) (min_ss Un (S n) pr)). + assert (H0 := lb_to_glb (fun k:nat => Un (n + k)%nat) (min_ss Un n pr)). elim H; intros. elim H0; intros. - cut (minorant (fun k:nat => Un (S n + k)%nat) (min_ss Un (S n) pr) = - x); + cut (glb (fun k:nat => Un (S n + k)%nat) (min_ss Un (S n) pr) = - x); [ intro Maj1; rewrite Maj1 | idtac ]. - cut (minorant (fun k:nat => Un (n + k)%nat) (min_ss Un n pr) = - x0); + cut (glb (fun k:nat => Un (n + k)%nat) (min_ss Un n pr) = - x0); [ intro Maj2; rewrite Maj2 | idtac ]. unfold is_lub in p. unfold is_lub in p0. @@ -260,38 +267,38 @@ Proof. replace (S n) with (1 + n)%nat; [ ring | ring ]. cut (is_lub (EUn (opp_seq (fun k:nat => Un (n + k)%nat))) - (- minorant (fun k:nat => Un (n + k)%nat) (min_ss Un n pr))). + (- glb (fun k:nat => Un (n + k)%nat) (min_ss Un n pr))). intro. unfold is_lub in p0; unfold is_lub in H1. elim p0; intros; elim H1; intros. assert (H6 := H5 x0 H2). assert - (H7 := H3 (- minorant (fun k:nat => Un (n + k)%nat) (min_ss Un n pr)) H4). + (H7 := H3 (- glb (fun k:nat => Un (n + k)%nat) (min_ss Un n pr)) H4). rewrite <- - (Ropp_involutive (minorant (fun k:nat => Un (n + k)%nat) (min_ss Un n pr))) + (Ropp_involutive (glb (fun k:nat => Un (n + k)%nat) (min_ss Un n pr))) . apply Ropp_eq_compat; apply Rle_antisym; assumption. - unfold minorant in |- *. - case (min_inf (fun k:nat => Un (n + k)%nat) (min_ss Un n pr)). + unfold glb in |- *. + case (lb_to_glb (fun k:nat => Un (n + k)%nat) (min_ss Un n pr)); simpl. intro; rewrite Ropp_involutive. trivial. cut (is_lub (EUn (opp_seq (fun k:nat => Un (S n + k)%nat))) - (- minorant (fun k:nat => Un (S n + k)%nat) (min_ss Un (S n) pr))). + (- glb (fun k:nat => Un (S n + k)%nat) (min_ss Un (S n) pr))). intro. unfold is_lub in p; unfold is_lub in H1. elim p; intros; elim H1; intros. assert (H6 := H5 x H2). assert (H7 := - H3 (- minorant (fun k:nat => Un (S n + k)%nat) (min_ss Un (S n) pr)) H4). + H3 (- glb (fun k:nat => Un (S n + k)%nat) (min_ss Un (S n) pr)) H4). rewrite <- (Ropp_involutive - (minorant (fun k:nat => Un (S n + k)%nat) (min_ss Un (S n) pr))) + (glb (fun k:nat => Un (S n + k)%nat) (min_ss Un (S n) pr))) . apply Ropp_eq_compat; apply Rle_antisym; assumption. - unfold minorant in |- *. - case (min_inf (fun k:nat => Un (S n + k)%nat) (min_ss Un (S n) pr)). + unfold glb in |- *. + case (lb_to_glb (fun k:nat => Un (S n + k)%nat) (min_ss Un (S n) pr)); simpl. intro; rewrite Ropp_involutive. trivial. Qed. @@ -299,16 +306,15 @@ Qed. (**********) Lemma Vn_Un_Wn_order : forall (Un:nat -> R) (pr1:has_ub Un) (pr2:has_lb Un) - (n:nat), sequence_minorant Un pr2 n <= Un n <= sequence_majorant Un pr1 n. + (n:nat), sequence_lb Un pr2 n <= Un n <= sequence_ub Un pr1 n. Proof. intros. split. - unfold sequence_minorant in |- *. - cut - (sigT (fun l:R => is_lub (EUn (opp_seq (fun i:nat => Un (n + i)%nat))) l)). + unfold sequence_lb in |- *. + cut { l:R | is_lub (EUn (opp_seq (fun i:nat => Un (n + i)%nat))) l }. intro X. elim X; intros. - replace (minorant (fun k:nat => Un (n + k)%nat) (min_ss Un n pr2)) with (- x). + replace (glb (fun k:nat => Un (n + k)%nat) (min_ss Un n pr2)) with (- x). unfold is_lub in p. elim p; intros. unfold is_upper_bound in H. @@ -320,28 +326,28 @@ Proof. replace (n + 0)%nat with n; [ reflexivity | ring ]. cut (is_lub (EUn (opp_seq (fun k:nat => Un (n + k)%nat))) - (- minorant (fun k:nat => Un (n + k)%nat) (min_ss Un n pr2))). + (- glb (fun k:nat => Un (n + k)%nat) (min_ss Un n pr2))). intro. unfold is_lub in p; unfold is_lub in H. elim p; intros; elim H; intros. assert (H4 := H3 x H0). assert - (H5 := H1 (- minorant (fun k:nat => Un (n + k)%nat) (min_ss Un n pr2)) H2). + (H5 := H1 (- glb (fun k:nat => Un (n + k)%nat) (min_ss Un n pr2)) H2). rewrite <- - (Ropp_involutive (minorant (fun k:nat => Un (n + k)%nat) (min_ss Un n pr2))) + (Ropp_involutive (glb (fun k:nat => Un (n + k)%nat) (min_ss Un n pr2))) . apply Ropp_eq_compat; apply Rle_antisym; assumption. - unfold minorant in |- *. - case (min_inf (fun k:nat => Un (n + k)%nat) (min_ss Un n pr2)). + unfold glb in |- *. + case (lb_to_glb (fun k:nat => Un (n + k)%nat) (min_ss Un n pr2)); simpl. intro; rewrite Ropp_involutive. trivial. - apply min_inf. + apply lb_to_glb. apply min_ss; assumption. - unfold sequence_majorant in |- *. - cut (sigT (fun l:R => is_lub (EUn (fun i:nat => Un (n + i)%nat)) l)). + unfold sequence_ub in |- *. + cut { l:R | is_lub (EUn (fun i:nat => Un (n + i)%nat)) l }. intro X. elim X; intros. - replace (majorant (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr1)) with x. + replace (lub (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr1)) with x. unfold is_lub in p. elim p; intros. unfold is_upper_bound in H. @@ -350,24 +356,24 @@ Proof. replace (n + 0)%nat with n; [ reflexivity | ring ]. cut (is_lub (EUn (fun k:nat => Un (n + k)%nat)) - (majorant (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr1))). + (lub (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr1))). intro. unfold is_lub in p; unfold is_lub in H. elim p; intros; elim H; intros. assert (H4 := H3 x H0). assert - (H5 := H1 (majorant (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr1)) H2). + (H5 := H1 (lub (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr1)) H2). apply Rle_antisym; assumption. - unfold majorant in |- *. - case (maj_sup (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr1)). + unfold lub in |- *. + case (ub_to_lub (fun k:nat => Un (n + k)%nat) (maj_ss Un n pr1)). intro; trivial. - apply maj_sup. + apply ub_to_lub. apply maj_ss; assumption. Qed. Lemma min_maj : forall (Un:nat -> R) (pr1:has_ub Un) (pr2:has_lb Un), - has_ub (sequence_minorant Un pr2). + has_ub (sequence_lb Un pr2). Proof. intros. assert (H := Vn_Un_Wn_order Un pr1 pr2). @@ -390,7 +396,7 @@ Qed. Lemma maj_min : forall (Un:nat -> R) (pr1:has_ub Un) (pr2:has_lb Un), - has_lb (sequence_majorant Un pr1). + has_lb (sequence_ub Un pr1). Proof. intros. assert (H := Vn_Un_Wn_order Un pr1 pr2). @@ -451,7 +457,7 @@ Qed. (**********) Lemma maj_cv : forall (Un:nat -> R) (pr:Cauchy_crit Un), - sigT (fun l:R => Un_cv (sequence_majorant Un (cauchy_maj Un pr)) l). + { l:R | Un_cv (sequence_ub Un (cauchy_maj Un pr)) l }. Proof. intros. apply decreasing_cv. @@ -464,7 +470,7 @@ Qed. (**********) Lemma min_cv : forall (Un:nat -> R) (pr:Cauchy_crit Un), - sigT (fun l:R => Un_cv (sequence_minorant Un (cauchy_min Un pr)) l). + { l:R | Un_cv (sequence_lb Un (cauchy_min Un pr)) l }. Proof. intros. apply growing_cv. @@ -510,40 +516,40 @@ Qed. (**********) Lemma approx_maj : forall (Un:nat -> R) (pr:has_ub Un) (eps:R), - 0 < eps -> exists k : nat, Rabs (majorant Un pr - Un k) < eps. + 0 < eps -> exists k : nat, Rabs (lub Un pr - Un k) < eps. Proof. intros. - set (P := fun k:nat => Rabs (majorant Un pr - Un k) < eps). + set (P := fun k:nat => Rabs (lub Un pr - Un k) < eps). unfold P in |- *. cut ((exists k : nat, P k) -> - exists k : nat, Rabs (majorant Un pr - Un k) < eps). + exists k : nat, Rabs (lub Un pr - Un k) < eps). intros. apply H0. apply not_all_not_ex. red in |- *; intro. 2: unfold P in |- *; trivial. unfold P in H1. - cut (forall n:nat, Rabs (majorant Un pr - Un n) >= eps). + cut (forall n:nat, Rabs (lub Un pr - Un n) >= eps). intro. - cut (is_lub (EUn Un) (majorant Un pr)). + cut (is_lub (EUn Un) (lub Un pr)). intro. unfold is_lub in H3. unfold is_upper_bound in H3. elim H3; intros. - cut (forall n:nat, eps <= majorant Un pr - Un n). + cut (forall n:nat, eps <= lub Un pr - Un n). intro. - cut (forall n:nat, Un n <= majorant Un pr - eps). + cut (forall n:nat, Un n <= lub Un pr - eps). intro. - cut (forall x:R, EUn Un x -> x <= majorant Un pr - eps). + cut (forall x:R, EUn Un x -> x <= lub Un pr - eps). intro. - assert (H9 := H5 (majorant Un pr - eps) H8). + assert (H9 := H5 (lub Un pr - eps) H8). cut (eps <= 0). intro. elim (Rlt_irrefl _ (Rlt_le_trans _ _ _ H H10)). - apply Rplus_le_reg_l with (majorant Un pr - eps). + apply Rplus_le_reg_l with (lub Un pr - eps). rewrite Rplus_0_r. - replace (majorant Un pr - eps + eps) with (majorant Un pr); + replace (lub Un pr - eps + eps) with (lub Un pr); [ assumption | ring ]. intros. unfold EUn in H8. @@ -553,7 +559,7 @@ Proof. assert (H7 := H6 n). apply Rplus_le_reg_l with (eps - Un n). replace (eps - Un n + Un n) with eps. - replace (eps - Un n + (majorant Un pr - eps)) with (majorant Un pr - Un n). + replace (eps - Un n + (lub Un pr - eps)) with (lub Un pr - Un n). assumption. ring. ring. @@ -565,11 +571,11 @@ Proof. apply Rle_ge. apply Rplus_le_reg_l with (Un n). rewrite Rplus_0_r; - replace (Un n + (majorant Un pr - Un n)) with (majorant Un pr); + replace (Un n + (lub Un pr - Un n)) with (lub Un pr); [ apply H4 | ring ]. exists n; reflexivity. - unfold majorant in |- *. - case (maj_sup Un pr). + unfold lub in |- *. + case (ub_to_lub Un pr). trivial. intro. assert (H2 := H1 n). @@ -579,40 +585,40 @@ Qed. (**********) Lemma approx_min : forall (Un:nat -> R) (pr:has_lb Un) (eps:R), - 0 < eps -> exists k : nat, Rabs (minorant Un pr - Un k) < eps. + 0 < eps -> exists k : nat, Rabs (glb Un pr - Un k) < eps. Proof. intros. - set (P := fun k:nat => Rabs (minorant Un pr - Un k) < eps). + set (P := fun k:nat => Rabs (glb Un pr - Un k) < eps). unfold P in |- *. cut ((exists k : nat, P k) -> - exists k : nat, Rabs (minorant Un pr - Un k) < eps). + exists k : nat, Rabs (glb Un pr - Un k) < eps). intros. apply H0. apply not_all_not_ex. red in |- *; intro. 2: unfold P in |- *; trivial. unfold P in H1. - cut (forall n:nat, Rabs (minorant Un pr - Un n) >= eps). + cut (forall n:nat, Rabs (glb Un pr - Un n) >= eps). intro. - cut (is_lub (EUn (opp_seq Un)) (- minorant Un pr)). + cut (is_lub (EUn (opp_seq Un)) (- glb Un pr)). intro. unfold is_lub in H3. unfold is_upper_bound in H3. elim H3; intros. - cut (forall n:nat, eps <= Un n - minorant Un pr). + cut (forall n:nat, eps <= Un n - glb Un pr). intro. - cut (forall n:nat, opp_seq Un n <= - minorant Un pr - eps). + cut (forall n:nat, opp_seq Un n <= - glb Un pr - eps). intro. - cut (forall x:R, EUn (opp_seq Un) x -> x <= - minorant Un pr - eps). + cut (forall x:R, EUn (opp_seq Un) x -> x <= - glb Un pr - eps). intro. - assert (H9 := H5 (- minorant Un pr - eps) H8). + assert (H9 := H5 (- glb Un pr - eps) H8). cut (eps <= 0). intro. elim (Rlt_irrefl _ (Rlt_le_trans _ _ _ H H10)). - apply Rplus_le_reg_l with (- minorant Un pr - eps). + apply Rplus_le_reg_l with (- glb Un pr - eps). rewrite Rplus_0_r. - replace (- minorant Un pr - eps + eps) with (- minorant Un pr); + replace (- glb Un pr - eps + eps) with (- glb Un pr); [ assumption | ring ]. intros. unfold EUn in H8. @@ -623,7 +629,7 @@ Proof. unfold opp_seq in |- *. apply Rplus_le_reg_l with (eps + Un n). replace (eps + Un n + - Un n) with eps. - replace (eps + Un n + (- minorant Un pr - eps)) with (Un n - minorant Un pr). + replace (eps + Un n + (- glb Un pr - eps)) with (Un n - glb Un pr). assumption. ring. ring. @@ -631,16 +637,16 @@ Proof. assert (H6 := H2 n). rewrite Rabs_left1 in H6. apply Rge_le. - replace (Un n - minorant Un pr) with (- (minorant Un pr - Un n)); + replace (Un n - glb Un pr) with (- (glb Un pr - Un n)); [ assumption | ring ]. - apply Rplus_le_reg_l with (- minorant Un pr). + apply Rplus_le_reg_l with (- glb Un pr). rewrite Rplus_0_r; - replace (- minorant Un pr + (minorant Un pr - Un n)) with (- Un n). + replace (- glb Un pr + (glb Un pr - Un n)) with (- Un n). apply H4. exists n; reflexivity. ring. - unfold minorant in |- *. - case (min_inf Un pr). + unfold glb in |- *. + case (lb_to_glb Un pr); simpl. intro. rewrite Ropp_involutive. trivial. @@ -711,7 +717,7 @@ Qed. (**********) Lemma CV_Cauchy : - forall Un:nat -> R, sigT (fun l:R => Un_cv Un l) -> Cauchy_crit Un. + forall Un:nat -> R, { l:R | Un_cv Un l } -> Cauchy_crit Un. Proof. intros Un X; elim X; intros. unfold Cauchy_crit in |- *; intros. @@ -734,11 +740,11 @@ Qed. (**********) Lemma maj_by_pos : forall Un:nat -> R, - sigT (fun l:R => Un_cv Un l) -> + { l:R | Un_cv Un l } -> exists l : R, 0 < l /\ (forall n:nat, Rabs (Un n) <= l). Proof. intros Un X; elim X; intros. - cut (sigT (fun l:R => Un_cv (fun k:nat => Rabs (Un k)) l)). + cut { l:R | Un_cv (fun k:nat => Rabs (Un k)) l }. intro X0. assert (H := CV_Cauchy (fun k:nat => Rabs (Un k)) X0). assert (H0 := cauchy_bound (fun k:nat => Rabs (Un k)) H). @@ -760,7 +766,7 @@ Proof. unfold is_upper_bound in H1. apply H1. exists 0%nat; reflexivity. - apply existT with (Rabs x). + exists (Rabs x). apply cv_cvabs; assumption. Qed. @@ -770,7 +776,7 @@ Lemma CV_mult : Un_cv An l1 -> Un_cv Bn l2 -> Un_cv (fun i:nat => An i * Bn i) (l1 * l2). Proof. intros. - cut (sigT (fun l:R => Un_cv An l)). + cut { l:R | Un_cv An l }. intro X. assert (H1 := maj_by_pos An X). elim H1; intros M H2. @@ -881,7 +887,7 @@ Proof. [ assumption | apply Rinv_0_lt_compat; apply Rmult_lt_0_compat; [ prove_sup0 | assumption ] ]. - apply existT with l1; assumption. + exists l1; assumption. Qed. Lemma tech9 : diff --git a/theories/Reals/SeqSeries.v b/theories/Reals/SeqSeries.v index bc17cd43..9680b75e 100644 --- a/theories/Reals/SeqSeries.v +++ b/theories/Reals/SeqSeries.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: SeqSeries.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: SeqSeries.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. @@ -33,15 +33,9 @@ Lemma sum_maj1 : Rabs (l1 - SP fn N x) <= l2 - sum_f_R0 An N. Proof. intros; - cut - (sigT - (fun l:R => - Un_cv (fun n:nat => sum_f_R0 (fun l:nat => fn (S N + l)%nat x) n) l)). + cut { l:R | Un_cv (fun n => sum_f_R0 (fun l => fn (S N + l)%nat x) n) l }. intro X; - cut - (sigT - (fun l:R => - Un_cv (fun n:nat => sum_f_R0 (fun l:nat => An (S N + l)%nat) n) l)). + cut { l:R | Un_cv (fun n => sum_f_R0 (fun l => An (S N + l)%nat) n) l }. intro X0; elim X; intros l1N H2. elim X0; intros l2N H3. cut (l1 - SP fn N x = l1N). @@ -131,7 +125,7 @@ Proof. apply le_lt_n_Sm. apply le_plus_l. apply le_O_n. - apply existT with (l2 - sum_f_R0 An N). + exists (l2 - sum_f_R0 An N). unfold Un_cv in H0; unfold Un_cv in |- *; intros. elim (H0 eps H2); intros N0 H3. unfold R_dist in H3; exists N0; intros. @@ -167,7 +161,7 @@ Proof. apply le_lt_n_Sm. apply le_plus_l. apply le_O_n. - apply existT with (l1 - SP fn N x). + exists (l1 - SP fn N x). unfold Un_cv in H; unfold Un_cv in |- *; intros. elim (H eps H2); intros N0 H3. unfold R_dist in H3; exists N0; intros. @@ -216,8 +210,8 @@ Qed. Lemma Rseries_CV_comp : forall An Bn:nat -> R, (forall n:nat, 0 <= An n <= Bn n) -> - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 Bn N) l) -> - sigT (fun l:R => Un_cv (fun N:nat => sum_f_R0 An N) l). + { l:R | Un_cv (fun N:nat => sum_f_R0 Bn N) l } -> + { l:R | Un_cv (fun N:nat => sum_f_R0 An N) l }. Proof. intros An Bn H X; apply cv_cauchy_2. assert (H0 := cv_cauchy_1 _ X). diff --git a/theories/Reals/Sqrt_reg.v b/theories/Reals/Sqrt_reg.v index ff0a72e8..13be46da 100644 --- a/theories/Reals/Sqrt_reg.v +++ b/theories/Reals/Sqrt_reg.v @@ -6,12 +6,13 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Sqrt_reg.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Sqrt_reg.v 10710 2008-03-23 09:24:09Z herbelin $ i*) Require Import Rbase. Require Import Rfunctions. Require Import Ranalysis1. -Require Import R_sqrt. Open Local Scope R_scope. +Require Import R_sqrt. +Open Local Scope R_scope. (**********) Lemma sqrt_var_maj : @@ -309,7 +310,7 @@ Qed. Lemma derivable_pt_sqrt : forall x:R, 0 < x -> derivable_pt sqrt x. Proof. unfold derivable_pt in |- *; intros. - apply existT with (/ (2 * sqrt x)). + exists (/ (2 * sqrt x)). apply derivable_pt_lim_sqrt; assumption. Qed. diff --git a/theories/Relations/Operators_Properties.v b/theories/Relations/Operators_Properties.v index 7e202359..0638ca8f 100644 --- a/theories/Relations/Operators_Properties.v +++ b/theories/Relations/Operators_Properties.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Operators_Properties.v 9597 2007-02-06 19:44:05Z herbelin $ i*) +(*i $Id: Operators_Properties.v 9598 2007-02-06 19:45:52Z herbelin $ i*) (****************************************************************************) (* Bruno Barras *) diff --git a/theories/Relations/Relation_Operators.v b/theories/Relations/Relation_Operators.v index 4c5a6519..87cd1e6f 100644 --- a/theories/Relations/Relation_Operators.v +++ b/theories/Relations/Relation_Operators.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Relation_Operators.v 9610 2007-02-07 14:45:18Z herbelin $ i*) +(*i $Id: Relation_Operators.v 10681 2008-03-16 13:40:45Z msozeau $ i*) (****************************************************************************) (* Bruno Barras, Cristina Cornes *) @@ -83,9 +83,9 @@ Variable leA : A -> A -> Prop. Variable leB : B -> B -> Prop. Inductive le_AsB : A + B -> A + B -> Prop := - | le_aa : forall x y:A, leA x y -> le_AsB (inl B x) (inl B y) - | le_ab : forall (x:A) (y:B), le_AsB (inl B x) (inr A y) - | le_bb : forall x y:B, leB x y -> le_AsB (inr A x) (inr A y). + | le_aa : forall x y:A, leA x y -> le_AsB (inl _ x) (inl _ y) + | le_ab : forall (x:A) (y:B), le_AsB (inl _ x) (inr _ y) + | le_bb : forall x y:B, leB x y -> le_AsB (inr _ x) (inr _ y). End Disjoint_Union. diff --git a/theories/Relations/Relations.v b/theories/Relations/Relations.v index 9da30e9b..6368ae25 100644 --- a/theories/Relations/Relations.v +++ b/theories/Relations/Relations.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Relations.v 9597 2007-02-06 19:44:05Z herbelin $ i*) +(*i $Id: Relations.v 9598 2007-02-06 19:45:52Z herbelin $ i*) Require Export Relation_Definitions. Require Export Relation_Operators. diff --git a/theories/Relations/Rstar.v b/theories/Relations/Rstar.v index 91d2aaa4..82668006 100644 --- a/theories/Relations/Rstar.v +++ b/theories/Relations/Rstar.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Rstar.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Rstar.v 9642 2007-02-12 10:31:53Z herbelin $ i*) (** Properties of a binary relation [R] on type [A] *) @@ -87,7 +87,7 @@ Section Rstar. (** Property of Commutativity of two relations *) - Definition commut (A:Set) (R1 R2:A -> A -> Prop) := + Definition commut (A:Type) (R1 R2:A -> A -> Prop) := forall x y:A, R1 y x -> forall z:A, R2 z y -> exists2 y' : A, R2 y' x & R1 z y'. diff --git a/theories/Setoids/Setoid.v b/theories/Setoids/Setoid.v index 84af7d5d..d6975e91 100644 --- a/theories/Setoids/Setoid.v +++ b/theories/Setoids/Setoid.v @@ -1,4 +1,3 @@ - (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) (* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *) @@ -7,673 +6,20 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Setoid.v 9245 2006-10-17 12:53:34Z notin $: i*) - -Require Export Relation_Definitions. - -Set Implicit Arguments. - -(** * Definitions of [Relation_Class] and n-ary [Morphism_Theory] *) - -(* X will be used to distinguish covariant arguments whose type is an *) -(* Asymmetric* relation from contravariant arguments of the same type *) -Inductive X_Relation_Class (X: Type) : Type := - SymmetricReflexive : - forall A Aeq, symmetric A Aeq -> reflexive _ Aeq -> X_Relation_Class X - | AsymmetricReflexive : X -> forall A Aeq, reflexive A Aeq -> X_Relation_Class X - | SymmetricAreflexive : forall A Aeq, symmetric A Aeq -> X_Relation_Class X - | AsymmetricAreflexive : X -> forall A (Aeq : relation A), X_Relation_Class X - | Leibniz : Type -> X_Relation_Class X. - -Inductive variance : Set := - Covariant - | Contravariant. - -Definition Argument_Class := X_Relation_Class variance. -Definition Relation_Class := X_Relation_Class unit. - -Inductive Reflexive_Relation_Class : Type := - RSymmetric : - forall A Aeq, symmetric A Aeq -> reflexive _ Aeq -> Reflexive_Relation_Class - | RAsymmetric : - forall A Aeq, reflexive A Aeq -> Reflexive_Relation_Class - | RLeibniz : Type -> Reflexive_Relation_Class. - -Inductive Areflexive_Relation_Class : Type := - | ASymmetric : forall A Aeq, symmetric A Aeq -> Areflexive_Relation_Class - | AAsymmetric : forall A (Aeq : relation A), Areflexive_Relation_Class. - -Implicit Type Hole Out: Relation_Class. - -Definition relation_class_of_argument_class : Argument_Class -> Relation_Class. - destruct 1. - exact (SymmetricReflexive _ s r). - exact (AsymmetricReflexive tt r). - exact (SymmetricAreflexive _ s). - exact (AsymmetricAreflexive tt Aeq). - exact (Leibniz _ T). -Defined. - -Definition carrier_of_relation_class : forall X, X_Relation_Class X -> Type. - destruct 1. - exact A. - exact A. - exact A. - exact A. - exact T. -Defined. - -Definition relation_of_relation_class : - forall X R, @carrier_of_relation_class X R -> carrier_of_relation_class R -> Prop. - destruct R. - exact Aeq. - exact Aeq. - exact Aeq. - exact Aeq. - exact (@eq T). -Defined. - -Lemma about_carrier_of_relation_class_and_relation_class_of_argument_class : - forall R, - carrier_of_relation_class (relation_class_of_argument_class R) = - carrier_of_relation_class R. - destruct R; reflexivity. -Defined. - -Inductive nelistT (A : Type) : Type := - singl : A -> nelistT A - | necons : A -> nelistT A -> nelistT A. - -Definition Arguments := nelistT Argument_Class. - -Implicit Type In: Arguments. - -Definition function_type_of_morphism_signature : - Arguments -> Relation_Class -> Type. - intros In Out. - induction In. - exact (carrier_of_relation_class a -> carrier_of_relation_class Out). - exact (carrier_of_relation_class a -> IHIn). -Defined. - -Definition make_compatibility_goal_aux: - forall In Out - (f g: function_type_of_morphism_signature In Out), Prop. - intros; induction In; simpl in f, g. - induction a; simpl in f, g. - exact (forall x1 x2, Aeq x1 x2 -> relation_of_relation_class Out (f x1) (g x2)). - destruct x. - exact (forall x1 x2, Aeq x1 x2 -> relation_of_relation_class Out (f x1) (g x2)). - exact (forall x1 x2, Aeq x2 x1 -> relation_of_relation_class Out (f x1) (g x2)). - exact (forall x1 x2, Aeq x1 x2 -> relation_of_relation_class Out (f x1) (g x2)). - destruct x. - exact (forall x1 x2, Aeq x1 x2 -> relation_of_relation_class Out (f x1) (g x2)). - exact (forall x1 x2, Aeq x2 x1 -> relation_of_relation_class Out (f x1) (g x2)). - exact (forall x, relation_of_relation_class Out (f x) (g x)). - induction a; simpl in f, g. - exact (forall x1 x2, Aeq x1 x2 -> IHIn (f x1) (g x2)). - destruct x. - exact (forall x1 x2, Aeq x1 x2 -> IHIn (f x1) (g x2)). - exact (forall x1 x2, Aeq x2 x1 -> IHIn (f x1) (g x2)). - exact (forall x1 x2, Aeq x1 x2 -> IHIn (f x1) (g x2)). - destruct x. - exact (forall x1 x2, Aeq x1 x2 -> IHIn (f x1) (g x2)). - exact (forall x1 x2, Aeq x2 x1 -> IHIn (f x1) (g x2)). - exact (forall x, IHIn (f x) (g x)). -Defined. - -Definition make_compatibility_goal := - (fun In Out f => make_compatibility_goal_aux In Out f f). - -Record Morphism_Theory In Out : Type := - { Function : function_type_of_morphism_signature In Out; - Compat : make_compatibility_goal In Out Function }. - -(** The [iff] relation class *) - -Definition Iff_Relation_Class : Relation_Class. - eapply (@SymmetricReflexive unit _ iff). - exact iff_sym. - exact iff_refl. -Defined. - -(** The [impl] relation class *) - -Definition impl (A B: Prop) := A -> B. - -Theorem impl_refl: reflexive _ impl. -Proof. - hnf; unfold impl; tauto. -Qed. - -Definition Impl_Relation_Class : Relation_Class. - eapply (@AsymmetricReflexive unit tt _ impl). - exact impl_refl. -Defined. - -(** Every function is a morphism from Leibniz+ to Leibniz *) - -Definition list_of_Leibniz_of_list_of_types: nelistT Type -> Arguments. - induction 1. - exact (singl (Leibniz _ a)). - exact (necons (Leibniz _ a) IHX). -Defined. - -Definition morphism_theory_of_function : - forall (In: nelistT Type) (Out: Type), - let In' := list_of_Leibniz_of_list_of_types In in - let Out' := Leibniz _ Out in - function_type_of_morphism_signature In' Out' -> - Morphism_Theory In' Out'. - intros. - exists X. - induction In; unfold make_compatibility_goal; simpl. - reflexivity. - intro; apply (IHIn (X x)). -Defined. - -(** Every predicate is a morphism from Leibniz+ to Iff_Relation_Class *) - -Definition morphism_theory_of_predicate : - forall (In: nelistT Type), - let In' := list_of_Leibniz_of_list_of_types In in - function_type_of_morphism_signature In' Iff_Relation_Class -> - Morphism_Theory In' Iff_Relation_Class. - intros. - exists X. - induction In; unfold make_compatibility_goal; simpl. - intro; apply iff_refl. - intro; apply (IHIn (X x)). -Defined. - -(** * Utility functions to prove that every transitive relation is a morphism *) - -Definition equality_morphism_of_symmetric_areflexive_transitive_relation: - forall (A: Type)(Aeq: relation A)(sym: symmetric _ Aeq)(trans: transitive _ Aeq), - let ASetoidClass := SymmetricAreflexive _ sym in - (Morphism_Theory (necons ASetoidClass (singl ASetoidClass)) Iff_Relation_Class). - intros. - exists Aeq. - unfold make_compatibility_goal; simpl; split; eauto. -Defined. - -Definition equality_morphism_of_symmetric_reflexive_transitive_relation: - forall (A: Type)(Aeq: relation A)(refl: reflexive _ Aeq)(sym: symmetric _ Aeq) - (trans: transitive _ Aeq), let ASetoidClass := SymmetricReflexive _ sym refl in - (Morphism_Theory (necons ASetoidClass (singl ASetoidClass)) Iff_Relation_Class). - intros. - exists Aeq. - unfold make_compatibility_goal; simpl; split; eauto. -Defined. - -Definition equality_morphism_of_asymmetric_areflexive_transitive_relation: - forall (A: Type)(Aeq: relation A)(trans: transitive _ Aeq), - let ASetoidClass1 := AsymmetricAreflexive Contravariant Aeq in - let ASetoidClass2 := AsymmetricAreflexive Covariant Aeq in - (Morphism_Theory (necons ASetoidClass1 (singl ASetoidClass2)) Impl_Relation_Class). - intros. - exists Aeq. - unfold make_compatibility_goal; simpl; unfold impl; eauto. -Defined. - -Definition equality_morphism_of_asymmetric_reflexive_transitive_relation: - forall (A: Type)(Aeq: relation A)(refl: reflexive _ Aeq)(trans: transitive _ Aeq), - let ASetoidClass1 := AsymmetricReflexive Contravariant refl in - let ASetoidClass2 := AsymmetricReflexive Covariant refl in - (Morphism_Theory (necons ASetoidClass1 (singl ASetoidClass2)) Impl_Relation_Class). - intros. - exists Aeq. - unfold make_compatibility_goal; simpl; unfold impl; eauto. -Defined. - -(** * A few examples on [iff] *) - -(** [iff] as a relation *) - -Add Relation Prop iff - reflexivity proved by iff_refl - symmetry proved by iff_sym - transitivity proved by iff_trans -as iff_relation. - -(** [impl] as a relation *) - -Theorem impl_trans: transitive _ impl. -Proof. - hnf; unfold impl; tauto. -Qed. - -Add Relation Prop impl - reflexivity proved by impl_refl - transitivity proved by impl_trans -as impl_relation. - -(** [impl] is a morphism *) - -Add Morphism impl with signature iff ==> iff ==> iff as Impl_Morphism. -Proof. - unfold impl; tauto. -Qed. - -(** [and] is a morphism *) - -Add Morphism and with signature iff ==> iff ==> iff as And_Morphism. - tauto. -Qed. - -(** [or] is a morphism *) - -Add Morphism or with signature iff ==> iff ==> iff as Or_Morphism. -Proof. - tauto. -Qed. - -(** [not] is a morphism *) - -Add Morphism not with signature iff ==> iff as Not_Morphism. -Proof. - tauto. -Qed. - -(** The same examples on [impl] *) - -Add Morphism and with signature impl ++> impl ++> impl as And_Morphism2. -Proof. - unfold impl; tauto. -Qed. - -Add Morphism or with signature impl ++> impl ++> impl as Or_Morphism2. -Proof. - unfold impl; tauto. -Qed. - -Add Morphism not with signature impl --> impl as Not_Morphism2. -Proof. - unfold impl; tauto. -Qed. - -(** * The CIC part of the reflexive tactic ([setoid_rewrite]) *) - -Inductive rewrite_direction : Type := - | Left2Right - | Right2Left. - -Implicit Type dir: rewrite_direction. - -Definition variance_of_argument_class : Argument_Class -> option variance. - destruct 1. - exact None. - exact (Some v). - exact None. - exact (Some v). - exact None. -Defined. - -Definition opposite_direction := - fun dir => - match dir with - | Left2Right => Right2Left - | Right2Left => Left2Right - end. - -Lemma opposite_direction_idempotent: - forall dir, (opposite_direction (opposite_direction dir)) = dir. -Proof. - destruct dir; reflexivity. -Qed. - -Inductive check_if_variance_is_respected : - option variance -> rewrite_direction -> rewrite_direction -> Prop := - | MSNone : forall dir dir', check_if_variance_is_respected None dir dir' - | MSCovariant : forall dir, check_if_variance_is_respected (Some Covariant) dir dir - | MSContravariant : - forall dir, - check_if_variance_is_respected (Some Contravariant) dir (opposite_direction dir). - -Definition relation_class_of_reflexive_relation_class: - Reflexive_Relation_Class -> Relation_Class. - induction 1. - exact (SymmetricReflexive _ s r). - exact (AsymmetricReflexive tt r). - exact (Leibniz _ T). -Defined. - -Definition relation_class_of_areflexive_relation_class: - Areflexive_Relation_Class -> Relation_Class. - induction 1. - exact (SymmetricAreflexive _ s). - exact (AsymmetricAreflexive tt Aeq). -Defined. - -Definition carrier_of_reflexive_relation_class := - fun R => carrier_of_relation_class (relation_class_of_reflexive_relation_class R). - -Definition carrier_of_areflexive_relation_class := - fun R => carrier_of_relation_class (relation_class_of_areflexive_relation_class R). - -Definition relation_of_areflexive_relation_class := - fun R => relation_of_relation_class (relation_class_of_areflexive_relation_class R). - -Inductive Morphism_Context Hole dir : Relation_Class -> rewrite_direction -> Type := - | App : - forall In Out dir', - Morphism_Theory In Out -> Morphism_Context_List Hole dir dir' In -> - Morphism_Context Hole dir Out dir' - | ToReplace : Morphism_Context Hole dir Hole dir - | ToKeep : - forall S dir', - carrier_of_reflexive_relation_class S -> - Morphism_Context Hole dir (relation_class_of_reflexive_relation_class S) dir' - | ProperElementToKeep : - forall S dir' (x: carrier_of_areflexive_relation_class S), - relation_of_areflexive_relation_class S x x -> - Morphism_Context Hole dir (relation_class_of_areflexive_relation_class S) dir' -with Morphism_Context_List Hole dir : - rewrite_direction -> Arguments -> Type -:= - fcl_singl : - forall S dir' dir'', - check_if_variance_is_respected (variance_of_argument_class S) dir' dir'' -> - Morphism_Context Hole dir (relation_class_of_argument_class S) dir' -> - Morphism_Context_List Hole dir dir'' (singl S) - | fcl_cons : - forall S L dir' dir'', - check_if_variance_is_respected (variance_of_argument_class S) dir' dir'' -> - Morphism_Context Hole dir (relation_class_of_argument_class S) dir' -> - Morphism_Context_List Hole dir dir'' L -> - Morphism_Context_List Hole dir dir'' (necons S L). - -Scheme Morphism_Context_rect2 := Induction for Morphism_Context Sort Type -with Morphism_Context_List_rect2 := Induction for Morphism_Context_List Sort Type. - -Definition product_of_arguments : Arguments -> Type. - induction 1. - exact (carrier_of_relation_class a). - exact (prod (carrier_of_relation_class a) IHX). -Defined. - -Definition get_rewrite_direction: rewrite_direction -> Argument_Class -> rewrite_direction. - intros dir R. - destruct (variance_of_argument_class R). - destruct v. - exact dir. (* covariant *) - exact (opposite_direction dir). (* contravariant *) - exact dir. (* symmetric relation *) -Defined. - -Definition directed_relation_of_relation_class: - forall dir (R: Relation_Class), - carrier_of_relation_class R -> carrier_of_relation_class R -> Prop. - destruct 1. - exact (@relation_of_relation_class unit). - intros; exact (relation_of_relation_class _ X0 X). -Defined. - -Definition directed_relation_of_argument_class: - forall dir (R: Argument_Class), - carrier_of_relation_class R -> carrier_of_relation_class R -> Prop. - intros dir R. - rewrite <- - (about_carrier_of_relation_class_and_relation_class_of_argument_class R). - exact (directed_relation_of_relation_class dir (relation_class_of_argument_class R)). -Defined. - - -Definition relation_of_product_of_arguments: - forall dir In, - product_of_arguments In -> product_of_arguments In -> Prop. - induction In. - simpl. - exact (directed_relation_of_argument_class (get_rewrite_direction dir a) a). - - simpl; intros. - destruct X; destruct X0. - apply and. - exact - (directed_relation_of_argument_class (get_rewrite_direction dir a) a c c0). - exact (IHIn p p0). -Defined. - -Definition apply_morphism: - forall In Out (m: function_type_of_morphism_signature In Out) - (args: product_of_arguments In), carrier_of_relation_class Out. - intros. - induction In. - exact (m args). - simpl in m, args. - destruct args. - exact (IHIn (m c) p). -Defined. - -Theorem apply_morphism_compatibility_Right2Left: - forall In Out (m1 m2: function_type_of_morphism_signature In Out) - (args1 args2: product_of_arguments In), - make_compatibility_goal_aux _ _ m1 m2 -> - relation_of_product_of_arguments Right2Left _ args1 args2 -> - directed_relation_of_relation_class Right2Left _ - (apply_morphism _ _ m2 args1) - (apply_morphism _ _ m1 args2). - induction In; intros. - simpl in m1, m2, args1, args2, H0 |- *. - destruct a; simpl in H; hnf in H0. - apply H; exact H0. - destruct v; simpl in H0; apply H; exact H0. - apply H; exact H0. - destruct v; simpl in H0; apply H; exact H0. - rewrite H0; apply H; exact H0. - - simpl in m1, m2, args1, args2, H0 |- *. - destruct args1; destruct args2; simpl. - destruct H0. - simpl in H. - destruct a; simpl in H. - apply IHIn. - apply H; exact H0. - exact H1. - destruct v. - apply IHIn. - apply H; exact H0. - exact H1. - apply IHIn. - apply H; exact H0. - exact H1. - apply IHIn. - apply H; exact H0. - exact H1. - destruct v. - apply IHIn. - apply H; exact H0. - exact H1. - apply IHIn. - apply H; exact H0. - exact H1. - rewrite H0; apply IHIn. - apply H. - exact H1. -Qed. - -Theorem apply_morphism_compatibility_Left2Right: - forall In Out (m1 m2: function_type_of_morphism_signature In Out) - (args1 args2: product_of_arguments In), - make_compatibility_goal_aux _ _ m1 m2 -> - relation_of_product_of_arguments Left2Right _ args1 args2 -> - directed_relation_of_relation_class Left2Right _ - (apply_morphism _ _ m1 args1) - (apply_morphism _ _ m2 args2). -Proof. - induction In; intros. - simpl in m1, m2, args1, args2, H0 |- *. - destruct a; simpl in H; hnf in H0. - apply H; exact H0. - destruct v; simpl in H0; apply H; exact H0. - apply H; exact H0. - destruct v; simpl in H0; apply H; exact H0. - rewrite H0; apply H; exact H0. - - simpl in m1, m2, args1, args2, H0 |- *. - destruct args1; destruct args2; simpl. - destruct H0. - simpl in H. - destruct a; simpl in H. - apply IHIn. - apply H; exact H0. - exact H1. - destruct v. - apply IHIn. - apply H; exact H0. - exact H1. - apply IHIn. - apply H; exact H0. - exact H1. - apply IHIn. - apply H; exact H0. - exact H1. - apply IHIn. - destruct v; simpl in H, H0; apply H; exact H0. - exact H1. - rewrite H0; apply IHIn. - apply H. - exact H1. -Qed. - -Definition interp : - forall Hole dir Out dir', carrier_of_relation_class Hole -> - Morphism_Context Hole dir Out dir' -> carrier_of_relation_class Out. - intros Hole dir Out dir' H t. - elim t using - (@Morphism_Context_rect2 Hole dir (fun S _ _ => carrier_of_relation_class S) - (fun _ L fcl => product_of_arguments L)); - intros. - exact (apply_morphism _ _ (Function m) X). - exact H. - exact c. - exact x. - simpl; - rewrite <- - (about_carrier_of_relation_class_and_relation_class_of_argument_class S); - exact X. - split. - rewrite <- - (about_carrier_of_relation_class_and_relation_class_of_argument_class S); - exact X. - exact X0. -Defined. - -(* CSC: interp and interp_relation_class_list should be mutually defined, since - the proof term of each one contains the proof term of the other one. However - I cannot do that interactively (I should write the Fix by hand) *) -Definition interp_relation_class_list : - forall Hole dir dir' (L: Arguments), carrier_of_relation_class Hole -> - Morphism_Context_List Hole dir dir' L -> product_of_arguments L. - intros Hole dir dir' L H t. - elim t using - (@Morphism_Context_List_rect2 Hole dir (fun S _ _ => carrier_of_relation_class S) - (fun _ L fcl => product_of_arguments L)); - intros. - exact (apply_morphism _ _ (Function m) X). - exact H. - exact c. - exact x. - simpl; - rewrite <- - (about_carrier_of_relation_class_and_relation_class_of_argument_class S); - exact X. - split. - rewrite <- - (about_carrier_of_relation_class_and_relation_class_of_argument_class S); - exact X. - exact X0. -Defined. - -Theorem setoid_rewrite: - forall Hole dir Out dir' (E1 E2: carrier_of_relation_class Hole) - (E: Morphism_Context Hole dir Out dir'), - (directed_relation_of_relation_class dir Hole E1 E2) -> - (directed_relation_of_relation_class dir' Out (interp E1 E) (interp E2 E)). -Proof. - intros. - elim E using - (@Morphism_Context_rect2 Hole dir - (fun S dir'' E => directed_relation_of_relation_class dir'' S (interp E1 E) (interp E2 E)) - (fun dir'' L fcl => - relation_of_product_of_arguments dir'' _ - (interp_relation_class_list E1 fcl) - (interp_relation_class_list E2 fcl))); intros. - change (directed_relation_of_relation_class dir'0 Out0 - (apply_morphism _ _ (Function m) (interp_relation_class_list E1 m0)) - (apply_morphism _ _ (Function m) (interp_relation_class_list E2 m0))). - destruct dir'0. - apply apply_morphism_compatibility_Left2Right. - exact (Compat m). - exact H0. - apply apply_morphism_compatibility_Right2Left. - exact (Compat m). - exact H0. - - exact H. - - unfold interp, Morphism_Context_rect2. - (* CSC: reflexivity used here *) - destruct S; destruct dir'0; simpl; (apply r || reflexivity). - - destruct dir'0; exact r. - - destruct S; unfold directed_relation_of_argument_class; simpl in H0 |- *; - unfold get_rewrite_direction; simpl. - destruct dir'0; destruct dir''; - (exact H0 || - unfold directed_relation_of_argument_class; simpl; apply s; exact H0). - (* the following mess with generalize/clear/intros is to help Coq resolving *) - (* second order unification problems. *) - generalize m c H0; clear H0 m c; inversion c; - generalize m c; clear m c; rewrite <- H1; rewrite <- H2; intros; - (exact H3 || rewrite (opposite_direction_idempotent dir'0); apply H3). - destruct dir'0; destruct dir''; - (exact H0 || - unfold directed_relation_of_argument_class; simpl; apply s; exact H0). - (* the following mess with generalize/clear/intros is to help Coq resolving *) - (* second order unification problems. *) - generalize m c H0; clear H0 m c; inversion c; - generalize m c; clear m c; rewrite <- H1; rewrite <- H2; intros; - (exact H3 || rewrite (opposite_direction_idempotent dir'0); apply H3). - destruct dir'0; destruct dir''; (exact H0 || hnf; symmetry; exact H0). - - change - (directed_relation_of_argument_class (get_rewrite_direction dir'' S) S - (eq_rect _ (fun T : Type => T) (interp E1 m) _ - (about_carrier_of_relation_class_and_relation_class_of_argument_class S)) - (eq_rect _ (fun T : Type => T) (interp E2 m) _ - (about_carrier_of_relation_class_and_relation_class_of_argument_class S)) /\ - relation_of_product_of_arguments dir'' _ - (interp_relation_class_list E1 m0) (interp_relation_class_list E2 m0)). - split. - clear m0 H1; destruct S; simpl in H0 |- *; unfold get_rewrite_direction; simpl. - destruct dir''; destruct dir'0; (exact H0 || hnf; apply s; exact H0). - inversion c. - rewrite <- H3; exact H0. - rewrite (opposite_direction_idempotent dir'0); exact H0. - destruct dir''; destruct dir'0; (exact H0 || hnf; apply s; exact H0). - inversion c. - rewrite <- H3; exact H0. - rewrite (opposite_direction_idempotent dir'0); exact H0. - destruct dir''; destruct dir'0; (exact H0 || hnf; symmetry; exact H0). - exact H1. - Qed. - -(** * Miscelenous *) - -(** For backwark compatibility *) +(*i $Id: Setoid.v 10765 2008-04-08 16:15:23Z msozeau $: i*) -Record Setoid_Theory (A: Type) (Aeq: relation A) : Prop := - { Seq_refl : forall x:A, Aeq x x; - Seq_sym : forall x y:A, Aeq x y -> Aeq y x; - Seq_trans : forall x y z:A, Aeq x y -> Aeq y z -> Aeq x z }. +Require Export Coq.Classes.SetoidTactics. -Implicit Arguments Setoid_Theory []. -Implicit Arguments Seq_refl []. -Implicit Arguments Seq_sym []. -Implicit Arguments Seq_trans []. +(** For backward compatibility *) +Definition Setoid_Theory := @Equivalence. +Definition Build_Setoid_Theory := @Build_Equivalence. +Definition Seq_refl A Aeq (s : Setoid_Theory A Aeq) : forall x:A, Aeq x x := + Eval compute in reflexivity. +Definition Seq_sym A Aeq (s : Setoid_Theory A Aeq) : forall x y:A, Aeq x y -> Aeq y x := + Eval compute in symmetry. +Definition Seq_trans A Aeq (s : Setoid_Theory A Aeq) : forall x y z:A, Aeq x y -> Aeq y z -> Aeq x z := + Eval compute in transitivity. (** Some tactics for manipulating Setoid Theory not officially declared as Setoid. *) diff --git a/theories/Setoids/Setoid_Prop.v b/theories/Setoids/Setoid_Prop.v new file mode 100644 index 00000000..7300937e --- /dev/null +++ b/theories/Setoids/Setoid_Prop.v @@ -0,0 +1,79 @@ + +(************************************************************************) +(* 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: Setoid_Prop.v 10739 2008-04-01 14:45:20Z herbelin $: i*) + +Require Import Setoid_tac. + +(** * A few examples on [iff] *) + +(** [iff] as a relation *) + +Add Relation Prop iff + reflexivity proved by iff_refl + symmetry proved by iff_sym + transitivity proved by iff_trans +as iff_relation. + +(** [impl] as a relation *) + +Theorem impl_trans: transitive _ impl. +Proof. + hnf; unfold impl; tauto. +Qed. + +Add Relation Prop impl + reflexivity proved by impl_refl + transitivity proved by impl_trans +as impl_relation. + +(** [impl] is a morphism *) + +Add Morphism impl with signature iff ==> iff ==> iff as Impl_Morphism. +Proof. + unfold impl; tauto. +Qed. + +(** [and] is a morphism *) + +Add Morphism and with signature iff ==> iff ==> iff as And_Morphism. + tauto. +Qed. + +(** [or] is a morphism *) + +Add Morphism or with signature iff ==> iff ==> iff as Or_Morphism. +Proof. + tauto. +Qed. + +(** [not] is a morphism *) + +Add Morphism not with signature iff ==> iff as Not_Morphism. +Proof. + tauto. +Qed. + +(** The same examples on [impl] *) + +Add Morphism and with signature impl ++> impl ++> impl as And_Morphism2. +Proof. + unfold impl; tauto. +Qed. + +Add Morphism or with signature impl ++> impl ++> impl as Or_Morphism2. +Proof. + unfold impl; tauto. +Qed. + +Add Morphism not with signature impl --> impl as Not_Morphism2. +Proof. + unfold impl; tauto. +Qed. + diff --git a/theories/Setoids/Setoid_tac.v b/theories/Setoids/Setoid_tac.v new file mode 100644 index 00000000..cdc4eafe --- /dev/null +++ b/theories/Setoids/Setoid_tac.v @@ -0,0 +1,595 @@ +(************************************************************************) +(* 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: Setoid_tac.v 10739 2008-04-01 14:45:20Z herbelin $ i*) + +Require Export Relation_Definitions. + +Set Implicit Arguments. + +(** * Definitions of [Relation_Class] and n-ary [Morphism_Theory] *) + +(* X will be used to distinguish covariant arguments whose type is an *) +(* Asymmetric* relation from contravariant arguments of the same type *) +Inductive X_Relation_Class (X: Type) : Type := + SymmetricReflexive : + forall A Aeq, symmetric A Aeq -> reflexive _ Aeq -> X_Relation_Class X + | AsymmetricReflexive : X -> forall A Aeq, reflexive A Aeq -> X_Relation_Class X + | SymmetricAreflexive : forall A Aeq, symmetric A Aeq -> X_Relation_Class X + | AsymmetricAreflexive : X -> forall A (Aeq : relation A), X_Relation_Class X + | Leibniz : Type -> X_Relation_Class X. + +Inductive variance : Set := + Covariant + | Contravariant. + +Definition Argument_Class := X_Relation_Class variance. +Definition Relation_Class := X_Relation_Class unit. + +Inductive Reflexive_Relation_Class : Type := + RSymmetric : + forall A Aeq, symmetric A Aeq -> reflexive _ Aeq -> Reflexive_Relation_Class + | RAsymmetric : + forall A Aeq, reflexive A Aeq -> Reflexive_Relation_Class + | RLeibniz : Type -> Reflexive_Relation_Class. + +Inductive Areflexive_Relation_Class : Type := + | ASymmetric : forall A Aeq, symmetric A Aeq -> Areflexive_Relation_Class + | AAsymmetric : forall A (Aeq : relation A), Areflexive_Relation_Class. + +Implicit Type Hole Out: Relation_Class. + +Definition relation_class_of_argument_class : Argument_Class -> Relation_Class. + destruct 1. + exact (SymmetricReflexive _ s r). + exact (AsymmetricReflexive tt r). + exact (SymmetricAreflexive _ s). + exact (AsymmetricAreflexive tt Aeq). + exact (Leibniz _ T). +Defined. + +Definition carrier_of_relation_class : forall X, X_Relation_Class X -> Type. + destruct 1. + exact A. + exact A. + exact A. + exact A. + exact T. +Defined. + +Definition relation_of_relation_class : + forall X R, @carrier_of_relation_class X R -> carrier_of_relation_class R -> Prop. + destruct R. + exact Aeq. + exact Aeq. + exact Aeq. + exact Aeq. + exact (@eq T). +Defined. + +Lemma about_carrier_of_relation_class_and_relation_class_of_argument_class : + forall R, + carrier_of_relation_class (relation_class_of_argument_class R) = + carrier_of_relation_class R. + destruct R; reflexivity. +Defined. + +Inductive nelistT (A : Type) : Type := + singl : A -> nelistT A + | necons : A -> nelistT A -> nelistT A. + +Definition Arguments := nelistT Argument_Class. + +Implicit Type In: Arguments. + +Definition function_type_of_morphism_signature : + Arguments -> Relation_Class -> Type. + intros In Out. + induction In. + exact (carrier_of_relation_class a -> carrier_of_relation_class Out). + exact (carrier_of_relation_class a -> IHIn). +Defined. + +Definition make_compatibility_goal_aux: + forall In Out + (f g: function_type_of_morphism_signature In Out), Prop. + intros; induction In; simpl in f, g. + induction a; simpl in f, g. + exact (forall x1 x2, Aeq x1 x2 -> relation_of_relation_class Out (f x1) (g x2)). + destruct x. + exact (forall x1 x2, Aeq x1 x2 -> relation_of_relation_class Out (f x1) (g x2)). + exact (forall x1 x2, Aeq x2 x1 -> relation_of_relation_class Out (f x1) (g x2)). + exact (forall x1 x2, Aeq x1 x2 -> relation_of_relation_class Out (f x1) (g x2)). + destruct x. + exact (forall x1 x2, Aeq x1 x2 -> relation_of_relation_class Out (f x1) (g x2)). + exact (forall x1 x2, Aeq x2 x1 -> relation_of_relation_class Out (f x1) (g x2)). + exact (forall x, relation_of_relation_class Out (f x) (g x)). + induction a; simpl in f, g. + exact (forall x1 x2, Aeq x1 x2 -> IHIn (f x1) (g x2)). + destruct x. + exact (forall x1 x2, Aeq x1 x2 -> IHIn (f x1) (g x2)). + exact (forall x1 x2, Aeq x2 x1 -> IHIn (f x1) (g x2)). + exact (forall x1 x2, Aeq x1 x2 -> IHIn (f x1) (g x2)). + destruct x. + exact (forall x1 x2, Aeq x1 x2 -> IHIn (f x1) (g x2)). + exact (forall x1 x2, Aeq x2 x1 -> IHIn (f x1) (g x2)). + exact (forall x, IHIn (f x) (g x)). +Defined. + +Definition make_compatibility_goal := + (fun In Out f => make_compatibility_goal_aux In Out f f). + +Record Morphism_Theory In Out : Type := + { Function : function_type_of_morphism_signature In Out; + Compat : make_compatibility_goal In Out Function }. + + +(** The [iff] relation class *) + +Definition Iff_Relation_Class : Relation_Class. + eapply (@SymmetricReflexive unit _ iff). + exact iff_sym. + exact iff_refl. +Defined. + +(** The [impl] relation class *) + +Definition impl (A B: Prop) := A -> B. + +Theorem impl_refl: reflexive _ impl. +Proof. + hnf; unfold impl; tauto. +Qed. + +Definition Impl_Relation_Class : Relation_Class. + eapply (@AsymmetricReflexive unit tt _ impl). + exact impl_refl. +Defined. + +(** Every function is a morphism from Leibniz+ to Leibniz *) + +Definition list_of_Leibniz_of_list_of_types: nelistT Type -> Arguments. + induction 1. + exact (singl (Leibniz _ a)). + exact (necons (Leibniz _ a) IHX). +Defined. + +Definition morphism_theory_of_function : + forall (In: nelistT Type) (Out: Type), + let In' := list_of_Leibniz_of_list_of_types In in + let Out' := Leibniz _ Out in + function_type_of_morphism_signature In' Out' -> + Morphism_Theory In' Out'. + intros. + exists X. + induction In; unfold make_compatibility_goal; simpl. + reflexivity. + intro; apply (IHIn (X x)). +Defined. + +(** Every predicate is a morphism from Leibniz+ to Iff_Relation_Class *) + +Definition morphism_theory_of_predicate : + forall (In: nelistT Type), + let In' := list_of_Leibniz_of_list_of_types In in + function_type_of_morphism_signature In' Iff_Relation_Class -> + Morphism_Theory In' Iff_Relation_Class. + intros. + exists X. + induction In; unfold make_compatibility_goal; simpl. + intro; apply iff_refl. + intro; apply (IHIn (X x)). +Defined. + +(** * Utility functions to prove that every transitive relation is a morphism *) + +Definition equality_morphism_of_symmetric_areflexive_transitive_relation: + forall (A: Type)(Aeq: relation A)(sym: symmetric _ Aeq)(trans: transitive _ Aeq), + let ASetoidClass := SymmetricAreflexive _ sym in + (Morphism_Theory (necons ASetoidClass (singl ASetoidClass)) Iff_Relation_Class). + intros. + exists Aeq. + unfold make_compatibility_goal; simpl; split; eauto. +Defined. + +Definition equality_morphism_of_symmetric_reflexive_transitive_relation: + forall (A: Type)(Aeq: relation A)(refl: reflexive _ Aeq)(sym: symmetric _ Aeq) + (trans: transitive _ Aeq), let ASetoidClass := SymmetricReflexive _ sym refl in + (Morphism_Theory (necons ASetoidClass (singl ASetoidClass)) Iff_Relation_Class). + intros. + exists Aeq. + unfold make_compatibility_goal; simpl; split; eauto. +Defined. + +Definition equality_morphism_of_asymmetric_areflexive_transitive_relation: + forall (A: Type)(Aeq: relation A)(trans: transitive _ Aeq), + let ASetoidClass1 := AsymmetricAreflexive Contravariant Aeq in + let ASetoidClass2 := AsymmetricAreflexive Covariant Aeq in + (Morphism_Theory (necons ASetoidClass1 (singl ASetoidClass2)) Impl_Relation_Class). + intros. + exists Aeq. + unfold make_compatibility_goal; simpl; unfold impl; eauto. +Defined. + +Definition equality_morphism_of_asymmetric_reflexive_transitive_relation: + forall (A: Type)(Aeq: relation A)(refl: reflexive _ Aeq)(trans: transitive _ Aeq), + let ASetoidClass1 := AsymmetricReflexive Contravariant refl in + let ASetoidClass2 := AsymmetricReflexive Covariant refl in + (Morphism_Theory (necons ASetoidClass1 (singl ASetoidClass2)) Impl_Relation_Class). + intros. + exists Aeq. + unfold make_compatibility_goal; simpl; unfold impl; eauto. +Defined. + +(** * The CIC part of the reflexive tactic ([setoid_rewrite]) *) + +Inductive rewrite_direction : Type := + | Left2Right + | Right2Left. + +Implicit Type dir: rewrite_direction. + +Definition variance_of_argument_class : Argument_Class -> option variance. + destruct 1. + exact None. + exact (Some v). + exact None. + exact (Some v). + exact None. +Defined. + +Definition opposite_direction := + fun dir => + match dir with + | Left2Right => Right2Left + | Right2Left => Left2Right + end. + +Lemma opposite_direction_idempotent: + forall dir, (opposite_direction (opposite_direction dir)) = dir. +Proof. + destruct dir; reflexivity. +Qed. + +Inductive check_if_variance_is_respected : + option variance -> rewrite_direction -> rewrite_direction -> Prop := + | MSNone : forall dir dir', check_if_variance_is_respected None dir dir' + | MSCovariant : forall dir, check_if_variance_is_respected (Some Covariant) dir dir + | MSContravariant : + forall dir, + check_if_variance_is_respected (Some Contravariant) dir (opposite_direction dir). + +Definition relation_class_of_reflexive_relation_class: + Reflexive_Relation_Class -> Relation_Class. + induction 1. + exact (SymmetricReflexive _ s r). + exact (AsymmetricReflexive tt r). + exact (Leibniz _ T). +Defined. + +Definition relation_class_of_areflexive_relation_class: + Areflexive_Relation_Class -> Relation_Class. + induction 1. + exact (SymmetricAreflexive _ s). + exact (AsymmetricAreflexive tt Aeq). +Defined. + +Definition carrier_of_reflexive_relation_class := + fun R => carrier_of_relation_class (relation_class_of_reflexive_relation_class R). + +Definition carrier_of_areflexive_relation_class := + fun R => carrier_of_relation_class (relation_class_of_areflexive_relation_class R). + +Definition relation_of_areflexive_relation_class := + fun R => relation_of_relation_class (relation_class_of_areflexive_relation_class R). + +Inductive Morphism_Context Hole dir : Relation_Class -> rewrite_direction -> Type := + | App : + forall In Out dir', + Morphism_Theory In Out -> Morphism_Context_List Hole dir dir' In -> + Morphism_Context Hole dir Out dir' + | ToReplace : Morphism_Context Hole dir Hole dir + | ToKeep : + forall S dir', + carrier_of_reflexive_relation_class S -> + Morphism_Context Hole dir (relation_class_of_reflexive_relation_class S) dir' + | ProperElementToKeep : + forall S dir' (x: carrier_of_areflexive_relation_class S), + relation_of_areflexive_relation_class S x x -> + Morphism_Context Hole dir (relation_class_of_areflexive_relation_class S) dir' +with Morphism_Context_List Hole dir : + rewrite_direction -> Arguments -> Type +:= + fcl_singl : + forall S dir' dir'', + check_if_variance_is_respected (variance_of_argument_class S) dir' dir'' -> + Morphism_Context Hole dir (relation_class_of_argument_class S) dir' -> + Morphism_Context_List Hole dir dir'' (singl S) + | fcl_cons : + forall S L dir' dir'', + check_if_variance_is_respected (variance_of_argument_class S) dir' dir'' -> + Morphism_Context Hole dir (relation_class_of_argument_class S) dir' -> + Morphism_Context_List Hole dir dir'' L -> + Morphism_Context_List Hole dir dir'' (necons S L). + +Scheme Morphism_Context_rect2 := Induction for Morphism_Context Sort Type +with Morphism_Context_List_rect2 := Induction for Morphism_Context_List Sort Type. + +Definition product_of_arguments : Arguments -> Type. + induction 1. + exact (carrier_of_relation_class a). + exact (prod (carrier_of_relation_class a) IHX). +Defined. + +Definition get_rewrite_direction: rewrite_direction -> Argument_Class -> rewrite_direction. + intros dir R. + destruct (variance_of_argument_class R). + destruct v. + exact dir. (* covariant *) + exact (opposite_direction dir). (* contravariant *) + exact dir. (* symmetric relation *) +Defined. + +Definition directed_relation_of_relation_class: + forall dir (R: Relation_Class), + carrier_of_relation_class R -> carrier_of_relation_class R -> Prop. + destruct 1. + exact (@relation_of_relation_class unit). + intros; exact (relation_of_relation_class _ X0 X). +Defined. + +Definition directed_relation_of_argument_class: + forall dir (R: Argument_Class), + carrier_of_relation_class R -> carrier_of_relation_class R -> Prop. + intros dir R. + rewrite <- + (about_carrier_of_relation_class_and_relation_class_of_argument_class R). + exact (directed_relation_of_relation_class dir (relation_class_of_argument_class R)). +Defined. + + +Definition relation_of_product_of_arguments: + forall dir In, + product_of_arguments In -> product_of_arguments In -> Prop. + induction In. + simpl. + exact (directed_relation_of_argument_class (get_rewrite_direction dir a) a). + + simpl; intros. + destruct X; destruct X0. + apply and. + exact + (directed_relation_of_argument_class (get_rewrite_direction dir a) a c c0). + exact (IHIn p p0). +Defined. + +Definition apply_morphism: + forall In Out (m: function_type_of_morphism_signature In Out) + (args: product_of_arguments In), carrier_of_relation_class Out. + intros. + induction In. + exact (m args). + simpl in m, args. + destruct args. + exact (IHIn (m c) p). +Defined. + +Theorem apply_morphism_compatibility_Right2Left: + forall In Out (m1 m2: function_type_of_morphism_signature In Out) + (args1 args2: product_of_arguments In), + make_compatibility_goal_aux _ _ m1 m2 -> + relation_of_product_of_arguments Right2Left _ args1 args2 -> + directed_relation_of_relation_class Right2Left _ + (apply_morphism _ _ m2 args1) + (apply_morphism _ _ m1 args2). + induction In; intros. + simpl in m1, m2, args1, args2, H0 |- *. + destruct a; simpl in H; hnf in H0. + apply H; exact H0. + destruct v; simpl in H0; apply H; exact H0. + apply H; exact H0. + destruct v; simpl in H0; apply H; exact H0. + rewrite H0; apply H; exact H0. + + simpl in m1, m2, args1, args2, H0 |- *. + destruct args1; destruct args2; simpl. + destruct H0. + simpl in H. + destruct a; simpl in H. + apply IHIn. + apply H; exact H0. + exact H1. + destruct v. + apply IHIn. + apply H; exact H0. + exact H1. + apply IHIn. + apply H; exact H0. + exact H1. + apply IHIn. + apply H; exact H0. + exact H1. + destruct v. + apply IHIn. + apply H; exact H0. + exact H1. + apply IHIn. + apply H; exact H0. + exact H1. + rewrite H0; apply IHIn. + apply H. + exact H1. +Qed. + +Theorem apply_morphism_compatibility_Left2Right: + forall In Out (m1 m2: function_type_of_morphism_signature In Out) + (args1 args2: product_of_arguments In), + make_compatibility_goal_aux _ _ m1 m2 -> + relation_of_product_of_arguments Left2Right _ args1 args2 -> + directed_relation_of_relation_class Left2Right _ + (apply_morphism _ _ m1 args1) + (apply_morphism _ _ m2 args2). +Proof. + induction In; intros. + simpl in m1, m2, args1, args2, H0 |- *. + destruct a; simpl in H; hnf in H0. + apply H; exact H0. + destruct v; simpl in H0; apply H; exact H0. + apply H; exact H0. + destruct v; simpl in H0; apply H; exact H0. + rewrite H0; apply H; exact H0. + + simpl in m1, m2, args1, args2, H0 |- *. + destruct args1; destruct args2; simpl. + destruct H0. + simpl in H. + destruct a; simpl in H. + apply IHIn. + apply H; exact H0. + exact H1. + destruct v. + apply IHIn. + apply H; exact H0. + exact H1. + apply IHIn. + apply H; exact H0. + exact H1. + apply IHIn. + apply H; exact H0. + exact H1. + apply IHIn. + destruct v; simpl in H, H0; apply H; exact H0. + exact H1. + rewrite H0; apply IHIn. + apply H. + exact H1. +Qed. + +Definition interp : + forall Hole dir Out dir', carrier_of_relation_class Hole -> + Morphism_Context Hole dir Out dir' -> carrier_of_relation_class Out. + intros Hole dir Out dir' H t. + elim t using + (@Morphism_Context_rect2 Hole dir (fun S _ _ => carrier_of_relation_class S) + (fun _ L fcl => product_of_arguments L)); + intros. + exact (apply_morphism _ _ (Function m) X). + exact H. + exact c. + exact x. + simpl; + rewrite <- + (about_carrier_of_relation_class_and_relation_class_of_argument_class S); + exact X. + split. + rewrite <- + (about_carrier_of_relation_class_and_relation_class_of_argument_class S); + exact X. + exact X0. +Defined. + +(* CSC: interp and interp_relation_class_list should be mutually defined, since + the proof term of each one contains the proof term of the other one. However + I cannot do that interactively (I should write the Fix by hand) *) +Definition interp_relation_class_list : + forall Hole dir dir' (L: Arguments), carrier_of_relation_class Hole -> + Morphism_Context_List Hole dir dir' L -> product_of_arguments L. + intros Hole dir dir' L H t. + elim t using + (@Morphism_Context_List_rect2 Hole dir (fun S _ _ => carrier_of_relation_class S) + (fun _ L fcl => product_of_arguments L)); + intros. + exact (apply_morphism _ _ (Function m) X). + exact H. + exact c. + exact x. + simpl; + rewrite <- + (about_carrier_of_relation_class_and_relation_class_of_argument_class S); + exact X. + split. + rewrite <- + (about_carrier_of_relation_class_and_relation_class_of_argument_class S); + exact X. + exact X0. +Defined. + +Theorem setoid_rewrite: + forall Hole dir Out dir' (E1 E2: carrier_of_relation_class Hole) + (E: Morphism_Context Hole dir Out dir'), + (directed_relation_of_relation_class dir Hole E1 E2) -> + (directed_relation_of_relation_class dir' Out (interp E1 E) (interp E2 E)). +Proof. + intros. + elim E using + (@Morphism_Context_rect2 Hole dir + (fun S dir'' E => directed_relation_of_relation_class dir'' S (interp E1 E) (interp E2 E)) + (fun dir'' L fcl => + relation_of_product_of_arguments dir'' _ + (interp_relation_class_list E1 fcl) + (interp_relation_class_list E2 fcl))); intros. + change (directed_relation_of_relation_class dir'0 Out0 + (apply_morphism _ _ (Function m) (interp_relation_class_list E1 m0)) + (apply_morphism _ _ (Function m) (interp_relation_class_list E2 m0))). + destruct dir'0. + apply apply_morphism_compatibility_Left2Right. + exact (Compat m). + exact H0. + apply apply_morphism_compatibility_Right2Left. + exact (Compat m). + exact H0. + + exact H. + + unfold interp, Morphism_Context_rect2. + (* CSC: reflexivity used here *) + destruct S; destruct dir'0; simpl; (apply r || reflexivity). + + destruct dir'0; exact r. + + destruct S; unfold directed_relation_of_argument_class; simpl in H0 |- *; + unfold get_rewrite_direction; simpl. + destruct dir'0; destruct dir''; + (exact H0 || + unfold directed_relation_of_argument_class; simpl; apply s; exact H0). + (* the following mess with generalize/clear/intros is to help Coq resolving *) + (* second order unification problems. *) + generalize m c H0; clear H0 m c; inversion c; + generalize m c; clear m c; rewrite <- H1; rewrite <- H2; intros; + (exact H3 || rewrite (opposite_direction_idempotent dir'0); apply H3). + destruct dir'0; destruct dir''; + (exact H0 || + unfold directed_relation_of_argument_class; simpl; apply s; exact H0). + (* the following mess with generalize/clear/intros is to help Coq resolving *) + (* second order unification problems. *) + generalize m c H0; clear H0 m c; inversion c; + generalize m c; clear m c; rewrite <- H1; rewrite <- H2; intros; + (exact H3 || rewrite (opposite_direction_idempotent dir'0); apply H3). + destruct dir'0; destruct dir''; (exact H0 || hnf; symmetry; exact H0). + + change + (directed_relation_of_argument_class (get_rewrite_direction dir'' S) S + (eq_rect _ (fun T : Type => T) (interp E1 m) _ + (about_carrier_of_relation_class_and_relation_class_of_argument_class S)) + (eq_rect _ (fun T : Type => T) (interp E2 m) _ + (about_carrier_of_relation_class_and_relation_class_of_argument_class S)) /\ + relation_of_product_of_arguments dir'' _ + (interp_relation_class_list E1 m0) (interp_relation_class_list E2 m0)). + split. + clear m0 H1; destruct S; simpl in H0 |- *; unfold get_rewrite_direction; simpl. + destruct dir''; destruct dir'0; (exact H0 || hnf; apply s; exact H0). + inversion c. + rewrite <- H3; exact H0. + rewrite (opposite_direction_idempotent dir'0); exact H0. + destruct dir''; destruct dir'0; (exact H0 || hnf; apply s; exact H0). + inversion c. + rewrite <- H3; exact H0. + rewrite (opposite_direction_idempotent dir'0); exact H0. + destruct dir''; destruct dir'0; (exact H0 || hnf; symmetry; exact H0). + exact H1. + Qed. diff --git a/theories/Sets/Infinite_sets.v b/theories/Sets/Infinite_sets.v index 47554ac4..ae2143c8 100644 --- a/theories/Sets/Infinite_sets.v +++ b/theories/Sets/Infinite_sets.v @@ -24,7 +24,7 @@ (* in Summer 1995. Several developments by E. Ledinot were an inspiration. *) (****************************************************************************) -(*i $Id: Infinite_sets.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Infinite_sets.v 10637 2008-03-07 23:52:56Z letouzey $ i*) Require Export Finite_sets. Require Export Constructive_sets. @@ -162,7 +162,7 @@ Section Infinite_sets. generalize (H'3 x). intro H'4; lapply H'4; [ intro H'8; try exact H'8; clear H'4 | clear H'4 ]; auto with sets. - specialize 5Im_inv with (U := U) (V := V) (X := A) (f := f) (y := x); + specialize Im_inv with (U := U) (V := V) (X := A) (f := f) (y := x); intro H'11; lapply H'11; [ intro H'13; elim H'11; clear H'11 | clear H'11 ]; auto with sets. intros x1 H'4; try assumption. diff --git a/theories/Sets/Integers.v b/theories/Sets/Integers.v index c969ad9c..1786edf1 100644 --- a/theories/Sets/Integers.v +++ b/theories/Sets/Integers.v @@ -24,7 +24,7 @@ (* in Summer 1995. Several developments by E. Ledinot were an inspiration. *) (****************************************************************************) -(*i $Id: Integers.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Integers.v 10637 2008-03-07 23:52:56Z letouzey $ i*) Require Export Finite_sets. Require Export Constructive_sets. @@ -87,7 +87,7 @@ Section Integers_sect. apply Totally_ordered_definition. simpl in |- *. intros H' x y H'0. - specialize 2le_or_lt with (n := x) (m := y); intro H'2; elim H'2. + elim le_or_lt with (n := x) (m := y). intro H'1; left; auto with sets arith. intro H'1; right. cut (y <= x); auto with sets arith. @@ -142,8 +142,8 @@ Section Integers_sect. elim H'0; intros H'1 H'2. cut (In nat Integers (S x)). intro H'3. - specialize 1H'2 with (y := S x); intro H'4; lapply H'4; - [ intro H'5; clear H'4 | try assumption; clear H'4 ]. + specialize H'2 with (y := S x); lapply H'2; + [ intro H'5; clear H'2 | try assumption; clear H'2 ]. simpl in H'5. absurd (S x <= x); auto with arith. apply triv_nat. diff --git a/theories/Sets/Multiset.v b/theories/Sets/Multiset.v index 7084a82d..d2bff488 100644 --- a/theories/Sets/Multiset.v +++ b/theories/Sets/Multiset.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Multiset.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Multiset.v 10616 2008-03-04 17:33:35Z letouzey $ i*) (* G. Huet 1-9-95 *) @@ -16,11 +16,11 @@ Set Implicit Arguments. Section multiset_defs. - Variable A : Set. + Variable A : Type. Variable eqA : A -> A -> Prop. Hypothesis Aeq_dec : forall x y:A, {eqA x y} + {~ eqA x y}. - Inductive multiset : Set := + Inductive multiset : Type := Bag : (A -> nat) -> multiset. Definition EmptyBag := Bag (fun a:A => 0). diff --git a/theories/Sets/Permut.v b/theories/Sets/Permut.v index a7c3db3a..4380f10c 100644 --- a/theories/Sets/Permut.v +++ b/theories/Sets/Permut.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Permut.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Permut.v 10616 2008-03-04 17:33:35Z letouzey $ i*) (* G. Huet 1-9-95 *) @@ -15,7 +15,7 @@ Section Axiomatisation. - Variable U : Set. + Variable U : Type. Variable op : U -> U -> U. Variable cong : U -> U -> Prop. diff --git a/theories/Sets/Powerset_Classical_facts.v b/theories/Sets/Powerset_Classical_facts.v index 47857705..34c49409 100644 --- a/theories/Sets/Powerset_Classical_facts.v +++ b/theories/Sets/Powerset_Classical_facts.v @@ -24,7 +24,7 @@ (* in Summer 1995. Several developments by E. Ledinot were an inspiration. *) (****************************************************************************) -(*i $Id: Powerset_Classical_facts.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Powerset_Classical_facts.v 10855 2008-04-27 11:16:15Z msozeau $ i*) Require Export Ensembles. Require Export Constructive_sets. diff --git a/theories/Sets/Relations_2_facts.v b/theories/Sets/Relations_2_facts.v index 3291f3ee..2374c2bf 100644 --- a/theories/Sets/Relations_2_facts.v +++ b/theories/Sets/Relations_2_facts.v @@ -24,7 +24,7 @@ (* in Summer 1995. Several developments by E. Ledinot were an inspiration. *) (****************************************************************************) -(*i $Id: Relations_2_facts.v 8642 2006-03-17 10:09:02Z notin $ i*) +(*i $Id: Relations_2_facts.v 10637 2008-03-07 23:52:56Z letouzey $ i*) Require Export Relations_1. Require Export Relations_1_facts. @@ -140,10 +140,10 @@ intros U R H' x b H'0; elim H'0. intros x0 a H'1; exists a; auto with sets. intros x0 y z H'1 H'2 H'3 a H'4. red in H'. -specialize 3H' with (x := x0) (a := a) (b := y); intro H'7; lapply H'7; +specialize H' with (x := x0) (a := a) (b := y); lapply H'; [ intro H'8; lapply H'8; - [ intro H'9; try exact H'9; clear H'8 H'7 | clear H'8 H'7 ] - | clear H'7 ]; auto with sets. + [ intro H'9; try exact H'9; clear H'8 H' | clear H'8 H' ] + | clear H' ]; auto with sets. elim H'9. intros t H'5; elim H'5; intros H'6 H'7; try exact H'6; clear H'5. elim (H'3 t); auto with sets. diff --git a/theories/Sorting/Heap.v b/theories/Sorting/Heap.v index e1e026f5..fe7902aa 100644 --- a/theories/Sorting/Heap.v +++ b/theories/Sorting/Heap.v @@ -6,18 +6,13 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Heap.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Heap.v 10698 2008-03-19 18:46:59Z letouzey $ i*) (** A development of Treesort on Heap trees *) (* G. Huet 1-9-95 uses Multiset *) -Require Import List. -Require Import Multiset. -Require Import Permutation. -Require Import Relations. -Require Import Sorting. - +Require Import List Multiset Permutation Relations Sorting. Section defs. @@ -25,7 +20,7 @@ Section defs. (** ** Definition of trees over an ordered set *) - Variable A : Set. + Variable A : Type. Variable leA : relation A. Variable eqA : relation A. @@ -43,7 +38,7 @@ Section defs. Let emptyBag := EmptyBag A. Let singletonBag := SingletonBag _ eqA_dec. - Inductive Tree : Set := + Inductive Tree := | Tree_Leaf : Tree | Tree_Node : A -> Tree -> Tree -> Tree. @@ -87,6 +82,23 @@ Section defs. Qed. (* This lemma ought to be generated automatically by the Inversion tools *) + Lemma is_heap_rect : + forall P:Tree -> Type, + P Tree_Leaf -> + (forall (a:A) (T1 T2:Tree), + leA_Tree a T1 -> + leA_Tree a T2 -> + is_heap T1 -> P T1 -> is_heap T2 -> P T2 -> P (Tree_Node a T1 T2)) -> + forall T:Tree, is_heap T -> P T. + Proof. + simple induction T; auto with datatypes. + intros a G PG D PD PN. + elim (invert_heap a G D); auto with datatypes. + intros H1 H2; elim H2; intros H3 H4; elim H4; intros. + apply X0; auto with datatypes. + Qed. + + (* This lemma ought to be generated automatically by the Inversion tools *) Lemma is_heap_rec : forall P:Tree -> Set, P Tree_Leaf -> @@ -100,7 +112,7 @@ Section defs. intros a G PG D PD PN. elim (invert_heap a G D); auto with datatypes. intros H1 H2; elim H2; intros H3 H4; elim H4; intros. - apply H0; auto with datatypes. + apply X; auto with datatypes. Qed. Lemma low_trans : @@ -136,7 +148,7 @@ Section defs. (** ** Specification of heap insertion *) - Inductive insert_spec (a:A) (T:Tree) : Set := + Inductive insert_spec (a:A) (T:Tree) : Type := insert_exist : forall T1:Tree, is_heap T1 -> @@ -152,11 +164,11 @@ Section defs. auto using node_is_heap, nil_is_heap, leA_Tree_Leaf with datatypes. simpl in |- *; unfold meq, munion in |- *; auto using node_is_heap with datatypes. elim (leA_dec a a0); intros. - elim (H3 a0); intros. + elim (X a0); intros. apply insert_exist with (Tree_Node a T2 T0); auto using node_is_heap, nil_is_heap, leA_Tree_Leaf with datatypes. simpl in |- *; apply treesort_twist1; trivial with datatypes. - elim (H3 a); intros T3 HeapT3 ConT3 LeA. + elim (X a); intros T3 HeapT3 ConT3 LeA. apply insert_exist with (Tree_Node a0 T2 T3); auto using node_is_heap, nil_is_heap, leA_Tree_Leaf with datatypes. apply node_is_heap; auto using node_is_heap, nil_is_heap, leA_Tree_Leaf with datatypes. @@ -169,7 +181,7 @@ Section defs. (** ** Building a heap from a list *) - Inductive build_heap (l:list A) : Set := + Inductive build_heap (l:list A) : Type := heap_exist : forall T:Tree, is_heap T -> @@ -193,7 +205,7 @@ Section defs. (** ** Building the sorted list *) - Inductive flat_spec (T:Tree) : Set := + Inductive flat_spec (T:Tree) : Type := flat_exist : forall l:list A, sort leA l -> @@ -204,7 +216,7 @@ Section defs. Proof. intros T h; elim h; intros. apply flat_exist with (nil (A:=A)); auto with datatypes. - elim H2; intros l1 s1 i1 m1; elim H4; intros l2 s2 i2 m2. + elim X; intros l1 s1 i1 m1; elim X0; intros l2 s2 i2 m2. elim (merge _ leA_dec eqA_dec s1 s2); intros. apply flat_exist with (a :: l); simpl in |- *; auto with datatypes. apply meq_trans with diff --git a/theories/Sorting/PermutEq.v b/theories/Sorting/PermutEq.v index f4986198..084aae92 100644 --- a/theories/Sorting/PermutEq.v +++ b/theories/Sorting/PermutEq.v @@ -6,14 +6,9 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: PermutEq.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: PermutEq.v 10739 2008-04-01 14:45:20Z herbelin $ i*) -Require Import Omega. -Require Import Relations. -Require Import Setoid. -Require Import List. -Require Import Multiset. -Require Import Permutation. +Require Import Omega Relations Setoid List Multiset Permutation. Set Implicit Arguments. @@ -25,7 +20,7 @@ Set Implicit Arguments. Section Perm. - Variable A : Set. + Variable A : Type. Hypothesis eq_dec : forall x y:A, {x=y} + {~ x=y}. Notation permutation := (permutation _ eq_dec). @@ -214,7 +209,7 @@ Section Perm. apply permut_remove_hd with a; auto. Qed. - Variable B : Set. + Variable B : Type. Variable eqB_dec : forall x y:B, { x=y }+{ ~x=y }. (** Permutation is compatible with map. *) diff --git a/theories/Sorting/PermutSetoid.v b/theories/Sorting/PermutSetoid.v index 65369a01..c3888cfa 100644 --- a/theories/Sorting/PermutSetoid.v +++ b/theories/Sorting/PermutSetoid.v @@ -6,14 +6,9 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: PermutSetoid.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: PermutSetoid.v 10739 2008-04-01 14:45:20Z herbelin $ i*) -Require Import Omega. -Require Import Relations. -Require Import List. -Require Import Multiset. -Require Import Permutation. -Require Import SetoidList. +Require Import Omega Relations Multiset Permutation SetoidList. Set Implicit Arguments. @@ -23,7 +18,7 @@ Set Implicit Arguments. Section Perm. -Variable A : Set. +Variable A : Type. Variable eqA : relation A. Hypothesis eqA_dec : forall x y:A, {eqA x y} + {~ eqA x y}. @@ -81,7 +76,7 @@ Proof. rewrite IHl in H1. intros; destruct (eqA_dec a a0) as [H2|H2]; simpl; auto. rewrite multiplicity_InA_O; auto. - swap H0. + contradict H0. apply InA_eqA with a0; auto. intros; constructor. rewrite multiplicity_InA. @@ -185,9 +180,9 @@ Proof. destruct H2; apply eqA_trans with a; auto. Qed. -Lemma NoDupA_eqlistA_permut : +Lemma NoDupA_equivlistA_permut : forall l l', NoDupA eqA l -> NoDupA eqA l' -> - eqlistA eqA l l' -> permutation l l'. + equivlistA eqA l l' -> permutation l l'. Proof. intros. red; unfold meq; intros. @@ -198,7 +193,7 @@ Proof. Qed. -Variable B : Set. +Variable B : Type. Variable eqB : B->B->Prop. Variable eqB_dec : forall x y:B, { eqB x y }+{ ~eqB x y }. Variable eqB_trans : forall x y z, eqB x y -> eqB y z -> eqB x z. diff --git a/theories/Sorting/Permutation.v b/theories/Sorting/Permutation.v index 3ff026c2..82294b70 100644 --- a/theories/Sorting/Permutation.v +++ b/theories/Sorting/Permutation.v @@ -6,12 +6,9 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Permutation.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Permutation.v 10698 2008-03-19 18:46:59Z letouzey $ i*) -Require Import Relations. -Require Import List. -Require Import Multiset. -Require Import Arith. +Require Import Relations List Multiset Arith. (** This file define a notion of permutation for lists, based on multisets: there exists a permutation between two lists iff every elements have @@ -38,7 +35,7 @@ Section defs. (** * From lists to multisets *) - Variable A : Set. + Variable A : Type. Variable eqA : relation A. Hypothesis eqA_dec : forall x y:A, {eqA x y} + {~ eqA x y}. diff --git a/theories/Sorting/Sorting.v b/theories/Sorting/Sorting.v index f895d79e..aed8cd15 100644 --- a/theories/Sorting/Sorting.v +++ b/theories/Sorting/Sorting.v @@ -6,18 +6,15 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Sorting.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Sorting.v 10698 2008-03-19 18:46:59Z letouzey $ i*) -Require Import List. -Require Import Multiset. -Require Import Permutation. -Require Import Relations. +Require Import List Multiset Permutation Relations. Set Implicit Arguments. Section defs. - Variable A : Set. + Variable A : Type. Variable leA : relation A. Variable eqA : relation A. @@ -59,6 +56,16 @@ Section defs. intros; inversion H; auto with datatypes. Qed. + Lemma sort_rect : + forall P:list A -> Type, + P nil -> + (forall (a:A) (l:list A), sort l -> P l -> lelistA a l -> P (a :: l)) -> + forall y:list A, sort y -> P y. + Proof. + simple induction y; auto with datatypes. + intros; elim (sort_inv (a:=a) (l:=l)); auto with datatypes. + Qed. + Lemma sort_rec : forall P:list A -> Set, P nil -> @@ -71,7 +78,7 @@ Section defs. (** * Merging two sorted lists *) - Inductive merge_lem (l1 l2:list A) : Set := + Inductive merge_lem (l1 l2:list A) : Type := merge_exist : forall l:list A, sort l -> @@ -85,7 +92,7 @@ Section defs. Proof. simple induction 1; intros. apply merge_exist with l2; auto with datatypes. - elim H3; intros. + elim H2; intros. apply merge_exist with (a :: l); simpl in |- *; auto using cons_sort with datatypes. elim (leA_dec a a0); intros. @@ -104,7 +111,7 @@ Section defs. apply lelistA_inv with l; trivial with datatypes. (* 2 (leA a0 a) *) - elim H5; simpl in |- *; intros. + elim X0; simpl in |- *; intros. apply merge_exist with (a0 :: l3); simpl in |- *; auto using cons_sort, cons_leA with datatypes. apply meq_trans with diff --git a/theories/Strings/String.v b/theories/Strings/String.v index f2c58364..53260480 100644 --- a/theories/Strings/String.v +++ b/theories/Strings/String.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: String.v 8026 2006-02-11 19:40:49Z herbelin $ *) +(* $Id: String.v 10855 2008-04-27 11:16:15Z msozeau $ *) (** Contributed by Laurent Théry (INRIA); Adapted to Coq V8 by the Coq Development Team *) @@ -110,8 +110,8 @@ Proof. intros s1; elim s1; simpl in |- *; auto. intros s2 n; rewrite plus_comm; simpl in |- *; auto. intros a s1' Rec s2 n; case n; simpl in |- *; auto. -generalize (Rec s2 0); simpl in |- *; auto. -intros n0; rewrite <- Plus.plus_Snm_nSm; auto. +generalize (Rec s2 0); simpl in |- *; auto. intros. +rewrite <- Plus.plus_Snm_nSm; auto. Qed. (** *** Substrings *) diff --git a/theories/Unicode/Utf8.v b/theories/Unicode/Utf8.v new file mode 100644 index 00000000..32b892b6 --- /dev/null +++ b/theories/Unicode/Utf8.v @@ -0,0 +1,60 @@ +(* -*- coding:utf-8 -* *) +(************************************************************************) +(* 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 *) +(************************************************************************) + +(* Logic *) +Notation "∀ x , P" := (forall x , P) + (at level 200, x ident, right associativity) : type_scope. +Notation "∀ x y , P" := (forall x y , P) + (at level 200, x ident, y ident, right associativity) : type_scope. +Notation "∀ x y z , P" := (forall x y z , P) + (at level 200, x ident, y ident, z ident, right associativity) : type_scope. +Notation "∀ x y z u , P" := (forall x y z u , P) + (at level 200, x ident, y ident, z ident, u ident, right associativity) + : type_scope. +Notation "∀ x : t , P" := (forall x : t , P) + (at level 200, x ident, right associativity) : type_scope. +Notation "∀ x y : t , P" := (forall x y : t , P) + (at level 200, x ident, y ident, right associativity) : type_scope. +Notation "∀ x y z : t , P" := (forall x y z : t , P) + (at level 200, x ident, y ident, z ident, right associativity) : type_scope. +Notation "∀ x y z u : t , P" := (forall x y z u : t , P) + (at level 200, x ident, y ident, z ident, u ident, right associativity) + : type_scope. + +Notation "∃ x , P" := (exists x , P) + (at level 200, x ident, right associativity) : type_scope. +Notation "∃ x : t , P" := (exists x : t, P) + (at level 200, x ident, right associativity) : type_scope. + +Notation "x ∨ y" := (x \/ y) (at level 85, right associativity) : type_scope. +Notation "x ∧ y" := (x /\ y) (at level 80, right associativity) : type_scope. +Notation "x → y" := (x -> y) (at level 90, right associativity): type_scope. +Notation "x ↔ y" := (x <-> y) (at level 95, no associativity): type_scope. +Notation "⌉ x" := (~x) (at level 75, right associativity) : type_scope. +Notation "x ≠y" := (x <> y) (at level 70) : type_scope. + +(* Abstraction *) +(* Not nice +Notation "'λ' x : T , y" := ([x:T] y) (at level 1, x,T,y at level 10). +Notation "'λ' x := T , y" := ([x:=T] y) (at level 1, x,T,y at level 10). +*) + +(* Arithmetic *) +Notation "x ≤ y" := (le x y) (at level 70, no associativity). +Notation "x ≥ y" := (ge x y) (at level 70, no associativity). + +(* test *) +(* +Goal ∀ x, True -> (∃ y , x ≥ y + 1) ∨ x ≤ 0. +*) + +(* Integer Arithmetic *) +(* TODO: this should come after ZArith +Notation "x ≤ y" := (Zle x y) (at level 1, y at level 10). +*) diff --git a/theories/Wellfounded/Disjoint_Union.v b/theories/Wellfounded/Disjoint_Union.v index 1e22730b..6adf629d 100644 --- a/theories/Wellfounded/Disjoint_Union.v +++ b/theories/Wellfounded/Disjoint_Union.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Disjoint_Union.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Disjoint_Union.v 10681 2008-03-16 13:40:45Z msozeau $ i*) (** Author: Cristina Cornes From : Constructing Recursion Operators in Type Theory @@ -15,7 +15,7 @@ Require Import Relation_Operators. Section Wf_Disjoint_Union. - Variables A B : Set. + Variables A B : Type. Variable leA : A -> A -> Prop. Variable leB : B -> B -> Prop. @@ -52,4 +52,4 @@ Section Wf_Disjoint_Union. apply (H0 b). Qed. -End Wf_Disjoint_Union.
\ No newline at end of file +End Wf_Disjoint_Union. diff --git a/theories/Wellfounded/Inclusion.v b/theories/Wellfounded/Inclusion.v index 44e07d0b..e5ef4a70 100644 --- a/theories/Wellfounded/Inclusion.v +++ b/theories/Wellfounded/Inclusion.v @@ -6,14 +6,14 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Inclusion.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Inclusion.v 9642 2007-02-12 10:31:53Z herbelin $ i*) (** Author: Bruno Barras *) Require Import Relation_Definitions. Section WfInclusion. - Variable A : Set. + Variable A : Type. Variables R1 R2 : A -> A -> Prop. Lemma Acc_incl : inclusion A R1 R2 -> forall z:A, Acc R2 z -> Acc R1 z. @@ -29,4 +29,4 @@ Section WfInclusion. unfold well_founded in |- *; auto with sets. Qed. -End WfInclusion.
\ No newline at end of file +End WfInclusion. diff --git a/theories/Wellfounded/Inverse_Image.v b/theories/Wellfounded/Inverse_Image.v index 210cc757..29fe7bb2 100644 --- a/theories/Wellfounded/Inverse_Image.v +++ b/theories/Wellfounded/Inverse_Image.v @@ -6,13 +6,13 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Inverse_Image.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Inverse_Image.v 9642 2007-02-12 10:31:53Z herbelin $ i*) (** Author: Bruno Barras *) Section Inverse_Image. - Variables A B : Set. + Variables A B : Type. Variable R : B -> B -> Prop. Variable f : A -> B. diff --git a/theories/Wellfounded/Lexicographic_Exponentiation.v b/theories/Wellfounded/Lexicographic_Exponentiation.v index efdf0495..4dfcb24b 100644 --- a/theories/Wellfounded/Lexicographic_Exponentiation.v +++ b/theories/Wellfounded/Lexicographic_Exponentiation.v @@ -6,14 +6,13 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Lexicographic_Exponentiation.v 9610 2007-02-07 14:45:18Z herbelin $ i*) +(*i $Id: Lexicographic_Exponentiation.v 9609 2007-02-07 14:42:26Z herbelin $ i*) (** Author: Cristina Cornes From : Constructing Recursion Operators in Type Theory L. Paulson JSC (1986) 2, 325-355 *) -Require Import Eqdep. Require Import List. Require Import Relation_Operators. Require Import Transitive_Closure. diff --git a/theories/Wellfounded/Lexicographic_Product.v b/theories/Wellfounded/Lexicographic_Product.v index 051c8127..818084b2 100644 --- a/theories/Wellfounded/Lexicographic_Product.v +++ b/theories/Wellfounded/Lexicographic_Product.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Lexicographic_Product.v 9597 2007-02-06 19:44:05Z herbelin $ i*) +(*i $Id: Lexicographic_Product.v 9598 2007-02-06 19:45:52Z herbelin $ i*) (** Authors: Bruno Barras, Cristina Cornes *) diff --git a/theories/Wellfounded/Transitive_Closure.v b/theories/Wellfounded/Transitive_Closure.v index bd4e4fec..e552598c 100644 --- a/theories/Wellfounded/Transitive_Closure.v +++ b/theories/Wellfounded/Transitive_Closure.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Transitive_Closure.v 9597 2007-02-06 19:44:05Z herbelin $ i*) +(*i $Id: Transitive_Closure.v 9598 2007-02-06 19:45:52Z herbelin $ i*) (** Author: Bruno Barras *) diff --git a/theories/Wellfounded/Union.v b/theories/Wellfounded/Union.v index 634576ad..8589c18f 100644 --- a/theories/Wellfounded/Union.v +++ b/theories/Wellfounded/Union.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Union.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Union.v 9642 2007-02-12 10:31:53Z herbelin $ i*) (** Author: Bruno Barras *) @@ -15,7 +15,7 @@ Require Import Relation_Definitions. Require Import Transitive_Closure. Section WfUnion. - Variable A : Set. + Variable A : Type. Variables R1 R2 : relation A. Notation Union := (union A R1 R2). @@ -72,4 +72,4 @@ Section WfUnion. apply Acc_union; auto with sets. Qed. -End WfUnion.
\ No newline at end of file +End WfUnion. diff --git a/theories/Wellfounded/Well_Ordering.v b/theories/Wellfounded/Well_Ordering.v index f691f2b7..af8832ec 100644 --- a/theories/Wellfounded/Well_Ordering.v +++ b/theories/Wellfounded/Well_Ordering.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Well_Ordering.v 9597 2007-02-06 19:44:05Z herbelin $ i*) +(*i $Id: Well_Ordering.v 9598 2007-02-06 19:45:52Z herbelin $ i*) (** Author: Cristina Cornes. From: Constructing Recursion Operators in Type Theory diff --git a/theories/ZArith/BinInt.v b/theories/ZArith/BinInt.v index 71e48360..1ff88604 100644 --- a/theories/ZArith/BinInt.v +++ b/theories/ZArith/BinInt.v @@ -6,10 +6,10 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: BinInt.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: BinInt.v 11015 2008-05-28 20:06:42Z herbelin $ i*) (***********************************************************) -(** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) +(** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) (***********************************************************) Require Export BinPos. @@ -40,43 +40,48 @@ Arguments Scope Zneg [positive_scope]. Definition Zdouble_plus_one (x:Z) := match x with | Z0 => Zpos 1 - | Zpos p => Zpos (xI p) + | Zpos p => Zpos p~1 | Zneg p => Zneg (Pdouble_minus_one p) end. Definition Zdouble_minus_one (x:Z) := match x with | Z0 => Zneg 1 - | Zneg p => Zneg (xI p) + | Zneg p => Zneg p~1 | Zpos p => Zpos (Pdouble_minus_one p) end. Definition Zdouble (x:Z) := match x with | Z0 => Z0 - | Zpos p => Zpos (xO p) - | Zneg p => Zneg (xO p) + | Zpos p => Zpos p~0 + | Zneg p => Zneg p~0 end. +Open Local Scope positive_scope. + Fixpoint ZPminus (x y:positive) {struct y} : Z := match x, y with - | xI x', xI y' => Zdouble (ZPminus x' y') - | xI x', xO y' => Zdouble_plus_one (ZPminus x' y') - | xI x', xH => Zpos (xO x') - | xO x', xI y' => Zdouble_minus_one (ZPminus x' y') - | xO x', xO y' => Zdouble (ZPminus x' y') - | xO x', xH => Zpos (Pdouble_minus_one x') - | xH, xI y' => Zneg (xO y') - | xH, xO y' => Zneg (Pdouble_minus_one y') - | xH, xH => Z0 + | p~1, q~1 => Zdouble (ZPminus p q) + | p~1, q~0 => Zdouble_plus_one (ZPminus p q) + | p~1, 1 => Zpos p~0 + | p~0, q~1 => Zdouble_minus_one (ZPminus p q) + | p~0, q~0 => Zdouble (ZPminus p q) + | p~0, 1 => Zpos (Pdouble_minus_one p) + | 1, q~1 => Zneg q~0 + | 1, q~0 => Zneg (Pdouble_minus_one q) + | 1, 1 => Z0 end. +Close Local Scope positive_scope. + (** ** Addition on integers *) Definition Zplus (x y:Z) := match x, y with | Z0, y => y - | x, Z0 => x + | Zpos x', Z0 => Zpos x' + | Zneg x', Z0 => Zneg x' | Zpos x', Zpos y' => Zpos (x' + y') | Zpos x', Zneg y' => match (x' ?= y')%positive Eq with @@ -217,6 +222,7 @@ Qed. (**********************************************************************) + (** ** Properties of opposite on binary integer numbers *) Theorem Zopp_neg : forall p:positive, - Zneg p = Zpos p. @@ -247,30 +253,6 @@ Proof. | simplify_eq H; intro E; rewrite E; trivial ]. Qed. -(*************************************************************************) -(** ** Properties of the direct definition of successor and predecessor *) - -Lemma Zpred'_succ' : forall n:Z, Zpred' (Zsucc' n) = n. -Proof. - intro x; destruct x; simpl in |- *. - reflexivity. - destruct p; simpl in |- *; try rewrite Pdouble_minus_one_o_succ_eq_xI; - reflexivity. - destruct p; simpl in |- *; try rewrite Psucc_o_double_minus_one_eq_xO; - reflexivity. -Qed. - -Lemma Zsucc'_discr : forall n:Z, n <> Zsucc' n. -Proof. - intro x; destruct x; simpl in |- *. - discriminate. - injection; apply Psucc_discr. - destruct p; simpl in |- *. - discriminate. - intro H; symmetry in H; injection H; apply double_moins_un_xO_discr. - discriminate. -Qed. - (**********************************************************************) (** ** Other properties of binary integer numbers *) @@ -313,10 +295,15 @@ Qed. Theorem Zopp_plus_distr : forall n m:Z, - (n + m) = - n + - m. Proof. intro x; destruct x as [| p| p]; intro y; destruct y as [| q| q]; - simpl in |- *; reflexivity || destruct ((p ?= q)%positive Eq); + simpl in |- *; reflexivity || destruct ((p ?= q)%positive Eq); reflexivity. Qed. +Theorem Zopp_succ : forall n:Z, Zopp (Zsucc n) = Zpred (Zopp n). +Proof. +intro; unfold Zsucc; now rewrite Zopp_plus_distr. +Qed. + (** ** opposite is inverse for addition *) Theorem Zplus_opp_r : forall n:Z, n + - n = Z0. @@ -520,11 +507,13 @@ Proof. trivial with arith. Qed. -Lemma Zplus_succ_r : forall n m:Z, Zsucc (n + m) = n + Zsucc m. +Lemma Zplus_succ_r_reverse : forall n m:Z, Zsucc (n + m) = n + Zsucc m. Proof. intros n m; unfold Zsucc in |- *; rewrite Zplus_assoc; trivial with arith. Qed. +Notation Zplus_succ_r := Zplus_succ_r_reverse (only parsing). + Lemma Zplus_succ_comm : forall n m:Z, Zsucc n + m = n + Zsucc m. Proof. unfold Zsucc in |- *; intros n m; rewrite <- Zplus_assoc; @@ -586,10 +575,10 @@ Theorem Zsucc_pred : forall n:Z, n = Zsucc (Zpred n). Proof. intros n; unfold Zsucc, Zpred in |- *; rewrite <- Zplus_assoc; simpl in |- *; rewrite Zplus_0_r; trivial with arith. -Qed. +Qed. Hint Immediate Zsucc_pred: zarith. - + Theorem Zpred_succ : forall n:Z, n = Zpred (Zsucc n). Proof. intros m; unfold Zpred, Zsucc in |- *; rewrite <- Zplus_assoc; simpl in |- *; @@ -603,7 +592,59 @@ Proof. do 2 rewrite <- Zplus_assoc; do 2 rewrite (Zplus_comm (Zpos 1)); unfold Zsucc in H; rewrite H; trivial with arith. Qed. - + +(*************************************************************************) +(** ** Properties of the direct definition of successor and predecessor *) + +Theorem Zsucc_succ' : forall n:Z, Zsucc n = Zsucc' n. +Proof. +destruct n as [| p | p]; simpl. +reflexivity. +now rewrite Pplus_one_succ_r. +now destruct p as [q | q |]. +Qed. + +Theorem Zpred_pred' : forall n:Z, Zpred n = Zpred' n. +Proof. +destruct n as [| p | p]; simpl. +reflexivity. +now destruct p as [q | q |]. +now rewrite Pplus_one_succ_r. +Qed. + +Theorem Zsucc'_inj : forall n m:Z, Zsucc' n = Zsucc' m -> n = m. +Proof. +intros n m; do 2 rewrite <- Zsucc_succ'; now apply Zsucc_inj. +Qed. + +Theorem Zsucc'_pred' : forall n:Z, Zsucc' (Zpred' n) = n. +Proof. +intro; rewrite <- Zsucc_succ'; rewrite <- Zpred_pred'; +symmetry; apply Zsucc_pred. +Qed. + +Theorem Zpred'_succ' : forall n:Z, Zpred' (Zsucc' n) = n. +Proof. +intro; apply Zsucc'_inj; now rewrite Zsucc'_pred'. +Qed. + +Theorem Zpred'_inj : forall n m:Z, Zpred' n = Zpred' m -> n = m. +Proof. +intros n m H. +rewrite <- (Zsucc'_pred' n); rewrite <- (Zsucc'_pred' m); now rewrite H. +Qed. + +Theorem Zsucc'_discr : forall n:Z, n <> Zsucc' n. +Proof. + intro x; destruct x; simpl in |- *. + discriminate. + injection; apply Psucc_discr. + destruct p; simpl in |- *. + discriminate. + intro H; symmetry in H; injection H; apply double_moins_un_xO_discr. + discriminate. +Qed. + (** Misc properties, usually redundant or non natural *) Lemma Zsucc_eq_compat : forall n m:Z, n = m -> Zsucc n = Zsucc m. @@ -645,6 +686,22 @@ Qed. (** ** Relating [minus] with [plus] and [Zsucc] *) +Lemma Zminus_plus_distr : forall n m p:Z, n - (m + p) = n - m - p. +Proof. +intros; unfold Zminus; rewrite Zopp_plus_distr; apply Zplus_assoc. +Qed. + +Lemma Zminus_succ_l : forall n m:Z, Zsucc (n - m) = Zsucc n - m. +Proof. + intros n m; unfold Zminus, Zsucc in |- *; rewrite (Zplus_comm n (- m)); + rewrite <- Zplus_assoc; apply Zplus_comm. +Qed. + +Lemma Zminus_succ_r : forall n m:Z, n - (Zsucc m) = Zpred (n - m). +Proof. +intros; unfold Zsucc; now rewrite Zminus_plus_distr. +Qed. + Lemma Zplus_minus_eq : forall n m p:Z, n = m + p -> p = n - m. Proof. intros n m p H; unfold Zminus in |- *; apply (Zplus_reg_l m); @@ -665,12 +722,6 @@ Proof. apply Zplus_0_r. Qed. -Lemma Zminus_succ_l : forall n m:Z, Zsucc (n - m) = Zsucc n - m. -Proof. - intros n m; unfold Zminus, Zsucc in |- *; rewrite (Zplus_comm n (- m)); - rewrite <- Zplus_assoc; apply Zplus_comm. -Qed. - Lemma Zminus_plus_simpl_l : forall n m p:Z, p + n - (p + m) = n - m. Proof. intros n m p; unfold Zminus in |- *; rewrite Zopp_plus_distr; @@ -696,6 +747,16 @@ Proof. reflexivity. Qed. +Lemma Zpos_minus_morphism : forall a b:positive, Pcompare a b Eq = Lt -> + Zpos (b-a) = Zpos b - Zpos a. +Proof. + intros. + simpl. + change Eq with (CompOpp Eq). + rewrite <- Pcompare_antisym. + rewrite H; simpl; auto. +Qed. + (** ** Misc redundant properties *) Lemma Zeq_minus : forall n m:Z, n = m -> n - m = Z0. @@ -805,6 +866,19 @@ Proof. reflexivity). Qed. +(** ** Multiplication and Doubling *) + +Lemma Zdouble_mult : forall z, Zdouble z = (Zpos 2) * z. +Proof. + reflexivity. +Qed. + +Lemma Zdouble_plus_one_mult : forall z, + Zdouble_plus_one z = (Zpos 2) * z + (Zpos 1). +Proof. + destruct z; simpl; auto with zarith. +Qed. + (** ** Multiplication and Opposite *) Theorem Zopp_mult_distr_l : forall n m:Z, - (n * m) = - n * m. @@ -967,22 +1041,37 @@ Qed. (**********************************************************************) (** * Relating binary positive numbers and binary integers *) -Lemma Zpos_xI : forall p:positive, Zpos (xI p) = Zpos 2 * Zpos p + Zpos 1. +Lemma Zpos_eq : forall p q:positive, p = q -> Zpos p = Zpos q. +Proof. + intros; f_equal; auto. +Qed. + +Lemma Zpos_eq_rev : forall p q:positive, Zpos p = Zpos q -> p = q. +Proof. + inversion 1; auto. +Qed. + +Lemma Zpos_eq_iff : forall p q:positive, p = q <-> Zpos p = Zpos q. +Proof. + split; [apply Zpos_eq|apply Zpos_eq_rev]. +Qed. + +Lemma Zpos_xI : forall p:positive, Zpos p~1 = Zpos 2 * Zpos p + Zpos 1. Proof. intro; apply refl_equal. Qed. -Lemma Zpos_xO : forall p:positive, Zpos (xO p) = Zpos 2 * Zpos p. +Lemma Zpos_xO : forall p:positive, Zpos p~0 = Zpos 2 * Zpos p. Proof. intro; apply refl_equal. Qed. -Lemma Zneg_xI : forall p:positive, Zneg (xI p) = Zpos 2 * Zneg p - Zpos 1. +Lemma Zneg_xI : forall p:positive, Zneg p~1 = Zpos 2 * Zneg p - Zpos 1. Proof. intro; apply refl_equal. Qed. -Lemma Zneg_xO : forall p:positive, Zneg (xO p) = Zpos 2 * Zneg p. +Lemma Zneg_xO : forall p:positive, Zneg p~0 = Zpos 2 * Zneg p. Proof. reflexivity. Qed. @@ -1057,7 +1146,8 @@ Definition Zabs_N (z:Z) := | Zneg p => Npos p end. -Definition Z_of_N (x:N) := match x with - | N0 => Z0 - | Npos p => Zpos p - end. +Definition Z_of_N (x:N) := + match x with + | N0 => Z0 + | Npos p => Zpos p + end. diff --git a/theories/ZArith/Int.v b/theories/ZArith/Int.v index 3cee9190..fcb44d6f 100644 --- a/theories/ZArith/Int.v +++ b/theories/ZArith/Int.v @@ -7,11 +7,11 @@ (***********************************************************************) (* Finite sets library. - * Authors: Pierre Letouzey and Jean-Christophe Filliâtre - * Institution: LRI, CNRS UMR 8623 - Université Paris Sud + * Authors: Pierre Letouzey and Jean-Christophe Filliâtre + * Institution: LRI, CNRS UMR 8623 - Université Paris Sud * 91405 Orsay, France *) -(* $Id: Int.v 9319 2006-10-30 12:41:21Z barras $ *) +(* $Id: Int.v 10739 2008-04-01 14:45:20Z herbelin $ *) (** An axiomatization of integers. *) @@ -352,46 +352,15 @@ Module MoreInt (I:Int). Ltac i2z_refl := i2z_gen; match goal with |- ?t => - let e := p2ep t - in - (change (ep2p e); - apply norm_ep_correct2; - simpl) + let e := p2ep t in + change (ep2p e); apply norm_ep_correct2; simpl end. - Ltac iauto := i2z_refl; auto. - Ltac iomega := i2z_refl; intros; romega. - - Open Scope Z_scope. - - Lemma max_spec : forall (x y:Z), - x >= y /\ Zmax x y = x \/ - x < y /\ Zmax x y = y. - Proof. - intros; unfold Zmax, Zlt, Zge. - destruct (Zcompare x y); [ left | right | left ]; split; auto; discriminate. - Qed. - - Ltac omega_max_genspec x y := - generalize (max_spec x y); - (let z := fresh "z" in let Hz := fresh "Hz" in - set (z:=Zmax x y); clearbody z). - - Ltac omega_max_loop := - match goal with - (* hack: we don't want [i2z (height ...)] to be reduced by romega later... *) - | |- context [ i2z (?f ?x) ] => - let i := fresh "i2z" in (set (i:=i2z (f x)); clearbody i); omega_max_loop - | |- context [ Zmax ?x ?y ] => omega_max_genspec x y; omega_max_loop - | _ => intros - end. - - Ltac omega_max := i2z_refl; omega_max_loop; try romega. + (* i2z_refl can be replaced below by (simpl in *; i2z). + The reflexive version improves compilation of AVL files by about 15% *) - Ltac false_omega := i2z_refl; intros; romega. - Ltac false_omega_max := elimtype False; omega_max. + Ltac omega_max := i2z_refl; romega with Z. - Open Scope Int_scope. End MoreInt. diff --git a/theories/ZArith/ZArith_dec.v b/theories/ZArith/ZArith_dec.v index 7febbf6a..b831afee 100644 --- a/theories/ZArith/ZArith_dec.v +++ b/theories/ZArith/ZArith_dec.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: ZArith_dec.v 9958 2007-07-06 22:47:40Z letouzey $ i*) +(*i $Id: ZArith_dec.v 9759 2007-04-12 17:46:54Z notin $ i*) Require Import Sumbool. diff --git a/theories/ZArith/ZOdiv.v b/theories/ZArith/ZOdiv.v new file mode 100644 index 00000000..03e061f2 --- /dev/null +++ b/theories/ZArith/ZOdiv.v @@ -0,0 +1,953 @@ +(************************************************************************) +(* 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 Nnat ZArith_base ROmega ZArithRing. +Require Export ZOdiv_def. +Require Zdiv. + +Open Scope Z_scope. + +(** This file provides results about the Round-Toward-Zero Euclidean + division [ZOdiv_eucl], whose projections are [ZOdiv] and [ZOmod]. + Definition of this division can be found in file [ZOdiv_def]. + + This division and the one defined in Zdiv agree only on positive + numbers. Otherwise, Zdiv performs Round-Toward-Bottom. + + The current approach is compatible with the division of usual + programming languages such as Ocaml. In addition, it has nicer + properties with respect to opposite and other usual operations. +*) + +(** Since ZOdiv and Zdiv are not meant to be used concurrently, + we reuse the same notation. *) + +Infix "/" := ZOdiv : Z_scope. +Infix "mod" := ZOmod (at level 40, no associativity) : Z_scope. + +Infix "/" := Ndiv : N_scope. +Infix "mod" := Nmod (at level 40, no associativity) : N_scope. + +(** Auxiliary results on the ad-hoc comparison [NPgeb]. *) + +Lemma NPgeb_Zge : forall (n:N)(p:positive), + NPgeb n p = true -> Z_of_N n >= Zpos p. +Proof. + destruct n as [|n]; simpl; intros. + discriminate. + red; simpl; destruct Pcompare; now auto. +Qed. + +Lemma NPgeb_Zlt : forall (n:N)(p:positive), + NPgeb n p = false -> Z_of_N n < Zpos p. +Proof. + destruct n as [|n]; simpl; intros. + red; auto. + red; simpl; destruct Pcompare; now auto. +Qed. + +(** * Relation between division on N and on Z. *) + +Lemma Ndiv_Z0div : forall a b:N, + Z_of_N (a/b) = (Z_of_N a / Z_of_N b). +Proof. + intros. + destruct a; destruct b; simpl; auto. + unfold Ndiv, ZOdiv; simpl; destruct Pdiv_eucl; auto. +Qed. + +Lemma Nmod_Z0mod : forall a b:N, + Z_of_N (a mod b) = (Z_of_N a) mod (Z_of_N b). +Proof. + intros. + destruct a; destruct b; simpl; auto. + unfold Nmod, ZOmod; simpl; destruct Pdiv_eucl; auto. +Qed. + +(** * Characterization of this euclidean division. *) + +(** First, the usual equation [a=q*b+r]. Notice that [a mod 0] + has been chosen to be [a], so this equation holds even for [b=0]. +*) + +Theorem N_div_mod_eq : forall a b, + a = (b * (Ndiv a b) + (Nmod a b))%N. +Proof. + intros; generalize (Ndiv_eucl_correct a b). + unfold Ndiv, Nmod; destruct Ndiv_eucl; simpl. + intro H; rewrite H; rewrite Nmult_comm; auto. +Qed. + +Theorem ZO_div_mod_eq : forall a b, + a = b * (ZOdiv a b) + (ZOmod a b). +Proof. + intros; generalize (ZOdiv_eucl_correct a b). + unfold ZOdiv, ZOmod; destruct ZOdiv_eucl; simpl. + intro H; rewrite H; rewrite Zmult_comm; auto. +Qed. + +(** Then, the inequalities constraining the remainder. *) + +Theorem Pdiv_eucl_remainder : forall a b:positive, + Z_of_N (snd (Pdiv_eucl a b)) < Zpos 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. + romega with *. + apply NPgeb_Zlt; 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. + romega with *. + apply NPgeb_Zlt; auto. + destruct b; simpl; romega with *. +Qed. + +Theorem Nmod_lt : forall (a b:N), b<>0%N -> + (a mod b < b)%N. +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. + romega with *. +Qed. + +(** The remainder is bounded by the divisor, in term of absolute values *) + +Theorem ZOmod_lt : forall a b:Z, b<>0 -> + Zabs (a mod b) < Zabs b. +Proof. + destruct b as [ |b|b]; intro H; try solve [elim H;auto]; + destruct a as [ |a|a]; try solve [compute;auto]; unfold ZOmod, ZOdiv_eucl; + generalize (Pdiv_eucl_remainder a b); destruct Pdiv_eucl; simpl; + try rewrite Zabs_Zopp; rewrite Zabs_eq; auto; apply Z_of_N_le_0. +Qed. + +(** The sign of the remainder is the one of [a]. Due to the possible + nullity of [a], a general result is to be stated in the following form: +*) + +Theorem ZOmod_sgn : forall a b:Z, + 0 <= Zsgn (a mod b) * Zsgn a. +Proof. + destruct b as [ |b|b]; destruct a as [ |a|a]; simpl; auto with zarith; + unfold ZOmod, ZOdiv_eucl; destruct Pdiv_eucl; + simpl; destruct n0; simpl; auto with zarith. +Qed. + +(** This can also be said in a simplier way: *) + +Theorem Zsgn_pos_iff : forall z, 0 <= Zsgn z <-> 0 <= z. +Proof. + destruct z; simpl; intuition auto with zarith. +Qed. + +Theorem ZOmod_sgn2 : forall a b:Z, + 0 <= (a mod b) * a. +Proof. + intros; rewrite <-Zsgn_pos_iff, Zsgn_Zmult; apply ZOmod_sgn. +Qed. + +(** Reformulation of [ZOdiv_lt] and [ZOmod_sgn] in 2 + then 4 particular cases. *) + +Theorem ZOmod_lt_pos : forall a b:Z, 0<=a -> b<>0 -> + 0 <= a mod b < Zabs b. +Proof. + intros. + assert (0 <= a mod b). + generalize (ZOmod_sgn a b). + destruct (Zle_lt_or_eq 0 a H). + rewrite <- Zsgn_pos in H1; rewrite H1; romega with *. + subst a; simpl; auto. + generalize (ZOmod_lt a b H0); romega with *. +Qed. + +Theorem ZOmod_lt_neg : forall a b:Z, a<=0 -> b<>0 -> + -Zabs b < a mod b <= 0. +Proof. + intros. + assert (a mod b <= 0). + generalize (ZOmod_sgn a b). + destruct (Zle_lt_or_eq a 0 H). + rewrite <- Zsgn_neg in H1; rewrite H1; romega with *. + subst a; simpl; auto. + generalize (ZOmod_lt a b H0); romega with *. +Qed. + +Theorem ZOmod_lt_pos_pos : forall a b:Z, 0<=a -> 0<b -> 0 <= a mod b < b. +Proof. + intros; generalize (ZOmod_lt_pos a b); romega with *. +Qed. + +Theorem ZOmod_lt_pos_neg : forall a b:Z, 0<=a -> b<0 -> 0 <= a mod b < -b. +Proof. + intros; generalize (ZOmod_lt_pos a b); romega with *. +Qed. + +Theorem ZOmod_lt_neg_pos : forall a b:Z, a<=0 -> 0<b -> -b < a mod b <= 0. +Proof. + intros; generalize (ZOmod_lt_neg a b); romega with *. +Qed. + +Theorem ZOmod_lt_neg_neg : forall a b:Z, a<=0 -> b<0 -> b < a mod b <= 0. +Proof. + intros; generalize (ZOmod_lt_neg a b); romega with *. +Qed. + +(** * Division and Opposite *) + +(* The precise equalities that are invalid with "historic" Zdiv. *) + +Theorem ZOdiv_opp_l : forall a b:Z, (-a)/b = -(a/b). +Proof. + destruct a; destruct b; simpl; auto; + unfold ZOdiv, ZOdiv_eucl; destruct Pdiv_eucl; simpl; auto with zarith. +Qed. + +Theorem ZOdiv_opp_r : forall a b:Z, a/(-b) = -(a/b). +Proof. + destruct a; destruct b; simpl; auto; + unfold ZOdiv, ZOdiv_eucl; destruct Pdiv_eucl; simpl; auto with zarith. +Qed. + +Theorem ZOmod_opp_l : forall a b:Z, (-a) mod b = -(a mod b). +Proof. + destruct a; destruct b; simpl; auto; + unfold ZOmod, ZOdiv_eucl; destruct Pdiv_eucl; simpl; auto with zarith. +Qed. + +Theorem ZOmod_opp_r : forall a b:Z, a mod (-b) = a mod b. +Proof. + destruct a; destruct b; simpl; auto; + unfold ZOmod, ZOdiv_eucl; destruct Pdiv_eucl; simpl; auto with zarith. +Qed. + +Theorem ZOdiv_opp_opp : forall a b:Z, (-a)/(-b) = a/b. +Proof. + destruct a; destruct b; simpl; auto; + unfold ZOdiv, ZOdiv_eucl; destruct Pdiv_eucl; simpl; auto with zarith. +Qed. + +Theorem ZOmod_opp_opp : forall a b:Z, (-a) mod (-b) = -(a mod b). +Proof. + destruct a; destruct b; simpl; auto; + unfold ZOmod, ZOdiv_eucl; destruct Pdiv_eucl; simpl; auto with zarith. +Qed. + +(** * Unicity results *) + +Definition Remainder a b r := + (0 <= a /\ 0 <= r < Zabs b) \/ (a <= 0 /\ -Zabs b < r <= 0). + +Definition Remainder_alt a b r := + Zabs r < Zabs b /\ 0 <= r * a. + +Lemma Remainder_equiv : forall a b r, + Remainder a b r <-> Remainder_alt a b r. +Proof. + unfold Remainder, Remainder_alt; intuition. + romega with *. + romega with *. + rewrite <-(Zmult_opp_opp). + apply Zmult_le_0_compat; romega. + assert (0 <= Zsgn r * Zsgn a) by (rewrite <-Zsgn_Zmult, Zsgn_pos_iff; auto). + destruct r; simpl Zsgn in *; romega with *. +Qed. + +Theorem ZOdiv_mod_unique_full: + forall a b q r, Remainder a b r -> + a = b*q + r -> q = a/b /\ r = a mod b. +Proof. + destruct 1 as [(H,H0)|(H,H0)]; intros. + apply Zdiv.Zdiv_mod_unique with b; auto. + apply ZOmod_lt_pos; auto. + romega with *. + rewrite <- H1; apply ZO_div_mod_eq. + + rewrite <- (Zopp_involutive a). + rewrite ZOdiv_opp_l, ZOmod_opp_l. + generalize (Zdiv.Zdiv_mod_unique b (-q) (-a/b) (-r) (-a mod b)). + generalize (ZOmod_lt_pos (-a) b). + rewrite <-ZO_div_mod_eq, <-Zopp_mult_distr_r, <-Zopp_plus_distr, <-H1. + romega with *. +Qed. + +Theorem ZOdiv_unique_full: + forall a b q r, Remainder a b r -> + a = b*q + r -> q = a/b. +Proof. + intros; destruct (ZOdiv_mod_unique_full a b q r); auto. +Qed. + +Theorem ZOdiv_unique: + forall a b q r, 0 <= a -> 0 <= r < b -> + a = b*q + r -> q = a/b. +Proof. + intros; eapply ZOdiv_unique_full; eauto. + red; romega with *. +Qed. + +Theorem ZOmod_unique_full: + forall a b q r, Remainder a b r -> + a = b*q + r -> r = a mod b. +Proof. + intros; destruct (ZOdiv_mod_unique_full a b q r); auto. +Qed. + +Theorem ZOmod_unique: + forall a b q r, 0 <= a -> 0 <= r < b -> + a = b*q + r -> r = a mod b. +Proof. + intros; eapply ZOmod_unique_full; eauto. + red; romega with *. +Qed. + +(** * Basic values of divisions and modulo. *) + +Lemma ZOmod_0_l: forall a, 0 mod a = 0. +Proof. + destruct a; simpl; auto. +Qed. + +Lemma ZOmod_0_r: forall a, a mod 0 = a. +Proof. + destruct a; simpl; auto. +Qed. + +Lemma ZOdiv_0_l: forall a, 0/a = 0. +Proof. + destruct a; simpl; auto. +Qed. + +Lemma ZOdiv_0_r: forall a, a/0 = 0. +Proof. + destruct a; simpl; auto. +Qed. + +Lemma ZOmod_1_r: forall a, a mod 1 = 0. +Proof. + intros; symmetry; apply ZOmod_unique_full with a; auto with zarith. + rewrite Remainder_equiv; red; simpl; auto with zarith. +Qed. + +Lemma ZOdiv_1_r: forall a, a/1 = a. +Proof. + intros; symmetry; apply ZOdiv_unique_full with 0; auto with zarith. + rewrite Remainder_equiv; red; simpl; auto with zarith. +Qed. + +Hint Resolve ZOmod_0_l ZOmod_0_r ZOdiv_0_l ZOdiv_0_r ZOdiv_1_r ZOmod_1_r + : zarith. + +Lemma ZOdiv_1_l: forall a, 1 < a -> 1/a = 0. +Proof. + intros; symmetry; apply ZOdiv_unique with 1; auto with zarith. +Qed. + +Lemma ZOmod_1_l: forall a, 1 < a -> 1 mod a = 1. +Proof. + intros; symmetry; apply ZOmod_unique with 0; auto with zarith. +Qed. + +Lemma ZO_div_same : forall a:Z, a<>0 -> a/a = 1. +Proof. + intros; symmetry; apply ZOdiv_unique_full with 0; auto with *. + rewrite Remainder_equiv; red; simpl; romega with *. +Qed. + +Lemma ZO_mod_same : forall a, a mod a = 0. +Proof. + destruct a; intros; symmetry. + compute; auto. + apply ZOmod_unique with 1; auto with *; romega with *. + apply ZOmod_unique_full with 1; auto with *; red; romega with *. +Qed. + +Lemma ZO_mod_mult : forall a b, (a*b) mod b = 0. +Proof. + intros a b; destruct (Z_eq_dec b 0) as [Hb|Hb]. + subst; simpl; rewrite ZOmod_0_r; auto with zarith. + symmetry; apply ZOmod_unique_full with a; [ red; romega with * | ring ]. +Qed. + +Lemma ZO_div_mult : forall a b:Z, b <> 0 -> (a*b)/b = a. +Proof. + intros; symmetry; apply ZOdiv_unique_full with 0; auto with zarith; + [ red; romega with * | ring]. +Qed. + +(** * Order results about ZOmod and ZOdiv *) + +(* Division of positive numbers is positive. *) + +Lemma ZO_div_pos: forall a b, 0 <= a -> 0 <= b -> 0 <= a/b. +Proof. + intros. + destruct (Zle_lt_or_eq 0 b H0). + assert (H2:=ZOmod_lt_pos_pos a b H H1). + rewrite (ZO_div_mod_eq a b) in H. + destruct (Z_lt_le_dec (a/b) 0); auto. + assert (b*(a/b) <= -b). + replace (-b) with (b*-1); [ | ring]. + apply Zmult_le_compat_l; auto with zarith. + romega. + subst b; rewrite ZOdiv_0_r; auto. +Qed. + +(** As soon as the divisor is greater or equal than 2, + the division is strictly decreasing. *) + +Lemma ZO_div_lt : forall a b:Z, 0 < a -> 2 <= b -> a/b < a. +Proof. + intros. + assert (Hb : 0 < b) by romega. + assert (H1 : 0 <= a/b) by (apply ZO_div_pos; auto with zarith). + assert (H2 : 0 <= a mod b < b) by (apply ZOmod_lt_pos_pos; auto with zarith). + destruct (Zle_lt_or_eq 0 (a/b) H1) as [H3|H3]; [ | rewrite <- H3; auto]. + pattern a at 2; rewrite (ZO_div_mod_eq a b). + apply Zlt_le_trans with (2*(a/b)). + romega. + apply Zle_trans with (b*(a/b)). + apply Zmult_le_compat_r; auto. + romega. +Qed. + +(** A division of a small number by a bigger one yields zero. *) + +Theorem ZOdiv_small: forall a b, 0 <= a < b -> a/b = 0. +Proof. + intros a b H; apply sym_equal; apply ZOdiv_unique with a; auto with zarith. +Qed. + +(** Same situation, in term of modulo: *) + +Theorem ZOmod_small: forall a n, 0 <= a < n -> a mod n = a. +Proof. + intros a b H; apply sym_equal; apply ZOmod_unique with 0; auto with zarith. +Qed. + +(** [Zge] is compatible with a positive division. *) + +Lemma ZO_div_monotone_pos : forall a b c:Z, 0<=c -> 0<=a<=b -> a/c <= b/c. +Proof. + intros. + destruct H0. + destruct (Zle_lt_or_eq 0 c H); + [ clear H | subst c; do 2 rewrite ZOdiv_0_r; auto]. + generalize (ZO_div_mod_eq a c). + generalize (ZOmod_lt_pos_pos a c H0 H2). + generalize (ZO_div_mod_eq b c). + generalize (ZOmod_lt_pos_pos b c (Zle_trans _ _ _ H0 H1) H2). + intros. + elim (Z_le_gt_dec (a / c) (b / c)); auto with zarith. + intro. + absurd (a - b >= 1). + omega. + replace (a-b) with (c * (a/c-b/c) + a mod c - b mod c) by + (symmetry; pattern a at 1; rewrite H5; pattern b at 1; rewrite H3; ring). + assert (c * (a / c - b / c) >= c * 1). + apply Zmult_ge_compat_l. + omega. + omega. + assert (c * 1 = c). + ring. + omega. +Qed. + +Lemma ZO_div_monotone : forall a b c, 0<=c -> a<=b -> a/c <= b/c. +Proof. + intros. + destruct (Z_le_gt_dec 0 a). + apply ZO_div_monotone_pos; auto with zarith. + destruct (Z_le_gt_dec 0 b). + apply Zle_trans with 0. + apply Zle_left_rev. + simpl. + rewrite <- ZOdiv_opp_l. + apply ZO_div_pos; auto with zarith. + apply ZO_div_pos; auto with zarith. + rewrite <-(Zopp_involutive a), (ZOdiv_opp_l (-a)). + rewrite <-(Zopp_involutive b), (ZOdiv_opp_l (-b)). + generalize (ZO_div_monotone_pos (-b) (-a) c H). + romega. +Qed. + +(** With our choice of division, rounding of (a/b) is always done toward zero: *) + +Lemma ZO_mult_div_le : forall a b:Z, 0 <= a -> 0 <= b*(a/b) <= a. +Proof. + intros a b Ha. + destruct b as [ |b|b]. + simpl; auto with zarith. + split. + apply Zmult_le_0_compat; auto with zarith. + apply ZO_div_pos; auto with zarith. + generalize (ZO_div_mod_eq a (Zpos b)) (ZOmod_lt_pos_pos a (Zpos b) Ha); romega with *. + change (Zneg b) with (-Zpos b); rewrite ZOdiv_opp_r, Zmult_opp_opp. + split. + apply Zmult_le_0_compat; auto with zarith. + apply ZO_div_pos; auto with zarith. + generalize (ZO_div_mod_eq a (Zpos b)) (ZOmod_lt_pos_pos a (Zpos b) Ha); romega with *. +Qed. + +Lemma ZO_mult_div_ge : forall a b:Z, a <= 0 -> a <= b*(a/b) <= 0. +Proof. + intros a b Ha. + destruct b as [ |b|b]. + simpl; auto with zarith. + split. + generalize (ZO_div_mod_eq a (Zpos b)) (ZOmod_lt_neg_pos a (Zpos b) Ha); romega with *. + apply Zle_left_rev; unfold Zplus. + rewrite Zopp_mult_distr_r, <-ZOdiv_opp_l. + apply Zmult_le_0_compat; auto with zarith. + apply ZO_div_pos; auto with zarith. + change (Zneg b) with (-Zpos b); rewrite ZOdiv_opp_r, Zmult_opp_opp. + split. + generalize (ZO_div_mod_eq a (Zpos b)) (ZOmod_lt_neg_pos a (Zpos b) Ha); romega with *. + apply Zle_left_rev; unfold Zplus. + rewrite Zopp_mult_distr_r, <-ZOdiv_opp_l. + apply Zmult_le_0_compat; auto with zarith. + apply ZO_div_pos; auto with zarith. +Qed. + +(** The previous inequalities between [b*(a/b)] and [a] are exact + iff the modulo is zero. *) + +Lemma ZO_div_exact_full_1 : forall a b:Z, a = b*(a/b) -> a mod b = 0. +Proof. + intros; generalize (ZO_div_mod_eq a b); romega. +Qed. + +Lemma ZO_div_exact_full_2 : forall a b:Z, a mod b = 0 -> a = b*(a/b). +Proof. + intros; generalize (ZO_div_mod_eq a b); romega. +Qed. + +(** A modulo cannot grow beyond its starting point. *) + +Theorem ZOmod_le: forall a b, 0 <= a -> 0 <= b -> a mod b <= a. +Proof. + intros a b H1 H2. + destruct (Zle_lt_or_eq _ _ H2). + case (Zle_or_lt b a); intros H3. + case (ZOmod_lt_pos_pos a b); auto with zarith. + rewrite ZOmod_small; auto with zarith. + subst; rewrite ZOmod_0_r; auto with zarith. +Qed. + +(** Some additionnal inequalities about Zdiv. *) + +Theorem ZOdiv_le_upper_bound: + forall a b q, 0 <= a -> 0 < b -> a <= q*b -> a/b <= q. +Proof. + intros a b q H1 H2 H3. + apply Zmult_le_reg_r with b; auto with zarith. + apply Zle_trans with (2 := H3). + pattern a at 2; rewrite (ZO_div_mod_eq a b); auto with zarith. + rewrite (Zmult_comm b); case (ZOmod_lt_pos_pos a b); auto with zarith. +Qed. + +Theorem ZOdiv_lt_upper_bound: + forall a b q, 0 <= a -> 0 < b -> a < q*b -> a/b < q. +Proof. + intros a b q H1 H2 H3. + apply Zmult_lt_reg_r with b; auto with zarith. + apply Zle_lt_trans with (2 := H3). + pattern a at 2; rewrite (ZO_div_mod_eq a b); auto with zarith. + rewrite (Zmult_comm b); case (ZOmod_lt_pos_pos a b); auto with zarith. +Qed. + +Theorem ZOdiv_le_lower_bound: + forall a b q, 0 <= a -> 0 < b -> q*b <= a -> q <= a/b. +Proof. + intros a b q H1 H2 H3. + assert (q < a / b + 1); auto with zarith. + apply Zmult_lt_reg_r with b; auto with zarith. + apply Zle_lt_trans with (1 := H3). + pattern a at 1; rewrite (ZO_div_mod_eq a b); auto with zarith. + rewrite Zmult_plus_distr_l; rewrite (Zmult_comm b); case (ZOmod_lt_pos_pos a b); + auto with zarith. +Qed. + +Theorem ZOdiv_sgn: forall a b, + 0 <= Zsgn (a/b) * Zsgn a * Zsgn b. +Proof. + destruct a as [ |a|a]; destruct b as [ |b|b]; simpl; auto with zarith; + unfold ZOdiv; simpl; destruct Pdiv_eucl; simpl; destruct n; simpl; auto with zarith. +Qed. + +(** * Relations between usual operations and Zmod and Zdiv *) + +(** First, a result that used to be always valid with Zdiv, + but must be restricted here. + For instance, now (9+(-5)*2) mod 2 = -1 <> 1 = 9 mod 2 *) + +Lemma ZO_mod_plus : forall a b c:Z, + 0 <= (a+b*c) * a -> + (a + b * c) mod c = a mod c. +Proof. + intros; destruct (Z_eq_dec a 0) as [Ha|Ha]. + subst; simpl; rewrite ZOmod_0_l; apply ZO_mod_mult. + intros; destruct (Z_eq_dec c 0) as [Hc|Hc]. + subst; do 2 rewrite ZOmod_0_r; romega. + symmetry; apply ZOmod_unique_full with (a/c+b); auto with zarith. + rewrite Remainder_equiv; split. + apply ZOmod_lt; auto. + apply Zmult_le_0_reg_r with (a*a); eauto. + destruct a; simpl; auto with zarith. + replace ((a mod c)*(a+b*c)*(a*a)) with (((a mod c)*a)*((a+b*c)*a)) by ring. + apply Zmult_le_0_compat; auto. + apply ZOmod_sgn2. + rewrite Zmult_plus_distr_r, Zmult_comm. + generalize (ZO_div_mod_eq a c); romega. +Qed. + +Lemma ZO_div_plus : forall a b c:Z, + 0 <= (a+b*c) * a -> c<>0 -> + (a + b * c) / c = a / c + b. +Proof. + intros; destruct (Z_eq_dec a 0) as [Ha|Ha]. + subst; simpl; apply ZO_div_mult; auto. + symmetry. + apply ZOdiv_unique_full with (a mod c); auto with zarith. + rewrite Remainder_equiv; split. + apply ZOmod_lt; auto. + apply Zmult_le_0_reg_r with (a*a); eauto. + destruct a; simpl; auto with zarith. + replace ((a mod c)*(a+b*c)*(a*a)) with (((a mod c)*a)*((a+b*c)*a)) by ring. + apply Zmult_le_0_compat; auto. + apply ZOmod_sgn2. + rewrite Zmult_plus_distr_r, Zmult_comm. + generalize (ZO_div_mod_eq a c); romega. +Qed. + +Theorem ZO_div_plus_l: forall a b c : Z, + 0 <= (a*b+c)*c -> b<>0 -> + b<>0 -> (a * b + c) / b = a + c / b. +Proof. + intros a b c; rewrite Zplus_comm; intros; rewrite ZO_div_plus; + try apply Zplus_comm; auto with zarith. +Qed. + +(** Cancellations. *) + +Lemma ZOdiv_mult_cancel_r : forall a b c:Z, + c<>0 -> (a*c)/(b*c) = a/b. +Proof. + intros a b c Hc. + destruct (Z_eq_dec b 0). + subst; simpl; do 2 rewrite ZOdiv_0_r; auto. + symmetry. + apply ZOdiv_unique_full with ((a mod b)*c); auto with zarith. + rewrite Remainder_equiv. + split. + do 2 rewrite Zabs_Zmult. + apply Zmult_lt_compat_r. + romega with *. + apply ZOmod_lt; auto. + replace ((a mod b)*c*(a*c)) with (((a mod b)*a)*(c*c)) by ring. + apply Zmult_le_0_compat. + apply ZOmod_sgn2. + destruct c; simpl; auto with zarith. + pattern a at 1; rewrite (ZO_div_mod_eq a b); ring. +Qed. + +Lemma ZOdiv_mult_cancel_l : forall a b c:Z, + c<>0 -> (c*a)/(c*b) = a/b. +Proof. + intros. + rewrite (Zmult_comm c a); rewrite (Zmult_comm c b). + apply ZOdiv_mult_cancel_r; auto. +Qed. + +Lemma ZOmult_mod_distr_l: forall a b c, + (c*a) mod (c*b) = c * (a mod b). +Proof. + intros; destruct (Z_eq_dec c 0) as [Hc|Hc]. + subst; simpl; rewrite ZOmod_0_r; auto. + destruct (Z_eq_dec b 0) as [Hb|Hb]. + subst; repeat rewrite Zmult_0_r || rewrite ZOmod_0_r; auto. + assert (c*b <> 0). + contradict Hc; eapply Zmult_integral_l; eauto. + rewrite (Zplus_minus_eq _ _ _ (ZO_div_mod_eq (c*a) (c*b))). + rewrite (Zplus_minus_eq _ _ _ (ZO_div_mod_eq a b)). + rewrite ZOdiv_mult_cancel_l; auto with zarith. + ring. +Qed. + +Lemma ZOmult_mod_distr_r: forall a b c, + (a*c) mod (b*c) = (a mod b) * c. +Proof. + intros; repeat rewrite (fun x => (Zmult_comm x c)). + apply ZOmult_mod_distr_l; auto. +Qed. + +(** Operations modulo. *) + +Theorem ZOmod_mod: forall a n, (a mod n) mod n = a mod n. +Proof. + intros. + generalize (ZOmod_sgn2 a n). + pattern a at 2 4; rewrite (ZO_div_mod_eq a n); auto with zarith. + rewrite Zplus_comm; rewrite (Zmult_comm n). + intros. + apply sym_equal; apply ZO_mod_plus; auto with zarith. + rewrite Zmult_comm; auto. +Qed. + +Theorem ZOmult_mod: forall a b n, + (a * b) mod n = ((a mod n) * (b mod n)) mod n. +Proof. + intros. + generalize (Zmult_le_0_compat _ _ (ZOmod_sgn2 a n) (ZOmod_sgn2 b n)). + pattern a at 2 3; rewrite (ZO_div_mod_eq a n); auto with zarith. + pattern b at 2 3; rewrite (ZO_div_mod_eq b n); auto with zarith. + set (A:=a mod n); set (B:=b mod n); set (A':=a/n); set (B':=b/n). + replace (A*(n*A'+A)*(B*(n*B'+B))) with (((n*A' + A) * (n*B' + B))*(A*B)) + by ring. + replace ((n*A' + A) * (n*B' + B)) + with (A*B + (A'*B+B'*A+n*A'*B')*n) by ring. + intros. + apply ZO_mod_plus; auto with zarith. +Qed. + +(** addition and modulo + + Generally speaking, unlike with Zdiv, we don't have + (a+b) mod n = (a mod n + b mod n) mod n + for any a and b. + For instance, take (8 + (-10)) mod 3 = -2 whereas + (8 mod 3 + (-10 mod 3)) mod 3 = 1. *) + +Theorem ZOplus_mod: forall a b n, + 0 <= a * b -> + (a + b) mod n = (a mod n + b mod n) mod n. +Proof. + assert (forall a b n, 0<a -> 0<b -> + (a + b) mod n = (a mod n + b mod n) mod n). + intros a b n Ha Hb. + assert (H : 0<=a+b) by (romega with * ); revert H. + pattern a at 1 2; rewrite (ZO_div_mod_eq a n); auto with zarith. + pattern b at 1 2; rewrite (ZO_div_mod_eq b n); auto with zarith. + replace ((n * (a / n) + a mod n) + (n * (b / n) + b mod n)) + with ((a mod n + b mod n) + (a / n + b / n) * n) by ring. + intros. + apply ZO_mod_plus; auto with zarith. + apply Zmult_le_0_compat; auto with zarith. + apply Zplus_le_0_compat. + apply Zmult_le_reg_r with a; auto with zarith. + simpl; apply ZOmod_sgn2; auto. + apply Zmult_le_reg_r with b; auto with zarith. + simpl; apply ZOmod_sgn2; auto. + (* general situation *) + intros a b n Hab. + destruct (Z_eq_dec a 0). + subst; simpl; symmetry; apply ZOmod_mod. + destruct (Z_eq_dec b 0). + subst; simpl; do 2 rewrite Zplus_0_r; symmetry; apply ZOmod_mod. + assert (0<a /\ 0<b \/ a<0 /\ b<0). + destruct a; destruct b; simpl in *; intuition; romega with *. + destruct H0. + apply H; intuition. + rewrite <-(Zopp_involutive a), <-(Zopp_involutive b). + rewrite <- Zopp_plus_distr; rewrite ZOmod_opp_l. + rewrite (ZOmod_opp_l (-a)),(ZOmod_opp_l (-b)). + match goal with |- _ = (-?x+-?y) mod n => + rewrite <-(Zopp_plus_distr x y), ZOmod_opp_l end. + f_equal; apply H; auto with zarith. +Qed. + +Lemma ZOplus_mod_idemp_l: forall a b n, + 0 <= a * b -> + (a mod n + b) mod n = (a + b) mod n. +Proof. + intros. + rewrite ZOplus_mod. + rewrite ZOmod_mod. + symmetry. + apply ZOplus_mod; auto. + destruct (Z_eq_dec a 0). + subst; rewrite ZOmod_0_l; auto. + destruct (Z_eq_dec b 0). + subst; rewrite Zmult_0_r; auto with zarith. + apply Zmult_le_reg_r with (a*b). + assert (a*b <> 0). + intro Hab. + rewrite (Zmult_integral_l _ _ n1 Hab) in n0; auto with zarith. + auto with zarith. + simpl. + replace (a mod n * b * (a*b)) with ((a mod n * a)*(b*b)) by ring. + apply Zmult_le_0_compat. + apply ZOmod_sgn2. + destruct b; simpl; auto with zarith. +Qed. + +Lemma ZOplus_mod_idemp_r: forall a b n, + 0 <= a*b -> + (b + a mod n) mod n = (b + a) mod n. +Proof. + intros. + rewrite Zplus_comm, (Zplus_comm b a). + apply ZOplus_mod_idemp_l; auto. +Qed. + +Lemma ZOmult_mod_idemp_l: forall a b n, (a mod n * b) mod n = (a * b) mod n. +Proof. + intros; rewrite ZOmult_mod, ZOmod_mod, <- ZOmult_mod; auto. +Qed. + +Lemma ZOmult_mod_idemp_r: forall a b n, (b * (a mod n)) mod n = (b * a) mod n. +Proof. + intros; rewrite ZOmult_mod, ZOmod_mod, <- ZOmult_mod; auto. +Qed. + +(** Unlike with Zdiv, the following result is true without restrictions. *) + +Lemma ZOdiv_ZOdiv : forall a b c, (a/b)/c = a/(b*c). +Proof. + (* particular case: a, b, c positive *) + assert (forall a b c, a>0 -> b>0 -> c>0 -> (a/b)/c = a/(b*c)). + intros a b c H H0 H1. + pattern a at 2;rewrite (ZO_div_mod_eq a b). + pattern (a/b) at 2;rewrite (ZO_div_mod_eq (a/b) c). + replace (b * (c * (a / b / c) + (a / b) mod c) + a mod b) with + ((a / b / c)*(b * c) + (b * ((a / b) mod c) + a mod b)) by ring. + assert (b*c<>0). + intro H2; + assert (H3: c <> 0) by auto with zarith; + rewrite (Zmult_integral_l _ _ H3 H2) in H0; auto with zarith. + assert (0<=a/b) by (apply (ZO_div_pos a b); auto with zarith). + assert (0<=a mod b < b) by (apply ZOmod_lt_pos_pos; auto with zarith). + assert (0<=(a/b) mod c < c) by + (apply ZOmod_lt_pos_pos; auto with zarith). + rewrite ZO_div_plus_l; auto with zarith. + rewrite (ZOdiv_small (b * ((a / b) mod c) + a mod b)). + ring. + split. + apply Zplus_le_0_compat;auto with zarith. + apply Zle_lt_trans with (b * ((a / b) mod c) + (b-1)). + apply Zplus_le_compat;auto with zarith. + apply Zle_lt_trans with (b * (c-1) + (b - 1)). + apply Zplus_le_compat;auto with zarith. + replace (b * (c - 1) + (b - 1)) with (b*c-1);try ring;auto with zarith. + repeat (apply Zmult_le_0_compat || apply Zplus_le_0_compat); auto with zarith. + apply (ZO_div_pos (a/b) c); auto with zarith. + (* b c positive, a general *) + assert (forall a b c, b>0 -> c>0 -> (a/b)/c = a/(b*c)). + intros; destruct a as [ |a|a]; try reflexivity. + apply H; auto with zarith. + change (Zneg a) with (-Zpos a); repeat rewrite ZOdiv_opp_l. + f_equal; apply H; auto with zarith. + (* c positive, a b general *) + assert (forall a b c, c>0 -> (a/b)/c = a/(b*c)). + intros; destruct b as [ |b|b]. + repeat rewrite ZOdiv_0_r; reflexivity. + apply H0; auto with zarith. + change (Zneg b) with (-Zpos b); + repeat (rewrite ZOdiv_opp_r || rewrite ZOdiv_opp_l || rewrite <- Zopp_mult_distr_l). + f_equal; apply H0; auto with zarith. + (* a b c general *) + intros; destruct c as [ |c|c]. + rewrite Zmult_0_r; repeat rewrite ZOdiv_0_r; reflexivity. + apply H1; auto with zarith. + change (Zneg c) with (-Zpos c); + rewrite <- Zopp_mult_distr_r; do 2 rewrite ZOdiv_opp_r. + f_equal; apply H1; auto with zarith. +Qed. + +(** A last inequality: *) + +Theorem ZOdiv_mult_le: + forall a b c, 0<=a -> 0<=b -> 0<=c -> c*(a/b) <= (c*a)/b. +Proof. + intros a b c Ha Hb Hc. + destruct (Zle_lt_or_eq _ _ Ha); + [ | subst; rewrite ZOdiv_0_l, Zmult_0_r, ZOdiv_0_l; auto]. + destruct (Zle_lt_or_eq _ _ Hb); + [ | subst; rewrite ZOdiv_0_r, ZOdiv_0_r, Zmult_0_r; auto]. + destruct (Zle_lt_or_eq _ _ Hc); + [ | subst; rewrite ZOdiv_0_l; auto]. + case (ZOmod_lt_pos_pos a b); auto with zarith; intros Hu1 Hu2. + case (ZOmod_lt_pos_pos c b); auto with zarith; intros Hv1 Hv2. + apply Zmult_le_reg_r with b; auto with zarith. + rewrite <- Zmult_assoc. + replace (a / b * b) with (a - a mod b). + replace (c * a / b * b) with (c * a - (c * a) mod b). + rewrite Zmult_minus_distr_l. + unfold Zminus; apply Zplus_le_compat_l. + match goal with |- - ?X <= -?Y => assert (Y <= X); auto with zarith end. + apply Zle_trans with ((c mod b) * (a mod b)); auto with zarith. + rewrite ZOmult_mod; auto with zarith. + apply (ZOmod_le ((c mod b) * (a mod b)) b); auto with zarith. + apply Zmult_le_compat_r; auto with zarith. + apply (ZOmod_le c b); auto. + pattern (c * a) at 1; rewrite (ZO_div_mod_eq (c * a) b); try ring; + auto with zarith. + pattern a at 1; rewrite (ZO_div_mod_eq a b); try ring; auto with zarith. +Qed. + +(** ZOmod is related to divisibility (see more in Znumtheory) *) + +Lemma ZOmod_divides : forall a b, + a mod b = 0 <-> exists c, a = b*c. +Proof. + split; intros. + exists (a/b). + pattern a at 1; rewrite (ZO_div_mod_eq a b). + rewrite H; auto with zarith. + destruct H as [c Hc]. + destruct (Z_eq_dec b 0). + subst b; simpl in *; subst a; auto. + symmetry. + apply ZOmod_unique_full with c; auto with zarith. + red; romega with *. +Qed. + +(** * Interaction with "historic" Zdiv *) + +(** They agree at least on positive numbers: *) + +Theorem ZOdiv_eucl_Zdiv_eucl_pos : forall a b:Z, 0 <= a -> 0 < b -> + a/b = Zdiv.Zdiv a b /\ a mod b = Zdiv.Zmod a b. +Proof. + intros. + apply Zdiv.Zdiv_mod_unique with b. + apply ZOmod_lt_pos; auto with zarith. + rewrite Zabs_eq; auto with *; apply Zdiv.Z_mod_lt; auto with *. + rewrite <- Zdiv.Z_div_mod_eq; auto with *. + symmetry; apply ZO_div_mod_eq; auto with *. +Qed. + +Theorem ZOdiv_Zdiv_pos : forall a b, 0 <= a -> 0 <= b -> + a/b = Zdiv.Zdiv a b. +Proof. + intros a b Ha Hb. + destruct (Zle_lt_or_eq _ _ Hb). + generalize (ZOdiv_eucl_Zdiv_eucl_pos a b Ha H); intuition. + subst; rewrite ZOdiv_0_r, Zdiv.Zdiv_0_r; reflexivity. +Qed. + +Theorem ZOmod_Zmod_pos : forall a b, 0 <= a -> 0 < b -> + a mod b = Zdiv.Zmod a b. +Proof. + intros a b Ha Hb; generalize (ZOdiv_eucl_Zdiv_eucl_pos a b Ha Hb); + intuition. +Qed. + +(** Modulos are null at the same places *) + +Theorem ZOmod_Zmod_zero : forall a b, b<>0 -> + (a mod b = 0 <-> Zdiv.Zmod a b = 0). +Proof. + intros. + rewrite ZOmod_divides, Zdiv.Zmod_divides; intuition. +Qed. diff --git a/theories/ZArith/ZOdiv_def.v b/theories/ZArith/ZOdiv_def.v new file mode 100644 index 00000000..2c84765e --- /dev/null +++ b/theories/ZArith/ZOdiv_def.v @@ -0,0 +1,136 @@ +(************************************************************************) +(* 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 Nnat ZArith_base. + +Open Scope Z_scope. + +Definition NPgeb (a:N)(b:positive) := + match a with + | N0 => false + | Npos na => match Pcompare na b Eq with Lt => false | _ => true end + end. + +Fixpoint Pdiv_eucl (a b:positive) {struct a} : N * N := + match a with + | xH => + match b with xH => (1, 0)%N | _ => (0, 1)%N end + | xO a' => + let (q, r) := Pdiv_eucl a' b in + let r' := (2 * r)%N in + if (NPgeb r' b) then (2 * q + 1, (Nminus r' (Npos b)))%N + else (2 * q, r')%N + | xI a' => + let (q, r) := Pdiv_eucl a' b in + let r' := (2 * r + 1)%N in + if (NPgeb r' b) then (2 * q + 1, (Nminus r' (Npos b)))%N + else (2 * q, r')%N + end. + +Definition ZOdiv_eucl (a b:Z) : Z * Z := + match a, b with + | Z0, _ => (Z0, Z0) + | _, Z0 => (Z0, a) + | Zpos na, Zpos nb => + let (nq, nr) := Pdiv_eucl na nb in + (Z_of_N nq, Z_of_N nr) + | Zneg na, Zpos nb => + let (nq, nr) := Pdiv_eucl na nb in + (Zopp (Z_of_N nq), Zopp (Z_of_N nr)) + | Zpos na, Zneg nb => + let (nq, nr) := Pdiv_eucl na nb in + (Zopp (Z_of_N nq), Z_of_N nr) + | Zneg na, Zneg nb => + let (nq, nr) := Pdiv_eucl na nb in + (Z_of_N nq, Zopp (Z_of_N nr)) + end. + +Definition ZOdiv a b := fst (ZOdiv_eucl a b). +Definition ZOmod a b := snd (ZOdiv_eucl a b). + + +Definition Ndiv_eucl (a b:N) : N * N := + match a, b with + | N0, _ => (N0, N0) + | _, N0 => (N0, 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). + + +(* Proofs of specifications for these euclidean divisions. *) + +Theorem NPgeb_correct: forall (a:N)(b:positive), + if NPgeb a b then a = (Nminus a (Npos b) + Npos b)%N else True. +Proof. + destruct a; intros; simpl; auto. + generalize (Pcompare_Eq_eq p b). + case_eq (Pcompare p b Eq); intros; auto. + rewrite H0; auto. + now rewrite Pminus_mask_diag. + destruct (Pminus_mask_Gt p b H) as [d [H2 [H3 _]]]. + rewrite H2. rewrite <- H3. + simpl; f_equal; apply Pplus_comm. +Qed. + +Hint Rewrite Z_of_N_plus Z_of_N_mult Z_of_N_minus Zmult_1_l Zmult_assoc + Zmult_plus_distr_l Zmult_plus_distr_r : zdiv. +Hint Rewrite <- Zplus_assoc : zdiv. + +Theorem Pdiv_eucl_correct: forall a b, + let (q,r) := Pdiv_eucl a b in + Zpos a = Z_of_N q * Zpos b + Z_of_N 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. + generalize (NPgeb_correct (2 * r1 + 1) b); case NPgeb; intros H. + set (u := Nminus (2 * r1 + 1) (Npos b)) in * |- *. + assert (HH: Z_of_N u = (Z_of_N (2 * r1 + 1) - Zpos b)%Z). + rewrite H; autorewrite with zdiv; simpl. + rewrite Zplus_comm, Zminus_plus; trivial. + rewrite HH; autorewrite with zdiv; simpl Z_of_N. + rewrite Zpos_xI, Hq1. + autorewrite with zdiv; f_equal; rewrite Zplus_minus; trivial. + rewrite Zpos_xI, Hq1; autorewrite with zdiv; auto. + intros b; generalize (IHa b); case Pdiv_eucl. + intros q1 r1 Hq1. + generalize (NPgeb_correct (2 * r1) b); case NPgeb; intros H. + set (u := Nminus (2 * r1) (Npos b)) in * |- *. + assert (HH: Z_of_N u = (Z_of_N (2 * r1) - Zpos b)%Z). + rewrite H; autorewrite with zdiv; simpl. + rewrite Zplus_comm, Zminus_plus; trivial. + rewrite HH; autorewrite with zdiv; simpl Z_of_N. + rewrite Zpos_xO, Hq1. + autorewrite with zdiv; f_equal; rewrite Zplus_minus; trivial. + rewrite Zpos_xO, Hq1; autorewrite with zdiv; auto. + destruct b; auto. +Qed. + +Theorem ZOdiv_eucl_correct: forall a b, + let (q,r) := ZOdiv_eucl a b in a = q * b + r. +Proof. + destruct a; destruct b; simpl; auto; + generalize (Pdiv_eucl_correct p p0); case Pdiv_eucl; auto; intros; + try change (Zneg p) with (Zopp (Zpos p)); rewrite H. + destruct n; auto. + repeat (rewrite Zopp_plus_distr || rewrite Zopp_mult_distr_l); trivial. + repeat (rewrite Zopp_plus_distr || rewrite Zopp_mult_distr_r); trivial. +Qed. + +Theorem Ndiv_eucl_correct: forall a b, + let (q,r) := Ndiv_eucl a b in a = (q * b + r)%N. +Proof. + destruct a; destruct b; simpl; auto; + generalize (Pdiv_eucl_correct p p0); case Pdiv_eucl; auto; intros; + destruct n; destruct n0; simpl; simpl in H; try discriminate; + injection H; intros; subst; trivial. +Qed. diff --git a/theories/ZArith/Zabs.v b/theories/ZArith/Zabs.v index ed641358..c15493e3 100644 --- a/theories/ZArith/Zabs.v +++ b/theories/ZArith/Zabs.v @@ -5,14 +5,16 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zabs.v 9302 2006-10-27 21:21:17Z barras $ i*) +(*i $Id: Zabs.v 10302 2007-11-08 09:54:31Z letouzey $ i*) -(** Binary Integers (Pierre Crégut (CNET, Lannion, France) *) +(** Binary Integers (Pierre Crégut (CNET, Lannion, France) *) Require Import Arith_base. Require Import BinPos. Require Import BinInt. Require Import Zorder. +Require Import Zmax. +Require Import Znat. Require Import ZArith_dec. Open Local Scope Z_scope. @@ -63,6 +65,11 @@ Lemma Zabs_pos : forall n:Z, 0 <= Zabs n. intro x; destruct x; auto with arith; compute in |- *; intros H; inversion H. Qed. +Lemma Zabs_involutive : forall x:Z, Zabs (Zabs x) = Zabs x. +Proof. + intros; apply Zabs_eq; apply Zabs_pos. +Qed. + Theorem Zabs_eq_case : forall n m:Z, Zabs n = Zabs m -> n = m \/ n = - m. Proof. intros z1 z2; case z1; case z2; simpl in |- *; auto; @@ -70,6 +77,13 @@ Proof. (intros H2; rewrite H2); auto. Qed. +Lemma Zabs_spec : forall x:Z, + 0 <= x /\ Zabs x = x \/ + 0 > x /\ Zabs x = -x. +Proof. + intros; unfold Zabs, Zle, Zgt; destruct x; simpl; intuition discriminate. +Qed. + (** * Triangular inequality *) Hint Local Resolve Zle_neg_pos: zarith. @@ -106,25 +120,106 @@ Proof. intros z1 z2; case z1; case z2; simpl in |- *; auto. Qed. -(** * Absolute value in nat is compatible with order *) +Theorem Zabs_square : forall a, Zabs a * Zabs a = a * a. +Proof. + destruct a; simpl; auto. +Qed. + +(** * Results about absolute value in nat. *) + +Theorem inj_Zabs_nat : forall z:Z, Z_of_nat (Zabs_nat z) = Zabs z. +Proof. + destruct z; simpl; auto; symmetry; apply Zpos_eq_Z_of_nat_o_nat_of_P. +Qed. + +Theorem Zabs_nat_Z_of_nat: forall n, Zabs_nat (Z_of_nat n) = n. +Proof. + destruct n; simpl; auto. + apply nat_of_P_o_P_of_succ_nat_eq_succ. +Qed. + +Lemma Zabs_nat_mult: forall n m:Z, Zabs_nat (n*m) = (Zabs_nat n * Zabs_nat m)%nat. +Proof. + intros; apply inj_eq_rev. + rewrite inj_mult; repeat rewrite inj_Zabs_nat; apply Zabs_Zmult. +Qed. + +Lemma Zabs_nat_Zsucc: + forall p, 0 <= p -> Zabs_nat (Zsucc p) = S (Zabs_nat p). +Proof. + intros; apply inj_eq_rev. + rewrite inj_S; repeat rewrite inj_Zabs_nat, Zabs_eq; auto with zarith. +Qed. + +Lemma Zabs_nat_Zplus: + forall x y, 0<=x -> 0<=y -> Zabs_nat (x+y) = (Zabs_nat x + Zabs_nat y)%nat. +Proof. + intros; apply inj_eq_rev. + rewrite inj_plus; repeat rewrite inj_Zabs_nat, Zabs_eq; auto with zarith. + apply Zplus_le_0_compat; auto. +Qed. + +Lemma Zabs_nat_Zminus: + forall x y, 0 <= x <= y -> Zabs_nat (y - x) = (Zabs_nat y - Zabs_nat x)%nat. +Proof. + intros x y (H,H'). + assert (0 <= y) by (apply Zle_trans with x; auto). + assert (0 <= y-x) by (apply Zle_minus_le_0; auto). + apply inj_eq_rev. + rewrite inj_minus; repeat rewrite inj_Zabs_nat, Zabs_eq; auto. + rewrite Zmax_right; auto. +Qed. + +Lemma Zabs_nat_le : + forall n m:Z, 0 <= n <= m -> (Zabs_nat n <= Zabs_nat m)%nat. +Proof. + intros n m (H,H'); apply inj_le_rev. + repeat rewrite inj_Zabs_nat, Zabs_eq; auto. + apply Zle_trans with n; auto. +Qed. Lemma Zabs_nat_lt : - forall n m:Z, 0 <= n /\ n < m -> (Zabs_nat n < Zabs_nat m)%nat. + forall n m:Z, 0 <= n < m -> (Zabs_nat n < Zabs_nat m)%nat. +Proof. + intros n m (H,H'); apply inj_lt_rev. + repeat rewrite inj_Zabs_nat, Zabs_eq; auto. + apply Zlt_le_weak; apply Zle_lt_trans with n; auto. +Qed. + +(** * Some results about the sign function. *) + +Lemma Zsgn_Zmult : forall a b, Zsgn (a*b) = Zsgn a * Zsgn b. +Proof. + destruct a; destruct b; simpl; auto. +Qed. + +Lemma Zsgn_Zopp : forall a, Zsgn (-a) = - Zsgn a. Proof. - intros x y. case x; simpl in |- *. case y; simpl in |- *. + destruct a; simpl; auto. +Qed. - intro. absurd (0 < 0). compute in |- *. intro H0. discriminate H0. intuition. - intros. elim (ZL4 p). intros. rewrite H0. auto with arith. - intros. elim (ZL4 p). intros. rewrite H0. auto with arith. - - case y; simpl in |- *. - intros. absurd (Zpos p < 0). compute in |- *. intro H0. discriminate H0. intuition. - intros. change (nat_of_P p > nat_of_P p0)%nat in |- *. - apply nat_of_P_gt_Gt_compare_morphism. - elim H; auto with arith. intro. exact (ZC2 p0 p). +(** A characterization of the sign function: *) - intros. absurd (Zpos p0 < Zneg p). - compute in |- *. intro H0. discriminate H0. intuition. +Lemma Zsgn_spec : forall x:Z, + 0 < x /\ Zsgn x = 1 \/ + 0 = x /\ Zsgn x = 0 \/ + 0 > x /\ Zsgn x = -1. +Proof. + intros; unfold Zsgn, Zle, Zgt; destruct x; compute; intuition. +Qed. - intros. absurd (0 <= Zneg p). compute in |- *. auto with arith. intuition. +Lemma Zsgn_pos : forall x:Z, Zsgn x = 1 <-> 0 < x. +Proof. + destruct x; now intuition. Qed. + +Lemma Zsgn_neg : forall x:Z, Zsgn x = -1 <-> x < 0. +Proof. + destruct x; now intuition. +Qed. + +Lemma Zsgn_null : forall x:Z, Zsgn x = 0 <-> x = 0. +Proof. + destruct x; now intuition. +Qed. + diff --git a/theories/ZArith/Zbool.v b/theories/ZArith/Zbool.v index 7da91c44..34114d46 100644 --- a/theories/ZArith/Zbool.v +++ b/theories/ZArith/Zbool.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: Zbool.v 9245 2006-10-17 12:53:34Z notin $ *) +(* $Id: Zbool.v 10063 2007-08-08 14:21:03Z emakarov $ *) Require Import BinInt. Require Import Zeven. @@ -104,7 +104,7 @@ Qed. Lemma Zle_bool_imp_le : forall n m:Z, Zle_bool n m = true -> (n <= m)%Z. Proof. - unfold Zle_bool, Zle in |- *. intros x y. unfold not in |- *. + unfold Zle_bool, Zle in |- *. intros x y. unfold not in |- *. case (x ?= y)%Z; intros; discriminate. Qed. @@ -178,6 +178,18 @@ Proof. intro. apply Zle_ge. apply Zle_bool_imp_le. assumption. Qed. +Lemma Zlt_is_lt_bool : forall n m:Z, (n < m)%Z <-> Zlt_bool n m = true. +Proof. +intros n m; unfold Zlt_bool, Zlt. +destruct (n ?= m)%Z; simpl; split; now intro. +Qed. + +Lemma Zgt_is_gt_bool : forall n m:Z, (n > m)%Z <-> Zgt_bool n m = true. +Proof. +intros n m; unfold Zgt_bool, Zgt. +destruct (n ?= m)%Z; simpl; split; now intro. +Qed. + Lemma Zlt_is_le_bool : forall n m:Z, (n < m)%Z <-> Zle_bool n (m - 1) = true. Proof. diff --git a/theories/ZArith/Zcomplements.v b/theories/ZArith/Zcomplements.v index 78c8a976..c6ade934 100644 --- a/theories/ZArith/Zcomplements.v +++ b/theories/ZArith/Zcomplements.v @@ -6,11 +6,11 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zcomplements.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Zcomplements.v 10617 2008-03-04 18:07:16Z letouzey $ i*) Require Import ZArithRing. Require Import ZArith_base. -Require Import Omega. +Require Export Omega. Require Import Wf_nat. Open Local Scope Z_scope. @@ -160,7 +160,7 @@ Qed. Require Import List. -Fixpoint Zlength_aux (acc:Z) (A:Set) (l:list A) {struct l} : Z := +Fixpoint Zlength_aux (acc:Z) (A:Type) (l:list A) {struct l} : Z := match l with | nil => acc | _ :: l => Zlength_aux (Zsucc acc) A l @@ -171,7 +171,7 @@ Implicit Arguments Zlength [A]. Section Zlength_properties. - Variable A : Set. + Variable A : Type. Implicit Type l : list A. diff --git a/theories/ZArith/Zdiv.v b/theories/ZArith/Zdiv.v index 31f68207..4c560c6b 100644 --- a/theories/ZArith/Zdiv.v +++ b/theories/ZArith/Zdiv.v @@ -6,9 +6,9 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zdiv.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Zdiv.v 10999 2008-05-27 15:55:22Z letouzey $ i*) -(* Contribution by Claude Marché and Xavier Urbain *) +(* Contribution by Claude Marché and Xavier Urbain *) (** Euclidean Division @@ -21,6 +21,7 @@ Require Import Zbool. Require Import Omega. Require Import ZArithRing. Require Import Zcomplements. +Require Export Setoid. Open Local Scope Z_scope. (** * Definitions of Euclidian operations *) @@ -70,8 +71,21 @@ Unboxed Fixpoint Zdiv_eucl_POS (a:positive) (b:Z) {struct a} : if r = 0 then (-q,0) else (-(q+1),b+r) In other word, when b is non-zero, q is chosen to be the greatest integer - smaller or equal to a/b. And sgn(r)=sgn(b) and |r| < |b|. + smaller or equal to a/b. And sgn(r)=sgn(b) and |r| < |b| (at least when + r is not null). +*) + +(* Nota: At least two others conventions also exist for euclidean division. + They all satify the equation a=b*q+r, but differ on the choice of (q,r) + on negative numbers. + + * Ocaml uses Round-Toward-Zero division: (-a)/b = a/(-b) = -(a/b). + Hence (-a) mod b = - (a mod b) + a mod (-b) = a mod b + And: |r| < |b| and sgn(r) = sgn(a) (notice the a here instead of b). + * Another solution is to always pick a non-negative remainder: + a=b*q+r with 0 <= r < |b| *) Definition Zdiv_eucl (a b:Z) : Z * Z := @@ -96,7 +110,7 @@ Definition Zdiv_eucl (a b:Z) : Z * Z := (** Division and modulo are projections of [Zdiv_eucl] *) - + Definition Zdiv (a b:Z) : Z := let (q, _) := Zdiv_eucl a b in q. Definition Zmod (a b:Z) : Z := let (_, r) := Zdiv_eucl a b in r. @@ -108,20 +122,20 @@ Infix "mod" := Zmod (at level 40, no associativity) : Z_scope. (* Tests: -Eval Compute in `(Zdiv_eucl 7 3)`. +Eval compute in (Zdiv_eucl 7 3). -Eval Compute in `(Zdiv_eucl (-7) 3)`. +Eval compute in (Zdiv_eucl (-7) 3). -Eval Compute in `(Zdiv_eucl 7 (-3))`. +Eval compute in (Zdiv_eucl 7 (-3)). -Eval Compute in `(Zdiv_eucl (-7) (-3))`. +Eval compute in (Zdiv_eucl (-7) (-3)). *) (** * Main division theorem *) -(** First a lemma for positive *) +(** First a lemma for two positive arguments *) Lemma Z_div_mod_POS : forall b:Z, @@ -129,7 +143,8 @@ Lemma Z_div_mod_POS : forall a:positive, let (q, r) := Zdiv_eucl_POS a b in Zpos a = b * q + r /\ 0 <= r < b. Proof. -simple induction a; unfold Zdiv_eucl_POS in |- *; fold Zdiv_eucl_POS in |- *. +simple induction a; cbv beta iota delta [Zdiv_eucl_POS] in |- *; + fold Zdiv_eucl_POS in |- *; cbv zeta. intro p; case (Zdiv_eucl_POS p b); intros q r [H0 H1]. generalize (Zgt_cases b (2 * r + 1)). @@ -147,6 +162,7 @@ case (Zge_bool b 2); (intros; split; [ try ring | omega ]). omega. Qed. +(** Then the usual situation of a positive [b] and no restriction on [a] *) Theorem Z_div_mod : forall a b:Z, @@ -166,27 +182,131 @@ Proof. intros [H1 H2]. split; trivial. - replace (Zneg p0) with (- Zpos p0); [ rewrite H1; ring | trivial ]. + change (Zneg p0) with (- Zpos p0); rewrite H1; ring. intros p1 [H1 H2]. split; trivial. - replace (Zneg p0) with (- Zpos p0); [ rewrite H1; ring | trivial ]. + change (Zneg p0) with (- Zpos p0); rewrite H1; ring. generalize (Zorder.Zgt_pos_0 p1); omega. intros p1 [H1 H2]. split; trivial. - replace (Zneg p0) with (- Zpos p0); [ rewrite H1; ring | trivial ]. + change (Zneg p0) with (- Zpos p0); rewrite H1; ring. generalize (Zorder.Zlt_neg_0 p1); omega. intros; discriminate. Qed. -(** Existence theorems *) +(** For stating the fully general result, let's give a short name + to the condition on the remainder. *) -Theorem Zdiv_eucl_exist : - forall b:Z, - b > 0 -> - forall a:Z, {qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < b}. +Definition Remainder r b := 0 <= r < b \/ b < r <= 0. + +(** Another equivalent formulation: *) + +Definition Remainder_alt r b := Zabs r < Zabs b /\ Zsgn r <> - Zsgn b. + +(* In the last formulation, [ Zsgn r <> - Zsgn b ] is less nice than saying + [ Zsgn r = Zsgn b ], but at least it works even when [r] is null. *) + +Lemma Remainder_equiv : forall r b, Remainder r b <-> Remainder_alt r b. +Proof. + intros; unfold Remainder, Remainder_alt; omega with *. +Qed. + +Hint Unfold Remainder. + +(** Now comes the fully general result about Euclidean division. *) + +Theorem Z_div_mod_full : + forall a b:Z, + b <> 0 -> let (q, r) := Zdiv_eucl a b in a = b * q + r /\ Remainder r b. +Proof. + destruct b as [|b|b]. + (* b = 0 *) + intro H; elim H; auto. + (* b > 0 *) + intros _. + assert (Zpos b > 0) by auto with zarith. + generalize (Z_div_mod a (Zpos b) H). + destruct Zdiv_eucl as (q,r); intuition; simpl; auto. + (* b < 0 *) + intros _. + assert (Zpos b > 0) by auto with zarith. + generalize (Z_div_mod a (Zpos b) H). + unfold Remainder. + destruct a as [|a|a]. + (* a = 0 *) + simpl; intuition. + (* a > 0 *) + unfold Zdiv_eucl; destruct Zdiv_eucl_POS as (q,r). + destruct r as [|r|r]; [ | | omega with *]. + rewrite <- Zmult_opp_comm; simpl Zopp; intuition. + rewrite <- Zmult_opp_comm; simpl Zopp. + rewrite Zmult_plus_distr_r; omega with *. + (* a < 0 *) + unfold Zdiv_eucl. + generalize (Z_div_mod_POS (Zpos b) H a). + destruct Zdiv_eucl_POS as (q,r). + destruct r as [|r|r]; change (Zneg b) with (-Zpos b). + rewrite Zmult_opp_comm; omega with *. + rewrite <- Zmult_opp_comm, Zmult_plus_distr_r; + repeat rewrite Zmult_opp_comm; omega. + rewrite Zmult_opp_comm; omega with *. +Qed. + +(** The same results as before, stated separately in terms of Zdiv and Zmod *) + +Lemma Z_mod_remainder : forall a b:Z, b<>0 -> Remainder (a mod b) b. +Proof. + unfold Zmod; intros a b Hb; generalize (Z_div_mod_full a b Hb); auto. + destruct Zdiv_eucl; tauto. +Qed. + +Lemma Z_mod_lt : forall a b:Z, b > 0 -> 0 <= a mod b < b. +Proof. + unfold Zmod; intros a b Hb; generalize (Z_div_mod a b Hb). + destruct Zdiv_eucl; tauto. +Qed. + +Lemma Z_mod_neg : forall a b:Z, b < 0 -> b < a mod b <= 0. +Proof. + unfold Zmod; intros a b Hb. + assert (Hb' : b<>0) by (auto with zarith). + generalize (Z_div_mod_full a b Hb'). + destruct Zdiv_eucl. + unfold Remainder; intuition. +Qed. + +Lemma Z_div_mod_eq_full : forall a b:Z, b <> 0 -> a = b*(a/b) + (a mod b). +Proof. + unfold Zdiv, Zmod; intros a b Hb; generalize (Z_div_mod_full a b Hb). + destruct Zdiv_eucl; tauto. +Qed. + +Lemma Z_div_mod_eq : forall a b:Z, b > 0 -> a = b*(a/b) + (a mod b). +Proof. + intros; apply Z_div_mod_eq_full; auto with zarith. +Qed. + +Lemma Zmod_eq_full : forall a b:Z, b<>0 -> a mod b = a - (a/b)*b. +Proof. + intros. + rewrite <- Zeq_plus_swap, Zplus_comm, Zmult_comm; symmetry. + apply Z_div_mod_eq_full; auto. +Qed. + +Lemma Zmod_eq : forall a b:Z, b>0 -> a mod b = a - (a/b)*b. +Proof. + intros. + rewrite <- Zeq_plus_swap, Zplus_comm, Zmult_comm; symmetry. + apply Z_div_mod_eq; auto. +Qed. + +(** Existence theorem *) + +Theorem Zdiv_eucl_exist : forall (b:Z)(Hb:b>0)(a:Z), + {qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < b}. Proof. intros b Hb a. exists (Zdiv_eucl a b). @@ -195,70 +315,180 @@ Qed. Implicit Arguments Zdiv_eucl_exist. -Theorem Zdiv_eucl_extended : - forall b:Z, - b <> 0 -> - forall a:Z, - {qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Zabs b}. + +(** Uniqueness theorems *) + +Theorem Zdiv_mod_unique : + forall b q1 q2 r1 r2:Z, + 0 <= r1 < Zabs b -> 0 <= r2 < Zabs b -> + b*q1+r1 = b*q2+r2 -> q1=q2 /\ r1=r2. Proof. - intros b Hb a. - elim (Z_le_gt_dec 0 b); intro Hb'. - cut (b > 0); [ intro Hb'' | omega ]. - rewrite Zabs_eq; [ apply Zdiv_eucl_exist; assumption | assumption ]. - cut (- b > 0); [ intro Hb'' | omega ]. - elim (Zdiv_eucl_exist Hb'' a); intros qr. - elim qr; intros q r Hqr. - exists (- q, r). - elim Hqr; intros. - split. - rewrite <- Zmult_opp_comm; assumption. - rewrite Zabs_non_eq; [ assumption | omega ]. +intros b q1 q2 r1 r2 Hr1 Hr2 H. +destruct (Z_eq_dec q1 q2) as [Hq|Hq]. +split; trivial. +rewrite Hq in H; omega. +elim (Zlt_not_le (Zabs (r2 - r1)) (Zabs b)). +omega with *. +replace (r2-r1) with (b*(q1-q2)) by (rewrite Zmult_minus_distr_l; omega). +replace (Zabs b) with ((Zabs b)*1) by ring. +rewrite Zabs_Zmult. +apply Zmult_le_compat_l; auto with *. +omega with *. Qed. -Implicit Arguments Zdiv_eucl_extended. +Theorem Zdiv_mod_unique_2 : + forall b q1 q2 r1 r2:Z, + Remainder r1 b -> Remainder r2 b -> + b*q1+r1 = b*q2+r2 -> q1=q2 /\ r1=r2. +Proof. +unfold Remainder. +intros b q1 q2 r1 r2 Hr1 Hr2 H. +destruct (Z_eq_dec q1 q2) as [Hq|Hq]. +split; trivial. +rewrite Hq in H; omega. +elim (Zlt_not_le (Zabs (r2 - r1)) (Zabs b)). +omega with *. +replace (r2-r1) with (b*(q1-q2)) by (rewrite Zmult_minus_distr_l; omega). +replace (Zabs b) with ((Zabs b)*1) by ring. +rewrite Zabs_Zmult. +apply Zmult_le_compat_l; auto with *. +omega with *. +Qed. -(** * Auxiliary lemmas about [Zdiv] and [Zmod] *) +Theorem Zdiv_unique_full: + forall a b q r, Remainder r b -> + a = b*q + r -> q = a/b. +Proof. + intros. + assert (b <> 0) by (unfold Remainder in *; omega with *). + generalize (Z_div_mod_full a b H1). + unfold Zdiv; destruct Zdiv_eucl as (q',r'). + intros (H2,H3); rewrite H2 in H0. + destruct (Zdiv_mod_unique_2 b q q' r r'); auto. +Qed. -Lemma Z_div_mod_eq : forall a b:Z, b > 0 -> a = b * Zdiv a b + Zmod a b. +Theorem Zdiv_unique: + forall a b q r, 0 <= r < b -> + a = b*q + r -> q = a/b. Proof. - unfold Zdiv, Zmod in |- *. - intros a b Hb. - generalize (Z_div_mod a b Hb). - case Zdiv_eucl; tauto. + intros; eapply Zdiv_unique_full; eauto. Qed. -Lemma Z_mod_lt : forall a b:Z, b > 0 -> 0 <= Zmod a b < b. +Theorem Zmod_unique_full: + forall a b q r, Remainder r b -> + a = b*q + r -> r = a mod b. Proof. - unfold Zmod in |- *. - intros a b Hb. - generalize (Z_div_mod a b Hb). - case (Zdiv_eucl a b); tauto. + intros. + assert (b <> 0) by (unfold Remainder in *; omega with *). + generalize (Z_div_mod_full a b H1). + unfold Zmod; destruct Zdiv_eucl as (q',r'). + intros (H2,H3); rewrite H2 in H0. + destruct (Zdiv_mod_unique_2 b q q' r r'); auto. Qed. -Lemma Z_div_POS_ge0 : - forall (b:Z) (a:positive), let (q, _) := Zdiv_eucl_POS a b in q >= 0. +Theorem Zmod_unique: + forall a b q r, 0 <= r < b -> + a = b*q + r -> r = a mod b. Proof. - simple induction a; unfold Zdiv_eucl_POS in |- *; fold Zdiv_eucl_POS in |- *. - intro p; case (Zdiv_eucl_POS p b). - intros; case (Zgt_bool b (2 * z0 + 1)); intros; omega. - intro p; case (Zdiv_eucl_POS p b). - intros; case (Zgt_bool b (2 * z0)); intros; omega. - case (Zge_bool b 2); simpl in |- *; omega. + intros; eapply Zmod_unique_full; eauto. Qed. -Lemma Z_div_ge0 : forall a b:Z, b > 0 -> a >= 0 -> Zdiv a b >= 0. +(** * Basic values of divisions and modulo. *) + +Lemma Zmod_0_l: forall a, 0 mod a = 0. Proof. - intros a b Hb; unfold Zdiv, Zdiv_eucl in |- *; case a; simpl in |- *; intros. - case b; simpl in |- *; trivial. - generalize Hb; case b; try trivial. - auto with zarith. - intros p0 Hp0; generalize (Z_div_POS_ge0 (Zpos p0) p). - case (Zdiv_eucl_POS p (Zpos p0)); simpl in |- *; tauto. - intros; discriminate. - elim H; trivial. + destruct a; simpl; auto. +Qed. + +Lemma Zmod_0_r: forall a, a mod 0 = 0. +Proof. + destruct a; simpl; auto. +Qed. + +Lemma Zdiv_0_l: forall a, 0/a = 0. +Proof. + destruct a; simpl; auto. +Qed. + +Lemma Zdiv_0_r: forall a, a/0 = 0. +Proof. + destruct a; simpl; auto. +Qed. + +Lemma Zmod_1_r: forall a, a mod 1 = 0. +Proof. + intros; symmetry; apply Zmod_unique with a; auto with zarith. Qed. -Lemma Z_div_lt : forall a b:Z, b >= 2 -> a > 0 -> Zdiv a b < a. +Lemma Zdiv_1_r: forall a, a/1 = a. +Proof. + intros; symmetry; apply Zdiv_unique with 0; auto with zarith. +Qed. + +Hint Resolve Zmod_0_l Zmod_0_r Zdiv_0_l Zdiv_0_r Zdiv_1_r Zmod_1_r + : zarith. + +Lemma Zdiv_1_l: forall a, 1 < a -> 1/a = 0. +Proof. + intros; symmetry; apply Zdiv_unique with 1; auto with zarith. +Qed. + +Lemma Zmod_1_l: forall a, 1 < a -> 1 mod a = 1. +Proof. + intros; symmetry; apply Zmod_unique with 0; auto with zarith. +Qed. + +Lemma Z_div_same_full : forall a:Z, a<>0 -> a/a = 1. +Proof. + intros; symmetry; apply Zdiv_unique_full with 0; auto with *; red; omega. +Qed. + +Lemma Z_mod_same_full : forall a, a mod a = 0. +Proof. + destruct a; intros; symmetry. + compute; auto. + apply Zmod_unique with 1; auto with *; omega with *. + apply Zmod_unique_full with 1; auto with *; red; omega with *. +Qed. + +Lemma Z_mod_mult : forall a b, (a*b) mod b = 0. +Proof. + intros a b; destruct (Z_eq_dec b 0) as [Hb|Hb]. + subst; simpl; rewrite Zmod_0_r; auto. + symmetry; apply Zmod_unique_full with a; [ red; omega | ring ]. +Qed. + +Lemma Z_div_mult_full : forall a b:Z, b <> 0 -> (a*b)/b = a. +Proof. + intros; symmetry; apply Zdiv_unique_full with 0; auto with zarith; + [ red; omega | ring]. +Qed. + +(** * Order results about Zmod and Zdiv *) + +(* Division of positive numbers is positive. *) + +Lemma Z_div_pos: forall a b, b > 0 -> 0 <= a -> 0 <= a/b. +Proof. + intros. + rewrite (Z_div_mod_eq a b H) in H0. + assert (H1:=Z_mod_lt a b H). + destruct (Z_lt_le_dec (a/b) 0); auto. + assert (b*(a/b) <= -b). + replace (-b) with (b*-1); [ | ring]. + apply Zmult_le_compat_l; auto with zarith. + omega. +Qed. + +Lemma Z_div_ge0: forall a b, b > 0 -> a >= 0 -> a/b >=0. +Proof. + intros; generalize (Z_div_pos a b H); auto with zarith. +Qed. + +(** As soon as the divisor is greater or equal than 2, + the division is strictly decreasing. *) + +Lemma Z_div_lt : forall a b:Z, b >= 2 -> a > 0 -> a/b < a. Proof. intros. cut (b > 0); [ intro Hb | omega ]. generalize (Z_div_mod a b Hb). @@ -271,9 +501,24 @@ Proof. auto with zarith. Qed. -(** * Other lemmas (now using the syntax for [Zdiv] and [Zmod]). *) -Lemma Z_div_ge : forall a b c:Z, c > 0 -> a >= b -> a / c >= b / c. +(** A division of a small number by a bigger one yields zero. *) + +Theorem Zdiv_small: forall a b, 0 <= a < b -> a/b = 0. +Proof. + intros a b H; apply sym_equal; apply Zdiv_unique with a; auto with zarith. +Qed. + +(** Same situation, in term of modulo: *) + +Theorem Zmod_small: forall a n, 0 <= a < n -> a mod n = a. +Proof. + intros a b H; apply sym_equal; apply Zmod_unique with 0; auto with zarith. +Qed. + +(** [Zge] is compatible with a positive division. *) + +Lemma Z_div_ge : forall a b c:Z, c > 0 -> a >= b -> a/c >= b/c. Proof. intros a b c cPos aGeb. generalize (Z_div_mod_eq a c cPos). @@ -285,13 +530,8 @@ Proof. intro. absurd (b - a >= 1). omega. - rewrite H0. - rewrite H2. - assert - (c * (b / c) + b mod c - (c * (a / c) + a mod c) = - c * (b / c - a / c) + b mod c - a mod c). - ring. - rewrite H3. + replace (b-a) with (c * (b/c-a/c) + b mod c - a mod c) by + (symmetry; pattern a at 1; rewrite H2; pattern b at 1; rewrite H0; ring). assert (c * (b / c - a / c) >= c * 1). apply Zmult_ge_compat_l. omega. @@ -301,111 +541,639 @@ Proof. omega. Qed. -Lemma Z_mod_plus : forall a b c:Z, c > 0 -> (a + b * c) mod c = a mod c. +(** Same, with [Zle]. *) + +Lemma Z_div_le : forall a b c:Z, c > 0 -> a <= b -> a/c <= b/c. Proof. - intros a b c cPos. - generalize (Z_div_mod_eq a c cPos). - generalize (Z_mod_lt a c cPos). - generalize (Z_div_mod_eq (a + b * c) c cPos). - generalize (Z_mod_lt (a + b * c) c cPos). - intros. + intros a b c H H0. + apply Zge_le. + apply Z_div_ge; auto with *. +Qed. - assert ((a + b * c) mod c - a mod c = c * (b + a / c - (a + b * c) / c)). - replace ((a + b * c) mod c) with (a + b * c - c * ((a + b * c) / c)). - replace (a mod c) with (a - c * (a / c)). - ring. - omega. - omega. - set (q := b + a / c - (a + b * c) / c) in *. - apply (Zcase_sign q); intros. - assert (c * q = 0). - rewrite H4; ring. - rewrite H5 in H3. - omega. +(** With our choice of division, rounding of (a/b) is always done toward bottom: *) - assert (c * q >= c). - pattern c at 2 in |- *; replace c with (c * 1). - apply Zmult_ge_compat_l; omega. - ring. - omega. +Lemma Z_mult_div_ge : forall a b:Z, b > 0 -> b*(a/b) <= a. +Proof. + intros a b H; generalize (Z_div_mod_eq a b H) (Z_mod_lt a b H); omega. +Qed. + +Lemma Z_mult_div_ge_neg : forall a b:Z, b < 0 -> b*(a/b) >= a. +Proof. + intros a b H. + generalize (Z_div_mod_eq_full a _ (Zlt_not_eq _ _ H)) (Z_mod_neg a _ H); omega. +Qed. + +(** The previous inequalities are exact iff the modulo is zero. *) + +Lemma Z_div_exact_full_1 : forall a b:Z, a = b*(a/b) -> a mod b = 0. +Proof. + intros; destruct (Z_eq_dec b 0) as [Hb|Hb]. + subst b; simpl in *; subst; auto. + generalize (Z_div_mod_eq_full a b Hb); omega. +Qed. + +Lemma Z_div_exact_full_2 : forall a b:Z, b <> 0 -> a mod b = 0 -> a = b*(a/b). +Proof. + intros; generalize (Z_div_mod_eq_full a b H); omega. +Qed. + +(** A modulo cannot grow beyond its starting point. *) + +Theorem Zmod_le: forall a b, 0 < b -> 0 <= a -> a mod b <= a. +Proof. + intros a b H1 H2; case (Zle_or_lt b a); intros H3. + case (Z_mod_lt a b); auto with zarith. + rewrite Zmod_small; auto with zarith. +Qed. + +(** Some additionnal inequalities about Zdiv. *) + +Theorem Zdiv_le_upper_bound: + forall a b q, 0 <= a -> 0 < b -> a <= q*b -> a/b <= q. +Proof. + intros a b q H1 H2 H3. + apply Zmult_le_reg_r with b; auto with zarith. + apply Zle_trans with (2 := H3). + pattern a at 2; rewrite (Z_div_mod_eq a b); auto with zarith. + rewrite (Zmult_comm b); case (Z_mod_lt a b); auto with zarith. +Qed. + +Theorem Zdiv_lt_upper_bound: + forall a b q, 0 <= a -> 0 < b -> a < q*b -> a/b < q. +Proof. + intros a b q H1 H2 H3. + apply Zmult_lt_reg_r with b; auto with zarith. + apply Zle_lt_trans with (2 := H3). + pattern a at 2; rewrite (Z_div_mod_eq a b); auto with zarith. + rewrite (Zmult_comm b); case (Z_mod_lt a b); auto with zarith. +Qed. + +Theorem Zdiv_le_lower_bound: + forall a b q, 0 <= a -> 0 < b -> q*b <= a -> q <= a/b. +Proof. + intros a b q H1 H2 H3. + assert (q < a / b + 1); auto with zarith. + apply Zmult_lt_reg_r with b; auto with zarith. + apply Zle_lt_trans with (1 := H3). + pattern a at 1; rewrite (Z_div_mod_eq a b); auto with zarith. + rewrite Zmult_plus_distr_l; rewrite (Zmult_comm b); case (Z_mod_lt a b); + auto with zarith. +Qed. + + +(** A division of respect opposite monotonicity for the divisor *) + +Lemma Zdiv_le_compat_l: forall p q r, 0 <= p -> 0 < q < r -> + p / r <= p / q. +Proof. + intros p q r H H1. + apply Zdiv_le_lower_bound; auto with zarith. + rewrite Zmult_comm. + pattern p at 2; rewrite (Z_div_mod_eq p r); auto with zarith. + apply Zle_trans with (r * (p / r)); auto with zarith. + apply Zmult_le_compat_r; auto with zarith. + apply Zdiv_le_lower_bound; auto with zarith. + case (Z_mod_lt p r); auto with zarith. +Qed. + +Theorem Zdiv_sgn: forall a b, + 0 <= Zsgn (a/b) * Zsgn a * Zsgn b. +Proof. + destruct a as [ |a|a]; destruct b as [ |b|b]; simpl; auto with zarith; + generalize (Z_div_pos (Zpos a) (Zpos b)); unfold Zdiv, Zdiv_eucl; + destruct Zdiv_eucl_POS as (q,r); destruct r; omega with *. +Qed. + +(** * Relations between usual operations and Zmod and Zdiv *) + +Lemma Z_mod_plus_full : forall a b c:Z, (a + b * c) mod c = a mod c. +Proof. + intros; destruct (Z_eq_dec c 0) as [Hc|Hc]. + subst; do 2 rewrite Zmod_0_r; auto. + symmetry; apply Zmod_unique_full with (a/c+b); auto with zarith. + red; generalize (Z_mod_lt a c)(Z_mod_neg a c); omega. + rewrite Zmult_plus_distr_r, Zmult_comm. + generalize (Z_div_mod_eq_full a c Hc); omega. +Qed. + +Lemma Z_div_plus_full : forall a b c:Z, c <> 0 -> (a + b * c) / c = a / c + b. +Proof. + intro; symmetry. + apply Zdiv_unique_full with (a mod c); auto with zarith. + red; generalize (Z_mod_lt a c)(Z_mod_neg a c); omega. + rewrite Zmult_plus_distr_r, Zmult_comm. + generalize (Z_div_mod_eq_full a c H); omega. +Qed. + +Theorem Z_div_plus_full_l: forall a b c : Z, b <> 0 -> (a * b + c) / b = a + c / b. +Proof. + intros a b c H; rewrite Zplus_comm; rewrite Z_div_plus_full; + try apply Zplus_comm; auto with zarith. +Qed. - assert (c * q <= - c). - replace (- c) with (c * -1). - apply Zmult_le_compat_l; omega. +(** [Zopp] and [Zdiv], [Zmod]. + Due to the choice of convention for our Euclidean division, + some of the relations about [Zopp] and divisions are rather complex. *) + +Lemma Zdiv_opp_opp : forall a b:Z, (-a)/(-b) = a/b. +Proof. + intros [|a|a] [|b|b]; try reflexivity; unfold Zdiv; simpl; + destruct (Zdiv_eucl_POS a (Zpos b)); destruct z0; try reflexivity. +Qed. + +Lemma Zmod_opp_opp : forall a b:Z, (-a) mod (-b) = - (a mod b). +Proof. + intros; destruct (Z_eq_dec b 0) as [Hb|Hb]. + subst; do 2 rewrite Zmod_0_r; auto. + intros; symmetry. + apply Zmod_unique_full with ((-a)/(-b)); auto. + generalize (Z_mod_remainder a b Hb); destruct 1; [right|left]; omega. + rewrite Zdiv_opp_opp. + pattern a at 1; rewrite (Z_div_mod_eq_full a b Hb); ring. +Qed. + +Lemma Z_mod_zero_opp_full : forall a b:Z, a mod b = 0 -> (-a) mod b = 0. +Proof. + intros; destruct (Z_eq_dec b 0) as [Hb|Hb]. + subst; rewrite Zmod_0_r; auto. + rewrite Z_div_exact_full_2 with a b; auto. + replace (- (b * (a / b))) with (0 + - (a / b) * b). + rewrite Z_mod_plus_full; auto. ring. - omega. Qed. -Lemma Z_div_plus : forall a b c:Z, c > 0 -> (a + b * c) / c = a / c + b. +Lemma Z_mod_nz_opp_full : forall a b:Z, a mod b <> 0 -> + (-a) mod b = b - (a mod b). Proof. - intros a b c cPos. - generalize (Z_div_mod_eq a c cPos). - generalize (Z_mod_lt a c cPos). - generalize (Z_div_mod_eq (a + b * c) c cPos). - generalize (Z_mod_lt (a + b * c) c cPos). intros. - apply Zmult_reg_l with c. omega. - replace (c * ((a + b * c) / c)) with (a + b * c - (a + b * c) mod c). - rewrite (Z_mod_plus a b c cPos). - pattern a at 1 in |- *; rewrite H2. - ring. - pattern (a + b * c) at 1 in |- *; rewrite H0. - ring. + assert (b<>0) by (contradict H; subst; rewrite Zmod_0_r; auto). + symmetry; apply Zmod_unique_full with (-1-a/b); auto. + generalize (Z_mod_remainder a b H0); destruct 1; [left|right]; omega. + rewrite Zmult_minus_distr_l. + pattern a at 1; rewrite (Z_div_mod_eq_full a b H0); ring. Qed. -Lemma Z_div_mult : forall a b:Z, b > 0 -> a * b / b = a. - intros; replace (a * b) with (0 + a * b); auto. - rewrite Z_div_plus; auto. +Lemma Z_mod_zero_opp_r : forall a b:Z, a mod b = 0 -> a mod (-b) = 0. +Proof. + intros. + rewrite <- (Zopp_involutive a). + rewrite Zmod_opp_opp. + rewrite Z_mod_zero_opp_full; auto. Qed. -Lemma Z_mult_div_ge : forall a b:Z, b > 0 -> b * (a / b) <= a. +Lemma Z_mod_nz_opp_r : forall a b:Z, a mod b <> 0 -> + a mod (-b) = (a mod b) - b. Proof. - intros a b bPos. - generalize (Z_div_mod_eq a _ bPos); intros. - generalize (Z_mod_lt a _ bPos); intros. - pattern a at 2 in |- *; rewrite H. - omega. + intros. + pattern a at 1; rewrite <- (Zopp_involutive a). + rewrite Zmod_opp_opp. + rewrite Z_mod_nz_opp_full; auto; omega. +Qed. + +Lemma Z_div_zero_opp_full : forall a b:Z, a mod b = 0 -> (-a)/b = -(a/b). +Proof. + intros; destruct (Z_eq_dec b 0) as [Hb|Hb]. + subst; do 2 rewrite Zdiv_0_r; auto. + symmetry; apply Zdiv_unique_full with 0; auto. + red; omega. + pattern a at 1; rewrite (Z_div_mod_eq_full a b Hb). + rewrite H; ring. Qed. -Lemma Z_mod_same : forall a:Z, a > 0 -> a mod a = 0. +Lemma Z_div_nz_opp_full : forall a b:Z, a mod b <> 0 -> + (-a)/b = -(a/b)-1. Proof. - intros a aPos. - generalize (Z_mod_plus 0 1 a aPos). - replace (0 + 1 * a) with a. intros. - rewrite H. - compute in |- *. - trivial. - ring. + assert (b<>0) by (contradict H; subst; rewrite Zmod_0_r; auto). + symmetry; apply Zdiv_unique_full with (b-a mod b); auto. + generalize (Z_mod_remainder a b H0); destruct 1; [left|right]; omega. + pattern a at 1; rewrite (Z_div_mod_eq_full a b H0); ring. +Qed. + +Lemma Z_div_zero_opp_r : forall a b:Z, a mod b = 0 -> a/(-b) = -(a/b). +Proof. + intros. + pattern a at 1; rewrite <- (Zopp_involutive a). + rewrite Zdiv_opp_opp. + rewrite Z_div_zero_opp_full; auto. +Qed. + +Lemma Z_div_nz_opp_r : forall a b:Z, a mod b <> 0 -> + a/(-b) = -(a/b)-1. +Proof. + intros. + pattern a at 1; rewrite <- (Zopp_involutive a). + rewrite Zdiv_opp_opp. + rewrite Z_div_nz_opp_full; auto; omega. +Qed. + +(** Cancellations. *) + +Lemma Zdiv_mult_cancel_r : forall a b c:Z, + c <> 0 -> (a*c)/(b*c) = a/b. +Proof. +assert (X: forall a b c, b > 0 -> c > 0 -> (a*c) / (b*c) = a / b). + intros a b c Hb Hc. + symmetry. + apply Zdiv_unique with ((a mod b)*c); auto with zarith. + destruct (Z_mod_lt a b Hb); split. + apply Zmult_le_0_compat; auto with zarith. + apply Zmult_lt_compat_r; auto with zarith. + pattern a at 1; rewrite (Z_div_mod_eq a b Hb); ring. +intros a b c Hc. +destruct (Z_dec b 0) as [Hb|Hb]. +destruct Hb as [Hb|Hb]; destruct (not_Zeq_inf _ _ Hc); auto with *. +rewrite <- (Zdiv_opp_opp a), <- (Zmult_opp_opp b), <-(Zmult_opp_opp a); + auto with *. +rewrite <- (Zdiv_opp_opp a), <- Zdiv_opp_opp, Zopp_mult_distr_l, + Zopp_mult_distr_l; auto with *. +rewrite <- Zdiv_opp_opp, Zopp_mult_distr_r, Zopp_mult_distr_r; auto with *. +rewrite Hb; simpl; do 2 rewrite Zdiv_0_r; auto. Qed. -Lemma Z_div_same : forall a:Z, a > 0 -> a / a = 1. +Lemma Zdiv_mult_cancel_l : forall a b c:Z, + c<>0 -> (c*a)/(c*b) = a/b. Proof. - intros a aPos. - generalize (Z_div_plus 0 1 a aPos). - replace (0 + 1 * a) with a. intros. - rewrite H. - compute in |- *. - trivial. + rewrite (Zmult_comm c a); rewrite (Zmult_comm c b). + apply Zdiv_mult_cancel_r; auto. +Qed. + +Lemma Zmult_mod_distr_l: forall a b c, + (c*a) mod (c*b) = c * (a mod b). +Proof. + intros; destruct (Z_eq_dec c 0) as [Hc|Hc]. + subst; simpl; rewrite Zmod_0_r; auto. + destruct (Z_eq_dec b 0) as [Hb|Hb]. + subst; repeat rewrite Zmult_0_r || rewrite Zmod_0_r; auto. + assert (c*b <> 0). + contradict Hc; eapply Zmult_integral_l; eauto. + rewrite (Zplus_minus_eq _ _ _ (Z_div_mod_eq_full (c*a) (c*b) H)). + rewrite (Zplus_minus_eq _ _ _ (Z_div_mod_eq_full a b Hb)). + rewrite Zdiv_mult_cancel_l; auto with zarith. ring. Qed. -Lemma Z_div_exact_1 : forall a b:Z, b > 0 -> a = b * (a / b) -> a mod b = 0. - intros a b Hb; generalize (Z_div_mod a b Hb); unfold Zmod, Zdiv in |- *. - case (Zdiv_eucl a b); intros q r; omega. +Lemma Zmult_mod_distr_r: forall a b c, + (a*c) mod (b*c) = (a mod b) * c. +Proof. + intros; repeat rewrite (fun x => (Zmult_comm x c)). + apply Zmult_mod_distr_l; auto. +Qed. + +(** Operations modulo. *) + +Theorem Zmod_mod: forall a n, (a mod n) mod n = a mod n. +Proof. + intros; destruct (Z_eq_dec n 0) as [Hb|Hb]. + subst; do 2 rewrite Zmod_0_r; auto. + pattern a at 2; rewrite (Z_div_mod_eq_full a n); auto with zarith. + rewrite Zplus_comm; rewrite Zmult_comm. + apply sym_equal; apply Z_mod_plus_full; auto with zarith. +Qed. + +Theorem Zmult_mod: forall a b n, + (a * b) mod n = ((a mod n) * (b mod n)) mod n. +Proof. + intros; destruct (Z_eq_dec n 0) as [Hb|Hb]. + subst; do 2 rewrite Zmod_0_r; auto. + pattern a at 1; rewrite (Z_div_mod_eq_full a n); auto with zarith. + pattern b at 1; rewrite (Z_div_mod_eq_full b n); auto with zarith. + set (A:=a mod n); set (B:=b mod n); set (A':=a/n); set (B':=b/n). + replace ((n*A' + A) * (n*B' + B)) + with (A*B + (A'*B+B'*A+n*A'*B')*n) by ring. + apply Z_mod_plus_full; auto with zarith. Qed. -Lemma Z_div_exact_2 : forall a b:Z, b > 0 -> a mod b = 0 -> a = b * (a / b). - intros a b Hb; generalize (Z_div_mod a b Hb); unfold Zmod, Zdiv in |- *. - case (Zdiv_eucl a b); intros q r; omega. +Theorem Zplus_mod: forall a b n, + (a + b) mod n = (a mod n + b mod n) mod n. +Proof. + intros; destruct (Z_eq_dec n 0) as [Hb|Hb]. + subst; do 2 rewrite Zmod_0_r; auto. + pattern a at 1; rewrite (Z_div_mod_eq_full a n); auto with zarith. + pattern b at 1; rewrite (Z_div_mod_eq_full b n); auto with zarith. + replace ((n * (a / n) + a mod n) + (n * (b / n) + b mod n)) + with ((a mod n + b mod n) + (a / n + b / n) * n) by ring. + apply Z_mod_plus_full; auto with zarith. Qed. -Lemma Z_mod_zero_opp : forall a b:Z, b > 0 -> a mod b = 0 -> - a mod b = 0. - intros a b Hb. +Theorem Zminus_mod: forall a b n, + (a - b) mod n = (a mod n - b mod n) mod n. +Proof. intros. - rewrite Z_div_exact_2 with a b; auto. - replace (- (b * (a / b))) with (0 + - (a / b) * b). - rewrite Z_mod_plus; auto. + replace (a - b) with (a + (-1) * b); auto with zarith. + replace (a mod n - b mod n) with (a mod n + (-1) * (b mod n)); auto with zarith. + rewrite Zplus_mod. + rewrite Zmult_mod. + rewrite Zplus_mod with (b:=(-1) * (b mod n)). + rewrite Zmult_mod. + rewrite Zmult_mod with (b:= b mod n). + repeat rewrite Zmod_mod; auto. +Qed. + +Lemma Zplus_mod_idemp_l: forall a b n, (a mod n + b) mod n = (a + b) mod n. +Proof. + intros; rewrite Zplus_mod, Zmod_mod, <- Zplus_mod; auto. +Qed. + +Lemma Zplus_mod_idemp_r: forall a b n, (b + a mod n) mod n = (b + a) mod n. +Proof. + intros; rewrite Zplus_mod, Zmod_mod, <- Zplus_mod; auto. +Qed. + +Lemma Zminus_mod_idemp_l: forall a b n, (a mod n - b) mod n = (a - b) mod n. +Proof. + intros; rewrite Zminus_mod, Zmod_mod, <- Zminus_mod; auto. +Qed. + +Lemma Zminus_mod_idemp_r: forall a b n, (a - b mod n) mod n = (a - b) mod n. +Proof. + intros; rewrite Zminus_mod, Zmod_mod, <- Zminus_mod; auto. +Qed. + +Lemma Zmult_mod_idemp_l: forall a b n, (a mod n * b) mod n = (a * b) mod n. +Proof. + intros; rewrite Zmult_mod, Zmod_mod, <- Zmult_mod; auto. +Qed. + +Lemma Zmult_mod_idemp_r: forall a b n, (b * (a mod n)) mod n = (b * a) mod n. +Proof. + intros; rewrite Zmult_mod, Zmod_mod, <- Zmult_mod; auto. +Qed. + +(** For a specific number n, equality modulo n is hence a nice setoid + equivalence, compatible with the usual operations. Due to restrictions + with Coq setoids, we cannot state this in a section, but it works + at least with a module. *) + +Module Type SomeNumber. + Parameter n:Z. +End SomeNumber. + +Module EqualityModulo (M:SomeNumber). + + Definition eqm a b := (a mod M.n = b mod M.n). + Infix "==" := eqm (at level 70). + + Lemma eqm_refl : forall a, a == a. + Proof. unfold eqm; auto. Qed. + + Lemma eqm_sym : forall a b, a == b -> b == a. + Proof. unfold eqm; auto. Qed. + + Lemma eqm_trans : forall a b c, a == b -> b == c -> a == c. + Proof. unfold eqm; eauto with *. Qed. + + Add Relation Z eqm + reflexivity proved by eqm_refl + symmetry proved by eqm_sym + transitivity proved by eqm_trans as eqm_setoid. + + Add Morphism Zplus : Zplus_eqm. + Proof. + unfold eqm; intros; rewrite Zplus_mod, H, H0, <- Zplus_mod; auto. + Qed. + + Add Morphism Zminus : Zminus_eqm. + Proof. + unfold eqm; intros; rewrite Zminus_mod, H, H0, <- Zminus_mod; auto. + Qed. + + Add Morphism Zmult : Zmult_eqm. + Proof. + unfold eqm; intros; rewrite Zmult_mod, H, H0, <- Zmult_mod; auto. + Qed. + + Add Morphism Zopp : Zopp_eqm. + Proof. + intros; change (-x == -y) with (0-x == 0-y). + rewrite H; red; auto. + Qed. + + Lemma Zmod_eqm : forall a, a mod M.n == a. + Proof. + unfold eqm; intros; apply Zmod_mod. + Qed. + + (* Zmod and Zdiv are not full morphisms with respect to eqm. + For instance, take n=2. Then 3 == 1 but we don't have + 1 mod 3 == 1 mod 1 nor 1/3 == 1/1. + *) + +End EqualityModulo. + +Lemma Zdiv_Zdiv : forall a b c, 0<=b -> 0<=c -> (a/b)/c = a/(b*c). +Proof. + intros a b c Hb Hc. + destruct (Zle_lt_or_eq _ _ Hb); [ | subst; rewrite Zdiv_0_r, Zdiv_0_r, Zdiv_0_l; auto]. + destruct (Zle_lt_or_eq _ _ Hc); [ | subst; rewrite Zmult_0_r, Zdiv_0_r, Zdiv_0_r; auto]. + pattern a at 2;rewrite (Z_div_mod_eq_full a b);auto with zarith. + pattern (a/b) at 2;rewrite (Z_div_mod_eq_full (a/b) c);auto with zarith. + replace (b * (c * (a / b / c) + (a / b) mod c) + a mod b) with + ((a / b / c)*(b * c) + (b * ((a / b) mod c) + a mod b)) by ring. + rewrite Z_div_plus_full_l; auto with zarith. + rewrite (Zdiv_small (b * ((a / b) mod c) + a mod b)). ring. + split. + apply Zplus_le_0_compat;auto with zarith. + apply Zmult_le_0_compat;auto with zarith. + destruct (Z_mod_lt (a/b) c);auto with zarith. + destruct (Z_mod_lt a b);auto with zarith. + apply Zle_lt_trans with (b * ((a / b) mod c) + (b-1)). + destruct (Z_mod_lt a b);auto with zarith. + apply Zle_lt_trans with (b * (c-1) + (b - 1)). + apply Zplus_le_compat;auto with zarith. + destruct (Z_mod_lt (a/b) c);auto with zarith. + replace (b * (c - 1) + (b - 1)) with (b*c-1);try ring;auto with zarith. + intro H1; + assert (H2: c <> 0) by auto with zarith; + rewrite (Zmult_integral_l _ _ H2 H1) in H; auto with zarith. +Qed. + +(** Unfortunately, the previous result isn't always true on negative numbers. + For instance: 3/(-2)/(-2) = 1 <> 0 = 3 / (-2*-2) *) + +(** A last inequality: *) + +Theorem Zdiv_mult_le: + forall a b c, 0<=a -> 0<=b -> 0<=c -> c*(a/b) <= (c*a)/b. +Proof. + intros a b c H1 H2 H3. + destruct (Zle_lt_or_eq _ _ H2); + [ | subst; rewrite Zdiv_0_r, Zdiv_0_r, Zmult_0_r; auto]. + case (Z_mod_lt a b); auto with zarith; intros Hu1 Hu2. + case (Z_mod_lt c b); auto with zarith; intros Hv1 Hv2. + apply Zmult_le_reg_r with b; auto with zarith. + rewrite <- Zmult_assoc. + replace (a / b * b) with (a - a mod b). + replace (c * a / b * b) with (c * a - (c * a) mod b). + rewrite Zmult_minus_distr_l. + unfold Zminus; apply Zplus_le_compat_l. + match goal with |- - ?X <= -?Y => assert (Y <= X); auto with zarith end. + apply Zle_trans with ((c mod b) * (a mod b)); auto with zarith. + rewrite Zmult_mod; auto with zarith. + apply (Zmod_le ((c mod b) * (a mod b)) b); auto with zarith. + apply Zmult_le_compat_r; auto with zarith. + apply (Zmod_le c b); auto. + pattern (c * a) at 1; rewrite (Z_div_mod_eq (c * a) b); try ring; + auto with zarith. + pattern a at 1; rewrite (Z_div_mod_eq a b); try ring; auto with zarith. +Qed. + +(** Zmod is related to divisibility (see more in Znumtheory) *) + +Lemma Zmod_divides : forall a b, b<>0 -> + (a mod b = 0 <-> exists c, a = b*c). +Proof. + split; intros. + exists (a/b). + pattern a at 1; rewrite (Z_div_mod_eq_full a b); auto with zarith. + destruct H0 as [c Hc]. + symmetry. + apply Zmod_unique_full with c; auto with zarith. + red; omega with *. +Qed. + +(** * Compatibility *) + +(** Weaker results kept only for compatibility *) + +Lemma Z_mod_same : forall a, a > 0 -> a mod a = 0. +Proof. + intros; apply Z_mod_same_full. +Qed. + +Lemma Z_div_same : forall a, a > 0 -> a/a = 1. +Proof. + intros; apply Z_div_same_full; auto with zarith. +Qed. + +Lemma Z_div_plus : forall a b c:Z, c > 0 -> (a + b * c) / c = a / c + b. +Proof. + intros; apply Z_div_plus_full; auto with zarith. +Qed. + +Lemma Z_div_mult : forall a b:Z, b > 0 -> (a*b)/b = a. +Proof. + intros; apply Z_div_mult_full; auto with zarith. Qed. + +Lemma Z_mod_plus : forall a b c:Z, c > 0 -> (a + b * c) mod c = a mod c. +Proof. + intros; apply Z_mod_plus_full; auto with zarith. +Qed. + +Lemma Z_div_exact_1 : forall a b:Z, b > 0 -> a = b*(a/b) -> a mod b = 0. +Proof. + intros; apply Z_div_exact_full_1; auto with zarith. +Qed. + +Lemma Z_div_exact_2 : forall a b:Z, b > 0 -> a mod b = 0 -> a = b*(a/b). +Proof. + intros; apply Z_div_exact_full_2; auto with zarith. +Qed. + +Lemma Z_mod_zero_opp : forall a b:Z, b > 0 -> a mod b = 0 -> (-a) mod b = 0. +Proof. + intros; apply Z_mod_zero_opp_full; auto with zarith. +Qed. + +(** * A direct way to compute Zmod *) + +Fixpoint Zmod_POS (a : positive) (b : Z) {struct a} : Z := + match a with + | xI a' => + let r := Zmod_POS a' b in + let r' := (2 * r + 1) in + if Zgt_bool b r' then r' else (r' - b) + | xO a' => + let r := Zmod_POS a' b in + let r' := (2 * r) in + if Zgt_bool b r' then r' else (r' - b) + | xH => if Zge_bool b 2 then 1 else 0 + end. + +Definition Zmod' a b := + match a with + | Z0 => 0 + | Zpos a' => + match b with + | Z0 => 0 + | Zpos _ => Zmod_POS a' b + | Zneg b' => + let r := Zmod_POS a' (Zpos b') in + match r with Z0 => 0 | _ => b + r end + end + | Zneg a' => + match b with + | Z0 => 0 + | Zpos _ => + let r := Zmod_POS a' b in + match r with Z0 => 0 | _ => b - r end + | Zneg b' => - (Zmod_POS a' (Zpos b')) + end + end. + + +Theorem Zmod_POS_correct: forall a b, Zmod_POS a b = (snd (Zdiv_eucl_POS a b)). +Proof. + intros a b; elim a; simpl; auto. + intros p Rec; rewrite Rec. + case (Zdiv_eucl_POS p b); intros z1 z2; simpl; auto. + match goal with |- context [Zgt_bool _ ?X] => case (Zgt_bool b X) end; auto. + intros p Rec; rewrite Rec. + case (Zdiv_eucl_POS p b); intros z1 z2; simpl; auto. + match goal with |- context [Zgt_bool _ ?X] => case (Zgt_bool b X) end; auto. + case (Zge_bool b 2); auto. +Qed. + +Theorem Zmod'_correct: forall a b, Zmod' a b = Zmod a b. +Proof. + intros a b; unfold Zmod; case a; simpl; auto. + intros p; case b; simpl; auto. + intros p1; refine (Zmod_POS_correct _ _); auto. + intros p1; rewrite Zmod_POS_correct; auto. + case (Zdiv_eucl_POS p (Zpos p1)); simpl; intros z1 z2; case z2; auto. + intros p; case b; simpl; auto. + intros p1; rewrite Zmod_POS_correct; auto. + case (Zdiv_eucl_POS p (Zpos p1)); simpl; intros z1 z2; case z2; auto. + intros p1; rewrite Zmod_POS_correct; simpl; auto. + case (Zdiv_eucl_POS p (Zpos p1)); auto. +Qed. + + +(** Another convention is possible for division by negative numbers: + * quotient is always the biggest integer smaller than or equal to a/b + * remainder is hence always positive or null. *) + +Theorem Zdiv_eucl_extended : + forall b:Z, + b <> 0 -> + forall a:Z, + {qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Zabs b}. +Proof. + intros b Hb a. + elim (Z_le_gt_dec 0 b); intro Hb'. + cut (b > 0); [ intro Hb'' | omega ]. + rewrite Zabs_eq; [ apply Zdiv_eucl_exist; assumption | assumption ]. + cut (- b > 0); [ intro Hb'' | omega ]. + elim (Zdiv_eucl_exist Hb'' a); intros qr. + elim qr; intros q r Hqr. + exists (- q, r). + elim Hqr; intros. + split. + rewrite <- Zmult_opp_comm; assumption. + rewrite Zabs_non_eq; [ assumption | omega ]. +Qed. + +Implicit Arguments Zdiv_eucl_extended. + +(** A third convention: Ocaml. + + See files ZOdiv_def.v and ZOdiv.v. + + Ocaml uses Round-Toward-Zero division: (-a)/b = a/(-b) = -(a/b). + Hence (-a) mod b = - (a mod b) + a mod (-b) = a mod b + And: |r| < |b| and sgn(r) = sgn(a) (notice the a here instead of b). +*) diff --git a/theories/ZArith/Zeven.v b/theories/ZArith/Zeven.v index 6fab4461..4a402c61 100644 --- a/theories/ZArith/Zeven.v +++ b/theories/ZArith/Zeven.v @@ -6,10 +6,12 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zeven.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Zeven.v 10291 2007-11-06 02:18:53Z letouzey $ i*) Require Import BinInt. +Open Scope Z_scope. + (*******************************************************************) (** About parity: even and odd predicates on Z, division by 2 on Z *) @@ -135,14 +137,14 @@ Hint Unfold Zeven Zodd: zarith. Definition Zdiv2 (z:Z) := match z with - | Z0 => 0%Z - | Zpos xH => 0%Z + | Z0 => 0 + | Zpos xH => 0 | Zpos p => Zpos (Pdiv2 p) - | Zneg xH => 0%Z + | Zneg xH => 0 | Zneg p => Zneg (Pdiv2 p) end. -Lemma Zeven_div2 : forall n:Z, Zeven n -> n = (2 * Zdiv2 n)%Z. +Lemma Zeven_div2 : forall n:Z, Zeven n -> n = 2 * Zdiv2 n. Proof. intro x; destruct x. auto with arith. @@ -154,27 +156,27 @@ Proof. intros. absurd (Zeven (-1)); red in |- *; auto with arith. Qed. -Lemma Zodd_div2 : forall n:Z, (n >= 0)%Z -> Zodd n -> n = (2 * Zdiv2 n + 1)%Z. +Lemma Zodd_div2 : forall n:Z, n >= 0 -> Zodd n -> n = 2 * Zdiv2 n + 1. Proof. intro x; destruct x. intros. absurd (Zodd 0); red in |- *; auto with arith. destruct p; auto with arith. intros. absurd (Zodd (Zpos (xO p))); red in |- *; auto with arith. - intros. absurd (Zneg p >= 0)%Z; red in |- *; auto with arith. + intros. absurd (Zneg p >= 0); red in |- *; auto with arith. Qed. Lemma Zodd_div2_neg : - forall n:Z, (n <= 0)%Z -> Zodd n -> n = (2 * Zdiv2 n - 1)%Z. + forall n:Z, n <= 0 -> Zodd n -> n = 2 * Zdiv2 n - 1. Proof. intro x; destruct x. intros. absurd (Zodd 0); red in |- *; auto with arith. - intros. absurd (Zneg p >= 0)%Z; red in |- *; auto with arith. + intros. absurd (Zneg p >= 0); red in |- *; auto with arith. destruct p; auto with arith. intros. absurd (Zodd (Zneg (xO p))); red in |- *; auto with arith. Qed. Lemma Z_modulo_2 : - forall n:Z, {y : Z | n = (2 * y)%Z} + {y : Z | n = (2 * y + 1)%Z}. + forall n:Z, {y : Z | n = 2 * y} + {y : Z | n = 2 * y + 1}. Proof. intros x. elim (Zeven_odd_dec x); intro. @@ -193,7 +195,7 @@ Qed. Lemma Zsplit2 : forall n:Z, {p : Z * Z | - let (x1, x2) := p in n = (x1 + x2)%Z /\ (x1 = x2 \/ x2 = (x1 + 1)%Z)}. + let (x1, x2) := p in n = x1 + x2 /\ (x1 = x2 \/ x2 = x1 + 1)}. Proof. intros x. elim (Z_modulo_2 x); intros [y Hy]; rewrite Zmult_comm in Hy; @@ -206,3 +208,109 @@ Proof. right; reflexivity. Qed. + +Theorem Zeven_ex: forall n, Zeven n -> exists m, n = 2 * m. +Proof. + intro n; exists (Zdiv2 n); apply Zeven_div2; auto. +Qed. + +Theorem Zodd_ex: forall n, Zodd n -> exists m, n = 2 * m + 1. +Proof. + destruct n; intros. + inversion H. + exists (Zdiv2 (Zpos p)). + apply Zodd_div2; simpl; auto; compute; inversion 1. + exists (Zdiv2 (Zneg p) - 1). + unfold Zminus. + rewrite Zmult_plus_distr_r. + rewrite <- Zplus_assoc. + assert (Zneg p <= 0) by (compute; inversion 1). + exact (Zodd_div2_neg _ H0 H). +Qed. + +Theorem Zeven_2p: forall p, Zeven (2 * p). +Proof. + destruct p; simpl; auto. +Qed. + +Theorem Zodd_2p_plus_1: forall p, Zodd (2 * p + 1). +Proof. + destruct p; simpl; auto. + destruct p; simpl; auto. +Qed. + +Theorem Zeven_plus_Zodd: forall a b, + Zeven a -> Zodd b -> Zodd (a + b). +Proof. + intros a b H1 H2; case Zeven_ex with (1 := H1); intros x H3; try rewrite H3; auto. + case Zodd_ex with (1 := H2); intros y H4; try rewrite H4; auto. + replace (2 * x + (2 * y + 1)) with (2 * (x + y) + 1); try apply Zodd_2p_plus_1; auto with zarith. + rewrite Zmult_plus_distr_r, Zplus_assoc; auto. +Qed. + +Theorem Zeven_plus_Zeven: forall a b, + Zeven a -> Zeven b -> Zeven (a + b). +Proof. + intros a b H1 H2; case Zeven_ex with (1 := H1); intros x H3; try rewrite H3; auto. + case Zeven_ex with (1 := H2); intros y H4; try rewrite H4; auto. + replace (2 * x + 2 * y) with (2 * (x + y)); try apply Zeven_2p; auto with zarith. + apply Zmult_plus_distr_r; auto. +Qed. + +Theorem Zodd_plus_Zeven: forall a b, + Zodd a -> Zeven b -> Zodd (a + b). +Proof. + intros a b H1 H2; rewrite Zplus_comm; apply Zeven_plus_Zodd; auto. +Qed. + +Theorem Zodd_plus_Zodd: forall a b, + Zodd a -> Zodd b -> Zeven (a + b). +Proof. + intros a b H1 H2; case Zodd_ex with (1 := H1); intros x H3; try rewrite H3; auto. + case Zodd_ex with (1 := H2); intros y H4; try rewrite H4; auto. + replace ((2 * x + 1) + (2 * y + 1)) with (2 * (x + y + 1)); try apply Zeven_2p; auto. + (* ring part *) + do 2 rewrite Zmult_plus_distr_r; auto. + repeat rewrite <- Zplus_assoc; f_equal. + rewrite (Zplus_comm 1). + repeat rewrite <- Zplus_assoc; auto. +Qed. + +Theorem Zeven_mult_Zeven_l: forall a b, + Zeven a -> Zeven (a * b). +Proof. + intros a b H1; case Zeven_ex with (1 := H1); intros x H3; try rewrite H3; auto. + replace (2 * x * b) with (2 * (x * b)); try apply Zeven_2p; auto with zarith. + (* ring part *) + apply Zmult_assoc. +Qed. + +Theorem Zeven_mult_Zeven_r: forall a b, + Zeven b -> Zeven (a * b). +Proof. + intros a b H1; case Zeven_ex with (1 := H1); intros x H3; try rewrite H3; auto. + replace (a * (2 * x)) with (2 * (x * a)); try apply Zeven_2p; auto. + (* ring part *) + rewrite (Zmult_comm x a). + do 2 rewrite Zmult_assoc. + rewrite (Zmult_comm 2 a); auto. +Qed. + +Hint Rewrite Zmult_plus_distr_r Zmult_plus_distr_l + Zplus_assoc Zmult_1_r Zmult_1_l : Zexpand. + +Theorem Zodd_mult_Zodd: forall a b, + Zodd a -> Zodd b -> Zodd (a * b). +Proof. + intros a b H1 H2; case Zodd_ex with (1 := H1); intros x H3; try rewrite H3; auto. + case Zodd_ex with (1 := H2); intros y H4; try rewrite H4; auto. + replace ((2 * x + 1) * (2 * y + 1)) with (2 * (2 * x * y + x + y) + 1); try apply Zodd_2p_plus_1; auto. + (* ring part *) + autorewrite with Zexpand; f_equal. + repeat rewrite <- Zplus_assoc; f_equal. + repeat rewrite <- Zmult_assoc; f_equal. + repeat rewrite Zmult_assoc; f_equal; apply Zmult_comm. +Qed. + +(* for compatibility *) +Close Scope Z_scope. diff --git a/theories/ZArith/Zgcd_alt.v b/theories/ZArith/Zgcd_alt.v new file mode 100644 index 00000000..286dd710 --- /dev/null +++ b/theories/ZArith/Zgcd_alt.v @@ -0,0 +1,317 @@ +(************************************************************************) +(* 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: Zgcd_alt.v 10997 2008-05-27 15:16:40Z letouzey $ i*) + +(** * Zgcd_alt : an alternate version of Zgcd, based on Euler's algorithm *) + +(** +Author: Pierre Letouzey +*) + +(** The alternate [Zgcd_alt] given here used to be the main [Zgcd] + function (see file [Znumtheory]), but this main [Zgcd] is now + based on a modern binary-efficient algorithm. This earlier + version, based on Euler's algorithm of iterated modulo, is kept + here due to both its intrinsic interest and its use as reference + point when proving gcd on Int31 numbers *) + +Require Import ZArith_base. +Require Import ZArithRing. +Require Import Zdiv. +Require Import Znumtheory. + +Open Scope Z_scope. + +(** In Coq, we need to control the number of iteration of modulo. + For that, we use an explicit measure in [nat], and we prove later + that using [2*d] is enough, where [d] is the number of binary + digits of the first argument. *) + + Fixpoint Zgcdn (n:nat) : Z -> Z -> Z := fun a b => + match n with + | O => 1 (* arbitrary, since n should be big enough *) + | S n => match a with + | Z0 => Zabs b + | Zpos _ => Zgcdn n (Zmod b a) a + | Zneg a => Zgcdn n (Zmod b (Zpos a)) (Zpos a) + end + end. + + Definition Zgcd_bound (a:Z) := + match a with + | Z0 => S O + | Zpos p => let n := Psize p in (n+n)%nat + | Zneg p => let n := Psize p in (n+n)%nat + end. + + Definition Zgcd_alt a b := Zgcdn (Zgcd_bound a) a b. + + (** A first obvious fact : [Zgcd a b] is positive. *) + + Lemma Zgcdn_pos : forall n a b, + 0 <= Zgcdn n a b. + Proof. + induction n. + simpl; auto with zarith. + destruct a; simpl; intros; auto with zarith; auto. + Qed. + + Lemma Zgcd_alt_pos : forall a b, 0 <= Zgcd_alt a b. + Proof. + intros; unfold Zgcd; apply Zgcdn_pos; auto. + Qed. + + (** We now prove that Zgcd is indeed a gcd. *) + + (** 1) We prove a weaker & easier bound. *) + + Lemma Zgcdn_linear_bound : forall n a b, + Zabs a < Z_of_nat n -> Zis_gcd a b (Zgcdn n a b). + Proof. + induction n. + simpl; intros. + elimtype False; generalize (Zabs_pos a); omega. + destruct a; intros; simpl; + [ generalize (Zis_gcd_0_abs b); intuition | | ]; + unfold Zmod; + generalize (Z_div_mod b (Zpos p) (refl_equal Gt)); + destruct (Zdiv_eucl b (Zpos p)) as (q,r); + intros (H0,H1); + rewrite inj_S in H; simpl Zabs in H; + (assert (H2: Zabs r < Z_of_nat n) by + (rewrite Zabs_eq; auto with zarith)); + assert (IH:=IHn r (Zpos p) H2); clear IHn; + simpl in IH |- *; + rewrite H0. + apply Zis_gcd_for_euclid2; auto. + apply Zis_gcd_minus; apply Zis_gcd_sym. + apply Zis_gcd_for_euclid2; auto. + Qed. + + (** 2) For Euclid's algorithm, the worst-case situation corresponds + to Fibonacci numbers. Let's define them: *) + + Fixpoint fibonacci (n:nat) : Z := + match n with + | O => 1 + | S O => 1 + | S (S n as p) => fibonacci p + fibonacci n + end. + + Lemma fibonacci_pos : forall n, 0 <= fibonacci n. + Proof. + cut (forall N n, (n<N)%nat -> 0<=fibonacci n). + eauto. + induction N. + inversion 1. + intros. + destruct n. + simpl; auto with zarith. + destruct n. + simpl; auto with zarith. + change (0 <= fibonacci (S n) + fibonacci n). + generalize (IHN n) (IHN (S n)); omega. + Qed. + + Lemma fibonacci_incr : + forall n m, (n<=m)%nat -> fibonacci n <= fibonacci m. + Proof. + induction 1. + auto with zarith. + apply Zle_trans with (fibonacci m); auto. + clear. + destruct m. + simpl; auto with zarith. + change (fibonacci (S m) <= fibonacci (S m)+fibonacci m). + generalize (fibonacci_pos m); omega. + Qed. + + (** 3) We prove that fibonacci numbers are indeed worst-case: + for a given number [n], if we reach a conclusion about [gcd(a,b)] in + exactly [n+1] loops, then [fibonacci (n+1)<=a /\ fibonacci(n+2)<=b] *) + + Lemma Zgcdn_worst_is_fibonacci : forall n a b, + 0 < a < b -> + Zis_gcd a b (Zgcdn (S n) a b) -> + Zgcdn n a b <> Zgcdn (S n) a b -> + fibonacci (S n) <= a /\ + fibonacci (S (S n)) <= b. + Proof. + induction n. + simpl; intros. + destruct a; omega. + intros. + destruct a; [simpl in *; omega| | destruct H; discriminate]. + revert H1; revert H0. + set (m:=S n) in *; (assert (m=S n) by auto); clearbody m. + pattern m at 2; rewrite H0. + simpl Zgcdn. + unfold Zmod; generalize (Z_div_mod b (Zpos p) (refl_equal Gt)). + destruct (Zdiv_eucl b (Zpos p)) as (q,r). + intros (H1,H2). + destruct H2. + destruct (Zle_lt_or_eq _ _ H2). + generalize (IHn _ _ (conj H4 H3)). + intros H5 H6 H7. + replace (fibonacci (S (S m))) with (fibonacci (S m) + fibonacci m) by auto. + assert (r = Zpos p * (-q) + b) by (rewrite H1; ring). + destruct H5; auto. + pattern r at 1; rewrite H8. + apply Zis_gcd_sym. + apply Zis_gcd_for_euclid2; auto. + apply Zis_gcd_sym; auto. + split; auto. + rewrite H1. + apply Zplus_le_compat; auto. + apply Zle_trans with (Zpos p * 1); auto. + ring_simplify (Zpos p * 1); auto. + apply Zmult_le_compat_l. + destruct q. + omega. + assert (0 < Zpos p0) by (compute; auto). + omega. + assert (Zpos p * Zneg p0 < 0) by (compute; auto). + omega. + compute; intros; discriminate. + (* r=0 *) + subst r. + simpl; rewrite H0. + intros. + simpl in H4. + simpl in H5. + destruct n. + simpl in H5. + simpl. + omega. + simpl in H5. + elim H5; auto. + Qed. + + (** 3b) We reformulate the previous result in a more positive way. *) + + Lemma Zgcdn_ok_before_fibonacci : forall n a b, + 0 < a < b -> a < fibonacci (S n) -> + Zis_gcd a b (Zgcdn n a b). + Proof. + destruct a; [ destruct 1; elimtype False; omega | | destruct 1; discriminate]. + cut (forall k n b, + k = (S (nat_of_P p) - n)%nat -> + 0 < Zpos p < b -> Zpos p < fibonacci (S n) -> + Zis_gcd (Zpos p) b (Zgcdn n (Zpos p) b)). + destruct 2; eauto. + clear n; induction k. + intros. + assert (nat_of_P p < n)%nat by omega. + apply Zgcdn_linear_bound. + simpl. + generalize (inj_le _ _ H2). + rewrite inj_S. + rewrite <- Zpos_eq_Z_of_nat_o_nat_of_P; auto. + omega. + intros. + generalize (Zgcdn_worst_is_fibonacci n (Zpos p) b H0); intros. + assert (Zis_gcd (Zpos p) b (Zgcdn (S n) (Zpos p) b)). + apply IHk; auto. + omega. + replace (fibonacci (S (S n))) with (fibonacci (S n)+fibonacci n) by auto. + generalize (fibonacci_pos n); omega. + replace (Zgcdn n (Zpos p) b) with (Zgcdn (S n) (Zpos p) b); auto. + generalize (H2 H3); clear H2 H3; omega. + Qed. + + (** 4) The proposed bound leads to a fibonacci number that is big enough. *) + + Lemma Zgcd_bound_fibonacci : + forall a, 0 < a -> a < fibonacci (Zgcd_bound a). + Proof. + destruct a; [omega| | intro H; discriminate]. + intros _. + induction p; [ | | compute; auto ]; + simpl Zgcd_bound in *; + rewrite plus_comm; simpl plus; + set (n:= (Psize p+Psize p)%nat) in *; simpl; + assert (n <> O) by (unfold n; destruct p; simpl; auto). + + destruct n as [ |m]; [elim H; auto| ]. + generalize (fibonacci_pos m); rewrite Zpos_xI; omega. + + destruct n as [ |m]; [elim H; auto| ]. + generalize (fibonacci_pos m); rewrite Zpos_xO; omega. + Qed. + + (* 5) the end: we glue everything together and take care of + situations not corresponding to [0<a<b]. *) + + Lemma Zgcdn_is_gcd : + forall n a b, (Zgcd_bound a <= n)%nat -> + Zis_gcd a b (Zgcdn n a b). + Proof. + destruct a; intros. + simpl in H. + destruct n; [elimtype False; omega | ]. + simpl; generalize (Zis_gcd_0_abs b); intuition. + (*Zpos*) + generalize (Zgcd_bound_fibonacci (Zpos p)). + simpl Zgcd_bound in *. + remember (Psize p+Psize p)%nat as m. + assert (1 < m)%nat. + rewrite Heqm; destruct p; simpl; rewrite 1? plus_comm; + auto with arith. + destruct m as [ |m]; [inversion H0; auto| ]. + destruct n as [ |n]; [inversion H; auto| ]. + simpl Zgcdn. + unfold Zmod. + generalize (Z_div_mod b (Zpos p) (refl_equal Gt)). + destruct (Zdiv_eucl b (Zpos p)) as (q,r). + intros (H2,H3) H4. + rewrite H2. + apply Zis_gcd_for_euclid2. + destruct H3. + destruct (Zle_lt_or_eq _ _ H1). + apply Zgcdn_ok_before_fibonacci; auto. + apply Zlt_le_trans with (fibonacci (S m)); [ omega | apply fibonacci_incr; auto]. + subst r; simpl. + destruct m as [ |m]; [elimtype False; omega| ]. + destruct n as [ |n]; [elimtype False; omega| ]. + simpl; apply Zis_gcd_sym; apply Zis_gcd_0. + (*Zneg*) + generalize (Zgcd_bound_fibonacci (Zpos p)). + simpl Zgcd_bound in *. + remember (Psize p+Psize p)%nat as m. + assert (1 < m)%nat. + rewrite Heqm; destruct p; simpl; rewrite 1? plus_comm; + auto with arith. + destruct m as [ |m]; [inversion H0; auto| ]. + destruct n as [ |n]; [inversion H; auto| ]. + simpl Zgcdn. + unfold Zmod. + generalize (Z_div_mod b (Zpos p) (refl_equal Gt)). + destruct (Zdiv_eucl b (Zpos p)) as (q,r). + intros (H1,H2) H3. + rewrite H1. + apply Zis_gcd_minus. + apply Zis_gcd_sym. + apply Zis_gcd_for_euclid2. + destruct H2. + destruct (Zle_lt_or_eq _ _ H2). + apply Zgcdn_ok_before_fibonacci; auto. + apply Zlt_le_trans with (fibonacci (S m)); [ omega | apply fibonacci_incr; auto]. + subst r; simpl. + destruct m as [ |m]; [elimtype False; omega| ]. + destruct n as [ |n]; [elimtype False; omega| ]. + simpl; apply Zis_gcd_sym; apply Zis_gcd_0. + Qed. + + Lemma Zgcd_is_gcd : + forall a b, Zis_gcd a b (Zgcd_alt a b). + Proof. + unfold Zgcd_alt; intros; apply Zgcdn_is_gcd; auto. + Qed. + + diff --git a/theories/ZArith/Zmax.v b/theories/ZArith/Zmax.v index 8af9b891..0d6fc94a 100644 --- a/theories/ZArith/Zmax.v +++ b/theories/ZArith/Zmax.v @@ -5,7 +5,7 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zmax.v 9302 2006-10-27 21:21:17Z barras $ i*) +(*i $Id: Zmax.v 10291 2007-11-06 02:18:53Z letouzey $ i*) Require Import Arith_base. Require Import BinInt. @@ -38,6 +38,28 @@ Proof. destruct (n ?= m); (apply H1|| apply H2); discriminate. Qed. +Lemma Zmax_spec : forall x y:Z, + x >= y /\ Zmax x y = x \/ + x < y /\ Zmax x y = y. +Proof. + intros; unfold Zmax, Zlt, Zge. + destruct (Zcompare x y); [ left | right | left ]; split; auto; discriminate. +Qed. + +Lemma Zmax_left : forall n m:Z, n>=m -> Zmax n m = n. +Proof. + intros n m; unfold Zmax, Zge; destruct (n ?= m); auto. + intro H; elim H; auto. +Qed. + +Lemma Zmax_right : forall n m:Z, n<=m -> Zmax n m = m. +Proof. + intros n m; unfold Zmax, Zle. + generalize (Zcompare_Eq_eq n m). + destruct (n ?= m); auto. + intros _ H; elim H; auto. +Qed. + (** * Least upper bound properties of max *) Lemma Zle_max_l : forall n m:Z, n <= Zmax n m. @@ -106,3 +128,39 @@ Proof. rewrite (Zcompare_plus_compat x y n). case (x ?= y); apply Zplus_comm. Qed. + +(** * Maximum and Zpos *) + +Lemma Zpos_max : forall p q, Zpos (Pmax p q) = Zmax (Zpos p) (Zpos q). +Proof. + intros; unfold Zmax, Pmax; simpl; generalize (Pcompare_Eq_eq p q). + destruct Pcompare; auto. + intro H; rewrite H; auto. +Qed. + +Lemma Zpos_max_1 : forall p, Zmax 1 (Zpos p) = Zpos p. +Proof. + intros; unfold Zmax; simpl; destruct p; simpl; auto. +Qed. + +(** * Characterization of Pminus in term of Zminus and Zmax *) + +Lemma Zpos_minus : forall p q, Zpos (Pminus p q) = Zmax 1 (Zpos p - Zpos q). +Proof. + intros. + case_eq (Pcompare p q Eq). + intros H; rewrite (Pcompare_Eq_eq _ _ H). + rewrite Zminus_diag. + unfold Zmax; simpl. + unfold Pminus; rewrite Pminus_mask_diag; auto. + intros; rewrite Pminus_Lt; auto. + destruct (Zmax_spec 1 (Zpos p - Zpos q)) as [(H1,H2)|(H1,H2)]; auto. + elimtype False; clear H2. + assert (H1':=Zlt_trans 0 1 _ Zlt_0_1 H1). + generalize (Zlt_0_minus_lt _ _ H1'). + unfold Zlt; simpl. + rewrite (ZC2 _ _ H); intro; discriminate. + intros; simpl; rewrite H. + symmetry; apply Zpos_max_1. +Qed. + diff --git a/theories/ZArith/Zmin.v b/theories/ZArith/Zmin.v index 37d78a74..bad40a32 100644 --- a/theories/ZArith/Zmin.v +++ b/theories/ZArith/Zmin.v @@ -5,9 +5,9 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zmin.v 9302 2006-10-27 21:21:17Z barras $ i*) +(*i $Id: Zmin.v 10028 2007-07-18 22:38:06Z letouzey $ i*) -(** Initial version from Pierre Crégut (CNET, Lannion, France), 1996. +(** Initial version from Pierre Crégut (CNET, Lannion, France), 1996. Further extensions by the Coq development team, with suggestions from Russell O'Connor (Radbout U., Nijmegen, The Netherlands). *) @@ -43,6 +43,14 @@ Proof. intros n m P H1 H2; unfold Zmin in |- *; case (n ?= m); auto with arith. Qed. +Lemma Zmin_spec : forall x y:Z, + x <= y /\ Zmin x y = x \/ + x > y /\ Zmin x y = y. +Proof. + intros; unfold Zmin, Zle, Zgt. + destruct (Zcompare x y); [ left | left | right ]; split; auto; discriminate. +Qed. + (** * Greatest lower bound properties of min *) Lemma Zle_min_l : forall n m:Z, Zmin n m <= n. @@ -128,3 +136,11 @@ Proof. Qed. Notation Zmin_plus := Zplus_min_distr_r (only parsing). + +(** * Minimum and Zpos *) + +Lemma Zpos_min : forall p q, Zpos (Pmin p q) = Zmin (Zpos p) (Zpos q). +Proof. + intros; unfold Zmin, Pmin; simpl; destruct Pcompare; auto. +Qed. + diff --git a/theories/ZArith/Zmisc.v b/theories/ZArith/Zmisc.v index d01cada6..0634096e 100644 --- a/theories/ZArith/Zmisc.v +++ b/theories/ZArith/Zmisc.v @@ -6,8 +6,9 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zmisc.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Zmisc.v 11072 2008-06-08 16:13:37Z herbelin $ i*) +Require Import Wf_nat. Require Import BinInt. Require Import Zcompare. Require Import Zorder. @@ -18,37 +19,23 @@ Open Local Scope Z_scope. (** Iterators *) (** [n]th iteration of the function [f] *) -Fixpoint iter_nat (n:nat) (A:Set) (f:A -> A) (x:A) {struct n} : A := - match n with - | O => x - | S n' => f (iter_nat n' A f x) - end. -Fixpoint iter_pos (n:positive) (A:Set) (f:A -> A) (x:A) {struct n} : A := +Fixpoint iter_pos (n:positive) (A:Type) (f:A -> A) (x:A) {struct n} : A := match n with | xH => f x | xO n' => iter_pos n' A f (iter_pos n' A f x) | xI n' => f (iter_pos n' A f (iter_pos n' A f x)) end. -Definition iter (n:Z) (A:Set) (f:A -> A) (x:A) := +Definition iter (n:Z) (A:Type) (f:A -> A) (x:A) := match n with | Z0 => x | Zpos p => iter_pos p A f x | Zneg p => x end. -Theorem iter_nat_plus : - forall (n m:nat) (A:Set) (f:A -> A) (x:A), - iter_nat (n + m) A f x = iter_nat n A f (iter_nat m A f x). -Proof. - simple induction n; - [ simpl in |- *; auto with arith - | intros; simpl in |- *; apply f_equal with (f := f); apply H ]. -Qed. - Theorem iter_nat_of_P : - forall (p:positive) (A:Set) (f:A -> A) (x:A), + forall (p:positive) (A:Type) (f:A -> A) (x:A), iter_pos p A f x = iter_nat (nat_of_P p) A f x. Proof. intro n; induction n as [p H| p H| ]; @@ -63,7 +50,7 @@ Proof. Qed. Theorem iter_pos_plus : - forall (p q:positive) (A:Set) (f:A -> A) (x:A), + forall (p q:positive) (A:Type) (f:A -> A) (x:A), iter_pos (p + q) A f x = iter_pos p A f (iter_pos q A f x). Proof. intros n m; intros. @@ -78,7 +65,7 @@ Qed. then the iterates of [f] also preserve it. *) Theorem iter_nat_invariant : - forall (n:nat) (A:Set) (f:A -> A) (Inv:A -> Prop), + forall (n:nat) (A:Type) (f:A -> A) (Inv:A -> Prop), (forall x:A, Inv x -> Inv (f x)) -> forall x:A, Inv x -> Inv (iter_nat n A f x). Proof. @@ -89,7 +76,7 @@ Proof. Qed. Theorem iter_pos_invariant : - forall (p:positive) (A:Set) (f:A -> A) (Inv:A -> Prop), + forall (p:positive) (A:Type) (f:A -> A) (Inv:A -> Prop), (forall x:A, Inv x -> Inv (f x)) -> forall x:A, Inv x -> Inv (iter_pos p A f x). Proof. diff --git a/theories/ZArith/Znat.v b/theories/ZArith/Znat.v index f0a3d47b..c5b5edc1 100644 --- a/theories/ZArith/Znat.v +++ b/theories/ZArith/Znat.v @@ -6,9 +6,9 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Znat.v 9302 2006-10-27 21:21:17Z barras $ i*) +(*i $Id: Znat.v 10726 2008-03-28 18:15:23Z notin $ i*) -(** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) +(** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) Require Export Arith_base. Require Import BinPos. @@ -17,6 +17,7 @@ Require Import Zcompare. Require Import Zorder. Require Import Decidable. Require Import Peano_dec. +Require Import Min Max Zmin Zmax. Require Export Compare_dec. Open Local Scope Z_scope. @@ -26,6 +27,13 @@ Definition neq (x y:nat) := x <> y. (************************************************) (** Properties of the injection from nat into Z *) +(** Injection and successor *) + +Theorem inj_0 : Z_of_nat 0 = 0%Z. +Proof. + reflexivity. +Qed. + Theorem inj_S : forall n:nat, Z_of_nat (S n) = Zsucc (Z_of_nat n). Proof. intro y; induction y as [| n H]; @@ -33,25 +41,12 @@ Proof. | change (Zpos (Psucc (P_of_succ_nat n)) = Zsucc (Z_of_nat (S n))) in |- *; rewrite Zpos_succ_morphism; trivial with arith ]. Qed. - -Theorem inj_plus : forall n m:nat, Z_of_nat (n + m) = Z_of_nat n + Z_of_nat m. -Proof. - intro x; induction x as [| n H]; intro y; destruct y as [| m]; - [ simpl in |- *; trivial with arith - | simpl in |- *; trivial with arith - | simpl in |- *; rewrite <- plus_n_O; trivial with arith - | change (Z_of_nat (S (n + S m)) = Z_of_nat (S n) + Z_of_nat (S m)) in |- *; - rewrite inj_S; rewrite H; do 2 rewrite inj_S; rewrite Zplus_succ_l; - trivial with arith ]. -Qed. -Theorem inj_mult : forall n m:nat, Z_of_nat (n * m) = Z_of_nat n * Z_of_nat m. +(** Injection and equality. *) + +Theorem inj_eq : forall n m:nat, n = m -> Z_of_nat n = Z_of_nat m. Proof. - intro x; induction x as [| n H]; - [ simpl in |- *; trivial with arith - | intro y; rewrite inj_S; rewrite <- Zmult_succ_l_reverse; rewrite <- H; - rewrite <- inj_plus; simpl in |- *; rewrite plus_comm; - trivial with arith ]. + intros x y H; rewrite H; trivial with arith. Qed. Theorem inj_neq : forall n m:nat, neq n m -> Zne (Z_of_nat n) (Z_of_nat m). @@ -66,6 +61,24 @@ Proof. intros E; rewrite E; auto with arith ]. Qed. +Theorem inj_eq_rev : forall n m:nat, Z_of_nat n = Z_of_nat m -> n = m. +Proof. + intros x y H. + destruct (eq_nat_dec x y) as [H'|H']; auto. + elimtype False. + exact (inj_neq _ _ H' H). +Qed. + +Theorem inj_eq_iff : forall n m:nat, n=m <-> Z_of_nat n = Z_of_nat m. +Proof. + split; [apply inj_eq | apply inj_eq_rev]. +Qed. + + +(** Injection and order relations: *) + +(** One way ... *) + Theorem inj_le : forall n m:nat, (n <= m)%nat -> Z_of_nat n <= Z_of_nat m. Proof. intros x y; intros H; elim H; @@ -81,29 +94,100 @@ Proof. exact H. Qed. +Theorem inj_ge : forall n m:nat, (n >= m)%nat -> Z_of_nat n >= Z_of_nat m. +Proof. + intros x y H; apply Zle_ge; apply inj_le; apply H. +Qed. + Theorem inj_gt : forall n m:nat, (n > m)%nat -> Z_of_nat n > Z_of_nat m. Proof. intros x y H; apply Zlt_gt; apply inj_lt; exact H. Qed. -Theorem inj_ge : forall n m:nat, (n >= m)%nat -> Z_of_nat n >= Z_of_nat m. +(** The other way ... *) + +Theorem inj_le_rev : forall n m:nat, Z_of_nat n <= Z_of_nat m -> (n <= m)%nat. Proof. - intros x y H; apply Zle_ge; apply inj_le; apply H. + intros x y H. + destruct (le_lt_dec x y) as [H0|H0]; auto. + elimtype False. + assert (H1:=inj_lt _ _ H0). + red in H; red in H1. + rewrite <- Zcompare_antisym in H; rewrite H1 in H; auto. Qed. -Theorem inj_eq : forall n m:nat, n = m -> Z_of_nat n = Z_of_nat m. +Theorem inj_lt_rev : forall n m:nat, Z_of_nat n < Z_of_nat m -> (n < m)%nat. Proof. - intros x y H; rewrite H; trivial with arith. + intros x y H. + destruct (le_lt_dec y x) as [H0|H0]; auto. + elimtype False. + assert (H1:=inj_le _ _ H0). + red in H; red in H1. + rewrite <- Zcompare_antisym in H1; rewrite H in H1; auto. Qed. -Theorem intro_Z : - forall n:nat, exists y : Z, Z_of_nat n = y /\ 0 <= y * 1 + 0. +Theorem inj_ge_rev : forall n m:nat, Z_of_nat n >= Z_of_nat m -> (n >= m)%nat. Proof. - intros x; exists (Z_of_nat x); split; - [ trivial with arith - | rewrite Zmult_comm; rewrite Zmult_1_l; rewrite Zplus_0_r; - unfold Zle in |- *; elim x; intros; simpl in |- *; - discriminate ]. + intros x y H. + destruct (le_lt_dec y x) as [H0|H0]; auto. + elimtype False. + assert (H1:=inj_gt _ _ H0). + red in H; red in H1. + rewrite <- Zcompare_antisym in H; rewrite H1 in H; auto. +Qed. + +Theorem inj_gt_rev : forall n m:nat, Z_of_nat n > Z_of_nat m -> (n > m)%nat. +Proof. + intros x y H. + destruct (le_lt_dec x y) as [H0|H0]; auto. + elimtype False. + assert (H1:=inj_ge _ _ H0). + red in H; red in H1. + rewrite <- Zcompare_antisym in H1; rewrite H in H1; auto. +Qed. + +(* Both ways ... *) + +Theorem inj_le_iff : forall n m:nat, (n<=m)%nat <-> Z_of_nat n <= Z_of_nat m. +Proof. + split; [apply inj_le | apply inj_le_rev]. +Qed. + +Theorem inj_lt_iff : forall n m:nat, (n<m)%nat <-> Z_of_nat n < Z_of_nat m. +Proof. + split; [apply inj_lt | apply inj_lt_rev]. +Qed. + +Theorem inj_ge_iff : forall n m:nat, (n>=m)%nat <-> Z_of_nat n >= Z_of_nat m. +Proof. + split; [apply inj_ge | apply inj_ge_rev]. +Qed. + +Theorem inj_gt_iff : forall n m:nat, (n>m)%nat <-> Z_of_nat n > Z_of_nat m. +Proof. + split; [apply inj_gt | apply inj_gt_rev]. +Qed. + +(** Injection and usual operations *) + +Theorem inj_plus : forall n m:nat, Z_of_nat (n + m) = Z_of_nat n + Z_of_nat m. +Proof. + intro x; induction x as [| n H]; intro y; destruct y as [| m]; + [ simpl in |- *; trivial with arith + | simpl in |- *; trivial with arith + | simpl in |- *; rewrite <- plus_n_O; trivial with arith + | change (Z_of_nat (S (n + S m)) = Z_of_nat (S n) + Z_of_nat (S m)) in |- *; + rewrite inj_S; rewrite H; do 2 rewrite inj_S; rewrite Zplus_succ_l; + trivial with arith ]. +Qed. + +Theorem inj_mult : forall n m:nat, Z_of_nat (n * m) = Z_of_nat n * Z_of_nat m. +Proof. + intro x; induction x as [| n H]; + [ simpl in |- *; trivial with arith + | intro y; rewrite inj_S; rewrite <- Zmult_succ_l_reverse; rewrite <- H; + rewrite <- inj_plus; simpl in |- *; rewrite plus_comm; + trivial with arith ]. Qed. Theorem inj_minus1 : @@ -121,6 +205,46 @@ Proof. [ trivial with arith | apply gt_not_le; assumption ]. Qed. +Theorem inj_minus : forall n m:nat, + Z_of_nat (minus n m) = Zmax 0 (Z_of_nat n - Z_of_nat m). +Proof. + intros. + rewrite Zmax_comm. + unfold Zmax. + destruct (le_lt_dec m n) as [H|H]. + + rewrite (inj_minus1 _ _ H). + assert (H':=Zle_minus_le_0 _ _ (inj_le _ _ H)). + unfold Zle in H'. + rewrite <- Zcompare_antisym in H'. + destruct Zcompare; simpl in *; intuition. + + rewrite (inj_minus2 _ _ H). + assert (H':=Zplus_lt_compat_r _ _ (- Z_of_nat m) (inj_lt _ _ H)). + rewrite Zplus_opp_r in H'. + unfold Zminus; rewrite H'; auto. +Qed. + +Theorem inj_min : forall n m:nat, + Z_of_nat (min n m) = Zmin (Z_of_nat n) (Z_of_nat m). +Proof. + induction n; destruct m; try (compute; auto; fail). + simpl min. + do 3 rewrite inj_S. + rewrite <- Zsucc_min_distr; f_equal; auto. +Qed. + +Theorem inj_max : forall n m:nat, + Z_of_nat (max n m) = Zmax (Z_of_nat n) (Z_of_nat m). +Proof. + induction n; destruct m; try (compute; auto; fail). + simpl max. + do 3 rewrite inj_S. + rewrite <- Zsucc_max_distr; f_equal; auto. +Qed. + +(** Composition of injections **) + Theorem Zpos_eq_Z_of_nat_o_nat_of_P : forall p:positive, Zpos p = Z_of_nat (nat_of_P p). Proof. @@ -136,3 +260,26 @@ Proof. rewrite inj_plus; repeat rewrite <- H. rewrite Zpos_xO; simpl in |- *; rewrite Pplus_diag; reflexivity. Qed. + +(** Misc *) + +Theorem intro_Z : + forall n:nat, exists y : Z, Z_of_nat n = y /\ 0 <= y * 1 + 0. +Proof. + intros x; exists (Z_of_nat x); split; + [ trivial with arith + | rewrite Zmult_comm; rewrite Zmult_1_l; rewrite Zplus_0_r; + unfold Zle in |- *; elim x; intros; simpl in |- *; + discriminate ]. +Qed. + +Lemma Zpos_P_of_succ_nat : forall n:nat, + Zpos (P_of_succ_nat n) = Zsucc (Z_of_nat n). +Proof. + intros. + unfold Z_of_nat. + destruct n. + simpl; auto. + simpl (P_of_succ_nat (S n)). + apply Zpos_succ_morphism. +Qed. diff --git a/theories/ZArith/Znumtheory.v b/theories/ZArith/Znumtheory.v index d89ec052..e77475e0 100644 --- a/theories/ZArith/Znumtheory.v +++ b/theories/ZArith/Znumtheory.v @@ -6,13 +6,12 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Znumtheory.v 9245 2006-10-17 12:53:34Z notin $ i*) +(*i $Id: Znumtheory.v 10295 2007-11-06 22:46:21Z letouzey $ i*) Require Import ZArith_base. Require Import ZArithRing. Require Import Zcomplements. Require Import Zdiv. -Require Import Ndigits. Require Import Wf_nat. Open Local Scope Z_scope. @@ -156,21 +155,27 @@ Qed. Lemma Zdivide_antisym : forall a b:Z, (a | b) -> (b | a) -> a = b \/ a = - b. Proof. -simple induction 1; intros. -inversion H1. -rewrite H0 in H2; clear H H1. -case (Z_zerop a); intro. -left; rewrite H0; rewrite e; ring. -assert (Hqq0 : q0 * q = 1). -apply Zmult_reg_l with a. -assumption. -ring_simplify. -pattern a at 2 in |- *; rewrite H2; ring. -assert (q | 1). -rewrite <- Hqq0; auto with zarith. -elim (Zdivide_1 q H); intros. -rewrite H1 in H0; left; omega. -rewrite H1 in H0; right; omega. + simple induction 1; intros. + inversion H1. + rewrite H0 in H2; clear H H1. + case (Z_zerop a); intro. + left; rewrite H0; rewrite e; ring. + assert (Hqq0 : q0 * q = 1). + apply Zmult_reg_l with a. + assumption. + ring_simplify. + pattern a at 2 in |- *; rewrite H2; ring. + assert (q | 1). + rewrite <- Hqq0; auto with zarith. + elim (Zdivide_1 q H); intros. + rewrite H1 in H0; left; omega. + rewrite H1 in H0; right; omega. +Qed. + +Theorem Zdivide_trans: forall a b c, (a | b) -> (b | c) -> (a | c). +Proof. + intros a b c [d H1] [e H2]; exists (d * e); auto with zarith. + rewrite H2; rewrite H1; ring. Qed. (** If [a] divides [b] and [b<>0] then [|a| <= |b|]. *) @@ -194,6 +199,134 @@ Proof. subst q; omega. Qed. +(** [Zdivide] can be expressed using [Zmod]. *) + +Lemma Zmod_divide : forall a b:Z, b > 0 -> a mod b = 0 -> (b | a). +Proof. + intros a b H H0. + apply Zdivide_intro with (a / b). + pattern a at 1 in |- *; rewrite (Z_div_mod_eq a b H). + rewrite H0; ring. +Qed. + +Lemma Zdivide_mod : forall a b:Z, b > 0 -> (b | a) -> a mod b = 0. +Proof. + intros a b; simple destruct 2; intros; subst. + change (q * b) with (0 + q * b) in |- *. + rewrite Z_mod_plus; auto. +Qed. + +(** [Zdivide] is hence decidable *) + +Lemma Zdivide_dec : forall a b:Z, {(a | b)} + {~ (a | b)}. +Proof. + intros a b; elim (Ztrichotomy_inf a 0). + (* a<0 *) + intros H; elim H; intros. + case (Z_eq_dec (b mod - a) 0). + left; apply Zdivide_opp_l_rev; apply Zmod_divide; auto with zarith. + intro H1; right; intro; elim H1; apply Zdivide_mod; auto with zarith. + (* a=0 *) + case (Z_eq_dec b 0); intro. + left; subst; auto with zarith. + right; subst; intro H0; inversion H0; omega. + (* a>0 *) + intro H; case (Z_eq_dec (b mod a) 0). + left; apply Zmod_divide; auto with zarith. + intro H1; right; intro; elim H1; apply Zdivide_mod; auto with zarith. +Qed. + +Theorem Zdivide_Zdiv_eq: forall a b : Z, + 0 < a -> (a | b) -> b = a * (b / a). +Proof. + intros a b Hb Hc. + pattern b at 1; rewrite (Z_div_mod_eq b a); auto with zarith. + rewrite (Zdivide_mod b a); auto with zarith. +Qed. + +Theorem Zdivide_Zdiv_eq_2: forall a b c : Z, + 0 < a -> (a | b) -> (c * b)/a = c * (b / a). +Proof. + intros a b c H1 H2. + inversion H2 as [z Hz]. + rewrite Hz; rewrite Zmult_assoc. + repeat rewrite Z_div_mult; auto with zarith. +Qed. + +Theorem Zdivide_Zabs_l: forall a b, (Zabs a | b) -> (a | b). +Proof. + intros a b [x H]; subst b. + pattern (Zabs a); apply Zabs_intro. + exists (- x); ring. + exists x; ring. +Qed. + +Theorem Zdivide_Zabs_inv_l: forall a b, (a | b) -> (Zabs a | b). +Proof. + intros a b [x H]; subst b. + pattern (Zabs a); apply Zabs_intro. + exists (- x); ring. + exists x; ring. +Qed. + +Theorem Zdivide_le: forall a b : Z, + 0 <= a -> 0 < b -> (a | b) -> a <= b. +Proof. + intros a b H1 H2 [q H3]; subst b. + case (Zle_lt_or_eq 0 a); auto with zarith; intros H3. + case (Zle_lt_or_eq 0 q); auto with zarith. + apply (Zmult_le_0_reg_r a); auto with zarith. + intros H4; apply Zle_trans with (1 * a); auto with zarith. + intros H4; subst q; omega. +Qed. + +Theorem Zdivide_Zdiv_lt_pos: forall a b : Z, + 1 < a -> 0 < b -> (a | b) -> 0 < b / a < b . +Proof. + intros a b H1 H2 H3; split. + apply Zmult_lt_reg_r with a; auto with zarith. + rewrite (Zmult_comm (Zdiv b a)); rewrite <- Zdivide_Zdiv_eq; auto with zarith. + apply Zmult_lt_reg_r with a; auto with zarith. + repeat rewrite (fun x => Zmult_comm x a); auto with zarith. + rewrite <- Zdivide_Zdiv_eq; auto with zarith. + pattern b at 1; replace b with (1 * b); auto with zarith. + apply Zmult_lt_compat_r; auto with zarith. +Qed. + +Lemma Zmod_div_mod: forall n m a, 0 < n -> 0 < m -> + (n | m) -> a mod n = (a mod m) mod n. +Proof. + intros n m a H1 H2 H3. + pattern a at 1; rewrite (Z_div_mod_eq a m); auto with zarith. + case H3; intros q Hq; pattern m at 1; rewrite Hq. + rewrite (Zmult_comm q). + rewrite Zplus_mod; auto with zarith. + rewrite <- Zmult_assoc; rewrite Zmult_mod; auto with zarith. + rewrite Z_mod_same; try rewrite Zmult_0_l; auto with zarith. + rewrite (Zmod_small 0); auto with zarith. + rewrite Zplus_0_l; rewrite Zmod_mod; auto with zarith. +Qed. + +Lemma Zmod_divide_minus: forall a b c : Z, 0 < b -> + a mod b = c -> (b | a - c). +Proof. + intros a b c H H1; apply Zmod_divide; auto with zarith. + rewrite Zminus_mod; auto with zarith. + rewrite H1; pattern c at 1; rewrite <- (Zmod_small c b); auto with zarith. + rewrite Zminus_diag; apply Zmod_small; auto with zarith. + subst; apply Z_mod_lt; auto with zarith. +Qed. + +Lemma Zdivide_mod_minus: forall a b c : Z, 0 <= c < b -> + (b | a - c) -> a mod b = c. +Proof. + intros a b c (H1, H2) H3; assert (0 < b); try apply Zle_lt_trans with c; auto. + replace a with ((a - c) + c); auto with zarith. + rewrite Zplus_mod; auto with zarith. + rewrite (Zdivide_mod (a -c) b); try rewrite Zplus_0_l; auto with zarith. + rewrite Zmod_mod; try apply Zmod_small; auto with zarith. +Qed. + (** * Greatest common divisor (gcd). *) (** There is no unicity of the gcd; hence we define the predicate [gcd a b d] @@ -246,6 +379,18 @@ Proof. Qed. Hint Resolve Zis_gcd_sym Zis_gcd_0 Zis_gcd_minus Zis_gcd_opp: zarith. + +Theorem Zis_gcd_unique: forall a b c d : Z, + Zis_gcd a b c -> Zis_gcd a b d -> c = d \/ c = (- d). +Proof. +intros a b c d H1 H2. +inversion_clear H1 as [Hc1 Hc2 Hc3]. +inversion_clear H2 as [Hd1 Hd2 Hd3]. +assert (H3: Zdivide c d); auto. +assert (H4: Zdivide d c); auto. +apply Zdivide_antisym; auto. +Qed. + (** * Extended Euclid algorithm. *) @@ -463,6 +608,7 @@ Qed. Lemma Zis_gcd_rel_prime : forall a b g:Z, b > 0 -> g >= 0 -> Zis_gcd a b g -> rel_prime (a / g) (b / g). +Proof. intros a b g; intros. assert (g <> 0). intro. @@ -491,6 +637,68 @@ Lemma Zis_gcd_rel_prime : exists q; auto with zarith. Qed. +Theorem rel_prime_sym: forall a b, rel_prime a b -> rel_prime b a. +Proof. + intros a b H; auto with zarith. + red; apply Zis_gcd_sym; auto with zarith. +Qed. + +Theorem rel_prime_div: forall p q r, + rel_prime p q -> (r | p) -> rel_prime r q. +Proof. + intros p q r H (u, H1); subst. + inversion_clear H as [H1 H2 H3]. + red; apply Zis_gcd_intro; try apply Zone_divide. + intros x H4 H5; apply H3; auto. + apply Zdivide_mult_r; auto. +Qed. + +Theorem rel_prime_1: forall n, rel_prime 1 n. +Proof. + intros n; red; apply Zis_gcd_intro; auto. + exists 1; auto with zarith. + exists n; auto with zarith. +Qed. + +Theorem not_rel_prime_0: forall n, 1 < n -> ~ rel_prime 0 n. +Proof. + intros n H H1; absurd (n = 1 \/ n = -1). + intros [H2 | H2]; subst; contradict H; auto with zarith. + case (Zis_gcd_unique 0 n n 1); auto. + apply Zis_gcd_intro; auto. + exists 0; auto with zarith. + exists 1; auto with zarith. +Qed. + +Theorem rel_prime_mod: forall p q, 0 < q -> + rel_prime p q -> rel_prime (p mod q) q. +Proof. + intros p q H H0. + assert (H1: Bezout p q 1). + apply rel_prime_bezout; auto. + inversion_clear H1 as [q1 r1 H2]. + apply bezout_rel_prime. + apply Bezout_intro with q1 (r1 + q1 * (p / q)). + rewrite <- H2. + pattern p at 3; rewrite (Z_div_mod_eq p q); try ring; auto with zarith. +Qed. + +Theorem rel_prime_mod_rev: forall p q, 0 < q -> + rel_prime (p mod q) q -> rel_prime p q. +Proof. + intros p q H H0. + rewrite (Z_div_mod_eq p q); auto with zarith; red. + apply Zis_gcd_sym; apply Zis_gcd_for_euclid2; auto with zarith. +Qed. + +Theorem Zrel_prime_neq_mod_0: forall a b, 1 < b -> rel_prime a b -> a mod b <> 0. +Proof. + intros a b H H1 H2. + case (not_rel_prime_0 _ H). + rewrite <- H2. + apply rel_prime_mod; auto with zarith. +Qed. + (** * Primality *) Inductive prime (p:Z) : Prop := @@ -543,42 +751,19 @@ Qed. Hint Resolve prime_rel_prime: zarith. -(** [Zdivide] can be expressed using [Zmod]. *) +(** As a consequence, a prime number is relatively prime with smaller numbers *) -Lemma Zmod_divide : forall a b:Z, b > 0 -> a mod b = 0 -> (b | a). +Theorem rel_prime_le_prime: + forall a p, prime p -> 1 <= a < p -> rel_prime a p. Proof. - intros a b H H0. - apply Zdivide_intro with (a / b). - pattern a at 1 in |- *; rewrite (Z_div_mod_eq a b H). - rewrite H0; ring. + intros a p Hp [H1 H2]. + apply rel_prime_sym; apply prime_rel_prime; auto. + intros [q Hq]; subst a. + case (Zle_or_lt q 0); intros Hl. + absurd (q * p <= 0 * p); auto with zarith. + absurd (1 * p <= q * p); auto with zarith. Qed. -Lemma Zdivide_mod : forall a b:Z, b > 0 -> (b | a) -> a mod b = 0. -Proof. - intros a b; simple destruct 2; intros; subst. - change (q * b) with (0 + q * b) in |- *. - rewrite Z_mod_plus; auto. -Qed. - -(** [Zdivide] is hence decidable *) - -Lemma Zdivide_dec : forall a b:Z, {(a | b)} + {~ (a | b)}. -Proof. - intros a b; elim (Ztrichotomy_inf a 0). - (* a<0 *) - intros H; elim H; intros. - case (Z_eq_dec (b mod - a) 0). - left; apply Zdivide_opp_l_rev; apply Zmod_divide; auto with zarith. - intro H1; right; intro; elim H1; apply Zdivide_mod; auto with zarith. - (* a=0 *) - case (Z_eq_dec b 0); intro. - left; subst; auto with zarith. - right; subst; intro H0; inversion H0; omega. - (* a>0 *) - intro H; case (Z_eq_dec (b mod a) 0). - left; apply Zmod_divide; auto with zarith. - intro H1; right; intro; elim H1; apply Zdivide_mod; auto with zarith. -Qed. (** If a prime [p] divides [ab] then it divides either [a] or [b] *) @@ -590,6 +775,108 @@ Proof. right; apply Gauss with a; auto with zarith. Qed. +Lemma not_prime_0: ~ prime 0. +Proof. + intros H1; case (prime_divisors _ H1 2); auto with zarith. +Qed. + +Lemma not_prime_1: ~ prime 1. +Proof. + intros H1; absurd (1 < 1); auto with zarith. + inversion H1; auto. +Qed. + +Lemma prime_2: prime 2. +Proof. + apply prime_intro; auto with zarith. + intros n [H1 H2]; case Zle_lt_or_eq with ( 1 := H1 ); auto with zarith; + clear H1; intros H1. + contradict H2; auto with zarith. + subst n; red; auto with zarith. + apply Zis_gcd_intro; auto with zarith. +Qed. + +Theorem prime_3: prime 3. +Proof. + apply prime_intro; auto with zarith. + intros n [H1 H2]; case Zle_lt_or_eq with ( 1 := H1 ); auto with zarith; + clear H1; intros H1. + case (Zle_lt_or_eq 2 n); auto with zarith; clear H1; intros H1. + contradict H2; auto with zarith. + subst n; red; auto with zarith. + apply Zis_gcd_intro; auto with zarith. + intros x [q1 Hq1] [q2 Hq2]. + exists (q2 - q1). + apply trans_equal with (3 - 2); auto with zarith. + rewrite Hq1; rewrite Hq2; ring. + subst n; red; auto with zarith. + apply Zis_gcd_intro; auto with zarith. +Qed. + +Theorem prime_ge_2: forall p, prime p -> 2 <= p. +Proof. + intros p Hp; inversion Hp; auto with zarith. +Qed. + +Definition prime' p := 1<p /\ (forall n, 1<n<p -> ~ (n|p)). + +Theorem prime_alt: + forall p, prime' p <-> prime p. +Proof. + split; destruct 1; intros. + (* prime -> prime' *) + constructor; auto; intros. + red; apply Zis_gcd_intro; auto with zarith; intros. + case (Zle_lt_or_eq 0 (Zabs x)); auto with zarith; intros H6. + case (Zle_lt_or_eq 1 (Zabs x)); auto with zarith; intros H7. + case (Zle_lt_or_eq (Zabs x) p); auto with zarith. + apply Zdivide_le; auto with zarith. + apply Zdivide_Zabs_inv_l; auto. + intros H8; case (H0 (Zabs x)); auto. + apply Zdivide_Zabs_inv_l; auto. + intros H8; subst p; absurd (Zabs x <= n); auto with zarith. + apply Zdivide_le; auto with zarith. + apply Zdivide_Zabs_inv_l; auto. + rewrite H7; pattern (Zabs x); apply Zabs_intro; auto with zarith. + absurd (0%Z = p); auto with zarith. + assert (x=0) by (destruct x; simpl in *; now auto). + subst x; elim H3; intro q; rewrite Zmult_0_r; auto. + (* prime' -> prime *) + split; auto; intros. + intros H2. + case (Zis_gcd_unique n p n 1); auto with zarith. + apply Zis_gcd_intro; auto with zarith. + apply H0; auto with zarith. +Qed. + +Theorem square_not_prime: forall a, ~ prime (a * a). +Proof. + intros a Ha. + rewrite <- (Zabs_square a) in Ha. + assert (0 <= Zabs a) by auto with zarith. + set (b:=Zabs a) in *; clearbody b. + rewrite <- prime_alt in Ha; destruct Ha. + case (Zle_lt_or_eq 0 b); auto with zarith; intros Hza1; [ | subst; omega]. + case (Zle_lt_or_eq 1 b); auto with zarith; intros Hza2; [ | subst; omega]. + assert (Hza3 := Zmult_lt_compat_r 1 b b Hza1 Hza2). + rewrite Zmult_1_l in Hza3. + elim (H1 _ (conj Hza2 Hza3)). + exists b; auto. +Qed. + +Theorem prime_div_prime: forall p q, + prime p -> prime q -> (p | q) -> p = q. +Proof. + intros p q H H1 H2; + assert (Hp: 0 < p); try apply Zlt_le_trans with 2; try apply prime_ge_2; auto with zarith. + assert (Hq: 0 < q); try apply Zlt_le_trans with 2; try apply prime_ge_2; auto with zarith. + case prime_divisors with (2 := H2); auto. + intros H4; contradict Hp; subst; auto with zarith. + intros [H4| [H4 | H4]]; subst; auto. + contradict H; auto; apply not_prime_1. + contradict Hp; auto with zarith. +Qed. + (** We could obtain a [Zgcd] function via Euclid algorithm. But we propose here a binary version of [Zgcd], faster and executable within Coq. @@ -617,105 +904,34 @@ Fixpoint Pgcdn (n: nat) (a b : positive) { struct n } : positive := | xO a, xO b => xO (Pgcdn n a b) | a, xO b => Pgcdn n a b | xO a, b => Pgcdn n a b - | xI a', xI b' => match Pcompare a' b' Eq with - | Eq => a - | Lt => Pgcdn n (b'-a') a - | Gt => Pgcdn n (a'-b') b - end - end - end. - -Fixpoint Pggcdn (n: nat) (a b : positive) { struct n } : (positive*(positive*positive)) := - match n with - | O => (1,(a,b)) - | S n => - match a,b with - | xH, b => (1,(1,b)) - | a, xH => (1,(a,1)) - | xO a, xO b => - let (g,p) := Pggcdn n a b in - (xO g,p) - | a, xO b => - let (g,p) := Pggcdn n a b in - let (aa,bb) := p in - (g,(aa, xO bb)) - | xO a, b => - let (g,p) := Pggcdn n a b in - let (aa,bb) := p in - (g,(xO aa, bb)) - | xI a', xI b' => match Pcompare a' b' Eq with - | Eq => (a,(1,1)) - | Lt => - let (g,p) := Pggcdn n (b'-a') a in - let (ba,aa) := p in - (g,(aa, aa + xO ba)) - | Gt => - let (g,p) := Pggcdn n (a'-b') b in - let (ab,bb) := p in - (g,(bb+xO ab, bb)) - end + | xI a', xI b' => + match Pcompare a' b' Eq with + | Eq => a + | Lt => Pgcdn n (b'-a') a + | Gt => Pgcdn n (a'-b') b + end end end. Definition Pgcd (a b: positive) := Pgcdn (Psize a + Psize b)%nat a b. -Definition Pggcd (a b: positive) := Pggcdn (Psize a + Psize b)%nat a b. -Open Scope Z_scope. +Close Scope positive_scope. -Definition Zgcd (a b : Z) : Z := match a,b with - | Z0, _ => Zabs b - | _, Z0 => Zabs a - | Zpos a, Zpos b => Zpos (Pgcd a b) - | Zpos a, Zneg b => Zpos (Pgcd a b) - | Zneg a, Zpos b => Zpos (Pgcd a b) - | Zneg a, Zneg b => Zpos (Pgcd a b) - end. - -Definition Zggcd (a b : Z) : Z*(Z*Z) := match a,b with - | Z0, _ => (Zabs b,(0, Zsgn b)) - | _, Z0 => (Zabs a,(Zsgn a, 0)) - | Zpos a, Zpos b => - let (g,p) := Pggcd a b in - let (aa,bb) := p in - (Zpos g, (Zpos aa, Zpos bb)) - | Zpos a, Zneg b => - let (g,p) := Pggcd a b in - let (aa,bb) := p in - (Zpos g, (Zpos aa, Zneg bb)) - | Zneg a, Zpos b => - let (g,p) := Pggcd a b in - let (aa,bb) := p in - (Zpos g, (Zneg aa, Zpos bb)) - | Zneg a, Zneg b => - let (g,p) := Pggcd a b in - let (aa,bb) := p in - (Zpos g, (Zneg aa, Zneg bb)) - end. +Definition Zgcd (a b : Z) : Z := + match a,b with + | Z0, _ => Zabs b + | _, Z0 => Zabs a + | Zpos a, Zpos b => Zpos (Pgcd a b) + | Zpos a, Zneg b => Zpos (Pgcd a b) + | Zneg a, Zpos b => Zpos (Pgcd a b) + | Zneg a, Zneg b => Zpos (Pgcd a b) + end. Lemma Zgcd_is_pos : forall a b, 0 <= Zgcd a b. Proof. unfold Zgcd; destruct a; destruct b; auto with zarith. Qed. -Lemma Psize_monotone : forall p q, Pcompare p q Eq = Lt -> (Psize p <= Psize q)%nat. -Proof. - induction p; destruct q; simpl; auto with arith; intros; try discriminate. - intros; generalize (Pcompare_Gt_Lt _ _ H); auto with arith. - intros; destruct (Pcompare_Lt_Lt _ _ H); auto with arith; subst; auto. -Qed. - -Lemma Pminus_Zminus : forall a b, Pcompare a b Eq = Lt -> - Zpos (b-a) = Zpos b - Zpos a. -Proof. - intros. - repeat rewrite Zpos_eq_Z_of_nat_o_nat_of_P. - rewrite nat_of_P_minus_morphism. - apply inj_minus1. - apply lt_le_weak. - apply nat_of_P_lt_Lt_compare_morphism; auto. - rewrite ZC4; rewrite H; auto. -Qed. - Lemma Zis_gcd_even_odd : forall a b g, Zis_gcd (Zpos a) (Zpos (xI b)) g -> Zis_gcd (Zpos (xO a)) (Zpos (xI b)) g. Proof. @@ -758,12 +974,12 @@ Proof. assert (Psize (b-a) <= Psize b)%nat. apply Psize_monotone. change (Zpos (b-a) < Zpos b). - rewrite (Pminus_Zminus _ _ H1). + rewrite (Zpos_minus_morphism _ _ H1). assert (0 < Zpos a) by (compute; auto). omega. omega. rewrite Zpos_xO; do 2 rewrite Zpos_xI. - rewrite Pminus_Zminus; auto. + rewrite Zpos_minus_morphism; auto. omega. (* a = xI, b = xI, compare = Gt *) apply Zis_gcd_for_euclid with 1. @@ -775,13 +991,13 @@ Proof. assert (Psize (a-b) <= Psize a)%nat. apply Psize_monotone. change (Zpos (a-b) < Zpos a). - rewrite (Pminus_Zminus b a). + rewrite (Zpos_minus_morphism b a). assert (0 < Zpos b) by (compute; auto). omega. rewrite ZC4; rewrite H1; auto. omega. rewrite Zpos_xO; do 2 rewrite Zpos_xI. - rewrite Pminus_Zminus; auto. + rewrite Zpos_minus_morphism; auto. omega. rewrite ZC4; rewrite H1; auto. (* a = xI, b = xO *) @@ -840,6 +1056,230 @@ Proof. apply Pgcd_correct. Qed. +Theorem Zgcd_spec : forall x y : Z, {z : Z | Zis_gcd x y z /\ 0 <= z}. +Proof. + intros x y; exists (Zgcd x y). + split; [apply Zgcd_is_gcd | apply Zgcd_is_pos]. +Qed. + +Theorem Zdivide_Zgcd: forall p q r : Z, + (p | q) -> (p | r) -> (p | Zgcd q r). +Proof. + intros p q r H1 H2. + assert (H3: (Zis_gcd q r (Zgcd q r))). + apply Zgcd_is_gcd. + inversion_clear H3; auto. +Qed. + +Theorem Zis_gcd_gcd: forall a b c : Z, + 0 <= c -> Zis_gcd a b c -> Zgcd a b = c. +Proof. + intros a b c H1 H2. + case (Zis_gcd_uniqueness_apart_sign a b c (Zgcd a b)); auto. + apply Zgcd_is_gcd; auto. + case Zle_lt_or_eq with (1 := H1); clear H1; intros H1; subst; auto. + intros H3; subst. + generalize (Zgcd_is_pos a b); auto with zarith. + case (Zgcd a b); simpl; auto; intros; discriminate. +Qed. + +Theorem Zgcd_inv_0_l: forall x y, Zgcd x y = 0 -> x = 0. +Proof. + intros x y H. + assert (F1: Zdivide 0 x). + rewrite <- H. + generalize (Zgcd_is_gcd x y); intros HH; inversion HH; auto. + inversion F1 as [z H1]. + rewrite H1; ring. +Qed. + +Theorem Zgcd_inv_0_r: forall x y, Zgcd x y = 0 -> y = 0. +Proof. + intros x y H. + assert (F1: Zdivide 0 y). + rewrite <- H. + generalize (Zgcd_is_gcd x y); intros HH; inversion HH; auto. + inversion F1 as [z H1]. + rewrite H1; ring. +Qed. + +Theorem Zgcd_div_swap0 : forall a b : Z, + 0 < Zgcd a b -> + 0 < b -> + (a / Zgcd a b) * b = a * (b/Zgcd a b). +Proof. + intros a b Hg Hb. + assert (F := Zgcd_is_gcd a b); inversion F as [F1 F2 F3]. + pattern b at 2; rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto. + repeat rewrite Zmult_assoc; f_equal. + rewrite Zmult_comm. + rewrite <- Zdivide_Zdiv_eq; auto. +Qed. + +Theorem Zgcd_div_swap : forall a b c : Z, + 0 < Zgcd a b -> + 0 < b -> + (c * a) / Zgcd a b * b = c * a * (b/Zgcd a b). +Proof. + intros a b c Hg Hb. + assert (F := Zgcd_is_gcd a b); inversion F as [F1 F2 F3]. + pattern b at 2; rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto. + repeat rewrite Zmult_assoc; f_equal. + rewrite Zdivide_Zdiv_eq_2; auto. + repeat rewrite <- Zmult_assoc; f_equal. + rewrite Zmult_comm. + rewrite <- Zdivide_Zdiv_eq; auto. +Qed. + +Theorem Zgcd_1_rel_prime : forall a b, + Zgcd a b = 1 <-> rel_prime a b. +Proof. + unfold rel_prime; split; intro H. + rewrite <- H; apply Zgcd_is_gcd. + case (Zis_gcd_unique a b (Zgcd a b) 1); auto. + apply Zgcd_is_gcd. + intros H2; absurd (0 <= Zgcd a b); auto with zarith. + generalize (Zgcd_is_pos a b); auto with zarith. +Qed. + +Definition rel_prime_dec: forall a b, + { rel_prime a b }+{ ~ rel_prime a b }. +Proof. + intros a b; case (Z_eq_dec (Zgcd a b) 1); intros H1. + left; apply -> Zgcd_1_rel_prime; auto. + right; contradict H1; apply <- Zgcd_1_rel_prime; auto. +Defined. + +Definition prime_dec_aux: + forall p m, + { forall n, 1 < n < m -> rel_prime n p } + + { exists n, 1 < n < m /\ ~ rel_prime n p }. +Proof. + intros p m. + case (Z_lt_dec 1 m); intros H1; + [ | left; intros; elimtype False; omega ]. + pattern m; apply natlike_rec; auto with zarith. + left; intros; elimtype False; omega. + intros x Hx IH; destruct IH as [F|E]. + destruct (rel_prime_dec x p) as [Y|N]. + left; intros n [HH1 HH2]. + case (Zgt_succ_gt_or_eq x n); auto with zarith. + intros HH3; subst x; auto. + case (Z_lt_dec 1 x); intros HH1. + right; exists x; split; auto with zarith. + left; intros n [HHH1 HHH2]; contradict HHH1; auto with zarith. + right; destruct E as (n,((H0,H2),H3)); exists n; auto with zarith. +Defined. + +Definition prime_dec: forall p, { prime p }+{ ~ prime p }. +Proof. + intros p; case (Z_lt_dec 1 p); intros H1. + case (prime_dec_aux p p); intros H2. + left; apply prime_intro; auto. + intros n [Hn1 Hn2]; case Zle_lt_or_eq with ( 1 := Hn1 ); auto. + intros HH; subst n. + red; apply Zis_gcd_intro; auto with zarith. + right; intros H3; inversion_clear H3 as [Hp1 Hp2]. + case H2; intros n [Hn1 Hn2]; case Hn2; auto with zarith. + right; intros H3; inversion_clear H3 as [Hp1 Hp2]; case H1; auto. +Defined. + +Theorem not_prime_divide: + forall p, 1 < p -> ~ prime p -> exists n, 1 < n < p /\ (n | p). +Proof. + intros p Hp Hp1. + case (prime_dec_aux p p); intros H1. + elim Hp1; constructor; auto. + intros n [Hn1 Hn2]. + case Zle_lt_or_eq with ( 1 := Hn1 ); auto with zarith. + intros H2; subst n; red; apply Zis_gcd_intro; auto with zarith. + case H1; intros n [Hn1 Hn2]. + generalize (Zgcd_is_pos n p); intros Hpos. + case (Zle_lt_or_eq 0 (Zgcd n p)); auto with zarith; intros H3. + case (Zle_lt_or_eq 1 (Zgcd n p)); auto with zarith; intros H4. + exists (Zgcd n p); split; auto. + split; auto. + apply Zle_lt_trans with n; auto with zarith. + generalize (Zgcd_is_gcd n p); intros tmp; inversion_clear tmp as [Hr1 Hr2 Hr3]. + case Hr1; intros q Hq. + case (Zle_or_lt q 0); auto with zarith; intros Ht. + absurd (n <= 0 * Zgcd n p) ; auto with zarith. + pattern n at 1; rewrite Hq; auto with zarith. + apply Zle_trans with (1 * Zgcd n p); auto with zarith. + pattern n at 2; rewrite Hq; auto with zarith. + generalize (Zgcd_is_gcd n p); intros Ht; inversion Ht; auto. + case Hn2; red. + rewrite H4; apply Zgcd_is_gcd. + generalize (Zgcd_is_gcd n p); rewrite <- H3; intros tmp; + inversion_clear tmp as [Hr1 Hr2 Hr3]. + absurd (n = 0); auto with zarith. + case Hr1; auto with zarith. +Qed. + +(** A Generalized Gcd that also computes Bezout coefficients. + The algorithm is the same as for Zgcd. *) + +Open Scope positive_scope. + +Fixpoint Pggcdn (n: nat) (a b : positive) { struct n } : (positive*(positive*positive)) := + match n with + | O => (1,(a,b)) + | S n => + match a,b with + | xH, b => (1,(1,b)) + | a, xH => (1,(a,1)) + | xO a, xO b => + let (g,p) := Pggcdn n a b in + (xO g,p) + | a, xO b => + let (g,p) := Pggcdn n a b in + let (aa,bb) := p in + (g,(aa, xO bb)) + | xO a, b => + let (g,p) := Pggcdn n a b in + let (aa,bb) := p in + (g,(xO aa, bb)) + | xI a', xI b' => + match Pcompare a' b' Eq with + | Eq => (a,(1,1)) + | Lt => + let (g,p) := Pggcdn n (b'-a') a in + let (ba,aa) := p in + (g,(aa, aa + xO ba)) + | Gt => + let (g,p) := Pggcdn n (a'-b') b in + let (ab,bb) := p in + (g,(bb+xO ab, bb)) + end + end + end. + +Definition Pggcd (a b: positive) := Pggcdn (Psize a + Psize b)%nat a b. + +Open Scope Z_scope. + +Definition Zggcd (a b : Z) : Z*(Z*Z) := + match a,b with + | Z0, _ => (Zabs b,(0, Zsgn b)) + | _, Z0 => (Zabs a,(Zsgn a, 0)) + | Zpos a, Zpos b => + let (g,p) := Pggcd a b in + let (aa,bb) := p in + (Zpos g, (Zpos aa, Zpos bb)) + | Zpos a, Zneg b => + let (g,p) := Pggcd a b in + let (aa,bb) := p in + (Zpos g, (Zpos aa, Zneg bb)) + | Zneg a, Zpos b => + let (g,p) := Pggcd a b in + let (aa,bb) := p in + (Zpos g, (Zneg aa, Zpos bb)) + | Zneg a, Zneg b => + let (g,p) := Pggcd a b in + let (aa,bb) := p in + (Zpos g, (Zneg aa, Zneg bb)) + end. + Lemma Pggcdn_gcdn : forall n a b, fst (Pggcdn n a b) = Pgcdn n a b. @@ -870,8 +1310,8 @@ Open Scope positive_scope. Lemma Pggcdn_correct_divisors : forall n a b, let (g,p) := Pggcdn n a b in - let (aa,bb):=p in - (a=g*aa) /\ (b=g*bb). + let (aa,bb):=p in + (a=g*aa) /\ (b=g*bb). Proof. induction n. simpl; auto. @@ -910,30 +1350,32 @@ Qed. Lemma Pggcd_correct_divisors : forall a b, let (g,p) := Pggcd a b in - let (aa,bb):=p in - (a=g*aa) /\ (b=g*bb). + let (aa,bb):=p in + (a=g*aa) /\ (b=g*bb). Proof. intros a b; exact (Pggcdn_correct_divisors (Psize a + Psize b)%nat a b). Qed. -Open Scope Z_scope. +Close Scope positive_scope. Lemma Zggcd_correct_divisors : forall a b, let (g,p) := Zggcd a b in - let (aa,bb):=p in - (a=g*aa) /\ (b=g*bb). + let (aa,bb):=p in + (a=g*aa) /\ (b=g*bb). Proof. destruct a; destruct b; simpl; auto; try solve [rewrite Pmult_comm; simpl; auto]; generalize (Pggcd_correct_divisors p p0); destruct (Pggcd p p0) as (g,(aa,bb)); destruct 1; subst; auto. Qed. -Theorem Zgcd_spec : forall x y : Z, {z : Z | Zis_gcd x y z /\ 0 <= z}. +Theorem Zggcd_opp: forall x y, + Zggcd (-x) y = let (p1,p) := Zggcd x y in + let (p2,p3) := p in + (p1,(-p2,p3)). Proof. - intros x y; exists (Zgcd x y). - split; [apply Zgcd_is_gcd | apply Zgcd_is_pos]. +intros [|x|x] [|y|y]; unfold Zggcd, Zopp; auto. +case Pggcd; intros p1 (p2, p3); auto. +case Pggcd; intros p1 (p2, p3); auto. +case Pggcd; intros p1 (p2, p3); auto. +case Pggcd; intros p1 (p2, p3); auto. Qed. - - - - diff --git a/theories/ZArith/Zorder.v b/theories/ZArith/Zorder.v index 47490be6..425aa83b 100644 --- a/theories/ZArith/Zorder.v +++ b/theories/ZArith/Zorder.v @@ -5,9 +5,9 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zorder.v 9302 2006-10-27 21:21:17Z barras $ i*) +(*i $Id: Zorder.v 10291 2007-11-06 02:18:53Z letouzey $ i*) -(** Binary Integers (Pierre Crégut (CNET, Lannion, France) *) +(** Binary Integers (Pierre Crégut (CNET, Lannion, France) *) Require Import BinPos. Require Import BinInt. @@ -549,7 +549,7 @@ Hint Immediate Zeq_le: zarith. (** Transitivity using successor *) -Lemma Zge_trans_succ : forall n m p:Z, Zsucc n > m -> m > p -> n > p. +Lemma Zgt_trans_succ : forall n m p:Z, Zsucc n > m -> m > p -> n > p. Proof. intros n m p H1 H2; apply Zle_gt_trans with (m := m); [ apply Zgt_succ_le; assumption | assumption ]. @@ -997,5 +997,31 @@ Proof. rewrite <- Zplus_assoc; rewrite Zplus_opp_l; rewrite Zplus_0_r; exact H. Qed. +Lemma Zmult_lt_compat: + forall n m p q : Z, 0 <= n < p -> 0 <= m < q -> n * m < p * q. +Proof. + intros n m p q (H1, H2) (H3,H4). + assert (0<p) by (apply Zle_lt_trans with n; auto). + assert (0<q) by (apply Zle_lt_trans with m; auto). + case Zle_lt_or_eq with (1 := H1); intros H5; auto with zarith. + case Zle_lt_or_eq with (1 := H3); intros H6; auto with zarith. + apply Zlt_trans with (n * q). + apply Zmult_lt_compat_l; auto. + apply Zmult_lt_compat_r; auto with zarith. + rewrite <- H6; rewrite Zmult_0_r; apply Zmult_lt_0_compat; auto with zarith. + rewrite <- H5; simpl; apply Zmult_lt_0_compat; auto with zarith. +Qed. + +Lemma Zmult_lt_compat2: + forall n m p q : Z, 0 < n <= p -> 0 < m < q -> n * m < p * q. +Proof. + intros n m p q (H1, H2) (H3, H4). + apply Zle_lt_trans with (p * m). + apply Zmult_le_compat_r; auto. + apply Zlt_le_weak; auto. + apply Zmult_lt_compat_l; auto. + apply Zlt_le_trans with n; auto. +Qed. + (** For compatibility *) Notation Zlt_O_minus_lt := Zlt_0_minus_lt (only parsing). diff --git a/theories/ZArith/Zpow_facts.v b/theories/ZArith/Zpow_facts.v new file mode 100644 index 00000000..3d4d235a --- /dev/null +++ b/theories/ZArith/Zpow_facts.v @@ -0,0 +1,465 @@ +(************************************************************************) +(* 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: Zpow_facts.v 11098 2008-06-11 09:16:22Z letouzey $ i*) + +Require Import ZArith_base. +Require Import ZArithRing. +Require Import Zcomplements. +Require Export Zpower. +Require Import Zdiv. +Require Import Znumtheory. +Open Local Scope Z_scope. + +Lemma Zpower_pos_1_r: forall x, Zpower_pos x 1 = x. +Proof. + intros x; unfold Zpower_pos; simpl; auto with zarith. +Qed. + +Lemma Zpower_pos_1_l: forall p, Zpower_pos 1 p = 1. +Proof. + induction p. + (* xI *) + rewrite xI_succ_xO, <-Pplus_diag, Pplus_one_succ_l. + repeat rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r, IHp; auto. + (* xO *) + rewrite <- Pplus_diag. + repeat rewrite Zpower_pos_is_exp. + rewrite IHp; auto. + (* xH *) + rewrite Zpower_pos_1_r; auto. +Qed. + +Lemma Zpower_pos_0_l: forall p, Zpower_pos 0 p = 0. +Proof. + induction p. + change (xI p) with (1 + (xO p))%positive. + rewrite Zpower_pos_is_exp, Zpower_pos_1_r; auto. + rewrite <- Pplus_diag. + rewrite Zpower_pos_is_exp, IHp; auto. + rewrite Zpower_pos_1_r; auto. +Qed. + +Lemma Zpower_pos_pos: forall x p, + 0 < x -> 0 < Zpower_pos x p. +Proof. + induction p; intros. + (* xI *) + rewrite xI_succ_xO, <-Pplus_diag, Pplus_one_succ_l. + repeat rewrite Zpower_pos_is_exp. + rewrite Zpower_pos_1_r. + repeat apply Zmult_lt_0_compat; auto. + (* xO *) + rewrite <- Pplus_diag. + repeat rewrite Zpower_pos_is_exp. + repeat apply Zmult_lt_0_compat; auto. + (* xH *) + rewrite Zpower_pos_1_r; auto. +Qed. + + +Theorem Zpower_1_r: forall z, z^1 = z. +Proof. + exact Zpower_pos_1_r. +Qed. + +Theorem Zpower_1_l: forall z, 0 <= z -> 1^z = 1. +Proof. + destruct z; simpl; auto. + intros; apply Zpower_pos_1_l. + intros; compute in H; elim H; auto. +Qed. + +Theorem Zpower_0_l: forall z, z<>0 -> 0^z = 0. +Proof. + destruct z; simpl; auto with zarith. + intros; apply Zpower_pos_0_l. +Qed. + +Theorem Zpower_0_r: forall z, z^0 = 1. +Proof. + simpl; auto. +Qed. + +Theorem Zpower_2: forall z, z^2 = z * z. +Proof. + intros; ring. +Qed. + +Theorem Zpower_gt_0: forall x y, + 0 < x -> 0 <= y -> 0 < x^y. +Proof. + destruct y; simpl; auto with zarith. + intros; apply Zpower_pos_pos; auto. + intros; compute in H0; elim H0; auto. +Qed. + +Theorem Zpower_Zabs: forall a b, Zabs (a^b) = (Zabs a)^b. +Proof. + intros a b; case (Zle_or_lt 0 b). + intros Hb; pattern b; apply natlike_ind; auto with zarith. + intros x Hx Hx1; unfold Zsucc. + (repeat rewrite Zpower_exp); auto with zarith. + rewrite Zabs_Zmult; rewrite Hx1. + f_equal; auto. + replace (a ^ 1) with a; auto. + simpl; unfold Zpower_pos; simpl; rewrite Zmult_1_r; auto. + simpl; unfold Zpower_pos; simpl; rewrite Zmult_1_r; auto. + case b; simpl; auto with zarith. + intros p Hp; discriminate. +Qed. + +Theorem Zpower_Zsucc: forall p n, 0 <= n -> p^(Zsucc n) = p * p^n. +Proof. + intros p n H. + unfold Zsucc; rewrite Zpower_exp; auto with zarith. + rewrite Zpower_1_r; apply Zmult_comm. +Qed. + +Theorem Zpower_mult: forall p q r, 0 <= q -> 0 <= r -> p^(q*r) = (p^q)^r. +Proof. + intros p q r H1 H2; generalize H2; pattern r; apply natlike_ind; auto. + intros H3; rewrite Zmult_0_r; repeat rewrite Zpower_exp_0; auto. + intros r1 H3 H4 H5. + unfold Zsucc; rewrite Zpower_exp; auto with zarith. + rewrite <- H4; try rewrite Zpower_1_r; try rewrite <- Zpower_exp; try f_equal; auto with zarith. + ring. + apply Zle_ge; replace 0 with (0 * r1); try apply Zmult_le_compat_r; auto. +Qed. + +Theorem Zpower_le_monotone: forall a b c, + 0 < a -> 0 <= b <= c -> a^b <= a^c. +Proof. + intros a b c H (H1, H2). + rewrite <- (Zmult_1_r (a ^ b)); replace c with (b + (c - b)); auto with zarith. + rewrite Zpower_exp; auto with zarith. + apply Zmult_le_compat_l; auto with zarith. + assert (0 < a ^ (c - b)); auto with zarith. + apply Zpower_gt_0; auto with zarith. + apply Zlt_le_weak; apply Zpower_gt_0; auto with zarith. +Qed. + +Theorem Zpower_lt_monotone: forall a b c, + 1 < a -> 0 <= b < c -> a^b < a^c. +Proof. + intros a b c H (H1, H2). + rewrite <- (Zmult_1_r (a ^ b)); replace c with (b + (c - b)); auto with zarith. + rewrite Zpower_exp; auto with zarith. + apply Zmult_lt_compat_l; auto with zarith. + apply Zpower_gt_0; auto with zarith. + assert (0 < a ^ (c - b)); auto with zarith. + apply Zpower_gt_0; auto with zarith. + apply Zlt_le_trans with (a ^1); auto with zarith. + rewrite Zpower_1_r; auto with zarith. + apply Zpower_le_monotone; auto with zarith. +Qed. + +Theorem Zpower_gt_1 : forall x y, + 1 < x -> 0 < y -> 1 < x^y. +Proof. + intros x y H1 H2. + replace 1 with (x ^ 0) by apply Zpower_0_r. + apply Zpower_lt_monotone; auto with zarith. +Qed. + +Theorem Zpower_ge_0: forall x y, 0 <= x -> 0 <= x^y. +Proof. + intros x y; case y; auto with zarith. + simpl ; auto with zarith. + intros p H1; assert (H: 0 <= Zpos p); auto with zarith. + generalize H; pattern (Zpos p); apply natlike_ind; auto with zarith. + intros p1 H2 H3 _; unfold Zsucc; rewrite Zpower_exp; simpl; auto with zarith. + apply Zmult_le_0_compat; auto with zarith. + generalize H1; case x; compute; intros; auto; try discriminate. +Qed. + +Theorem Zpower_le_monotone2: + forall a b c, 0 < a -> b <= c -> a^b <= a^c. +Proof. + intros a b c H H2. + destruct (Z_le_gt_dec 0 b). + apply Zpower_le_monotone; auto. + replace (a^b) with 0. + destruct (Z_le_gt_dec 0 c). + destruct (Zle_lt_or_eq _ _ z0). + apply Zlt_le_weak;apply Zpower_gt_0;trivial. + rewrite <- H0;simpl;auto with zarith. + replace (a^c) with 0. auto with zarith. + destruct c;trivial;unfold Zgt in z0;discriminate z0. + destruct b;trivial;unfold Zgt in z;discriminate z. +Qed. + +Theorem Zmult_power: forall p q r, 0 <= r -> + (p*q)^r = p^r * q^r. +Proof. + intros p q r H1; generalize H1; pattern r; apply natlike_ind; auto. + clear r H1; intros r H1 H2 H3. + unfold Zsucc; rewrite Zpower_exp; auto with zarith. + rewrite H2; repeat rewrite Zpower_exp; auto with zarith; ring. +Qed. + +Hint Resolve Zpower_ge_0 Zpower_gt_0: zarith. + +Theorem Zpower_le_monotone3: forall a b c, + 0 <= c -> 0 <= a <= b -> a^c <= b^c. +Proof. + intros a b c H (H1, H2). + generalize H; pattern c; apply natlike_ind; auto. + intros x HH HH1 _; unfold Zsucc; repeat rewrite Zpower_exp; auto with zarith. + repeat rewrite Zpower_1_r. + apply Zle_trans with (a^x * b); auto with zarith. +Qed. + +Lemma Zpower_le_monotone_inv: forall a b c, + 1 < a -> 0 < b -> a^b <= a^c -> b <= c. +Proof. + intros a b c H H0 H1. + destruct (Z_le_gt_dec b c);trivial. + assert (2 <= a^b). + apply Zle_trans with (2^b). + pattern 2 at 1;replace 2 with (2^1);trivial. + apply Zpower_le_monotone;auto with zarith. + apply Zpower_le_monotone3;auto with zarith. + assert (c > 0). + destruct (Z_le_gt_dec 0 c);trivial. + destruct (Zle_lt_or_eq _ _ z0);auto with zarith. + rewrite <- H3 in H1;simpl in H1; elimtype False;omega. + destruct c;try discriminate z0. simpl in H1. elimtype False;omega. + assert (H4 := Zpower_lt_monotone a c b H). elimtype False;omega. +Qed. + +Theorem Zpower_nat_Zpower: forall p q, 0 <= q -> + p^q = Zpower_nat p (Zabs_nat q). +Proof. + intros p1 q1; case q1; simpl. + intros _; exact (refl_equal _). + intros p2 _; apply Zpower_pos_nat. + intros p2 H1; case H1; auto. +Qed. + +Theorem Zpower2_lt_lin: forall n, 0 <= n -> n < 2^n. +Proof. + intros n; apply (natlike_ind (fun n => n < 2 ^n)); clear n. + simpl; auto with zarith. + intros n H1 H2; unfold Zsucc. + case (Zle_lt_or_eq _ _ H1); clear H1; intros H1. + apply Zle_lt_trans with (n + n); auto with zarith. + rewrite Zpower_exp; auto with zarith. + rewrite Zpower_1_r. + assert (tmp: forall p, p * 2 = p + p); intros; try ring; + rewrite tmp; auto with zarith. + subst n; simpl; unfold Zpower_pos; simpl; auto with zarith. +Qed. + +Theorem Zpower2_le_lin: forall n, 0 <= n -> n <= 2^n. +Proof. + intros; apply Zlt_le_weak; apply Zpower2_lt_lin; auto. +Qed. + +Lemma Zpower2_Psize : + forall n p, Zpos p < 2^(Z_of_nat n) <-> (Psize p <= n)%nat. +Proof. + induction n. + destruct p; split; intros H; discriminate H || inversion H. + destruct p; simpl Psize. + rewrite inj_S, Zpower_Zsucc; auto with zarith. + rewrite Zpos_xI; specialize IHn with p; omega. + rewrite inj_S, Zpower_Zsucc; auto with zarith. + rewrite Zpos_xO; specialize IHn with p; omega. + split; auto with arith. + intros _; apply Zpower_gt_1; auto with zarith. + rewrite inj_S; generalize (Zle_0_nat n); omega. +Qed. + +(** * Zpower and modulo *) + +Theorem Zpower_mod: forall p q n, 0 < n -> + (p^q) mod n = ((p mod n)^q) mod n. +Proof. + intros p q n Hn; case (Zle_or_lt 0 q); intros H1. + generalize H1; pattern q; apply natlike_ind; auto. + intros q1 Hq1 Rec _; unfold Zsucc; repeat rewrite Zpower_exp; repeat rewrite Zpower_1_r; auto with zarith. + rewrite (fun x => (Zmult_mod x p)); try rewrite Rec; auto with zarith. + rewrite (fun x y => (Zmult_mod (x ^y))); try f_equal; auto with zarith. + f_equal; auto; apply sym_equal; apply Zmod_mod; auto with zarith. + generalize H1; case q; simpl; auto. + intros; discriminate. +Qed. + +(** A direct way to compute Zpower modulo **) + +Fixpoint Zpow_mod_pos (a: Z)(m: positive)(n : Z) {struct m} : Z := + match m with + | xH => a mod n + | xO m' => + let z := Zpow_mod_pos a m' n in + match z with + | 0 => 0 + | _ => (z * z) mod n + end + | xI m' => + let z := Zpow_mod_pos a m' n in + match z with + | 0 => 0 + | _ => (z * z * a) mod n + end + end. + +Definition Zpow_mod a m n := + match m with + | 0 => 1 + | Zpos p => Zpow_mod_pos a p n + | Zneg p => 0 + end. + +Theorem Zpow_mod_pos_correct: forall a m n, 0 < n -> + Zpow_mod_pos a m n = (Zpower_pos a m) mod n. +Proof. + intros a m; elim m; simpl; auto. + intros p Rec n H1; rewrite xI_succ_xO, Pplus_one_succ_r, <-Pplus_diag; auto. + repeat rewrite Zpower_pos_is_exp; auto. + repeat rewrite Rec; auto. + rewrite Zpower_pos_1_r. + repeat rewrite (fun x => (Zmult_mod x a)); auto with zarith. + rewrite (Zmult_mod (Zpower_pos a p)); auto with zarith. + case (Zpower_pos a p mod n); auto. + intros p Rec n H1; rewrite <- Pplus_diag; auto. + repeat rewrite Zpower_pos_is_exp; auto. + repeat rewrite Rec; auto. + rewrite (Zmult_mod (Zpower_pos a p)); auto with zarith. + case (Zpower_pos a p mod n); auto. + unfold Zpower_pos; simpl; rewrite Zmult_1_r; auto with zarith. +Qed. + +Theorem Zpow_mod_correct: forall a m n, 1 < n -> 0 <= m -> + Zpow_mod a m n = (a ^ m) mod n. +Proof. + intros a m n; case m; simpl. + intros; apply sym_equal; apply Zmod_small; auto with zarith. + intros; apply Zpow_mod_pos_correct; auto with zarith. + intros p H H1; case H1; auto. +Qed. + +(* Complements about power and number theory. *) + +Lemma Zpower_divide: forall p q, 0 < q -> (p | p ^ q). +Proof. + intros p q H; exists (p ^(q - 1)). + pattern p at 3; rewrite <- (Zpower_1_r p); rewrite <- Zpower_exp; try f_equal; auto with zarith. +Qed. + +Theorem rel_prime_Zpower_r: forall i p q, 0 < i -> + rel_prime p q -> rel_prime p (q^i). +Proof. + intros i p q Hi Hpq; generalize Hi; pattern i; apply natlike_ind; auto with zarith; clear i Hi. + intros H; contradict H; auto with zarith. + intros i Hi Rec _; rewrite Zpower_Zsucc; auto. + apply rel_prime_mult; auto. + case Zle_lt_or_eq with (1 := Hi); intros Hi1; subst; auto. + rewrite Zpower_0_r; apply rel_prime_sym; apply rel_prime_1. +Qed. + +Theorem rel_prime_Zpower: forall i j p q, 0 <= i -> 0 <= j -> + rel_prime p q -> rel_prime (p^i) (q^j). +Proof. + intros i j p q Hi; generalize Hi j p q; pattern i; apply natlike_ind; auto with zarith; clear i Hi j p q. + intros _ j p q H H1; rewrite Zpower_0_r; apply rel_prime_1. + intros n Hn Rec _ j p q Hj Hpq. + rewrite Zpower_Zsucc; auto. + case Zle_lt_or_eq with (1 := Hj); intros Hj1; subst. + apply rel_prime_sym; apply rel_prime_mult; auto. + apply rel_prime_sym; apply rel_prime_Zpower_r; auto with arith. + apply rel_prime_sym; apply Rec; auto. + rewrite Zpower_0_r; apply rel_prime_sym; apply rel_prime_1. +Qed. + +Theorem prime_power_prime: forall p q n, 0 <= n -> + prime p -> prime q -> (p | q^n) -> p = q. +Proof. + intros p q n Hn Hp Hq; pattern n; apply natlike_ind; auto; clear n Hn. + rewrite Zpower_0_r; intros. + assert (2<=p) by (apply prime_ge_2; auto). + assert (p<=1) by (apply Zdivide_le; auto with zarith). + omega. + intros n1 H H1. + unfold Zsucc; rewrite Zpower_exp; try rewrite Zpower_1_r; auto with zarith. + assert (2<=p) by (apply prime_ge_2; auto). + assert (2<=q) by (apply prime_ge_2; auto). + intros H3; case prime_mult with (2 := H3); auto. + intros; apply prime_div_prime; auto. +Qed. + +Theorem Zdivide_power_2: forall x p n, 0 <= n -> 0 <= x -> prime p -> + (x | p^n) -> exists m, x = p^m. +Proof. + intros x p n Hn Hx; revert p n Hn; generalize Hx. + pattern x; apply Z_lt_induction; auto. + clear x Hx; intros x IH Hx p n Hn Hp H. + case Zle_lt_or_eq with (1 := Hx); auto; clear Hx; intros Hx; subst. + case (Zle_lt_or_eq 1 x); auto with zarith; clear Hx; intros Hx; subst. + (* x > 1 *) + case (prime_dec x); intros H2. + exists 1; rewrite Zpower_1_r; apply prime_power_prime with n; auto. + case not_prime_divide with (2 := H2); auto. + intros p1 ((H3, H4), (q1, Hq1)); subst. + case (IH p1) with p n; auto with zarith. + apply Zdivide_trans with (2 := H); exists q1; auto with zarith. + intros r1 Hr1. + case (IH q1) with p n; auto with zarith. + case (Zle_lt_or_eq 0 q1). + apply Zmult_le_0_reg_r with p1; auto with zarith. + split; auto with zarith. + pattern q1 at 1; replace q1 with (q1 * 1); auto with zarith. + apply Zmult_lt_compat_l; auto with zarith. + intros H5; subst; contradict Hx; auto with zarith. + apply Zmult_le_0_reg_r with p1; auto with zarith. + apply Zdivide_trans with (2 := H); exists p1; auto with zarith. + intros r2 Hr2; exists (r2 + r1); subst. + apply sym_equal; apply Zpower_exp. + generalize Hx; case r2; simpl; auto with zarith. + intros; red; simpl; intros; discriminate. + generalize H3; case r1; simpl; auto with zarith. + intros; red; simpl; intros; discriminate. + (* x = 1 *) + exists 0; rewrite Zpower_0_r; auto. + (* x = 0 *) + exists n; destruct H; rewrite Zmult_0_r in H; auto. +Qed. + +(** * Zsquare: a direct definition of [z^2] *) + +Fixpoint Psquare (p: positive): positive := + match p with + | xH => xH + | xO p => xO (xO (Psquare p)) + | xI p => xI (xO (Pplus (Psquare p) p)) + end. + +Definition Zsquare p := + match p with + | Z0 => Z0 + | Zpos p => Zpos (Psquare p) + | Zneg p => Zpos (Psquare p) + end. + +Theorem Psquare_correct: forall p, Psquare p = (p * p)%positive. +Proof. + induction p; simpl; auto; f_equal; rewrite IHp. + apply trans_equal with (xO p + xO (p*p))%positive; auto. + rewrite (Pplus_comm (xO p)); auto. + rewrite Pmult_xI_permute_r; rewrite Pplus_assoc. + f_equal; auto. + symmetry; apply Pplus_diag. + symmetry; apply Pmult_xO_permute_r. +Qed. + +Theorem Zsquare_correct: forall p, Zsquare p = p * p. +Proof. + intro p; case p; simpl; auto; intros p1; rewrite Psquare_correct; auto. +Qed. diff --git a/theories/ZArith/Zpower.v b/theories/ZArith/Zpower.v index c9cee31d..1912f5e1 100644 --- a/theories/ZArith/Zpower.v +++ b/theories/ZArith/Zpower.v @@ -6,89 +6,75 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zpower.v 9551 2007-01-29 15:13:35Z bgregoir $ i*) +(*i $Id: Zpower.v 11072 2008-06-08 16:13:37Z herbelin $ i*) +Require Import Wf_nat. Require Import ZArith_base. Require Export Zpow_def. Require Import Omega. Require Import Zcomplements. Open Local Scope Z_scope. -Section section1. +Infix "^" := Zpower : Z_scope. (** * Definition of powers over [Z]*) (** [Zpower_nat z n] is the n-th power of [z] when [n] is an unary integer (type [nat]) and [z] a signed integer (type [Z]) *) - Definition Zpower_nat (z:Z) (n:nat) := iter_nat n Z (fun x:Z => z * x) 1. - - (** [Zpower_nat_is_exp] says [Zpower_nat] is a morphism for - [plus : nat->nat] and [Zmult : Z->Z] *) - - Lemma Zpower_nat_is_exp : - forall (n m:nat) (z:Z), - Zpower_nat z (n + m) = Zpower_nat z n * Zpower_nat z m. - Proof. - intros; elim n; - [ simpl in |- *; elim (Zpower_nat z m); auto with zarith - | unfold Zpower_nat in |- *; intros; simpl in |- *; rewrite H; - apply Zmult_assoc ]. - Qed. - - (** This theorem shows that powers of unary and binary integers - are the same thing, modulo the function convert : [positive -> nat] *) - - Theorem Zpower_pos_nat : - forall (z:Z) (p:positive), Zpower_pos z p = Zpower_nat z (nat_of_P p). - Proof. - intros; unfold Zpower_pos in |- *; unfold Zpower_nat in |- *; - apply iter_nat_of_P. - Qed. - - (** Using the theorem [Zpower_pos_nat] and the lemma [Zpower_nat_is_exp] we - deduce that the function [[n:positive](Zpower_pos z n)] is a morphism - for [add : positive->positive] and [Zmult : Z->Z] *) - - Theorem Zpower_pos_is_exp : - forall (n m:positive) (z:Z), - Zpower_pos z (n + m) = Zpower_pos z n * Zpower_pos z m. - Proof. - intros. - rewrite (Zpower_pos_nat z n). - rewrite (Zpower_pos_nat z m). - rewrite (Zpower_pos_nat z (n + m)). - rewrite (nat_of_P_plus_morphism n m). - apply Zpower_nat_is_exp. - Qed. - - Infix "^" := Zpower : Z_scope. - - Hint Immediate Zpower_nat_is_exp: zarith. - Hint Immediate Zpower_pos_is_exp: zarith. - Hint Unfold Zpower_pos: zarith. - Hint Unfold Zpower_nat: zarith. - - Lemma Zpower_exp : - forall x n m:Z, n >= 0 -> m >= 0 -> x ^ (n + m) = x ^ n * x ^ m. - Proof. - destruct n; destruct m; auto with zarith. - simpl in |- *; intros; apply Zred_factor0. - simpl in |- *; auto with zarith. - intros; compute in H0; absurd (Datatypes.Lt = Datatypes.Lt); auto with zarith. - intros; compute in H0; absurd (Datatypes.Lt = Datatypes.Lt); auto with zarith. - Qed. - -End section1. - -(** Exporting notation "^" *) - -Infix "^" := Zpower : Z_scope. - -Hint Immediate Zpower_nat_is_exp: zarith. -Hint Immediate Zpower_pos_is_exp: zarith. -Hint Unfold Zpower_pos: zarith. -Hint Unfold Zpower_nat: zarith. +Definition Zpower_nat (z:Z) (n:nat) := iter_nat n Z (fun x:Z => z * x) 1. + +(** [Zpower_nat_is_exp] says [Zpower_nat] is a morphism for + [plus : nat->nat] and [Zmult : Z->Z] *) + +Lemma Zpower_nat_is_exp : + forall (n m:nat) (z:Z), + Zpower_nat z (n + m) = Zpower_nat z n * Zpower_nat z m. +Proof. + intros; elim n; + [ simpl in |- *; elim (Zpower_nat z m); auto with zarith + | unfold Zpower_nat in |- *; intros; simpl in |- *; rewrite H; + apply Zmult_assoc ]. +Qed. + +(** This theorem shows that powers of unary and binary integers + are the same thing, modulo the function convert : [positive -> nat] *) + +Lemma Zpower_pos_nat : + forall (z:Z) (p:positive), Zpower_pos z p = Zpower_nat z (nat_of_P p). +Proof. + intros; unfold Zpower_pos in |- *; unfold Zpower_nat in |- *; + apply iter_nat_of_P. +Qed. + +(** Using the theorem [Zpower_pos_nat] and the lemma [Zpower_nat_is_exp] we + deduce that the function [[n:positive](Zpower_pos z n)] is a morphism + for [add : positive->positive] and [Zmult : Z->Z] *) + +Lemma Zpower_pos_is_exp : + forall (n m:positive) (z:Z), + Zpower_pos z (n + m) = Zpower_pos z n * Zpower_pos z m. +Proof. + intros. + rewrite (Zpower_pos_nat z n). + rewrite (Zpower_pos_nat z m). + rewrite (Zpower_pos_nat z (n + m)). + rewrite (nat_of_P_plus_morphism n m). + apply Zpower_nat_is_exp. +Qed. + +Hint Immediate Zpower_nat_is_exp Zpower_pos_is_exp : zarith. +Hint Unfold Zpower_pos Zpower_nat: zarith. + +Theorem Zpower_exp : + forall x n m:Z, n >= 0 -> m >= 0 -> x ^ (n + m) = x ^ n * x ^ m. +Proof. + destruct n; destruct m; auto with zarith. + simpl; intros; apply Zred_factor0. + simpl; auto with zarith. + intros; compute in H0; elim H0; auto. + intros; compute in H; elim H; auto. +Qed. Section Powers_of_2. diff --git a/theories/ZArith/Zsqrt.v b/theories/ZArith/Zsqrt.v index 3f475a63..6ea952e6 100644 --- a/theories/ZArith/Zsqrt.v +++ b/theories/ZArith/Zsqrt.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: Zsqrt.v 9551 2007-01-29 15:13:35Z bgregoir $ *) +(* $Id: Zsqrt.v 10295 2007-11-06 22:46:21Z letouzey $ *) Require Import ZArithRing. Require Import Omega. @@ -148,6 +148,7 @@ Definition Zsqrt_plain (x:Z) : Z := end. (** A basic theorem about Zsqrt_plain *) + Theorem Zsqrt_interval : forall n:Z, 0 <= n -> @@ -162,3 +163,53 @@ Proof. intros p Hle; elim Hle; auto. Qed. +(** Positivity *) + +Theorem Zsqrt_plain_is_pos: forall n, 0 <= n -> 0 <= Zsqrt_plain n. +Proof. + intros n m; case (Zsqrt_interval n); auto with zarith. + intros H1 H2; case (Zle_or_lt 0 (Zsqrt_plain n)); auto. + intros H3; contradict H2; auto; apply Zle_not_lt. + apply Zle_trans with ( 2 := H1 ). + replace ((Zsqrt_plain n + 1) * (Zsqrt_plain n + 1)) + with (Zsqrt_plain n * Zsqrt_plain n + (2 * Zsqrt_plain n + 1)); + auto with zarith. + ring. +Qed. + +(** Direct correctness on squares. *) + +Theorem Zsqrt_square_id: forall a, 0 <= a -> Zsqrt_plain (a * a) = a. +Proof. + intros a H. + generalize (Zsqrt_plain_is_pos (a * a)); auto with zarith; intros Haa. + case (Zsqrt_interval (a * a)); auto with zarith. + intros H1 H2. + case (Zle_or_lt a (Zsqrt_plain (a * a))); intros H3; auto. + case Zle_lt_or_eq with (1:=H3); auto; clear H3; intros H3. + contradict H1; auto; apply Zlt_not_le; auto with zarith. + apply Zle_lt_trans with (a * Zsqrt_plain (a * a)); auto with zarith. + apply Zmult_lt_compat_r; auto with zarith. + contradict H2; auto; apply Zle_not_lt; auto with zarith. + apply Zmult_le_compat; auto with zarith. +Qed. + +(** [Zsqrt_plain] is increasing *) + +Theorem Zsqrt_le: + forall p q, 0 <= p <= q -> Zsqrt_plain p <= Zsqrt_plain q. +Proof. + intros p q [H1 H2]; case Zle_lt_or_eq with (1:=H2); clear H2; intros H2; + [ | subst q; auto with zarith]. + case (Zle_or_lt (Zsqrt_plain p) (Zsqrt_plain q)); auto; intros H3. + assert (Hp: (0 <= Zsqrt_plain q)). + apply Zsqrt_plain_is_pos; auto with zarith. + absurd (q <= p); auto with zarith. + apply Zle_trans with ((Zsqrt_plain q + 1) * (Zsqrt_plain q + 1)). + case (Zsqrt_interval q); auto with zarith. + apply Zle_trans with (Zsqrt_plain p * Zsqrt_plain p); auto with zarith. + apply Zmult_le_compat; auto with zarith. + case (Zsqrt_interval p); auto with zarith. +Qed. + + |