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.
(************************************************************************) (* * 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) *) (************************************************************************) Require Import ZAxioms ZMulOrder ZSgnAbs NZDiv.
Euclidean Division for integers, Euclid convention
Module Type EuclidSpec (Import A : ZAxiomsSig')(Import B : DivMod A). Axiom mod_always_pos : forall a b, b ~= 0 -> 0 <= B.modulo a b < abs b. End EuclidSpec. Module Type ZEuclid (Z:ZAxiomsSig) := NZDiv.NZDiv Z <+ EuclidSpec Z. Module ZEuclidProp (Import A : ZAxiomsSig') (Import B : ZMulOrderProp A) (Import C : ZSgnAbsProp A B) (Import D : ZEuclid A).
We put notations in a scope, to avoid warnings about
redefinitions of notations
Declare Scope euclid. Infix "/" := D.div : euclid. Infix "mod" := D.modulo : euclid. Local Open Scope euclid. Module Import Private_NZDiv := Nop <+ NZDivProp A D B.
Another formulation of the main equation
forall a b : t, b ~= 0 -> a mod b == a - b * (a / b)forall a b : t, b ~= 0 -> a mod b == a - b * (a / b)a, b:tH:b ~= 0a mod b == a - b * (a / b)a, b:tH:b ~= 0b * (a / b) + a mod b == anow apply div_mod. Qed. Ltac pos_or_neg a := let LT := fresh "LT" in let LE := fresh "LE" in destruct (le_gt_cases 0 a) as [LE|LT]; [|rewrite <- opp_pos_neg in LT].a, b:tH:b ~= 0a == b * (a / b) + a mod b
Uniqueness theorems
forall b q1 q2 r1 r2 : t, 0 <= r1 < abs b -> 0 <= r2 < abs b -> b * q1 + r1 == b * q2 + r2 -> q1 == q2 /\ r1 == r2forall b q1 q2 r1 r2 : t, 0 <= r1 < abs b -> 0 <= r2 < abs b -> b * q1 + r1 == b * q2 + r2 -> q1 == q2 /\ r1 == r2b, q1, q2, r1, r2:tHr1:0 <= r1 < abs bHr2:0 <= r2 < abs bEQ:b * q1 + r1 == b * q2 + r2q1 == q2 /\ r1 == r2b, q1, q2, r1, r2:tHr1:0 <= r1 < abs bHr2:0 <= r2 < abs bEQ:b * q1 + r1 == b * q2 + r2LE:0 <= bq1 == q2 /\ r1 == r2b, q1, q2, r1, r2:tHr1:0 <= r1 < abs bHr2:0 <= r2 < abs bEQ:b * q1 + r1 == b * q2 + r2LT:0 < - bq1 == q2 /\ r1 == r2b, q1, q2, r1, r2:tHr1:0 <= r1 < bHr2:0 <= r2 < bEQ:b * q1 + r1 == b * q2 + r2LE:0 <= bq1 == q2 /\ r1 == r2b, q1, q2, r1, r2:tHr1:0 <= r1 < abs bHr2:0 <= r2 < abs bEQ:b * q1 + r1 == b * q2 + r2LT:0 < - bq1 == q2 /\ r1 == r2b, q1, q2, r1, r2:tHr1:0 <= r1 < abs bHr2:0 <= r2 < abs bEQ:b * q1 + r1 == b * q2 + r2LT:0 < - bq1 == q2 /\ r1 == r2b, q1, q2, r1, r2:tHr1:0 <= r1 < - bHr2:0 <= r2 < - bEQ:b * q1 + r1 == b * q2 + r2LT:0 < - bq1 == q2 /\ r1 == r2b, q1, q2, r1, r2:tHr1:0 <= r1 < - bHr2:0 <= r2 < - bEQ:b * q1 + r1 == b * q2 + r2LT:0 < - bq2 == q1 /\ r1 == r2b, q1, q2, r1, r2:tHr1:0 <= r1 < - bHr2:0 <= r2 < - bEQ:b * q1 + r1 == b * q2 + r2LT:0 < - b- b * q2 + r1 == - b * q1 + r2b, q1, q2, r1, r2:tHr1:0 <= r1 < - bHr2:0 <= r2 < - bEQ:b * q1 + r1 == b * q2 + r2LT:0 < - b- (b * q2) + r1 == - (b * q1) + r2b, q1, q2, r1, r2:tHr1:0 <= r1 < - bHr2:0 <= r2 < - bEQ:b * q1 + r1 == b * q2 + r2LT:0 < - br1 == - (b * q1) + r2 + b * q2b, q1, q2, r1, r2:tHr1:0 <= r1 < - bHr2:0 <= r2 < - bEQ:b * q1 + r1 == b * q2 + r2LT:0 < - br1 == - (b * q1) + (r2 + b * q2)b, q1, q2, r1, r2:tHr1:0 <= r1 < - bHr2:0 <= r2 < - bEQ:b * q1 + r1 == b * q2 + r2LT:0 < - b- (b * q1) + (r2 + b * q2) == r1now rewrite (add_comm r2), (add_comm r1). Qed.b, q1, q2, r1, r2:tHr1:0 <= r1 < - bHr2:0 <= r2 < - bEQ:b * q1 + r1 == b * q2 + r2LT:0 < - br2 + b * q2 == r1 + b * q1forall a b q r : t, 0 <= r < abs b -> a == b * q + r -> q == a / bforall a b q r : t, 0 <= r < abs b -> a == b * q + r -> q == a / ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rq == a / ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rb ~= 0a, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0q == a / ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rLE:0 <= bb ~= 0a, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rLT:0 < - bb ~= 0a, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0q == a / ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rLT:0 < - bb ~= 0a, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0q == a / ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rLT:0 < - b- b ~= 0a, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0q == a / ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0q == a / ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 00 <= a mod b < abs ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0b * q + r == b * (a / b) + a mod bnow rewrite <- div_mod. Qed.a, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0b * q + r == b * (a / b) + a mod bforall a b q r : t, 0 <= r < abs b -> a == b * q + r -> r == a mod bforall a b q r : t, 0 <= r < abs b -> a == b * q + r -> r == a mod ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rr == a mod ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rb ~= 0a, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0r == a mod ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rLE:0 <= bb ~= 0a, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rLT:0 < - bb ~= 0a, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0r == a mod ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rLT:0 < - bb ~= 0a, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0r == a mod ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rLT:0 < - b- b ~= 0a, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0r == a mod ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0r == a mod ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 00 <= a mod b < abs ba, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0b * q + r == b * (a / b) + a mod bnow rewrite <- div_mod. Qed.a, b, q, r:tHr:0 <= r < abs bEQ:a == b * q + rHb:b ~= 0b * q + r == b * (a / b) + a mod b
Sign rules
forall a b : t, b ~= 0 -> a / - b == - (a / b)forall a b : t, b ~= 0 -> a / - b == - (a / b)a, b:tH:b ~= 0a / - b == - (a / b)a, b:tH:b ~= 0- (a / b) == a / - ba, b:tH:b ~= 00 <= a mod b < abs (- b)a, b:tH:b ~= 0a == - b * - (a / b) + a mod brewrite mul_opp_opp; now apply div_mod. Qed.a, b:tH:b ~= 0a == - b * - (a / b) + a mod bforall a b : t, b ~= 0 -> a mod - b == a mod bforall a b : t, b ~= 0 -> a mod - b == a mod ba, b:tH:b ~= 0a mod - b == a mod ba, b:tH:b ~= 0a mod b == a mod - ba, b:tH:b ~= 00 <= a mod b < abs (- b)a, b:tH:b ~= 0a == - b * - (a / b) + a mod brewrite mul_opp_opp; now apply div_mod. Qed.a, b:tH:b ~= 0a == - b * - (a / b) + a mod bforall a b : t, b ~= 0 -> a mod b == 0 -> - a / b == - (a / b)forall a b : t, b ~= 0 -> a mod b == 0 -> - a / b == - (a / b)a, b:tHb:b ~= 0Hab:a mod b == 0- a / b == - (a / b)a, b:tHb:b ~= 0Hab:a mod b == 0- (a / b) == - a / ba, b:tHb:b ~= 0Hab:a mod b == 00 <= - (a mod b) < abs ba, b:tHb:b ~= 0Hab:a mod b == 0- a == b * - (a / b) + - (a mod b)a, b:tHb:b ~= 0Hab:a mod b == 00 <= 0 < abs ba, b:tHb:b ~= 0Hab:a mod b == 0- a == b * - (a / b) + - (a mod b)a, b:tHb:b ~= 0Hab:a mod b == 00 < abs ba, b:tHb:b ~= 0Hab:a mod b == 0- a == b * - (a / b) + - (a mod b)now rewrite mul_opp_r, <-opp_add_distr, <-div_mod. Qed.a, b:tHb:b ~= 0Hab:a mod b == 0- a == b * - (a / b) + - (a mod b)forall a b : t, b ~= 0 -> a mod b ~= 0 -> - a / b == - (a / b) - sgn bforall a b : t, b ~= 0 -> a mod b ~= 0 -> - a / b == - (a / b) - sgn ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a / b == - (a / b) - sgn ba, b:tHb:b ~= 0Hab:a mod b ~= 0- (a / b) - sgn b == - a / ba, b:tHb:b ~= 0Hab:a mod b ~= 00 <= abs b - a mod b < abs ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 00 <= abs b - a mod b /\ abs b < a mod b + abs ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 0a mod b + 0 <= abs b < a mod b + abs ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 0a mod b <= abs b < a mod b + abs ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 0a mod b <= abs b /\ 0 + abs b < a mod b + abs ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 0a mod b <= abs b /\ 0 < a mod ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 0- a == - (b * (a / b)) + - (b * sgn b) + (abs b + - (a mod b))a, b:tHb:b ~= 0Hab:a mod b ~= 0- a == - (b * (a / b)) + - abs b + (abs b + - (a mod b))rewrite <-opp_add_distr, <-div_mod; order. Qed.a, b:tHb:b ~= 0Hab:a mod b ~= 0- a == - (b * (a / b)) + - (a mod b)forall a b : t, b ~= 0 -> a mod b == 0 -> - a mod b == 0forall a b : t, b ~= 0 -> a mod b == 0 -> - a mod b == 0a, b:tHb:b ~= 0Hab:a mod b == 0- a mod b == 0a, b:tHb:b ~= 0Hab:a mod b == 00 == - a mod ba, b:tHb:b ~= 0Hab:a mod b == 00 <= 0 < abs ba, b:tHb:b ~= 0Hab:a mod b == 0- a == b * - (a / b) + 0now rewrite <-opp_0, <-Hab, mul_opp_r, <-opp_add_distr, <-div_mod. Qed.a, b:tHb:b ~= 0Hab:a mod b == 0- a == b * - (a / b) + 0forall a b : t, b ~= 0 -> a mod b ~= 0 -> - a mod b == abs b - a mod bforall a b : t, b ~= 0 -> a mod b ~= 0 -> - a mod b == abs b - a mod ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a mod b == abs b - a mod ba, b:tHb:b ~= 0Hab:a mod b ~= 0abs b - a mod b == - a mod ba, b:tHb:b ~= 0Hab:a mod b ~= 00 <= abs b - a mod b < abs ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 00 <= abs b - a mod b /\ abs b < a mod b + abs ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 0a mod b + 0 <= abs b < a mod b + abs ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 0a mod b <= abs b < a mod b + abs ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 0a mod b <= abs b /\ 0 + abs b < a mod b + abs ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 0a mod b <= abs b /\ 0 < a mod ba, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 0- a == b * (- (a / b) - sgn b) + (abs b - a mod b)a, b:tHb:b ~= 0Hab:a mod b ~= 0- a == - (b * (a / b)) + - (b * sgn b) + (abs b + - (a mod b))a, b:tHb:b ~= 0Hab:a mod b ~= 0- a == - (b * (a / b)) + - abs b + (abs b + - (a mod b))rewrite <-opp_add_distr, <-div_mod; order. Qed.a, b:tHb:b ~= 0Hab:a mod b ~= 0- a == - (b * (a / b)) + - (a mod b)forall a b : t, b ~= 0 -> a mod b == 0 -> - a / - b == a / bforall a b : t, b ~= 0 -> a mod b == 0 -> - a / - b == a / bnow rewrite div_opp_r, div_opp_l_z, opp_involutive. Qed.a, b:tH:b ~= 0H0:a mod b == 0- a / - b == a / bforall a b : t, b ~= 0 -> a mod b ~= 0 -> - a / - b == a / b + sgn bforall a b : t, b ~= 0 -> a mod b ~= 0 -> - a / - b == a / b + sgn ba, b:tH:b ~= 0H0:a mod b ~= 0- a / - b == a / b + sgn bnow rewrite opp_sub_distr, opp_involutive. Qed.a, b:tH:b ~= 0H0:a mod b ~= 0- (- (a / b) - sgn b) == a / b + sgn bforall a b : t, b ~= 0 -> a mod b == 0 -> - a mod - b == 0forall a b : t, b ~= 0 -> a mod b == 0 -> - a mod - b == 0now rewrite mod_opp_r, mod_opp_l_z. Qed.a, b:tH:b ~= 0H0:a mod b == 0- a mod - b == 0forall a b : t, b ~= 0 -> a mod b ~= 0 -> - a mod - b == abs b - a mod bforall a b : t, b ~= 0 -> a mod b ~= 0 -> - a mod - b == abs b - a mod bnow rewrite mod_opp_r, mod_opp_l_nz. Qed.a, b:tH:b ~= 0H0:a mod b ~= 0- a mod - b == abs b - a mod b
A division by itself returns 1
forall a : t, a ~= 0 -> a / a == 1forall a : t, a ~= 0 -> a / a == 1a:tH:a ~= 0a / a == 1a:tH:a ~= 01 == a / aa:tH:a ~= 00 <= 0 < abs aa:tH:a ~= 0a == a * 1 + 0now nzsimpl. Qed.a:tH:a ~= 0a == a * 1 + 0forall a : t, a ~= 0 -> a mod a == 0forall a : t, a ~= 0 -> a mod a == 0a:tH:a ~= 0a mod a == 0a:tH:a ~= 0a - a * 1 == 0apply sub_diag. Qed.a:tH:a ~= 0a - a == 0
A division of a small number by a bigger one yields zero.
forall a b : t, 0 <= a < b -> a / b == 0exact div_small. Qed.forall a b : t, 0 <= a < b -> a / b == 0
Same situation, in term of modulo:
forall a b : t, 0 <= a < b -> a mod b == aexact mod_small. Qed.forall a b : t, 0 <= a < b -> a mod b == a
forall a : t, a ~= 0 -> 0 / a == 0forall a : t, a ~= 0 -> 0 / a == 0a:tH:a ~= 00 / a == 0a:tH:a ~= 0LE:0 <= a0 / a == 0a:tH:a ~= 0LT:0 < - a0 / a == 0a:tH:a ~= 0LT:0 < - a0 / a == 0a:tH:a ~= 0LT:0 < - a- (0 / a) == - 0now apply div_0_l. Qed.a:tH:a ~= 0LT:0 < - a0 / - a == 0forall a : t, a ~= 0 -> 0 mod a == 0intros; rewrite mod_eq, div_0_l; now nzsimpl. Qed.forall a : t, a ~= 0 -> 0 mod a == 0forall a : t, a / 1 == aforall a : t, a / 1 == aa:ta / 1 == aa:ta == a / 1a:t0 <= 0 < abs 1a:ta == 1 * a + 0now nzsimpl. Qed.a:ta == 1 * a + 0forall a : t, a mod 1 == 0forall a : t, a mod 1 == 0a:ta mod 1 == 0apply neq_sym, lt_neq; apply lt_0_1. Qed.a:t1 ~= 0forall a : t, 1 < a -> 1 / a == 0exact div_1_l. Qed.forall a : t, 1 < a -> 1 / a == 0forall a : t, 1 < a -> 1 mod a == 1exact mod_1_l. Qed.forall a : t, 1 < a -> 1 mod a == 1forall a b : t, b ~= 0 -> a * b / b == aforall a b : t, b ~= 0 -> a * b / b == aa, b:tH:b ~= 0a * b / b == aa, b:tH:b ~= 0a == a * b / ba, b:tH:b ~= 00 <= 0 < abs ba, b:tH:b ~= 0a * b == b * a + 0nzsimpl; apply mul_comm. Qed.a, b:tH:b ~= 0a * b == b * a + 0forall a b : t, b ~= 0 -> (a * b) mod b == 0forall a b : t, b ~= 0 -> (a * b) mod b == 0a, b:tH:b ~= 0(a * b) mod b == 0rewrite mul_comm; apply sub_diag. Qed.a, b:tH:b ~= 0a * b - b * a == 0a, b, q:tb ~= 0 -> a == b * q -> q == a / ba, b, q:tb ~= 0 -> a == b * q -> q == a / ba, b, q:tHb:b ~= 0H:a == b * qq == a / ba, b, q:tHb:b ~= 0H:a == b * qq == q * b / bnow apply div_mul. Qed.a, b, q:tHb:b ~= 0H:a == b * qq * b / b == q
A modulo cannot grow beyond its starting point.
forall a b : t, 0 <= a -> b ~= 0 -> a mod b <= aforall a b : t, 0 <= a -> b ~= 0 -> a mod b <= aa, b:tH:0 <= aH0:b ~= 0a mod b <= aa, b:tH:0 <= aH0:b ~= 0LE:0 <= ba mod b <= aa, b:tH:0 <= aH0:b ~= 0LT:0 < - ba mod b <= aa, b:tH:0 <= aH0:b ~= 0LT:0 < - ba mod b <= aapply mod_le; order. Qed.a, b:tH:0 <= aH0:b ~= 0LT:0 < - ba mod - b <= aforall a b : t, 0 <= a -> 0 < b -> 0 <= a / bexact div_pos. Qed.forall a b : t, 0 <= a -> 0 < b -> 0 <= a / bforall a b : t, 0 < b <= a -> 0 < a / bexact div_str_pos. Qed.forall a b : t, 0 < b <= a -> 0 < a / bforall a b : t, b ~= 0 -> a / b == 0 <-> 0 <= a < abs bforall a b : t, b ~= 0 -> a / b == 0 <-> 0 <= a < abs ba, b:tHb:b ~= 0a / b == 0 <-> 0 <= a < abs ba, b:tHb:b ~= 0a / b == 0 -> 0 <= a < abs ba, b:tHb:b ~= 00 <= a < abs b -> a / b == 0a, b:tHb:b ~= 0EQ:a / b == 00 <= a < abs ba, b:tHb:b ~= 00 <= a < abs b -> a / b == 0a, b:tHb:b ~= 0EQ:a / b == 00 <= a mod b < abs ba, b:tHb:b ~= 00 <= a < abs b -> a / b == 0a, b:tHb:b ~= 00 <= a < abs b -> a / b == 0a, b:tHb:b ~= 0H:0 <= a < abs ba / b == 0a, b:tHb:b ~= 0H:0 <= a < abs bLE:0 <= ba / b == 0a, b:tHb:b ~= 0H:0 <= a < abs bLT:0 < - ba / b == 0a, b:tHb:b ~= 0H:0 <= a < abs bLE:0 <= b0 <= a < ba, b:tHb:b ~= 0H:0 <= a < abs bLT:0 < - ba / b == 0a, b:tHb:b ~= 0H:0 <= a < abs bLT:0 < - ba / b == 0a, b:tHb:b ~= 0H:0 <= a < abs bLT:0 < - ba / - b == 0a, b:tHb:b ~= 0H:0 <= a < abs bLT:0 < - b0 <= a < - btrivial. Qed.a, b:tHb:b ~= 0H:0 <= a < abs bLT:0 < - b0 <= a < abs bforall a b : t, b ~= 0 -> a mod b == a <-> 0 <= a < abs bforall a b : t, b ~= 0 -> a mod b == a <-> 0 <= a < abs ba, b:tH:b ~= 0a mod b == a <-> 0 <= a < abs ba, b:tH:b ~= 0a - b * (a / b) == a <-> a / b == 0a, b:tH:b ~= 0a + 0 == a + b * (a / b) <-> a / b == 0a, b:tH:b ~= 00 == b * (a / b) <-> a / b == 0tauto. Qed.a, b:tH:b ~= 0b == 0 \/ a / b == 0 <-> a / b == 0
As soon as the divisor is strictly greater than 1,
the division is strictly decreasing.
forall a b : t, 0 < a -> 1 < b -> a / b < aexact div_lt. Qed.forall a b : t, 0 < a -> 1 < b -> a / b < a
le is compatible with a positive division.
forall a b c : t, 0 < c -> a <= b -> a / c <= b / cforall a b c : t, 0 < c -> a <= b -> a / c <= b / ca, b, c:tHc:0 < cHab:a <= ba / c <= b / ca, b, c:tHc:0 < cHab:a < b \/ a == ba / c <= b / ca, b, c:tHc:0 < cLT:a < ba / c <= b / ca, b, c:tHc:0 < cLT:a < ba / c < S (b / c)a, b, c:tHc:0 < cLT:a < bc * (a / c) < c * S (b / c)a, b, c:tHc:0 < cLT:a < bc * (a / c) < c * (b / c) + ca, b, c:tHc:0 < cLT:a < bc * (a / c) + a mod c < c * (b / c) + c + a mod ca, b, c:tHc:0 < cLT:a < ba < c * (b / c) + c + a mod ca, b, c:tHc:0 < cLT:a < bb <= c * (b / c) + c + a mod ca, b, c:tHc:0 < cLT:a < bc * (b / c) + b mod c <= c * (b / c) + c + a mod ca, b, c:tHc:0 < cLT:a < bb mod c <= c + a mod ca, b, c:tHc:0 < cLT:a < bb mod c <= c + 0a, b, c:tHc:0 < cLT:a < bc + 0 <= c + a mod ca, b, c:tHc:0 < cLT:a < bH:0 <= b mod cH0:b mod c < abs cb mod c <= ca, b, c:tHc:0 < cLT:a < bc + 0 <= c + a mod ca, b, c:tHc:0 < cLT:a < bc + 0 <= c + a mod cdestruct (mod_always_pos a c); order. Qed.a, b, c:tHc:0 < cLT:a < b0 <= a mod c
In this convention, div performs Rounding-Toward-Bottom
when divisor is positive, and Rounding-Toward-Top otherwise.
Since we cannot speak of rational values here, we express this
fact by multiplying back by b, and this leads to a nice
unique statement.
forall a b : t, b ~= 0 -> b * (a / b) <= aforall a b : t, b ~= 0 -> b * (a / b) <= aa, b:tH:b ~= 0b * (a / b) <= aa, b:tH:b ~= 0b * (a / b) <= b * (a / b) + a mod ba, b:tH:b ~= 0b * (a / b) + 0 <= b * (a / b) + a mod bnow destruct (mod_always_pos a b). Qed.a, b:tH:b ~= 00 <= a mod b
Giving a reversed bound is slightly more complex
forall a b : t, 0 < b -> a < b * S (a / b)forall a b : t, 0 < b -> a < b * S (a / b)a, b:tH:0 < ba < b * S (a / b)a, b:tH:0 < ba < b * (a / b) + ba, b:tH:0 < bb * (a / b) + a mod b < b * (a / b) + ba, b:tH:0 < ba mod b < ba, b:tH:0 < bb ~= 0a, b:tH:0 < bH0:0 <= a mod bH1:a mod b < abs ba mod b < brewrite abs_eq in *; order. Qed.a, b:tH:0 < bH0:0 <= a mod bH1:a mod b < abs ba mod b < bforall a b : t, b < 0 -> a < b * P (a / b)forall a b : t, b < 0 -> a < b * P (a / b)a, b:tHb:b < 0a < b * P (a / b)a, b:tHb:b < 0a < b * (a / b) + - ba, b:tHb:b < 0b * (a / b) + a mod b < b * (a / b) + - ba, b:tHb:b < 0a mod b < - ba, b:tHb:b < 0b ~= 0a, b:tHb:b < 0H:0 <= a mod bH0:a mod b < abs ba mod b < - ba, b:tHb:b < 0H:0 <= a mod bH0:a mod b < abs ba mod b < - brewrite abs_neq' in *; order. Qed.a, b:tHb:0 < - bH:0 <= a mod bH0:a mod b < abs ba mod b < - b
NB: The three previous properties could be used as
specifications for div.
Inequality mul_div_le is exact iff the modulo is zero.
forall a b : t, b ~= 0 -> a == b * (a / b) <-> a mod b == 0forall a b : t, b ~= 0 -> a == b * (a / b) <-> a mod b == 0a, b:tH:b ~= 0a == b * (a / b) <-> a mod b == 0a, b:tH:b ~= 0b * (a / b) + a mod b == b * (a / b) <-> a mod b == 0apply add_cancel_l. Qed.a, b:tH:b ~= 0b * (a / b) + a mod b == b * (a / b) + 0 <-> a mod b == 0
Some additional inequalities about div.
forall a b q : t, 0 < b -> a < b * q -> a / b < qforall a b q : t, 0 < b -> a < b * q -> a / b < qa, b, q:tH:0 < bH0:a < b * qa / b < qa, b, q:tH:0 < bH0:a < b * qb * (a / b) < b * qapply mul_div_le; order. Qed.a, b, q:tH:0 < bH0:a < b * qb * (a / b) <= aforall a b q : t, 0 < b -> a <= b * q -> a / b <= qforall a b q : t, 0 < b -> a <= b * q -> a / b <= qa, b, q:tH:0 < bH0:a <= b * qa / b <= qa, b, q:tH:0 < bH0:a <= b * qa / b <= q * b / bnow rewrite mul_comm. Qed.a, b, q:tH:0 < bH0:a <= b * qa <= q * bforall a b q : t, 0 < b -> b * q <= a -> q <= a / bforall a b q : t, 0 < b -> b * q <= a -> q <= a / ba, b, q:tH:0 < bH0:b * q <= aq <= a / ba, b, q:tH:0 < bH0:b * q <= aq * b / b <= a / bnow rewrite mul_comm. Qed.a, b, q:tH:0 < bH0:b * q <= aq * b <= a
A division respects opposite monotonicity for the divisor
forall p q r : t, 0 <= p -> 0 < q <= r -> p / r <= p / qexact div_le_compat_l. Qed.forall p q r : t, 0 <= p -> 0 < q <= r -> p / r <= p / q
forall a b c : t, c ~= 0 -> (a + b * c) mod c == a mod cforall a b c : t, c ~= 0 -> (a + b * c) mod c == a mod ca, b, c:tH:c ~= 0(a + b * c) mod c == a mod ca, b, c:tH:c ~= 0a mod c == (a + b * c) mod ca, b, c:tH:c ~= 00 <= a mod c < abs ca, b, c:tH:c ~= 0a + b * c == c * (a / c + b) + a mod ca, b, c:tH:c ~= 0a + b * c == c * (a / c + b) + a mod cnow rewrite mul_comm. Qed.a, b, c:tH:c ~= 0a + b * c == a + c * bforall a b c : t, c ~= 0 -> (a + b * c) / c == a / c + bforall a b c : t, c ~= 0 -> (a + b * c) / c == a / c + ba, b, c:tH:c ~= 0(a + b * c) / c == a / c + ba, b, c:tH:c ~= 0c * ((a + b * c) / c) == c * (a / c + b)a, b, c:tH:c ~= 0c * ((a + b * c) / c) + (a + b * c) mod c == c * (a / c + b) + (a + b * c) mod ca, b, c:tH:c ~= 0a + b * c == c * (a / c + b) + a mod cnow rewrite mul_comm. Qed.a, b, c:tH:c ~= 0a + b * c == a + c * bforall a b c : t, b ~= 0 -> (a * b + c) / b == a + c / bforall a b c : t, b ~= 0 -> (a * b + c) / b == a + c / ba, b, c:tb ~= 0 -> (a * b + c) / b == a + c / bnow apply div_add. Qed.a, b, c:tb ~= 0 -> (c + a * b) / b == c / b + a
Cancellations.
With the current convention, the following isn't always true
when c<0: -3*-1 / -2*-1 = 3/2 = 1 while -3/-2 = 2
forall a b c : t, b ~= 0 -> 0 < c -> a * c / (b * c) == a / bforall a b c : t, b ~= 0 -> 0 < c -> a * c / (b * c) == a / ba, b, c:tH:b ~= 0H0:0 < ca * c / (b * c) == a / ba, b, c:tH:b ~= 0H0:0 < ca / b == a * c / (b * c)(* ineqs *)a, b, c:tH:b ~= 0H0:0 < c0 <= a mod b * c < abs (b * c)a, b, c:tH:b ~= 0H0:0 < ca * c == b * c * (a / b) + a mod b * ca, b, c:tH:b ~= 0H0:0 < c0 <= a mod b * c < abs b * ca, b, c:tH:b ~= 0H0:0 < ca * c == b * c * (a / b) + a mod b * ca, b, c:tH:b ~= 0H0:0 < c0 <= a mod b < abs ba, b, c:tH:b ~= 0H0:0 < ca * c == b * c * (a / b) + a mod b * c(* equation *)a, b, c:tH:b ~= 0H0:0 < ca * c == b * c * (a / b) + a mod b * ca, b, c:tH:b ~= 0H0:0 < c(b * (a / b) + a mod b) * c == b * c * (a / b) + a mod b * ca, b, c:tH:b ~= 0H0:0 < cb * (a / b) * c + a mod b * c == b * c * (a / b) + a mod b * ca, b, c:tH:b ~= 0H0:0 < cb * (a / b) * c == b * c * (a / b)now rewrite (mul_comm c). Qed.a, b, c:tH:b ~= 0H0:0 < cb * (a / b * c) == b * (c * (a / b))forall a b c : t, b ~= 0 -> 0 < c -> c * a / (c * b) == a / bforall a b c : t, b ~= 0 -> 0 < c -> c * a / (c * b) == a / brewrite !(mul_comm c); now apply div_mul_cancel_r. Qed.a, b, c:tH:b ~= 0H0:0 < cc * a / (c * b) == a / bforall a b c : t, b ~= 0 -> 0 < c -> (c * a) mod (c * b) == c * (a mod b)forall a b c : t, b ~= 0 -> 0 < c -> (c * a) mod (c * b) == c * (a mod b)a, b, c:tH:b ~= 0H0:0 < c(c * a) mod (c * b) == c * (a mod b)a, b, c:tH:b ~= 0H0:0 < cc * b * (c * a / (c * b)) + (c * a) mod (c * b) == c * b * (c * a / (c * b)) + c * (a mod b)a, b, c:tH:b ~= 0H0:0 < cc * a == c * b * (c * a / (c * b)) + c * (a mod b)a, b, c:tH:b ~= 0H0:0 < cc * b ~= 0a, b, c:tH:b ~= 0H0:0 < cc * a == c * b * (a / b) + c * (a mod b)a, b, c:tH:b ~= 0H0:0 < cc * b ~= 0a, b, c:tH:b ~= 0H0:0 < ca == b * (a / b) + a mod ba, b, c:tH:b ~= 0H0:0 < cc * b ~= 0rewrite <- neq_mul_0; intuition; order. Qed.a, b, c:tH:b ~= 0H0:0 < cc * b ~= 0forall a b c : t, b ~= 0 -> 0 < c -> (a * c) mod (b * c) == a mod b * cforall a b c : t, b ~= 0 -> 0 < c -> (a * c) mod (b * c) == a mod b * crewrite !(mul_comm _ c); now rewrite mul_mod_distr_l. Qed.a, b, c:tH:b ~= 0H0:0 < c(a * c) mod (b * c) == a mod b * c
Operations modulo.
forall a n : t, n ~= 0 -> (a mod n) mod n == a mod nforall a n : t, n ~= 0 -> (a mod n) mod n == a mod na, n:tH:n ~= 0(a mod n) mod n == a mod nnow apply mod_always_pos. Qed.a, n:tH:n ~= 00 <= a mod n < abs nforall a b n : t, n ~= 0 -> (a mod n * b) mod n == (a * b) mod nforall a b n : t, n ~= 0 -> (a mod n * b) mod n == (a * b) mod na, b, n:tHn:n ~= 0(a mod n * b) mod n == (a * b) mod na, b, n:tHn:n ~= 0(a * b) mod n == (a mod n * b) mod na, b, n:tHn:n ~= 0((n * (a / n) + a mod n) * b) mod n == (a mod n * b) mod na, b, n:tHn:n ~= 0(b * (a mod n + a / n * n)) mod n == (a mod n * b) mod na, b, n:tHn:n ~= 0(b * (a mod n) + b * (a / n) * n) mod n == (a mod n * b) mod nnow rewrite mul_comm. Qed.a, b, n:tHn:n ~= 0(b * (a mod n)) mod n == (a mod n * b) mod nforall a b n : t, n ~= 0 -> (a * (b mod n)) mod n == (a * b) mod nforall a b n : t, n ~= 0 -> (a * (b mod n)) mod n == (a * b) mod na, b, n:tH:n ~= 0(a * (b mod n)) mod n == (a * b) mod nnow apply mul_mod_idemp_l. Qed.a, b, n:tH:n ~= 0(b mod n * a) mod n == (b * a) mod nforall a b n : t, n ~= 0 -> (a * b) mod n == (a mod n * (b mod n)) mod nforall a b n : t, n ~= 0 -> (a * b) mod n == (a mod n * (b mod n)) mod nnow rewrite mul_mod_idemp_l, mul_mod_idemp_r. Qed.a, b, n:tH:n ~= 0(a * b) mod n == (a mod n * (b mod n)) mod nforall a b n : t, n ~= 0 -> (a mod n + b) mod n == (a + b) mod nforall a b n : t, n ~= 0 -> (a mod n + b) mod n == (a + b) mod na, b, n:tHn:n ~= 0(a mod n + b) mod n == (a + b) mod na, b, n:tHn:n ~= 0(a + b) mod n == (a mod n + b) mod na, b, n:tHn:n ~= 0(n * (a / n) + a mod n + b) mod n == (a mod n + b) mod nnow rewrite mod_add. Qed.a, b, n:tHn:n ~= 0(a mod n + b + a / n * n) mod n == (a mod n + b) mod nforall a b n : t, n ~= 0 -> (a + b mod n) mod n == (a + b) mod nforall a b n : t, n ~= 0 -> (a + b mod n) mod n == (a + b) mod na, b, n:tH:n ~= 0(a + b mod n) mod n == (a + b) mod nnow apply add_mod_idemp_l. Qed.a, b, n:tH:n ~= 0(b mod n + a) mod n == (b + a) mod nforall a b n : t, n ~= 0 -> (a + b) mod n == (a mod n + b mod n) mod nforall a b n : t, n ~= 0 -> (a + b) mod n == (a mod n + b mod n) mod nnow rewrite add_mod_idemp_l, add_mod_idemp_r. Qed.a, b, n:tH:n ~= 0(a + b) mod n == (a mod n + b mod n) mod n
With the current convention, the following result isn't always
true with a negative intermediate divisor. For instance
3/(-2)/(-2) = 1 ≠ 0 = 3 / (-2*-2) and
3/(-2)/2 = -1 ≠ 0 = 3 / (-2*2) .
forall a b c : t, 0 < b -> c ~= 0 -> a / b / c == a / (b * c)forall a b c : t, 0 < b -> c ~= 0 -> a / b / c == a / (b * c)a, b, c:tHb:0 < bHc:c ~= 0a / b / c == a / (b * c)(* begin 0<= ... <abs(b*c) *)a, b, c:tHb:0 < bHc:c ~= 00 <= b * ((a / b) mod c) + a mod b < abs (b * c)a, b, c:tHb:0 < bHc:c ~= 0a == b * c * (a / b / c) + (b * ((a / b) mod c) + a mod b)a, b, c:tHb:0 < bHc:c ~= 00 <= b * ((a / b) mod c) + a mod b < abs b * abs ca, b, c:tHb:0 < bHc:c ~= 0a == b * c * (a / b / c) + (b * ((a / b) mod c) + a mod b)a, b, c:tHb:0 < bHc:c ~= 0H:0 <= (a / b) mod cH0:(a / b) mod c < abs cH1:0 <= a mod bH2:a mod b < abs b0 <= b * ((a / b) mod c) + a mod b < abs b * abs ca, b, c:tHb:0 < bHc:c ~= 0a == b * c * (a / b / c) + (b * ((a / b) mod c) + a mod b)a, b, c:tHb:0 < bHc:c ~= 0H:0 <= (a / b) mod cH0:(a / b) mod c < abs cH1:0 <= a mod bH2:a mod b < abs b0 <= b * ((a / b) mod c) + a mod ba, b, c:tHb:0 < bHc:c ~= 0H:0 <= (a / b) mod cH0:(a / b) mod c < abs cH1:0 <= a mod bH2:a mod b < abs bb * ((a / b) mod c) + a mod b < abs b * abs ca, b, c:tHb:0 < bHc:c ~= 0a == b * c * (a / b / c) + (b * ((a / b) mod c) + a mod b)a, b, c:tHb:0 < bHc:c ~= 0H:0 <= (a / b) mod cH0:(a / b) mod c < abs cH1:0 <= a mod bH2:a mod b < abs b0 <= b * ((a / b) mod c)a, b, c:tHb:0 < bHc:c ~= 0H:0 <= (a / b) mod cH0:(a / b) mod c < abs cH1:0 <= a mod bH2:a mod b < abs bb * ((a / b) mod c) + a mod b < abs b * abs ca, b, c:tHb:0 < bHc:c ~= 0a == b * c * (a / b / c) + (b * ((a / b) mod c) + a mod b)a, b, c:tHb:0 < bHc:c ~= 0H:0 <= (a / b) mod cH0:(a / b) mod c < abs cH1:0 <= a mod bH2:a mod b < abs bb * ((a / b) mod c) + a mod b < abs b * abs ca, b, c:tHb:0 < bHc:c ~= 0a == b * c * (a / b / c) + (b * ((a / b) mod c) + a mod b)a, b, c:tHb:0 < bHc:c ~= 0H:0 <= (a / b) mod cH0:(a / b) mod c < abs cH1:0 <= a mod bH2:a mod b < abs bb * ((a / b) mod c) + a mod b < b * ((a / b) mod c) + abs ba, b, c:tHb:0 < bHc:c ~= 0H:0 <= (a / b) mod cH0:(a / b) mod c < abs cH1:0 <= a mod bH2:a mod b < abs bb * ((a / b) mod c) + abs b <= abs b * abs ca, b, c:tHb:0 < bHc:c ~= 0a == b * c * (a / b / c) + (b * ((a / b) mod c) + a mod b)a, b, c:tHb:0 < bHc:c ~= 0H:0 <= (a / b) mod cH0:(a / b) mod c < abs cH1:0 <= a mod bH2:a mod b < abs bb * ((a / b) mod c) + abs b <= abs b * abs ca, b, c:tHb:0 < bHc:c ~= 0a == b * c * (a / b / c) + (b * ((a / b) mod c) + a mod b)a, b, c:tHb:0 < bHc:c ~= 0H:0 <= (a / b) mod cH0:(a / b) mod c < abs cH1:0 <= a mod bH2:a mod b < abs bb * ((a / b) mod c) + b <= b * abs ca, b, c:tHb:0 < bHc:c ~= 0a == b * c * (a / b / c) + (b * ((a / b) mod c) + a mod b)(* end 0<= ... < abs(b*c) *)a, b, c:tHb:0 < bHc:c ~= 0a == b * c * (a / b / c) + (b * ((a / b) mod c) + a mod b)a, b, c:tHb:0 < bHc:c ~= 0b * (a / b) + a mod b == b * c * (a / b / c) + (b * ((a / b) mod c) + a mod b)a, b, c:tHb:0 < bHc:c ~= 0b * (a / b) == b * c * (a / b / c) + b * ((a / b) mod c)apply div_mod; order. Qed.a, b, c:tHb:0 < bHc:c ~= 0a / b == c * (a / b / c) + (a / b) mod c
Similarly, the following result doesn't always hold when b<0.
For instance 3 mod (-2*-2)) = 3 while
3 mod (-2) + (-2)*((3/-2) mod -2) = -1.
forall a b c : t, 0 < b -> c ~= 0 -> a mod (b * c) == a mod b + b * ((a / b) mod c)forall a b c : t, 0 < b -> c ~= 0 -> a mod (b * c) == a mod b + b * ((a / b) mod c)a, b, c:tHb:0 < bHc:c ~= 0a mod (b * c) == a mod b + b * ((a / b) mod c)a, b, c:tHb:0 < bHc:c ~= 0b * c * (a / (b * c)) + a mod (b * c) == b * c * (a / (b * c)) + (a mod b + b * ((a / b) mod c))a, b, c:tHb:0 < bHc:c ~= 0a == b * c * (a / (b * c)) + (a mod b + b * ((a / b) mod c))a, b, c:tHb:0 < bHc:c ~= 0a == b * c * (a / b / c) + (a mod b + b * ((a / b) mod c))a, b, c:tHb:0 < bHc:c ~= 0a == b * (c * (a / b / c) + (a / b) mod c) + a mod bapply div_mod; order. Qed.a, b, c:tHb:0 < bHc:c ~= 0a == b * (a / b) + a mod bforall a b : t, b ~= 0 -> a mod b / b == 0forall a b : t, b ~= 0 -> a mod b / b == 0a, b:tHb:b ~= 0a mod b / b == 0auto using mod_always_pos. Qed.a, b:tHb:b ~= 00 <= a mod b < abs b
A last inequality:
forall a b c : t, 0 <= a -> 0 < b -> 0 <= c -> c * (a / b) <= c * a / bexact div_mul_le. Qed.forall a b c : t, 0 <= a -> 0 < b -> 0 <= c -> c * (a / b) <= c * a / b
mod is related to divisibility
forall a b : t, b ~= 0 -> a mod b == 0 <-> (b | a)forall a b : t, b ~= 0 -> a mod b == 0 <-> (b | a)a, b:tHb:b ~= 0a mod b == 0 <-> (b | a)a, b:tHb:b ~= 0a mod b == 0 -> (b | a)a, b:tHb:b ~= 0(b | a) -> a mod b == 0a, b:tHb:b ~= 0Hab:a mod b == 0(b | a)a, b:tHb:b ~= 0(b | a) -> a mod b == 0a, b:tHb:b ~= 0Hab:a mod b == 0a == a / b * ba, b:tHb:b ~= 0(b | a) -> a mod b == 0a, b:tHb:b ~= 0Hab:a mod b == 0a == b * (a / b)a, b:tHb:b ~= 0(b | a) -> a mod b == 0a, b:tHb:b ~= 0Hab:a mod b == 0b * (a / b) + a mod b == b * (a / b)a, b:tHb:b ~= 0(b | a) -> a mod b == 0a, b:tHb:b ~= 0(b | a) -> a mod b == 0a, b:tHb:b ~= 0c:tHc:a == c * ba mod b == 0now apply mod_mul. Qed. End ZEuclidProp.a, b:tHb:b ~= 0c:tHc:a == c * b(c * b) mod b == 0