# HG changeset patch # User haftmann # Date 1664460220 0 # Node ID 64e8d4afcf1075fa2601dda97448c1ee4eb244ae # Parent be91db94e526672ed3a3ae0c098d7a99864a67ef moved relevant theorems from theory Divides to theory Euclidean_Division diff -r be91db94e526 -r 64e8d4afcf10 src/HOL/Divides.thy --- a/src/HOL/Divides.thy Thu Sep 29 14:15:01 2022 +0200 +++ b/src/HOL/Divides.thy Thu Sep 29 14:03:40 2022 +0000 @@ -1,537 +1,12 @@ (* Title: HOL/Divides.thy - Author: Lawrence C Paulson, Cambridge University Computer Laboratory - Copyright 1999 University of Cambridge *) -section \More on quotient and remainder\ +section \Lemmas of doubtful value\ theory Divides imports Parity begin -subsection \More on division\ - -subsubsection \Monotonicity in the First Argument (Dividend)\ - -lemma unique_quotient_lemma: - assumes "b * q' + r' \ b * q + r" "0 \ r'" "r' < b" "r < b" shows "q' \ (q::int)" -proof - - have "r' + b * (q'-q) \ r" - using assms by (simp add: right_diff_distrib) - moreover have "0 < b * (1 + q - q') " - using assms by (simp add: right_diff_distrib distrib_left) - moreover have "b * q' < b * (1 + q)" - using assms by (simp add: right_diff_distrib distrib_left) - ultimately show ?thesis - using assms by (simp add: mult_less_cancel_left) -qed - -lemma unique_quotient_lemma_neg: - "b * q' + r' \ b*q + r \ r \ 0 \ b < r \ b < r' \ q \ (q'::int)" - using unique_quotient_lemma[where b = "-b" and r = "-r'" and r'="-r"] by auto - -lemma zdiv_mono1: - \a div b \ a' div b\ - if \a \ a'\ \0 < b\ - for a b b' :: int -proof (rule unique_quotient_lemma) - show "b * (a div b) + a mod b \ b * (a' div b) + a' mod b" - using \a \ a'\ by auto -qed (use that in auto) - -lemma zdiv_mono1_neg: - fixes b::int - assumes "a \ a'" "b < 0" shows "a' div b \ a div b" -proof (rule unique_quotient_lemma_neg) - show "b * (a div b) + a mod b \ b * (a' div b) + a' mod b" - using assms(1) by auto -qed (use assms in auto) - - -subsubsection \Monotonicity in the Second Argument (Divisor)\ - -lemma q_pos_lemma: - fixes q'::int - assumes "0 \ b'*q' + r'" "r' < b'" "0 < b'" - shows "0 \ q'" -proof - - have "0 < b'* (q' + 1)" - using assms by (simp add: distrib_left) - with assms show ?thesis - by (simp add: zero_less_mult_iff) -qed - -lemma zdiv_mono2_lemma: - fixes q'::int - assumes eq: "b*q + r = b'*q' + r'" and le: "0 \ b'*q' + r'" and "r' < b'" "0 \ r" "0 < b'" "b' \ b" - shows "q \ q'" -proof - - have "0 \ q'" - using q_pos_lemma le \r' < b'\ \0 < b'\ by blast - moreover have "b*q = r' - r + b'*q'" - using eq by linarith - ultimately have "b*q < b* (q' + 1)" - using mult_right_mono assms unfolding distrib_left by fastforce - with assms show ?thesis - by (simp add: mult_less_cancel_left_pos) -qed - -lemma zdiv_mono2: - fixes a::int - assumes "0 \ a" "0 < b'" "b' \ b" shows "a div b \ a div b'" -proof (rule zdiv_mono2_lemma) - have "b \ 0" - using assms by linarith - show "b * (a div b) + a mod b = b' * (a div b') + a mod b'" - by simp -qed (use assms in auto) - -lemma zdiv_mono2_neg_lemma: - fixes q'::int - assumes "b*q + r = b'*q' + r'" "b'*q' + r' < 0" "r < b" "0 \ r'" "0 < b'" "b' \ b" - shows "q' \ q" -proof - - have "b'*q' < 0" - using assms by linarith - with assms have "q' \ 0" - by (simp add: mult_less_0_iff) - have "b*q' \ b'*q'" - by (simp add: \q' \ 0\ assms(6) mult_right_mono_neg) - then have "b*q' < b* (q + 1)" - using assms by (simp add: distrib_left) - then show ?thesis - using assms by (simp add: mult_less_cancel_left) -qed - -lemma zdiv_mono2_neg: - fixes a::int - assumes "a < 0" "0 < b'" "b' \ b" shows "a div b' \ a div b" -proof (rule zdiv_mono2_neg_lemma) - have "b \ 0" - using assms by linarith - show "b * (a div b) + a mod b = b' * (a div b') + a mod b'" - by simp -qed (use assms in auto) - - -subsubsection \Quotients of Signs\ - -lemma div_eq_minus1: "0 < b \ - 1 div b = - 1" for b :: int - by (simp add: divide_int_def) - -lemma zmod_minus1: "0 < b \ - 1 mod b = b - 1" for b :: int - by (auto simp add: modulo_int_def) - -lemma minus_mod_int_eq: - \- k mod l = l - 1 - (k - 1) mod l\ if \l \ 0\ for k l :: int -proof (cases \l = 0\) - case True - then show ?thesis - by simp -next - case False - with that have \l > 0\ - by simp - then show ?thesis - proof (cases \l dvd k\) - case True - then obtain j where \k = l * j\ .. - moreover have \(l * j mod l - 1) mod l = l - 1\ - using \l > 0\ by (simp add: zmod_minus1) - then have \(l * j - 1) mod l = l - 1\ - by (simp only: mod_simps) - ultimately show ?thesis - by simp - next - case False - moreover have 1: \0 < k mod l\ - using \0 < l\ False le_less by fastforce - moreover have 2: \k mod l < 1 + l\ - using \0 < l\ pos_mod_bound[of l k] by linarith - from 1 2 \l > 0\ have \(k mod l - 1) mod l = k mod l - 1\ - by (simp add: zmod_trivial_iff) - ultimately show ?thesis - by (simp only: zmod_zminus1_eq_if) - (simp add: mod_eq_0_iff_dvd algebra_simps mod_simps) - qed -qed - -lemma div_neg_pos_less0: - fixes a::int - assumes "a < 0" "0 < b" - shows "a div b < 0" -proof - - have "a div b \ - 1 div b" - using zdiv_mono1 assms by auto - also have "... \ -1" - by (simp add: assms(2) div_eq_minus1) - finally show ?thesis - by force -qed - -lemma div_nonneg_neg_le0: "[| (0::int) \ a; b < 0 |] ==> a div b \ 0" - by (drule zdiv_mono1_neg, auto) - -lemma div_nonpos_pos_le0: "[| (a::int) \ 0; b > 0 |] ==> a div b \ 0" - by (drule zdiv_mono1, auto) - -text\Now for some equivalences of the form \a div b >=< 0 \ \\ -conditional upon the sign of \a\ or \b\. There are many more. -They should all be simp rules unless that causes too much search.\ - -lemma pos_imp_zdiv_nonneg_iff: - fixes a::int - assumes "0 < b" - shows "(0 \ a div b) = (0 \ a)" -proof - show "0 \ a div b \ 0 \ a" - using assms - by (simp add: linorder_not_less [symmetric]) (blast intro: div_neg_pos_less0) -next - assume "0 \ a" - then have "0 div b \ a div b" - using zdiv_mono1 assms by blast - then show "0 \ a div b" - by auto -qed - -lemma pos_imp_zdiv_pos_iff: - "0 0 < (i::int) div k \ k \ i" - using pos_imp_zdiv_nonneg_iff[of k i] zdiv_eq_0_iff[of i k] by arith - -lemma neg_imp_zdiv_nonneg_iff: - fixes a::int - assumes "b < 0" - shows "(0 \ a div b) = (a \ 0)" - using assms by (simp add: div_minus_minus [of a, symmetric] pos_imp_zdiv_nonneg_iff del: div_minus_minus) - -(*But not (a div b \ 0 iff a\0); consider a=1, b=2 when a div b = 0.*) -lemma pos_imp_zdiv_neg_iff: "(0::int) < b ==> (a div b < 0) = (a < 0)" - by (simp add: linorder_not_le [symmetric] pos_imp_zdiv_nonneg_iff) - -(*Again the law fails for \: consider a = -1, b = -2 when a div b = 0*) -lemma neg_imp_zdiv_neg_iff: "b < (0::int) ==> (a div b < 0) = (0 < a)" - by (simp add: linorder_not_le [symmetric] neg_imp_zdiv_nonneg_iff) - -lemma nonneg1_imp_zdiv_pos_iff: - fixes a::int - assumes "0 \ a" - shows "a div b > 0 \ a \ b \ b>0" -proof - - have "0 < a div b \ b \ a" - using div_pos_pos_trivial[of a b] assms by arith - moreover have "0 < a div b \ b > 0" - using assms div_nonneg_neg_le0[of a b] by(cases "b=0"; force) - moreover have "b \ a \ 0 < b \ 0 < a div b" - using int_one_le_iff_zero_less[of "a div b"] zdiv_mono1[of b a b] by simp - ultimately show ?thesis - by blast -qed - -lemma zmod_le_nonneg_dividend: "(m::int) \ 0 \ m mod k \ m" - by (rule split_zmod[THEN iffD2]) (fastforce dest: q_pos_lemma intro: split_mult_pos_le) - -lemma sgn_div_eq_sgn_mult: - \sgn (k div l) = of_bool (k div l \ 0) * sgn (k * l)\ - for k l :: int -proof (cases \k div l = 0\) - case True - then show ?thesis - by simp -next - case False - have \0 \ \k\ div \l\\ - by (cases \l = 0\) (simp_all add: pos_imp_zdiv_nonneg_iff) - then have \\k\ div \l\ \ 0 \ 0 < \k\ div \l\\ - by (simp add: less_le) - also have \\ \ \k\ \ \l\\ - using False nonneg1_imp_zdiv_pos_iff by auto - finally have *: \\k\ div \l\ \ 0 \ \l\ \ \k\\ . - show ?thesis - using \0 \ \k\ div \l\\ False - by (auto simp add: div_eq_div_abs [of k l] div_eq_sgn_abs [of k l] - sgn_mult sgn_1_pos sgn_1_neg sgn_eq_0_iff nonneg1_imp_zdiv_pos_iff * dest: sgn_not_eq_imp) -qed - -lemma - fixes a b q r :: int - assumes \a = b * q + r\ \0 \ r\ \r < b\ - shows int_div_pos_eq: - \a div b = q\ (is ?Q) - and int_mod_pos_eq: - \a mod b = r\ (is ?R) -proof - - from assms have \(a div b, a mod b) = (q, r)\ - by (cases b q r a rule: euclidean_relation_intI) - (auto simp add: ac_simps dvd_add_left_iff sgn_1_pos le_less dest: zdvd_imp_le) - then show ?Q and ?R - by simp_all -qed - -lemma int_div_neg_eq: - \a div b = q\ if \a = b * q + r\ \r \ 0\ \b < r\ for a b q r :: int - using that int_div_pos_eq [of a \- b\ \- q\ \- r\] by simp_all - -lemma int_mod_neg_eq: - \a mod b = r\ if \a = b * q + r\ \r \ 0\ \b < r\ for a b q r :: int - using that int_div_neg_eq [of a b q r] by simp - - -subsubsection \Further properties\ - -lemma div_int_pos_iff: - "k div l \ 0 \ k = 0 \ l = 0 \ k \ 0 \ l \ 0 - \ k < 0 \ l < 0" - for k l :: int -proof (cases "k = 0 \ l = 0") - case False - then have *: "k \ 0" "l \ 0" - by auto - then have "0 \ k div l \ \ k < 0 \ 0 \ l" - by (meson neg_imp_zdiv_neg_iff not_le not_less_iff_gr_or_eq) - then show ?thesis - using * by (auto simp add: pos_imp_zdiv_nonneg_iff neg_imp_zdiv_nonneg_iff) -qed auto - -lemma mod_int_pos_iff: - "k mod l \ 0 \ l dvd k \ l = 0 \ k \ 0 \ l > 0" - for k l :: int -proof (cases "l > 0") - case False - then show ?thesis - by (simp add: dvd_eq_mod_eq_0) (use neg_mod_sign [of l k] in \auto simp add: le_less not_less\) -qed auto - -text \Simplify expressions in which div and mod combine numerical constants\ - -lemma abs_div: "(y::int) dvd x \ \x div y\ = \x\ div \y\" - unfolding dvd_def by (cases "y=0") (auto simp add: abs_mult) - -text\Suggested by Matthias Daum\ -lemma int_power_div_base: - fixes k :: int - assumes "0 < m" "0 < k" - shows "k ^ m div k = (k::int) ^ (m - Suc 0)" -proof - - have eq: "k ^ m = k ^ ((m - Suc 0) + Suc 0)" - by (simp add: assms) - show ?thesis - using assms by (simp only: power_add eq) auto -qed - -text\Suggested by Matthias Daum\ -lemma int_div_less_self: - fixes x::int - assumes "0 < x" "1 < k" - shows "x div k < x" -proof - - have "nat x div nat k < nat x" - by (simp add: assms) - with assms show ?thesis - by (simp add: nat_div_distrib [symmetric]) -qed - -lemma mod_eq_dvd_iff_nat: - "m mod q = n mod q \ q dvd m - n" if "m \ n" for m n q :: nat -proof - - have "int m mod int q = int n mod int q \ int q dvd int m - int n" - by (simp add: mod_eq_dvd_iff) - with that have "int (m mod q) = int (n mod q) \ int q dvd int (m - n)" - by (simp only: of_nat_mod of_nat_diff) - then show ?thesis - by simp -qed - -lemma mod_eq_nat1E: - fixes m n q :: nat - assumes "m mod q = n mod q" and "m \ n" - obtains s where "m = n + q * s" -proof - - from assms have "q dvd m - n" - by (simp add: mod_eq_dvd_iff_nat) - then obtain s where "m - n = q * s" .. - with \m \ n\ have "m = n + q * s" - by simp - with that show thesis . -qed - -lemma mod_eq_nat2E: - fixes m n q :: nat - assumes "m mod q = n mod q" and "n \ m" - obtains s where "n = m + q * s" - using assms mod_eq_nat1E [of n q m] by (auto simp add: ac_simps) - -lemma nat_mod_eq_lemma: - assumes "(x::nat) mod n = y mod n" and "y \ x" - shows "\q. x = y + n * q" - using assms by (rule mod_eq_nat1E) (rule exI) - -lemma nat_mod_eq_iff: "(x::nat) mod n = y mod n \ (\q1 q2. x + n * q1 = y + n * q2)" - (is "?lhs = ?rhs") -proof - assume H: "x mod n = y mod n" - {assume xy: "x \ y" - from H have th: "y mod n = x mod n" by simp - from nat_mod_eq_lemma[OF th xy] have ?rhs - proof - fix q - assume "y = x + n * q" - then have "x + n * q = y + n * 0" - by simp - then show "\q1 q2. x + n * q1 = y + n * q2" - by blast - qed} - moreover - {assume xy: "y \ x" - from nat_mod_eq_lemma[OF H xy] have ?rhs - proof - fix q - assume "x = y + n * q" - then have "x + n * 0 = y + n * q" - by simp - then show "\q1 q2. x + n * q1 = y + n * q2" - by blast - qed} - ultimately show ?rhs using linear[of x y] by blast -next - assume ?rhs then obtain q1 q2 where q12: "x + n * q1 = y + n * q2" by blast - hence "(x + n * q1) mod n = (y + n * q2) mod n" by simp - thus ?lhs by simp -qed - - -subsubsection \Computing \div\ and \mod\ with shifting\ - -lemma div_pos_geq: - fixes k l :: int - assumes "0 < l" and "l \ k" - shows "k div l = (k - l) div l + 1" -proof - - have "k = (k - l) + l" by simp - then obtain j where k: "k = j + l" .. - with assms show ?thesis by (simp add: div_add_self2) -qed - -lemma mod_pos_geq: - fixes k l :: int - assumes "0 < l" and "l \ k" - shows "k mod l = (k - l) mod l" -proof - - have "k = (k - l) + l" by simp - then obtain j where k: "k = j + l" .. - with assms show ?thesis by simp -qed - -text\computing div by shifting\ - -lemma pos_zdiv_mult_2: \(1 + 2 * b) div (2 * a) = b div a\ (is ?Q) - and pos_zmod_mult_2: \(1 + 2 * b) mod (2 * a) = 1 + 2 * (b mod a)\ (is ?R) - if \0 \ a\ for a b :: int -proof - - have \((1 + 2 * b) div (2 * a), (1 + 2 * b) mod (2 * a)) = (b div a, 1 + 2 * (b mod a))\ - proof (cases \2 * a\ \b div a\ \1 + 2 * (b mod a)\ \1 + 2 * b\ rule: euclidean_relation_intI) - case by0 - then show ?case - by simp - next - case divides - have \even (2 * a)\ - by simp - then have \even (1 + 2 * b)\ - using \2 * a dvd 1 + 2 * b\ by (rule dvd_trans) - then show ?case - by simp - next - case euclidean_relation - with that have \a > 0\ - by simp - moreover have \b mod a < a\ - using \a > 0\ by simp - then have \1 + 2 * (b mod a) < 2 * a\ - by simp - moreover have \2 * (b mod a) + a * (2 * (b div a)) = 2 * (b div a * a + b mod a)\ - by (simp only: algebra_simps) - moreover have \0 \ 2 * (b mod a)\ - using \a > 0\ by simp - ultimately show ?case - by (simp add: algebra_simps) - qed - then show ?Q and ?R - by simp_all -qed - -lemma neg_zdiv_mult_2: \(1 + 2 * b) div (2 * a) = (b + 1) div a\ (is ?Q) - and neg_zmod_mult_2: \(1 + 2 * b) mod (2 * a) = 2 * ((b + 1) mod a) - 1\ (is ?R) - if \a \ 0\ for a b :: int -proof - - have \((1 + 2 * b) div (2 * a), (1 + 2 * b) mod (2 * a)) = ((b + 1) div a, 2 * ((b + 1) mod a) - 1)\ - proof (cases \2 * a\ \(b + 1) div a\ \2 * ((b + 1) mod a) - 1\ \1 + 2 * b\ rule: euclidean_relation_intI) - case by0 - then show ?case - by simp - next - case divides - have \even (2 * a)\ - by simp - then have \even (1 + 2 * b)\ - using \2 * a dvd 1 + 2 * b\ by (rule dvd_trans) - then show ?case - by simp - next - case euclidean_relation - with that have \a < 0\ - by simp - moreover have \(b + 1) mod a > a\ - using \a < 0\ by simp - then have \2 * ((b + 1) mod a) > 1 + 2 * a\ - by simp - moreover have \((1 + b) mod a) \ 0\ - using \a < 0\ by simp - then have \2 * ((1 + b) mod a) \ 0\ - by simp - moreover have \2 * ((1 + b) mod a) + a * (2 * ((1 + b) div a)) = - 2 * ((1 + b) div a * a + (1 + b) mod a)\ - by (simp only: algebra_simps) - ultimately show ?case - by (simp add: algebra_simps sgn_mult abs_mult) - qed - then show ?Q and ?R - by simp_all -qed - -lemma zdiv_numeral_Bit0 [simp]: - "numeral (Num.Bit0 v) div numeral (Num.Bit0 w) = - numeral v div (numeral w :: int)" - unfolding numeral.simps unfolding mult_2 [symmetric] - by (rule div_mult_mult1, simp) - -lemma zdiv_numeral_Bit1 [simp]: - "numeral (Num.Bit1 v) div numeral (Num.Bit0 w) = - (numeral v div (numeral w :: int))" - unfolding numeral.simps - unfolding mult_2 [symmetric] add.commute [of _ 1] - by (rule pos_zdiv_mult_2, simp) - -lemma zmod_numeral_Bit0 [simp]: - "numeral (Num.Bit0 v) mod numeral (Num.Bit0 w) = - (2::int) * (numeral v mod numeral w)" - unfolding numeral_Bit0 [of v] numeral_Bit0 [of w] - unfolding mult_2 [symmetric] by (rule mod_mult_mult1) - -lemma zmod_numeral_Bit1 [simp]: - "numeral (Num.Bit1 v) mod numeral (Num.Bit0 w) = - 2 * (numeral v mod numeral w) + (1::int)" - unfolding numeral_Bit1 [of v] numeral_Bit0 [of w] - unfolding mult_2 [symmetric] add.commute [of _ 1] - by (rule pos_zmod_mult_2, simp) - - -code_identifier - code_module Divides \ (SML) Arith and (OCaml) Arith and (Haskell) Arith - - -subsection \Lemmas of doubtful value\ - class unique_euclidean_semiring_numeral = unique_euclidean_semiring_with_nat + linordered_semidom + assumes div_less: "0 \ a \ a < b \ a div b = 0" and mod_less: " 0 \ a \ a < b \ a mod b = a" @@ -646,4 +121,7 @@ "k div l > 0" if "k \ l" and "l > 0" for k l :: int using that by (simp add: nonneg1_imp_zdiv_pos_iff) +code_identifier + code_module Divides \ (SML) Arith and (OCaml) Arith and (Haskell) Arith + end diff -r be91db94e526 -r 64e8d4afcf10 src/HOL/Euclidean_Division.thy --- a/src/HOL/Euclidean_Division.thy Thu Sep 29 14:15:01 2022 +0200 +++ b/src/HOL/Euclidean_Division.thy Thu Sep 29 14:03:40 2022 +0000 @@ -10,11 +10,11 @@ begin subsection \Euclidean (semi)rings with explicit division and remainder\ - -class euclidean_semiring = semidom_modulo + + +class euclidean_semiring = semidom_modulo + fixes euclidean_size :: "'a \ nat" assumes size_0 [simp]: "euclidean_size 0 = 0" - assumes mod_size_less: + assumes mod_size_less: "b \ 0 \ euclidean_size (a mod b) < euclidean_size b" assumes size_mult_mono: "b \ 0 \ euclidean_size a \ euclidean_size (a * b)" @@ -46,7 +46,7 @@ lemma dvd_euclidean_size_eq_imp_dvd: assumes "a \ 0" and "euclidean_size a = euclidean_size b" - and "b dvd a" + and "b dvd a" shows "a dvd b" proof (rule ccontr) assume "\ a dvd b" @@ -83,7 +83,7 @@ "is_unit a \ euclidean_size a = euclidean_size 1" using euclidean_size_times_unit [of a 1] by simp -lemma unit_iff_euclidean_size: +lemma unit_iff_euclidean_size: "is_unit a \ euclidean_size a = euclidean_size 1 \ a \ 0" proof safe assume A: "a \ 0" and B: "euclidean_size a = euclidean_size 1" @@ -96,7 +96,7 @@ shows "euclidean_size b < euclidean_size (a * b)" proof (rule ccontr) assume "\euclidean_size b < euclidean_size (a * b)" - with size_mult_mono'[OF assms(1), of b] + with size_mult_mono'[OF assms(1), of b] have eq: "euclidean_size (a * b) = euclidean_size b" by simp have "a * b dvd b" by (rule dvd_euclidean_size_eq_imp_dvd [OF _ eq]) @@ -107,12 +107,12 @@ qed lemma dvd_imp_size_le: - assumes "a dvd b" "b \ 0" + assumes "a dvd b" "b \ 0" shows "euclidean_size a \ euclidean_size b" using assms by (auto simp: size_mult_mono) lemma dvd_proper_imp_size_less: - assumes "a dvd b" "\ b dvd a" "b \ 0" + assumes "a dvd b" "\ b dvd a" "b \ 0" shows "euclidean_size a < euclidean_size b" proof - from assms(1) obtain c where "b = a * c" by (erule dvdE) @@ -160,7 +160,7 @@ then show ?thesis by simp qed - + end @@ -450,7 +450,7 @@ text \Exponentiation respects modular equivalence.\ -lemma power_mod [mod_simps]: +lemma power_mod [mod_simps]: "((a mod b) ^ n) mod b = (a ^ n) mod b" proof (induct n) case 0 @@ -601,10 +601,10 @@ end - + subsection \Uniquely determined division\ -class unique_euclidean_semiring = euclidean_semiring + +class unique_euclidean_semiring = euclidean_semiring + assumes euclidean_size_mult: \euclidean_size (a * b) = euclidean_size a * euclidean_size b\ fixes division_segment :: \'a \ 'a\ assumes is_unit_division_segment [simp]: \is_unit (division_segment a)\ @@ -838,7 +838,7 @@ class unique_euclidean_ring = euclidean_ring + unique_euclidean_semiring begin - + subclass euclidean_ring_cancel .. end @@ -923,7 +923,7 @@ by (auto simp add: mult_div_unfold ac_simps intro: Max.boundedI) then show "m div n * n + m mod n = m" by (simp add: modulo_nat_def) - assume "n \ 0" + assume "n \ 0" show "euclidean_size (m mod n) < euclidean_size n" proof - have "m < Suc (m div n) * n" @@ -1115,7 +1115,7 @@ and mod_less [simp]: "m mod n = m" if "m < n" for m n :: nat using that by (auto intro: div_nat_eqI mod_nat_eqI) - + lemma split_div: \P (m div n) \ (n = 0 \ P 0) \ @@ -1229,7 +1229,7 @@ then have "m mod 2 = 0 \ m mod 2 = 1" by arith then show ?thesis - by auto + by auto qed lemma mod_Suc_eq [mod_simps]: @@ -1501,7 +1501,7 @@ proof assume P: "P (p - Suc m)" with \\ P 0\ have "Suc m < p" - by (auto intro: ccontr) + by (auto intro: ccontr) then have "Suc (p - Suc m) = p - m" by arith moreover from \0 < p\ have "p - Suc m < p" @@ -1540,6 +1540,72 @@ by simp qed +lemma mod_eq_dvd_iff_nat: + \m mod q = n mod q \ q dvd m - n\ (is \?P \ ?Q\) + if \m \ n\ for m n q :: nat +proof + assume ?Q + then obtain s where \m - n = q * s\ .. + with that have \m = q * s + n\ + by simp + then show ?P + by simp +next + assume ?P + have \m - n = m div q * q + m mod q - (n div q * q + n mod q)\ + by simp + also have \\ = q * (m div q - n div q)\ + by (simp only: algebra_simps \?P\) + finally show ?Q .. +qed + +lemma mod_eq_nat1E: + fixes m n q :: nat + assumes "m mod q = n mod q" and "m \ n" + obtains s where "m = n + q * s" +proof - + from assms have "q dvd m - n" + by (simp add: mod_eq_dvd_iff_nat) + then obtain s where "m - n = q * s" .. + with \m \ n\ have "m = n + q * s" + by simp + with that show thesis . +qed + +lemma mod_eq_nat2E: + fixes m n q :: nat + assumes "m mod q = n mod q" and "n \ m" + obtains s where "n = m + q * s" + using assms mod_eq_nat1E [of n q m] by (auto simp add: ac_simps) + +lemma nat_mod_eq_iff: + "(x::nat) mod n = y mod n \ (\q1 q2. x + n * q1 = y + n * q2)" (is "?lhs = ?rhs") +proof + assume H: "x mod n = y mod n" + { assume xy: "x \ y" + from H have th: "y mod n = x mod n" by simp + from mod_eq_nat1E [OF th xy] obtain q where "y = x + n * q" . + then have "x + n * q = y + n * 0" + by simp + then have "\q1 q2. x + n * q1 = y + n * q2" + by blast + } + moreover + { assume xy: "y \ x" + from mod_eq_nat1E [OF H xy] obtain q where "x = y + n * q" . + then have "x + n * 0 = y + n * q" + by simp + then have "\q1 q2. x + n * q1 = y + n * q2" + by blast + } + ultimately show ?rhs using linear[of x y] by blast +next + assume ?rhs then obtain q1 q2 where q12: "x + n * q1 = y + n * q2" by blast + hence "(x + n * q1) mod n = (y + n * q2) mod n" by simp + thus ?lhs by simp +qed + + subsection \Elementary euclidean division on \<^typ>\int\\ @@ -1577,7 +1643,7 @@ next fix k l :: int assume "l \ 0" - obtain n m and s t where k: "k = sgn s * int n" and l: "l = sgn t * int m" + obtain n m and s t where k: "k = sgn s * int n" and l: "l = sgn t * int m" by (blast intro: int_sgnE elim: that) then have "k * l = sgn (s * t) * int (n * m)" by (simp add: ac_simps sgn_mult) @@ -1586,7 +1652,7 @@ (auto simp add: algebra_simps sgn_mult sgn_1_pos sgn_0_0) next fix k l :: int - obtain n m and s t where "k = sgn s * int n" and "l = sgn t * int m" + obtain n m and s t where "k = sgn s * int n" and "l = sgn t * int m" by (blast intro: int_sgnE elim: that) then show "k div l * l + k mod l = k" by (simp add: divide_int_unfold modulo_int_unfold algebra_simps modulo_nat_def of_nat_diff) @@ -1736,7 +1802,7 @@ lemma abs_mod_less: "\k mod l\ < \l\" if "l \ 0" for k l :: int proof - - obtain n m and s t where "k = sgn s * int n" and "l = sgn t * int m" + obtain n m and s t where "k = sgn s * int n" and "l = sgn t * int m" by (blast intro: int_sgnE elim: that) with that show ?thesis by (auto simp add: modulo_int_unfold abs_mult mod_greater_zero_iff_not_dvd @@ -1747,7 +1813,7 @@ lemma sgn_mod: "sgn (k mod l) = sgn l" if "l \ 0" "\ l dvd k" for k l :: int proof - - obtain n m and s t where "k = sgn s * int n" and "l = sgn t * int m" + obtain n m and s t where "k = sgn s * int n" and "l = sgn t * int m" by (blast intro: int_sgnE elim: that) with that show ?thesis by (auto simp add: modulo_int_unfold sgn_mult mod_greater_zero_iff_not_dvd @@ -2143,52 +2209,72 @@ "k mod l = k" if "k \ 0" and "l < k" for k l :: int using that by (simp add: mod_eq_self_iff_div_eq_0) -lemma div_pos_neg_trivial: - \k div l = - 1\ if \0 < k\ and \k + l \ 0\ for k l :: int -proof (cases \l dvd k\) - case True - then obtain j where \k = l * j\ .. +lemma + div_pos_neg_trivial: \k div l = - 1\ (is ?Q) + and mod_pos_neg_trivial: \k mod l = k + l\ (is ?R) + if \0 < k\ and \k + l \ 0\ for k l :: int +proof - from that have \l < 0\ by simp - with \k = l * j\ \0 < k\ have \j \ - 1\ - by (simp add: zero_less_mult_iff) - moreover from \k + l \ 0\ \k = l * j\ have \l * (j + 1) \ 0\ - by (simp add: algebra_simps) - with \l < 0\ have \- 1 \ j\ - by (simp add: mult_le_0_iff) - ultimately have \j = - 1\ - by (rule order.antisym) - with \k = l * j\ \l < 0\ show ?thesis - by (simp add: dvd_neg_div) -next - case False - have \k + l < 0\ - proof (rule ccontr) - assume \\ k + l < 0\ - with \k + l \ 0\ have \k + l = 0\ + have \(k div l, k mod l) = (- 1, k + l)\ + proof (cases l \- 1 :: int\ \k + l\ k rule: euclidean_relation_intI) + case by0 + with \l < 0\ show ?case by simp - then have \k = - l\ + next + case divides + from \l dvd k\ obtain j where \k = l * j\ .. + with \l < 0\ \0 < k\ have \j < 0\ + by (simp add: zero_less_mult_iff) + moreover from \k + l \ 0\ \k = l * j\ have \l * (j + 1) \ 0\ + by (simp add: algebra_simps) + with \l < 0\ have \j + 1 \ 0\ + by (simp add: mult_le_0_iff) + with \j < 0\ have \j = - 1\ by simp - then have \l dvd k\ + with \k = l * j\ show ?case by simp - with \\ l dvd k\ show False .. + next + case euclidean_relation + with \k + l \ 0\ have \k + l < 0\ + by (auto simp add: less_le add_eq_0_iff) + with \0 < k\ show ?case + by simp qed - with that \\ l dvd k\ show ?thesis - by (simp add: div_eq_div_abs [of k l]) -qed - -lemma mod_pos_neg_trivial: - \k mod l = k + l\ if \0 < k\ and \k + l \ 0\ for k l :: int -proof - - from that have \k mod l = k div l * l + k mod l + l\ - by (simp add: div_pos_neg_trivial) - then show ?thesis by simp + then show ?Q and ?R + by simp_all qed text \There is neither \div_neg_pos_trivial\ nor \mod_neg_pos_trivial\ because \<^term>\0 div l = 0\ would supersede it.\ +subsubsection \More uniqueness rules\ + +lemma + fixes a b q r :: int + assumes \a = b * q + r\ \0 \ r\ \r < b\ + shows int_div_pos_eq: + \a div b = q\ (is ?Q) + and int_mod_pos_eq: + \a mod b = r\ (is ?R) +proof - + from assms have \(a div b, a mod b) = (q, r)\ + by (cases b q r a rule: euclidean_relation_intI) + (auto simp add: ac_simps dvd_add_left_iff sgn_1_pos le_less dest: zdvd_imp_le) + then show ?Q and ?R + by simp_all +qed + +lemma int_div_neg_eq: + \a div b = q\ if \a = b * q + r\ \r \ 0\ \b < r\ for a b q r :: int + using that int_div_pos_eq [of a \- b\ \- q\ \- r\] by simp_all + +lemma int_mod_neg_eq: + \a mod b = r\ if \a = b * q + r\ \r \ 0\ \b < r\ for a b q r :: int + using that int_div_neg_eq [of a b q r] by simp + + subsubsection \Laws for unary minus\ lemma zmod_zminus1_not_zero: @@ -2310,7 +2396,7 @@ from * [of \\q _. P q\] show ?div . from * [of \\_ r. Q r\] show ?mod . qed - + text \Enable (lin)arith to deal with \<^const>\divide\ and \<^const>\modulo\ when these are applied to some constant that is of the form \<^term>\numeral k\:\ @@ -2415,6 +2501,421 @@ using that by (simp add: modulo_int_def sgn_if) +subsubsection \Monotonicity in the First Argument (Dividend)\ + +lemma zdiv_mono1: + \a div b \ a' div b\ + if \a \ a'\ \0 < b\ + for a b b' :: int +proof - + from \a \ a'\ have \b * (a div b) + a mod b \ b * (a' div b) + a' mod b\ + by simp + then have \b * (a div b) \ (a' mod b - a mod b) + b * (a' div b)\ + by (simp add: algebra_simps) + moreover have \a' mod b < b + a mod b\ + by (rule less_le_trans [of _ b]) (use \0 < b\ in simp_all) + ultimately have \b * (a div b) < b * (1 + a' div b)\ + by (simp add: distrib_left) + with \0 < b\ have \a div b < 1 + a' div b\ + by (simp add: mult_less_cancel_left) + then show ?thesis + by simp +qed + +lemma zdiv_mono1_neg: + \a' div b \ a div b\ + if \a \ a'\ \b < 0\ + for a a' b :: int + using that zdiv_mono1 [of \- a'\ \- a\ \- b\] by simp + + +subsubsection \Monotonicity in the Second Argument (Divisor)\ + +lemma zdiv_mono2: + \a div b \ a div b'\ if \0 \ a\ \0 < b'\ \b' \ b\ for a b b' :: int +proof - + define q q' r r' where **: \q = a div b\ \q' = a div b'\ \r = a mod b\ \r' = a mod b'\ + then have *: \b * q + r = b' * q' + r'\ \0 \ b' * q' + r'\ + \r' < b'\ \0 \ r\ \0 < b'\ \b' \ b\ + using that by simp_all + have \0 < b' * (q' + 1)\ + using * by (simp add: distrib_left) + with * have \0 \ q'\ + by (simp add: zero_less_mult_iff) + moreover have \b * q = r' - r + b' * q'\ + using * by linarith + ultimately have \b * q < b * (q' + 1)\ + using mult_right_mono * unfolding distrib_left by fastforce + with * have \q \ q'\ + by (simp add: mult_less_cancel_left_pos) + with ** show ?thesis + by simp +qed + +lemma zdiv_mono2_neg: + \a div b' \ a div b\ if \a < 0\ \0 < b'\ \b' \ b\ for a b b' :: int +proof - + define q q' r r' where **: \q = a div b\ \q' = a div b'\ \r = a mod b\ \r' = a mod b'\ + then have *: \b * q + r = b' * q' + r'\ \b' * q' + r' < 0\ + \r < b\ \0 \ r'\ \0 < b'\ \b' \ b\ + using that by simp_all + have \b' * q' < 0\ + using * by linarith + with * have \q' \ 0\ + by (simp add: mult_less_0_iff) + have \b * q' \ b' * q'\ + by (simp add: \q' \ 0\ * mult_right_mono_neg) + then have "b * q' < b * (q + 1)" + using * by (simp add: distrib_left) + then have \q' \ q\ + using * by (simp add: mult_less_cancel_left) + then show ?thesis + by (simp add: **) +qed + + +subsubsection \Quotients of Signs\ + +lemma div_eq_minus1: + \0 < b \ - 1 div b = - 1\ for b :: int + by (simp add: divide_int_def) + +lemma zmod_minus1: + \0 < b \ - 1 mod b = b - 1\ for b :: int + by (auto simp add: modulo_int_def) + +lemma minus_mod_int_eq: + \- k mod l = l - 1 - (k - 1) mod l\ if \l \ 0\ for k l :: int +proof (cases \l = 0\) + case True + then show ?thesis + by simp +next + case False + with that have \l > 0\ + by simp + then show ?thesis + proof (cases \l dvd k\) + case True + then obtain j where \k = l * j\ .. + moreover have \(l * j mod l - 1) mod l = l - 1\ + using \l > 0\ by (simp add: zmod_minus1) + then have \(l * j - 1) mod l = l - 1\ + by (simp only: mod_simps) + ultimately show ?thesis + by simp + next + case False + moreover have 1: \0 < k mod l\ + using \0 < l\ False le_less by fastforce + moreover have 2: \k mod l < 1 + l\ + using \0 < l\ pos_mod_bound[of l k] by linarith + from 1 2 \l > 0\ have \(k mod l - 1) mod l = k mod l - 1\ + by (simp add: zmod_trivial_iff) + ultimately show ?thesis + by (simp only: zmod_zminus1_eq_if) + (simp add: mod_eq_0_iff_dvd algebra_simps mod_simps) + qed +qed + +lemma div_neg_pos_less0: + \a div b < 0\ if \a < 0\ \0 < b\ for a b :: int +proof - + have "a div b \ - 1 div b" + using zdiv_mono1 that by auto + also have "... \ -1" + by (simp add: that(2) div_eq_minus1) + finally show ?thesis + by force +qed + +lemma div_nonneg_neg_le0: + \a div b \ 0\ if \0 \ a\ \b < 0\ for a b :: int + using that by (auto dest: zdiv_mono1_neg) + +lemma div_nonpos_pos_le0: + \a div b \ 0\ if \a \ 0\ \0 < b\ for a b :: int + using that by (auto dest: zdiv_mono1) + +text\Now for some equivalences of the form \a div b >=< 0 \ \\ +conditional upon the sign of \a\ or \b\. There are many more. +They should all be simp rules unless that causes too much search.\ + +lemma pos_imp_zdiv_nonneg_iff: + \0 \ a div b \ 0 \ a\ + if \0 < b\ for a b :: int +proof + assume \0 \ a div b\ + show \0 \ a\ + proof (rule ccontr) + assume \\ 0 \ a\ + then have \a < 0\ + by simp + then have \a div b < 0\ + using that by (rule div_neg_pos_less0) + with \0 \ a div b\ show False + by simp + qed +next + assume "0 \ a" + then have "0 div b \ a div b" + using zdiv_mono1 that by blast + then show "0 \ a div b" + by auto +qed + +lemma neg_imp_zdiv_nonneg_iff: + \0 \ a div b \ a \ 0\ if \b < 0\ for a b :: int + using that pos_imp_zdiv_nonneg_iff [of \- b\ \- a\] by simp + +lemma pos_imp_zdiv_pos_iff: + \0 < (i::int) div k \ k \ i\ if \0 < k\ for i k :: int + using that pos_imp_zdiv_nonneg_iff [of k i] zdiv_eq_0_iff [of i k] by arith + +lemma pos_imp_zdiv_neg_iff: + \a div b < 0 \ a < 0\ if \0 < b\ for a b :: int + \ \But not \<^prop>\a div b \ 0 \ a \ 0\; consider \<^prop>\a = 1\, \<^prop>\b = 2\ when \<^prop>\a div b = 0\.\ + using that by (simp add: pos_imp_zdiv_nonneg_iff flip: linorder_not_le) + +lemma neg_imp_zdiv_neg_iff: + \ \But not \<^prop>\a div b \ 0 \ 0 \ a\; consider \<^prop>\a = - 1\, \<^prop>\b = - 2\ when \<^prop>\a div b = 0\.\ + \a div b < 0 \ 0 < a\ if \b < 0\ for a b :: int + using that by (simp add: neg_imp_zdiv_nonneg_iff flip: linorder_not_le) + +lemma nonneg1_imp_zdiv_pos_iff: + \a div b > 0 \ a \ b \ b > 0\ if \0 \ a\ for a b :: int +proof - + have "0 < a div b \ b \ a" + using div_pos_pos_trivial[of a b] that by arith + moreover have "0 < a div b \ b > 0" + using that div_nonneg_neg_le0[of a b] by (cases "b=0"; force) + moreover have "b \ a \ 0 < b \ 0 < a div b" + using int_one_le_iff_zero_less[of "a div b"] zdiv_mono1[of b a b] by simp + ultimately show ?thesis + by blast +qed + +lemma zmod_le_nonneg_dividend: + \m mod k \ m\ if \(m::int) \ 0\ for m k :: int +proof - + from that have \m > 0 \ m = 0\ + by auto + then show ?thesis proof + assume \m = 0\ then show ?thesis + by simp + next + assume \m > 0\ then show ?thesis + proof (cases k \0::int\ rule: linorder_cases) + case less + moreover define l where \l = - k\ + ultimately have \l > 0\ + by simp + with \m > 0\ have \int (nat m mod nat l) \ m\ + by (simp flip: le_nat_iff) + then have \int (nat m mod nat l) - l \ m\ + using \l > 0\ by simp + with \m > 0\ \l > 0\ show ?thesis + by (simp add: modulo_int_def l_def flip: le_nat_iff) + qed (simp_all add: modulo_int_def flip: le_nat_iff) + qed +qed + +lemma sgn_div_eq_sgn_mult: + \sgn (k div l) = of_bool (k div l \ 0) * sgn (k * l)\ + for k l :: int +proof (cases \k div l = 0\) + case True + then show ?thesis + by simp +next + case False + have \0 \ \k\ div \l\\ + by (cases \l = 0\) (simp_all add: pos_imp_zdiv_nonneg_iff) + then have \\k\ div \l\ \ 0 \ 0 < \k\ div \l\\ + by (simp add: less_le) + also have \\ \ \k\ \ \l\\ + using False nonneg1_imp_zdiv_pos_iff by auto + finally have *: \\k\ div \l\ \ 0 \ \l\ \ \k\\ . + show ?thesis + using \0 \ \k\ div \l\\ False + by (auto simp add: div_eq_div_abs [of k l] div_eq_sgn_abs [of k l] + sgn_mult sgn_1_pos sgn_1_neg sgn_eq_0_iff nonneg1_imp_zdiv_pos_iff * dest: sgn_not_eq_imp) +qed + + +subsubsection \Further properties\ + +lemma div_int_pos_iff: + "k div l \ 0 \ k = 0 \ l = 0 \ k \ 0 \ l \ 0 + \ k < 0 \ l < 0" + for k l :: int +proof (cases "k = 0 \ l = 0") + case False + then have *: "k \ 0" "l \ 0" + by auto + then have "0 \ k div l \ \ k < 0 \ 0 \ l" + by (meson neg_imp_zdiv_neg_iff not_le not_less_iff_gr_or_eq) + then show ?thesis + using * by (auto simp add: pos_imp_zdiv_nonneg_iff neg_imp_zdiv_nonneg_iff) +qed auto + +lemma mod_int_pos_iff: + \k mod l \ 0 \ l dvd k \ l = 0 \ k \ 0 \ l > 0\ + for k l :: int +proof (cases "l > 0") + case False + then show ?thesis + by (simp add: dvd_eq_mod_eq_0) (use neg_mod_sign [of l k] in \auto simp add: le_less not_less\) +qed auto + +lemma abs_div: + \\x div y\ = \x\ div \y\\ if \y dvd x\ for x y :: int + using that by (cases \y = 0\) (auto simp add: abs_mult) + +lemma int_power_div_base: \<^marker>\contributor \Matthias Daum\\ + \k ^ m div k = k ^ (m - Suc 0)\ if \0 < m\ \0 < k\ for k :: int + using that by (cases m) simp_all + +lemma int_div_less_self: \<^marker>\contributor \Matthias Daum\\ + \x div k < x\ if \0 < x\ \1 < k\ for x k :: int +proof - + from that have \nat (x div k) = nat x div nat k\ + by (simp add: nat_div_distrib) + also from that have \nat x div nat k < nat x\ + by simp + finally show ?thesis + by simp +qed + + +subsubsection \Computing \div\ and \mod\ by shifting\ + +lemma div_pos_geq: + \k div l = (k - l) div l + 1\ if \0 < l\ \l \ k\ for k l :: int +proof - + have "k = (k - l) + l" by simp + then obtain j where k: "k = j + l" .. + with that show ?thesis by (simp add: div_add_self2) +qed + +lemma mod_pos_geq: + \k mod l = (k - l) mod l\ if \0 < l\ \l \ k\ for k l :: int +proof - + have "k = (k - l) + l" by simp + then obtain j where k: "k = j + l" .. + with that show ?thesis by simp +qed + +lemma pos_zdiv_mult_2: \(1 + 2 * b) div (2 * a) = b div a\ (is ?Q) + and pos_zmod_mult_2: \(1 + 2 * b) mod (2 * a) = 1 + 2 * (b mod a)\ (is ?R) + if \0 \ a\ for a b :: int +proof - + have \((1 + 2 * b) div (2 * a), (1 + 2 * b) mod (2 * a)) = (b div a, 1 + 2 * (b mod a))\ + proof (cases \2 * a\ \b div a\ \1 + 2 * (b mod a)\ \1 + 2 * b\ rule: euclidean_relation_intI) + case by0 + then show ?case + by simp + next + case divides + have \2 dvd (2 * a)\ + by simp + then have \2 dvd (1 + 2 * b)\ + using \2 * a dvd 1 + 2 * b\ by (rule dvd_trans) + then have \2 dvd (1 + b * 2)\ + by (simp add: ac_simps) + then have \is_unit (2 :: int)\ + by simp + then show ?case + by simp + next + case euclidean_relation + with that have \a > 0\ + by simp + moreover have \b mod a < a\ + using \a > 0\ by simp + then have \1 + 2 * (b mod a) < 2 * a\ + by simp + moreover have \2 * (b mod a) + a * (2 * (b div a)) = 2 * (b div a * a + b mod a)\ + by (simp only: algebra_simps) + moreover have \0 \ 2 * (b mod a)\ + using \a > 0\ by simp + ultimately show ?case + by (simp add: algebra_simps) + qed + then show ?Q and ?R + by simp_all +qed + +lemma neg_zdiv_mult_2: \(1 + 2 * b) div (2 * a) = (b + 1) div a\ (is ?Q) + and neg_zmod_mult_2: \(1 + 2 * b) mod (2 * a) = 2 * ((b + 1) mod a) - 1\ (is ?R) + if \a \ 0\ for a b :: int +proof - + have \((1 + 2 * b) div (2 * a), (1 + 2 * b) mod (2 * a)) = ((b + 1) div a, 2 * ((b + 1) mod a) - 1)\ + proof (cases \2 * a\ \(b + 1) div a\ \2 * ((b + 1) mod a) - 1\ \1 + 2 * b\ rule: euclidean_relation_intI) + case by0 + then show ?case + by simp + next + case divides + have \2 dvd (2 * a)\ + by simp + then have \2 dvd (1 + 2 * b)\ + using \2 * a dvd 1 + 2 * b\ by (rule dvd_trans) + then have \2 dvd (1 + b * 2)\ + by (simp add: ac_simps) + then have \is_unit (2 :: int)\ + by simp + then show ?case + by simp + next + case euclidean_relation + with that have \a < 0\ + by simp + moreover have \(b + 1) mod a > a\ + using \a < 0\ by simp + then have \2 * ((b + 1) mod a) > 1 + 2 * a\ + by simp + moreover have \((1 + b) mod a) \ 0\ + using \a < 0\ by simp + then have \2 * ((1 + b) mod a) \ 0\ + by simp + moreover have \2 * ((1 + b) mod a) + a * (2 * ((1 + b) div a)) = + 2 * ((1 + b) div a * a + (1 + b) mod a)\ + by (simp only: algebra_simps) + ultimately show ?case + by (simp add: algebra_simps sgn_mult abs_mult) + qed + then show ?Q and ?R + by simp_all +qed + +lemma zdiv_numeral_Bit0 [simp]: + \numeral (Num.Bit0 v) div numeral (Num.Bit0 w) = + numeral v div (numeral w :: int)\ + unfolding numeral.simps unfolding mult_2 [symmetric] + by (rule div_mult_mult1) simp + +lemma zdiv_numeral_Bit1 [simp]: + \numeral (Num.Bit1 v) div numeral (Num.Bit0 w) = + (numeral v div (numeral w :: int))\ + unfolding numeral.simps + unfolding mult_2 [symmetric] add.commute [of _ 1] + by (rule pos_zdiv_mult_2) simp + +lemma zmod_numeral_Bit0 [simp]: + \numeral (Num.Bit0 v) mod numeral (Num.Bit0 w) = + (2::int) * (numeral v mod numeral w)\ + unfolding numeral_Bit0 [of v] numeral_Bit0 [of w] + unfolding mult_2 [symmetric] by (rule mod_mult_mult1) + +lemma zmod_numeral_Bit1 [simp]: + \numeral (Num.Bit1 v) mod numeral (Num.Bit0 w) = + 2 * (numeral v mod numeral w) + (1::int)\ + unfolding numeral_Bit1 [of v] numeral_Bit0 [of w] + unfolding mult_2 [symmetric] add.commute [of _ 1] + by (rule pos_zmod_mult_2) simp + + subsection \Generic symbolic computations\ text \ @@ -2548,13 +3049,13 @@ "numeral m dvd numeral n \ divides_aux (divmod n m)" by (simp add: divmod_def mod_eq_0_iff_dvd) -text \Generic computation of quotient and remainder\ - -lemma numeral_div_numeral [simp]: +text \Generic computation of quotient and remainder\ + +lemma numeral_div_numeral [simp]: "numeral k div numeral l = fst (divmod k l)" by (simp add: fst_divmod) -lemma numeral_mod_numeral [simp]: +lemma numeral_mod_numeral [simp]: "numeral k mod numeral l = snd (divmod k l)" by (simp add: snd_divmod) @@ -2622,7 +3123,7 @@ context begin - + qualified definition adjust_div :: "int \ int \ int" where "adjust_div qr = (let (q, r) = qr in q + of_bool (r \ 0))" @@ -2667,7 +3168,7 @@ then show ?thesis by (auto simp add: split_def Let_def adjust_div_def divides_aux_def divide_int_def) qed - + lemma numeral_mod_minus_numeral [simp]: "numeral m mod - numeral n = - adjust_mod n (snd (divmod m n) :: int)" proof (cases "snd (divmod m n) = (0::int)") @@ -2685,7 +3186,7 @@ lemma minus_one_div_numeral [simp]: "- 1 div numeral n = - (adjust_div (divmod Num.One n) :: int)" - using minus_numeral_div_numeral [of Num.One n] by simp + using minus_numeral_div_numeral [of Num.One n] by simp lemma minus_one_mod_numeral [simp]: "- 1 mod numeral n = adjust_mod n (snd (divmod Num.One n) :: int)" @@ -2694,14 +3195,14 @@ lemma one_div_minus_numeral [simp]: "1 div - numeral n = - (adjust_div (divmod Num.One n) :: int)" using numeral_div_minus_numeral [of Num.One n] by simp - + lemma one_mod_minus_numeral [simp]: "1 mod - numeral n = - adjust_mod n (snd (divmod Num.One n) :: int)" using numeral_mod_minus_numeral [of Num.One n] by simp lemma [code]: fixes k :: int - shows + shows "k div 0 = 0" "k mod 0 = k" "0 div k = 0" @@ -2788,7 +3289,7 @@ \ \ \ There is space for improvement here: the calculation itself could be carried out outside the logic, and a generic simproc - (simplifier setup) for generic calculation would be helpful. + (simplifier setup) for generic calculation would be helpful. \ diff -r be91db94e526 -r 64e8d4afcf10 src/HOL/Groebner_Basis.thy --- a/src/HOL/Groebner_Basis.thy Thu Sep 29 14:15:01 2022 +0200 +++ b/src/HOL/Groebner_Basis.thy Thu Sep 29 14:03:40 2022 +0000 @@ -69,7 +69,11 @@ declare div_minus1_right[algebra] declare mod_mult_self2_is_0[algebra] declare mod_mult_self1_is_0[algebra] -declare zmod_eq_0_iff[algebra] + +lemma zmod_eq_0_iff [algebra]: + \m mod d = 0 \ (\q. m = d * q)\ for m d :: int + by (auto simp add: mod_eq_0_iff_dvd) + declare dvd_0_left_iff[algebra] declare zdvd1_eq[algebra] declare mod_eq_dvd_iff[algebra] diff -r be91db94e526 -r 64e8d4afcf10 src/HOL/Main.thy --- a/src/HOL/Main.thy Thu Sep 29 14:15:01 2022 +0200 +++ b/src/HOL/Main.thy Thu Sep 29 14:03:40 2022 +0000 @@ -17,6 +17,7 @@ Conditionally_Complete_Lattices Binomial GCD + Divides begin subsection \Namespace cleanup\ diff -r be91db94e526 -r 64e8d4afcf10 src/HOL/Number_Theory/Cong.thy --- a/src/HOL/Number_Theory/Cong.thy Thu Sep 29 14:15:01 2022 +0200 +++ b/src/HOL/Number_Theory/Cong.thy Thu Sep 29 14:03:40 2022 +0000 @@ -278,7 +278,7 @@ lemma cong_diff_iff_cong_0_nat: "[a - b = 0] (mod m) \ [a = b] (mod m)" if "a \ b" for a b :: nat - using that by (auto simp add: cong_def le_imp_diff_is_add dest: nat_mod_eq_lemma) + using that by (simp add: cong_0_iff) (simp add: cong_def mod_eq_dvd_iff_nat) lemma cong_diff_iff_cong_0_nat': "[nat \int a - int b\ = 0] (mod m) \ [a = b] (mod m)" @@ -348,26 +348,12 @@ for a m :: int by (auto simp: cong_def) (metis mod_mod_trivial pos_mod_conj) -lemma cong_iff_lin_nat: "([a = b] (mod m)) \ (\k1 k2. b + k1 * m = a + k2 * m)" - (is "?lhs = ?rhs") +lemma cong_iff_lin_nat: "[a = b] (mod m) \ (\k1 k2. b + k1 * m = a + k2 * m)" for a b :: nat -proof - assume ?lhs - show ?rhs - proof (cases "b \ a") - case True - with \?lhs\ show ?rhs - by (metis cong_altdef_nat dvd_def le_add_diff_inverse add_0_right mult_0 mult.commute) - next - case False - with \?lhs\ show ?rhs - by (metis cong_def mult.commute nat_le_linear nat_mod_eq_lemma) - qed -next - assume ?rhs - then show ?lhs - by (metis cong_def mult.commute nat_mod_eq_iff) -qed + apply (auto simp add: cong_def nat_mod_eq_iff) + apply (metis mult.commute) + apply (metis mult.commute) + done lemma cong_cong_mod_nat: "[a = b] (mod m) \ [a mod m = b mod m] (mod m)" for a b :: nat @@ -395,8 +381,7 @@ lemma cong_dvd_modulus_nat: "[x = y] (mod m) \ n dvd m \ [x = y] (mod n)" for x y :: nat - unfolding cong_iff_lin_nat dvd_def - by (metis mult.commute mult.left_commute) + by (auto simp add: cong_altdef_nat') lemma cong_to_1_nat: fixes a :: nat @@ -428,8 +413,7 @@ lemma cong_le_nat: "y \ x \ [x = y] (mod n) \ (\q. x = q * n + y)" for x y :: nat - by (auto simp add: cong_altdef_nat le_imp_diff_is_add elim!: dvdE) - + by (auto simp add: cong_altdef_nat le_imp_diff_is_add) lemma cong_solve_nat: fixes a :: nat diff -r be91db94e526 -r 64e8d4afcf10 src/HOL/Numeral_Simprocs.thy --- a/src/HOL/Numeral_Simprocs.thy Thu Sep 29 14:15:01 2022 +0200 +++ b/src/HOL/Numeral_Simprocs.thy Thu Sep 29 14:03:40 2022 +0000 @@ -3,7 +3,7 @@ section \Combination and Cancellation Simprocs for Numeral Expressions\ theory Numeral_Simprocs -imports Divides +imports Parity begin ML_file \~~/src/Provers/Arith/assoc_fold.ML\ diff -r be91db94e526 -r 64e8d4afcf10 src/HOL/Set_Interval.thy --- a/src/HOL/Set_Interval.thy Thu Sep 29 14:15:01 2022 +0200 +++ b/src/HOL/Set_Interval.thy Thu Sep 29 14:03:40 2022 +0000 @@ -12,7 +12,7 @@ section \Set intervals\ theory Set_Interval -imports Divides +imports Parity begin (* Belongs in Finite_Set but 2 is not available there *)