(* Title: HOL/Int.thy Author: Lawrence C Paulson, Cambridge University Computer Laboratory Author: Tobias Nipkow, Florian Haftmann, TU Muenchen *) section \The Integers as Equivalence Classes over Pairs of Natural Numbers\ theory Int imports Equiv_Relations Power Quotient Fun_Def begin subsection \Definition of integers as a quotient type\ definition intrel :: "(nat \ nat) \ (nat \ nat) \ bool" where "intrel = (\(x, y) (u, v). x + v = u + y)" lemma intrel_iff [simp]: "intrel (x, y) (u, v) \ x + v = u + y" by (simp add: intrel_def) quotient_type int = "nat \ nat" / "intrel" morphisms Rep_Integ Abs_Integ proof (rule equivpI) show "reflp intrel" by (auto simp: reflp_def) show "symp intrel" by (auto simp: symp_def) show "transp intrel" by (auto simp: transp_def) qed lemma eq_Abs_Integ [case_names Abs_Integ, cases type: int]: "(\x y. z = Abs_Integ (x, y) \ P) \ P" by (induct z) auto subsection \Integers form a commutative ring\ instantiation int :: comm_ring_1 begin lift_definition zero_int :: "int" is "(0, 0)" . lift_definition one_int :: "int" is "(1, 0)" . lift_definition plus_int :: "int \ int \ int" is "\(x, y) (u, v). (x + u, y + v)" by clarsimp lift_definition uminus_int :: "int \ int" is "\(x, y). (y, x)" by clarsimp lift_definition minus_int :: "int \ int \ int" is "\(x, y) (u, v). (x + v, y + u)" by clarsimp lift_definition times_int :: "int \ int \ int" is "\(x, y) (u, v). (x*u + y*v, x*v + y*u)" proof (clarsimp) fix s t u v w x y z :: nat assume "s + v = u + t" and "w + z = y + x" then have "(s + v) * w + (u + t) * x + u * (w + z) + v * (y + x) = (u + t) * w + (s + v) * x + u * (y + x) + v * (w + z)" by simp then show "(s * w + t * x) + (u * z + v * y) = (u * y + v * z) + (s * x + t * w)" by (simp add: algebra_simps) qed instance by standard (transfer; clarsimp simp: algebra_simps)+ end abbreviation int :: "nat \ int" where "int \ of_nat" lemma int_def: "int n = Abs_Integ (n, 0)" by (induct n) (simp add: zero_int.abs_eq, simp add: one_int.abs_eq plus_int.abs_eq) lemma int_transfer [transfer_rule]: includes lifting_syntax shows "rel_fun (=) pcr_int (\n. (n, 0)) int" by (simp add: rel_fun_def int.pcr_cr_eq cr_int_def int_def) lemma int_diff_cases: obtains (diff) m n where "z = int m - int n" by transfer clarsimp subsection \Integers are totally ordered\ instantiation int :: linorder begin lift_definition less_eq_int :: "int \ int \ bool" is "\(x, y) (u, v). x + v \ u + y" by auto lift_definition less_int :: "int \ int \ bool" is "\(x, y) (u, v). x + v < u + y" by auto instance by standard (transfer, force)+ end instantiation int :: distrib_lattice begin definition "(inf :: int \ int \ int) = min" definition "(sup :: int \ int \ int) = max" instance by standard (auto simp add: inf_int_def sup_int_def max_min_distrib2) end subsection \Ordering properties of arithmetic operations\ instance int :: ordered_cancel_ab_semigroup_add proof fix i j k :: int show "i \ j \ k + i \ k + j" by transfer clarsimp qed text \Strict Monotonicity of Multiplication.\ text \Strict, in 1st argument; proof is by induction on \k > 0\.\ lemma zmult_zless_mono2_lemma: "i < j \ 0 < k \ int k * i < int k * j" for i j :: int proof (induct k) case 0 then show ?case by simp next case (Suc k) then show ?case by (cases "k = 0") (simp_all add: distrib_right add_strict_mono) qed lemma zero_le_imp_eq_int: "0 \ k \ \n. k = int n" for k :: int apply transfer apply clarsimp apply (rule_tac x="a - b" in exI) apply simp done lemma zero_less_imp_eq_int: "0 < k \ \n>0. k = int n" for k :: int apply transfer apply clarsimp apply (rule_tac x="a - b" in exI) apply simp done lemma zmult_zless_mono2: "i < j \ 0 < k \ k * i < k * j" for i j k :: int by (drule zero_less_imp_eq_int) (auto simp add: zmult_zless_mono2_lemma) text \The integers form an ordered integral domain.\ instantiation int :: linordered_idom begin definition zabs_def: "\i::int\ = (if i < 0 then - i else i)" definition zsgn_def: "sgn (i::int) = (if i = 0 then 0 else if 0 < i then 1 else - 1)" instance proof fix i j k :: int show "i < j \ 0 < k \ k * i < k * j" by (rule zmult_zless_mono2) show "\i\ = (if i < 0 then -i else i)" by (simp only: zabs_def) show "sgn (i::int) = (if i=0 then 0 else if 0 w + 1 \ z" for w z :: int by transfer clarsimp lemma zless_iff_Suc_zadd: "w < z \ (\n. z = w + int (Suc n))" for w z :: int apply transfer apply auto apply (rename_tac a b c d) apply (rule_tac x="c+b - Suc(a+d)" in exI) apply arith done lemma zabs_less_one_iff [simp]: "\z\ < 1 \ z = 0" (is "?lhs \ ?rhs") for z :: int proof assume ?rhs then show ?lhs by simp next assume ?lhs with zless_imp_add1_zle [of "\z\" 1] have "\z\ + 1 \ 1" by simp then have "\z\ \ 0" by simp then show ?rhs by simp qed subsection \Embedding of the Integers into any \ring_1\: \of_int\\ context ring_1 begin lift_definition of_int :: "int \ 'a" is "\(i, j). of_nat i - of_nat j" by (clarsimp simp add: diff_eq_eq eq_diff_eq diff_add_eq of_nat_add [symmetric] simp del: of_nat_add) lemma of_int_0 [simp]: "of_int 0 = 0" by transfer simp lemma of_int_1 [simp]: "of_int 1 = 1" by transfer simp lemma of_int_add [simp]: "of_int (w + z) = of_int w + of_int z" by transfer (clarsimp simp add: algebra_simps) lemma of_int_minus [simp]: "of_int (- z) = - (of_int z)" by (transfer fixing: uminus) clarsimp lemma of_int_diff [simp]: "of_int (w - z) = of_int w - of_int z" using of_int_add [of w "- z"] by simp lemma of_int_mult [simp]: "of_int (w*z) = of_int w * of_int z" by (transfer fixing: times) (clarsimp simp add: algebra_simps) lemma mult_of_int_commute: "of_int x * y = y * of_int x" by (transfer fixing: times) (auto simp: algebra_simps mult_of_nat_commute) text \Collapse nested embeddings.\ lemma of_int_of_nat_eq [simp]: "of_int (int n) = of_nat n" by (induct n) auto lemma of_int_numeral [simp, code_post]: "of_int (numeral k) = numeral k" by (simp add: of_nat_numeral [symmetric] of_int_of_nat_eq [symmetric]) lemma of_int_neg_numeral [code_post]: "of_int (- numeral k) = - numeral k" by simp lemma of_int_power [simp]: "of_int (z ^ n) = of_int z ^ n" by (induct n) simp_all lemma of_int_of_bool [simp]: "of_int (of_bool P) = of_bool P" by auto end context ring_char_0 begin lemma of_int_eq_iff [simp]: "of_int w = of_int z \ w = z" by transfer (clarsimp simp add: algebra_simps of_nat_add [symmetric] simp del: of_nat_add) text \Special cases where either operand is zero.\ lemma of_int_eq_0_iff [simp]: "of_int z = 0 \ z = 0" using of_int_eq_iff [of z 0] by simp lemma of_int_0_eq_iff [simp]: "0 = of_int z \ z = 0" using of_int_eq_iff [of 0 z] by simp lemma of_int_eq_1_iff [iff]: "of_int z = 1 \ z = 1" using of_int_eq_iff [of z 1] by simp lemma numeral_power_eq_of_int_cancel_iff [simp]: "numeral x ^ n = of_int y \ numeral x ^ n = y" using of_int_eq_iff[of "numeral x ^ n" y, unfolded of_int_numeral of_int_power] . lemma of_int_eq_numeral_power_cancel_iff [simp]: "of_int y = numeral x ^ n \ y = numeral x ^ n" using numeral_power_eq_of_int_cancel_iff [of x n y] by (metis (mono_tags)) lemma neg_numeral_power_eq_of_int_cancel_iff [simp]: "(- numeral x) ^ n = of_int y \ (- numeral x) ^ n = y" using of_int_eq_iff[of "(- numeral x) ^ n" y] by simp lemma of_int_eq_neg_numeral_power_cancel_iff [simp]: "of_int y = (- numeral x) ^ n \ y = (- numeral x) ^ n" using neg_numeral_power_eq_of_int_cancel_iff[of x n y] by (metis (mono_tags)) lemma of_int_eq_of_int_power_cancel_iff[simp]: "(of_int b) ^ w = of_int x \ b ^ w = x" by (metis of_int_power of_int_eq_iff) lemma of_int_power_eq_of_int_cancel_iff[simp]: "of_int x = (of_int b) ^ w \ x = b ^ w" by (metis of_int_eq_of_int_power_cancel_iff) end context linordered_idom begin text \Every \linordered_idom\ has characteristic zero.\ subclass ring_char_0 .. lemma of_int_le_iff [simp]: "of_int w \ of_int z \ w \ z" by (transfer fixing: less_eq) (clarsimp simp add: algebra_simps of_nat_add [symmetric] simp del: of_nat_add) lemma of_int_less_iff [simp]: "of_int w < of_int z \ w < z" by (simp add: less_le order_less_le) lemma of_int_0_le_iff [simp]: "0 \ of_int z \ 0 \ z" using of_int_le_iff [of 0 z] by simp lemma of_int_le_0_iff [simp]: "of_int z \ 0 \ z \ 0" using of_int_le_iff [of z 0] by simp lemma of_int_0_less_iff [simp]: "0 < of_int z \ 0 < z" using of_int_less_iff [of 0 z] by simp lemma of_int_less_0_iff [simp]: "of_int z < 0 \ z < 0" using of_int_less_iff [of z 0] by simp lemma of_int_1_le_iff [simp]: "1 \ of_int z \ 1 \ z" using of_int_le_iff [of 1 z] by simp lemma of_int_le_1_iff [simp]: "of_int z \ 1 \ z \ 1" using of_int_le_iff [of z 1] by simp lemma of_int_1_less_iff [simp]: "1 < of_int z \ 1 < z" using of_int_less_iff [of 1 z] by simp lemma of_int_less_1_iff [simp]: "of_int z < 1 \ z < 1" using of_int_less_iff [of z 1] by simp lemma of_int_pos: "z > 0 \ of_int z > 0" by simp lemma of_int_nonneg: "z \ 0 \ of_int z \ 0" by simp lemma of_int_abs [simp]: "of_int \x\ = \of_int x\" by (auto simp add: abs_if) lemma of_int_lessD: assumes "\of_int n\ < x" shows "n = 0 \ x > 1" proof (cases "n = 0") case True then show ?thesis by simp next case False then have "\n\ \ 0" by simp then have "\n\ > 0" by simp then have "\n\ \ 1" using zless_imp_add1_zle [of 0 "\n\"] by simp then have "\of_int n\ \ 1" unfolding of_int_1_le_iff [of "\n\", symmetric] by simp then have "1 < x" using assms by (rule le_less_trans) then show ?thesis .. qed lemma of_int_leD: assumes "\of_int n\ \ x" shows "n = 0 \ 1 \ x" proof (cases "n = 0") case True then show ?thesis by simp next case False then have "\n\ \ 0" by simp then have "\n\ > 0" by simp then have "\n\ \ 1" using zless_imp_add1_zle [of 0 "\n\"] by simp then have "\of_int n\ \ 1" unfolding of_int_1_le_iff [of "\n\", symmetric] by simp then have "1 \ x" using assms by (rule order_trans) then show ?thesis .. qed lemma numeral_power_le_of_int_cancel_iff [simp]: "numeral x ^ n \ of_int a \ numeral x ^ n \ a" by (metis (mono_tags) local.of_int_eq_numeral_power_cancel_iff of_int_le_iff) lemma of_int_le_numeral_power_cancel_iff [simp]: "of_int a \ numeral x ^ n \ a \ numeral x ^ n" by (metis (mono_tags) local.numeral_power_eq_of_int_cancel_iff of_int_le_iff) lemma numeral_power_less_of_int_cancel_iff [simp]: "numeral x ^ n < of_int a \ numeral x ^ n < a" by (metis (mono_tags) local.of_int_eq_numeral_power_cancel_iff of_int_less_iff) lemma of_int_less_numeral_power_cancel_iff [simp]: "of_int a < numeral x ^ n \ a < numeral x ^ n" by (metis (mono_tags) local.of_int_eq_numeral_power_cancel_iff of_int_less_iff) lemma neg_numeral_power_le_of_int_cancel_iff [simp]: "(- numeral x) ^ n \ of_int a \ (- numeral x) ^ n \ a" by (metis (mono_tags) of_int_le_iff of_int_neg_numeral of_int_power) lemma of_int_le_neg_numeral_power_cancel_iff [simp]: "of_int a \ (- numeral x) ^ n \ a \ (- numeral x) ^ n" by (metis (mono_tags) of_int_le_iff of_int_neg_numeral of_int_power) lemma neg_numeral_power_less_of_int_cancel_iff [simp]: "(- numeral x) ^ n < of_int a \ (- numeral x) ^ n < a" using of_int_less_iff[of "(- numeral x) ^ n" a] by simp lemma of_int_less_neg_numeral_power_cancel_iff [simp]: "of_int a < (- numeral x) ^ n \ a < (- numeral x::int) ^ n" using of_int_less_iff[of a "(- numeral x) ^ n"] by simp lemma of_int_le_of_int_power_cancel_iff[simp]: "(of_int b) ^ w \ of_int x \ b ^ w \ x" by (metis (mono_tags) of_int_le_iff of_int_power) lemma of_int_power_le_of_int_cancel_iff[simp]: "of_int x \ (of_int b) ^ w\ x \ b ^ w" by (metis (mono_tags) of_int_le_iff of_int_power) lemma of_int_less_of_int_power_cancel_iff[simp]: "(of_int b) ^ w < of_int x \ b ^ w < x" by (metis (mono_tags) of_int_less_iff of_int_power) lemma of_int_power_less_of_int_cancel_iff[simp]: "of_int x < (of_int b) ^ w\ x < b ^ w" by (metis (mono_tags) of_int_less_iff of_int_power) lemma of_int_max: "of_int (max x y) = max (of_int x) (of_int y)" by (auto simp: max_def) lemma of_int_min: "of_int (min x y) = min (of_int x) (of_int y)" by (auto simp: min_def) end context division_ring begin lemmas mult_inverse_of_int_commute = mult_commute_imp_mult_inverse_commute[OF mult_of_int_commute] end text \Comparisons involving \<^term>\of_int\.\ lemma of_int_eq_numeral_iff [iff]: "of_int z = (numeral n :: 'a::ring_char_0) \ z = numeral n" using of_int_eq_iff by fastforce lemma of_int_le_numeral_iff [simp]: "of_int z \ (numeral n :: 'a::linordered_idom) \ z \ numeral n" using of_int_le_iff [of z "numeral n"] by simp lemma of_int_numeral_le_iff [simp]: "(numeral n :: 'a::linordered_idom) \ of_int z \ numeral n \ z" using of_int_le_iff [of "numeral n"] by simp lemma of_int_less_numeral_iff [simp]: "of_int z < (numeral n :: 'a::linordered_idom) \ z < numeral n" using of_int_less_iff [of z "numeral n"] by simp lemma of_int_numeral_less_iff [simp]: "(numeral n :: 'a::linordered_idom) < of_int z \ numeral n < z" using of_int_less_iff [of "numeral n" z] by simp lemma of_nat_less_of_int_iff: "(of_nat n::'a::linordered_idom) < of_int x \ int n < x" by (metis of_int_of_nat_eq of_int_less_iff) lemma of_int_eq_id [simp]: "of_int = id" proof show "of_int z = id z" for z by (cases z rule: int_diff_cases) simp qed instance int :: no_top apply standard apply (rule_tac x="x + 1" in exI) apply simp done instance int :: no_bot apply standard apply (rule_tac x="x - 1" in exI) apply simp done subsection \Magnitude of an Integer, as a Natural Number: \nat\\ lift_definition nat :: "int \ nat" is "\(x, y). x - y" by auto lemma nat_int [simp]: "nat (int n) = n" by transfer simp lemma int_nat_eq [simp]: "int (nat z) = (if 0 \ z then z else 0)" by transfer clarsimp lemma nat_0_le: "0 \ z \ int (nat z) = z" by simp lemma nat_le_0 [simp]: "z \ 0 \ nat z = 0" by transfer clarsimp lemma nat_le_eq_zle: "0 < w \ 0 \ z \ nat w \ nat z \ w \ z" by transfer (clarsimp, arith) text \An alternative condition is \<^term>\0 \ w\.\ lemma nat_mono_iff: "0 < z \ nat w < nat z \ w < z" by (simp add: nat_le_eq_zle linorder_not_le [symmetric]) lemma nat_less_eq_zless: "0 \ w \ nat w < nat z \ w < z" by (simp add: nat_le_eq_zle linorder_not_le [symmetric]) lemma zless_nat_conj [simp]: "nat w < nat z \ 0 < z \ w < z" by transfer (clarsimp, arith) lemma nonneg_int_cases: assumes "0 \ k" obtains n where "k = int n" proof - from assms have "k = int (nat k)" by simp then show thesis by (rule that) qed lemma pos_int_cases: assumes "0 < k" obtains n where "k = int n" and "n > 0" proof - from assms have "0 \ k" by simp then obtain n where "k = int n" by (rule nonneg_int_cases) moreover have "n > 0" using \k = int n\ assms by simp ultimately show thesis by (rule that) qed lemma nonpos_int_cases: assumes "k \ 0" obtains n where "k = - int n" proof - from assms have "- k \ 0" by simp then obtain n where "- k = int n" by (rule nonneg_int_cases) then have "k = - int n" by simp then show thesis by (rule that) qed lemma neg_int_cases: assumes "k < 0" obtains n where "k = - int n" and "n > 0" proof - from assms have "- k > 0" by simp then obtain n where "- k = int n" and "- k > 0" by (blast elim: pos_int_cases) then have "k = - int n" and "n > 0" by simp_all then show thesis by (rule that) qed lemma nat_eq_iff: "nat w = m \ (if 0 \ w then w = int m else m = 0)" by transfer (clarsimp simp add: le_imp_diff_is_add) lemma nat_eq_iff2: "m = nat w \ (if 0 \ w then w = int m else m = 0)" using nat_eq_iff [of w m] by auto lemma nat_0 [simp]: "nat 0 = 0" by (simp add: nat_eq_iff) lemma nat_1 [simp]: "nat 1 = Suc 0" by (simp add: nat_eq_iff) lemma nat_numeral [simp]: "nat (numeral k) = numeral k" by (simp add: nat_eq_iff) lemma nat_neg_numeral [simp]: "nat (- numeral k) = 0" by simp lemma nat_2: "nat 2 = Suc (Suc 0)" by simp lemma nat_less_iff: "0 \ w \ nat w < m \ w < of_nat m" by transfer (clarsimp, arith) lemma nat_le_iff: "nat x \ n \ x \ int n" by transfer (clarsimp simp add: le_diff_conv) lemma nat_mono: "x \ y \ nat x \ nat y" by transfer auto lemma nat_0_iff[simp]: "nat i = 0 \ i \ 0" for i :: int by transfer clarsimp lemma int_eq_iff: "of_nat m = z \ m = nat z \ 0 \ z" by (auto simp add: nat_eq_iff2) lemma zero_less_nat_eq [simp]: "0 < nat z \ 0 < z" using zless_nat_conj [of 0] by auto lemma nat_add_distrib: "0 \ z \ 0 \ z' \ nat (z + z') = nat z + nat z'" by transfer clarsimp lemma nat_diff_distrib': "0 \ x \ 0 \ y \ nat (x - y) = nat x - nat y" by transfer clarsimp lemma nat_diff_distrib: "0 \ z' \ z' \ z \ nat (z - z') = nat z - nat z'" by (rule nat_diff_distrib') auto lemma nat_zminus_int [simp]: "nat (- int n) = 0" by transfer simp lemma le_nat_iff: "k \ 0 \ n \ nat k \ int n \ k" by transfer auto lemma zless_nat_eq_int_zless: "m < nat z \ int m < z" by transfer (clarsimp simp add: less_diff_conv) lemma (in ring_1) of_nat_nat [simp]: "0 \ z \ of_nat (nat z) = of_int z" by transfer (clarsimp simp add: of_nat_diff) lemma diff_nat_numeral [simp]: "(numeral v :: nat) - numeral v' = nat (numeral v - numeral v')" by (simp only: nat_diff_distrib' zero_le_numeral nat_numeral) lemma nat_abs_triangle_ineq: "nat \k + l\ \ nat \k\ + nat \l\" by (simp add: nat_add_distrib [symmetric] nat_le_eq_zle abs_triangle_ineq) lemma nat_of_bool [simp]: "nat (of_bool P) = of_bool P" by auto lemma split_nat [arith_split]: "P (nat i) \ ((\n. i = int n \ P n) \ (i < 0 \ P 0))" (is "?P = (?L \ ?R)") for i :: int proof (cases "i < 0") case True then show ?thesis by auto next case False have "?P = ?L" proof assume ?P then show ?L using False by auto next assume ?L moreover from False have "int (nat i) = i" by (simp add: not_less) ultimately show ?P by simp qed with False show ?thesis by simp qed lemma all_nat: "(\x. P x) \ (\x\0. P (nat x))" by (auto split: split_nat) lemma ex_nat: "(\x. P x) \ (\x. 0 \ x \ P (nat x))" proof assume "\x. P x" then obtain x where "P x" .. then have "int x \ 0 \ P (nat (int x))" by simp then show "\x\0. P (nat x)" .. next assume "\x\0. P (nat x)" then show "\x. P x" by auto qed text \For termination proofs:\ lemma measure_function_int[measure_function]: "is_measure (nat \ abs)" .. subsection \Lemmas about the Function \<^term>\of_nat\ and Orderings\ lemma negative_zless_0: "- (int (Suc n)) < (0 :: int)" by (simp add: order_less_le del: of_nat_Suc) lemma negative_zless [iff]: "- (int (Suc n)) < int m" by (rule negative_zless_0 [THEN order_less_le_trans], simp) lemma negative_zle_0: "- int n \ 0" by (simp add: minus_le_iff) lemma negative_zle [iff]: "- int n \ int m" by (rule order_trans [OF negative_zle_0 of_nat_0_le_iff]) lemma not_zle_0_negative [simp]: "\ 0 \ - int (Suc n)" by (subst le_minus_iff) (simp del: of_nat_Suc) lemma int_zle_neg: "int n \ - int m \ n = 0 \ m = 0" by transfer simp lemma not_int_zless_negative [simp]: "\ int n < - int m" by (simp add: linorder_not_less) lemma negative_eq_positive [simp]: "- int n = of_nat m \ n = 0 \ m = 0" by (force simp add: order_eq_iff [of "- of_nat n"] int_zle_neg) lemma zle_iff_zadd: "w \ z \ (\n. z = w + int n)" (is "?lhs \ ?rhs") proof assume ?rhs then show ?lhs by auto next assume ?lhs then have "0 \ z - w" by simp then obtain n where "z - w = int n" using zero_le_imp_eq_int [of "z - w"] by blast then have "z = w + int n" by simp then show ?rhs .. qed lemma zadd_int_left: "int m + (int n + z) = int (m + n) + z" by simp text \ This version is proved for all ordered rings, not just integers! It is proved here because attribute \arith_split\ is not available in theory \Rings\. But is it really better than just rewriting with \abs_if\? \ lemma abs_split [arith_split, no_atp]: "P \a\ \ (0 \ a \ P a) \ (a < 0 \ P (- a))" for a :: "'a::linordered_idom" by (force dest: order_less_le_trans simp add: abs_if linorder_not_less) lemma negD: "x < 0 \ \n. x = - (int (Suc n))" apply transfer apply clarsimp apply (rule_tac x="b - Suc a" in exI) apply arith done subsection \Cases and induction\ text \ Now we replace the case analysis rule by a more conventional one: whether an integer is negative or not. \ text \This version is symmetric in the two subgoals.\ lemma int_cases2 [case_names nonneg nonpos, cases type: int]: "(\n. z = int n \ P) \ (\n. z = - (int n) \ P) \ P" by (cases "z < 0") (auto simp add: linorder_not_less dest!: negD nat_0_le [THEN sym]) text \This is the default, with a negative case.\ lemma int_cases [case_names nonneg neg, cases type: int]: "(\n. z = int n \ P) \ (\n. z = - (int (Suc n)) \ P) \ P" apply (cases "z < 0") apply (blast dest!: negD) apply (simp add: linorder_not_less del: of_nat_Suc) apply auto apply (blast dest: nat_0_le [THEN sym]) done lemma int_cases3 [case_names zero pos neg]: fixes k :: int assumes "k = 0 \ P" and "\n. k = int n \ n > 0 \ P" and "\n. k = - int n \ n > 0 \ P" shows "P" proof (cases k "0::int" rule: linorder_cases) case equal with assms(1) show P by simp next case greater then have *: "nat k > 0" by simp moreover from * have "k = int (nat k)" by auto ultimately show P using assms(2) by blast next case less then have *: "nat (- k) > 0" by simp moreover from * have "k = - int (nat (- k))" by auto ultimately show P using assms(3) by blast qed lemma int_of_nat_induct [case_names nonneg neg, induct type: int]: "(\n. P (int n)) \ (\n. P (- (int (Suc n)))) \ P z" by (cases z) auto lemma sgn_mult_dvd_iff [simp]: "sgn r * l dvd k \ l dvd k \ (r = 0 \ k = 0)" for k l r :: int by (cases r rule: int_cases3) auto lemma mult_sgn_dvd_iff [simp]: "l * sgn r dvd k \ l dvd k \ (r = 0 \ k = 0)" for k l r :: int using sgn_mult_dvd_iff [of r l k] by (simp add: ac_simps) lemma dvd_sgn_mult_iff [simp]: "l dvd sgn r * k \ l dvd k \ r = 0" for k l r :: int by (cases r rule: int_cases3) simp_all lemma dvd_mult_sgn_iff [simp]: "l dvd k * sgn r \ l dvd k \ r = 0" for k l r :: int using dvd_sgn_mult_iff [of l r k] by (simp add: ac_simps) lemma int_sgnE: fixes k :: int obtains n and l where "k = sgn l * int n" proof - have "k = sgn k * int (nat \k\)" by (simp add: sgn_mult_abs) then show ?thesis .. qed subsubsection \Binary comparisons\ text \Preliminaries\ lemma le_imp_0_less: fixes z :: int assumes le: "0 \ z" shows "0 < 1 + z" proof - have "0 \ z" by fact also have "\ < z + 1" by (rule less_add_one) also have "\ = 1 + z" by (simp add: ac_simps) finally show "0 < 1 + z" . qed lemma odd_less_0_iff: "1 + z + z < 0 \ z < 0" for z :: int proof (cases z) case (nonneg n) then show ?thesis by (simp add: linorder_not_less add.assoc add_increasing le_imp_0_less [THEN order_less_imp_le]) next case (neg n) then show ?thesis by (simp del: of_nat_Suc of_nat_add of_nat_1 add: algebra_simps of_nat_1 [where 'a=int, symmetric] of_nat_add [symmetric]) qed subsubsection \Comparisons, for Ordered Rings\ lemma odd_nonzero: "1 + z + z \ 0" for z :: int proof (cases z) case (nonneg n) have le: "0 \ z + z" by (simp add: nonneg add_increasing) then show ?thesis using le_imp_0_less [OF le] by (auto simp: ac_simps) next case (neg n) show ?thesis proof assume eq: "1 + z + z = 0" have "0 < 1 + (int n + int n)" by (simp add: le_imp_0_less add_increasing) also have "\ = - (1 + z + z)" by (simp add: neg add.assoc [symmetric]) also have "\ = 0" by (simp add: eq) finally have "0<0" .. then show False by blast qed qed subsection \The Set of Integers\ context ring_1 begin definition Ints :: "'a set" ("\") where "\ = range of_int" lemma Ints_of_int [simp]: "of_int z \ \" by (simp add: Ints_def) lemma Ints_of_nat [simp]: "of_nat n \ \" using Ints_of_int [of "of_nat n"] by simp lemma Ints_0 [simp]: "0 \ \" using Ints_of_int [of "0"] by simp lemma Ints_1 [simp]: "1 \ \" using Ints_of_int [of "1"] by simp lemma Ints_numeral [simp]: "numeral n \ \" by (subst of_nat_numeral [symmetric], rule Ints_of_nat) lemma Ints_add [simp]: "a \ \ \ b \ \ \ a + b \ \" apply (auto simp add: Ints_def) apply (rule range_eqI) apply (rule of_int_add [symmetric]) done lemma Ints_minus [simp]: "a \ \ \ -a \ \" apply (auto simp add: Ints_def) apply (rule range_eqI) apply (rule of_int_minus [symmetric]) done lemma minus_in_Ints_iff: "-x \ \ \ x \ \" using Ints_minus[of x] Ints_minus[of "-x"] by auto lemma Ints_diff [simp]: "a \ \ \ b \ \ \ a - b \ \" apply (auto simp add: Ints_def) apply (rule range_eqI) apply (rule of_int_diff [symmetric]) done lemma Ints_mult [simp]: "a \ \ \ b \ \ \ a * b \ \" apply (auto simp add: Ints_def) apply (rule range_eqI) apply (rule of_int_mult [symmetric]) done lemma Ints_power [simp]: "a \ \ \ a ^ n \ \" by (induct n) simp_all lemma Ints_cases [cases set: Ints]: assumes "q \ \" obtains (of_int) z where "q = of_int z" unfolding Ints_def proof - from \q \ \\ have "q \ range of_int" unfolding Ints_def . then obtain z where "q = of_int z" .. then show thesis .. qed lemma Ints_induct [case_names of_int, induct set: Ints]: "q \ \ \ (\z. P (of_int z)) \ P q" by (rule Ints_cases) auto lemma Nats_subset_Ints: "\ \ \" unfolding Nats_def Ints_def by (rule subsetI, elim imageE, hypsubst, subst of_int_of_nat_eq[symmetric], rule imageI) simp_all lemma Nats_altdef1: "\ = {of_int n |n. n \ 0}" proof (intro subsetI equalityI) fix x :: 'a assume "x \ {of_int n |n. n \ 0}" then obtain n where "x = of_int n" "n \ 0" by (auto elim!: Ints_cases) then have "x = of_nat (nat n)" by (subst of_nat_nat) simp_all then show "x \ \" by simp next fix x :: 'a assume "x \ \" then obtain n where "x = of_nat n" by (auto elim!: Nats_cases) then have "x = of_int (int n)" by simp also have "int n \ 0" by simp then have "of_int (int n) \ {of_int n |n. n \ 0}" by blast finally show "x \ {of_int n |n. n \ 0}" . qed end lemma (in linordered_idom) Ints_abs [simp]: shows "a \ \ \ abs a \ \" by (auto simp: abs_if) lemma (in linordered_idom) Nats_altdef2: "\ = {n \ \. n \ 0}" proof (intro subsetI equalityI) fix x :: 'a assume "x \ {n \ \. n \ 0}" then obtain n where "x = of_int n" "n \ 0" by (auto elim!: Ints_cases) then have "x = of_nat (nat n)" by (subst of_nat_nat) simp_all then show "x \ \" by simp qed (auto elim!: Nats_cases) lemma (in idom_divide) of_int_divide_in_Ints: "of_int a div of_int b \ \" if "b dvd a" proof - from that obtain c where "a = b * c" .. then show ?thesis by (cases "of_int b = 0") simp_all qed text \The premise involving \<^term>\Ints\ prevents \<^term>\a = 1/2\.\ lemma Ints_double_eq_0_iff: fixes a :: "'a::ring_char_0" assumes in_Ints: "a \ \" shows "a + a = 0 \ a = 0" (is "?lhs \ ?rhs") proof - from in_Ints have "a \ range of_int" unfolding Ints_def [symmetric] . then obtain z where a: "a = of_int z" .. show ?thesis proof assume ?rhs then show ?lhs by simp next assume ?lhs with a have "of_int (z + z) = (of_int 0 :: 'a)" by simp then have "z + z = 0" by (simp only: of_int_eq_iff) then have "z = 0" by (simp only: double_zero) with a show ?rhs by simp qed qed lemma Ints_odd_nonzero: fixes a :: "'a::ring_char_0" assumes in_Ints: "a \ \" shows "1 + a + a \ 0" proof - from in_Ints have "a \ range of_int" unfolding Ints_def [symmetric] . then obtain z where a: "a = of_int z" .. show ?thesis proof assume "1 + a + a = 0" with a have "of_int (1 + z + z) = (of_int 0 :: 'a)" by simp then have "1 + z + z = 0" by (simp only: of_int_eq_iff) with odd_nonzero show False by blast qed qed lemma Nats_numeral [simp]: "numeral w \ \" using of_nat_in_Nats [of "numeral w"] by simp lemma Ints_odd_less_0: fixes a :: "'a::linordered_idom" assumes in_Ints: "a \ \" shows "1 + a + a < 0 \ a < 0" proof - from in_Ints have "a \ range of_int" unfolding Ints_def [symmetric] . then obtain z where a: "a = of_int z" .. with a have "1 + a + a < 0 \ of_int (1 + z + z) < (of_int 0 :: 'a)" by simp also have "\ \ z < 0" by (simp only: of_int_less_iff odd_less_0_iff) also have "\ \ a < 0" by (simp add: a) finally show ?thesis . qed subsection \\<^term>\sum\ and \<^term>\prod\\ context semiring_1 begin lemma of_nat_sum [simp]: "of_nat (sum f A) = (\x\A. of_nat (f x))" by (induction A rule: infinite_finite_induct) auto end context ring_1 begin lemma of_int_sum [simp]: "of_int (sum f A) = (\x\A. of_int (f x))" by (induction A rule: infinite_finite_induct) auto end context comm_semiring_1 begin lemma of_nat_prod [simp]: "of_nat (prod f A) = (\x\A. of_nat (f x))" by (induction A rule: infinite_finite_induct) auto end context comm_ring_1 begin lemma of_int_prod [simp]: "of_int (prod f A) = (\x\A. of_int (f x))" by (induction A rule: infinite_finite_induct) auto end subsection \Setting up simplification procedures\ ML_file \Tools/int_arith.ML\ declaration \K ( Lin_Arith.add_discrete_type \<^type_name>\Int.int\ #> Lin_Arith.add_lessD @{thm zless_imp_add1_zle} #> Lin_Arith.add_inj_thms @{thms of_nat_le_iff [THEN iffD2] of_nat_eq_iff [THEN iffD2]} #> Lin_Arith.add_inj_const (\<^const_name>\of_nat\, \<^typ>\nat \ int\) #> Lin_Arith.add_simps @{thms of_int_0 of_int_1 of_int_add of_int_mult of_int_numeral of_int_neg_numeral nat_0 nat_1 diff_nat_numeral nat_numeral neg_less_iff_less True_implies_equals distrib_left [where a = "numeral v" for v] distrib_left [where a = "- numeral v" for v] div_by_1 div_0 times_divide_eq_right times_divide_eq_left minus_divide_left [THEN sym] minus_divide_right [THEN sym] add_divide_distrib diff_divide_distrib of_int_minus of_int_diff of_int_of_nat_eq} #> Lin_Arith.add_simprocs [Int_Arith.zero_one_idom_simproc] )\ simproc_setup fast_arith ("(m::'a::linordered_idom) < n" | "(m::'a::linordered_idom) \ n" | "(m::'a::linordered_idom) = n") = \K Lin_Arith.simproc\ subsection\More Inequality Reasoning\ lemma zless_add1_eq: "w < z + 1 \ w < z \ w = z" for w z :: int by arith lemma add1_zle_eq: "w + 1 \ z \ w < z" for w z :: int by arith lemma zle_diff1_eq [simp]: "w \ z - 1 \ w < z" for w z :: int by arith lemma zle_add1_eq_le [simp]: "w < z + 1 \ w \ z" for w z :: int by arith lemma int_one_le_iff_zero_less: "1 \ z \ 0 < z" for z :: int by arith lemma Ints_nonzero_abs_ge1: fixes x:: "'a :: linordered_idom" assumes "x \ Ints" "x \ 0" shows "1 \ abs x" proof (rule Ints_cases [OF \x \ Ints\]) fix z::int assume "x = of_int z" with \x \ 0\ show "1 \ \x\" apply (auto simp add: abs_if) by (metis diff_0 of_int_1 of_int_le_iff of_int_minus zle_diff1_eq) qed lemma Ints_nonzero_abs_less1: fixes x:: "'a :: linordered_idom" shows "\x \ Ints; abs x < 1\ \ x = 0" using Ints_nonzero_abs_ge1 [of x] by auto lemma Ints_eq_abs_less1: fixes x:: "'a :: linordered_idom" shows "\x \ Ints; y \ Ints\ \ x = y \ abs (x-y) < 1" using eq_iff_diff_eq_0 by (fastforce intro: Ints_nonzero_abs_less1) subsection \The functions \<^term>\nat\ and \<^term>\int\\ text \Simplify the term \<^term>\w + - z\.\ lemma one_less_nat_eq [simp]: "Suc 0 < nat z \ 1 < z" using zless_nat_conj [of 1 z] by auto lemma int_eq_iff_numeral [simp]: "int m = numeral v \ m = numeral v" by (simp add: int_eq_iff) lemma nat_abs_int_diff: "nat \int a - int b\ = (if a \ b then b - a else a - b)" by auto lemma nat_int_add: "nat (int a + int b) = a + b" by auto context ring_1 begin lemma of_int_of_nat [nitpick_simp]: "of_int k = (if k < 0 then - of_nat (nat (- k)) else of_nat (nat k))" proof (cases "k < 0") case True then have "0 \ - k" by simp then have "of_nat (nat (- k)) = of_int (- k)" by (rule of_nat_nat) with True show ?thesis by simp next case False then show ?thesis by (simp add: not_less) qed end lemma transfer_rule_of_int: includes lifting_syntax fixes R :: "'a::ring_1 \ 'b::ring_1 \ bool" assumes [transfer_rule]: "R 0 0" "R 1 1" "(R ===> R ===> R) (+) (+)" "(R ===> R) uminus uminus" shows "((=) ===> R) of_int of_int" proof - note assms note transfer_rule_of_nat [transfer_rule] have [transfer_rule]: "((=) ===> R) of_nat of_nat" by transfer_prover show ?thesis by (unfold of_int_of_nat [abs_def]) transfer_prover qed lemma nat_mult_distrib: fixes z z' :: int assumes "0 \ z" shows "nat (z * z') = nat z * nat z'" proof (cases "0 \ z'") case False with assms have "z * z' \ 0" by (simp add: not_le mult_le_0_iff) then have "nat (z * z') = 0" by simp moreover from False have "nat z' = 0" by simp ultimately show ?thesis by simp next case True with assms have ge_0: "z * z' \ 0" by (simp add: zero_le_mult_iff) show ?thesis by (rule injD [of "of_nat :: nat \ int", OF inj_of_nat]) (simp only: of_nat_mult of_nat_nat [OF True] of_nat_nat [OF assms] of_nat_nat [OF ge_0], simp) qed lemma nat_mult_distrib_neg: "z \ 0 \ nat (z * z') = nat (- z) * nat (- z')" for z z' :: int apply (rule trans) apply (rule_tac [2] nat_mult_distrib) apply auto done lemma nat_abs_mult_distrib: "nat \w * z\ = nat \w\ * nat \z\" by (cases "z = 0 \ w = 0") (auto simp add: abs_if nat_mult_distrib [symmetric] nat_mult_distrib_neg [symmetric] mult_less_0_iff) lemma int_in_range_abs [simp]: "int n \ range abs" proof (rule range_eqI) show "int n = \int n\" by simp qed lemma range_abs_Nats [simp]: "range abs = (\ :: int set)" proof - have "\k\ \ \" for k :: int by (cases k) simp_all moreover have "k \ range abs" if "k \ \" for k :: int using that by induct simp ultimately show ?thesis by blast qed lemma Suc_nat_eq_nat_zadd1: "0 \ z \ Suc (nat z) = nat (1 + z)" for z :: int by (rule sym) (simp add: nat_eq_iff) lemma diff_nat_eq_if: "nat z - nat z' = (if z' < 0 then nat z else let d = z - z' in if d < 0 then 0 else nat d)" by (simp add: Let_def nat_diff_distrib [symmetric]) lemma nat_numeral_diff_1 [simp]: "numeral v - (1::nat) = nat (numeral v - 1)" using diff_nat_numeral [of v Num.One] by simp subsection \Induction principles for int\ text \Well-founded segments of the integers.\ definition int_ge_less_than :: "int \ (int \ int) set" where "int_ge_less_than d = {(z', z). d \ z' \ z' < z}" lemma wf_int_ge_less_than: "wf (int_ge_less_than d)" proof - have "int_ge_less_than d \ measure (\z. nat (z - d))" by (auto simp add: int_ge_less_than_def) then show ?thesis by (rule wf_subset [OF wf_measure]) qed text \ This variant looks odd, but is typical of the relations suggested by RankFinder.\ definition int_ge_less_than2 :: "int \ (int \ int) set" where "int_ge_less_than2 d = {(z',z). d \ z \ z' < z}" lemma wf_int_ge_less_than2: "wf (int_ge_less_than2 d)" proof - have "int_ge_less_than2 d \ measure (\z. nat (1 + z - d))" by (auto simp add: int_ge_less_than2_def) then show ?thesis by (rule wf_subset [OF wf_measure]) qed (* `set:int': dummy construction *) theorem int_ge_induct [case_names base step, induct set: int]: fixes i :: int assumes ge: "k \ i" and base: "P k" and step: "\i. k \ i \ P i \ P (i + 1)" shows "P i" proof - have "\i::int. n = nat (i - k) \ k \ i \ P i" for n proof (induct n) case 0 then have "i = k" by arith with base show "P i" by simp next case (Suc n) then have "n = nat ((i - 1) - k)" by arith moreover have k: "k \ i - 1" using Suc.prems by arith ultimately have "P (i - 1)" by (rule Suc.hyps) from step [OF k this] show ?case by simp qed with ge show ?thesis by fast qed (* `set:int': dummy construction *) theorem int_gr_induct [case_names base step, induct set: int]: fixes i k :: int assumes gr: "k < i" and base: "P (k + 1)" and step: "\i. k < i \ P i \ P (i + 1)" shows "P i" apply (rule int_ge_induct[of "k + 1"]) using gr apply arith apply (rule base) apply (rule step) apply simp_all done theorem int_le_induct [consumes 1, case_names base step]: fixes i k :: int assumes le: "i \ k" and base: "P k" and step: "\i. i \ k \ P i \ P (i - 1)" shows "P i" proof - have "\i::int. n = nat(k-i) \ i \ k \ P i" for n proof (induct n) case 0 then have "i = k" by arith with base show "P i" by simp next case (Suc n) then have "n = nat (k - (i + 1))" by arith moreover have k: "i + 1 \ k" using Suc.prems by arith ultimately have "P (i + 1)" by (rule Suc.hyps) from step[OF k this] show ?case by simp qed with le show ?thesis by fast qed theorem int_less_induct [consumes 1, case_names base step]: fixes i k :: int assumes less: "i < k" and base: "P (k - 1)" and step: "\i. i < k \ P i \ P (i - 1)" shows "P i" apply (rule int_le_induct[of _ "k - 1"]) using less apply arith apply (rule base) apply (rule step) apply simp_all done theorem int_induct [case_names base step1 step2]: fixes k :: int assumes base: "P k" and step1: "\i. k \ i \ P i \ P (i + 1)" and step2: "\i. k \ i \ P i \ P (i - 1)" shows "P i" proof - have "i \ k \ i \ k" by arith then show ?thesis proof assume "i \ k" then show ?thesis using base by (rule int_ge_induct) (fact step1) next assume "i \ k" then show ?thesis using base by (rule int_le_induct) (fact step2) qed qed subsection \Intermediate value theorems\ lemma nat_intermed_int_val: "\i. m \ i \ i \ n \ f i = k" if "\i. m \ i \ i < n \ \f (Suc i) - f i\ \ 1" "m \ n" "f m \ k" "k \ f n" for m n :: nat and k :: int proof - have "(\if (Suc i) - f i\ \ 1) \ f 0 \ k \ k \ f n \ (\i \ n. f i = k)" for n :: nat and f apply (induct n) apply auto apply (erule_tac x = n in allE) apply (case_tac "k = f (Suc n)") apply (auto simp add: abs_if split: if_split_asm intro: le_SucI) done from this [of "n - m" "f \ plus m"] that show ?thesis apply auto apply (rule_tac x = "m + i" in exI) apply auto done qed lemma nat0_intermed_int_val: "\i\n. f i = k" if "\if (i + 1) - f i\ \ 1" "f 0 \ k" "k \ f n" for n :: nat and k :: int using nat_intermed_int_val [of 0 n f k] that by auto subsection \Products and 1, by T. M. Rasmussen\ lemma abs_zmult_eq_1: fixes m n :: int assumes mn: "\m * n\ = 1" shows "\m\ = 1" proof - from mn have 0: "m \ 0" "n \ 0" by auto have "\ 2 \ \m\" proof assume "2 \ \m\" then have "2 * \n\ \ \m\ * \n\" by (simp add: mult_mono 0) also have "\ = \m * n\" by (simp add: abs_mult) also from mn have "\ = 1" by simp finally have "2 * \n\ \ 1" . with 0 show "False" by arith qed with 0 show ?thesis by auto qed lemma pos_zmult_eq_1_iff_lemma: "m * n = 1 \ m = 1 \ m = - 1" for m n :: int using abs_zmult_eq_1 [of m n] by arith lemma pos_zmult_eq_1_iff: fixes m n :: int assumes "0 < m" shows "m * n = 1 \ m = 1 \ n = 1" proof - from assms have "m * n = 1 \ m = 1" by (auto dest: pos_zmult_eq_1_iff_lemma) then show ?thesis by (auto dest: pos_zmult_eq_1_iff_lemma) qed lemma zmult_eq_1_iff: "m * n = 1 \ (m = 1 \ n = 1) \ (m = - 1 \ n = - 1)" for m n :: int apply (rule iffI) apply (frule pos_zmult_eq_1_iff_lemma) apply (simp add: mult.commute [of m]) apply (frule pos_zmult_eq_1_iff_lemma) apply auto done lemma infinite_UNIV_int [simp]: "\ finite (UNIV::int set)" proof assume "finite (UNIV::int set)" moreover have "inj (\i::int. 2 * i)" by (rule injI) simp ultimately have "surj (\i::int. 2 * i)" by (rule finite_UNIV_inj_surj) then obtain i :: int where "1 = 2 * i" by (rule surjE) then show False by (simp add: pos_zmult_eq_1_iff) qed subsection \The divides relation\ lemma zdvd_antisym_nonneg: "0 \ m \ 0 \ n \ m dvd n \ n dvd m \ m = n" for m n :: int by (auto simp add: dvd_def mult.assoc zero_le_mult_iff zmult_eq_1_iff) lemma zdvd_antisym_abs: fixes a b :: int assumes "a dvd b" and "b dvd a" shows "\a\ = \b\" proof (cases "a = 0") case True with assms show ?thesis by simp next case False from \a dvd b\ obtain k where k: "b = a * k" unfolding dvd_def by blast from \b dvd a\ obtain k' where k': "a = b * k'" unfolding dvd_def by blast from k k' have "a = a * k * k'" by simp with mult_cancel_left1[where c="a" and b="k*k'"] have kk': "k * k' = 1" using \a \ 0\ by (simp add: mult.assoc) then have "k = 1 \ k' = 1 \ k = -1 \ k' = -1" by (simp add: zmult_eq_1_iff) with k k' show ?thesis by auto qed lemma zdvd_zdiffD: "k dvd m - n \ k dvd n \ k dvd m" for k m n :: int using dvd_add_right_iff [of k "- n" m] by simp lemma zdvd_reduce: "k dvd n + k * m \ k dvd n" for k m n :: int using dvd_add_times_triv_right_iff [of k n m] by (simp add: ac_simps) lemma dvd_imp_le_int: fixes d i :: int assumes "i \ 0" and "d dvd i" shows "\d\ \ \i\" proof - from \d dvd i\ obtain k where "i = d * k" .. with \i \ 0\ have "k \ 0" by auto then have "1 \ \k\" and "0 \ \d\" by auto then have "\d\ * 1 \ \d\ * \k\" by (rule mult_left_mono) with \i = d * k\ show ?thesis by (simp add: abs_mult) qed lemma zdvd_not_zless: fixes m n :: int assumes "0 < m" and "m < n" shows "\ n dvd m" proof from assms have "0 < n" by auto assume "n dvd m" then obtain k where k: "m = n * k" .. with \0 < m\ have "0 < n * k" by auto with \0 < n\ have "0 < k" by (simp add: zero_less_mult_iff) with k \0 < n\ \m < n\ have "n * k < n * 1" by simp with \0 < n\ \0 < k\ show False unfolding mult_less_cancel_left by auto qed lemma zdvd_mult_cancel: fixes k m n :: int assumes d: "k * m dvd k * n" and "k \ 0" shows "m dvd n" proof - from d obtain h where h: "k * n = k * m * h" unfolding dvd_def by blast have "n = m * h" proof (rule ccontr) assume "\ ?thesis" with \k \ 0\ have "k * n \ k * (m * h)" by simp with h show False by (simp add: mult.assoc) qed then show ?thesis by simp qed lemma int_dvd_int_iff [simp]: "int m dvd int n \ m dvd n" proof - have "m dvd n" if "int n = int m * k" for k proof (cases k) case (nonneg q) with that have "n = m * q" by (simp del: of_nat_mult add: of_nat_mult [symmetric]) then show ?thesis .. next case (neg q) with that have "int n = int m * (- int (Suc q))" by simp also have "\ = - (int m * int (Suc q))" by (simp only: mult_minus_right) also have "\ = - int (m * Suc q)" by (simp only: of_nat_mult [symmetric]) finally have "- int (m * Suc q) = int n" .. then show ?thesis by (simp only: negative_eq_positive) auto qed then show ?thesis by (auto simp add: dvd_def) qed lemma dvd_nat_abs_iff [simp]: "n dvd nat \k\ \ int n dvd k" proof - have "n dvd nat \k\ \ int n dvd int (nat \k\)" by (simp only: int_dvd_int_iff) then show ?thesis by simp qed lemma nat_abs_dvd_iff [simp]: "nat \k\ dvd n \ k dvd int n" proof - have "nat \k\ dvd n \ int (nat \k\) dvd int n" by (simp only: int_dvd_int_iff) then show ?thesis by simp qed lemma zdvd1_eq [simp]: "x dvd 1 \ \x\ = 1" (is "?lhs \ ?rhs") for x :: int proof assume ?lhs then have "nat \x\ dvd nat \1\" by (simp only: nat_abs_dvd_iff) simp then have "nat \x\ = 1" by simp then show ?rhs by (cases "x < 0") simp_all next assume ?rhs then have "x = 1 \ x = - 1" by auto then show ?lhs by (auto intro: dvdI) qed lemma zdvd_mult_cancel1: fixes m :: int assumes mp: "m \ 0" shows "m * n dvd m \ \n\ = 1" (is "?lhs \ ?rhs") proof assume ?rhs then show ?lhs by (cases "n > 0") (auto simp add: minus_equation_iff) next assume ?lhs then have "m * n dvd m * 1" by simp from zdvd_mult_cancel[OF this mp] show ?rhs by (simp only: zdvd1_eq) qed lemma nat_dvd_iff: "nat z dvd m \ (if 0 \ z then z dvd int m else m = 0)" using nat_abs_dvd_iff [of z m] by (cases "z \ 0") auto lemma eq_nat_nat_iff: "0 \ z \ 0 \ z' \ nat z = nat z' \ z = z'" by (auto elim: nonneg_int_cases) lemma nat_power_eq: "0 \ z \ nat (z ^ n) = nat z ^ n" by (induct n) (simp_all add: nat_mult_distrib) lemma numeral_power_eq_nat_cancel_iff [simp]: "numeral x ^ n = nat y \ numeral x ^ n = y" using nat_eq_iff2 by auto lemma nat_eq_numeral_power_cancel_iff [simp]: "nat y = numeral x ^ n \ y = numeral x ^ n" using numeral_power_eq_nat_cancel_iff[of x n y] by (metis (mono_tags)) lemma numeral_power_le_nat_cancel_iff [simp]: "numeral x ^ n \ nat a \ numeral x ^ n \ a" using nat_le_eq_zle[of "numeral x ^ n" a] by (auto simp: nat_power_eq) lemma nat_le_numeral_power_cancel_iff [simp]: "nat a \ numeral x ^ n \ a \ numeral x ^ n" by (simp add: nat_le_iff) lemma numeral_power_less_nat_cancel_iff [simp]: "numeral x ^ n < nat a \ numeral x ^ n < a" using nat_less_eq_zless[of "numeral x ^ n" a] by (auto simp: nat_power_eq) lemma nat_less_numeral_power_cancel_iff [simp]: "nat a < numeral x ^ n \ a < numeral x ^ n" using nat_less_eq_zless[of a "numeral x ^ n"] by (cases "a < 0") (auto simp: nat_power_eq less_le_trans[where y=0]) lemma zdvd_imp_le: "z dvd n \ 0 < n \ z \ n" for n z :: int apply (cases n) apply auto apply (cases z) apply (auto simp add: dvd_imp_le) done lemma zdvd_period: fixes a d :: int assumes "a dvd d" shows "a dvd (x + t) \ a dvd ((x + c * d) + t)" (is "?lhs \ ?rhs") proof - from assms have "a dvd (x + t) \ a dvd ((x + t) + c * d)" by (simp add: dvd_add_left_iff) then show ?thesis by (simp add: ac_simps) qed subsection \Finiteness of intervals\ lemma finite_interval_int1 [iff]: "finite {i :: int. a \ i \ i \ b}" proof (cases "a \ b") case True then show ?thesis proof (induct b rule: int_ge_induct) case base have "{i. a \ i \ i \ a} = {a}" by auto then show ?case by simp next case (step b) then have "{i. a \ i \ i \ b + 1} = {i. a \ i \ i \ b} \ {b + 1}" by auto with step show ?case by simp qed next case False then show ?thesis by (metis (lifting, no_types) Collect_empty_eq finite.emptyI order_trans) qed lemma finite_interval_int2 [iff]: "finite {i :: int. a \ i \ i < b}" by (rule rev_finite_subset[OF finite_interval_int1[of "a" "b"]]) auto lemma finite_interval_int3 [iff]: "finite {i :: int. a < i \ i \ b}" by (rule rev_finite_subset[OF finite_interval_int1[of "a" "b"]]) auto lemma finite_interval_int4 [iff]: "finite {i :: int. a < i \ i < b}" by (rule rev_finite_subset[OF finite_interval_int1[of "a" "b"]]) auto subsection \Configuration of the code generator\ text \Constructors\ definition Pos :: "num \ int" where [simp, code_abbrev]: "Pos = numeral" definition Neg :: "num \ int" where [simp, code_abbrev]: "Neg n = - (Pos n)" code_datatype "0::int" Pos Neg text \Auxiliary operations.\ definition dup :: "int \ int" where [simp]: "dup k = k + k" lemma dup_code [code]: "dup 0 = 0" "dup (Pos n) = Pos (Num.Bit0 n)" "dup (Neg n) = Neg (Num.Bit0 n)" by (simp_all add: numeral_Bit0) definition sub :: "num \ num \ int" where [simp]: "sub m n = numeral m - numeral n" lemma sub_code [code]: "sub Num.One Num.One = 0" "sub (Num.Bit0 m) Num.One = Pos (Num.BitM m)" "sub (Num.Bit1 m) Num.One = Pos (Num.Bit0 m)" "sub Num.One (Num.Bit0 n) = Neg (Num.BitM n)" "sub Num.One (Num.Bit1 n) = Neg (Num.Bit0 n)" "sub (Num.Bit0 m) (Num.Bit0 n) = dup (sub m n)" "sub (Num.Bit1 m) (Num.Bit1 n) = dup (sub m n)" "sub (Num.Bit1 m) (Num.Bit0 n) = dup (sub m n) + 1" "sub (Num.Bit0 m) (Num.Bit1 n) = dup (sub m n) - 1" by (simp_all only: sub_def dup_def numeral.simps Pos_def Neg_def numeral_BitM) text \Implementations.\ lemma one_int_code [code]: "1 = Pos Num.One" by simp lemma plus_int_code [code]: "k + 0 = k" "0 + l = l" "Pos m + Pos n = Pos (m + n)" "Pos m + Neg n = sub m n" "Neg m + Pos n = sub n m" "Neg m + Neg n = Neg (m + n)" for k l :: int by simp_all lemma uminus_int_code [code]: "uminus 0 = (0::int)" "uminus (Pos m) = Neg m" "uminus (Neg m) = Pos m" by simp_all lemma minus_int_code [code]: "k - 0 = k" "0 - l = uminus l" "Pos m - Pos n = sub m n" "Pos m - Neg n = Pos (m + n)" "Neg m - Pos n = Neg (m + n)" "Neg m - Neg n = sub n m" for k l :: int by simp_all lemma times_int_code [code]: "k * 0 = 0" "0 * l = 0" "Pos m * Pos n = Pos (m * n)" "Pos m * Neg n = Neg (m * n)" "Neg m * Pos n = Neg (m * n)" "Neg m * Neg n = Pos (m * n)" for k l :: int by simp_all instantiation int :: equal begin definition "HOL.equal k l \ k = (l::int)" instance by standard (rule equal_int_def) end lemma equal_int_code [code]: "HOL.equal 0 (0::int) \ True" "HOL.equal 0 (Pos l) \ False" "HOL.equal 0 (Neg l) \ False" "HOL.equal (Pos k) 0 \ False" "HOL.equal (Pos k) (Pos l) \ HOL.equal k l" "HOL.equal (Pos k) (Neg l) \ False" "HOL.equal (Neg k) 0 \ False" "HOL.equal (Neg k) (Pos l) \ False" "HOL.equal (Neg k) (Neg l) \ HOL.equal k l" by (auto simp add: equal) lemma equal_int_refl [code nbe]: "HOL.equal k k \ True" for k :: int by (fact equal_refl) lemma less_eq_int_code [code]: "0 \ (0::int) \ True" "0 \ Pos l \ True" "0 \ Neg l \ False" "Pos k \ 0 \ False" "Pos k \ Pos l \ k \ l" "Pos k \ Neg l \ False" "Neg k \ 0 \ True" "Neg k \ Pos l \ True" "Neg k \ Neg l \ l \ k" by simp_all lemma less_int_code [code]: "0 < (0::int) \ False" "0 < Pos l \ True" "0 < Neg l \ False" "Pos k < 0 \ False" "Pos k < Pos l \ k < l" "Pos k < Neg l \ False" "Neg k < 0 \ True" "Neg k < Pos l \ True" "Neg k < Neg l \ l < k" by simp_all lemma nat_code [code]: "nat (Int.Neg k) = 0" "nat 0 = 0" "nat (Int.Pos k) = nat_of_num k" by (simp_all add: nat_of_num_numeral) lemma (in ring_1) of_int_code [code]: "of_int (Int.Neg k) = - numeral k" "of_int 0 = 0" "of_int (Int.Pos k) = numeral k" by simp_all text \Serializer setup.\ code_identifier code_module Int \ (SML) Arith and (OCaml) Arith and (Haskell) Arith quickcheck_params [default_type = int] hide_const (open) Pos Neg sub dup text \De-register \int\ as a quotient type:\ lifting_update int.lifting lifting_forget int.lifting subsection \Duplicates\ lemmas int_sum = of_nat_sum [where 'a=int] lemmas int_prod = of_nat_prod [where 'a=int] lemmas zle_int = of_nat_le_iff [where 'a=int] lemmas int_int_eq = of_nat_eq_iff [where 'a=int] lemmas nonneg_eq_int = nonneg_int_cases lemmas double_eq_0_iff = double_zero lemmas int_distrib = distrib_right [of z1 z2 w] distrib_left [of w z1 z2] left_diff_distrib [of z1 z2 w] right_diff_distrib [of w z1 z2] for z1 z2 w :: int end