(* This program is free software; you can redistribute it and/or      *)
(* modify it under the terms of the GNU Lesser General Public License *)
(* as published by the Free Software Foundation; either version 2.1   *)
(* of the License, or (at your option) any later version.             *)
(*                                                                    *)
(* This program is distributed in the hope that it will be useful,    *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of     *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *)
(* GNU General Public License for more details.                       *)
(*                                                                    *)
(* You should have received a copy of the GNU Lesser General Public   *)
(* License along with this program; if not, write to the Free         *)
(* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *)
(* 02110-1301 USA                                                     *)
Require Export Arith.
Require Export Compare_dec.
Require Export ArithRing.
Require Export Omega.
Require Export ZArith.
Require Export ZArithRing.
Ltac CaseEq f := generalize (refl_equal f); pattern f at -1 in |- *; case f.
Inductive Qpositive : Set :=
| nR : Qpositive -> Qpositive
| dL : Qpositive -> Qpositive
| One : Qpositive.
Fixpoint Qpositive_i (w : Qpositive) : nat * nat :=
match w with
| One => (1, 1)
| nR w' => match Qpositive_i w' with
| (p, q) => (p + q, q)
end
| dL w' => match Qpositive_i w' with
| (p, q) => (p, p + q)
end
end.
Coercion Z_of_nat : nat >-> Z.
intros w; elim w; clear w.
intros w Hrec; elim Hrec; intros a Hrec2; elim Hrec2; intros b; simpl in |- *;
case (Qpositive_i w); simpl in |- *.
intros p q Heq; exists a; exists (b - a)%Z.
rewrite <- Heq; repeat rewrite Znat.inj_plus; ring.
intros w Hrec; elim Hrec; intros a Hrec2; elim Hrec2; intros b; simpl in |- *;
case (Qpositive_i w); simpl in |- *.
intros p q Heq; exists (a - b)%Z; exists b.
rewrite <- Heq; repeat rewrite Znat.inj_plus; ring.
exists 1%Z; exists 0%Z; simpl in |- *; omega.
Qed.
Fixpoint Qpositive_inv (w : Qpositive) : Qpositive :=
match w with
| One => One
| nR w' => dL (Qpositive_inv w')
| dL w' => nR (Qpositive_inv w')
end.
let T_local :=
(intros w'; simpl in |- *; case (Qpositive_i w'); intros p' q' Hrec p q Heq;
rewrite (Hrec p' q'); auto; injection Heq; intros H1 H2;
rewrite <- H1; rewrite <- H2; rewrite plus_comm;
auto) in
(intros w; elim w; clear w;
[ T_local
| T_local
| simpl in |- *; intros p q Heq; injection Heq; intros H1 H2;
rewrite <- H1; rewrite <- H2; auto with * ]).
Qed.
simple induction w; simpl in |- *;
(repeat exists 0; auto; fail) ||
(intros w' Hrec; elim Hrec; intros p' Hex; elim Hex; intros q' Heq;
rewrite Heq).
exists (p' + S q'); exists q'; auto.
exists p'; exists (p' + S q'); auto.
Qed.
Fixpoint Qpositive_c (p q n : nat) {struct n} : Qpositive :=
match n with
| O => One
| S n' =>
match p - q with
| O => match q - p with
| O => One
| v => dL (Qpositive_c p v n')
end
| v => nR (Qpositive_c v q n')
end
end.
intros n; elim n; clear n.
auto with arith.
intros n Hrec m; case m; clear m.
simpl in |- *; intros Heq; discriminate Heq.
simpl in |- *; intros; apply le_n_S; apply Hrec; auto.
Qed.
intros n; elim n; clear n.
simpl in |- *; auto.
intros n Hrec m; case m; clear m.
intros Hle; inversion Hle.
intros m' Hle; simpl in |- *; apply Hrec; auto with arith.
Qed.
intros m; elim m.
simpl in |- *; auto.
intros m' Hrec n; case n; simpl in |- *; auto.
Qed.
intros n m; elim m; clear m.
intros p; case p; simpl in |- *.
auto.
intros p'; rewrite <- mult_n_O.
intros H; discriminate H.
intros m' Hrec p; case p.
rewrite <- mult_n_O; simpl in |- *; intros H; discriminate H.
intros p'; repeat rewrite (mult_comm (S n)); simpl in |- *.
intros H; injection H.
intros H'; apply f_equal with (f := S).
apply Hrec.
repeat rewrite (mult_comm (S n)).
apply plus_reg_l with n.
exact H'.
Qed.
intros x; case x.
auto.
simpl in |- *.
exact nat_of_P_o_P_of_succ_nat_eq_succ.
Qed.
intros x; case x; auto; intros p y; case y; auto; simpl in |- *; intros;
apply nat_of_P_mult_morphism.
Qed.
intros p q n Hle; simpl in |- *.
rewrite <- (plus_n_Sm p q).
rewrite <- (minus_Sn_m (p + q) q).
rewrite (plus_comm p); rewrite minus_plus; auto with *.
auto with arith.
Qed.
intros p q n Hle; simpl in |- *.
rewrite le_minus_O.
rewrite minus_plus.
auto.
auto with arith.
Qed.
intros w; elim w; clear w.
intros w'; simpl in |- *.
elim (interp_non_zero w'); intros p' Hex; elim Hex; intros q' Heq.
rewrite Heq.
intros Hrec p q n Heq_pair.
injection Heq_pair; intros Heq2 Heq1; rewrite <- Heq2; rewrite <- Heq1.
case n.
simpl in |- *; intros Hle; inversion Hle.
clear n; intros n.
intros Hle.
replace (Qpositive_c (S (p' + S q')) (S q') (S n)) with
(nR (Qpositive_c (S p') (S q') n)).
apply f_equal with (f := nR).
apply Hrec; auto with *.
rewrite <- plus_Sn_m.
rewrite Qpositive_c_unfold1. auto with *.
auto with *.
intros w'; simpl in |- *.
elim (interp_non_zero w'); intros p' Hex; elim Hex; intros q' Heq.
rewrite Heq.
intros Hrec p q n Heq_pair.
injection Heq_pair; intros Heq2 Heq1; rewrite <- Heq2; rewrite <- Heq1.
case n.
simpl in |- *; intros Hle; inversion Hle.
clear n; intros n.
intros Hle.
replace (Qpositive_c (S p') (S (p' + S q')) (S n)) with
(dL (Qpositive_c (S p') (S q') n)).
apply f_equal with (f := dL).
apply Hrec; auto with *.
rewrite <- plus_Sn_m.
rewrite Qpositive_c_unfold2; auto with *.
simpl in |- *; intros p q n Heq; injection Heq; intros Heq2 Heq1; case n.
rewrite <- Heq1; simpl in |- *; intros Hle; inversion Hle.
rewrite <- Heq1; rewrite <- Heq2; simpl in |- *; auto with *.
Qed.
intros n; elim n.
intros p q Hle; inversion Hle.
clear n; intros n.
intros Hrec p q Hle; case (le_gt_dec (S p) (S q)).
simpl in |- *.
intros Hle'; rewrite (le_minus_O p q).
CaseEq (q - p).
intros Heq_minus; exists p.
simpl in |- *; split; auto with arith.
rewrite <- plus_n_O.
apply le_antisym; auto with arith.
apply minus_O_le.
auto.
intros q' Heq_minus; elim (Hrec p q').
intros d; simpl in |- *; case (Qpositive_i (Qpositive_c (S p) (S q') n));
repeat rewrite <- (mult_comm (S d)); intros p'' q'' (Heq1, Heq2).
exists d; split.
exact Heq1.
rewrite (le_plus_minus (S p) (S q)).
simpl in |- *.
rewrite Heq_minus; rewrite Heq2.
simpl in |- *.
replace (S (p + q'' * S d)) with (S p + q'' * S d).
rewrite Heq1.
simpl in |- *.
ring.
simpl in |- *; auto.
auto with arith.
apply le_S_n.
rewrite plus_n_Sm.
apply le_trans with (S p + S q).
apply plus_le_compat_l.
apply le_n_S.
rewrite <- Heq_minus; apply minus_le.
exact Hle.
auto with arith.
intros Hgt; simpl in |- *; CaseEq (p - q).
intros H; elim (gt_not_le _ _ Hgt).
apply le_n_S.
apply minus_O_le.
exact H.
intros p'.
intros Heq_minus; simpl in |- *; elim (Hrec p' q).
intros d; case (Qpositive_i (Qpositive_c (S p') (S q) n)).
simpl in |- *; intros p'' q'' (Heq1, Heq2).
exists d; split; auto.
rewrite (le_plus_minus (S q) (S p)); simpl in |- *.
rewrite Heq_minus.
replace (S (q + S p')) with (S q + S p').
rewrite Heq2; rewrite Heq1; ring.
simpl in |- *; auto.
auto with arith.
rewrite <- Heq_minus.
replace (p - q) with (S p - S q).
rewrite <- (plus_comm (S q)).
rewrite <- (le_plus_minus (S q) (S p)).
apply le_trans with (S p + q).
auto with arith.
apply le_S_n; rewrite plus_n_Sm.
exact Hle.
auto with arith.
auto.
Qed.

Theorem construct_correct2' :
forall n p q : nat,
1 <= p ->
1 <= q ->
p + q <= n ->
exists d : nat,
p = fst (Qpositive_i (Qpositive_c p q n)) * S d /\
q = snd (Qpositive_i (Qpositive_c p q n)) * S d.