Ltac arithNormalize_step :=
    repeat rewrite mult_succ_r in *;
      repeat rewrite mult_plus_distr_r in *;
        repeat rewrite mult_plus_distr_l in *;
          repeat rewrite mult_minus_distr_r in *;
            repeat rewrite mult_minus_distr_l in *;
              repeat rewrite plus_assoc in *;
                repeat rewrite mult_assoc in *.Ltac arithNormalize := repeat arithNormalize_step.Ltac arithSimplify :=
    match goal with
      | [|- _ + ?x = _ + ?x] => f_equal
      | [|- _ + (?x1 * ?x2) = _ + (?x2 * ?x1) ] => f_equal
      | [|- _ + (?x1 * ?x2 * ?x3) = _ + (?x1 * ?x3 * ?x2) ] => f_equal
      | [|- _ + (?x1 * ?x2 * ?x3 * ?x4 * ?x5 * ?x6) = _ + (?x1 * ?x3 * ?x2 * ?x4 * ?x5 * ?x6) ] => f_equal
      | [|- _ * ?x1 = _ * ?x1] => f_equal
      | [|- _ * ?x = _ ] => rewrite mult_comm; repeat rewrite mult_assoc; arithSimplify
      | [|- _ + ?x = _ ] => rewrite plus_comm; repeat rewrite plus_assoc; arithSimplify
      | [|- _ * ?x1 <= _ * ?x1] => apply mult_le_compat; auto
      | [|- _ * ?x1 <= _ * ?x1] => apply plus_le_compat; auto
      | [|- _ * ?x <= _ ] => rewrite mult_comm; repeat rewrite mult_assoc; arithSimplify
      | [|- _ + ?x <= _ ] => rewrite plus_comm; repeat rewrite plus_assoc; arithSimplify
      
    end.

(* Specifications: *)
Lemma ratAdd_leRat_compat_l : forall r1 r2 r3, leRat r1 r2 -> r1 + r3 <= r2 + r3.
Theorem ratAdd_leRat_compat : forall r1 r2 r3 r4, leRat r1 r2 -> leRat r3 r4 -> r1 + r3 <= r2 + r4.
Theorem ratMult_leRat_compat : forall (r1 r2 r3 r4 : Rat), leRat r1 r2 -> leRat r3 r4 -> leRat (ratMult r1 r3) (ratMult r2 r4).
Theorem ratMult_eqRat_compat : forall (r1 r2 r3 r4 : Rat), eqRat r1 r2 -> eqRat r3 r4 -> eqRat (ratMult r1 r3) (ratMult r2 r4).
Theorem leRat_num : forall n1 n2 d, le n1 n2 -> leRat (RatIntro n1 d) (RatIntro n2 d).
Theorem eqRat_terms : forall n1 d1 n2 d2, n1 = n2 -> posnatToNat d1 = posnatToNat d2 -> eqRat (RatIntro n1 d1) (RatIntro n2 d2).
Lemma leRat_mult : forall n1 n2 d1 d2 (pf1 : d1 > 0) (pf2 : d2 > 0), RatIntro n1 (exist (fun d => d > 0) _ pf1) <= RatIntro n2 (exist (fun d => d > 0) _ pf2) -> (n1 * d2 <= n2 * d1)%nat.
Lemma nat_minus_eq : forall (n1 n2 : nat), (n1 <= n2)%nat -> n2 - n1 = O -> n1 = n2.
Lemma bleRat_total : forall r1 r2, bleRat r1 r2 = false -> bleRat r2 r1 = true.
Lemma ratAdd_any_leRat_l : forall r1 r2 r3, r1 <= r3 -> r1 <= r3 + r2.
Lemma ratAdd_any_leRat_r : forall r1 r2 r3, r1 <= r2 -> r1 <= r3 + r2.
Lemma ratSubtract_leRat_r : forall r1 r2 r3, r1 <= r2 -> ratSubtract r3 r2 <= ratSubtract r3 r1.
Lemma ratSubtract_leRat_l: forall r1 r2 r3 : Rat, r1 <= r2 -> ratSubtract r1 r3 <= ratSubtract r2 r3.
Lemma ratSubtract_leRat : forall r1 r2 r3 r4, r1 <= r2 -> r3 <= r4 -> ratSubtract r1 r4 <= ratSubtract r2 r3.
Lemma ratSubtract_partition_leRat : forall r3 r1 r2 d1 d2, ratSubtract r1 r3 <= d1 -> ratSubtract r3 r2 <= d2 -> ratSubtract r1 r2 <= d1 + d2.
Theorem ratTriangleInequality : forall r1 r2 r3, (ratDistance r1 r2) <= (ratDistance r1 r3) + (ratDistance r3 r2).
Lemma minus_le : forall n1 n2 n3, (n1 <= n3 -> n1 - n2 <= n3)%nat.
Theorem ratSubtract_le : forall r1 r2 d, r1 <= d -> ratSubtract r1 r2 <= d.
Theorem ratDistance_le_trans : forall r1 r2 r3 d1 d2, ratDistance r1 r2 <= d1 -> ratDistance r2 r3 <= d2 -> ratDistance r1 r3 <= d1 + d2.
Theorem ratDistance_le : forall r1 r2 d, r1 <= d -> r2 <= d -> (ratDistance r1 r2) <= d.
Lemma minus_plus_assoc : forall n1 n2 n3, (n3 <= n2 -> (n1 + n2) - n3 = n1 + (n2 - n3))%nat.
Theorem rat_distance_of_sum : forall r1 r2 r3 r4, ratDistance (r1 + r2) (r3 + r4) <= (ratDistance r1 r3) + (ratDistance r2 r4).
Theorem ratDistance_comm : forall r1 r2, eqRat (ratDistance r1 r2) (ratDistance r2 r1).
Lemma ratDistance_le_max : forall r1 r2 r3 v, r1 <= r2 -> r2 <= r3 -> (ratDistance r2 v) <= (maxRat (ratDistance r1 v) (ratDistance r3 v)).
Lemma maxRat_leRat_same : forall r1 r2 r3, r1 <= r3 -> r2 <= r3 -> maxRat r1 r2 <= r3.
Lemma ratMult_small_le : forall r1 r2, r2 <= 1 -> r1 * r2 <= r1.
Lemma ratDistance_ratMult_le : forall r1 r2 r3 r4 d, (ratDistance r1 r3) <= d -> (ratDistance r2 r4) <= d -> r1 <= 1 -> r2 <= 1 -> r3 <= 1 -> r4 <= 1 -> (ratDistance (r1 * r2) (r3 * r4)) <= (3 / 1) * d.
Lemma ratAdd_any_le : forall r1 r2 r3, r1 + r2 <= r3 -> r1 <= r3.
Lemma posnatMult_1_r : forall p, posnatToNat (posnatMult p (pos 1)) = posnatToNat p.
Lemma rat_le_1 : forall n (d : posnat), (n <= d)%nat -> (RatIntro n d) <= 1.