Module Coq.ZArith.Zdiv

Euclidean Division

Defines first of function that allows Coq to normalize. Then only after proves the main required property.

Require Export ZArith.
Require Omega.
Require ZArithRing.
Require Zcomplements.

Euclidean division of a positive by a integer (that is supposed to be positive).

total function than returns an arbitrary value when divisor is not positive

Fixpoint Zdiv_eucl_POS [a:positive] : Z -> Z*Z := [b:Z]
 Cases a of
 | xH => if `(Zge_bool b 2)` then `(0,1)` else `(1,0)`
 | (xO a') =>
    let (q,r) = (Zdiv_eucl_POS a' b) in
    if `(Zgt_bool b (r+r))` then `(q+q,r+r)` else `(q+q+1,r+r-b)`
 | (xI a') =>
    let (q,r) = (Zdiv_eucl_POS a' b) in
    if `(Zgt_bool b (r+r+1))` then `(q+q,r+r+1)` else `(q+q+1,r+r+1-b)`
 end.

Euclidean division of integers.

Total function than returns (0,0) when dividing by 0.


    
Definition Zdiv_eucl [a,b:Z] : Z*Z :=
  Cases a b of
  | ZERO _ => `(0,0)`
  | _ ZERO => `(0,0)`
  | (POS a') (POS _) => (Zdiv_eucl_POS a' b)
  | (NEG a') (POS _) =>
      let (q,r) = (Zdiv_eucl_POS a' b) in
      Cases r of
      | ZERO => `(-q,0)`
      | _ => `(-(q+1),b-r)`
      end
  | (NEG a') (NEG b') =>
         let (q,r) = (Zdiv_eucl_POS a' (POS b')) in `(q,-r)`
  | (POS a') (NEG b') =>
      let (q,r) = (Zdiv_eucl_POS a' (POS b')) in
      Cases r of
      | ZERO => `(-q,0)`
      | _ => `(-(q+1),b+r)`
      end
    end.

Division and modulo are projections of Zdiv_eucl

     
Definition Zdiv [a,b:Z] : Z := let (q,_) = (Zdiv_eucl a b) in q.

Definition Zmod [a,b:Z] : Z := let (_,r) = (Zdiv_eucl a b) in r.

Main division theorem.

First a lemma for positive

Lemma Z_div_mod_POS : (b:Z)`b > 0` -> (a:positive)
  let (q,r)=(Zdiv_eucl_POS a b) in `(POS a) = b*q + r`/\`0<=r<b`.
Proof.
Induction a; Simpl.
Intro p.
Case (Zdiv_eucl_POS p b).
Intros q r H1.
Decompose [and] H1.
Generalize (Zgt_cases b `r+r+1`).
Case (Zgt_bool b `r+r+1`);
(Rewrite POS_xI; Rewrite H0; Split ; [ Ring | Omega ]).

Intros p.
Case (Zdiv_eucl_POS p b).
Intros q r H1.
Decompose [and] H1.
Generalize (Zgt_cases b `r+r`).
Case (Zgt_bool b `r+r`);
(Rewrite POS_xO; Rewrite H0; Split ; [ Ring | Omega ]).

Generalize (Zge_cases b `2`).
Case (Zge_bool b `2`); (Intros; Split; [Ring | Omega ]).
Omega.
Qed.

Theorem Z_div_mod : (a,b:Z)`b > 0` ->
  let (q,r) = (Zdiv_eucl a b) in `a = b*q + r` /\ `0<=r<b`.
Proof.
Intros a b; Case a; Case b; Try (Simpl; Intros; Omega).
Unfold Zdiv_eucl; Intros; Apply Z_div_mod_POS; Trivial.

Intros; Discriminate.

Intros.
Generalize (Z_div_mod_POS (POS p) H p0).
Unfold Zdiv_eucl.
Case (Zdiv_eucl_POS p0 (POS p)).
Intros z z0.
Case z0.

Intros [H1 H2].
Split; Trivial.
Replace (NEG p0) with `-(POS p0)`; [ Rewrite H1; Ring | Trivial ].

Intros p1 [H1 H2].
Split; Trivial.
Replace (NEG p0) with `-(POS p0)`; [ Rewrite H1; Ring | Trivial ].
Generalize (POS_gt_ZERO p1); Omega.

Intros p1 [H1 H2].
Split; Trivial.
Replace (NEG p0) with `-(POS p0)`; [ Rewrite H1; Ring | Trivial ].
Generalize (NEG_lt_ZERO p1); Omega.

Intros; Discriminate.
Qed.

Existence theorems

Theorem Zdiv_eucl_exist : (b:Z)`b > 0` -> (a:Z)
  { qr:Z*Z | let (q,r)=qr in `a=b*q+r` /\ `0 <= r < b` }.
Proof.
Intros b Hb a.
Exists (Zdiv_eucl a b).
Exact (Z_div_mod a b Hb).
Qed.

Implicits Zdiv_eucl_exist.

Theorem Zdiv_eucl_extended : (b:Z)`b <> 0` -> (a:Z)
  { qr:Z*Z | let (q,r)=qr in `a=b*q+r` /\ `0 <= r < |b|` }.
Proof.
Intros b Hb a.
Elim (Z_le_gt_dec `0` b);Intro Hb'.
Cut `b>0`;[Intro Hb''|Omega].
Rewrite Zabs_eq;[Apply Zdiv_eucl_exist;Assumption|Assumption].
Cut `-b>0`;[Intro Hb''|Omega].
Elim (Zdiv_eucl_exist Hb'' a);Intros qr.
Elim qr;Intros q r Hqr.
Exists (pair ? ? `-q` r).
Elim Hqr;Intros.
Split.
Rewrite <- Zmult_Zopp_left;Assumption.
Rewrite Zabs_non_eq;[Assumption|Omega].
Qed.

Implicits Zdiv_eucl_extended.

Auxiliary lemmas about Zdiv and Zmod

Lemma Z_div_mod_eq : (a,b:Z)`b > 0` -> `a = b * (Zdiv a b) + (Zmod a b)`.
Proof.
Unfold Zdiv Zmod.
Intros a b Hb.
Generalize (Z_div_mod a b Hb).
Case (Zdiv_eucl); Tauto.
Save.

Lemma Z_mod_lt : (a,b:Z)`b > 0` -> `0 <= (Zmod a b) < b`.
Proof.
Unfold Zmod.
Intros a b Hb.
Generalize (Z_div_mod a b Hb).
Case (Zdiv_eucl a b); Tauto.
Save.

Lemma Z_div_POS_ge0 : (b:Z)(a:positive)
  let (q,_) = (Zdiv_eucl_POS a b) in `q >= 0`.
Proof.
Induction a; Intros; Simpl.
Generalize H; Case (Zdiv_eucl_POS p b); Simpl.
Intros; Case (Zgt_bool b `z0+z0+1`); Simpl; Omega.
Generalize H; Case (Zdiv_eucl_POS p b); Simpl.
Intros; Case (Zgt_bool b `z0+z0`); Simpl; Omega.
Case (Zge_bool b `2`); Simpl; Omega.
Save.

Lemma Z_div_ge0 : (a,b:Z)`b > 0` -> `a >= 0` -> `(Zdiv a b) >= 0`.
Proof.
Intros a b Hb; Unfold Zdiv Zdiv_eucl; Case a; Simpl; Intros.
Case b; Simpl; Trivial.
Generalize Hb; Case b; Try Trivial.
Auto with zarith.
Intros p0 Hp0; Generalize (Z_div_POS_ge0 (POS p0) p).
Case (Zdiv_eucl_POS p (POS p0)); Simpl; Tauto.
Intros; Discriminate.
Elim H; Trivial.
Save.

Lemma Z_div_lt : (a,b:Z)`b >= 2` -> `a > 0` -> `(Zdiv a b) < a`.
Proof.
Intros. Cut `b > 0`; [Intro Hb | Omega].
Generalize (Z_div_mod a b Hb).
Cut `a >= 0`; [Intro Ha | Omega].
Generalize (Z_div_ge0 a b Hb Ha).
Unfold Zdiv; Case (Zdiv_eucl a b); Intros q r H1 [H2 H3].
Cut `a >= 2*q` -> `q < a`; [ Intro h; Apply h; Clear h | Intros; Omega ].
Apply Zge_trans with `b*q`.
Omega.
Auto with zarith.
Save.

Syntax

Grammar znatural expr2 : constr :=
  expr_div [ expr2($p) "/" expr2($c) ] -> [ (Zdiv $p $c) ]
| expr_mod [ expr2($p) "%" expr2($c) ] -> [ (Zmod $p $c) ]
.

Syntax constr
  level 6:
    Zdiv [ (Zdiv $n1 $n2) ]
      -> [ [<hov 0> "`"(ZEXPR $n1):E "/" [0 0] (ZEXPR $n2):L "`"] ]
  | Zmod [ (Zmod $n1 $n2) ]
      -> [ [<hov 0> "`"(ZEXPR $n1):E "%" [0 0] (ZEXPR $n2):L "`"] ]
  | Zdiv_inside
      [ << (ZEXPR <<(Zdiv $n1 $n2)>>) >> ]
         -> [ (ZEXPR $n1):E "/" [0 0] (ZEXPR $n2):L ]
  | Zmod_inside
      [ << (ZEXPR <<(Zmod $n1 $n2)>>) >> ]
         -> [ (ZEXPR $n1):E "%" [0 0] (ZEXPR $n2):L ]
.

Other lemmas (now using the syntax for Zdiv and Zmod).

Lemma Z_div_ge : (a,b,c:Z)`c > 0`->`a >= b`->`a/c >= b/c`.
Proof.
Intros a b c cPos aGeb.
Generalize (Z_div_mod_eq a c cPos).
Generalize (Z_mod_lt a c cPos).
Generalize (Z_div_mod_eq b c cPos).
Generalize (Z_mod_lt b c cPos).
Intros.
Elim (Z_ge_lt_dec `a/c` `b/c`); Trivial.
Intro.
Absurd `b-a >= 1`.
Omega.
Rewrite -> H0.
Rewrite -> H2.
Assert `c*(b/c)+b%c-(c*(a/c)+a%c) = c*(b/c - a/c) + b%c - a%c`.
Ring.
Rewrite H3.
Assert `c*(b/c-a/c) >= c*1`.
Apply Zge_Zmult_pos_left.
Omega.
Omega.
Assert `c*1=c`.
Ring.
Omega.
Save.

Lemma Z_mod_plus : (a,b,c:Z)`c > 0`->`(a+b*c)%c = a%c`.
Proof.
Intros a b c cPos.
Generalize (Z_div_mod_eq a c cPos).
Generalize (Z_mod_lt a c cPos).
Generalize (Z_div_mod_eq `a+b*c` c cPos).
Generalize (Z_mod_lt `a+b*c` c cPos).
Intros.

Assert `(a+b*c)%c - a%c = c*(b+a/c - (a+b*c)/c)`.
Replace `(a+b*c)%c` with `a+b*c - c*((a+b*c)/c)`.
Replace `a%c` with `a - c*(a/c)`.
Ring.
Omega.
Omega.
LetTac q := `b+a/c-(a+b*c)/c`.
Apply (Zcase_sign q); Intros.
Assert `c*q=0`.
Rewrite H4; Ring.
Rewrite H5 in H3.
Omega.

Assert `c*q >= c`.
Pattern 2 c; Replace c with `c*1`.
Apply Zge_Zmult_pos_left; Omega.
Ring.
Omega.

Assert `c*q <= -c`.
Replace `-c` with `c*(-1)`.
Apply Zle_Zmult_pos_left; Omega.
Ring.
Omega.
Save.

Lemma Z_div_plus : (a,b,c:Z)`c > 0`->`(a+b*c)/c = a/c+b`.
Proof.
Intros a b c cPos.
Generalize (Z_div_mod_eq a c cPos).
Generalize (Z_mod_lt a c cPos).
Generalize (Z_div_mod_eq `a+b*c` c cPos).
Generalize (Z_mod_lt `a+b*c` c cPos).
Intros.
Apply Zmult_reg_left with 1:=cPos.
Replace `c*((a+b*c)/c)` with `a+b*c-(a+b*c)%c`.
Rewrite (Z_mod_plus a b c cPos).
Pattern 1 a; Rewrite H2.
Ring.
Pattern 1 `a+b*c`; Rewrite H0.
Ring.
Save.

Lemma Z_mult_div_ge : (a,b:Z)`b>0`->`b*(a/b) <= a`.
Proof.
Intros a b bPos.
Generalize (Z_div_mod_eq `a` ? bPos); Intros.
Generalize (Z_mod_lt `a` ? bPos); Intros.
Pattern 2 a; Rewrite H.
Omega.
Save.

Lemma Z_mod_same : (a:Z)`a>0`->`a%a=0`.
Proof.
Intros a aPos.
Generalize (Z_mod_plus `0` `1` a aPos).
Replace `0+1*a` with `a`.
Intros.
Rewrite H.
Compute.
Trivial.
Ring.
Save.

Lemma Z_div_same : (a:Z)`a>0`->`a/a=1`.
Proof.
Intros a aPos.
Generalize (Z_div_plus `0` `1` a aPos).
Replace `0+1*a` with `a`.
Intros.
Rewrite H.
Compute.
Trivial.
Ring.
Save.


Index
This page has been generated by coqdoc