src/HOL/Number_Theory/Mod_Exp.thy
author immler
Sun, 03 Nov 2019 21:46:46 -0500
changeset 71034 e0755162093f
parent 69790 154cf64e403e
permissions -rw-r--r--
replace approximation oracle by less ad-hoc @{computation}s
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
69790
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
     1
(*
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
     2
  File:    HOL/Number_Theory/Mod_Exp
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
     3
  Author:  Manuel Eberl, TU München
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
     4
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
     5
  Fast implementation of modular exponentiation and "cong" using exponentiation by squaring.
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
     6
  Includes code setup for nat and int.
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
     7
*)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
     8
section \<open>Fast modular exponentiation\<close>
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
     9
theory Mod_Exp
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    10
  imports Cong "HOL-Library.Power_By_Squaring"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    11
begin
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    12
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    13
context euclidean_semiring_cancel
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    14
begin
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    15
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    16
definition mod_exp_aux :: "'a \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> nat \<Rightarrow> 'a"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    17
  where "mod_exp_aux m = efficient_funpow (\<lambda>x y. x * y mod m)"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    18
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    19
lemma mod_exp_aux_code [code]:
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    20
  "mod_exp_aux m y x n =
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    21
     (if n = 0 then y
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    22
      else if n = 1 then (x * y) mod m
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    23
      else if even n then mod_exp_aux m y ((x * x) mod m) (n div 2)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    24
      else mod_exp_aux m ((x * y) mod m) ((x * x) mod m) (n div 2))"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    25
  unfolding mod_exp_aux_def by (rule efficient_funpow_code)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    26
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    27
lemma mod_exp_aux_correct:
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    28
  "mod_exp_aux m y x n mod m = (x ^ n * y) mod m"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    29
proof -
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    30
  have "mod_exp_aux m y x n = efficient_funpow (\<lambda>x y. x * y mod m) y x n"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    31
    by (simp add: mod_exp_aux_def)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    32
  also have "\<dots> = ((\<lambda>y. x * y mod m) ^^ n) y"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    33
    by (rule efficient_funpow_correct) (simp add: mod_mult_left_eq mod_mult_right_eq mult_ac)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    34
  also have "((\<lambda>y. x * y mod m) ^^ n) y mod m = (x ^ n * y) mod m"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    35
  proof (induction n)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    36
    case (Suc n)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    37
    hence "x * ((\<lambda>y. x * y mod m) ^^ n) y mod m = x * x ^ n * y mod m"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    38
      by (metis mod_mult_right_eq mult.assoc)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    39
    thus ?case by auto
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    40
  qed auto
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    41
  finally show ?thesis .
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    42
qed
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    43
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    44
definition mod_exp :: "'a \<Rightarrow> nat \<Rightarrow> 'a \<Rightarrow> 'a"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    45
  where "mod_exp b e m = (b ^ e) mod m"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    46
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    47
lemma mod_exp_code [code]: "mod_exp b e m = mod_exp_aux m 1 b e mod m"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    48
  by (simp add: mod_exp_def mod_exp_aux_correct)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    49
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    50
end
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    51
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    52
(*
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    53
  TODO: Setup here only for nat and int. Could be done for any
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    54
  euclidean_semiring_cancel. Should it?
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    55
*)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    56
lemmas [code_abbrev] = mod_exp_def[where ?'a = nat] mod_exp_def[where ?'a = int]
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    57
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    58
lemma cong_power_nat_code [code_unfold]:
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    59
  "[b ^ e = (x ::nat)] (mod m) \<longleftrightarrow> mod_exp b e m = x mod m"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    60
  by (simp add: mod_exp_def cong_def)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    61
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    62
lemma cong_power_int_code [code_unfold]:
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    63
  "[b ^ e = (x ::int)] (mod m) \<longleftrightarrow> mod_exp b e m = x mod m"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    64
  by (simp add: mod_exp_def cong_def)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    65
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    66
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    67
text \<open>
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    68
  The following rules allow the simplifier to evaluate @{const mod_exp} efficiently.
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    69
\<close>
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    70
lemma eval_mod_exp_aux [simp]:
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    71
  "mod_exp_aux m y x 0 = y"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    72
  "mod_exp_aux m y x (Suc 0) = (x * y) mod m"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    73
  "mod_exp_aux m y x (numeral (num.Bit0 n)) =
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    74
     mod_exp_aux m y (x\<^sup>2 mod m) (numeral n)"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    75
  "mod_exp_aux m y x (numeral (num.Bit1 n)) =
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    76
     mod_exp_aux m ((x * y) mod m) (x\<^sup>2 mod m) (numeral n)"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    77
proof -
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    78
  define n' where "n' = (numeral n :: nat)"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    79
  have [simp]: "n' \<noteq> 0" by (auto simp: n'_def)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    80
  
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    81
  show "mod_exp_aux m y x 0 = y" and "mod_exp_aux m y x (Suc 0) = (x * y) mod m"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    82
    by (simp_all add: mod_exp_aux_def)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    83
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    84
  have "numeral (num.Bit0 n) = (2 * n')"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    85
    by (subst numeral.numeral_Bit0) (simp del: arith_simps add: n'_def)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    86
  also have "mod_exp_aux m y x \<dots> = mod_exp_aux m y (x^2 mod m) n'"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    87
    by (subst mod_exp_aux_code) (simp_all add: power2_eq_square)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    88
  finally show "mod_exp_aux m y x (numeral (num.Bit0 n)) =
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    89
                  mod_exp_aux m y (x\<^sup>2 mod m) (numeral n)"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    90
    by (simp add: n'_def)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    91
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    92
  have "numeral (num.Bit1 n) = Suc (2 * n')"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    93
    by (subst numeral.numeral_Bit1) (simp del: arith_simps add: n'_def)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    94
  also have "mod_exp_aux m y x \<dots> = mod_exp_aux m ((x * y) mod m) (x^2 mod m) n'"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    95
    by (subst mod_exp_aux_code) (simp_all add: power2_eq_square)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    96
  finally show "mod_exp_aux m y x (numeral (num.Bit1 n)) =
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    97
                  mod_exp_aux m ((x * y) mod m) (x\<^sup>2 mod m) (numeral n)"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    98
    by (simp add: n'_def)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
    99
qed
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   100
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   101
lemma eval_mod_exp [simp]:
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   102
  "mod_exp b' 0 m' = 1 mod m'"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   103
  "mod_exp b' 1 m' = b' mod m'"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   104
  "mod_exp b' (Suc 0) m' = b' mod m'"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   105
  "mod_exp b' e' 0 = b' ^ e'"  
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   106
  "mod_exp b' e' 1 = 0"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   107
  "mod_exp b' e' (Suc 0) = 0"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   108
  "mod_exp 0 1 m' = 0"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   109
  "mod_exp 0 (Suc 0) m' = 0"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   110
  "mod_exp 0 (numeral e) m' = 0"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   111
  "mod_exp 1 e' m' = 1 mod m'"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   112
  "mod_exp (Suc 0) e' m' = 1 mod m'"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   113
  "mod_exp (numeral b) (numeral e) (numeral m) =
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   114
     mod_exp_aux (numeral m) 1 (numeral b) (numeral e) mod numeral m"
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   115
  by (simp_all add: mod_exp_def mod_exp_aux_correct)
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   116
154cf64e403e Exponentiation by squaring, fast modular exponentiation
Manuel Eberl <eberlm@in.tum.de>
parents:
diff changeset
   117
end