# HG changeset patch # User haftmann # Date 1662388763 -7200 # Node ID 3310317cc4840eeea7de3cb9115fbde225e0d3e7 # Parent 6a20d0ebd5b3c55be2b355ede95c8ea395c04f80 clarified generic euclidean relation diff -r 6a20d0ebd5b3 -r 3310317cc484 src/HOL/Code_Numeral.thy --- a/src/HOL/Code_Numeral.thy Mon Sep 05 12:54:05 2022 +0200 +++ b/src/HOL/Code_Numeral.thy Mon Sep 05 16:39:23 2022 +0200 @@ -276,9 +276,11 @@ declare division_segment_integer.rep_eq [simp] instance - by (standard; transfer) - (use mult_le_mono2 [of 1] in \auto simp add: sgn_mult_abs abs_mult sgn_mult abs_mod_less sgn_mod nat_mult_distrib - division_segment_mult division_segment_mod intro: div_eqI\) + apply (standard; transfer) + apply (use mult_le_mono2 [of 1] in \auto simp add: sgn_mult_abs abs_mult sgn_mult abs_mod_less sgn_mod nat_mult_distrib + division_segment_mult division_segment_mod\) + apply (simp add: division_segment_int_def split: if_splits) + done end diff -r 6a20d0ebd5b3 -r 3310317cc484 src/HOL/Divides.thy --- a/src/HOL/Divides.thy Mon Sep 05 12:54:05 2022 +0200 +++ b/src/HOL/Divides.thy Mon Sep 05 16:39:23 2022 +0200 @@ -114,155 +114,6 @@ qed (use assms in auto) -subsubsection \Computing \div\ and \mod\ with shifting\ - -inductive eucl_rel_int :: "int \ int \ int \ int \ bool" - where eucl_rel_int_by0: "eucl_rel_int k 0 (0, k)" - | eucl_rel_int_dividesI: "l \ 0 \ k = q * l \ eucl_rel_int k l (q, 0)" - | eucl_rel_int_remainderI: "sgn r = sgn l \ \r\ < \l\ - \ k = q * l + r \ eucl_rel_int k l (q, r)" - -lemma eucl_rel_int_iff: - "eucl_rel_int k l (q, r) \ - k = l * q + r \ - (if 0 < l then 0 \ r \ r < l else if l < 0 then l < r \ r \ 0 else q = 0)" - by (cases "r = 0") - (auto elim!: eucl_rel_int.cases intro: eucl_rel_int_by0 eucl_rel_int_dividesI eucl_rel_int_remainderI - simp add: ac_simps sgn_1_pos sgn_1_neg) - -lemma unique_quotient: - "eucl_rel_int a b (q, r) \ eucl_rel_int a b (q', r') \ q = q'" - apply (rule order_antisym) - apply (simp_all add: eucl_rel_int_iff linorder_neq_iff split: if_split_asm) - apply (blast intro: order_eq_refl [THEN unique_quotient_lemma] order_eq_refl [THEN unique_quotient_lemma_neg] sym)+ - done - -lemma unique_remainder: - assumes "eucl_rel_int a b (q, r)" - and "eucl_rel_int a b (q', r')" - shows "r = r'" -proof - - have "q = q'" - using assms by (blast intro: unique_quotient) - then show "r = r'" - using assms by (simp add: eucl_rel_int_iff) -qed - -lemma eucl_rel_int: - "eucl_rel_int k l (k div l, k mod l)" -proof (cases k rule: int_cases3) - case zero - then show ?thesis - by (simp add: eucl_rel_int_iff divide_int_def modulo_int_def) -next - case (pos n) - then show ?thesis - using div_mult_mod_eq [of n] - by (cases l rule: int_cases3) - (auto simp del: of_nat_mult of_nat_add - simp add: mod_greater_zero_iff_not_dvd of_nat_mult [symmetric] of_nat_add [symmetric] algebra_simps - eucl_rel_int_iff divide_int_def modulo_int_def) -next - case (neg n) - then show ?thesis - using div_mult_mod_eq [of n] - by (cases l rule: int_cases3) - (auto simp del: of_nat_mult of_nat_add - simp add: mod_greater_zero_iff_not_dvd of_nat_mult [symmetric] of_nat_add [symmetric] algebra_simps - eucl_rel_int_iff divide_int_def modulo_int_def) -qed - -lemma divmod_int_unique: - assumes "eucl_rel_int k l (q, r)" - shows div_int_unique: "k div l = q" and mod_int_unique: "k mod l = r" - using assms eucl_rel_int [of k l] - using unique_quotient [of k l] unique_remainder [of k l] - by auto - -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 - -lemma pos_eucl_rel_int_mult_2: - assumes "0 \ b" - assumes "eucl_rel_int a b (q, r)" - shows "eucl_rel_int (1 + 2*a) (2*b) (q, 1 + 2*r)" - using assms unfolding eucl_rel_int_iff by auto - -lemma neg_eucl_rel_int_mult_2: - assumes "b \ 0" - assumes "eucl_rel_int (a + 1) b (q, r)" - shows "eucl_rel_int (1 + 2*a) (2*b) (q, 2*r - 1)" - using assms unfolding eucl_rel_int_iff by auto - -text\computing div by shifting\ - -lemma pos_zdiv_mult_2: "(0::int) \ a ==> (1 + 2*b) div (2*a) = b div a" - using pos_eucl_rel_int_mult_2 [OF _ eucl_rel_int] - by (rule div_int_unique) - -lemma neg_zdiv_mult_2: - assumes A: "a \ (0::int)" shows "(1 + 2*b) div (2*a) = (b+1) div a" - using neg_eucl_rel_int_mult_2 [OF A eucl_rel_int] - by (rule div_int_unique) - -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 pos_zmod_mult_2: - fixes a b :: int - assumes "0 \ a" - shows "(1 + 2 * b) mod (2 * a) = 1 + 2 * (b mod a)" - using pos_eucl_rel_int_mult_2 [OF assms eucl_rel_int] - by (rule mod_int_unique) - -lemma neg_zmod_mult_2: - fixes a b :: int - assumes "a \ 0" - shows "(1 + 2 * b) mod (2 * a) = 2 * ((b + 1) mod a) - 1" - using neg_eucl_rel_int_mult_2 [OF assms eucl_rel_int] - by (rule mod_int_unique) - -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) - - subsubsection \Quotients of Signs\ lemma div_eq_minus1: "0 < b \ - 1 div b = - 1" for b :: int @@ -402,6 +253,29 @@ 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_relationI) + (auto simp add: division_segment_int_def ac_simps dvd_add_left_iff 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\ @@ -430,21 +304,6 @@ text \Simplify expressions in which div and mod combine numerical constants\ -lemma int_div_pos_eq: "\(a::int) = b * q + r; 0 \ r; r < b\ \ a div b = q" - by (rule div_int_unique [of a b q r]) (simp add: eucl_rel_int_iff) - -lemma int_div_neg_eq: "\(a::int) = b * q + r; r \ 0; b < r\ \ a div b = q" - by (rule div_int_unique [of a b q r], - simp add: eucl_rel_int_iff) - -lemma int_mod_pos_eq: "\(a::int) = b * q + r; 0 \ r; r < b\ \ a mod b = r" - by (rule mod_int_unique [of a b q r], - simp add: eucl_rel_int_iff) - -lemma int_mod_neg_eq: "\(a::int) = b * q + r; r \ 0; b < r\ \ a mod b = r" - by (rule mod_int_unique [of a b q r], - simp add: eucl_rel_int_iff) - 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) @@ -541,6 +400,157 @@ qed +subsubsection \Uniqueness rules\ + +inductive eucl_rel_int :: "int \ int \ int \ int \ bool" + where eucl_rel_int_by0: "eucl_rel_int k 0 (0, k)" + | eucl_rel_int_dividesI: "l \ 0 \ k = q * l \ eucl_rel_int k l (q, 0)" + | eucl_rel_int_remainderI: "sgn r = sgn l \ \r\ < \l\ + \ k = q * l + r \ eucl_rel_int k l (q, r)" + +lemma eucl_rel_int_iff: + "eucl_rel_int k l (q, r) \ + k = l * q + r \ + (if 0 < l then 0 \ r \ r < l else if l < 0 then l < r \ r \ 0 else q = 0)" + by (cases "r = 0") + (auto elim!: eucl_rel_int.cases intro: eucl_rel_int_by0 eucl_rel_int_dividesI eucl_rel_int_remainderI + simp add: ac_simps sgn_1_pos sgn_1_neg) + +lemma eucl_rel_int: + "eucl_rel_int k l (k div l, k mod l)" +proof (cases k rule: int_cases3) + case zero + then show ?thesis + by (simp add: eucl_rel_int_iff divide_int_def modulo_int_def) +next + case (pos n) + then show ?thesis + using div_mult_mod_eq [of n] + by (cases l rule: int_cases3) + (auto simp del: of_nat_mult of_nat_add + simp add: mod_greater_zero_iff_not_dvd of_nat_mult [symmetric] of_nat_add [symmetric] algebra_simps + eucl_rel_int_iff divide_int_def modulo_int_def) +next + case (neg n) + then show ?thesis + using div_mult_mod_eq [of n] + by (cases l rule: int_cases3) + (auto simp del: of_nat_mult of_nat_add + simp add: mod_greater_zero_iff_not_dvd of_nat_mult [symmetric] of_nat_add [symmetric] algebra_simps + eucl_rel_int_iff divide_int_def modulo_int_def) +qed + +lemma unique_quotient: + \q = q'\ if \eucl_rel_int a b (q, r)\ \eucl_rel_int a b (q', r')\ + apply (rule order_antisym) + using that + apply (simp_all add: eucl_rel_int_iff linorder_neq_iff split: if_split_asm) + apply (blast intro: order_eq_refl [THEN unique_quotient_lemma] order_eq_refl [THEN unique_quotient_lemma_neg] sym)+ + done + +lemma unique_remainder: + \r = r'\ if \eucl_rel_int a b (q, r)\ \eucl_rel_int a b (q', r')\ +proof - + have \q = q'\ + using that by (blast intro: unique_quotient) + then show ?thesis + using that by (simp add: eucl_rel_int_iff) +qed + +lemma divmod_int_unique: + assumes \eucl_rel_int k l (q, r)\ + shows div_int_unique: \k div l = q\ and mod_int_unique: \k mod l = r\ + using assms eucl_rel_int [of k l] + using unique_quotient [of k l] unique_remainder [of k l] + by auto + + +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 + +lemma pos_eucl_rel_int_mult_2: + assumes "0 \ b" + assumes "eucl_rel_int a b (q, r)" + shows "eucl_rel_int (1 + 2*a) (2*b) (q, 1 + 2*r)" + using assms unfolding eucl_rel_int_iff by auto + +lemma neg_eucl_rel_int_mult_2: + assumes "b \ 0" + assumes "eucl_rel_int (a + 1) b (q, r)" + shows "eucl_rel_int (1 + 2*a) (2*b) (q, 2*r - 1)" + using assms unfolding eucl_rel_int_iff by auto + +text\computing div by shifting\ + +lemma pos_zdiv_mult_2: "(0::int) \ a ==> (1 + 2*b) div (2*a) = b div a" + using pos_eucl_rel_int_mult_2 [OF _ eucl_rel_int] + by (rule div_int_unique) + +lemma neg_zdiv_mult_2: + assumes A: "a \ (0::int)" shows "(1 + 2*b) div (2*a) = (b+1) div a" + using neg_eucl_rel_int_mult_2 [OF A eucl_rel_int] + by (rule div_int_unique) + +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 pos_zmod_mult_2: + fixes a b :: int + assumes "0 \ a" + shows "(1 + 2 * b) mod (2 * a) = 1 + 2 * (b mod a)" + using pos_eucl_rel_int_mult_2 [OF assms eucl_rel_int] + by (rule mod_int_unique) + +lemma neg_zmod_mult_2: + fixes a b :: int + assumes "a \ 0" + shows "(1 + 2 * b) mod (2 * a) = 2 * ((b + 1) mod a) - 1" + using neg_eucl_rel_int_mult_2 [OF assms eucl_rel_int] + by (rule mod_int_unique) + +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 diff -r 6a20d0ebd5b3 -r 3310317cc484 src/HOL/Euclidean_Division.thy --- a/src/HOL/Euclidean_Division.thy Mon Sep 05 12:54:05 2022 +0200 +++ b/src/HOL/Euclidean_Division.thy Mon Sep 05 16:39:23 2022 +0200 @@ -605,205 +605,235 @@ subsection \Uniquely determined division\ 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)" + 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)\ and division_segment_mult: - "a \ 0 \ b \ 0 \ division_segment (a * b) = division_segment a * division_segment b" + \a \ 0 \ b \ 0 \ division_segment (a * b) = division_segment a * division_segment b\ and division_segment_mod: - "b \ 0 \ \ b dvd a \ division_segment (a mod b) = division_segment b" + \b \ 0 \ \ b dvd a \ division_segment (a mod b) = division_segment b\ assumes div_bounded: - "b \ 0 \ division_segment r = division_segment b + \b \ 0 \ division_segment r = division_segment b \ euclidean_size r < euclidean_size b - \ (q * b + r) div b = q" + \ (q * b + r) div b = q\ begin lemma division_segment_not_0 [simp]: - "division_segment a \ 0" - using is_unit_division_segment [of a] is_unitE [of "division_segment a"] by blast - -lemma divmod_cases [case_names divides remainder by0]: - obtains - (divides) q where "b \ 0" - and "a div b = q" - and "a mod b = 0" - and "a = q * b" - | (remainder) q r where "b \ 0" - and "division_segment r = division_segment b" - and "euclidean_size r < euclidean_size b" - and "r \ 0" - and "a div b = q" - and "a mod b = r" - and "a = q * b + r" - | (by0) "b = 0" -proof (cases "b = 0") + \division_segment a \ 0\ + using is_unit_division_segment [of a] is_unitE [of \division_segment a\] by blast + +lemma euclidean_relationI [case_names by0 divides euclidean_relation]: + \(a div b, a mod b) = (q, r)\ + if by0: \b = 0 \ q = 0 \ r = a\ + and divides: \b \ 0 \ b dvd a \ r = 0 \ a = q * b\ + and euclidean_relation: \b \ 0 \ \ b dvd a \ division_segment r = division_segment b + \ euclidean_size r < euclidean_size b \ a = q * b + r\ +proof (cases \b = 0\) case True - then show thesis - by (rule by0) + with by0 show ?thesis + by simp next case False - show thesis - proof (cases "b dvd a") + show ?thesis + proof (cases \b dvd a\) case True - then obtain q where "a = b * q" .. with \b \ 0\ divides - show thesis - by (simp add: ac_simps) + show ?thesis + by simp next case False - then have "a mod b \ 0" - by (simp add: mod_eq_0_iff_dvd) - moreover from \b \ 0\ \\ b dvd a\ have "division_segment (a mod b) = division_segment b" - by (rule division_segment_mod) - moreover have "euclidean_size (a mod b) < euclidean_size b" - using \b \ 0\ by (rule mod_size_less) - moreover have "a = a div b * b + a mod b" + with \b \ 0\ euclidean_relation + have \division_segment r = division_segment b\ + \euclidean_size r < euclidean_size b\ \a = q * b + r\ + by simp_all + from \b \ 0\ \division_segment r = division_segment b\ + \euclidean_size r < euclidean_size b\ + have \(q * b + r) div b = q\ + by (rule div_bounded) + with \a = q * b + r\ + have \q = a div b\ + by simp + from \a = q * b + r\ + have \a div b * b + a mod b = q * b + r\ by (simp add: div_mult_mod_eq) - ultimately show thesis - using \b \ 0\ by (blast intro!: remainder) + with \q = a div b\ + have \q * b + a mod b = q * b + r\ + by simp + then have \r = a mod b\ + by simp + with \q = a div b\ + show ?thesis + by simp qed qed -lemma div_eqI: - "a div b = q" if "b \ 0" "division_segment r = division_segment b" - "euclidean_size r < euclidean_size b" "q * b + r = a" -proof - - from that have "(q * b + r) div b = q" - by (auto intro: div_bounded) - with that show ?thesis - by simp -qed - -lemma mod_eqI: - "a mod b = r" if "b \ 0" "division_segment r = division_segment b" - "euclidean_size r < euclidean_size b" "q * b + r = a" -proof - - from that have "a div b = q" - by (rule div_eqI) - moreover have "a div b * b + a mod b = a" - by (fact div_mult_mod_eq) - ultimately have "a div b * b + a mod b = a div b * b + r" - using \q * b + r = a\ by simp - then show ?thesis - by simp -qed - subclass euclidean_semiring_cancel proof - show "(a + c * b) div b = c + a div b" if "b \ 0" for a b c - proof (cases a b rule: divmod_cases) + fix a b c + assume \b \ 0\ + have \((a + c * b) div b, (a + c * b) mod b) = (c + a div b, a mod b)\ + proof (cases b \c + a div b\ \a mod b\ \a + c * b\ rule: euclidean_relationI) case by0 - with \b \ 0\ show ?thesis + with \b \ 0\ + show ?case + by simp + next + case divides + then show ?case + by (simp add: algebra_simps dvd_add_left_iff) + next + case euclidean_relation + then have \\ b dvd a\ + by (simp add: dvd_add_left_iff) + have \a mod b + (b * c + b * (a div b)) = b * c + ((a div b) * b + a mod b)\ + by (simp add: ac_simps) + with \b \ 0\ have *: \a mod b + (b * c + b * (a div b)) = b * c + a\ + by (simp add: div_mult_mod_eq) + from \\ b dvd a\ euclidean_relation show ?case + by (simp_all add: algebra_simps division_segment_mod mod_size_less *) + qed + then show \(a + c * b) div b = c + a div b\ + by simp +next + fix a b c + assume \c \ 0\ + have \((c * a) div (c * b), (c * a) mod (c * b)) = (a div b, c * (a mod b))\ + proof (cases \c * b\ \a div b\ \c * (a mod b)\ \c * a\ rule: euclidean_relationI) + case by0 + with \c \ 0\ show ?case by simp next - case (divides q) - then show ?thesis - by (simp add: ac_simps) + case divides + then show ?case + by (auto simp add: algebra_simps) next - case (remainder q r) - then show ?thesis - by (auto intro: div_eqI simp add: algebra_simps) + case euclidean_relation + then have \b \ 0\ \a mod b \ 0\ + by (simp_all add: mod_eq_0_iff_dvd) + have \c * (a mod b) + b * (c * (a div b)) = c * ((a div b) * b + a mod b)\ + by (simp add: algebra_simps) + with \b \ 0\ have *: \c * (a mod b) + b * (c * (a div b)) = c * a\ + by (simp add: div_mult_mod_eq) + from \b \ 0\ \c \ 0\ have \euclidean_size c * euclidean_size (a mod b) + < euclidean_size c * euclidean_size b\ + using mod_size_less [of b a] by simp + with euclidean_relation \b \ 0\ \a mod b \ 0\ show ?case + by (simp add: algebra_simps division_segment_mult division_segment_mod euclidean_size_mult *) qed + then show \(c * a) div (c * b) = a div b\ + by simp +qed + +lemma div_eq_0_iff: + \a div b = 0 \ euclidean_size a < euclidean_size b \ b = 0\ (is "_ \ ?P") + if \division_segment a = division_segment b\ +proof (cases \a = 0 \ b = 0\) + case True + then show ?thesis by auto next - show"(c * a) div (c * b) = a div b" if "c \ 0" for a b c - proof (cases a b rule: divmod_cases) - case by0 - then show ?thesis + case False + then have \a \ 0\ \b \ 0\ + by simp_all + have \a div b = 0 \ euclidean_size a < euclidean_size b\ + proof + assume \a div b = 0\ + then have \a mod b = a\ + using div_mult_mod_eq [of a b] by simp + with \b \ 0\ mod_size_less [of b a] + show \euclidean_size a < euclidean_size b\ by simp next - case (divides q) - with \c \ 0\ show ?thesis - by (simp add: mult.left_commute [of c]) - next - case (remainder q r) - from \b \ 0\ \c \ 0\ have "b * c \ 0" + assume \euclidean_size a < euclidean_size b\ + have \(a div b, a mod b) = (0, a)\ + proof (cases b 0 a a rule: euclidean_relationI) + case by0 + show ?case + by simp + next + case divides + with \euclidean_size a < euclidean_size b\ show ?case + using dvd_imp_size_le [of b a] \a \ 0\ by simp + next + case euclidean_relation + with \euclidean_size a < euclidean_size b\ that + show ?case + by simp + qed + then show \a div b = 0\ by simp - from remainder \c \ 0\ - have "division_segment (r * c) = division_segment (b * c)" - and "euclidean_size (r * c) < euclidean_size (b * c)" - by (simp_all add: division_segment_mult division_segment_mod euclidean_size_mult) - with remainder show ?thesis - by (auto intro!: div_eqI [of _ "c * (a mod b)"] simp add: algebra_simps) - (use \b * c \ 0\ in simp) qed + with \b \ 0\ show ?thesis + by simp qed lemma div_mult1_eq: - "(a * b) div c = a * (b div c) + a * (b mod c) div c" -proof (cases "a * (b mod c)" c rule: divmod_cases) - case (divides q) - have "a * b = a * (b div c * c + b mod c)" - by (simp add: div_mult_mod_eq) - also have "\ = (a * (b div c) + q) * c" - using divides by (simp add: algebra_simps) - finally have "(a * b) div c = \ div c" - by simp - with divides show ?thesis - by simp -next - case (remainder q r) - from remainder(1-3) show ?thesis - proof (rule div_eqI) - have "a * b = a * (b div c * c + b mod c)" - by (simp add: div_mult_mod_eq) - also have "\ = a * c * (b div c) + q * c + r" - using remainder by (simp add: algebra_simps) - finally show "(a * (b div c) + a * (b mod c) div c) * c + r = a * b" - using remainder(5-7) by (simp add: algebra_simps) + \(a * b) div c = a * (b div c) + a * (b mod c) div c\ +proof - + have *: \(a * b) mod c + (a * (c * (b div c)) + c * (a * (b mod c) div c)) = a * b\ (is \?A + (?B + ?C) = _\) + proof - + have \?A = a * (b mod c) mod c\ + by (simp add: mod_mult_right_eq) + then have \?C + ?A = a * (b mod c)\ + by (simp add: mult_div_mod_eq) + then have \?B + (?C + ?A) = a * (c * (b div c) + (b mod c))\ + by (simp add: algebra_simps) + also have \\ = a * b\ + by (simp add: mult_div_mod_eq) + finally show ?thesis + by (simp add: algebra_simps) qed -next - case by0 + have \((a * b) div c, (a * b) mod c) = (a * (b div c) + a * (b mod c) div c, (a * b) mod c)\ + proof (cases c \a * (b div c) + a * (b mod c) div c\ \(a * b) mod c\ \a * b\ rule: euclidean_relationI) + case by0 + then show ?case by simp + next + case divides + with * show ?case + by (simp add: algebra_simps) + next + case euclidean_relation + with * show ?case + by (simp add: division_segment_mod mod_size_less algebra_simps) + qed then show ?thesis by simp qed lemma div_add1_eq: - "(a + b) div c = a div c + b div c + (a mod c + b mod c) div c" -proof (cases "a mod c + b mod c" c rule: divmod_cases) - case (divides q) - have "a + b = (a div c * c + a mod c) + (b div c * c + b mod c)" - using mod_mult_div_eq [of a c] mod_mult_div_eq [of b c] by (simp add: ac_simps) - also have "\ = (a div c + b div c) * c + (a mod c + b mod c)" - by (simp add: algebra_simps) - also have "\ = (a div c + b div c + q) * c" - using divides by (simp add: algebra_simps) - finally have "(a + b) div c = (a div c + b div c + q) * c div c" - by simp - with divides show ?thesis - by simp -next - case (remainder q r) - from remainder(1-3) show ?thesis - proof (rule div_eqI) - have "(a div c + b div c + q) * c + r + (a mod c + b mod c) = - (a div c * c + a mod c) + (b div c * c + b mod c) + q * c + r" + \(a + b) div c = a div c + b div c + (a mod c + b mod c) div c\ +proof - + have *: \(a + b) mod c + (c * (a div c) + (c * (b div c) + c * ((a mod c + b mod c) div c))) = a + b\ + (is \?A + (?B + (?C + ?D)) = _\) + proof - + have \?A + (?B + (?C + ?D)) = ?A + ?D + (?B + ?C)\ + by (simp add: ac_simps) + also have \?A + ?D = (a mod c + b mod c) mod c + ?D\ + by (simp add: mod_add_eq) + also have \\ = a mod c + b mod c\ + by (simp add: mod_mult_div_eq) + finally have \?A + (?B + (?C + ?D)) = (a mod c + ?B) + (b mod c + ?C)\ + by (simp add: ac_simps) + then show ?thesis + by (simp add: mod_mult_div_eq) + qed + have \((a + b) div c, (a + b) mod c) = (a div c + b div c + (a mod c + b mod c) div c, (a + b) mod c)\ + proof (cases c \a div c + b div c + (a mod c + b mod c) div c\ \(a + b) mod c\ \a + b\ rule: euclidean_relationI) + case by0 + then show ?case + by simp + next + case divides + with * show ?case by (simp add: algebra_simps) - also have "\ = a + b + (a mod c + b mod c)" - by (simp add: div_mult_mod_eq remainder) (simp add: ac_simps) - finally show "(a div c + b div c + (a mod c + b mod c) div c) * c + r = a + b" - using remainder by simp + next + case euclidean_relation + with * show ?case + by (simp add: division_segment_mod mod_size_less algebra_simps) qed -next - case by0 then show ?thesis by simp qed -lemma div_eq_0_iff: - "a div b = 0 \ euclidean_size a < euclidean_size b \ b = 0" (is "_ \ ?P") - if "division_segment a = division_segment b" -proof - assume ?P - with that show "a div b = 0" - by (cases "b = 0") (auto intro: div_eqI) -next - assume "a div b = 0" - then have "a mod b = a" - using div_mult_mod_eq [of a b] by simp - with mod_size_less [of b a] show ?P - by auto -qed - end class unique_euclidean_ring = euclidean_ring + unique_euclidean_semiring @@ -819,19 +849,19 @@ instantiation nat :: normalization_semidom begin -definition normalize_nat :: "nat \ nat" - where [simp]: "normalize = (id :: nat \ nat)" - -definition unit_factor_nat :: "nat \ nat" - where "unit_factor n = (if n = 0 then 0 else 1 :: nat)" +definition normalize_nat :: \nat \ nat\ + where [simp]: \normalize = (id :: nat \ nat)\ + +definition unit_factor_nat :: \nat \ nat\ + where \unit_factor n = of_bool (n > 0)\ for n :: nat lemma unit_factor_simps [simp]: - "unit_factor 0 = (0::nat)" - "unit_factor (Suc n) = 1" + \unit_factor 0 = (0::nat)\ + \unit_factor (Suc n) = 1\ by (simp_all add: unit_factor_nat_def) -definition divide_nat :: "nat \ nat \ nat" - where "m div n = (if n = 0 then 0 else Max {k::nat. k * n \ m})" +definition divide_nat :: \nat \ nat \ nat\ + where \m div n = (if n = 0 then 0 else Max {k. k * n \ m})\ for m n :: nat instance by standard (auto simp add: divide_nat_def ac_simps unit_factor_nat_def intro: Max_eqI) @@ -853,14 +883,14 @@ instantiation nat :: unique_euclidean_semiring begin -definition euclidean_size_nat :: "nat \ nat" - where [simp]: "euclidean_size_nat = id" - -definition division_segment_nat :: "nat \ nat" - where [simp]: "division_segment_nat n = 1" - -definition modulo_nat :: "nat \ nat \ nat" - where "m mod n = m - (m div n * (n::nat))" +definition euclidean_size_nat :: \nat \ nat\ + where [simp]: \euclidean_size_nat = id\ + +definition division_segment_nat :: \nat \ nat\ + where [simp]: \division_segment n = 1\ for n :: nat + +definition modulo_nat :: \nat \ nat \ nat\ + where \m mod n = m - (m div n * n)\ for m n :: nat instance proof fix m n :: nat @@ -938,12 +968,60 @@ end lemma div_nat_eqI: - "m div n = q" if "n * q \ m" and "m < n * Suc q" for m n q :: nat - by (rule div_eqI [of _ "m - n * q"]) (use that in \simp_all add: algebra_simps\) + \m div n = q\ if \n * q \ m\ and \m < n * Suc q\ for m n q :: nat +proof - + have \(m div n, m mod n) = (q, m - n * q)\ + proof (cases n q \m - n * q\ m rule: euclidean_relationI) + case by0 + with that show ?case + by simp + next + case divides + from \n dvd m\ obtain s where \m = n * s\ .. + with \n \ 0\ that have \s < Suc q\ + by (simp only: mult_less_cancel1) + with \m = n * s\ \n \ 0\ that have \q = s\ + by simp + with \m = n * s\ show ?case + by (simp add: ac_simps) + next + case euclidean_relation + with that show ?case + by (simp add: ac_simps) + qed + then show ?thesis + by simp +qed lemma mod_nat_eqI: - "m mod n = r" if "r < n" and "r \ m" and "n dvd m - r" for m n r :: nat - by (rule mod_eqI [of _ _ "(m - r) div n"]) (use that in \simp_all add: algebra_simps\) + \m mod n = r\ if \r < n\ and \r \ m\ and \n dvd m - r\ for m n r :: nat +proof - + have \(m div n, m mod n) = ((m - r) div n, r)\ + proof (cases n \(m - r) div n\ r m rule: euclidean_relationI) + case by0 + with that show ?case + by simp + next + case divides + from that dvd_minus_add [of r \m\ 1 n] + have \n dvd m + (n - r)\ + by simp + with divides have \n dvd n - r\ + by (simp add: dvd_add_right_iff) + then have \n \ n - r\ + by (rule dvd_imp_le) (use \r < n\ in simp) + with \n \ 0\ have \r = 0\ + by simp + with \n \ 0\ that show ?case + by simp + next + case euclidean_relation + with that show ?case + by (simp add: ac_simps) + qed + then show ?thesis + by simp +qed text \Tool support\ @@ -1029,7 +1107,7 @@ div_less [simp]: "m div n = 0" and mod_less [simp]: "m mod n = m" if "m < n" for m n :: nat - using that by (auto intro: div_eqI mod_eqI) + using that by (auto intro: div_nat_eqI mod_nat_eqI) lemma split_div: \P (m div n) \ @@ -1176,54 +1254,43 @@ "Suc 0 mod n = of_bool (n \ Suc 0)" by (cases n) simp_all -context - fixes m n q :: nat -begin - -private lemma eucl_rel_mult2: - "m mod n + n * (m div n mod q) < n * q" - if "n > 0" and "q > 0" +lemma div_mult2_eq: + \m div (n * q) = (m div n) div q\ (is ?Q) + and mod_mult2_eq: + \m mod (n * q) = n * (m div n mod q) + m mod n\ (is ?R) + for m n q :: nat proof - - from \n > 0\ have "m mod n < n" - by (rule mod_less_divisor) - from \q > 0\ have "m div n mod q < q" - by (rule mod_less_divisor) - then obtain s where "q = Suc (m div n mod q + s)" - by (blast dest: less_imp_Suc_add) - moreover have "m mod n + n * (m div n mod q) < n * Suc (m div n mod q + s)" - using \m mod n < n\ by (simp add: add_mult_distrib2) - ultimately show ?thesis - by simp + have \(m div (n * q), m mod (n * q)) = ((m div n) div q, n * (m div n mod q) + m mod n)\ + proof (cases \n * q\ \(m div n) div q\ \n * (m div n mod q) + m mod n\ m rule: euclidean_relationI) + case by0 + then show ?case + by auto + next + case divides + from \n * q dvd m\ obtain t where \m = n * q * t\ .. + with \n * q \ 0\ show ?case + by (simp add: algebra_simps) + next + case euclidean_relation + then have \n > 0\ \q > 0\ + by simp_all + from \n > 0\ have \m mod n < n\ + by (rule mod_less_divisor) + from \q > 0\ have \m div n mod q < q\ + by (rule mod_less_divisor) + then obtain s where \q = Suc (m div n mod q + s)\ + by (blast dest: less_imp_Suc_add) + moreover have \m mod n + n * (m div n mod q) < n * Suc (m div n mod q + s)\ + using \m mod n < n\ by (simp add: add_mult_distrib2) + ultimately have \m mod n + n * (m div n mod q) < n * q\ + by simp + then show ?case + by (simp add: algebra_simps flip: add_mult_distrib2) + qed + then show ?Q and ?R + by simp_all qed -lemma div_mult2_eq: - "m div (n * q) = (m div n) div q" -proof (cases "n = 0 \ q = 0") - case True - then show ?thesis - by auto -next - case False - with eucl_rel_mult2 show ?thesis - by (auto intro: div_eqI [of _ "n * (m div n mod q) + m mod n"] - simp add: algebra_simps add_mult_distrib2 [symmetric]) -qed - -lemma mod_mult2_eq: - "m mod (n * q) = n * (m div n mod q) + m mod n" -proof (cases "n = 0 \ q = 0") - case True - then show ?thesis - by auto -next - case False - with eucl_rel_mult2 show ?thesis - by (auto intro: mod_eqI [of _ _ "(m div n) div q"] - simp add: algebra_simps add_mult_distrib2 [symmetric]) -qed - -end - lemma div_le_mono: "m div k \ n div k" if "m \ n" for m n k :: nat proof - @@ -1864,42 +1931,54 @@ using div_mult_mod_eq [of 1 "2 ^ n"] by auto lemma div_mult2_eq': - "a div (of_nat m * of_nat n) = a div of_nat m div of_nat n" -proof (cases a "of_nat m * of_nat n" rule: divmod_cases) - case (divides q) - then show ?thesis - using nonzero_mult_div_cancel_right [of "of_nat m" "q * of_nat n"] - by (simp add: ac_simps) -next - case (remainder q r) - then have "division_segment r = 1" - using division_segment_of_nat [of "m * n"] by simp - with division_segment_euclidean_size [of r] - have "of_nat (euclidean_size r) = r" - by simp - have "a mod (of_nat m * of_nat n) div (of_nat m * of_nat n) = 0" - by simp - with remainder(6) have "r div (of_nat m * of_nat n) = 0" - by simp - with \of_nat (euclidean_size r) = r\ - have "of_nat (euclidean_size r) div (of_nat m * of_nat n) = 0" - by simp - then have "of_nat (euclidean_size r div (m * n)) = 0" - by (simp add: of_nat_div) - then have "of_nat (euclidean_size r div m div n) = 0" - by (simp add: div_mult2_eq) - with \of_nat (euclidean_size r) = r\ have "r div of_nat m div of_nat n = 0" - by (simp add: of_nat_div) - with remainder(1) - have "q = (r div of_nat m + q * of_nat n * of_nat m div of_nat m) div of_nat n" - by simp - with remainder(5) remainder(7) show ?thesis - using div_plus_div_distrib_dvd_right [of "of_nat m" "q * (of_nat m * of_nat n)" r] - by (simp add: ac_simps) -next - case by0 + \a div (of_nat m * of_nat n) = a div of_nat m div of_nat n\ +proof (cases \m = 0 \ n = 0\) + case True then show ?thesis by auto +next + case False + then have \m > 0\ \n > 0\ + by simp_all + show ?thesis + proof (cases \of_nat m * of_nat n dvd a\) + case True + then obtain b where \a = (of_nat m * of_nat n) * b\ .. + then have \a = of_nat m * (of_nat n * b)\ + by (simp add: ac_simps) + then show ?thesis + by simp + next + case False + define q where \q = a div (of_nat m * of_nat n)\ + define r where \r = a mod (of_nat m * of_nat n)\ + from \m > 0\ \n > 0\ \\ of_nat m * of_nat n dvd a\ r_def have "division_segment r = 1" + using division_segment_of_nat [of "m * n"] by (simp add: division_segment_mod) + with division_segment_euclidean_size [of r] + have "of_nat (euclidean_size r) = r" + by simp + have "a mod (of_nat m * of_nat n) div (of_nat m * of_nat n) = 0" + by simp + with \m > 0\ \n > 0\ r_def have "r div (of_nat m * of_nat n) = 0" + by simp + with \of_nat (euclidean_size r) = r\ + have "of_nat (euclidean_size r) div (of_nat m * of_nat n) = 0" + by simp + then have "of_nat (euclidean_size r div (m * n)) = 0" + by (simp add: of_nat_div) + then have "of_nat (euclidean_size r div m div n) = 0" + by (simp add: div_mult2_eq) + with \of_nat (euclidean_size r) = r\ have "r div of_nat m div of_nat n = 0" + by (simp add: of_nat_div) + with \m > 0\ \n > 0\ q_def + have "q = (r div of_nat m + q * of_nat n * of_nat m div of_nat m) div of_nat n" + by simp + moreover have \a = q * (of_nat m * of_nat n) + r\ + by (simp add: q_def r_def div_mult_mod_eq) + ultimately show \a div (of_nat m * of_nat n) = a div of_nat m div of_nat n\ + using q_def [symmetric] div_plus_div_distrib_dvd_right [of \of_nat m\ \q * (of_nat m * of_nat n)\ r] + by (simp add: ac_simps) + qed qed lemma mod_mult2_eq': @@ -2033,31 +2112,45 @@ 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 = - k\) + \k div l = - 1\ if \0 < k\ and \k + l \ 0\ for k l :: int +proof (cases \l dvd k\) case True - with that show ?thesis - by (simp add: divide_int_def) + then obtain j where \k = l * j\ .. + 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 - show ?thesis - apply (rule div_eqI [of _ "k + l"]) - using False that apply (simp_all add: division_segment_int_def) - done + have \k + l < 0\ + proof (rule ccontr) + assume \\ k + l < 0\ + with \k + l \ 0\ have \k + l = 0\ + by simp + then have \k = - l\ + by simp + then have \l dvd k\ + by simp + with \\ l dvd k\ show False .. + 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 (cases \l = - k\) - case True - with that show ?thesis - by (simp add: divide_int_def) -next - case False - show ?thesis - apply (rule mod_eqI [of _ _ \- 1\]) - using False that apply (simp_all add: division_segment_int_def) - done + \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 qed text \There is neither \div_neg_pos_trivial\ nor \mod_neg_pos_trivial\