(* 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.

Theorem construct_correct :
forall (w : Qpositive) (p q n : nat),
Qpositive_i w = (p, q) -> p + q <= n -> Qpositive_c p q n = w.