summaryrefslogtreecommitdiff
path: root/theories/Numbers/Rational/BigQ/Q0Make.v
diff options
context:
space:
mode:
Diffstat (limited to 'theories/Numbers/Rational/BigQ/Q0Make.v')
-rw-r--r--theories/Numbers/Rational/BigQ/Q0Make.v1412
1 files changed, 1412 insertions, 0 deletions
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.