src/Tools/isac/Knowledge/GCD_Poly_FP.thy
changeset 48864 679c95f19808
parent 48863 84da1e3e4600
child 48865 97408b42129d
equal deleted inserted replaced
48863:84da1e3e4600 48864:679c95f19808
    31 
    31 
    32 value "gcd (15::int) (6::int) = 3"
    32 value "gcd (15::int) (6::int) = 3"
    33 value "gcd (10::int) (3::int) = 1"
    33 value "gcd (10::int) (3::int) = 1"
    34 value "gcd (6::int) (24::int) = 6"
    34 value "gcd (6::int) (24::int) = 6"
    35 
    35 
    36 (* why has this been removed since 2002 ? *)
       
    37 definition last_elem :: "'a list \<Rightarrow> 'a" where
       
    38   "last_elem ls = (hd o rev) ls"
       
    39 
       
    40 (* drop tail elements equal 0 *)
    36 (* drop tail elements equal 0 *)
    41 primrec drop_hd_zeros :: "int list \<Rightarrow> int list" where
    37 primrec drop_hd_zeros :: "int list \<Rightarrow> int list" where
    42   "drop_hd_zeros (p # ps) = (if p = 0 then drop_hd_zeros ps else (p # ps))"
    38 "drop_hd_zeros (p # ps) = (if p = 0 then drop_hd_zeros ps else (p # ps))"
    43 definition drop_tl_zeros :: "int list \<Rightarrow> int list" where
    39 definition drop_tl_zeros :: "int list \<Rightarrow> int list" where
    44   "drop_tl_zeros p = (rev o drop_hd_zeros o rev) p"
    40 "drop_tl_zeros p = (rev o drop_hd_zeros o rev) p"
    45 
    41 
    46 subsection {* modulo calculations for integers *}
    42 subsection {* modulo calculations for integers *}
    47 (* modi is just local for mod_inv *)
    43 (* modi is just local for mod_inv *)
    48 function modi :: "int \<Rightarrow> int \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat" where
    44 function modi :: "int \<Rightarrow> int \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat" where
    49   "modi r rold m rinv = 
    45 "modi r rold m rinv = 
    50     (if m \<le> rinv
    46 (if m \<le> rinv
    51       then 0 else
    47   then 0 else
    52         if r mod (int m) = 1 
    48     if r mod (int m) = 1 
    53         then rinv 
    49     then rinv 
    54         else modi (rold * ((int rinv) + 1)) rold m (rinv + 1))"
    50     else modi (rold * ((int rinv) + 1)) rold m (rinv + 1))"
    55 by auto
    51 by auto
    56 termination by (relation "measure (\<lambda>(r, rold, m, rinv). m - rinv)") auto
    52 termination by (relation "measure (\<lambda>(r, rold, m, rinv). m - rinv)") auto
    57 
    53 
    58 (* mod_inv :: int \<Rightarrow> nat \<Rightarrow> nat
    54 (* mod_inv :: int \<Rightarrow> nat \<Rightarrow> nat
    59    mod_inv r m = s
    55    mod_inv r m = s
    60    assumes True
    56    assumes True
    61    yields r * s mod m = 1 *)
    57    yields r * s mod m = 1 *)
    62 definition mod_inv :: "int \<Rightarrow> nat \<Rightarrow> nat" where
    58 definition mod_inv :: "int \<Rightarrow> nat \<Rightarrow> nat" where "mod_inv r m = modi r r m 1"
    63   "mod_inv r m = modi r r m 1"
       
    64 
    59 
    65 value "modi 5 5 7 1   = 3"
    60 value "modi 5 5 7 1   = 3"
    66 value "modi 3 3 7 1   = 5"
    61 value "modi 3 3 7 1   = 5"
    67 value "modi 4 4 339 1 = 85"
    62 value "modi 4 4 339 1 = 85"
    68 
    63 
    77 (* mod_div :: int \<Rightarrow> int \<Rightarrow> nat \<Rightarrow> nat
    72 (* mod_div :: int \<Rightarrow> int \<Rightarrow> nat \<Rightarrow> nat
    78    mod_div a b m = c
    73    mod_div a b m = c
    79    assumes True
    74    assumes True
    80    yields a * b ^(-1) mod m = c   <\<Longrightarrow>  a mod m = *)
    75    yields a * b ^(-1) mod m = c   <\<Longrightarrow>  a mod m = *)
    81 definition mod_div :: "int \<Rightarrow> int \<Rightarrow> nat \<Rightarrow> nat" where
    76 definition mod_div :: "int \<Rightarrow> int \<Rightarrow> nat \<Rightarrow> nat" where
    82   "mod_div a b m = (nat a) * (mod_inv b m) mod m"
    77 "mod_div a b m = (nat a) * (mod_inv b m) mod m"
    83 
    78 
    84 (* root1 is just local to approx_root *)
    79 (* root1 is just local to approx_root *)
    85 function root1 :: "int \<Rightarrow> nat \<Rightarrow> nat" where
    80 function root1 :: "int \<Rightarrow> nat \<Rightarrow> nat" where
    86   "root1 a n = (if (int (n * n)) < a then root1 a (n + 1) else n)"
    81 "root1 a n = (if (int (n * n)) < a then root1 a (n + 1) else n)"
    87 by auto
    82 by auto
    88 termination by (relation "measure (\<lambda>(a, n). nat (a - (int (n * n))))") auto
    83 termination by (relation "measure (\<lambda>(a, n). nat (a - (int (n * n))))") auto
    89 
    84 
    90 (* required just for one approximation:
    85 (* required just for one approximation:
    91    approx_root :: nat \<Rightarrow> nat
    86    approx_root :: nat \<Rightarrow> nat
    92    approx_root a = r
    87    approx_root a = r
    93    assumes True
    88    assumes True
    94    yields r * r \<ge> a *)
    89    yields r * r \<ge> a *)
    95 definition approx_root :: "int \<Rightarrow> nat" where
    90 definition approx_root :: "int \<Rightarrow> nat" where "approx_root a = root1 a 1"
    96   "approx_root a = root1 a 1"
       
    97 
    91 
    98 (* chinese_remainder :: int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int
    92 (* chinese_remainder :: int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int
    99    chinese_remainder (r1, m1) (r2, m2) = r
    93    chinese_remainder (r1, m1) (r2, m2) = r
   100    assumes True
    94    assumes True
   101    yields r = r1 mod m1 \<and> r = r2 mod m2 *)
    95    yields r = r1 mod m1 \<and> r = r2 mod m2 *)
   102 definition chinese_remainder :: "int \<Rightarrow> nat \<Rightarrow> int \<Rightarrow> nat \<Rightarrow> nat" where
    96 definition chinese_remainder :: "int \<Rightarrow> nat \<Rightarrow> int \<Rightarrow> nat \<Rightarrow> nat" where
   103   "chinese_remainder r1 m1 r2 m2 = 
    97 "chinese_remainder r1 m1 r2 m2 = 
   104     ((nat (r1 mod (int m1))) + 
    98   ((nat (r1 mod (int m1))) + 
   105       (nat (((r2 - (r1 mod (int m1))) * (int (mod_inv (int m1) m2))) mod (int m2))) * m1)"
    99     (nat (((r2 - (r1 mod (int m1))) * (int (mod_inv (int m1) m2))) mod (int m2))) * m1)"
   106 
   100 
   107 value "chinese_remainder 17 9 3 4  = 35"
   101 value "chinese_remainder 17 9 3 4  = 35"
   108 value "chinese_remainder  7 2 6 11 = 17"
   102 value "chinese_remainder  7 2 6 11 = 17"
   109 
   103 
   110 subsection {* creation of lists of primes for efficiency *}
   104 subsection {* creation of lists of primes for efficiency *}
   114    assumes max ps < n  \<and>  n \<le> (max ps)^2  \<and>  
   108    assumes max ps < n  \<and>  n \<le> (max ps)^2  \<and>  
   115      (*     FIXME: really ^^^^^^^^^^^^^^^? *)
   109      (*     FIXME: really ^^^^^^^^^^^^^^^? *)
   116      (\<forall>p. List.member ps p \<longrightarrow> Primes.prime p) \<and> (\<forall>p. p < n \<and> Primes.prime p \<longrightarrow> List.member ps p)
   110      (\<forall>p. List.member ps p \<longrightarrow> Primes.prime p) \<and> (\<forall>p. p < n \<and> Primes.prime p \<longrightarrow> List.member ps p)
   117    yields Primes.prime n *)
   111    yields Primes.prime n *)
   118 fun is_prime :: "nat list \<Rightarrow> nat \<Rightarrow> bool" where
   112 fun is_prime :: "nat list \<Rightarrow> nat \<Rightarrow> bool" where
   119   "is_prime ps n = 
   113 "is_prime ps n = 
   120     (if List.length ps > 0
   114 (if List.length ps > 0
   121     then 
   115 then 
   122       if (n mod (List.hd ps)) = 0
   116   if (n mod (List.hd ps)) = 0
   123       then False
   117   then False
   124       else is_prime (List.tl ps) n
   118   else is_prime (List.tl ps) n
   125     else True)"
   119 else True)"
   126 declare is_prime.simps [simp del] -- "make_primes, next_prime_not_dvd"
   120 declare is_prime.simps [simp del] -- "make_primes, next_prime_not_dvd"
   127 
   121 
   128 value "is_prime [2, 3] 2  = False"    --"... precondition!"
   122 value "is_prime [2, 3] 2  = False"    --"... precondition!"
   129 value "is_prime [2, 3] 3  = False"    --"... precondition!"
   123 value "is_prime [2, 3] 3  = False"    --"... precondition!"
   130 value "is_prime [2, 3] 4  = False"
   124 value "is_prime [2, 3] 4  = False"
   140    assumes last_p = maxs ps  \<and>  (\<forall>p. List.member ps p \<longrightarrow> Primes.prime p)  \<and>
   134    assumes last_p = maxs ps  \<and>  (\<forall>p. List.member ps p \<longrightarrow> Primes.prime p)  \<and>
   141      (\<forall>p. p < last_p \<and> Primes.prime p \<longrightarrow> List.member ps p)
   135      (\<forall>p. p < last_p \<and> Primes.prime p \<longrightarrow> List.member ps p)
   142    yields n \<le> maxs pps  \<and>  (\<forall>p. List.member pps p \<longrightarrow> Primes.prime p)  \<and>
   136    yields n \<le> maxs pps  \<and>  (\<forall>p. List.member pps p \<longrightarrow> Primes.prime p)  \<and>
   143      (\<forall>p. (p < maxs pps \<and> Primes.prime p) \<longrightarrow> List.member pps p)*)
   137      (\<forall>p. (p < maxs pps \<and> Primes.prime p) \<longrightarrow> List.member pps p)*)
   144 function make_primes :: "nat list \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat list" where
   138 function make_primes :: "nat list \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat list" where
   145   "make_primes ps last_p n =
   139 "make_primes ps last_p n =
   146     (if n <= last_elem ps then ps else
   140 (if n <= last ps then ps else
   147       if is_prime ps (last_p + 2)
   141   if is_prime ps (last_p + 2)
   148       then make_primes (ps @ [(last_p + 2)]) (last_p + 2) n
   142   then make_primes (ps @ [(last_p + 2)]) (last_p + 2) n
   149       else make_primes  ps                   (last_p + 2) n)"
   143   else make_primes  ps                   (last_p + 2) n)"
   150 by pat_completeness auto --"simp del: is_prime.simps <-- declare"
   144 by pat_completeness auto --"simp del: is_prime.simps <-- declare"
   151 (*Calls:
   145 (*Calls:
   152   a) (ps, last_p, n) ~> (ps @ [last_p + 2], last_p + 2, n)
   146   a) (ps, last_p, n) ~> (ps @ [last_p + 2], last_p + 2, n)
   153   b) (ps, last_p, n) ~> (ps,                last_p + 2, n) 
   147   b) (ps, last_p, n) ~> (ps,                last_p + 2, n) 
   154 Measures:
   148 Measures:
   193      assumes True
   187      assumes True
   194      yields (\<forall>p. List.member ps p \<longrightarrow> Primes.prime p) \<and>
   188      yields (\<forall>p. List.member ps p \<longrightarrow> Primes.prime p) \<and>
   195        n \<le> maxs ps \<and> maxs ps \<le> Fact.fact n + 1 \<and>
   189        n \<le> maxs ps \<and> maxs ps \<le> Fact.fact n + 1 \<and>
   196        (\<forall>p. p \<le> maxs ps \<and> Primes.prime p \<longrightarrow> List.member ps p) *)
   190        (\<forall>p. p \<le> maxs ps \<and> Primes.prime p \<longrightarrow> List.member ps p) *)
   197 definition primes_upto :: "nat \<Rightarrow> nat list" where
   191 definition primes_upto :: "nat \<Rightarrow> nat list" where
   198   "primes_upto n = (if n < 3 then [2] else make_primes [2, 3] 3 n)"
   192 "primes_upto n = (if n < 3 then [2] else make_primes [2, 3] 3 n)"
   199 
   193 
   200 value "primes_upto  2 = [2]"
   194 value "primes_upto  2 = [2]"
   201 value "primes_upto  3 = [2, 3]"
   195 value "primes_upto  3 = [2, 3]"
   202 value "primes_upto  4 = [2, 3, 5]"
   196 value "primes_upto  4 = [2, 3, 5]"
   203 value "primes_upto  5 = [2, 3, 5]"
   197 value "primes_upto  5 = [2, 3, 5]"
   207 value "primes_upto  9 = [2, 3, 5, 7, 11]"
   201 value "primes_upto  9 = [2, 3, 5, 7, 11]"
   208 value "primes_upto 10 = [2, 3, 5, 7, 11]"
   202 value "primes_upto 10 = [2, 3, 5, 7, 11]"
   209 value "primes_upto 11 = [2, 3, 5, 7, 11]"
   203 value "primes_upto 11 = [2, 3, 5, 7, 11]"
   210 
   204 
   211 (* max's' is analogous to Integer.gcds *)
   205 (* max's' is analogous to Integer.gcds *)
   212 definition maxs :: "nat list \<Rightarrow> nat" where
   206 definition maxs :: "nat list \<Rightarrow> nat" where "maxs ns = List.fold max ns (List.hd ns)"
   213   "maxs ns = List.fold max ns (List.hd ns)"
   207 
   214 value "maxs [5, 3, 7, 1, 2, 4] = 7"
   208 value "maxs [5, 3, 7, 1, 2, 4] = 7"
   215 
   209 
   216 (* find the next prime greater p not dividing the number n:
   210 (* find the next prime greater p not dividing the number n:
   217   next_prime_not_dvd :: int \<Rightarrow> int \<Rightarrow> int (infix)
   211   next_prime_not_dvd :: int \<Rightarrow> int \<Rightarrow> int (infix)
   218   n1 next_prime_not_dvd n2 = p
   212   n1 next_prime_not_dvd n2 = p
   219     assumes True
   213     assumes True
   220     yields p is_prime  \<and>  n1 < p  \<and>  \<not> p dvd n2  \<and> (* smallest with these properties... *)
   214     yields p is_prime  \<and>  n1 < p  \<and>  \<not> p dvd n2  \<and> (* smallest with these properties... *)
   221       (\<forall> p'. (p' is_prime  \<and>  n1 < p'  \<and>  \<not> p' dvd n2)  \<longrightarrow>  p \<le> p') *)
   215       (\<forall> p'. (p' is_prime  \<and>  n1 < p'  \<and>  \<not> p' dvd n2)  \<longrightarrow>  p \<le> p') *)
   222 function next_prime_not_dvd :: "nat \<Rightarrow> nat \<Rightarrow> nat" (infixl "next'_prime'_not'_dvd" 70) where
   216 function next_prime_not_dvd :: "nat \<Rightarrow> nat \<Rightarrow> nat" (infixl "next'_prime'_not'_dvd" 70) where
   223  "n1 next_prime_not_dvd n2 = 
   217 "n1 next_prime_not_dvd n2 = 
   224   (let
   218 (let
   225     ps = primes_upto (n1 + 1);
   219   ps = primes_upto (n1 + 1);
   226     nxt = last ps
   220   nxt = last ps
   227   in
   221 in
   228     if n2 mod nxt \<noteq> 0
   222   if n2 mod nxt \<noteq> 0
   229     then nxt
   223   then nxt
   230     else nxt next_prime_not_dvd n2)"
   224   else nxt next_prime_not_dvd n2)"
   231 by auto --"simp del: is_prime.simps, make_primes.simps, primes_upto.simps <-- declare"
   225 by auto --"simp del: is_prime.simps, make_primes.simps, primes_upto.simps <-- declare"
   232 termination (*next_prime_not_dvd ..Inner syntax error*) (*not finished*)
   226 termination (*next_prime_not_dvd ..Inner syntax error*) (*not finished*)
   233   apply (relation "measure (\<lambda>(n1, n2). n2 - n1)") 
   227   apply (relation "measure (\<lambda>(n1, n2). n2 - n1)") 
   234   apply auto
   228   apply auto
   235 sorry (*by lexicographic_order unfinished subgoals*)
   229 sorry (*by lexicographic_order unfinished subgoals*)
   252 
   246 
   253 subsection {* basic notions for univariate polynomials *}
   247 subsection {* basic notions for univariate polynomials *}
   254 
   248 
   255 (* not in List.thy, copy from library.ML *)
   249 (* not in List.thy, copy from library.ML *)
   256 fun nth_drop :: "nat \<Rightarrow> 'a list \<Rightarrow> 'a list" where
   250 fun nth_drop :: "nat \<Rightarrow> 'a list \<Rightarrow> 'a list" where
   257   "nth_drop n xs = List.take n xs @ List.drop (n + 1) xs"
   251 "nth_drop n xs = List.take n xs @ List.drop (n + 1) xs"
   258 value "nth_drop 0 []              = []"
   252 value "nth_drop 0 []              = []"
   259 value "nth_drop 0 [1, 2, 3::int]  = [2, 3]"
   253 value "nth_drop 0 [1, 2, 3::int]  = [2, 3]"
   260 value "nth_drop 2 [1, 2, 3::int]  = [1, 2]"
   254 value "nth_drop 2 [1, 2, 3::int]  = [1, 2]"
   261 value "nth_drop 77 [1, 2, 3::int] = [1, 2, 3]"
   255 value "nth_drop 77 [1, 2, 3::int] = [1, 2, 3]"
   262 
   256 
   263 (* leading coefficient *)
   257 (* leading coefficient *)
   264 definition lcoeff_up :: "unipoly \<Rightarrow> int" where
   258 definition lcoeff_up :: "unipoly \<Rightarrow> int" where "lcoeff_up p = (last o drop_tl_zeros) p"
   265   "lcoeff_up p = (last_elem o drop_tl_zeros) p"
       
   266 
   259 
   267 value "lcoeff_up [3, 4, 5, 6]    = 6"
   260 value "lcoeff_up [3, 4, 5, 6]    = 6"
   268 value "lcoeff_up [3, 4, 5, 6, 0] = 6"
   261 value "lcoeff_up [3, 4, 5, 6, 0] = 6"
   269 
   262 
   270 (* drop leading coefficients equal 0 *)
   263 (* drop leading coefficients equal 0 *)
   274   "drop_lc0_up p = drop_tl_zeros p"
   267   "drop_lc0_up p = drop_tl_zeros p"
   275 (**)fun drop_lc0_up :: "unipoly \<Rightarrow> unipoly" where 
   268 (**)fun drop_lc0_up :: "unipoly \<Rightarrow> unipoly" where 
   276   "drop_lc0_up p = drop_tl_zeros p"
   269   "drop_lc0_up p = drop_tl_zeros p"
   277 *)
   270 *)
   278 fun drop_lc0_up :: "unipoly \<Rightarrow> unipoly" where 
   271 fun drop_lc0_up :: "unipoly \<Rightarrow> unipoly" where 
   279   "drop_lc0_up [] = []"
   272 "drop_lc0_up [] = []" |
   280 | "drop_lc0_up p = 
   273 "drop_lc0_up p = 
   281     (let l = List.length p - 1
   274   (let l = List.length p - 1
   282     in
   275   in
   283       if p ! l = 0
   276     if p ! l = 0
   284       then drop_lc0_up (nth_drop l p)
   277     then drop_lc0_up (nth_drop l p)
   285       else p)"
   278     else p)"
   286 
   279 
   287 value "drop_lc0_up [0, 1, 2, 3, 4, 5, 0, 0] = [0, 1, 2, 3, 4, 5]"
   280 value "drop_lc0_up [0, 1, 2, 3, 4, 5, 0, 0] = [0, 1, 2, 3, 4, 5]"
   288 value "drop_lc0_up [0, 1, 2, 3, 4, 5]       = [0, 1, 2, 3, 4, 5]"
   281 value "drop_lc0_up [0, 1, 2, 3, 4, 5]       = [0, 1, 2, 3, 4, 5]"
   289 
   282 
   290 (* degree *)
   283 (* degree *)
   300 
   293 
   301 (**)definition deg_up :: "unipoly \<Rightarrow> nat" where
   294 (**)definition deg_up :: "unipoly \<Rightarrow> nat" where
   302   "deg_up p = ((op - 1) o length o drop_lc0_up) p"
   295   "deg_up p = ((op - 1) o length o drop_lc0_up) p"
   303 *)
   296 *)
   304 function deg_up :: "unipoly \<Rightarrow> nat" where
   297 function deg_up :: "unipoly \<Rightarrow> nat" where
   305   "deg_up p =
   298 "deg_up p =
   306     (let len = List.length p - 1
   299 (let len = List.length p - 1
   307     in
   300 in
   308       if p ! len \<noteq> 0 then len else deg_up (nth_drop len p))"
   301   if p ! len \<noteq> 0 then len else deg_up (nth_drop len p))"
   309 by (*pat_completeness*) auto 
   302 by (*pat_completeness*) auto 
   310 
   303 
   311 lemma termin_1:
   304 lemma termin_1:
   312   fixes p::"nat list"
   305   fixes p::"nat list"
   313   assumes "length p - Suc 0 = 0"
   306   assumes "length p - Suc 0 = 0"
   335 value "deg_up [3, 4, 5, 6, 0] = 3"
   328 value "deg_up [3, 4, 5, 6, 0] = 3"
   336 value "deg_up [1, 0, 3, 0, 0] = 2"
   329 value "deg_up [1, 0, 3, 0, 0] = 2"
   337 
   330 
   338 (* norm is just local to normalise *)
   331 (* norm is just local to normalise *)
   339 fun norm :: "unipoly \<Rightarrow> unipoly \<Rightarrow> nat \<Rightarrow> int \<Rightarrow> nat \<Rightarrow> unipoly" where
   332 fun norm :: "unipoly \<Rightarrow> unipoly \<Rightarrow> nat \<Rightarrow> int \<Rightarrow> nat \<Rightarrow> unipoly" where
   340   "norm p nrm m lcp i = 
   333 "norm p nrm m lcp i = 
   341     (if i = 0
   334 (if i = 0
   342      then [int (mod_div (p ! i) lcp m)] @ nrm
   335   then [int (mod_div (p ! i) lcp m)] @ nrm
   343      else norm p ([int (mod_div (p ! i) lcp m)] @ nrm) m lcp (i - 1))"
   336   else norm p ([int (mod_div (p ! i) lcp m)] @ nrm) m lcp (i - 1))"
   344 (* normalise a unipoly such that lcoeff_up mod m = 1.
   337 (* normalise a unipoly such that lcoeff_up mod m = 1.
   345    normalise :: unipoly \<Rightarrow> nat \<Rightarrow> unipoly
   338    normalise :: unipoly \<Rightarrow> nat \<Rightarrow> unipoly
   346    normalise [p_0, .., p_k] m = [q_0, .., q_k]
   339    normalise [p_0, .., p_k] m = [q_0, .., q_k]
   347      assumes 
   340      assumes 
   348      yields \<exists> t. 0 \<le> i \<le> k \<Rightarrow> (p_i * t) mod m = q_i  \<and>  (p_k * t) mod m = 1 *)
   341      yields \<exists> t. 0 \<le> i \<le> k \<Rightarrow> (p_i * t) mod m = q_i  \<and>  (p_k * t) mod m = 1 *)
   349 fun normalise :: "unipoly \<Rightarrow> nat \<Rightarrow> unipoly" where
   342 fun normalise :: "unipoly \<Rightarrow> nat \<Rightarrow> unipoly" where
   350   "normalise p m = 
   343 "normalise p m = 
   351     (let
   344 (let
   352      p = drop_lc0_up p;
   345  p = drop_lc0_up p;
   353      lcp = lcoeff_up p
   346  lcp = lcoeff_up p
   354     in 
   347 in 
   355       if List.length p = 0 then [] else norm p [] m lcp (List.length p - 1))"
   348   if List.length p = 0 then [] else norm p [] m lcp (List.length p - 1))"
   356 declare normalise.simps [simp del] --"HENSEL_lifting_up"
   349 declare normalise.simps [simp del] --"HENSEL_lifting_up"
   357 
   350 
   358 value "normalise [-18, -15, -20, 12, 20, -13, 2] 5 = [1, 0, 0, 1, 0, 1, 1]"
   351 value "normalise [-18, -15, -20, 12, 20, -13, 2] 5 = [1, 0, 0, 1, 0, 1, 1]"
   359 value "normalise [9, 6, 3] 10                      = [3, 2, 1]"
   352 value "normalise [9, 6, 3] 10                      = [3, 2, 1]"
   360 
   353 
   361 subsection {* addition, multiplication, division *}
   354 subsection {* addition, multiplication, division *}
   362 
   355 
   363 (* scalar multiplication, %* in GCD_Poly.thy *)
   356 (* scalar multiplication *)
   364 definition  mult_ups :: "unipoly \<Rightarrow> int \<Rightarrow> unipoly" (infixl "mult'_ups" 70) where
   357 definition  mult_ups :: "unipoly \<Rightarrow> int \<Rightarrow> unipoly" (infixl "%*" 70) where
   365  "p mult_ups m = List.map (op * m) p"
   358 "p %* m = List.map (op * m) p"
   366 
   359 
   367 value "[5, 4, 7, 8, 1] mult_ups 5   = [25, 20, 35, 40, 5]"
   360 value "[5, 4, 7, 8, 1] %* 5   = [25, 20, 35, 40, 5]"
   368 value "[5, 4, -7, 8, -1] mult_ups 5 = [25, 20, -35, 40, -5]"
   361 value "[5, 4, -7, 8, -1] %* 5 = [25, 20, -35, 40, -5]"
   369 
   362 
   370 (* scalar divison, %/ in GCD_Poly.thy *)
   363 (* scalar divison *)
   371 definition swapf :: "('a \<Rightarrow> 'b \<Rightarrow> 'c) \<Rightarrow> 'b \<Rightarrow> 'a \<Rightarrow> 'c" where
   364 definition swapf :: "('a \<Rightarrow> 'b \<Rightarrow> 'c) \<Rightarrow> 'b \<Rightarrow> 'a \<Rightarrow> 'c" where "swapf f a b = f b a"
   372   "swapf f a b = f b a"
   365 definition div_ups :: "unipoly \<Rightarrow> int \<Rightarrow> unipoly" (infixl "div'_ups" (* %/ error FLORIAN*) 70) where
   373 definition div_ups :: "unipoly \<Rightarrow> int \<Rightarrow> unipoly" (infixl "div'_ups" 70) where
   366 "p div_ups m = map (swapf op div2 m) p"
   374   "p div_ups m = map (swapf op div2 m) p"
       
   375 
   367 
   376 value "[4, 3, 2, 5, 6] div_ups 3 = [1, 1, 0, 1, 2]"
   368 value "[4, 3, 2, 5, 6] div_ups 3 = [1, 1, 0, 1, 2]"
   377 value "[4, 3, 2, 0] div_ups 3    = [1, 1, 0, 0]"
   369 value "[4, 3, 2, 0] div_ups 3    = [1, 1, 0, 0]"
   378 
   370 
   379 (* not in List.thy, copy from library.ML *)
   371 (* not in List.thy, copy from library.ML *)
   380 fun map2 :: "('a \<Rightarrow> 'b \<Rightarrow> 'c) \<Rightarrow> 'a list \<Rightarrow> 'b list \<Rightarrow> 'c list" where
   372 fun map2 :: "('a \<Rightarrow> 'b \<Rightarrow> 'c) \<Rightarrow> 'a list \<Rightarrow> 'b list \<Rightarrow> 'c list" where
   381   "map2 _ [] [] = []"
   373 "map2 _ [] [] = []" |
   382 | "map2 f (x # xs) (y # ys) = f x y # map2 f xs ys"
   374 "map2 f (x # xs) (y # ys) = f x y # map2 f xs ys" |
   383 | "map2 _ _ _ = []" (*raise ListPair.UnequalLengths*)
   375 "map2 _ _ _ = []" (*raise ListPair.UnequalLengths*)
   384 
   376 
   385 (* minus of polys,  %-% in GCD_Poly.thy *)
   377 (* minus of polys *)
   386 definition minus_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> unipoly" (infixl "minus'_up" 70) where
   378 definition minus_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> unipoly" (infixl "%-%" 70) where
   387   "p1 minus_up p2 = map2 (op -) p1 p2"
   379 "p1 %-% p2 = map2 (op -) p1 p2"
   388 
   380 
   389 value "[8, -7, 0, 1] minus_up [-2, 2, 3, 0]     = [10, -9, -3, 1]"
   381 value "[8, -7, 0, 1] %-% [-2, 2, 3, 0]     = [10, -9, -3, 1]"
   390 value "[8, 7, 6, 5, 4] minus_up [2, 2, 3, 1, 1] = [6, 5, 3, 4, 3]"
   382 value "[8, 7, 6, 5, 4] %-% [2, 2, 3, 1, 1] = [6, 5, 3, 4, 3]"
   391 
   383 
   392 (* lemmata for pattern compatibility in dvd_up *)
   384 (* lemmata for pattern compatibility in dvd_up *)
   393 lemma ex_fals0_1: "([d], [p]) = (v # vb # vc, ps) \<Longrightarrow> QUODLIBET"
   385 lemma ex_fals0_1: "([d], [p]) = (v # vb # vc, ps) \<Longrightarrow> QUODLIBET" by simp
   394 by simp
   386 lemma ex_fals0_2: "([], ps) = (v # vb # vc, psa) \<Longrightarrow> QUODLIBET" by simp
   395 lemma ex_fals0_2: "([], ps) = (v # vb # vc, psa) \<Longrightarrow> QUODLIBET"
   387 lemma ex_fals0_3: "(ds, []) = (dsa, v # vb # vc) \<Longrightarrow> QUODLIBET" by simp
   396 by simp
   388 
   397 lemma ex_fals0_3: "(ds, []) = (dsa, v # vb # vc) \<Longrightarrow> QUODLIBET"
   389 function (sequential) dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "%|%" 70) where
   398 by simp
   390 "[d] %|% [p] = ((\<bar>d\<bar> \<le> \<bar>p\<bar>) & (p mod d = 0))" |
   399 
   391 "ds %|% ps =
   400 function (sequential) dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "dvd'_up" 70) where
   392   (let 
   401   "[d] dvd_up [p] = ((\<bar>d\<bar> \<le> \<bar>p\<bar>) & (p mod d = 0))"
   393     ds = drop_lc0_up ds; ps = drop_lc0_up ps;
   402 | "ds dvd_up ps =
   394     d000 = (List.replicate (List.length ps - List.length ds) 0) @ ds;
   403     (let 
   395     quot = (lcoeff_up ps) div2 (lcoeff_up d000);
   404       ds = drop_lc0_up ds; ps = drop_lc0_up ps;
   396     rest = drop_lc0_up (ps %-% (d000 %* quot))
   405       d000 = (List.replicate (List.length ps - List.length ds) 0) @ ds;
   397   in 
   406       quot = (lcoeff_up ps) div2 (lcoeff_up d000);
   398     if rest = [] then True else 
   407       rest = drop_lc0_up (ps minus_up (d000 mult_ups quot))
   399       if quot \<noteq> 0 & List.length ds \<le> List.length rest then ds %|% rest else False)"
   408     in 
       
   409       if rest = [] then True else 
       
   410         if quot \<noteq> 0 & List.length ds \<le> List.length rest then ds dvd_up rest else False)"
       
   411 apply pat_completeness
   400 apply pat_completeness
   412 apply simp
   401 apply simp
   413 apply simp
   402 apply simp
   414 defer (*a "mixed" obligation*)
   403 defer (*a "mixed" obligation*)
   415 apply simp
   404 apply simp
   439 done (* > 1 sec IMPROVED BY declare simp del: 
   428 done (* > 1 sec IMPROVED BY declare simp del: 
   440   centr_up_def normalise.simps mod_up_gcd.simps lcoeff_up.simps*)
   429   centr_up_def normalise.simps mod_up_gcd.simps lcoeff_up.simps*)
   441 termination (*dvd_up ..Inner syntax error*) sorry (*by lexicographic_order LOOPS*) (*not finished*)
   430 termination (*dvd_up ..Inner syntax error*) sorry (*by lexicographic_order LOOPS*) (*not finished*)
   442 (*cutting definition to 'fun' loops, so no Calls, Measure, Matrix ---?*)
   431 (*cutting definition to 'fun' loops, so no Calls, Measure, Matrix ---?*)
   443 
   432 
   444 value "[4] dvd_up [6]                 = False"
   433 value "[4] %|% [6]                 = False"
   445 value "[8] dvd_up [16, 0]             = True"
   434 value "[8] %|% [16, 0]             = True"
   446 value "[3, 2] dvd_up [0, 0, 9, 12, 4] = True"
   435 value "[3, 2] %|% [0, 0, 9, 12, 4] = True"
   447 value "[8, 0] dvd_up [16]             = True"
   436 value "[8, 0] %|% [16]             = True"
   448 
   437 
   449 subsection {* normalisation and Landau-Mignotte bound *}
   438 subsection {* normalisation and Landau-Mignotte bound *}
   450 
   439 
   451 (* centr is just local to centr_up *)
   440 (* centr is just local to centr_up *)
   452 definition centr :: "nat \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int" where
   441 definition centr :: "nat \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int" where
   453   "centr m mid p_i = (if mid < p_i then p_i - (int m) else p_i)"
   442 "centr m mid p_i = (if mid < p_i then p_i - (int m) else p_i)"
   454 
   443 
   455 (* normalise :: centr_up \<Rightarrow> unipoly => int \<Rightarrow> unipoly
   444 (* normalise :: centr_up \<Rightarrow> unipoly => int \<Rightarrow> unipoly
   456    normalise [p_0, .., p_k] m = [q_0, .., q_k]
   445    normalise [p_0, .., p_k] m = [q_0, .., q_k]
   457      assumes 
   446      assumes 
   458      yields 0 \<le> i \<le> k \<Rightarrow> |^ ~m/2 ^| <= q_i <=|^ m/2 ^| 
   447      yields 0 \<le> i \<le> k \<Rightarrow> |^ ~m/2 ^| <= q_i <=|^ m/2 ^| 
   459       (where |^ x ^| means round x up to the next greater integer) *)
   448       (where |^ x ^| means round x up to the next greater integer) *)
   460 definition centr_up :: "unipoly \<Rightarrow> nat \<Rightarrow> unipoly" where
   449 definition centr_up :: "unipoly \<Rightarrow> nat \<Rightarrow> unipoly" where
   461   "centr_up p m =
   450 "centr_up p m =
   462    (let
   451 (let
   463       mi = (int m) div2 2;
   452   mi = (int m) div2 2;
   464       mid = if (int m) mod mi = 0 then mi else mi + 1
   453   mid = if (int m) mod mi = 0 then mi else mi + 1
   465    in map (centr m mid) p)"
   454 in map (centr m mid) p)"
   466 
   455 
   467 value "centr_up [7, 3, 5, 8, 1, 3] 10 = [-3, 3, 5, -2, 1, 3]"
   456 value "centr_up [7, 3, 5, 8, 1, 3] 10 = [-3, 3, 5, -2, 1, 3]"
   468 value "centr_up [1, 2, 3, 4, 5] 2     = [1, 0, 1, 2, 3]"
   457 value "centr_up [1, 2, 3, 4, 5] 2     = [1, 0, 1, 2, 3]"
   469 value "centr_up [1, 2, 3, 4, 5] 3     = [1, -1, 0, 1, 2]"
   458 value "centr_up [1, 2, 3, 4, 5] 3     = [1, -1, 0, 1, 2]"
   470 value "centr_up [1, 2, 3, 4, 5] 4     = [1, 2, -1, 0, 1]"
   459 value "centr_up [1, 2, 3, 4, 5] 4     = [1, 2, -1, 0, 1]"
   474 value "centr_up [1, 2, 3, 4, 5] 8     = [1, 2, 3, 4, -3]"
   463 value "centr_up [1, 2, 3, 4, 5] 8     = [1, 2, 3, 4, -3]"
   475 value "centr_up [1, 2, 3, 4, 5] 9     = [1, 2, 3, 4, 5]"
   464 value "centr_up [1, 2, 3, 4, 5] 9     = [1, 2, 3, 4, 5]"
   476 value "centr_up [1, 2, 3, 4, 5] 10    = [1, 2, 3, 4, 5]"
   465 value "centr_up [1, 2, 3, 4, 5] 10    = [1, 2, 3, 4, 5]"
   477 value "centr_up [1, 2, 3, 4, 5] 11    = [1, 2, 3, 4, 5]"
   466 value "centr_up [1, 2, 3, 4, 5] 11    = [1, 2, 3, 4, 5]"
   478 
   467 
   479  (*  sum_lmb :: centr_up \<Rightarrow> unipoly \<Rightarrow> int \<Rightarrow> int
   468 (* sum_lmb :: centr_up \<Rightarrow> unipoly \<Rightarrow> int \<Rightarrow> int
   480    sum_lmb [p_0, .., p_k] e = s
   469    sum_lmb [p_0, .., p_k] e = s
   481      assumes exp >= 0
   470      assumes exp >= 0
   482      yields. p_0^e + p_1^e + ... + p_k^e *)
   471      yields. p_0^e + p_1^e + ... + p_k^e *)
   483 definition sum_lmb :: "unipoly \<Rightarrow> nat \<Rightarrow> int" where
   472 definition sum_lmb :: "unipoly \<Rightarrow> nat \<Rightarrow> int" where
   484   "sum_lmb p exp = List.fold ((op +) o (swapf power exp)) p 0"
   473 "sum_lmb p exp = List.fold ((op +) o (swapf power exp)) p 0"
   485 
   474 
   486 value "sum_lmb [-1, 2, -3, 4, -5] 1 = -3"
   475 value "sum_lmb [-1, 2, -3, 4, -5] 1 = -3"
   487 value "sum_lmb [-1, 2, -3, 4, -5] 2 = 55"
   476 value "sum_lmb [-1, 2, -3, 4, -5] 2 = 55"
   488 value "sum_lmb [-1, 2, -3, 4, -5] 3 = -81"
   477 value "sum_lmb [-1, 2, -3, 4, -5] 3 = -81"
   489 value "sum_lmb [-1, 2, -3, 4, -5] 4 = 979"
   478 value "sum_lmb [-1, 2, -3, 4, -5] 4 = 979"
   494    LANDAU_MIGNOTTE_bound [a_0, ..., a_m] [b_0, .., b_n] = lmb
   483    LANDAU_MIGNOTTE_bound [a_0, ..., a_m] [b_0, .., b_n] = lmb
   495      assumes True
   484      assumes True
   496      yields lmb = 2^min(m,n) * gcd(a_m,b_n) * 
   485      yields lmb = 2^min(m,n) * gcd(a_m,b_n) * 
   497        min( 1/|a_m| * root(sum_lmb [a_0,...a_m] 2 , 1/|b_n| * root(sum_lmb [b_0,...b_n] 2)*)
   486        min( 1/|a_m| * root(sum_lmb [a_0,...a_m] 2 , 1/|b_n| * root(sum_lmb [b_0,...b_n] 2)*)
   498 definition LANDAU_MIGNOTTE_bound :: "unipoly \<Rightarrow> unipoly \<Rightarrow> nat" where
   487 definition LANDAU_MIGNOTTE_bound :: "unipoly \<Rightarrow> unipoly \<Rightarrow> nat" where
   499   "LANDAU_MIGNOTTE_bound p1 p2 =
   488 "LANDAU_MIGNOTTE_bound p1 p2 =
   500     ((power 2 (min (deg_up p1) (deg_up p2))) * (nat (gcd (lcoeff_up p1) (lcoeff_up p2))) * 
   489   ((power 2 (min (deg_up p1) (deg_up p2))) * (nat (gcd (lcoeff_up p1) (lcoeff_up p2))) * 
   501     (nat (min (abs ((int (approx_root (sum_lmb p1 2))) div2 -(lcoeff_up p1)))
   490   (nat (min (abs ((int (approx_root (sum_lmb p1 2))) div2 -(lcoeff_up p1)))
   502               (abs ((int (approx_root (sum_lmb p2 2))) div2 -(lcoeff_up p2))))))"
   491             (abs ((int (approx_root (sum_lmb p2 2))) div2 -(lcoeff_up p2))))))"
   503 (*                                      |------------|        -|------------|
       
   504                          |--------------------------|
       
   505                     |--------------------------------|
       
   506                    |-------------------------------------------------------|  *)
       
   507 
   492 
   508 value "LANDAU_MIGNOTTE_bound [1] [4, 5]          = 1"
   493 value "LANDAU_MIGNOTTE_bound [1] [4, 5]          = 1"
   509 value "LANDAU_MIGNOTTE_bound [1, 2] [4, 5]       = 2"
   494 value "LANDAU_MIGNOTTE_bound [1, 2] [4, 5]       = 2"
   510 value "LANDAU_MIGNOTTE_bound [1, 2, 3] [4, 5]    = 2"
   495 value "LANDAU_MIGNOTTE_bound [1, 2, 3] [4, 5]    = 2"
   511 value "LANDAU_MIGNOTTE_bound [1, 2, 3] [4]       = 1"
   496 value "LANDAU_MIGNOTTE_bound [1, 2, 3] [4]       = 1"
   518 value "LANDAU_MIGNOTTE_bound [-1, 2, -3] [4]        = 1"
   503 value "LANDAU_MIGNOTTE_bound [-1, 2, -3] [4]        = 1"
   519 value "LANDAU_MIGNOTTE_bound [-1, 2, -3] [4, -5]    = 2"
   504 value "LANDAU_MIGNOTTE_bound [-1, 2, -3] [4, -5]    = 2"
   520 value "LANDAU_MIGNOTTE_bound [-1, 2, -3] [4, -5, 6] = 12"
   505 value "LANDAU_MIGNOTTE_bound [-1, 2, -3] [4, -5, 6] = 12"
   521 
   506 
   522 subsection {* modulo calculations for polynomials *}
   507 subsection {* modulo calculations for polynomials *}
       
   508 value "List.compound"
   523 
   509 
   524 (* pair is just local to chinese_remainder_up, is "op ~~" in library.ML *)
   510 (* pair is just local to chinese_remainder_up, is "op ~~" in library.ML *)
   525 fun pair :: "unipoly \<Rightarrow> unipoly \<Rightarrow> ((int \<times> int) list)" (infix "pair" 4) where
   511 fun pair :: "unipoly \<Rightarrow> unipoly \<Rightarrow> ((int \<times> int) list)" (infix "pair" 4) where
   526   "([] pair []) = []"
   512 "([] pair []) = []" |
   527 | "([] pair ys) = []" (*raise ListPair.UnequalLengths*)
   513 "([] pair ys) = []" | (*raise ListPair.UnequalLengths*)
   528 | "(xs pair []) = []" (*raise ListPair.UnequalLengths*)
   514 "(xs pair []) = []" | (*raise ListPair.UnequalLengths*)
   529 | "((x#xs) pair (y#ys)) = (x, y) # (xs pair ys)"
   515 "((x#xs) pair (y#ys)) = (x, y) # (xs pair ys)"
   530 fun chinese_rem :: "nat \<times> nat \<Rightarrow> int \<times> int \<Rightarrow> int" where
   516 fun chinese_rem :: "nat \<times> nat \<Rightarrow> int \<times> int \<Rightarrow> int" where
   531  "chinese_rem (m1, m2) (p1, p2) = (int (chinese_remainder p1 m1 p2 m2))"
   517 "chinese_rem (m1, m2) (p1, p2) = (int (chinese_remainder p1 m1 p2 m2))"
   532 
   518 
   533   (* chinese_remainder_up :: int * int \<Rightarrow> unipoly * unipoly \<Rightarrow> unipoly
   519   (* chinese_remainder_up :: int * int \<Rightarrow> unipoly * unipoly \<Rightarrow> unipoly
   534      chinese_remainder_up (m1, m2) (p1, p2) = p
   520      chinese_remainder_up (m1, m2) (p1, p2) = p
   535      assume m1, m2 relatively prime
   521      assume m1, m2 relatively prime
   536      yields p1 = p mod m1 \<and> p2 = p mod m2 *)
   522      yields p1 = p mod m1 \<and> p2 = p mod m2 *)
   537 fun chinese_remainder_up :: "nat \<times> nat \<Rightarrow> unipoly \<times> unipoly \<Rightarrow> unipoly" where
   523 fun chinese_remainder_up :: "nat \<times> nat \<Rightarrow> unipoly \<times> unipoly \<Rightarrow> unipoly" where
   538   "chinese_remainder_up (m1, m2) (p1, p2) = map (chinese_rem (m1, m2)) (p1 pair p2)"
   524 "chinese_remainder_up (m1, m2) (p1, p2) = map (chinese_rem (m1, m2)) (p1 pair p2)"
   539 
   525 
   540 value "chinese_remainder_up (5, 7) ([2, 2, 4, 3], [3, 2, 3, 5]) = [17, 2, 24, 33]"
   526 value "chinese_remainder_up (5, 7) ([2, 2, 4, 3], [3, 2, 3, 5]) = [17, 2, 24, 33]"
   541 
   527 
   542 (* mod_up :: unipoly \<Rightarrow> int \<Rightarrow> unipoly
   528 (* mod_up :: unipoly \<Rightarrow> int \<Rightarrow> unipoly
   543    mod_up [p1, p2, ..., pk] m = up 
   529    mod_up [p1, p2, ..., pk] m = up 
   544    assume m > 0
   530    assume m > 0
   545    yields up = [p1 mod m, p2 mod m, ..., pk mod m]*)
   531    yields up = [p1 mod m, p2 mod m, ..., pk mod m]*)
   546 definition mod' :: "nat \<Rightarrow> int \<Rightarrow> int" where "mod' m i = i mod (int m)"
   532 definition mod' :: "nat \<Rightarrow> int \<Rightarrow> int" where "mod' m i = i mod (int m)"
   547 definition mod_up :: "unipoly \<Rightarrow> nat \<Rightarrow> unipoly" (infixl "mod'_up" 70) where
   533 definition mod_up :: "unipoly \<Rightarrow> nat \<Rightarrow> unipoly" (infixl "mod'_up" 70) where
   548   "p mod_up m = map (mod' m) p"
   534 "p mod_up m = map (mod' m) p"
   549 
   535 
   550 value "[5, 4, 7, 8, 1] mod_up 5 = [0, 4, 2, 3, 1]"
   536 value "[5, 4, 7, 8, 1] mod_up 5 = [0, 4, 2, 3, 1]"
   551 value "[5, 4,-7, 8,-1] mod_up 5 = [0, 4, 3, 3, 4]"
   537 value "[5, 4,-7, 8,-1] mod_up 5 = [0, 4, 3, 3, 4]"
   552 
       
   553 value "curry"
       
   554 value "curry"
       
   555 value "5 mod 3::int"
       
   556 
       
   557 
   538 
   558 (* euclidean algoritm in Z_p[x].
   539 (* euclidean algoritm in Z_p[x].
   559    mod_up_gcd :: unipoly \<Rightarrow> unipoly \<Rightarrow> nat \<Rightarrow> unipoly
   540    mod_up_gcd :: unipoly \<Rightarrow> unipoly \<Rightarrow> nat \<Rightarrow> unipoly
   560    mod_up_gcd p1 p2 m = g
   541    mod_up_gcd p1 p2 m = g
   561      assumes 
   542      assumes 
   562      yields  gcd (p1 mod m) (p2 mod m) = g *)
   543      yields  gcd (p1 mod m) (p2 mod m) = g *)
   563 function mod_up_gcd :: "unipoly \<Rightarrow> unipoly  \<Rightarrow> nat \<Rightarrow> unipoly" where
   544 function mod_up_gcd :: "unipoly \<Rightarrow> unipoly  \<Rightarrow> nat \<Rightarrow> unipoly" where
   564  "mod_up_gcd p1 p2 m = 
   545 "mod_up_gcd p1 p2 m = 
   565    (let 
   546 (let 
   566       p1m = p1 mod_up m;
   547   p1m = p1 mod_up m;
   567       p2m = drop_lc0_up (p2 mod_up m);
   548   p2m = drop_lc0_up (p2 mod_up m);
   568       p2n = (replicate (List.length p1 - List.length p2m) 0) @ p2m;
   549   p2n = (replicate (List.length p1 - List.length p2m) 0) @ p2m;
   569       quot = mod_div (lcoeff_up p1m) (lcoeff_up p2n) m;
   550   quot = mod_div (lcoeff_up p1m) (lcoeff_up p2n) m;
   570       rest = drop_lc0_up ((p1m minus_up (p2n mult_ups (int quot))) mod_up m)
   551   rest = drop_lc0_up ((p1m %-% (p2n %* (int quot))) mod_up m)
   571     in 
   552 in 
   572       if rest = [] 
   553   if rest = [] 
   573       then p2
   554   then p2
   574       else
   555   else
   575         if List.length rest < List.length p2
   556     if List.length rest < List.length p2
   576         then mod_up_gcd p2 rest m 
   557     then mod_up_gcd p2 rest m 
   577         else mod_up_gcd rest p2 m)"
   558     else mod_up_gcd rest p2 m)"
   578 by auto 
   559 by auto 
   579 termination mod_up_gcd (*not finished*)
   560 termination mod_up_gcd (*not finished*)
   580 apply (relation "measures [\<lambda>(p1, p2, m). length p1,
   561 apply (relation "measures [\<lambda>(p1, p2, m). length p1,
   581                            \<lambda>(p1, p2, m). 00000000000000]")
   562                            \<lambda>(p1, p2, m). 00000000000000]")
   582 apply auto
   563 apply auto
   606   gcds :: int list \<Rightarrow> int
   587   gcds :: int list \<Rightarrow> int
   607   gcds ns = d
   588   gcds ns = d
   608   assumes True
   589   assumes True
   609   yields THE d. ((\<forall>n. List.member ns n \<longrightarrow> d dvd n) \<and>
   590   yields THE d. ((\<forall>n. List.member ns n \<longrightarrow> d dvd n) \<and>
   610     (\<forall>d'. (\<forall>n. List.member ns n \<and> d' dvd n) \<longrightarrow> d'modp \<le> d)) *)
   591     (\<forall>d'. (\<forall>n. List.member ns n \<and> d' dvd n) \<longrightarrow> d'modp \<le> d)) *)
   611 fun gcds :: "int list \<Rightarrow> int" where
   592 fun gcds :: "int list \<Rightarrow> int" where "gcds ns = List.fold gcd ns (List.hd ns)"
   612   "gcds ns = List.fold gcd ns (List.hd ns)"
       
   613 
   593 
   614 value "gcds [6, 9, 12] = 3"
   594 value "gcds [6, 9, 12] = 3"
   615 value "gcds [6, -9, 12] = 3"
   595 value "gcds [6, -9, 12] = 3"
   616 value "gcds [8, 12, 16] = 4"
   596 value "gcds [8, 12, 16] = 4"
   617 value "gcds [-8, 12, -16] = 4"
   597 value "gcds [-8, 12, -16] = 4"
   619 (* prim_poly :: unipoly \<Rightarrow> unipoly
   599 (* prim_poly :: unipoly \<Rightarrow> unipoly
   620    prim_poly p = pp
   600    prim_poly p = pp
   621    assumes True
   601    assumes True
   622    yields \<forall>p1, p2. (List.member pp p1 \<and> List.member pp p2 \<and> p1 \<noteq> p2) \<longrightarrow> gcd p1 p2 = 1 *)
   602    yields \<forall>p1, p2. (List.member pp p1 \<and> List.member pp p2 \<and> p1 \<noteq> p2) \<longrightarrow> gcd p1 p2 = 1 *)
   623 fun primitive_up :: "unipoly \<Rightarrow> unipoly" where
   603 fun primitive_up :: "unipoly \<Rightarrow> unipoly" where
   624   "primitive_up [c] = (if c = 0 then [0] else [1])"
   604 "primitive_up [c] = (if c = 0 then [0] else [1])" |
   625 | "primitive_up p =
   605 "primitive_up p =
   626     (let d = gcds p
   606   (let d = gcds p
   627     in
   607   in
   628       if d = 1 then p else p div_ups d)"
   608     if d = 1 then p else p div_ups d)"
   629 
   609 
   630 value "primitive_up [12, 16, 32, 44] = [3, 4, 8, 11]"
   610 value "primitive_up [12, 16, 32, 44] = [3, 4, 8, 11]"
   631 value "primitive_up [4, 5, 12] =  [4, 5, 12]"
   611 value "primitive_up [4, 5, 12] =  [4, 5, 12]"
   632 value "primitive_up [0] = [0]"
   612 value "primitive_up [0] = [0]"
   633 value "primitive_up [6] = [1]"
   613 value "primitive_up [6] = [1]"
   641      yields  new_g = [1] \<or> (new_g \<ge> g \<and> P > M)
   621      yields  new_g = [1] \<or> (new_g \<ge> g \<and> P > M)
   642 
   622 
   643   argumentns "a b d M P g p" named according to [1] p.93 *)
   623   argumentns "a b d M P g p" named according to [1] p.93 *)
   644 (*declare [[show_types]]*)
   624 (*declare [[show_types]]*)
   645 function try_new_prime_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> unipoly \<Rightarrow> nat \<Rightarrow> unipoly" 
   625 function try_new_prime_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> unipoly \<Rightarrow> nat \<Rightarrow> unipoly" 
   646   where 
   626 where 
   647   "try_new_prime_up           a          b          d      M      P     g          p   = 
   627 "try_new_prime_up             a          b          d      M      P     g          p   = 
   648     (if P > M then g else 
   628 (if P > M then g else 
   649       let p' = p next_prime_not_dvd d;
   629   let p' = p next_prime_not_dvd d;
   650           g_p = centr_up (          (          (normalise (mod_up_gcd a b p') p')
   630       g_p = centr_up (          (      (normalise (mod_up_gcd a b p') p')
   651                                         mult_ups ((int d) mod (int p')))
   631                                     %* ((int d) mod (int p')))
   652                              mod_up p')
   632                          mod_up p')
   653                            p'
   633                        p'
   654       in
   634   in
   655         if deg_up g_p < deg_up g
   635     if deg_up g_p < deg_up g
   656         then 
   636     then 
   657           if (deg_up g_p) = 0 then [1] else try_new_prime_up a b d M p g_p p'
   637       if (deg_up g_p) = 0 then [1] else try_new_prime_up a b d M p g_p p'
   658         else 
   638     else 
   659           if deg_up g_p \<noteq> deg_up g then try_new_prime_up a b d M P g p' else
   639       if deg_up g_p \<noteq> deg_up g then try_new_prime_up a b d M P g p' else
   660             let 
   640         let 
   661               P = P * p';
   641           P = P * p';
   662               g = centr_up ((chinese_remainder_up (P, p') (g, g_p)) mod_up P) P
   642           g = centr_up ((chinese_remainder_up (P, p') (g, g_p)) mod_up P) P
   663             in
   643         in
   664               try_new_prime_up a b d M P g p'
   644           try_new_prime_up a b d M P g p')"
   665       )"
       
   666 by pat_completeness auto --"simp del: centr_up_def normalise.simps mod_up_gcd.simps"
   645 by pat_completeness auto --"simp del: centr_up_def normalise.simps mod_up_gcd.simps"
   667 termination try_new_prime_up sorry (*by lexicographic_order LOOPS*) (*not finished*)
   646 termination try_new_prime_up sorry (*by lexicographic_order LOOPS*) (*not finished*)
   668 (*cutting definition to 'fun' loops, so no Calls, Measure, Matrix ---?*)
   647 (*cutting definition to 'fun' loops, so no Calls, Measure, Matrix ---?*)
   669 
   648 
   670 (* HENSEL_lifting_up :: unipoly \<Rightarrow> unipoly \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> unipoly
   649 (* HENSEL_lifting_up :: unipoly \<Rightarrow> unipoly \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> unipoly
   674              p1 is primitive  \<and>  p2 is primitive
   653              p1 is primitive  \<and>  p2 is primitive
   675      yields  gcd | p1  \<and>  gcd | p2  \<and>  gcd is primitive
   654      yields  gcd | p1  \<and>  gcd | p2  \<and>  gcd is primitive
   676 
   655 
   677   argumentns "a b d M p" named according to [1] p.93 *)
   656   argumentns "a b d M p" named according to [1] p.93 *)
   678 function HENSEL_lifting_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> unipoly" where
   657 function HENSEL_lifting_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> unipoly" where
   679   "HENSEL_lifting_up a b d M p = 
   658 "HENSEL_lifting_up a b d M p = 
   680     (let
   659 (let
   681       p = p next_prime_not_dvd d;
   660   p = p next_prime_not_dvd d;
   682       g_p = centr_up (((normalise (mod_up_gcd a b p) p) mult_ups (int (d mod p))) mod_up p) p
   661   g_p = centr_up (((normalise (mod_up_gcd a b p) p) %* (int (d mod p))) mod_up p) p
   683     in 
   662 in 
   684       if deg_up g_p = 0 then [1] else 
   663   if deg_up g_p = 0 then [1] else 
   685         (let 
   664     (let 
   686           g = primitive_up (try_new_prime_up a b d M p g_p p)
   665       g = primitive_up (try_new_prime_up a b d M p g_p p)
   687         in
   666     in
   688           if (g dvd_up a) \<and> (g dvd_up b) then g else HENSEL_lifting_up a b d M p))"
   667       if (g %|% a) \<and> (g %|% b) then g else HENSEL_lifting_up a b d M p))"
   689 by pat_completeness auto --"simp del: centr_up_def normalise.simps mod_up_gcd.simps"
   668 by pat_completeness auto --"simp del: centr_up_def normalise.simps mod_up_gcd.simps"
   690 termination HENSEL_lifting_up sorry (*by lexicographic_order LOOPS*) (*not finished*)
   669 termination HENSEL_lifting_up sorry (*by lexicographic_order LOOPS*) (*not finished*)
   691 (*cutting definition to 'fun' loops, so no Calls, Measure, Matrix ---?*)
   670 (*cutting definition to 'fun' loops, so no Calls, Measure, Matrix ---?*)
   692 
   671 
   693 (* gcd_up :: unipoly \<Rightarrow> unipoly \<Rightarrow> unipoly
   672 (* gcd_up :: unipoly \<Rightarrow> unipoly \<Rightarrow> unipoly
   694    gcd_up a b = c
   673    gcd_up a b = c
   695    assumes not (a = [] \<or> a = [0]) \<and> not (b = []\<or> b = [0]) \<and> 
   674    assumes not (a = [] \<or> a = [0]) \<and> not (b = []\<or> b = [0]) \<and> 
   696            a is primitive \<and> b is primitive
   675            a is primitive \<and> b is primitive
   697    yields c dvd a \<and> c dvd b \<and> (\<forall>c'. (c' dvd a \<and> c' dvd b) \<longrightarrow> c' \<le> c) *)
   676    yields c dvd a \<and> c dvd b \<and> (\<forall>c'. (c' dvd a \<and> c' dvd b) \<longrightarrow> c' \<le> c) *)
   698 function gcd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> unipoly" where
   677 function gcd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> unipoly" where
   699   "gcd_up a b = 
   678 "gcd_up a b = 
   700    (let d = \<bar>gcd (lcoeff_up a) (lcoeff_up b)\<bar>
   679 (let d = \<bar>gcd (lcoeff_up a) (lcoeff_up b)\<bar>
   701     in
   680 in
   702       if a = b then a else
   681   if a = b then a else
   703         HENSEL_lifting_up a b (nat d) (2 * (nat d) * LANDAU_MIGNOTTE_bound a b) 1)"
   682     HENSEL_lifting_up a b (nat d) (2 * (nat d) * LANDAU_MIGNOTTE_bound a b) 1)"
   704 by pat_completeness auto --"simp del: lcoeff_up.simps ?+ others?"
   683 by pat_completeness auto --"simp del: lcoeff_up.simps ?+ others?"
   705 termination by lexicographic_order (*works*)
   684 termination by lexicographic_order (*works*)
   706 
   685 
   707 value "gcd_up [-18, -15, -20, 12, 20, -13, 2] [8, 28, 22, -11, -14, 1, 2] = [-2, -1, 1]"
   686 value "gcd_up [-18, -15, -20, 12, 20, -13, 2] [8, 28, 22, -11, -14, 1, 2] = [-2, -1, 1]"
   708 (*     gcd    (-1 + x^2) (x + x^2) = (1 + x) *)
   687 (*     gcd    (-1 + x^2) (x + x^2) = (1 + x) *)
   709 value "gcd_up [-1, 0 ,1] [0, 1, 1] = [1, 1]"
   688 value "gcd_up [-1, 0 ,1] [0, 1, 1] = [1, 1]"
   710 
       
   711 primrec nth :: "'a list => nat => 'a" (infixl "!!" 100) where
       
   712 nth_Cons: "(x # xs) !! n = (case n of 0 \<Rightarrow> x | Suc k \<Rightarrow> xs !! k)"
       
   713 value "[1,2,3,4,5] ! 2"
       
   714 
       
   715 definition  mult_ups2 :: "unipoly \<Rightarrow> int \<Rightarrow> unipoly" (infixl "%*" 70) where
       
   716  "p %* m = List.map (op * m) p"
       
   717 
   689 
   718 (*
   690 (*
   719 print_configs
   691 print_configs
   720 declare [[simp_trace_depth_limit = 99]]
   692 declare [[simp_trace_depth_limit = 99]]
   721 declare [[simp_trace = true]]
   693 declare [[simp_trace = true]]