Library Coqtail.Arith.Modulo


Require NArith.
Require Omega.
Require Max.

Inductive mod (n:nat) : natnatProp :=
     | mod_base : k, k < nmod n k k
     | mod_nS : k l, mod n k lmod n k (n + l).

Lemma pred_itere : n, 0 < n m, {k:nat | m < n} + {k | m = n + k}.
Proof.
intros n n_pos m ; induction m.
 left ; 0 ; assumption.
 case (Compare_dec.le_lt_dec (S m) n) ; intro Hyp.
 case (Compare_dec.le_lt_eq_dec _ _ Hyp) ; clear Hyp ; intro Hyp.
 left ; 0 ; assumption.
 right ; 0 ; rewrite Hyp ; trivial.
 case IHm ; intro H.
 left ; 0 ; apply False_ind ; destruct H as (_,Hf) ; omega.
 destruct H as (k,Hk) ; right ; (S k).
 rewrite <- plus_n_Sm ; rewrite Hk ; simpl ; reflexivity.
Qed.

Lemma mod_bounded : n m l, mod n l ml < n.
Proof.
intros n m l modnl ; induction modnl ; assumption.
Qed.

Lemma mod_uniqueness1 : n m l, l < nmod n l m p, p < n
      p l¬mod n p m.
Proof.
intros n m l l_ub modnl p p_ub p_neq Hf ;
 induction modnl.
 inversion Hf ; intuition.
 apply IHmodnl.
 assumption.
 assumption.
 inversion Hf.
 assert (Temp := mod_bounded _ _ _ Hf).
 apply False_ind ; clear -H1 Temp ; intuition.
 assert (Temp := Plus.plus_reg_l _ _ _ H) ; rewrite <- Temp ; assumption.
Qed.

Lemma mod_uniqueness2 : n m l l', l < nl' < nmod n m l'mod n m ll = l'.
Proof.
intros n m l l' l_ub l'_ub modnl modnl' ; inversion modnl'.
 inversion modnl ; intuition.
 rewrite <- H1 in l_ub ; apply False_ind ; clear -l_ub ; intuition.
Qed.

Lemma mod_uniqueness : n m l l', mod n l mmod n l' ml = l'.
Proof.
intros n m l l' modnl modnl'.
 induction modnl.
 induction modnl'.
 reflexivity.
 apply False_ind ; intuition.
 apply IHmodnl ; inversion modnl'.
 apply False_ind ; intuition.
 assert (Temp := Plus.plus_reg_l _ _ _ H) ;
 rewrite <- Temp ; assumption.
Qed.

Lemma disjoints_prelim : n, 0 < n M m, m < max n M
      {k | k < n mod n k m l, l k¬ mod n l m}.
Proof.
intros n n_pos M ; induction M ; intros m m_ub.
 rewrite max_l in m_ub ; [| intuition].
  m ; repeat split ; [assumption | |].
 constructor ; assumption.
 intros l l_neq Hyp ; apply l_neq ; apply mod_uniqueness with (n:=n) (m:=m).
 intuition.
 constructor ; assumption.
 case (Compare_dec.le_lt_dec m (max n M)) ; intro m_ub'.
 case (Compare_dec.le_lt_eq_dec _ _ m_ub') ; clear m_ub' ; intro m_ub'.
 apply IHM ; intuition.
 case (pred_itere _ n_pos m) ; intro Hyp.
   0 ; apply False_ind ; destruct Hyp as (_,Hf).
  assert (Hf' : n m).
  apply Le.le_trans with (max n M) ; [apply Max.le_max_l | rewrite m_ub' ; intuition].
  intuition.
  destruct Hyp as (k,Hk).
  case (Compare_dec.le_lt_dec k n) ; intro Temp.
  case (Compare_dec.le_lt_eq_dec _ _ Temp) ; clear Temp ; intro Temp.
   k ; repeat split ; [assumption | |].
  rewrite Hk ; constructor ; constructor ; assumption.
  intros l l_neq modnl ; assert (l_ub := mod_bounded _ _ _ modnl) ;
  apply (mod_uniqueness1 _ _ _ l_ub modnl _ Temp).
  intro Hf ; apply l_neq ; symmetry ; assumption.
  rewrite Hk ; constructor ; constructor ; assumption.
   0 ; repeat split.
  assumption.
  rewrite Hk ; constructor.
  replace n with (n+0) in Temp by intuition ; rewrite Temp ; repeat constructor ; assumption.
  intros l l_neq modnl ; rewrite Hk in modnl.
  apply l_neq ; apply mod_uniqueness2 with (n:=n) (m:=l).
  apply (mod_bounded _ _ _ modnl).
  assumption.
  inversion modnl.
  apply False_ind ; intuition.
  assert (Temp2 := Plus.plus_reg_l _ _ _ H) ;
  replace n with (n+0) in Temp by intuition ; rewrite Temp2, Temp in H1.
  clear -H1 ; inversion H1.
  apply False_ind ; intuition.
  repeat (rewrite itere_S in H) ; assert (Temp2 := Plus.plus_reg_l _ _ _ H) ; rewrite <- Temp2 ;
  assumption.
  constructor.
  apply (mod_bounded _ _ _ modnl).
  assert (k_ub : k < max n M).
  rewrite Hk in m_ub' ; intuition.
  destruct (IHM k k_ub) as (p, [p_ub [modnp notmodnl]]) ; p ; repeat split.
  assumption.
  assert (H := mod_nS _ _ _ modnp).
  rewrite Hk ; assumption.
  intros l l_neq_p modnl.
  rewrite Hk in modnl ; inversion modnl.
  clear -H ; intuition.
  repeat (rewrite itere_S in H) ; assert (Temp2 := Plus.plus_reg_l _ _ _ H) ;
  replace n with (n+0) in Temp by intuition.
  rewrite Temp2 in H1.
  apply (notmodnl _ l_neq_p H1).
   0 ; apply False_ind.
  assert (max n M = M).
  clear -m_ub m_ub' ; induction n.
  intuition.
  case (Max.max_dec (S n) M) ; intro H.
  rewrite H in m_ub'.
  case (Max.max_dec (S n) (S M)) ; intro H'.
  rewrite H' in m_ub ; apply False_ind ; intuition.
  assert (M < m).
  apply Lt.le_lt_trans with (max (S n) M).
  apply Max.le_max_r.
  rewrite H ; assumption.
  rewrite H' in m_ub.
  apply False_ind ; intuition.
  assumption.
  assert (m < max (S n) (S M)).
  apply Lt.lt_le_trans with (max n (S M)).
  assumption.
  generalize M ; clear ; induction n.
  intuition.
  intro M ; replace (max (S (S n)) (S M)) with (S (max (S n) M)) by intuition.
  replace (max (S n) (S M)) with (S (max n M)) by intuition.
  apply Le.le_n_S.
  destruct M.
  repeat (rewrite Max.max_comm ; simpl); intuition.
  apply IHn.
  simpl in H0.
  intuition.
Qed.

Lemma disjoints : n, 0 < n m,
      {k | k < n mod n k m l, l k¬ mod n l m}.
Proof.
intros n n_pos m ; apply disjoints_prelim with (M:= (S m)) ; intuition.
Qed.

Lemma surjectif : n m p, m < nmod n m (n × p + m).
Proof.
intros n m p m_ub ; induction p.
 replace (n × 0) with 0 by omega ; constructor ; assumption.
 replace ((n × S p) + m) with (n + ((n × p) + m)).
 constructor ; assumption.
 rewrite Mult.mult_succ_r ; omega.
Qed.

Lemma n_decomp : N n m p, 0 < np < (S N) × nmod n m p{k | p = k × n + m}.
Proof.
intro N ; induction N ; intros n m p n_pos p_ub p_modn.
  0 ; inversion p_modn.
 intuition.
 rewrite <- H1 in p_ub ; apply False_ind ; intuition.
 case (Compare_dec.le_lt_dec p ((S N) × n)) ; intro p_ub2.
 case (Compare_dec.le_lt_eq_dec _ _ p_ub2) ; intro H.
 apply (IHN _ _ _ n_pos H p_modn).
  rewrite H in p_modn.
  replace (S N × n) with (N × n + n) in p_modn.
  destruct (IHN n m (N × n) n_pos) as (k, Hk).
  apply Mult.mult_lt_compat_r ; [constructor | apply n_pos].
  inversion p_modn.
  apply False_ind.
  assert (N × n < 0).
  apply Plus.plus_lt_reg_l with n.
  intuition.
  apply (Lt.lt_n_O _ H3).
  replace l with (N × n) in H2.
  assumption.
  intuition.
   (S k) ; simpl ; rewrite <- Plus.plus_assoc ; rewrite <- Hk ; intuition.
  apply Plus.plus_comm.
  assert (Hrew : p = n + (p - n)).
  apply Minus.le_plus_minus.
  apply Le.le_trans with (S N × n) ; intuition.
  apply Le.le_trans with (S 0 × n) ; intuition ; apply Mult.mult_le_compat_r ;
  intuition.
  destruct (IHN n m (p-n) n_pos) as (k, Hk).
  apply Plus.plus_lt_reg_l with n.
  rewrite <- Hrew ; intuition.
  rewrite Plus.plus_comm in Hrew ; rewrite Hrew in p_modn ; inversion p_modn.
  apply False_ind ; apply Lt.lt_irrefl with n.
  apply Lt.lt_trans with (S N × n).
  intuition.
  apply Lt.lt_trans with p.
  assumption.
  rewrite Hrew ; assumption.
  assert (Hrew' : l = p - n) by intuition.
  rewrite Hrew' in H1 ; assumption.
   (S k) ; simpl ; rewrite <- Plus.plus_assoc ; rewrite <- Hk ; intuition.
Qed.