summaryrefslogtreecommitdiff
path: root/theories/QArith
diff options
context:
space:
mode:
Diffstat (limited to 'theories/QArith')
-rw-r--r--theories/QArith/QArith_base.v62
-rw-r--r--theories/QArith/Qcanon.v526
-rw-r--r--theories/QArith/Qreduction.v111
3 files changed, 591 insertions, 108 deletions
diff --git a/theories/QArith/QArith_base.v b/theories/QArith/QArith_base.v
index 1d56b747..335466a6 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 8883 2006-05-31 21:56:37Z letouzey $ i*)
+(*i $Id: QArith_base.v 8989 2006-06-25 22:17:49Z letouzey $ i*)
Require Export ZArith.
Require Export ZArithRing.
@@ -43,12 +43,48 @@ Notation Qge := (fun x y : Q => Qle y x).
Infix "==" := Qeq (at level 70, no associativity) : Q_scope.
Infix "<" := Qlt : Q_scope.
+Infix ">" := Qgt : Q_scope.
Infix "<=" := Qle : Q_scope.
-Infix ">" := Qgt : Q_scope.
-Infix ">=" := Qge : Q_scope.
+Infix ">=" := Qge : Q_scope.
Notation "x <= y <= z" := (x<=y/\y<=z) : Q_scope.
-Hint Unfold Qeq Qle Qlt: qarith.
+(** Another approach : using Qcompare for defining order relations. *)
+
+Definition Qcompare (p q : Q) := (Qnum p * QDen q ?= Qnum q * QDen p)%Z.
+Notation "p ?= q" := (Qcompare p q) : Q_scope.
+
+Lemma Qeq_alt : forall p q, (p == q) <-> (p ?= q) = Eq.
+Proof.
+unfold Qeq, Qcompare; intros; split; intros.
+rewrite H; apply Zcompare_refl.
+apply Zcompare_Eq_eq; auto.
+Qed.
+
+Lemma Qlt_alt : forall p q, (p<q) <-> (p?=q = Lt).
+Proof.
+unfold Qlt, Qcompare, Zlt; split; auto.
+Qed.
+
+Lemma Qgt_alt : forall p q, (p>q) <-> (p?=q = Gt).
+Proof.
+unfold Qlt, Qcompare, Zlt.
+intros; rewrite Zcompare_Gt_Lt_antisym; split; auto.
+Qed.
+
+Lemma Qle_alt : forall p q, (p<=q) <-> (p?=q <> Gt).
+Proof.
+unfold Qle, Qcompare, Zle; split; auto.
+Qed.
+
+Lemma Qge_alt : forall p q, (p>=q) <-> (p?=q <> Lt).
+Proof.
+unfold Qle, Qcompare, Zle.
+split; intros; swap H.
+rewrite Zcompare_Gt_Lt_antisym; auto.
+rewrite Zcompare_Gt_Lt_antisym in H0; auto.
+Qed.
+
+Hint Unfold Qeq Qlt Qle: qarith.
Hint Extern 5 (?X1 <> ?X2) => intro; discriminate: qarith.
(** Properties of equality. *)
@@ -236,6 +272,24 @@ apply Zmult_gt_0_lt_compat_l; auto with zarith.
Open Scope Q_scope.
Qed.
+
+Lemma Qcompare_egal_dec: forall n m p q : Q,
+ (n<m -> p<q) -> (n==m -> p==q) -> (n>m -> p>q) -> ((n?=m) = (p?=q)).
+Proof.
+intros.
+do 2 rewrite Qeq_alt in H0.
+unfold Qeq, Qlt, Qcompare in *.
+apply Zcompare_egal_dec; auto.
+omega.
+Qed.
+
+
+Add Morphism Qcompare : Qcompare_comp.
+Proof.
+intros; apply Qcompare_egal_dec; rewrite H; rewrite H0; auto.
+Qed.
+
+
(** [0] and [1] are apart *)
Lemma Q_apart_0_1 : ~ 1 == 0.
diff --git a/theories/QArith/Qcanon.v b/theories/QArith/Qcanon.v
new file mode 100644
index 00000000..9cbd400d
--- /dev/null
+++ b/theories/QArith/Qcanon.v
@@ -0,0 +1,526 @@
+(************************************************************************)
+(* 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: Qcanon.v 8989 2006-06-25 22:17:49Z letouzey $ i*)
+
+Require Import QArith.
+Require Import Eqdep_dec.
+
+(** [Qc] : A canonical representation of rational numbers.
+ based on the setoid representation [Q]. *)
+
+Record Qc : Set := Qcmake { this :> Q ; canon : Qred this = this }.
+
+Delimit Scope Qc_scope with Qc.
+Bind Scope Qc_scope with Qc.
+Arguments Scope Qcmake [Q_scope].
+Open Scope Qc_scope.
+
+Lemma Qred_identity :
+ forall q:Q, Zgcd (Qnum q) (QDen q) = 1%Z -> Qred q = q.
+Proof.
+unfold Qred; intros (a,b); simpl.
+generalize (Zggcd_gcd a ('b)) (Zggcd_correct_divisors a ('b)).
+intros.
+rewrite H1 in H; clear H1.
+destruct (Zggcd a ('b)) as (g,(aa,bb)); simpl in *; subst.
+destruct H0.
+rewrite Zmult_1_l in H, H0.
+subst; simpl; auto.
+Qed.
+
+Lemma Qred_identity2 :
+ forall q:Q, Qred q = q -> Zgcd (Qnum q) (QDen q) = 1%Z.
+Proof.
+unfold Qred; intros (a,b); simpl.
+generalize (Zggcd_gcd a ('b)) (Zggcd_correct_divisors a ('b)) (Zgcd_is_pos a ('b)).
+intros.
+rewrite <- H; rewrite <- H in H1; clear H.
+destruct (Zggcd a ('b)) as (g,(aa,bb)); simpl in *; subst.
+injection H2; intros; clear H2.
+destruct H0.
+clear H0 H3.
+destruct g as [|g|g]; destruct bb as [|bb|bb]; simpl in *; try discriminate.
+f_equal.
+apply Pmult_reg_r with bb.
+injection H2; intros.
+rewrite <- H0.
+rewrite H; simpl; auto.
+elim H1; auto.
+Qed.
+
+Lemma Qred_iff : forall q:Q, Qred q = q <-> Zgcd (Qnum q) (QDen q) = 1%Z.
+Proof.
+split; intros.
+apply Qred_identity2; auto.
+apply Qred_identity; auto.
+Qed.
+
+
+Lemma Qred_involutive : forall q:Q, Qred (Qred q) = Qred q.
+Proof.
+intros; apply Qred_complete.
+apply Qred_correct.
+Qed.
+
+Definition Q2Qc (q:Q) : Qc := Qcmake (Qred q) (Qred_involutive q).
+Arguments Scope Q2Qc [Q_scope].
+Notation " !! " := Q2Qc : Qc_scope.
+
+Lemma Qc_is_canon : forall q q' : Qc, q == q' -> q = q'.
+Proof.
+intros (q,proof_q) (q',proof_q').
+simpl.
+intros H.
+assert (H0:=Qred_complete _ _ H).
+assert (q = q') by congruence.
+subst q'.
+assert (proof_q = proof_q').
+ apply eq_proofs_unicity; auto; intros.
+ repeat decide equality.
+congruence.
+Qed.
+Hint Resolve Qc_is_canon.
+
+Notation " 0 " := (!!0) : Qc_scope.
+Notation " 1 " := (!!1) : Qc_scope.
+
+Definition Qcle (x y : Qc) := (x <= y)%Q.
+Definition Qclt (x y : Qc) := (x < y)%Q.
+Notation Qcgt := (fun x y : Qc => Qlt y x).
+Notation Qcge := (fun x y : Qc => Qle y x).
+Infix "<" := Qclt : Qc_scope.
+Infix "<=" := Qcle : Qc_scope.
+Infix ">" := Qcgt : Qc_scope.
+Infix ">=" := Qcge : 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.
+
+Lemma Qceq_alt : forall p q, (p = q) <-> (p ?= q) = Eq.
+Proof.
+unfold Qccompare.
+intros; rewrite <- Qeq_alt.
+split; auto.
+intro H; rewrite H; auto with qarith.
+Qed.
+
+Lemma Qclt_alt : forall p q, (p<q) <-> (p?=q = Lt).
+Proof.
+intros; exact (Qlt_alt p q).
+Qed.
+
+Lemma Qcgt_alt : forall p q, (p>q) <-> (p?=q = Gt).
+Proof.
+intros; exact (Qgt_alt p q).
+Qed.
+
+Lemma Qle_alt : forall p q, (p<=q) <-> (p?=q <> Gt).
+Proof.
+intros; exact (Qle_alt p q).
+Qed.
+
+Lemma Qge_alt : forall p q, (p>=q) <-> (p?=q <> Lt).
+Proof.
+intros; exact (Qge_alt p q).
+Qed.
+
+(** equality on [Qc] is decidable: *)
+
+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.
+Defined.
+
+(** The addition, multiplication and opposite are defined
+ in the straightforward way: *)
+
+Definition Qcplus (x y : Qc) := !!(x+y).
+Infix "+" := Qcplus : Qc_scope.
+Definition Qcmult (x y : Qc) := !!(x*y).
+Infix "*" := Qcmult : Qc_scope.
+Definition Qcopp (x : Qc) := !!(-x).
+Notation "- x" := (Qcopp x) : Qc_scope.
+Definition Qcminus (x y : Qc) := x+-y.
+Infix "-" := Qcminus : Qc_scope.
+Definition Qcinv (x : Qc) := !!(/x).
+Notation "/ x" := (Qcinv x) : Qc_scope.
+Definition Qcdiv (x y : Qc) := x*/y.
+Infix "/" := Qcdiv : Qc_scope.
+
+(** [0] and [1] are apart *)
+
+Lemma Q_apart_0_1 : 1 <> 0.
+Proof.
+ unfold Q2Qc.
+ intros H; discriminate H.
+Qed.
+
+Ltac qc := match goal with
+ | q:Qc |- _ => destruct q; qc
+ | _ => apply Qc_is_canon; simpl; repeat rewrite Qred_correct
+end.
+
+Opaque Qred.
+
+(** Addition is associative: *)
+
+Theorem Qcplus_assoc : forall x y z, x+(y+z)=(x+y)+z.
+Proof.
+ intros; qc; apply Qplus_assoc.
+Qed.
+
+(** [0] is a neutral element for addition: *)
+
+Lemma Qcplus_0_l : forall x, 0+x = x.
+Proof.
+ intros; qc; apply Qplus_0_l.
+Qed.
+
+Lemma Qcplus_0_r : forall x, x+0 = x.
+Proof.
+ intros; qc; apply Qplus_0_r.
+Qed.
+
+(** Commutativity of addition: *)
+
+Theorem Qcplus_comm : forall x y, x+y = y+x.
+Proof.
+ intros; qc; apply Qplus_comm.
+Qed.
+
+(** Properties of [Qopp] *)
+
+Lemma Qcopp_involutive : forall q, - -q = q.
+Proof.
+ intros; qc; apply Qopp_involutive.
+Qed.
+
+Theorem Qcplus_opp_r : forall q, q+(-q) = 0.
+Proof.
+ intros; qc; apply Qplus_opp_r.
+Qed.
+
+(** Multiplication is associative: *)
+
+Theorem Qcmult_assoc : forall n m p, n*(m*p)=(n*m)*p.
+Proof.
+ intros; qc; apply Qmult_assoc.
+Qed.
+
+(** [1] is a neutral element for multiplication: *)
+
+Lemma Qcmult_1_l : forall n, 1*n = n.
+Proof.
+ intros; qc; apply Qmult_1_l.
+Qed.
+
+Theorem Qcmult_1_r : forall n, n*1=n.
+Proof.
+ intros; qc; apply Qmult_1_r.
+Qed.
+
+(** Commutativity of multiplication *)
+
+Theorem Qcmult_comm : forall x y, x*y=y*x.
+Proof.
+ intros; qc; apply Qmult_comm.
+Qed.
+
+(** Distributivity *)
+
+Theorem Qcmult_plus_distr_r : forall x y z, x*(y+z)=(x*y)+(x*z).
+Proof.
+ intros; qc; apply Qmult_plus_distr_r.
+Qed.
+
+Theorem Qcmult_plus_distr_l : forall x y z, (x+y)*z=(x*z)+(y*z).
+Proof.
+ intros; qc; apply Qmult_plus_distr_l.
+Qed.
+
+(** Integrality *)
+
+Theorem Qcmult_integral : forall x y, x*y=0 -> x=0 \/ y=0.
+Proof.
+ intros.
+ destruct (Qmult_integral x y); try qc; auto.
+ injection H; clear H; intros.
+ rewrite <- (Qred_correct (x*y)).
+ rewrite <- (Qred_correct 0).
+ rewrite H; auto with qarith.
+Qed.
+
+Theorem Qcmult_integral_l : forall x y, ~ x = 0 -> x*y = 0 -> y = 0.
+Proof.
+ intros; destruct (Qcmult_integral _ _ H0); tauto.
+Qed.
+
+(** Inverse and division. *)
+
+Theorem Qcmult_inv_r : forall x, x<>0 -> x*(/x) = 1.
+Proof.
+ intros; qc; apply Qmult_inv_r; auto.
+Qed.
+
+Theorem Qcmult_inv_l : forall x, x<>0 -> (/x)*x = 1.
+Proof.
+ intros.
+ rewrite Qcmult_comm.
+ apply Qcmult_inv_r; auto.
+Qed.
+
+Lemma Qcinv_mult_distr : forall p q, / (p * q) = /p * /q.
+Proof.
+ intros; qc; apply Qinv_mult_distr.
+Qed.
+
+Theorem Qcdiv_mult_l : forall x y, y<>0 -> (x*y)/y = x.
+Proof.
+ unfold Qcdiv.
+ intros.
+ rewrite <- Qcmult_assoc.
+ rewrite Qcmult_inv_r; auto.
+ apply Qcmult_1_r.
+Qed.
+
+Theorem Qcmult_div_r : forall x y, ~ y = 0 -> y*(x/y) = x.
+Proof.
+ unfold Qcdiv.
+ intros.
+ rewrite Qcmult_assoc.
+ rewrite Qcmult_comm.
+ rewrite Qcmult_assoc.
+ rewrite Qcmult_inv_l; auto.
+ apply Qcmult_1_l.
+Qed.
+
+(** Properties of order upon Q. *)
+
+Lemma Qcle_refl : forall x, x<=x.
+Proof.
+unfold Qcle; intros; simpl; apply Qle_refl.
+Qed.
+
+Lemma Qcle_antisym : forall x y, x<=y -> y<=x -> x=y.
+Proof.
+unfold Qcle; intros; simpl in *.
+apply Qc_is_canon; apply Qle_antisym; auto.
+Qed.
+
+Lemma Qcle_trans : forall x y z, x<=y -> y<=z -> x<=z.
+Proof.
+unfold Qcle; intros; eapply Qle_trans; eauto.
+Qed.
+
+Lemma Qclt_not_eq : forall x y, x<y -> x<>y.
+Proof.
+unfold Qclt; intros; simpl in *.
+intro; destruct (Qlt_not_eq _ _ H).
+subst; auto with qarith.
+Qed.
+
+(** Large = strict or equal *)
+
+Lemma Qclt_le_weak : forall x y, x<y -> x<=y.
+Proof.
+unfold Qcle, Qclt; intros; apply Qlt_le_weak; auto.
+Qed.
+
+Lemma Qcle_lt_trans : forall x y z, x<=y -> y<z -> x<z.
+Proof.
+unfold Qcle, Qclt; intros; eapply Qle_lt_trans; eauto.
+Qed.
+
+Lemma Qclt_le_trans : forall x y z, x<y -> y<=z -> x<z.
+Proof.
+unfold Qcle, Qclt; intros; eapply Qlt_le_trans; eauto.
+Qed.
+
+Lemma Qlt_trans : forall x y z, x<y -> y<z -> x<z.
+Proof.
+unfold Qclt; intros; eapply Qlt_trans; eauto.
+Qed.
+
+(** [x<y] iff [~(y<=x)] *)
+
+Lemma Qcnot_lt_le : forall x y, ~ x<y -> y<=x.
+Proof.
+unfold Qcle, Qclt; intros; apply Qnot_lt_le; auto.
+Qed.
+
+Lemma Qcnot_le_lt : forall x y, ~ x<=y -> y<x.
+Proof.
+unfold Qcle, Qclt; intros; apply Qnot_le_lt; auto.
+Qed.
+
+Lemma Qclt_not_le : forall x y, x<y -> ~ y<=x.
+Proof.
+unfold Qcle, Qclt; intros; apply Qlt_not_le; auto.
+Qed.
+
+Lemma Qcle_not_lt : forall x y, x<=y -> ~ y<x.
+Proof.
+unfold Qcle, Qclt; intros; apply Qle_not_lt; auto.
+Qed.
+
+Lemma Qcle_lt_or_eq : forall x y, x<=y -> x<y \/ x==y.
+Proof.
+unfold Qcle, Qclt; intros; apply Qle_lt_or_eq; auto.
+Qed.
+
+(** Some decidability results about orders. *)
+
+Lemma Qc_dec : forall x y, {x<y} + {y<x} + {x=y}.
+Proof.
+unfold Qclt, Qcle; intros.
+destruct (Q_dec x y) as [H|H].
+left; auto.
+right; apply Qc_is_canon; auto.
+Defined.
+
+Lemma Qclt_le_dec : forall x y, {x<y} + {y<=x}.
+Proof.
+unfold Qclt, Qcle; intros; apply Qlt_le_dec; auto.
+Defined.
+
+(** Compatibility of operations with respect to order. *)
+
+Lemma Qcopp_le_compat : forall p q, p<=q -> -q <= -p.
+Proof.
+unfold Qcle, Qcopp; intros; simpl in *.
+repeat rewrite Qred_correct.
+apply Qopp_le_compat; auto.
+Qed.
+
+Lemma Qcle_minus_iff : forall p q, p <= q <-> 0 <= q+-p.
+Proof.
+unfold Qcle, Qcminus; intros; simpl in *.
+repeat rewrite Qred_correct.
+apply Qle_minus_iff; auto.
+Qed.
+
+Lemma Qclt_minus_iff : forall p q, p < q <-> 0 < q+-p.
+Proof.
+unfold Qclt, Qcplus, Qcopp; intros; simpl in *.
+repeat rewrite Qred_correct.
+apply Qlt_minus_iff; auto.
+Qed.
+
+Lemma Qcplus_le_compat :
+ forall x y z t, x<=y -> z<=t -> x+z <= y+t.
+Proof.
+unfold Qcplus, Qcle; intros; simpl in *.
+repeat rewrite Qred_correct.
+apply Qplus_le_compat; auto.
+Qed.
+
+Lemma Qcmult_le_compat_r : forall x y z, x <= y -> 0 <= z -> x*z <= y*z.
+Proof.
+unfold Qcmult, Qcle; intros; simpl in *.
+repeat rewrite Qred_correct.
+apply Qmult_le_compat_r; auto.
+Qed.
+
+Lemma Qcmult_lt_0_le_reg_r : forall x y z, 0 < z -> x*z <= y*z -> x <= y.
+Proof.
+unfold Qcmult, Qcle, Qclt; intros; simpl in *.
+repeat progress rewrite Qred_correct in * |-.
+eapply Qmult_lt_0_le_reg_r; eauto.
+Qed.
+
+Lemma Qcmult_lt_compat_r : forall x y z, 0 < z -> x < y -> x*z < y*z.
+Proof.
+unfold Qcmult, Qclt; intros; simpl in *.
+repeat progress rewrite Qred_correct in *.
+eapply Qmult_lt_compat_r; eauto.
+Qed.
+
+(** Rational to the n-th power *)
+
+Fixpoint Qcpower (q:Qc)(n:nat) { struct n } : Qc :=
+ match n with
+ | O => 1
+ | S n => q * (Qcpower q n)
+ end.
+
+Notation " q ^ n " := (Qcpower q n) : Qc_scope.
+
+Lemma Qcpower_1 : forall n, 1^n = 1.
+Proof.
+induction n; simpl; auto with qarith.
+rewrite IHn; auto with qarith.
+Qed.
+
+Lemma Qcpower_0 : forall n, n<>O -> 0^n = 0.
+Proof.
+destruct n; simpl.
+destruct 1; auto.
+intros.
+apply Qc_is_canon.
+simpl.
+compute; auto.
+Qed.
+
+Lemma Qpower_pos : forall p n, 0 <= p -> 0 <= p^n.
+Proof.
+induction n; simpl; auto with qarith.
+intros; compute; intro; discriminate.
+intros.
+apply Qcle_trans with (0*(p^n)).
+compute; intro; discriminate.
+apply Qcmult_le_compat_r; auto.
+Qed.
+
+(** And now everything is easier concerning tactics: *)
+
+(** A ring tactic for rational numbers *)
+
+Definition Qc_eq_bool (x y : Qc) :=
+ if Qc_eq_dec x y then true else false.
+
+Lemma Qc_eq_bool_correct : forall x y : Qc, Qc_eq_bool x y = true -> x=y.
+intros x y; unfold Qc_eq_bool in |- *; case (Qc_eq_dec x y); simpl in |- *; auto.
+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 ].
+
+(** A field tactic for rational numbers *)
+
+Require Import Field.
+
+Add Field Qc Qcplus Qcmult 1 0 Qcopp Qc_eq_bool Qcinv Qcrt Qcmult_inv_l
+ with div:=Qcdiv.
+
+Example test_field : forall x y : Qc, y<>0 -> (x/y)*y = x.
+intros.
+field.
+auto.
+Qed.
+
+
+
diff --git a/theories/QArith/Qreduction.v b/theories/QArith/Qreduction.v
index 049c195a..c503daad 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 8883 2006-05-31 21:56:37Z letouzey $ i*)
+(*i $Id: Qreduction.v 8989 2006-06-25 22:17:49Z letouzey $ i*)
(** * Normalisation functions for rational numbers. *)
@@ -32,65 +32,17 @@ Proof.
simple destruct z; simpl in |- *; auto; intros; elim H; auto.
Qed.
-(** A simple cancelation by powers of two *)
-
-Fixpoint Pfactor_twos (p p':positive) {struct p} : (positive*positive) :=
- match p, p' with
- | xO p, xO p' => Pfactor_twos p p'
- | _, _ => (p,p')
- end.
-
-Definition Qfactor_twos (q:Q) :=
- let (p,q) := q in
- match p with
- | Z0 => 0
- | Zpos p => let (p,q) := Pfactor_twos p q in (Zpos p)#q
- | Zneg p => let (p,q) := Pfactor_twos p q in (Zneg p)#q
- end.
-
-Lemma Pfactor_twos_correct : forall p p',
- (p*(snd (Pfactor_twos p p')))%positive =
- (p'*(fst (Pfactor_twos p p')))%positive.
-Proof.
-induction p; intros.
-simpl snd; simpl fst; rewrite Pmult_comm; auto.
-destruct p'.
-simpl snd; simpl fst; rewrite Pmult_comm; auto.
-simpl; f_equal; auto.
-simpl snd; simpl fst; rewrite Pmult_comm; auto.
-simpl snd; simpl fst; rewrite Pmult_comm; auto.
-Qed.
-
-Lemma Qfactor_twos_correct : forall q, Qfactor_twos q == q.
-Proof.
-intros (p,q).
-destruct p.
-red; simpl; auto.
-simpl.
-generalize (Pfactor_twos_correct p q); destruct (Pfactor_twos p q).
-red; simpl.
-intros; f_equal.
-rewrite H; apply Pmult_comm.
-simpl.
-generalize (Pfactor_twos_correct p q); destruct (Pfactor_twos p q).
-red; simpl.
-intros; f_equal.
-rewrite H; apply Pmult_comm.
-Qed.
-Hint Resolve Qfactor_twos_correct.
-
(** Simplification of fractions using [Zgcd].
This version can compute within Coq. *)
Definition Qred (q:Q) :=
- let (q1,q2) := Qfactor_twos q in
- let (r1,r2) := snd (Zggcd q1 (Zpos q2)) in r1#(Z2P r2).
+ let (q1,q2) := q in
+ let (r1,r2) := snd (Zggcd q1 ('q2))
+ in r1#(Z2P r2).
Lemma Qred_correct : forall q, (Qred q) == q.
Proof.
-intros; apply Qeq_trans with (Qfactor_twos q); auto.
-unfold Qred.
-destruct (Qfactor_twos q) as (n,d); red; simpl.
+unfold Qred, Qeq; intros (n,d); simpl.
generalize (Zggcd_gcd n ('d)) (Zgcd_is_pos n ('d))
(Zgcd_is_gcd n ('d)) (Zggcd_correct_divisors n ('d)).
destruct (Zggcd n (Zpos d)) as (g,(nn,dd)); simpl.
@@ -112,16 +64,8 @@ Qed.
Lemma Qred_complete : forall p q, p==q -> Qred p = Qred q.
Proof.
-intros.
-assert (Qfactor_twos p == Qfactor_twos q).
- apply Qeq_trans with p; auto.
- apply Qeq_trans with q; auto.
- symmetry; auto.
-clear H.
-unfold Qred.
-destruct (Qfactor_twos p) as (a,b);
-destruct (Qfactor_twos q) as (c,d); clear p q.
-unfold Qeq in *; simpl in *.
+intros (a,b) (c,d).
+unfold Qred, Qeq in *; simpl in *.
Open Scope Z_scope.
generalize (Zggcd_gcd a ('b)) (Zgcd_is_gcd a ('b))
(Zgcd_is_pos a ('b)) (Zggcd_correct_divisors a ('b)).
@@ -198,47 +142,6 @@ rewrite (Qred_correct q); auto.
rewrite (Qred_correct q'); auto.
Qed.
-(** Another version, dedicated to extraction *)
-
-Definition Qred_extr (q : Q) :=
- let (q1, q2) := Qfactor_twos q in
- let (p,_) := Zggcd_spec_pos (Zpos q2) (Zle_0_pos q2) q1 in
- let (r2,r1) := snd p in r1#(Z2P r2).
-
-Lemma Qred_extr_Qred : forall q, Qred_extr q = Qred q.
-Proof.
-unfold Qred, Qred_extr.
-intro q; destruct (Qfactor_twos q) as (n,p); clear q.
-Open Scope Z_scope.
-destruct (Zggcd_spec_pos (' p) (Zle_0_pos p) n) as ((g,(pp,nn)),H).
-generalize (H (Zle_0_pos p)); clear H; intros (Hg1,(Hg2,(Hg4,Hg3))).
-simpl.
-generalize (Zggcd_gcd n ('p)) (Zgcd_is_gcd n ('p))
- (Zgcd_is_pos n ('p)) (Zggcd_correct_divisors n ('p)).
-destruct (Zggcd n (Zpos p)) as (g',(nn',pp')); simpl.
-intro H; rewrite <- H; clear H.
-intros Hg'1 Hg'2 (Hg'3,Hg'4).
-assert (g<>0).
- intro; subst g; discriminate.
-destruct (Zis_gcd_uniqueness_apart_sign n ('p) g g'); auto.
-apply Zis_gcd_sym; auto.
-subst g'.
-f_equal.
-apply Zmult_reg_l with g; auto; congruence.
-f_equal.
-apply Zmult_reg_l with g; auto; congruence.
-elimtype False; omega.
-Open Scope Q_scope.
-Qed.
-
-Add Morphism Qred_extr : Qred_extr_comp.
-Proof.
-intros q q' H.
-do 2 rewrite Qred_extr_Qred.
-rewrite (Qred_correct q); auto.
-rewrite (Qred_correct q'); auto.
-Qed.
-
Definition Qplus' (p q : Q) := Qred (Qplus p q).
Definition Qmult' (p q : Q) := Qred (Qmult p q).