Definition spec_h (a b c d : Z) (q : Q) : Q :=
  Qmult (Qplus (Qmult a q) b) (Qinv (Qplus (Qmult c q) d)).Definition spec_Qhomographic_Qpositive_to_Q (a b c d : Z) 
  (p : Qpositive) : Q :=
  Qmult (Qplus (Qmult a (Qpos p)) b) (Qinv (Qplus (Qmult c (Qpos p)) d)).Definition spec_ni (a b c d : Z) (p : Qpositive) : Qpositive :=
  Q_tail
    (Qmult (Qplus (Qmult a (Qpos p)) b) (Qinv (Qplus (Qmult c (Qpos p)) d))).(* Here we should expect that a*p+b > 0 and c*p+d > 0, this follow from homographicAcc *)
Definition spec_ni2 (a b c d : Z) (p : Qpositive) : Qpositive :=
  Qpositive_mult (Q_tail (Qplus (Qmult a (Qpos p)) b))
    (Qpositive_inv (Q_tail (Qplus (Qmult c (Qpos p)) d))).

(* Specifications: *)
Lemma spec_Qhomographic_Qpositive_to_Q_nR : forall (a b c d : Z) (q : Qpositive), spec_Qhomographic_Qpositive_to_Q a b c d (nR q) = spec_Qhomographic_Qpositive_to_Q a (a + b) c (c + d) q.
Lemma spec_Qhomographic_Qpositive_to_Q_dL : forall (a b c d : Z) (q : Qpositive), spec_Qhomographic_Qpositive_to_Q a b c d (dL q) = spec_Qhomographic_Qpositive_to_Q (a + b) b (c + d) d q.
Lemma spec_Qhomographic_Qpositive_to_Q_nR_unfolded : forall (a b c d : Z) (q : Qpositive), Qmult (Qplus (Qmult a (Qpos (nR q))) b) (Qinv (Qplus (Qmult c (Qpos (nR q))) d)) = Qmult (Qplus (Qmult a (Qpos q)) (a + b)%Z) (Qinv (Qplus (Qmult c (Qpos q)) (c + d)%Z)).
Lemma spec_Qhomographic_Qpositive_to_Q_dL_unfolded : forall (a b c d : Z) (q : Qpositive), Qmult (Qplus (Qmult a (Qpos (dL q))) b) (Qinv (Qplus (Qmult c (Qpos (dL q))) d)) = Qmult (Qplus (Qmult (a + b)%Z (Qpos q)) b) (Qinv (Qplus (Qmult (c + d)%Z (Qpos q)) d)).
Lemma spec_ni2_nR : forall (a b c d : Z) (q : Qpositive), spec_ni2 a b c d (nR q) = spec_ni2 a (a + b) c (c + d) q.
Lemma spec_ni2_dL : forall (a b c d : Z) (q : Qpositive), Qplus (Qmult (a + b)%Z (Qpos q)) b <> Zero -> Qplus (Qmult (c + d)%Z (Qpos q)) d <> Zero -> spec_ni2 a b c d (dL q) = spec_ni2 (a + b) b (c + d) d q.
Lemma spec_ni2_nR_emission : forall (a b c d : Z) (q : Qpositive), Qlt Zero (Qplus (Qmult a (Qpos q)) b) -> Qlt Zero (Qplus (Qmult c (Qpos q)) d) -> Qlt Zero (Qplus (Qmult (a - c)%Z (Qpos q)) (b - d)%Z) -> nR (spec_ni2 (a - c) (b - d) c d q) = spec_ni2 a b c d q.
Lemma spec_ni2_dL_emission : forall (a b c d : Z) (q : Qpositive), Qlt Zero (Qplus (Qmult a (Qpos q)) b) -> Qlt Zero (Qplus (Qmult c (Qpos q)) d) -> Qlt Zero (Qplus (Qmult (c - a)%Z (Qpos q)) (d - b)%Z) -> dL (spec_ni2 a b (c - a) (d - b) q) = spec_ni2 a b c d q.
Lemma homographic_sign : forall (a b c d : Z) (p : Qpositive) (H_Qhomographic_sg_denom_nonzero : Qhomographic_sg_denom_nonzero c d p), h_sign a b c d p H_Qhomographic_sg_denom_nonzero = Qsgn (spec_Qhomographic_Qpositive_to_Q a b c d p).
Lemma homographicAcc_positive : forall (a b c d : Z) (p : Qpositive), homographicAcc a b c d p -> Qlt Zero (Qplus (Qmult (Z_to_Q a) (Qpos p)) (Z_to_Q b)) /\ Qlt Zero (Qplus (Qmult (Z_to_Q c) (Qpos p)) (Z_to_Q d)).
Lemma homographicAcc_positive_numerator : forall (a b c d : Z) (p : Qpositive), homographicAcc a b c d p -> Qlt Zero (Qplus (Qmult (Z_to_Q a) (Qpos p)) (Z_to_Q b)).
Lemma homographicAcc_positive_denominator : forall (a b c d : Z) (p : Qpositive), homographicAcc a b c d p -> Qlt Zero (Qplus (Qmult (Z_to_Q c) (Qpos p)) (Z_to_Q d)).
Lemma output_bit : forall (a b c d : Z) (p : Qpositive) (hyp_Acc : homographicAcc a b c d p), Qhomographic_Qpositive_to_Qpositive a b c d p hyp_Acc = spec_ni2 a b c d p.
Lemma spec_Qhomographic_Qpositive_to_Q_spec_ni2_pos : forall (a b c d : Z) (q : Qpositive), Qsgn (spec_Qhomographic_Qpositive_to_Q a b c d q) = 1%Z -> spec_Qhomographic_Qpositive_to_Q a b c d q = Qpos (spec_ni2 a b c d q).
Lemma spec_Qhomographic_Qpositive_to_Q_spec_ni2_neg : forall (a b c d : Z) (q : Qpositive), Qsgn (spec_Qhomographic_Qpositive_to_Q a b c d q) = (-1)%Z -> spec_Qhomographic_Qpositive_to_Q a b c d q = Qneg (spec_ni2 a b c d q).
Lemma spec_Qhomographic_Qpositive_to_Q_spec_ni2_neg_1 : forall (a b c d : Z) (q : Qpositive), Qsgn (spec_Qhomographic_Qpositive_to_Q a b c d q) = (-1)%Z -> spec_Qhomographic_Qpositive_to_Q a b c d q = Qneg (spec_ni2 (- a) (- b) c d q).
Lemma spec_Qhomographic_Qpositive_to_Q_spec_ni2_neg_2 : forall (a b c d : Z) (q : Qpositive), Qsgn (spec_Qhomographic_Qpositive_to_Q a b c d q) = (-1)%Z -> spec_Qhomographic_Qpositive_to_Q a b c d q = Qneg (spec_ni2 a b (- c) (- d) q).
Lemma spec_Qhomographic_Qpositive_to_Q_Zopp : forall (a b c d : Z) (q : Qpositive), spec_Qhomographic_Qpositive_to_Q (- a) (- b) (- c) (- d) q = spec_Qhomographic_Qpositive_to_Q a b c d q.
Lemma spec_Qhomographic_Qpositive_to_Q_Zopp_2 : forall (a b c d : Z) (q : Qpositive), spec_Qhomographic_Qpositive_to_Q (- a) (- b) c d q = Qopp (spec_Qhomographic_Qpositive_to_Q a b c d q).
Lemma spec_Qhomographic_Qpositive_to_Q_Zopp_3 : forall (a b c d : Z) (q : Qpositive), spec_Qhomographic_Qpositive_to_Q a b (- c) (- d) q = Qopp (spec_Qhomographic_Qpositive_to_Q a b c d q).
Lemma sg_pres_fraction : forall (a b c d : Z) (p : Qpositive) (H_Qhomographic_sg_denom_nonzero : Qhomographic_sg_denom_nonzero c d p), Qmult (Qplus (Qmult (new_a a b c d p H_Qhomographic_sg_denom_nonzero) (Qpos (new_p a b c d p H_Qhomographic_sg_denom_nonzero))) (new_b a b c d p H_Qhomographic_sg_denom_nonzero)) (Qinv (Qplus (Qmult (new_c a b c d p H_Qhomographic_sg_denom_nonzero) (Qpos (new_p a b c d p H_Qhomographic_sg_denom_nonzero))) (new_d a b c d p H_Qhomographic_sg_denom_nonzero))) = Qmult (Qplus (Qmult a (Qpos p)) b) (Qinv (Qplus (Qmult c (Qpos p)) d)).
Lemma a_field_equality_1 : forall x y z t w : Q, Qmult x t = Qmult y z -> t <> Zero -> Qplus (Qmult z w) t <> Zero -> Qmult (Qplus (Qmult x w) y) (Qinv (Qplus (Qmult z w) t)) = Qmult y (Qinv t).
Lemma Qhomographic_sg_denom_nonzero_correct_1 : forall (c d : Z) (p : Qpositive), Qhomographic_sg_denom_nonzero c d p -> Qplus (Qmult c (Qpos p)) d <> Zero.
Lemma Qhomographic_sg_denom_nonzero_correct_2 : forall (c d : Z) (p : Qpositive), Qplus (Qmult c (Qpos p)) d <> Zero -> Qhomographic_sg_denom_nonzero c d p.
Lemma homography_positive_input : forall (a b c d : Z) (p : Qpositive) (H_Qhomographic_sg_denom_nonzero : Qhomographic_sg_denom_nonzero c d p), Qhomographic_Qpositive_to_Q a b c d p H_Qhomographic_sg_denom_nonzero = Qmult (Qplus (Qmult a (Qpos p)) b) (Qinv (Qplus (Qmult c (Qpos p)) d)).
Lemma homography : forall (a b c d : Z) (s : Q) (H_Qhomographic_denom_nonzero : Qhomographic_denom_nonzero c d s), Qhomographic a b c d s H_Qhomographic_denom_nonzero = spec_h a b c d s.
Lemma Qhomographic_denom_nonzero_correct_1 : forall (c d : Z) (q : Q), Qplus (Qmult c q) d <> Zero -> Qhomographic_denom_nonzero c d q.
Lemma Qhomographic_denom_nonzero_correct_2 : forall (c d : Z) (q : Q), Qhomographic_denom_nonzero c d q -> Qplus (Qmult c q) d <> Zero.
Theorem homography_algorithm_is_correct : forall (a b c d : Z) (q : Q) (H_denom : Qplus (Qmult c q) d <> Zero), Qhomographic a b c d q (Qhomographic_denom_nonzero_correct_1 c d q H_denom) = Qmult (Qplus (Qmult a q) b) (Qinv (Qplus (Qmult c q) d)).