Require Export Coqlib.
Require Export ZArith.
Require Import Tactics.
Load Param.
Lemma Plt_rev_trans :
forall a b,
  
Plt b a ->
  
forall c, 
Plt c b -> 
Plt c a.
Proof.
Lemma Ple_Plt_trans:
  
forall (
p q r: 
positive), 
Ple p q -> 
Plt q r -> 
Plt p r.
Proof.
  unfold Plt, Ple; intros; omega.
Qed.
Lemma Ple_antisym : 
forall p q, 
Ple p q -> 
Ple q p -> 
p = 
q.
Proof.
  unfold Ple.
  
intros.
  
assert (
Zpos p = 
Zpos q) 
by omega.
  
congruence.
Qed.
 
Section Bounded_gt.
Variable p : 
positive.
Inductive bounded_gt : 
positive -> 
positive -> 
Prop :=
| 
bounded_gt_intro : 
forall a b,
  
Plt b a -> 
Plt a p -> 
bounded_gt a b.
Function bound_gt (
q : 
positive) : 
nat :=
  
match (
Zpos p - 
Zpos q)%
Z with
    | 
Zpos r => 
nat_of_P r
    | 
_ => 
O
  end.
Theorem bounded_gt_wf : 
well_founded bounded_gt.
Proof.
 unfold well_founded.
 
cut (
forall n q, 
bound_gt q = 
n -> 
Acc bounded_gt q).
 
intros.
 
eauto.
 
induction n using (
well_founded_ind Wf_nat.lt_wf).
 
intros.
 
subst.
 
revert H.
 
unfold bound_gt.
 
case_eq (
Zpos p - 
Zpos q)%
Z.
  
intros.
  
assert (
Zpos p = 
Zpos q) 
by omega.
  
injection H1.
  
intros ; 
subst q.
  
constructor.
  
inversion 1.
  
subst.
  
apply False_rect.
  
destruct (
Plt_strict p).
  
eauto using Plt_trans.
 
intros.
 
constructor.
 
inversion 1.
 
subst.
 
unfold Plt in *.
 
assert (
Zpos p > 
Zpos q)%
Z.
 
cut (
Zpos p - 
Zpos q > 0)%
Z.
 
omega.
 
rewrite H.
 
compute.
 
trivial.
 
clear H4.
 
assert (
Zpos p - 
Zpos y < 
Zpos p - 
Zpos q)%
Z by omega.
 
assert (
Zpos p - 
Zpos y > 0)%
Z by omega.
 
generalize (
H5).
 
case_eq (
Zpos p - 
Zpos y)%
Z ; 
intros until 1 ; 
compute ; 
try congruence.
 
intros _.
 
generalize (
fun y0 Hq Hy => 
H0 y0 Hy y Hq).
 
rewrite H6.
 
intros.
 
eapply H7.
 
reflexivity.
apply nat_of_P_lt_Lt_compare_morphism.
 
rewrite H in H4.
 
rewrite H6 in H4.
 
unfold Zlt in H4.
 
simpl in H4.
 
assumption.
 
intros.
 
assert (
Zpos p < 
Zpos q)%
Z.
 
cut (
Zpos p - 
Zpos q < 0)%
Z.
  
omega.
 
rewrite H.
 
compute.
 
trivial.
 
assert (
Plt p q).
  
assumption.
 
constructor.
 
inversion 1.
 
subst.
 
destruct (
Plt_strict p).
 
eauto using Plt_trans.
Qed.
 
 
End Bounded_gt.
Section Bounded_exists.
 
Variable p : 
positive -> 
bool.
 
Lemma bounded_exists : 
forall n,
   {
j | 
Plt j n /\ 
p j = 
true} + {
forall j, 
Plt j n -> 
p j = 
false}.
Proof.
  intros.
  
induction n using Prec.
  
compute.
   
right.
   
destruct j ; 
simpl ; 
congruence.
  
case_eq (
p n).
   
left.
   
exists n.
   
split.
   
apply Plt_succ.
   
assumption.
  
intros.
  
destruct IHn as [ [
j [
Hlt Hp]] | 
Hlt].
   
left.
   
exists j.
   
split.
   
eauto using Plt_succ, 
Plt_trans.
   
assumption.
  
right.
  
intros j Hlt_succ.
  
destruct (
Plt_succ_inv _ _ Hlt_succ).
   
eauto.
  
congruence.
Qed.
 
End Bounded_exists. 
Definition lcm a b := 
a * (
b / 
Zgcd a b).
Lemma lcm_positive : 
forall a, 0 < 
a -> 
forall b, 0 < 
b -> 0 < 
lcm a b.
Proof.
Theorem lcm_prop : 
forall a, 0 < 
a -> 
forall b, 0 < 
b -> 
forall q,
  (
a | 
q) -> (
b | 
q) -> (
lcm a b | 
q).
Proof.
  destruct 3; 
subst.
  
destruct 1; 
subst.
  
unfold lcm.
  
generalize (
Zgcd_is_gcd a b).
  
inversion 1.
  
clear H5.
  
destruct H3.
  
destruct H4.  
  
generalize (
Zgcd_is_pos a b).
  
intros.
  
assert (0 < 
Zgcd a b).
   
cut (
Zgcd a b = 0 -> 
False).
    
intros.
    
omega.
   
intros.
   
generalize (
Zgcd_inv_0_l _ _ H6).
   
omega.
  
assert (
b > 0) 
by omega.
  
assert (
Zgcd a b >= 0) 
by omega.
  
generalize (
Zis_gcd_rel_prime _ _ _ H7 H8 H2).
  
revert H6 H4 H3.
  
clear H2 H5 H7 H8.  
  
generalize (
Zgcd a b).
  
intros.
  
subst.
  
assert (
z <> 0) 
by omega.
  
revert H2.
  
replace (
q2 * 
z / 
z) 
with q2.
  
replace (
q1 * 
z / 
z) 
with q1.
  
intros.
  
revert H1.
  
rewrite Zmult_assoc.
  
rewrite Zmult_assoc.
  
intros.
  
generalize (
Zmult_reg_r  _ _ _ H3 H1).
  
intros.
  
assert (
q2 | 
q0).
   
apply Gauss with q1.
   
exists q.
   
rewrite Zmult_comm.
   
congruence.
   
apply rel_prime_sym.
   
assumption.
  
destruct H5. 
  
subst.
  
exists q3.
  
ring.
  
rewrite Z_div_mult_full; 
trivial.
  
rewrite Z_div_mult_full; 
trivial.
Qed.
 
Lemma lcm_divides_left : 
forall a b, (
a | 
lcm a b).
Proof.
  unfold lcm.
  
intros.
  
exists (
b / 
Zgcd a b).
  
rewrite Zmult_comm.
  
trivial.
Qed.
 
Lemma lcm_divides_right : 
forall a b, 0 < 
b -> (
b | 
lcm a b).
Proof.
Lemma incr_align : 
forall a, (0 < 
a) -> 
forall p, {
q | 
p <= 
q /\ (
a | 
q)}.
Proof.
 intros.
 
assert (
J : 
a > 0) 
by omega.
 
generalize (
Z_div_mod p _ J).
 
destruct (
Zdiv_eucl p a).
 
destruct 1.
 
destruct (
Z_eq_dec z0 0).
  
exists p.
  
subst.
  
split.
   
omega.
  
exists z.
  
rewrite Zmult_comm.
  
omega.
 
exists (
p + 
a - 
z0).
 
split.
  
omega.
 
exists (
z + 1).
 
subst.
 
rewrite Zmult_plus_distr_l.
 
rewrite Zmult_comm.
 
replace (1 * 
a) 
with a by omega.
 
omega.
Qed.
 
  
  
           
           Section Bounded.
             
Variable align : 
Z.
             
Hypothesis align_pos : 0 < 
align.
             
Variable low_bound high_bound : 
Z.
             
Variable f : 
Z -> 
bool.
             
Definition bounded_offset : {
z | 
low_bound <= 
z /\ (
align | 
z) /\ (
high_bound <= 
z \/ 
f z = 
true)}.
Proof.
               cut (
forall j, 0 <= 
j -> 
forall z, (
align | 
z) -> 
high_bound - 
z = 
j -> {
z' | 
z <= 
z' /\ (
align | 
z') /\ (
high_bound <= 
z' \/ 
f z' = 
true)}).
               
intros.
                
destruct (
incr_align align_pos low_bound).
                
destruct a.
                
destruct (
Z_le_dec 0 (
high_bound - 
x)).
                 
destruct (
H _ z _ H1 (
refl_equal _)).
                 
destruct a.                 
                 
exists x0.
                 
split.
                 
omega.
                 
assumption.
                
exists x.
                
split.
                 
assumption.
                
split.
                 
assumption.
                
left.
                
omega.
              
intros until 1.
              
pattern j.
              
eapply Z_lt_rec; 
try eassumption.
              
intros.
              
clear j H.
              
subst.
              
case_eq (
f z).
               
intros.
               
exists z.
               
split.
               
omega.
               
split.
               
assumption.
               
auto.
              
intros _.
              
assert (
align | 
z + 
align) 
by eauto using Zdivide_plus_r, 
Zdivide_refl.
              
destruct (
Z_le_dec (
high_bound) (
z + 
align)).
               
exists (
z + 
align).
               
split.
               
omega.              
               
split.
               
assumption.
               
auto.
              
assert (0 <= 
high_bound - (
z + 
align) < 
high_bound - 
z) 
by omega.
              
destruct (
H0 _ H2 _ H (
refl_equal _)).
              
destruct a.
              
exists x.
              
split.
               
omega.
              
assumption.
            Qed.
 
          End Bounded.