Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(* -*- coding: utf-8 -*- *)
(************************************************************************)
(* * The Coq Proof Assistant / The Coq Development Team *)
(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
(* <O___,, * (see CREDITS file for the list of authors) *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
Initial Contribution by Claude Marché and Xavier Urbain
Require Export ZArith_base. Require Import Zbool Omega ZArithRing Zcomplements Setoid Morphisms. Local Open Scope Z_scope.
The definition of the division is now in BinIntDef, the initial
specifications and properties are in BinInt.
Notation Zdiv_eucl_POS := Z.pos_div_eucl (only parsing). Notation Zmod := Z.modulo (only parsing). Notation Z_div_mod_eq_full := Z.div_mod (only parsing). Notation Zmod_POS_bound := Z.pos_div_eucl_bound (only parsing). Notation Zmod_pos_bound := Z.mod_pos_bound (only parsing). Notation Zmod_neg_bound := Z.mod_neg_bound (only parsing).
NB: many things are stated twice for compatibility reasons
forall b : Z, b > 0 -> forall a : positive, let (q, r) := Z.pos_div_eucl a b in Z.pos a = b * q + r /\ 0 <= r < bforall b : Z, b > 0 -> forall a : positive, let (q, r) := Z.pos_div_eucl a b in Z.pos a = b * q + r /\ 0 <= r < bb:ZHb:b > 0a:positivelet (q, r) := Z.pos_div_eucl a b in Z.pos a = b * q + r /\ 0 <= r < bb:ZHb:0 < ba:positivelet (q, r) := Z.pos_div_eucl a b in Z.pos a = b * q + r /\ 0 <= r < bb:ZHb:0 < ba:positive(let (q, r) := Z.pos_div_eucl a b in Z.pos a = q * b + r) -> 0 <= snd (Z.pos_div_eucl a b) < b -> let (q, r) := Z.pos_div_eucl a b in Z.pos a = b * q + r /\ 0 <= r < bb:ZHb:0 < ba:positivez, z0:ZZ.pos a = z * b + z0 -> 0 <= snd (z, z0) < b -> Z.pos a = b * z + z0 /\ 0 <= z0 < bauto. Qed.b:ZHb:0 < ba:positivez, z0:ZZ.pos a = b * z + z0 -> 0 <= snd (z, z0) < b -> Z.pos a = b * z + z0 /\ 0 <= z0 < ba, b:Zb > 0 -> let (q, r) := Z.div_eucl a b in a = b * q + r /\ 0 <= r < ba, b:Zb > 0 -> let (q, r) := Z.div_eucl a b in a = b * q + r /\ 0 <= r < ba, b:Z0 < b -> let (q, r) := Z.div_eucl a b in a = b * q + r /\ 0 <= r < ba, b:ZHb:0 < blet (q, r) := Z.div_eucl a b in a = b * q + r /\ 0 <= r < ba, b:ZHb:0 < bHb':b <> 0let (q, r) := Z.div_eucl a b in a = b * q + r /\ 0 <= r < ba, b:ZHb:0 < bHb':b <> 0(let (q, r) := Z.div_eucl a b in a = b * q + r) -> 0 <= a mod b < b -> let (q, r) := Z.div_eucl a b in a = b * q + r /\ 0 <= r < ba, b:ZHb:0 < bHb':b <> 0(let (q, r) := Z.div_eucl a b in a = b * q + r) -> 0 <= (let (_, r) := Z.div_eucl a b in r) < b -> let (q, r) := Z.div_eucl a b in a = b * q + r /\ 0 <= r < bauto. Qed.a, b:ZHb:0 < bHb':b <> 0z, z0:Za = b * z + z0 -> 0 <= z0 < b -> a = b * z + z0 /\ 0 <= z0 < b
For stating the fully general result, let's give a short name
to the condition on the remainder.
Definition Remainder r b := 0 <= r < b \/ b < r <= 0.
Another equivalent formulation:
Definition Remainder_alt r b := Z.abs r < Z.abs b /\ Z.sgn r <> - Z.sgn b. (* In the last formulation, [ Z.sgn r <> - Z.sgn b ] is less nice than saying [ Z.sgn r = Z.sgn b ], but at least it works even when [r] is null. *)forall r b : Z, Remainder r b <-> Remainder_alt r bintros; unfold Remainder, Remainder_alt; omega with *. Qed. Hint Unfold Remainder : core.forall r b : Z, Remainder r b <-> Remainder_alt r b
Now comes the fully general result about Euclidean division.
a, b:Zb <> 0 -> let (q, r) := Z.div_eucl a b in a = b * q + r /\ Remainder r ba, b:Zb <> 0 -> let (q, r) := Z.div_eucl a b in a = b * q + r /\ Remainder r ba, b:ZHb:b <> 0let (q, r) := Z.div_eucl a b in a = b * q + r /\ Remainder r ba, b:ZHb:b <> 0(let (q, r) := Z.div_eucl a b in a = b * q + r) -> (0 < b -> 0 <= a mod b < b) -> (b < 0 -> b < a mod b <= 0) -> let (q, r) := Z.div_eucl a b in a = b * q + r /\ Remainder r ba, b:ZHb:b <> 0(let (q, r) := Z.div_eucl a b in a = b * q + r) -> (0 < b -> 0 <= (let (_, r) := Z.div_eucl a b in r) < b) -> (b < 0 -> b < (let (_, r) := Z.div_eucl a b in r) <= 0) -> let (q, r) := Z.div_eucl a b in a = b * q + r /\ Remainder r ba, b:ZHb:b <> 0q, r:Za = b * q + r -> (0 < b -> 0 <= r < b) -> (b < 0 -> b < r <= 0) -> a = b * q + r /\ Remainder r ba, b:ZHb:b <> 0q, r:ZEQ:a = b * q + rPOS:0 < b -> 0 <= r < bNEG:b < 0 -> b < r <= 0a = b * q + r /\ Remainder r ba, b:ZHb:b <> 0q, r:ZEQ:a = b * q + rPOS:0 < b -> 0 <= r < bNEG:b < 0 -> b < r <= 0Remainder r ba:ZHb:0 <> 0q, r:ZEQ:a = 0 * q + rPOS:0 < 0 -> 0 <= r < 0NEG:0 < 0 -> 0 < r <= 00 <= r < 0 \/ 0 < r <= 0a:Zp:positiveHb:Z.pos p <> 0q, r:ZEQ:a = Z.pos p * q + rPOS:0 < Z.pos p -> 0 <= r < Z.pos pNEG:Z.pos p < 0 -> Z.pos p < r <= 00 <= r < Z.pos p \/ Z.pos p < r <= 0a:Zp:positiveHb:Z.neg p <> 0q, r:ZEQ:a = Z.neg p * q + rPOS:0 < Z.neg p -> 0 <= r < Z.neg pNEG:Z.neg p < 0 -> Z.neg p < r <= 00 <= r < Z.neg p \/ Z.neg p < r <= 0a:Zp:positiveHb:Z.pos p <> 0q, r:ZEQ:a = Z.pos p * q + rPOS:0 < Z.pos p -> 0 <= r < Z.pos pNEG:Z.pos p < 0 -> Z.pos p < r <= 00 <= r < Z.pos p \/ Z.pos p < r <= 0a:Zp:positiveHb:Z.neg p <> 0q, r:ZEQ:a = Z.neg p * q + rPOS:0 < Z.neg p -> 0 <= r < Z.neg pNEG:Z.neg p < 0 -> Z.neg p < r <= 00 <= r < Z.neg p \/ Z.neg p < r <= 0right; now apply NEG. Qed.a:Zp:positiveHb:Z.neg p <> 0q, r:ZEQ:a = Z.neg p * q + rPOS:0 < Z.neg p -> 0 <= r < Z.neg pNEG:Z.neg p < 0 -> Z.neg p < r <= 00 <= r < Z.neg p \/ Z.neg p < r <= 0
The same results as before, stated separately in terms of Z.div and Z.modulo
a, b:Zb <> 0 -> Remainder (a mod b) ba, b:Zb <> 0 -> Remainder (a mod b) bdestruct Z.div_eucl; tauto. Qed.a, b:ZHb:b <> 0(let (q, r) := Z.div_eucl a b in a = b * q + r /\ Remainder r b) -> Remainder (let (_, r) := Z.div_eucl a b in r) bProof (fun Hb => Z.mod_pos_bound a b (Z.gt_lt _ _ Hb)).a, b:Zb > 0 -> 0 <= a mod b < bProof (Z.mod_neg_bound a b).a, b:Zb < 0 -> b < a mod b <= 0a, b:Zb > 0 -> a = b * (a / b) + a mod bintros Hb; apply Z.div_mod; auto with zarith. Qed.a, b:Zb > 0 -> a = b * (a / b) + a mod ba, b:Zb <> 0 -> a mod b = a - a / b * ba, b:Zb <> 0 -> a mod b = a - a / b * ba, b:ZH:b <> 0a mod b = a - a / b * bnow apply Z.mod_eq. Qed.a, b:ZH:b <> 0a mod b = a - b * (a / b)a, b:Zb > 0 -> a mod b = a - a / b * ba, b:Zb > 0 -> a mod b = a - a / b * ba, b:ZH:b > 0a mod b = a - a / b * bnow destruct b. Qed.a, b:ZH:b > 0b <> 0
Existence theorem
forall b : Z, b > 0 -> forall a : Z, {qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < b}forall b : Z, b > 0 -> forall a : Z, {qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < b}b:ZHb:b > 0a:Z{qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < b}exact (Z_div_mod a b Hb). Qed. Arguments Zdiv_eucl_exist : default implicits.b:ZHb:b > 0a:Zlet (q, r) := Z.div_eucl a b in a = b * q + r /\ 0 <= r < b
Uniqueness theorems
b, q1, q2, r1, r2:Z0 <= r1 < Z.abs b -> 0 <= r2 < Z.abs b -> b * q1 + r1 = b * q2 + r2 -> q1 = q2 /\ r1 = r2b, q1, q2, r1, r2:Z0 <= r1 < Z.abs b -> 0 <= r2 < Z.abs b -> b * q1 + r1 = b * q2 + r2 -> q1 = q2 /\ r1 = r2b, q1, q2, r1, r2:ZHr1:0 <= r1 < Z.abs bHr2:0 <= r2 < Z.abs bH:b * q1 + r1 = b * q2 + r2q1 = q2 /\ r1 = r2b, q1, q2, r1, r2:ZHr1:0 <= r1 < Z.abs bHr2:0 <= r2 < Z.abs bH:Z.abs b * (Z.sgn b * q1) + r1 = Z.abs b * (Z.sgn b * q2) + r2q1 = q2 /\ r1 = r2b, q1, q2, r1, r2:ZHr1:0 <= r1 < Z.abs bHr2:0 <= r2 < Z.abs bH:Z.abs b * (Z.sgn b * q1) + r1 = Z.abs b * (Z.sgn b * q2) + r2H0:Z.sgn b * q1 = Z.sgn b * q2H1:r1 = r2q1 = q2 /\ r1 = r2b, q1, q2, r1, r2:ZHr1:0 <= r1 < Z.abs bHr2:0 <= r2 < Z.abs bH:Z.abs b * (Z.sgn b * q1) + r1 = Z.abs b * (Z.sgn b * q2) + r2H0:Z.sgn b * q1 = Z.sgn b * q2H1:r1 = r2q1 = q2b, q1, q2, r1, r2:ZHr1:0 <= r1 < Z.abs bHr2:0 <= r2 < Z.abs bH:Z.abs b * (Z.sgn b * q1) + r1 = Z.abs b * (Z.sgn b * q2) + r2H0:Z.sgn b * q1 = Z.sgn b * q2H1:r1 = r2Z.sgn b <> 0destruct Hr1; Z.order. Qed.b, q1, q2, r1, r2:ZHr1:0 <= r1 < Z.abs bHr2:0 <= r2 < Z.abs bH:Z.abs b * (Z.sgn b * q1) + r1 = Z.abs b * (Z.sgn b * q2) + r2H0:Z.sgn b * q1 = Z.sgn b * q2H1:r1 = r2Z.abs b <> 0Proof Z.div_mod_unique.forall b q1 q2 r1 r2 : Z, Remainder r1 b -> Remainder r2 b -> b * q1 + r1 = b * q2 + r2 -> q1 = q2 /\ r1 = r2Proof Z.div_unique.forall a b q r : Z, Remainder r b -> a = b * q + r -> q = a / bforall a b q r : Z, 0 <= r < b -> a = b * q + r -> q = a / bintros; eapply Zdiv_unique_full; eauto. Qed.forall a b q r : Z, 0 <= r < b -> a = b * q + r -> q = a / bProof Z.mod_unique.forall a b q r : Z, Remainder r b -> a = b * q + r -> r = a mod bforall a b q r : Z, 0 <= r < b -> a = b * q + r -> r = a mod bintros; eapply Zmod_unique_full; eauto. Qed.forall a b q r : Z, 0 <= r < b -> a = b * q + r -> r = a mod b
forall a : Z, 0 mod a = 0destruct a; simpl; auto. Qed.forall a : Z, 0 mod a = 0forall a : Z, a mod 0 = 0destruct a; simpl; auto. Qed.forall a : Z, a mod 0 = 0forall a : Z, 0 / a = 0destruct a; simpl; auto. Qed.forall a : Z, 0 / a = 0forall a : Z, a / 0 = 0destruct a; simpl; auto. Qed. Ltac zero_or_not a := destruct (Z.eq_dec a 0); [subst; rewrite ?Zmod_0_l, ?Zdiv_0_l, ?Zmod_0_r, ?Zdiv_0_r; auto with zarith|].forall a : Z, a / 0 = 0forall a : Z, a mod 1 = 0forall a : Z, a mod 1 = 0a:Za mod 1 = 0apply Z.mod_1_r. Qed.a:Zn:a <> 0a mod 1 = 0forall a : Z, a / 1 = aforall a : Z, a / 1 = aa:Za / 1 = aapply Z.div_1_r. Qed. Hint Resolve Zmod_0_l Zmod_0_r Zdiv_0_l Zdiv_0_r Zdiv_1_r Zmod_1_r : zarith.a:Zn:a <> 0a / 1 = aProof Z.div_1_l.forall a : Z, 1 < a -> 1 / a = 0Proof Z.mod_1_l.forall a : Z, 1 < a -> 1 mod a = 1Proof Z.div_same.forall a : Z, a <> 0 -> a / a = 1forall a : Z, a mod a = 0forall a : Z, a mod a = 0a:Za mod a = 0apply Z.mod_same; auto. Qed.a:Zn:a <> 0a mod a = 0forall a b : Z, (a * b) mod b = 0forall a b : Z, (a * b) mod b = 0a, b:Z(a * b) mod b = 0a, b:Zn:b <> 0(a * b) mod b = 0auto. Qed.a, b:Zn:b <> 0b <> 0Proof Z.div_mul.forall a b : Z, b <> 0 -> a * b / b = a
(* Division of positive numbers is positive. *)forall a b : Z, b > 0 -> 0 <= a -> 0 <= a / bforall a b : Z, b > 0 -> 0 <= a -> 0 <= a / bapply Z.div_pos; auto with zarith. Qed.a, b:ZH:b > 0H0:0 <= a0 <= a / bforall a b : Z, b > 0 -> a >= 0 -> a / b >= 0intros; generalize (Z_div_pos a b H); auto with zarith. Qed.forall a b : Z, b > 0 -> a >= 0 -> a / b >= 0
As soon as the divisor is greater or equal than 2,
the division is strictly decreasing.
forall a b : Z, b >= 2 -> a > 0 -> a / b < aforall a b : Z, b >= 2 -> a > 0 -> a / b < aapply Z.div_lt; auto with zarith. Qed.a, b:ZH:b >= 2H0:a > 0a / b < a
A division of a small number by a bigger one yields zero.
Proof Z.div_small.forall a b : Z, 0 <= a < b -> a / b = 0
Same situation, in term of modulo:
Proof Z.mod_small.forall a n : Z, 0 <= a < n -> a mod n = a
Z.ge is compatible with a positive division.
forall a b c : Z, c > 0 -> a >= b -> a / c >= b / cforall a b c : Z, c > 0 -> a >= b -> a / c >= b / ca, b, c:ZH:c > 0H0:a >= ba / c >= b / capply Z.div_le_mono; auto with zarith. Qed.a, b, c:ZH:c > 0H0:a >= bb / c <= a / c
Same, with Z.le.
forall a b c : Z, c > 0 -> a <= b -> a / c <= b / cforall a b c : Z, c > 0 -> a <= b -> a / c <= b / capply Z.div_le_mono; auto with zarith. Qed.a, b, c:ZH:c > 0H0:a <= ba / c <= b / c
With our choice of division, rounding of (a/b) is always done toward bottom:
forall a b : Z, b > 0 -> b * (a / b) <= aforall a b : Z, b > 0 -> b * (a / b) <= aapply Z.mul_div_le; auto with zarith. Qed.a, b:ZH:b > 0b * (a / b) <= aforall a b : Z, b < 0 -> b * (a / b) >= aforall a b : Z, b < 0 -> b * (a / b) >= aa, b:ZH:b < 0b * (a / b) >= aapply Z.mul_div_ge; auto with zarith. Qed.a, b:ZH:b < 0a <= b * (a / b)
The previous inequalities are exact iff the modulo is zero.
forall a b : Z, a = b * (a / b) -> a mod b = 0forall a b : Z, a = b * (a / b) -> a mod b = 0a, b:Za = b * (a / b) -> a mod b = 0rewrite Z.div_exact; auto. Qed.a, b:Zn:b <> 0a = b * (a / b) -> a mod b = 0forall a b : Z, b <> 0 -> a mod b = 0 -> a = b * (a / b)intros; rewrite Z.div_exact; auto. Qed.forall a b : Z, b <> 0 -> a mod b = 0 -> a = b * (a / b)
A modulo cannot grow beyond its starting point.
forall a b : Z, 0 < b -> 0 <= a -> a mod b <= aforall a b : Z, 0 < b -> 0 <= a -> a mod b <= aapply Z.mod_le; auto. Qed.a, b:ZH:0 < bH0:0 <= aa mod b <= a
Some additional inequalities about Z.div.
forall a b q : Z, 0 < b -> a < q * b -> a / b < qintros a b q; rewrite Z.mul_comm; apply Z.div_lt_upper_bound. Qed.forall a b q : Z, 0 < b -> a < q * b -> a / b < qforall a b q : Z, 0 < b -> a <= q * b -> a / b <= qintros a b q; rewrite Z.mul_comm; apply Z.div_le_upper_bound. Qed.forall a b q : Z, 0 < b -> a <= q * b -> a / b <= qforall a b q : Z, 0 < b -> q * b <= a -> q <= a / bintros a b q; rewrite Z.mul_comm; apply Z.div_le_lower_bound. Qed.forall a b q : Z, 0 < b -> q * b <= a -> q <= a / b
A division of respect opposite monotonicity for the divisor
forall p q r : Z, 0 <= p -> 0 < q < r -> p / r <= p / qintros; apply Z.div_le_compat_l; auto with zarith. Qed.forall p q r : Z, 0 <= p -> 0 < q < r -> p / r <= p / qforall a b : Z, 0 <= Z.sgn (a / b) * Z.sgn a * Z.sgn bdestruct a as [ |a|a]; destruct b as [ |b|b]; simpl; auto with zarith; generalize (Z.div_pos (Zpos a) (Zpos b)); unfold Z.div, Z.div_eucl; destruct Z.pos_div_eucl as (q,r); destruct r; omega with *. Qed.forall a b : Z, 0 <= Z.sgn (a / b) * Z.sgn a * Z.sgn b
forall a b c : Z, (a + b * c) mod c = a mod cforall a b c : Z, (a + b * c) mod c = a mod ca, b, c:Z(a + b * c) mod c = a mod capply Z.mod_add; auto. Qed.a, b, c:Zn:c <> 0(a + b * c) mod c = a mod cProof Z.div_add.forall a b c : Z, c <> 0 -> (a + b * c) / c = a / c + bProof Z.div_add_l.forall a b c : Z, b <> 0 -> (a * b + c) / b = a + c / b
Z.opp and Z.div, Z.modulo.
Due to the choice of convention for our Euclidean division,
some of the relations about Z.opp and divisions are rather complex.
forall a b : Z, - a / - b = a / bforall a b : Z, - a / - b = a / ba, b:Z- a / - b = a / bapply Z.div_opp_opp; auto. Qed.a, b:Zn:b <> 0- a / - b = a / bforall a b : Z, - a mod - b = - (a mod b)forall a b : Z, - a mod - b = - (a mod b)a, b:Z- a mod - b = - (a mod b)apply Z.mod_opp_opp; auto. Qed.a, b:Zn:b <> 0- a mod - b = - (a mod b)forall a b : Z, a mod b = 0 -> - a mod b = 0forall a b : Z, a mod b = 0 -> - a mod b = 0a, b:ZH:a mod b = 0- a mod b = 0apply Z.mod_opp_l_z; auto. Qed.a, b:ZH:a mod b = 0n:b <> 0- a mod b = 0forall a b : Z, a mod b <> 0 -> - a mod b = b - a mod bforall a b : Z, a mod b <> 0 -> - a mod b = b - a mod ba, b:ZH:a mod b <> 0- a mod b = b - a mod bapply Z.mod_opp_l_nz; auto. Qed.a, b:ZH:a mod b <> 0n:b <> 0- a mod b = b - a mod bforall a b : Z, a mod b = 0 -> a mod - b = 0forall a b : Z, a mod b = 0 -> a mod - b = 0a, b:ZH:a mod b = 0a mod - b = 0apply Z.mod_opp_r_z; auto. Qed.a, b:ZH:a mod b = 0n:b <> 0a mod - b = 0forall a b : Z, a mod b <> 0 -> a mod - b = a mod b - bforall a b : Z, a mod b <> 0 -> a mod - b = a mod b - ba, b:ZH:a mod b <> 0a mod - b = a mod b - bapply Z.mod_opp_r_nz; auto. Qed.a, b:ZH:a mod b <> 0n:b <> 0a mod - b = a mod b - bforall a b : Z, a mod b = 0 -> - a / b = - (a / b)forall a b : Z, a mod b = 0 -> - a / b = - (a / b)a, b:ZH:a mod b = 0- a / b = - (a / b)apply Z.div_opp_l_z; auto. Qed.a, b:ZH:a mod b = 0n:b <> 0- a / b = - (a / b)forall a b : Z, a mod b <> 0 -> - a / b = - (a / b) - 1forall a b : Z, a mod b <> 0 -> - a / b = - (a / b) - 1a, b:Za mod b <> 0 -> - a / b = - (a / b) - 1intros; rewrite Z.div_opp_l_nz; auto. Qed.a, b:Zn:b <> 0a mod b <> 0 -> - a / b = - (a / b) - 1forall a b : Z, a mod b = 0 -> a / - b = - (a / b)forall a b : Z, a mod b = 0 -> a / - b = - (a / b)a, b:ZH:a mod b = 0a / - b = - (a / b)apply Z.div_opp_r_z; auto. Qed.a, b:ZH:a mod b = 0n:b <> 0a / - b = - (a / b)forall a b : Z, a mod b <> 0 -> a / - b = - (a / b) - 1forall a b : Z, a mod b <> 0 -> a / - b = - (a / b) - 1a, b:Za mod b <> 0 -> a / - b = - (a / b) - 1intros; rewrite Z.div_opp_r_nz; auto. Qed.a, b:Zn:b <> 0a mod b <> 0 -> a / - b = - (a / b) - 1
Cancellations.
forall a b c : Z, c <> 0 -> a * c / (b * c) = a / bforall a b c : Z, c <> 0 -> a * c / (b * c) = a / ba, b, c:ZH:c <> 0a * c / (b * c) = a / bapply Z.div_mul_cancel_r; auto. Qed.a, b, c:ZH:c <> 0n:b <> 0a * c / (b * c) = a / bforall a b c : Z, c <> 0 -> c * a / (c * b) = a / bforall a b c : Z, c <> 0 -> c * a / (c * b) = a / ba, b, c:ZH:c <> 0c * a / (c * b) = a / ba, b, c:ZH:c <> 0n:b <> 0c * a / (b * c) = a / bapply Z.div_mul_cancel_l; auto. Qed.a, b, c:ZH:c <> 0n:b <> 0c * a / (c * b) = a / bforall a b c : Z, (c * a) mod (c * b) = c * (a mod b)forall a b c : Z, (c * a) mod (c * b) = c * (a mod b)a, b, c:Z(c * a) mod (c * b) = c * (a mod b)a, b, c:Zn:c <> 0(c * a) mod (c * b) = c * (a mod b)a, b, c:Zn:c <> 0n0:b <> 0(c * a) mod (b * c) = c * (a mod b)apply Z.mul_mod_distr_l; auto. Qed.a, b, c:Zn:c <> 0n0:b <> 0(c * a) mod (c * b) = c * (a mod b)forall a b c : Z, (a * c) mod (b * c) = a mod b * cforall a b c : Z, (a * c) mod (b * c) = a mod b * ca, b, c:Z(a * c) mod (b * c) = a mod b * ca, b, c:Zn:b <> 0(a * c) mod (b * c) = a mod b * ca, b, c:Zn:b <> 0n0:c <> 0(a * c) mod (c * b) = a mod b * capply Z.mul_mod_distr_r; auto. Qed.a, b, c:Zn:b <> 0n0:c <> 0(a * c) mod (b * c) = a mod b * c
Operations modulo.
forall a n : Z, (a mod n) mod n = a mod nforall a n : Z, (a mod n) mod n = a mod na, n:Z(a mod n) mod n = a mod napply Z.mod_mod; auto. Qed.a, n:Zn0:n <> 0(a mod n) mod n = a mod nforall a b n : Z, (a * b) mod n = (a mod n * (b mod n)) mod nforall a b n : Z, (a * b) mod n = (a mod n * (b mod n)) mod na, b, n:Z(a * b) mod n = (a mod n * (b mod n)) mod napply Z.mul_mod; auto. Qed.a, b, n:Zn0:n <> 0(a * b) mod n = (a mod n * (b mod n)) mod nforall a b n : Z, (a + b) mod n = (a mod n + b mod n) mod nforall a b n : Z, (a + b) mod n = (a mod n + b mod n) mod na, b, n:Z(a + b) mod n = (a mod n + b mod n) mod napply Z.add_mod; auto. Qed.a, b, n:Zn0:n <> 0(a + b) mod n = (a mod n + b mod n) mod nforall a b n : Z, (a - b) mod n = (a mod n - b mod n) mod nforall a b n : Z, (a - b) mod n = (a mod n - b mod n) mod na, b, n:Z(a - b) mod n = (a mod n - b mod n) mod na, b, n:Z(a + -1 * b) mod n = (a mod n - b mod n) mod na, b, n:Z(a + -1 * b) mod n = (a mod n + -1 * (b mod n)) mod na, b, n:Z(a mod n + (-1 * b) mod n) mod n = (a mod n + -1 * (b mod n)) mod na, b, n:Z(a mod n + (-1 mod n * (b mod n)) mod n) mod n = (a mod n + -1 * (b mod n)) mod na, b, n:Z(a mod n + (-1 mod n * (b mod n)) mod n) mod n = ((a mod n) mod n + (-1 * (b mod n)) mod n) mod na, b, n:Z(a mod n + ((-1 mod n) mod n * ((b mod n) mod n)) mod n) mod n = ((a mod n) mod n + (-1 * (b mod n)) mod n) mod nrepeat rewrite Zmod_mod; auto. Qed.a, b, n:Z(a mod n + ((-1 mod n) mod n * ((b mod n) mod n)) mod n) mod n = ((a mod n) mod n + (-1 mod n * ((b mod n) mod n)) mod n) mod nforall a b n : Z, (a mod n + b) mod n = (a + b) mod nintros; rewrite Zplus_mod, Zmod_mod, <- Zplus_mod; auto. Qed.forall a b n : Z, (a mod n + b) mod n = (a + b) mod nforall a b n : Z, (b + a mod n) mod n = (b + a) mod nintros; rewrite Zplus_mod, Zmod_mod, <- Zplus_mod; auto. Qed.forall a b n : Z, (b + a mod n) mod n = (b + a) mod nforall a b n : Z, (a mod n - b) mod n = (a - b) mod nintros; rewrite Zminus_mod, Zmod_mod, <- Zminus_mod; auto. Qed.forall a b n : Z, (a mod n - b) mod n = (a - b) mod nforall a b n : Z, (a - b mod n) mod n = (a - b) mod nintros; rewrite Zminus_mod, Zmod_mod, <- Zminus_mod; auto. Qed.forall a b n : Z, (a - b mod n) mod n = (a - b) mod nforall a b n : Z, (a mod n * b) mod n = (a * b) mod nintros; rewrite Zmult_mod, Zmod_mod, <- Zmult_mod; auto. Qed.forall a b n : Z, (a mod n * b) mod n = (a * b) mod nforall a b n : Z, (b * (a mod n)) mod n = (b * a) mod nintros; rewrite Zmult_mod, Zmod_mod, <- Zmult_mod; auto. Qed.forall a b n : Z, (b * (a mod n)) mod n = (b * a) mod n
For a specific number N, equality modulo N is hence a nice setoid
equivalence, compatible with +, - and ×.
Section EqualityModulo. Variable N:Z. Definition eqm a b := (a mod N = b mod N). Infix "==" := eqm (at level 70).N:Zforall a : Z, a == aunfold eqm; auto. Qed.N:Zforall a : Z, a == aN:Zforall a b : Z, a == b -> b == aunfold eqm; auto. Qed.N:Zforall a b : Z, a == b -> b == aN:Zforall a b c : Z, a == b -> b == c -> a == cunfold eqm; eauto with *. Qed.N:Zforall a b c : Z, a == b -> b == c -> a == cN:ZEquivalence eqmconstructor; [exact eqm_refl | exact eqm_sym | exact eqm_trans]. Qed.N:ZEquivalence eqmN:ZProper (eqm ==> eqm ==> eqm) Z.addN:ZProper (eqm ==> eqm ==> eqm) Z.addrewrite Zplus_mod, H, H0, <- Zplus_mod; auto. Qed.N, x, y:ZH:x mod N = y mod Nx0, y0:ZH0:x0 mod N = y0 mod N(x + x0) mod N = (y + y0) mod NN:ZProper (eqm ==> eqm ==> eqm) Z.subN:ZProper (eqm ==> eqm ==> eqm) Z.subrewrite Zminus_mod, H, H0, <- Zminus_mod; auto. Qed.N, x, y:ZH:x mod N = y mod Nx0, y0:ZH0:x0 mod N = y0 mod N(x - x0) mod N = (y - y0) mod NN:ZProper (eqm ==> eqm ==> eqm) Z.mulN:ZProper (eqm ==> eqm ==> eqm) Z.mulrewrite Zmult_mod, H, H0, <- Zmult_mod; auto. Qed.N, x, y:ZH:x mod N = y mod Nx0, y0:ZH0:x0 mod N = y0 mod N(x * x0) mod N = (y * y0) mod NN:ZProper (eqm ==> eqm) Z.oppN:ZProper (eqm ==> eqm) Z.oppN, x, y:ZH:x == y- x == - ynow rewrite H. Qed.N, x, y:ZH:x == y0 - x == 0 - yN:Zforall a : Z, a mod N == aintros; exact (Zmod_mod a N). Qed. (* NB: Z.modulo and Z.div are not morphisms with respect to eqm. For instance, let (==) be (eqm 2). Then we have (3 == 1) but: ~ (3 mod 3 == 1 mod 3) ~ (1 mod 3 == 1 mod 1) ~ (3/3 == 1/3) ~ (1/3 == 1/1) *) End EqualityModulo.N:Zforall a : Z, a mod N == aforall a b c : Z, 0 <= b -> 0 <= c -> a / b / c = a / (b * c)forall a b c : Z, 0 <= b -> 0 <= c -> a / b / c = a / (b * c)a, b, c:ZH:0 <= bH0:0 <= ca / b / c = a / (b * c)a, b, c:ZH:0 <= bH0:0 <= cn:b <> 0a / b / c = a / (b * c)a, b, c:ZH:0 <= bH0:0 <= cn:b <> 0a / b / c = a / (c * b)a, b, c:ZH:0 <= bH0:0 <= cn:b <> 0n0:c <> 0a / b / c = a / (c * b)apply Z.div_div; auto with zarith. Qed.a, b, c:ZH:0 <= bH0:0 <= cn:b <> 0n0:c <> 0a / b / c = a / (b * c)
Unfortunately, the previous result isn't always true on negative numbers.
For instance: 3/(-2)/(-2) = 1 <> 0 = 3 / (-2*-2)
forall a b : Z, a mod b / b = 0forall a b : Z, a mod b / b = 0a, b:Za mod b / b = 0auto using Z.mod_div. Qed.a, b:Zn:b <> 0a mod b / b = 0
A last inequality:
forall a b c : Z, 0 <= a -> 0 <= b -> 0 <= c -> c * (a / b) <= c * a / bforall a b c : Z, 0 <= a -> 0 <= b -> 0 <= c -> c * (a / b) <= c * a / ba, b, c:ZH:0 <= aH0:0 <= bH1:0 <= cc * (a / b) <= c * a / bapply Z.div_mul_le; auto with zarith. Qed.a, b, c:ZH:0 <= aH0:0 <= bH1:0 <= cn:b <> 0c * (a / b) <= c * a / b
Z.modulo is related to divisibility (see more in Znumtheory)
forall a b : Z, b <> 0 -> a mod b = 0 <-> (exists c : Z, a = b * c)forall a b : Z, b <> 0 -> a mod b = 0 <-> (exists c : Z, a = b * c)a, b:ZH:b <> 0a mod b = 0 <-> (exists c : Z, a = b * c)split; intros (c,Hc); exists c; subst; auto with zarith. Qed.a, b:ZH:b <> 0(b | a) <-> (exists c : Z, a = b * c)
Particular case : dividing by 2 is related with parity
Proof Z.div2_div.forall a : Z, Z.div2 a = a / 2forall a : Z, a mod 2 = (if Z.odd a then 1 else 0)forall a : Z, a mod 2 = (if Z.odd a then 1 else 0)now rewrite <- Z.bit0_odd, <- Z.bit0_mod. Qed.a:Za mod 2 = (if Z.odd a then 1 else 0)forall a : Z, a mod 2 = (if Z.even a then 0 else 1)forall a : Z, a mod 2 = (if Z.even a then 0 else 1)a:Za mod 2 = (if Z.even a then 0 else 1)now destruct Z.even. Qed.a:Z(if negb (Z.even a) then 1 else 0) = (if Z.even a then 0 else 1)forall a : Z, Z.odd a = Zeq_bool (a mod 2) 1forall a : Z, Z.odd a = Zeq_bool (a mod 2) 1a:ZZ.odd a = Zeq_bool (a mod 2) 1now destruct Z.odd. Qed.a:ZZ.odd a = Zeq_bool (if Z.odd a then 1 else 0) 1forall a : Z, Z.even a = Zeq_bool (a mod 2) 0forall a : Z, Z.even a = Zeq_bool (a mod 2) 0a:ZZ.even a = Zeq_bool (a mod 2) 0now destruct Z.even. Qed.a:ZZ.even a = Zeq_bool (if Z.even a then 0 else 1) 0
Weaker results kept only for compatibility
forall a : Z, a > 0 -> a mod a = 0intros; apply Z_mod_same_full. Qed.forall a : Z, a > 0 -> a mod a = 0forall a : Z, a > 0 -> a / a = 1intros; apply Z_div_same_full; auto with zarith. Qed.forall a : Z, a > 0 -> a / a = 1forall a b c : Z, c > 0 -> (a + b * c) / c = a / c + bintros; apply Z_div_plus_full; auto with zarith. Qed.forall a b c : Z, c > 0 -> (a + b * c) / c = a / c + bforall a b : Z, b > 0 -> a * b / b = aintros; apply Z_div_mult_full; auto with zarith. Qed.forall a b : Z, b > 0 -> a * b / b = aforall a b c : Z, c > 0 -> (a + b * c) mod c = a mod cintros; apply Z_mod_plus_full; auto with zarith. Qed.forall a b c : Z, c > 0 -> (a + b * c) mod c = a mod cforall a b : Z, b > 0 -> a = b * (a / b) -> a mod b = 0intros; apply Z_div_exact_full_1; auto with zarith. Qed.forall a b : Z, b > 0 -> a = b * (a / b) -> a mod b = 0forall a b : Z, b > 0 -> a mod b = 0 -> a = b * (a / b)intros; apply Z_div_exact_full_2; auto with zarith. Qed.forall a b : Z, b > 0 -> a mod b = 0 -> a = b * (a / b)forall a b : Z, b > 0 -> a mod b = 0 -> - a mod b = 0intros; apply Z_mod_zero_opp_full; auto with zarith. Qed.forall a b : Z, b > 0 -> a mod b = 0 -> - a mod b = 0
Fixpoint Zmod_POS (a : positive) (b : Z) : Z := match a with | xI a' => let r := Zmod_POS a' b in let r' := (2 * r + 1) in if r' <? b then r' else (r' - b) | xO a' => let r := Zmod_POS a' b in let r' := (2 * r) in if r' <? b then r' else (r' - b) | xH => if 2 <=? b then 1 else 0 end. Definition Zmod' a b := match a with | Z0 => 0 | Zpos a' => match b with | Z0 => 0 | Zpos _ => Zmod_POS a' b | Zneg b' => let r := Zmod_POS a' (Zpos b') in match r with Z0 => 0 | _ => b + r end end | Zneg a' => match b with | Z0 => 0 | Zpos _ => let r := Zmod_POS a' b in match r with Z0 => 0 | _ => b - r end | Zneg b' => - (Zmod_POS a' (Zpos b')) end end.a:positiveb:ZZmod_POS a b = snd (Z.pos_div_eucl a b)a:positiveb:ZZmod_POS a b = snd (Z.pos_div_eucl a b)a:positiveb:ZIH:Zmod_POS a b = snd (Z.pos_div_eucl a b)(if match snd (Z.pos_div_eucl a b) with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end + 1 <? b then match snd (Z.pos_div_eucl a b) with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end + 1 else match snd (Z.pos_div_eucl a b) with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end + 1 - b) = snd (let (q, r) := Z.pos_div_eucl a b in if match r with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end + 1 <? b then (match q with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end, match r with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end + 1) else (match q with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end + 1, match r with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end + 1 - b))a:positiveb:ZIH:Zmod_POS a b = snd (Z.pos_div_eucl a b)(if match snd (Z.pos_div_eucl a b) with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end <? b then match snd (Z.pos_div_eucl a b) with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end else match snd (Z.pos_div_eucl a b) with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end - b) = snd (let (q, r) := Z.pos_div_eucl a b in if match r with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end <? b then (match q with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end, match r with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end) else (match q with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end + 1, match r with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end - b))b:Z(if 2 <=? b then 1 else 0) = snd (if 2 <=? b then (0, 1) else (1, 0))a:positiveb:ZIH:Zmod_POS a b = snd (Z.pos_div_eucl a b)(if match snd (Z.pos_div_eucl a b) with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end <? b then match snd (Z.pos_div_eucl a b) with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end else match snd (Z.pos_div_eucl a b) with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end - b) = snd (let (q, r) := Z.pos_div_eucl a b in if match r with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end <? b then (match q with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end, match r with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end) else (match q with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end + 1, match r with | 0 => 0 | Z.pos y' => Z.pos y'~0 | Z.neg y' => Z.neg y'~0 end - b))b:Z(if 2 <=? b then 1 else 0) = snd (if 2 <=? b then (0, 1) else (1, 0))case Z.leb_spec; trivial. Qed.b:Z(if 2 <=? b then 1 else 0) = snd (if 2 <=? b then (0, 1) else (1, 0))forall a b : Z, Zmod' a b = a mod bforall a b : Z, Zmod' a b = a mod ba, b:Zforall p : positive, match b with | 0 => 0 | Z.pos _ => Zmod_POS p b | Z.neg b' => match Zmod_POS p (Z.pos b') with | 0 => 0 | _ => b + Zmod_POS p (Z.pos b') end end = (let (_, r) := match b with | 0 => (0, 0) | Z.pos _ => Z.pos_div_eucl p b | Z.neg b' => let (q, r) := Z.pos_div_eucl p (Z.pos b') in match r with | 0 => (- q, 0) | _ => (- (q + 1), b + r) end end in r)a, b:Zforall p : positive, match b with | 0 => 0 | Z.pos _ => match Zmod_POS p b with | 0 => 0 | _ => b - Zmod_POS p b end | Z.neg b' => - Zmod_POS p (Z.pos b') end = (let (_, r) := match b with | 0 => (0, 0) | Z.pos _ => let (q, r) := Z.pos_div_eucl p b in match r with | 0 => (- q, 0) | _ => (- (q + 1), b - r) end | Z.neg b' => let (q, r) := Z.pos_div_eucl p (Z.pos b') in (q, - r) end in r)a, b:Zp:positiveforall p0 : positive, Zmod_POS p (Z.pos p0) = (let (_, r) := Z.pos_div_eucl p (Z.pos p0) in r)a, b:Zp:positiveforall p0 : positive, match Zmod_POS p (Z.pos p0) with | 0 => 0 | _ => match Zmod_POS p (Z.pos p0) with | 0 => Z.neg p0 | Z.pos y' => Z.pos_sub y' p0 | Z.neg y' => Z.neg (p0 + y') end end = (let (_, r) := let (q, r) := Z.pos_div_eucl p (Z.pos p0) in match r with | 0 => (- q, 0) | _ => (- (q + 1), match r with | 0 => Z.neg p0 | Z.pos y' => Z.pos_sub y' p0 | Z.neg y' => Z.neg (p0 + y') end) end in r)a, b:Zforall p : positive, match b with | 0 => 0 | Z.pos _ => match Zmod_POS p b with | 0 => 0 | _ => b - Zmod_POS p b end | Z.neg b' => - Zmod_POS p (Z.pos b') end = (let (_, r) := match b with | 0 => (0, 0) | Z.pos _ => let (q, r) := Z.pos_div_eucl p b in match r with | 0 => (- q, 0) | _ => (- (q + 1), b - r) end | Z.neg b' => let (q, r) := Z.pos_div_eucl p (Z.pos b') in (q, - r) end in r)a, b:Zp:positiveforall p0 : positive, match Zmod_POS p (Z.pos p0) with | 0 => 0 | _ => match Zmod_POS p (Z.pos p0) with | 0 => Z.neg p0 | Z.pos y' => Z.pos_sub y' p0 | Z.neg y' => Z.neg (p0 + y') end end = (let (_, r) := let (q, r) := Z.pos_div_eucl p (Z.pos p0) in match r with | 0 => (- q, 0) | _ => (- (q + 1), match r with | 0 => Z.neg p0 | Z.pos y' => Z.pos_sub y' p0 | Z.neg y' => Z.neg (p0 + y') end) end in r)a, b:Zforall p : positive, match b with | 0 => 0 | Z.pos _ => match Zmod_POS p b with | 0 => 0 | _ => b - Zmod_POS p b end | Z.neg b' => - Zmod_POS p (Z.pos b') end = (let (_, r) := match b with | 0 => (0, 0) | Z.pos _ => let (q, r) := Z.pos_div_eucl p b in match r with | 0 => (- q, 0) | _ => (- (q + 1), b - r) end | Z.neg b' => let (q, r) := Z.pos_div_eucl p (Z.pos b') in (q, - r) end in r)a, b:Zp, p1:positivematch snd (Z.pos_div_eucl p (Z.pos p1)) with | 0 => 0 | _ => match snd (Z.pos_div_eucl p (Z.pos p1)) with | 0 => Z.neg p1 | Z.pos y' => Z.pos_sub y' p1 | Z.neg y' => Z.neg (p1 + y') end end = (let (_, r) := let (q, r) := Z.pos_div_eucl p (Z.pos p1) in match r with | 0 => (- q, 0) | _ => (- (q + 1), match r with | 0 => Z.neg p1 | Z.pos y' => Z.pos_sub y' p1 | Z.neg y' => Z.neg (p1 + y') end) end in r)a, b:Zforall p : positive, match b with | 0 => 0 | Z.pos _ => match Zmod_POS p b with | 0 => 0 | _ => b - Zmod_POS p b end | Z.neg b' => - Zmod_POS p (Z.pos b') end = (let (_, r) := match b with | 0 => (0, 0) | Z.pos _ => let (q, r) := Z.pos_div_eucl p b in match r with | 0 => (- q, 0) | _ => (- (q + 1), b - r) end | Z.neg b' => let (q, r) := Z.pos_div_eucl p (Z.pos b') in (q, - r) end in r)a, b:Zforall p : positive, match b with | 0 => 0 | Z.pos _ => match Zmod_POS p b with | 0 => 0 | _ => b - Zmod_POS p b end | Z.neg b' => - Zmod_POS p (Z.pos b') end = (let (_, r) := match b with | 0 => (0, 0) | Z.pos _ => let (q, r) := Z.pos_div_eucl p b in match r with | 0 => (- q, 0) | _ => (- (q + 1), b - r) end | Z.neg b' => let (q, r) := Z.pos_div_eucl p (Z.pos b') in (q, - r) end in r)a, b:Zp:positiveforall p0 : positive, match Zmod_POS p (Z.pos p0) with | 0 => 0 | _ => match - Zmod_POS p (Z.pos p0) with | 0 => Z.pos p0 | Z.pos y' => Z.pos (p0 + y') | Z.neg y' => Z.pos_sub p0 y' end end = (let (_, r) := let (q, r) := Z.pos_div_eucl p (Z.pos p0) in match r with | 0 => (- q, 0) | _ => (- (q + 1), match - r with | 0 => Z.pos p0 | Z.pos y' => Z.pos (p0 + y') | Z.neg y' => Z.pos_sub p0 y' end) end in r)a, b:Zp:positiveforall p0 : positive, - Zmod_POS p (Z.pos p0) = (let (_, r) := let (q, r) := Z.pos_div_eucl p (Z.pos p0) in (q, - r) in r)a, b:Zp, p1:positivematch snd (Z.pos_div_eucl p (Z.pos p1)) with | 0 => 0 | _ => match - snd (Z.pos_div_eucl p (Z.pos p1)) with | 0 => Z.pos p1 | Z.pos y' => Z.pos (p1 + y') | Z.neg y' => Z.pos_sub p1 y' end end = (let (_, r) := let (q, r) := Z.pos_div_eucl p (Z.pos p1) in match r with | 0 => (- q, 0) | _ => (- (q + 1), match - r with | 0 => Z.pos p1 | Z.pos y' => Z.pos (p1 + y') | Z.neg y' => Z.pos_sub p1 y' end) end in r)a, b:Zp:positiveforall p0 : positive, - Zmod_POS p (Z.pos p0) = (let (_, r) := let (q, r) := Z.pos_div_eucl p (Z.pos p0) in (q, - r) in r)a, b:Zp:positiveforall p0 : positive, - Zmod_POS p (Z.pos p0) = (let (_, r) := let (q, r) := Z.pos_div_eucl p (Z.pos p0) in (q, - r) in r)case (Z.pos_div_eucl p (Zpos p1)); auto. Qed.a, b:Zp, p1:positive- snd (Z.pos_div_eucl p (Z.pos p1)) = (let (_, r) := let (q, r) := Z.pos_div_eucl p (Z.pos p1) in (q, - r) in r)
Another convention is possible for division by negative numbers:
quotient is always the biggest integer smaller than or equal to a/b
remainder is hence always positive or null.
forall b : Z, b <> 0 -> forall a : Z, {qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Z.abs b}forall b : Z, b <> 0 -> forall a : Z, {qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Z.abs b}b:ZHb:b <> 0a:Z{qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Z.abs b}b:ZHb:b <> 0a:ZHb':0 <= b{qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Z.abs b}b:ZHb:b <> 0a:ZHb':0 > b{qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Z.abs b}b:ZHb:b <> 0a:ZHb':0 <= b{qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Z.abs b}rewrite Z.abs_eq; [ apply Zdiv_eucl_exist; assumption | assumption ].b:ZHb:b <> 0a:ZHb':0 <= bHb'':b > 0{qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Z.abs b}b:ZHb:b <> 0a:ZHb':0 > b{qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Z.abs b}b:ZHb:b <> 0a:ZHb':0 > bHb'':- b > 0{qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Z.abs b}b:ZHb:b <> 0a:ZHb':0 > bHb'':- b > 0q, r:ZH:a = - b * q + rH0:0 <= r < - b{qr : Z * Z | let (q0, r0) := qr in a = b * q0 + r0 /\ 0 <= r0 < Z.abs b}b:ZHb:b <> 0a:ZHb':0 > bHb'':- b > 0q, r:ZH:a = - b * q + rH0:0 <= r < - ba = b * - q + r /\ 0 <= r < Z.abs bb:ZHb:b <> 0a:ZHb':0 > bHb'':- b > 0q, r:ZH:a = - b * q + rH0:0 <= r < - ba = b * - q + rb:ZHb:b <> 0a:ZHb':0 > bHb'':- b > 0q, r:ZH:a = - b * q + rH0:0 <= r < - b0 <= r < Z.abs brewrite <- Z.mul_opp_comm; assumption.b:ZHb:b <> 0a:ZHb':0 > bHb'':- b > 0q, r:ZH:a = - b * q + rH0:0 <= r < - ba = b * - q + rrewrite Z.abs_neq; [ assumption | omega ]. Qed. Arguments Zdiv_eucl_extended : default implicits.b:ZHb:b <> 0a:ZHb':0 > bHb'':- b > 0q, r:ZH:a = - b * q + rH0:0 <= r < - b0 <= r < Z.abs b
Require Import PeanoNat.n, m:natm <> 0%nat -> Z.of_nat (n / m) = Z.of_nat n / Z.of_nat mn, m:natm <> 0%nat -> Z.of_nat (n / m) = Z.of_nat n / Z.of_nat mn, m:natH:m <> 0%natZ.of_nat (n / m) = Z.of_nat n / Z.of_nat mn, m:natH:m <> 0%nat0 <= Z.of_nat (n mod m) < Z.of_nat mn, m:natH:m <> 0%natZ.of_nat n = Z.of_nat m * Z.of_nat (n / m) + Z.of_nat (n mod m)n, m:natH:m <> 0%nat0 <= Z.of_nat (n mod m)n, m:natH:m <> 0%natZ.of_nat (n mod m) < Z.of_nat mn, m:natH:m <> 0%natZ.of_nat n = Z.of_nat m * Z.of_nat (n / m) + Z.of_nat (n mod m)n, m:natH:m <> 0%natZ.of_nat (n mod m) < Z.of_nat mn, m:natH:m <> 0%natZ.of_nat n = Z.of_nat m * Z.of_nat (n / m) + Z.of_nat (n mod m)n, m:natH:m <> 0%natZ.of_nat n = Z.of_nat m * Z.of_nat (n / m) + Z.of_nat (n mod m)now apply inj_eq, Nat.div_mod. Qed.n, m:natH:m <> 0%natZ.of_nat n = Z.of_nat (m * (n / m) + n mod m)n, m:natm <> 0%nat -> Z.of_nat (n mod m) = Z.of_nat n mod Z.of_nat mn, m:natm <> 0%nat -> Z.of_nat (n mod m) = Z.of_nat n mod Z.of_nat mn, m:natH:m <> 0%natZ.of_nat (n mod m) = Z.of_nat n mod Z.of_nat mn, m:natH:m <> 0%nat0 <= Z.of_nat (n mod m) < Z.of_nat mn, m:natH:m <> 0%natZ.of_nat n = Z.of_nat m * (Z.of_nat n / Z.of_nat m) + Z.of_nat (n mod m)n, m:natH:m <> 0%nat0 <= Z.of_nat (n mod m)n, m:natH:m <> 0%natZ.of_nat (n mod m) < Z.of_nat mn, m:natH:m <> 0%natZ.of_nat n = Z.of_nat m * (Z.of_nat n / Z.of_nat m) + Z.of_nat (n mod m)n, m:natH:m <> 0%natZ.of_nat (n mod m) < Z.of_nat mn, m:natH:m <> 0%natZ.of_nat n = Z.of_nat m * (Z.of_nat n / Z.of_nat m) + Z.of_nat (n mod m)n, m:natH:m <> 0%natZ.of_nat n = Z.of_nat m * (Z.of_nat n / Z.of_nat m) + Z.of_nat (n mod m)now apply inj_eq, Nat.div_mod. Qed.n, m:natH:m <> 0%natZ.of_nat n = Z.of_nat (m * (n / m) + n mod m)