2778 |
2778 |
2779 lemma gcd_proj2_if_dvd_nat [simp]: "y dvd x \<Longrightarrow> gcd x y = y" |
2779 lemma gcd_proj2_if_dvd_nat [simp]: "y dvd x \<Longrightarrow> gcd x y = y" |
2780 for x y :: nat |
2780 for x y :: nat |
2781 by (fact gcd_nat.absorb2) |
2781 by (fact gcd_nat.absorb2) |
2782 |
2782 |
|
2783 lemma Gcd_in: |
|
2784 fixes A :: "nat set" |
|
2785 assumes "\<And>a b. a \<in> A \<Longrightarrow> b \<in> A \<Longrightarrow> gcd a b \<in> A" |
|
2786 assumes "A \<noteq> {}" |
|
2787 shows "Gcd A \<in> A" |
|
2788 proof (cases "A = {0}") |
|
2789 case False |
|
2790 with assms obtain x where "x \<in> A" "x > 0" |
|
2791 by auto |
|
2792 thus "Gcd A \<in> A" |
|
2793 proof (induction x rule: less_induct) |
|
2794 case (less x) |
|
2795 show ?case |
|
2796 proof (cases "x = Gcd A") |
|
2797 case False |
|
2798 have "\<exists>y\<in>A. \<not>x dvd y" |
|
2799 using False less.prems by (metis Gcd_dvd Gcd_greatest_nat gcd_nat.asym) |
|
2800 then obtain y where y: "y \<in> A" "\<not>x dvd y" |
|
2801 by blast |
|
2802 have "gcd x y \<in> A" |
|
2803 by (rule assms(1)) (use \<open>x \<in> A\<close> y in auto) |
|
2804 moreover have "gcd x y < x" |
|
2805 using \<open>x > 0\<close> y by (metis gcd_dvd1 gcd_dvd2 nat_dvd_not_less nat_neq_iff) |
|
2806 moreover have "gcd x y > 0" |
|
2807 using \<open>x > 0\<close> by auto |
|
2808 ultimately show ?thesis using less.IH by blast |
|
2809 qed (use less in auto) |
|
2810 qed |
|
2811 qed auto |
|
2812 |
|
2813 lemma bezout_gcd_nat': |
|
2814 fixes a b :: nat |
|
2815 shows "\<exists>x y. b * y \<le> a * x \<and> a * x - b * y = gcd a b \<or> a * y \<le> b * x \<and> b * x - a * y = gcd a b" |
|
2816 using bezout_nat[of a b] |
|
2817 by (metis add_diff_cancel_left' diff_zero gcd.commute gcd_0_nat |
|
2818 le_add_same_cancel1 mult.right_neutral zero_le) |
|
2819 |
2783 lemmas Lcm_eq_0_I_nat [simp] = Lcm_eq_0_I [where ?'a = nat] |
2820 lemmas Lcm_eq_0_I_nat [simp] = Lcm_eq_0_I [where ?'a = nat] |
2784 lemmas Lcm_0_iff_nat [simp] = Lcm_0_iff [where ?'a = nat] |
2821 lemmas Lcm_0_iff_nat [simp] = Lcm_0_iff [where ?'a = nat] |
2785 lemmas Lcm_least_int [simp] = Lcm_least [where ?'a = int] |
2822 lemmas Lcm_least_int [simp] = Lcm_least [where ?'a = int] |
2786 |
2823 |
|
2824 |
|
2825 subsection \<open>Characteristic of a semiring\<close> |
|
2826 |
|
2827 definition (in semiring_1) semiring_char :: "'a itself \<Rightarrow> nat" |
|
2828 where "semiring_char _ = Gcd {n. of_nat n = (0 :: 'a)}" |
|
2829 |
|
2830 context semiring_1 |
|
2831 begin |
|
2832 |
|
2833 context |
|
2834 fixes CHAR :: nat |
|
2835 defines "CHAR \<equiv> semiring_char (Pure.type :: 'a itself)" |
|
2836 begin |
|
2837 |
|
2838 lemma of_nat_CHAR [simp]: "of_nat CHAR = (0 :: 'a)" |
|
2839 proof - |
|
2840 have "CHAR \<in> {n. of_nat n = (0::'a)}" |
|
2841 unfolding CHAR_def semiring_char_def |
|
2842 proof (rule Gcd_in, clarify) |
|
2843 fix a b :: nat |
|
2844 assume *: "of_nat a = (0 :: 'a)" "of_nat b = (0 :: 'a)" |
|
2845 show "of_nat (gcd a b) = (0 :: 'a)" |
|
2846 proof (cases "a = 0") |
|
2847 case False |
|
2848 with bezout_nat obtain x y where "a * x = b * y + gcd a b" |
|
2849 by blast |
|
2850 hence "of_nat (a * x) = (of_nat (b * y + gcd a b) :: 'a)" |
|
2851 by (rule arg_cong) |
|
2852 thus "of_nat (gcd a b) = (0 :: 'a)" |
|
2853 using * by simp |
|
2854 qed (use * in auto) |
|
2855 next |
|
2856 have "of_nat 0 = (0 :: 'a)" |
|
2857 by simp |
|
2858 thus "{n. of_nat n = (0 :: 'a)} \<noteq> {}" |
|
2859 by blast |
|
2860 qed |
|
2861 thus ?thesis |
|
2862 by simp |
|
2863 qed |
|
2864 |
|
2865 lemma of_nat_eq_0_iff_char_dvd: "of_nat n = (0 :: 'a) \<longleftrightarrow> CHAR dvd n" |
|
2866 proof |
|
2867 assume "of_nat n = (0 :: 'a)" |
|
2868 thus "CHAR dvd n" |
|
2869 unfolding CHAR_def semiring_char_def by (intro Gcd_dvd) auto |
|
2870 next |
|
2871 assume "CHAR dvd n" |
|
2872 then obtain m where "n = CHAR * m" |
|
2873 by auto |
|
2874 thus "of_nat n = (0 :: 'a)" |
|
2875 by simp |
|
2876 qed |
|
2877 |
|
2878 lemma CHAR_eqI: |
|
2879 assumes "of_nat c = (0 :: 'a)" |
|
2880 assumes "\<And>x. of_nat x = (0 :: 'a) \<Longrightarrow> c dvd x" |
|
2881 shows "CHAR = c" |
|
2882 using assms by (intro dvd_antisym) (auto simp: of_nat_eq_0_iff_char_dvd) |
|
2883 |
|
2884 lemma CHAR_eq0_iff: "CHAR = 0 \<longleftrightarrow> (\<forall>n>0. of_nat n \<noteq> (0::'a))" |
|
2885 by (auto simp: of_nat_eq_0_iff_char_dvd) |
|
2886 |
|
2887 lemma CHAR_pos_iff: "CHAR > 0 \<longleftrightarrow> (\<exists>n>0. of_nat n = (0::'a))" |
|
2888 using CHAR_eq0_iff neq0_conv by blast |
|
2889 |
|
2890 lemma CHAR_eq_posI: |
|
2891 assumes "c > 0" "of_nat c = (0 :: 'a)" "\<And>x. x > 0 \<Longrightarrow> x < c \<Longrightarrow> of_nat x \<noteq> (0 :: 'a)" |
|
2892 shows "CHAR = c" |
|
2893 proof (rule antisym) |
|
2894 from assms have "CHAR > 0" |
|
2895 by (auto simp: CHAR_pos_iff) |
|
2896 from assms(3)[OF this] show "CHAR \<ge> c" |
|
2897 by force |
|
2898 next |
|
2899 have "CHAR dvd c" |
|
2900 using assms by (auto simp: of_nat_eq_0_iff_char_dvd) |
|
2901 thus "CHAR \<le> c" |
|
2902 using \<open>c > 0\<close> by (intro dvd_imp_le) auto |
|
2903 qed |
|
2904 |
2787 end |
2905 end |
|
2906 end |
|
2907 |
|
2908 lemma (in semiring_char_0) CHAR_eq_0 [simp]: "semiring_char (Pure.type :: 'a itself) = 0" |
|
2909 by (simp add: CHAR_eq0_iff) |
|
2910 |
|
2911 |
|
2912 (* nicer notation *) |
|
2913 |
|
2914 syntax "_type_char" :: "type => nat" ("(1CHAR/(1'(_')))") |
|
2915 |
|
2916 translations "CHAR('t)" => "CONST semiring_char (CONST Pure.type :: 't itself)" |
|
2917 |
|
2918 print_translation \<open> |
|
2919 let |
|
2920 fun char_type_tr' ctxt [Const (\<^const_syntax>\<open>Pure.type\<close>, Type (_, [T]))] = |
|
2921 Syntax.const \<^syntax_const>\<open>_type_char\<close> $ Syntax_Phases.term_of_typ ctxt T |
|
2922 in [(\<^const_syntax>\<open>semiring_char\<close>, char_type_tr')] end |
|
2923 \<close> |
|
2924 |
|
2925 end |