src/Tools/isac/Knowledge/GCD_Poly_FP.thy
author Walther Neuper <neuper@ist.tugraz.at>
Wed, 23 Jan 2013 15:56:24 +0100
changeset 48813 28b3d1c738cb
child 48814 46e7a7c569be
permissions -rw-r--r--
GCD_Poly: ML --> Isabelle's function package

until primes_upto.
neuper@48813
     1
header {* GCD for polynomials, implemented using the function package (_FP) *}
neuper@48813
     2
neuper@48813
     3
theory GCD_Poly_FP 
neuper@48813
     4
imports "~~/src/HOL/Library/Polynomial" "~~/src/HOL/Number_Theory/Primes"
neuper@48813
     5
begin
neuper@48813
     6
neuper@48813
     7
text {* 
neuper@48813
     8
  This code has been translated from GCD_Poly.thy by Diana Meindl,
neuper@48813
     9
  who follows Franz Winkler, Polynomial algorithyms in computer algebra, Springer 1996.
neuper@48813
    10
  Winkler's original identifiers are in test/../gcd_poly_winkler.sml;
neuper@48813
    11
  test/../gcd_poly.sml documents the changes towards GCD_Poly.thy;
neuper@48813
    12
  the style of GCD_Poly.thy has been adapted to the function package.
neuper@48813
    13
*}
neuper@48813
    14
neuper@48813
    15
section {* gcd for univariate polynomials *}
neuper@48813
    16
neuper@48813
    17
subsection {* a variant for div *}
neuper@48813
    18
neuper@48813
    19
fun div2 :: "int => int => int" (infixl "div2" 70)
neuper@48813
    20
  where "a div2 b = (if a div b < 0 then (\<bar>a\<bar> div \<bar>b\<bar>) * -1 else a div b)"
neuper@48813
    21
text {* Meindl:  infix div' ... div' didnt work, infix didnt work *}
neuper@48813
    22
neuper@48813
    23
text {*"----------- fun div2 -- --------------------------------"*};
neuper@48813
    24
value " 5 div2  2"    -- "=  2"
neuper@48813
    25
value "-5 div2  2"    -- "= -2"
neuper@48813
    26
value "-5 div2 -2"    -- "=  2"
neuper@48813
    27
value " 5 div2 -2"    -- "= -2"
neuper@48813
    28
thm div2.simps -- "?a div2 ?b = (if ?a div ?b < 0 then \<bar>?a\<bar> div \<bar>?b\<bar> * -1 else ?a div ?b)"
neuper@48813
    29
neuper@48813
    30
text {*"----------- fun INT_GCD --------------------------------"*};
neuper@48813
    31
value "gcd (15::int) (6::int)" -- "= 3"
neuper@48813
    32
value "gcd (10::int) (3::int)" -- "= 1"
neuper@48813
    33
value "gcd (6::int) (24::int)" -- "= 6"
neuper@48813
    34
neuper@48813
    35
subsection {* modulo calculations for integers *}
neuper@48813
    36
neuper@48813
    37
function modi :: "int => int => int => int => int"
neuper@48813
    38
  where "modi r rold m rinv = 
neuper@48813
    39
    (if rinv < m 
neuper@48813
    40
     then 
neuper@48813
    41
      if r mod m = 1 
neuper@48813
    42
      then rinv 
neuper@48813
    43
      else modi (rold * (rinv + 1)) rold m (rinv + 1) 
neuper@48813
    44
     else 0)"
neuper@48813
    45
  by auto
neuper@48813
    46
  termination sorry
neuper@48813
    47
(* modi is just local for mod_inv *)
neuper@48813
    48
fun mod_inv :: "int => int => int"
neuper@48813
    49
  where "mod_inv r m = modi r r m 1"
neuper@48813
    50
neuper@48813
    51
text {*"----------- fun mod_inv --------------------------------"*}
neuper@48813
    52
value "modi 5 5 7 1"   -- "= 3"
neuper@48813
    53
value "modi 3 3 7 1"   -- "= 5"
neuper@48813
    54
value "modi 4 4 339 1" -- "= 85"
neuper@48813
    55
neuper@48813
    56
value "mod_inv 5 7"    -- "= 3"
neuper@48813
    57
value "mod_inv 3 7"    -- "= 5"
neuper@48813
    58
value "mod_inv 4 339"  -- "= 85"
neuper@48813
    59
neuper@48813
    60
fun mod_div :: "int => int => int => int"
neuper@48813
    61
  where "mod_div a b m = a * (mod_inv b m) mod m"
neuper@48813
    62
neuper@48813
    63
function root1 :: "int => int => int"
neuper@48813
    64
  where "root1 a n = (if n * n < a then root1 a (n + 1) else n)"
neuper@48813
    65
  by auto
neuper@48813
    66
  termination sorry
neuper@48813
    67
(* root1 is only local to approx_root *)
neuper@48813
    68
fun approx_root :: "int => int"
neuper@48813
    69
  where "approx_root a = root1 a 1"
neuper@48813
    70
neuper@48813
    71
fun chinese_remainder :: "int => int => int => int => int"
neuper@48813
    72
  where "chinese_remainder r1 m1 r2 m2 = 
neuper@48813
    73
    (r1 mod m1) + ((r2 - (r1 mod m1)) * (mod_inv m1 m2) mod m2) * m1"
neuper@48813
    74
neuper@48813
    75
text {*"----------- fun chinese_remainder ----------------------"*}
neuper@48813
    76
value "chinese_remainder 17 9 3 4 "  -- "= 35"
neuper@48813
    77
value "chinese_remainder  7 2 6 11"  -- "= 17"
neuper@48813
    78
neuper@48813
    79
subsection {* operations with primes *}
neuper@48813
    80
neuper@48813
    81
(* assumes: 'primes' contains all of first primes /\ n =< (max primes)^2 *)
neuper@48813
    82
fun is_prime :: "int list \<Rightarrow> int \<Rightarrow> bool"
neuper@48813
    83
  where "is_prime primes n = 
neuper@48813
    84
    (if List.length primes > 0
neuper@48813
    85
    then 
neuper@48813
    86
      if (n mod (List.hd primes)) = 0
neuper@48813
    87
      then False
neuper@48813
    88
      else is_prime (List.tl primes) n
neuper@48813
    89
    else True)"
neuper@48813
    90
neuper@48813
    91
value "is_prime [2, 3] 2"  -- "= False"
neuper@48813
    92
value "is_prime [2, 3] 3"  -- "= False"
neuper@48813
    93
value "is_prime [2, 3] 4"  -- "= False"
neuper@48813
    94
value "is_prime [2, 3] 5"  -- "= True"
neuper@48813
    95
value "is_prime [2, 3] 6"  -- "= False"
neuper@48813
    96
value "is_prime [2, 3] 25" -- "= True ... because 5 not in list"
neuper@48813
    97
neuper@48813
    98
(* make_prims is local to make_primes *)
neuper@48813
    99
function make_primes :: "int list \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int list"
neuper@48813
   100
  where "make_primes primes last_p n =
neuper@48813
   101
    (if (List.nth primes (List.length primes - 1)) < n
neuper@48813
   102
    then
neuper@48813
   103
      if is_prime primes (last_p + 2) 
neuper@48813
   104
      then make_primes (primes @ [(last_p + 2)]) (last_p + 2) n
neuper@48813
   105
      else make_primes  primes (last_p + 2) n
neuper@48813
   106
    else primes)"
neuper@48813
   107
  by pat_completeness (simp del: is_prime.simps)
neuper@48813
   108
  termination sorry
neuper@48813
   109
neuper@48813
   110
(* make_primes :: int \<Rightarrow> int list
neuper@48813
   111
   make_primes n = [2, 3, 5, 7, .., p_k]                 -- sloppy formulations
neuper@48813
   112
     assumes 0 < n
neuper@48813
   113
     yields SOME k. ([2, 3, 5, 7, .., p_k] contains all primes \<le> p_n) \<and> n \<le> p_k *)
neuper@48813
   114
fun primes_upto :: "int \<Rightarrow> int list"
neuper@48813
   115
  where "primes_upto n = (if n < 3 then [2] else make_primes [2,3] 3 n)"
neuper@48813
   116
neuper@48813
   117
value "primes_upto 2" -- "[2]"
neuper@48813
   118
value "primes_upto 3" -- "[2, 3]"
neuper@48813
   119
value "primes_upto 4" -- "[2, 3]"
neuper@48813
   120
value "primes_upto 5" -- "[2, 3, 5]"
neuper@48813
   121
value "primes_upto 6" -- "[2, 3, 5, 7]"
neuper@48813
   122
value "primes_upto 7" -- "[2, 3, 5, 7]"
neuper@48813
   123
value "primes_upto 8" -- "[2, 3, 5, 7, 11]"
neuper@48813
   124
value "primes_upto 9" -- "[2, 3, 5, 7, 11]"
neuper@48813
   125
neuper@48813
   126
(*---------------------------------------------------*)
neuper@48813
   127
ML {* 
neuper@48813
   128
val ps = [2,3,5,7,11];
neuper@48813
   129
nth ps (List.length ps - 1);
neuper@48813
   130
*}
neuper@48813
   131
thm primes_upto.simps
neuper@48813
   132
thm primes_upto_def
neuper@48813
   133
neuper@48813
   134
(*---------------------------------------------------*)
neuper@48813
   135
neuper@48813
   136
text {*
neuper@48813
   137
  :
neuper@48813
   138
  by pat_completeness (simp del: is_prime.simps)
neuper@48813
   139
  by pat_completeness (simp del: primes_upto.simps)
neuper@48813
   140
  by pat_completeness (simp del: primes_upto.simps,is_prime.simps)
neuper@48813
   141
  by pat_completeness (simp (no_asm))
neuper@48813
   142
  by simp
neuper@48813
   143
  by pat_completeness auto 
neuper@48813
   144
  by pat_completeness force 
neuper@48813
   145
  by pat_completeness blast
neuper@48813
   146
  :
neuper@48813
   147
neuper@48813
   148
function next_prime_not_dividing :: "int \<Rightarrow> int \<Rightarrow> int" (infixl "next'_prime'_not'_dividing" 70)
neuper@48813
   149
  where "p next_prime_not_dividing n = 
neuper@48813
   150
    (let
neuper@48813
   151
      ps = primes_upto (p + 1);
neuper@48813
   152
      nxt = nth ps (List.length ps - 1)
neuper@48813
   153
    in
neuper@48813
   154
      if n mod nxt \<noteq> 0
neuper@48813
   155
      then nxt
neuper@48813
   156
      else nxt next_prime_not_dividing n)"
neuper@48813
   157
  using [[simp_trace_depth_limit=999]]
neuper@48813
   158
  using [[simp_trace=true]]
neuper@48813
   159
  by (simp del: primes_upto.simps is_prime.simps)
neuper@48813
   160
  termination sorry
neuper@48813
   161
*}
neuper@48813
   162
neuper@48813
   163
end