src/HOL/Library/Divides.thy
author wenzelm
Wed, 12 Mar 2025 11:39:00 +0100
changeset 82265 4b875a4c83b0
parent 80453 7a2d9e3fcdd5
permissions -rw-r--r--
update for release;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
80453
7a2d9e3fcdd5 moved transitional theory Divides to HOL-Library
haftmann
parents: 80452
diff changeset
     1
(*  Title:      HOL/Library/Divides.thy
18154
0c05abaf6244 add header
huffman
parents: 17609
diff changeset
     2
*)
3366
2402c6ab1561 Moving div and mod from Arith to Divides
paulson
parents:
diff changeset
     3
76231
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
     4
section \<open>Misc lemmas on division, to be sorted out finally\<close>
3366
2402c6ab1561 Moving div and mod from Arith to Divides
paulson
parents:
diff changeset
     5
15131
c69542757a4d New theory header syntax.
nipkow
parents: 14640
diff changeset
     6
theory Divides
80453
7a2d9e3fcdd5 moved transitional theory Divides to HOL-Library
haftmann
parents: 80452
diff changeset
     7
imports Main
15131
c69542757a4d New theory header syntax.
nipkow
parents: 14640
diff changeset
     8
begin
3366
2402c6ab1561 Moving div and mod from Arith to Divides
paulson
parents:
diff changeset
     9
78937
5e6b195eee83 slightly less technical formulation of very specific type class
haftmann
parents: 78935
diff changeset
    10
class unique_euclidean_semiring_numeral = linordered_euclidean_semiring + discrete_linordered_semidom +
76231
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
    11
  assumes div_less [no_atp]: "0 \<le> a \<Longrightarrow> a < b \<Longrightarrow> a div b = 0"
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
    12
    and mod_less [no_atp]: " 0 \<le> a \<Longrightarrow> a < b \<Longrightarrow> a mod b = a"
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
    13
    and div_positive [no_atp]: "0 < b \<Longrightarrow> b \<le> a \<Longrightarrow> a div b > 0"
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
    14
    and mod_less_eq_dividend [no_atp]: "0 \<le> a \<Longrightarrow> a mod b \<le> a"
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
    15
    and pos_mod_bound [no_atp]: "0 < b \<Longrightarrow> a mod b < b"
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
    16
    and pos_mod_sign [no_atp]: "0 < b \<Longrightarrow> 0 \<le> a mod b"
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
    17
    and mod_mult2_eq [no_atp]: "0 \<le> c \<Longrightarrow> a mod (b * c) = b * (a div b mod c) + a mod b"
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
    18
    and div_mult2_eq [no_atp]: "0 \<le> c \<Longrightarrow> a div (b * c) = a div b div c"
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
    19
78935
5e788ff7a489 explicit type class for discrete linordered semidoms
haftmann
parents: 78669
diff changeset
    20
hide_fact (open) div_less mod_less div_positive mod_less_eq_dividend pos_mod_bound pos_mod_sign mod_mult2_eq div_mult2_eq
76231
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
    21
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
    22
context unique_euclidean_semiring_numeral
75936
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    23
begin
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    24
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
    25
context
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
    26
begin
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
    27
78935
5e788ff7a489 explicit type class for discrete linordered semidoms
haftmann
parents: 78669
diff changeset
    28
qualified lemma discrete [no_atp]:
5e788ff7a489 explicit type class for discrete linordered semidoms
haftmann
parents: 78669
diff changeset
    29
  "a < b \<longleftrightarrow> a + 1 \<le> b"
5e788ff7a489 explicit type class for discrete linordered semidoms
haftmann
parents: 78669
diff changeset
    30
  by (fact less_iff_succ_less_eq)
5e788ff7a489 explicit type class for discrete linordered semidoms
haftmann
parents: 78669
diff changeset
    31
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
    32
qualified lemma divmod_digit_1 [no_atp]:
75936
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    33
  assumes "0 \<le> a" "0 < b" and "b \<le> a mod (2 * b)"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    34
  shows "2 * (a div (2 * b)) + 1 = a div b" (is "?P")
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    35
    and "a mod (2 * b) - b = a mod b" (is "?Q")
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    36
proof -
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    37
  from assms mod_less_eq_dividend [of a "2 * b"] have "b \<le> a"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    38
    by (auto intro: trans)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    39
  with \<open>0 < b\<close> have "0 < a div b" by (auto intro: div_positive)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    40
  then have [simp]: "1 \<le> a div b" by (simp add: discrete)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    41
  with \<open>0 < b\<close> have mod_less: "a mod b < b" by (simp add: pos_mod_bound)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    42
  define w where "w = a div b mod 2"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    43
  then have w_exhaust: "w = 0 \<or> w = 1" by auto
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    44
  have mod_w: "a mod (2 * b) = a mod b + b * w"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    45
    by (simp add: w_def mod_mult2_eq ac_simps)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    46
  from assms w_exhaust have "w = 1"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    47
    using mod_less by (auto simp add: mod_w)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    48
  with mod_w have mod: "a mod (2 * b) = a mod b + b" by simp
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    49
  have "2 * (a div (2 * b)) = a div b - w"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    50
    by (simp add: w_def div_mult2_eq minus_mod_eq_mult_div ac_simps)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    51
  with \<open>w = 1\<close> have div: "2 * (a div (2 * b)) = a div b - 1" by simp
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    52
  then show ?P and ?Q
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    53
    by (simp_all add: div mod add_implies_diff [symmetric])
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    54
qed
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    55
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
    56
qualified lemma divmod_digit_0 [no_atp]:
75936
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    57
  assumes "0 < b" and "a mod (2 * b) < b"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    58
  shows "2 * (a div (2 * b)) = a div b" (is "?P")
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    59
    and "a mod (2 * b) = a mod b" (is "?Q")
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    60
proof -
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    61
  define w where "w = a div b mod 2"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    62
  then have w_exhaust: "w = 0 \<or> w = 1" by auto
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    63
  have mod_w: "a mod (2 * b) = a mod b + b * w"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    64
    by (simp add: w_def mod_mult2_eq ac_simps)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    65
  moreover have "b \<le> a mod b + b"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    66
  proof -
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    67
    from \<open>0 < b\<close> pos_mod_sign have "0 \<le> a mod b" by blast
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    68
    then have "0 + b \<le> a mod b + b" by (rule add_right_mono)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    69
    then show ?thesis by simp
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    70
  qed
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    71
  moreover note assms w_exhaust
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    72
  ultimately have "w = 0" by auto
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    73
  with mod_w have mod: "a mod (2 * b) = a mod b" by simp
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    74
  have "2 * (a div (2 * b)) = a div b - w"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    75
    by (simp add: w_def div_mult2_eq minus_mod_eq_mult_div ac_simps)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    76
  with \<open>w = 0\<close> have div: "2 * (a div (2 * b)) = a div b" by simp
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    77
  then show ?P and ?Q
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    78
    by (simp_all add: div mod)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    79
qed
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    80
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
    81
qualified lemma mod_double_modulus [no_atp]:
75936
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    82
  assumes "m > 0" "x \<ge> 0"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    83
  shows   "x mod (2 * m) = x mod m \<or> x mod (2 * m) = x mod m + m"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    84
proof (cases "x mod (2 * m) < m")
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    85
  case True
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    86
  thus ?thesis using assms using divmod_digit_0(2)[of m x] by auto
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    87
next
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    88
  case False
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    89
  hence *: "x mod (2 * m) - m = x mod m"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    90
    using assms by (intro divmod_digit_1) auto
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    91
  hence "x mod (2 * m) = x mod m + m"
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    92
    by (subst * [symmetric], subst le_add_diff_inverse2) (use False in auto)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    93
  thus ?thesis by simp
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    94
qed
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    95
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    96
end
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
    97
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
    98
end
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
    99
75936
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
   100
instance nat :: unique_euclidean_semiring_numeral
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
   101
  by standard
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
   102
    (auto simp add: div_greater_zero_iff div_mult2_eq mod_mult2_eq)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
   103
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
   104
instance int :: unique_euclidean_semiring_numeral
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
   105
  by standard (auto intro: zmod_le_nonneg_dividend simp add:
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
   106
    pos_imp_zdiv_pos_iff zmod_zmult2_eq zdiv_zmult2_eq)
d2e6a1342c90 simplified computation algorithm construction
haftmann
parents: 75883
diff changeset
   107
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
   108
context
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
   109
begin
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
   110
80452
0303b3a0edde dropped dubious dest rule which always unfolds a definition in the assumptions
haftmann
parents: 78937
diff changeset
   111
qualified lemma zmod_eq_0D: "\<exists>q. m = d * q" if "m mod d = 0" for m d :: int
69695
753ae9e9773d algebraized more material from theory Divides
haftmann
parents: 69593
diff changeset
   112
  using that by auto
753ae9e9773d algebraized more material from theory Divides
haftmann
parents: 69593
diff changeset
   113
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
   114
qualified lemma div_geq [no_atp]: "m div n = Suc ((m - n) div n)" if "0 < n" and " \<not> m < n" for m n :: nat
76231
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
   115
  by (rule le_div_geq) (use that in \<open>simp_all add: not_less\<close>)
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
   116
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
   117
qualified lemma mod_geq [no_atp]: "m mod n = (m - n) mod n" if "\<not> m < n" for m n :: nat
76231
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
   118
  by (rule le_mod_geq) (use that in \<open>simp add: not_less\<close>)
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
   119
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
   120
qualified lemma mod_eq_0D [no_atp]: "\<exists>q. m = d * q" if "m mod d = 0" for m d :: nat
76231
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
   121
  using that by (auto simp add: mod_eq_0_iff_dvd)
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
   122
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
   123
qualified lemma pos_mod_conj [no_atp]: "0 < b \<Longrightarrow> 0 \<le> a mod b \<and> a mod b < b" for a b :: int
76231
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
   124
  by simp
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
   125
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
   126
qualified lemma neg_mod_conj [no_atp]: "b < 0 \<Longrightarrow> a mod b \<le> 0 \<and> b < a mod b" for a b :: int
76231
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
   127
  by simp
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
   128
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
   129
qualified lemma zmod_eq_0_iff [no_atp]: "m mod d = 0 \<longleftrightarrow> (\<exists>q. m = d * q)" for m d :: int
76231
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
   130
  by (auto simp add: mod_eq_0_iff_dvd)
8a48e18f081e reduce prominence of facts
haftmann
parents: 76224
diff changeset
   131
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
   132
qualified lemma div_positive_int [no_atp]:
75937
02b18f59f903 streamlined
haftmann
parents: 75936
diff changeset
   133
  "k div l > 0" if "k \<ge> l" and "l > 0" for k l :: int
02b18f59f903 streamlined
haftmann
parents: 75936
diff changeset
   134
  using that by (simp add: nonneg1_imp_zdiv_pos_iff)
02b18f59f903 streamlined
haftmann
parents: 75936
diff changeset
   135
78669
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
   136
end
18ea58bdcf77 reduced prominence of lemma names
haftmann
parents: 78668
diff changeset
   137
76224
64e8d4afcf10 moved relevant theorems from theory Divides to theory Euclidean_Division
haftmann
parents: 76141
diff changeset
   138
code_identifier
64e8d4afcf10 moved relevant theorems from theory Divides to theory Euclidean_Division
haftmann
parents: 76141
diff changeset
   139
  code_module Divides \<rightharpoonup> (SML) Arith and (OCaml) Arith and (Haskell) Arith
64e8d4afcf10 moved relevant theorems from theory Divides to theory Euclidean_Division
haftmann
parents: 76141
diff changeset
   140
33361
1f18de40b43f combined former theories Divides and IntDiv to one theory Divides
haftmann
parents: 33340
diff changeset
   141
end