src/Tools/isac/Knowledge/Rational2.thy
author Walther Neuper <neuper@ist.tugraz.at>
Mon, 24 Sep 2012 09:07:38 +0200
changeset 42517 550bb4d75c43
parent 42429 e24d0af5d705
permissions -rwxr-xr-x
meeding dmeindl
meindl_diana@42078
     1
(* rationals, i.e. fractions of multivariate polynomials over the real field
neuper@42517
     2
   author: (c) Diana Meindl
meindl_diana@42078
     3
   Use is subject to license terms. 
meindl_diana@42078
     4
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
meindl_diana@42078
     5
        10        20        30        40        50        60        70        80         90      100
meindl_diana@42078
     6
*)
meindl_diana@42078
     7
neuper@42385
     8
theory Rational2 imports Complex_Main begin 
meindl_diana@42078
     9
neuper@42517
    10
chapter {* The Isabelle Theory *}
neuper@42429
    11
text {*
neuper@42517
    12
  Below we reference \cite{winkler96} by page. From this book we adopt the 
neuper@42517
    13
  algorithms as closely as possible. Isabelle coding standards \cite{TODO isarimpl}
neuper@42517
    14
  require to change the identifiers; further changes concern the transition from
neuper@42517
    15
  Winkler's imperative pseudocode to efficient functional code.
meindl_diana@42078
    16
neuper@42517
    17
  However, in test/../reational.sml there is an almost original version of the
neuper@42517
    18
  algorithms, including the identifiers; this version was the first one
neuper@42517
    19
  developed in this thesis, the version is kept for simple reference to 
neuper@42517
    20
  \cite{winkler96}.
neuper@42385
    21
*}
neuper@42385
    22
neuper@42517
    23
section {* Auxiliary Functions *}
neuper@42517
    24
ML {*
neuper@42517
    25
  type unipoly = int list;
neuper@42385
    26
*}
neuper@42429
    27
neuper@42517
    28
subsection {* modulo calculations etc. *}
neuper@42517
    29
ML {*
neuper@42517
    30
  (*The "inverse modulo" functions: "mod_inv 5 7 = 3" 
neuper@42517
    31
  because 5*3 mod 7 = 1, or more precisely 5^-1 mod 7 = 3.*)
neuper@42517
    32
  fun mod_inv r m =
neuper@42517
    33
    let
neuper@42517
    34
      fun modi (r, rold, m, rinv) =
neuper@42517
    35
        if rinv < m
neuper@42517
    36
        then
neuper@42517
    37
          if r mod m = 1
neuper@42517
    38
          then rinv
neuper@42517
    39
          else modi (rold * (rinv + 1), rold, m, rinv + 1)
neuper@42517
    40
        else 0
neuper@42517
    41
    in modi (r, r, m, 1) end
neuper@42429
    42
neuper@42517
    43
  fun leading_coeff (uvp: unipoly) =
neuper@42517
    44
    if nth uvp (length uvp - 1) <> 0
neuper@42517
    45
    then nth uvp (length uvp - 1)
neuper@42517
    46
    else leading_coeff (nth_drop (length uvp - 1) uvp);
neuper@42517
    47
  
neuper@42517
    48
  fun deg (uvp:unipoly) = 
neuper@42517
    49
    if nth uvp (length uvp - 1) <> 0
neuper@42517
    50
    then length uvp - 1
neuper@42517
    51
    else deg (nth_drop (length uvp - 1) uvp)
neuper@42517
    52
neuper@42517
    53
  (* gcd is: greatest common divisor *)
neuper@42517
    54
  fun gcd a b = if b = 0 then a else gcd b (a mod b);
neuper@42517
    55
neuper@42517
    56
  (* Chinese remainder: given r1, r2, m1, m2 
neuper@42517
    57
     find r such that r = r1 mod m1 and r = r2 mod m2 *)
neuper@42517
    58
  fun CRA_2 (r1: int, m1: int, r2: int, m2: int) =
neuper@42517
    59
   (r1 mod m1) + ((r2 - (r1 mod m1)) * (mod_inv m1 m2) mod m2) * m1
neuper@42517
    60
*}
neuper@42517
    61
neuper@42517
    62
subsection {* primes *}
neuper@42517
    63
ML{*
neuper@42517
    64
  (* is n divisble by some number in primelist ? *)
neuper@42517
    65
  fun is_prime primelist n = 
neuper@42517
    66
    if length primelist > 0
neuper@42517
    67
    then 
neuper@42517
    68
      if (n mod (nth primelist 0)) = 0
neuper@42517
    69
      then false
neuper@42517
    70
      else is_prime (nth_drop 0 primelist) n
neuper@42517
    71
    else true
neuper@42517
    72
neuper@42517
    73
  (* sieve of erathostenes *)
neuper@42517
    74
  fun primeList p =
neuper@42517
    75
    let 
neuper@42517
    76
    fun make_primelist list last p =
neuper@42517
    77
      if (nth list (length list - 1)) < p 
neuper@42517
    78
      then
neuper@42517
    79
        if ( is_prime list (last + 2)) 
neuper@42517
    80
        then make_primelist (list @ [(last + 2)]) (last + 2) p
neuper@42517
    81
        else make_primelist  list (last + 2) p
neuper@42517
    82
      else list
neuper@42517
    83
    in
neuper@42517
    84
      if p < 3
neuper@42517
    85
      then [2]
neuper@42517
    86
      else make_primelist [2,3] 3 p
neuper@42517
    87
    end
neuper@42517
    88
*}
neuper@42517
    89
text {*
neuper@42517
    90
fun primeList' 2 =[2,3]|
neuper@42517
    91
 primeList' x= if x<2 then [2] else
neuper@42517
    92
  let 
neuper@42517
    93
  fun make_primelist list last x =
neuper@42517
    94
    if (nth list (length list -1)) < x 
neuper@42517
    95
    then
neuper@42517
    96
      if ( is_prime list (last + 2)) 
neuper@42517
    97
      then make_primelist (list @ [(last + 2)]) (last + 2) x
neuper@42517
    98
      else make_primelist  list (last + 2) x
neuper@42517
    99
    else list
neuper@42517
   100
  in
neuper@42517
   101
     make_primelist [2,3] 3 x end
neuper@42517
   102
*}
neuper@42517
   103
neuper@42517
   104
text {*
neuper@42517
   105
	To find now a new prime number not dividing a number d, we find the next prime number higher than the old one with (primeList old+1) and test again if it divide our d. If not we found a new prime not dividing d, else we repeat it with the next prime.\\
neuper@42517
   106
*}
neuper@42517
   107
neuper@42517
   108
ML {*
neuper@42517
   109
fun find_next_prime_not_divide a p  = 
neuper@42517
   110
  let
neuper@42517
   111
    val next = nth (primeList (p+1)) (length(primeList(p+1))-1) ;
neuper@42517
   112
  in
neuper@42517
   113
    if a mod next  <> 0
neuper@42517
   114
      then next
neuper@42517
   115
    else find_next_prime_not_divide a next
neuper@42517
   116
end
neuper@42517
   117
*}
neuper@42517
   118
neuper@42517
   119
text{*
neuper@42517
   120
find_next_prime_not_divide 12 2;
neuper@42517
   121
find_next_prime_not_divide 15 2;
neuper@42517
   122
find_next_prime_not_divide 90 7;
neuper@42517
   123
find_next_prime_not_divide 90 1;
neuper@42517
   124
find_next_prime_not_divide 2 7;
neuper@42517
   125
primeList 15;
neuper@42517
   126
primeList 1;
neuper@42517
   127
primeList 8;
neuper@42517
   128
primeList 2;
neuper@42517
   129
primeList 0;
neuper@42517
   130
primeList' 15;
neuper@42517
   131
primeList' 1;
neuper@42517
   132
primeList' 8;
neuper@42517
   133
primeList' 2;
neuper@42517
   134
*}
neuper@42517
   135
neuper@42517
   136
ML {*
neuper@42517
   137
is_prime (primeList 7) 9;
neuper@42517
   138
*}
neuper@42517
   139
neuper@42517
   140
ML {*
neuper@42517
   141
fun landau_mignotte_bound a b = 2603;
neuper@42517
   142
(* 2^min(m,n)gcd(leading_coeff(a),leading_coeff(b)) min(1/(abs leading_coeff(a)) sqrt(sum(a_^2), 1/(abs leading_coeff(b)) sqrt(sum(b_i^2))  *)
neuper@42517
   143
*}
neuper@42517
   144
neuper@42517
   145
ML {*
neuper@42517
   146
infix poly_mod
neuper@42517
   147
fun uvp poly_mod m =
neuper@42517
   148
  let fun poly_mod' uvp m n =
neuper@42517
   149
    if n<length (uvp)
neuper@42517
   150
    then poly_mod' ((nth_drop 0 uvp)@[(nth uvp 0)mod m]) m ( n + 1 )
neuper@42517
   151
    else uvp (*end of poly_mod'*)
neuper@42517
   152
  in
neuper@42517
   153
    poly_mod' uvp m 0 end (*poly_mod*)
neuper@42517
   154
*}                 
neuper@42517
   155
neuper@42517
   156
ML {*
neuper@42517
   157
infix %*
neuper@42517
   158
fun (a:unipoly) %* (b:int) =
neuper@42517
   159
  let fun mul a b = a*b;
neuper@42517
   160
  in map2 mul a (replicate (length(a)) b)end
neuper@42517
   161
neuper@42517
   162
infix %/
neuper@42517
   163
fun (poly:unipoly) %/ (b:int) = (* =quotient*)
neuper@42517
   164
  let fun division poly b = poly div b;
neuper@42517
   165
  in map2 division poly (replicate (length(poly)) b) end
neuper@42517
   166
*}                 
neuper@42517
   167
neuper@42517
   168
                 
neuper@42517
   169
neuper@42517
   170
ML {*
neuper@42517
   171
neuper@42517
   172
infix %-%
neuper@42517
   173
fun a %-% b =
neuper@42517
   174
  let fun minus a b = a-b;
neuper@42517
   175
  in  map2 minus a b end
neuper@42517
   176
neuper@42517
   177
infix %-
neuper@42517
   178
fun p %- b =
neuper@42517
   179
  let fun minus p b = p-b;
neuper@42517
   180
in map2 minus p (replicate (length(p)) b) end
neuper@42517
   181
neuper@42517
   182
infix %+
neuper@42517
   183
fun a %+ b =
neuper@42517
   184
  let fun plus a b = a+b;
neuper@42517
   185
  in  map2 plus a b end
neuper@42517
   186
*}
neuper@42429
   187
neuper@42429
   188
neuper@42385
   189
ML{*
neuper@42517
   190
fun CRA_2_poly (ma, mb) (r1, r2) = 
neuper@42517
   191
let 
neuper@42517
   192
 fun CRA_2' (ma, mb) (r1, r2) = CRA_2 (r1, ma,r2, mb)
neuper@42517
   193
in  map (CRA_2' (ma, mb)) (r1 ~~ r2)end
neuper@42517
   194
*}
neuper@42517
   195
neuper@42517
   196
ML {*(*a/b mod m*)
neuper@42517
   197
fun mod_div (a:int) (b:int) (m:int) =
neuper@42517
   198
  a*(mod_inv b m) mod m
neuper@42517
   199
neuper@42517
   200
fun  poly_mod_div (a:unipoly) (b:int)  m =
neuper@42517
   201
  let fun lm_div a b c m i =
neuper@42517
   202
    if length c = length a
neuper@42517
   203
    then c
neuper@42517
   204
    else lm_div a b (c @ [ mod_div (nth a i) b m ]) m (i+1)
neuper@42517
   205
  in  lm_div a b [] m 0 end
neuper@42517
   206
*}
neuper@42517
   207
neuper@42517
   208
ML {*
neuper@42517
   209
fun mod_mult a b m = (a * b) mod m;
neuper@42517
   210
fun mod_minus a b m = (a - b) mod m;
neuper@42517
   211
fun mod_plus a b m = (a + b) mod m;
neuper@42385
   212
*}
neuper@42385
   213
neuper@42385
   214
ML{*
neuper@42517
   215
fun lc_of_list_not_0 [] = [](* and delete leading_coeff=0*)
neuper@42517
   216
| lc_of_list_not_0 (uvp:unipoly) = 
neuper@42517
   217
  if nth uvp (length uvp -1) =0
neuper@42517
   218
  then lc_of_list_not_0 (nth_drop (length uvp-1) uvp)
neuper@42517
   219
  else 
neuper@42517
   220
    if nth uvp 0 = 0
neuper@42517
   221
    then  lc_of_list_not_0 (nth_drop 0 uvp)
neuper@42517
   222
    else uvp;
neuper@42429
   223
*}
neuper@42429
   224
neuper@42517
   225
ML {* (* if poly2|poly1 *)
neuper@42517
   226
infix %/%
neuper@42517
   227
fun [a:int] %/% [b:int] = 
neuper@42517
   228
  if b<a andalso a mod b = 0
neuper@42517
   229
  then true
neuper@42517
   230
  else false
neuper@42517
   231
| (poly1:unipoly) %/% (poly2:unipoly) = 
neuper@42517
   232
  let 
neuper@42517
   233
  val b = (replicate (length poly1 - length(lc_of_list_not_0 poly2)) 0) @ lc_of_list_not_0 poly2 ;
neuper@42517
   234
  val c = leading_coeff poly1 div leading_coeff b;
neuper@42517
   235
  val rest = lc_of_list_not_0 (poly1 %-% (b %* c));
neuper@42517
   236
  in 
neuper@42517
   237
    if rest = []
neuper@42517
   238
    then true
neuper@42517
   239
    else
neuper@42517
   240
      if c<>0 andalso length rest >= length poly2
neuper@42517
   241
      then rest %/% poly2 
neuper@42517
   242
      else false
neuper@42517
   243
  end
neuper@42517
   244
*}
neuper@42517
   245
neuper@42517
   246
neuper@42517
   247
ML {*
neuper@42517
   248
fun mod_poly_gcd (upoly1:unipoly, upoly2:unipoly, m:int) =
neuper@42517
   249
  let 
neuper@42517
   250
    val moda = upoly1 poly_mod m
neuper@42517
   251
    val modb = (replicate (length upoly1 - length(lc_of_list_not_0 upoly2)) 0)
neuper@42517
   252
                @ (lc_of_list_not_0 upoly2 poly_mod m) ;
neuper@42517
   253
    val c =  mod_div (leading_coeff moda) (leading_coeff modb) m
neuper@42517
   254
    val rest = lc_of_list_not_0 ((moda %-% (modb %*  c)) poly_mod m)
neuper@42517
   255
  in 
neuper@42517
   256
    if rest = []
neuper@42517
   257
    then [upoly1, [0] ]
neuper@42517
   258
    else
neuper@42517
   259
      if length rest < length upoly2
neuper@42517
   260
      then mod_poly_gcd (upoly2, rest, m) (*[ rest,[c]@d]*)
neuper@42517
   261
      else mod_poly_gcd (rest, upoly2, m)
neuper@42517
   262
  end
neuper@42517
   263
*}
neuper@42517
   264
neuper@42517
   265
ML {*
neuper@42517
   266
fun  mod_polynom_gcd (poly1:unipoly) (poly2:unipoly) (m:int) =
neuper@42517
   267
  let 
neuper@42517
   268
    val moda = poly1 poly_mod m;
neuper@42517
   269
    val modb = (replicate (length poly1 - length poly2) 0) @ (poly2 poly_mod m) ;
neuper@42517
   270
    val c =  mod_div (leading_coeff moda) (leading_coeff modb) m;
neuper@42517
   271
    val rest = lc_of_list_not_0 (moda %-% (modb %* c) poly_mod m) poly_mod m;
neuper@42517
   272
  in (* nth_drop ( length ( upoly1 ) - 1 )*)
neuper@42517
   273
    if rest = []
neuper@42517
   274
    then [poly2, [0]]
neuper@42517
   275
    else
neuper@42517
   276
      if length rest < length poly2
neuper@42517
   277
      then [rest]
neuper@42517
   278
      else mod_poly_gcd (rest, poly2 ,  m)
neuper@42517
   279
  end
neuper@42517
   280
*}
neuper@42429
   281
neuper@42429
   282
ML{*
neuper@42517
   283
fun normirt_polynom (poly1:unipoly) (m:int) =
neuper@42517
   284
  let
neuper@42517
   285
    val poly1 = lc_of_list_not_0 poly1
neuper@42517
   286
    val lc_a=leading_coeff poly1;
neuper@42517
   287
    fun normirt poly1 b m lc_a i =
neuper@42517
   288
      if i=0
neuper@42517
   289
      then [mod_div (nth poly1 i) lc_a m]@b
neuper@42517
   290
      else normirt poly1 ( [mod_div(nth poly1 i) lc_a m]@b) m lc_a (i-1) ;
neuper@42517
   291
  in 
neuper@42517
   292
    if length(poly1)=0
neuper@42517
   293
    then poly1
neuper@42517
   294
    else normirt poly1  [] m lc_a (length(poly1)-1)
neuper@42517
   295
end
neuper@42429
   296
*}
neuper@42429
   297
neuper@42517
   298
ML{*
neuper@42517
   299
fun  mod_gcd_p (poly1:unipoly) (poly2:unipoly) (p:int) =
neuper@42517
   300
  let
neuper@42517
   301
    val rest = mod_polynom_gcd poly1 poly2 p;
neuper@42517
   302
  in
neuper@42517
   303
    if length rest = 2
neuper@42517
   304
    then normirt_polynom (nth rest 0) p
neuper@42517
   305
    else   mod_gcd_p  poly2 (nth rest 0) p
neuper@42517
   306
end
neuper@42517
   307
*}
neuper@42517
   308
neuper@42429
   309
neuper@42429
   310
ML{*
neuper@42517
   311
fun gcd_n (list:int list) =
neuper@42517
   312
  if length list = 2
neuper@42517
   313
  then gcd (nth list 0)(nth list 1)
neuper@42517
   314
  else gcd_n ([gcd (nth list 0)(nth list 1)]@(nth_drop 0 (nth_drop 0 list)))
neuper@42517
   315
*}
neuper@42517
   316
neuper@42517
   317
ML {*
neuper@42517
   318
fun pp (poly1:unipoly) = 
neuper@42517
   319
  if (poly1 poly_mod (gcd_n poly1)) = (replicate (length (poly1)) 0)
neuper@42517
   320
  then  poly1 %/ (gcd_n poly1)
neuper@42517
   321
  else poly1
neuper@42429
   322
neuper@42429
   323
*}
neuper@42429
   324
neuper@42517
   325
ML {* 
neuper@42517
   326
pp [4,8,2,6];
neuper@42517
   327
*}
neuper@42517
   328
neuper@42517
   329
ML {* 
neuper@42517
   330
fun poly_centr (poly:unipoly) (m:int) =
neuper@42517
   331
  let
neuper@42517
   332
    fun midle m =
neuper@42517
   333
      let val mid = m div 2
neuper@42517
   334
      in 
neuper@42517
   335
        if m mod mid = 0
neuper@42517
   336
        then  mid
neuper@42517
   337
        else  mid+1
neuper@42517
   338
      end
neuper@42517
   339
    fun centr a m mid =
neuper@42517
   340
      if a > mid
neuper@42517
   341
      then a - m
neuper@42517
   342
      else a
neuper@42517
   343
    fun polyCentr poly poly' m mid counter =
neuper@42517
   344
      if length(poly) > counter
neuper@42517
   345
      then polyCentr poly (poly' @ [centr (nth poly counter) m mid]) m mid (counter+1)
neuper@42517
   346
      else (poly':unipoly)
neuper@42517
   347
  in polyCentr poly [] m (midle m) 0
neuper@42517
   348
end
neuper@42517
   349
*}
neuper@42517
   350
neuper@42517
   351
neuper@42517
   352
subsection {* GCD_MOD Algorgithmus *}
neuper@42517
   353
neuper@42517
   354
ML {*
neuper@42517
   355
 fun GCD_MOD a b =
neuper@42517
   356
   let
neuper@42517
   357
(*1*)val d = gcd (leading_coeff a) (leading_coeff b);
neuper@42517
   358
     val M  = 2*d*landau_mignotte_bound a b;
neuper@42517
   359
     fun GOTO2 a b d M p =   (*==============================*)
neuper@42517
   360
       let 
neuper@42517
   361
(*2*)    val p = find_next_prime_not_divide d p
neuper@42517
   362
         val c_p = normirt_polynom ( mod_gcd_p a b p) p
neuper@42517
   363
         val g_p = poly_centr((c_p %* (d mod p)) poly_mod p) p
neuper@42517
   364
         fun GOTO3 a b d M p g_p =  (*~~~~~~~~~~~~~~~~~~~~~~*)
neuper@42517
   365
(*3*)      if (deg g_p) = 0
neuper@42517
   366
           then  [1]
neuper@42517
   367
           else
neuper@42517
   368
             let
neuper@42517
   369
               val P = p
neuper@42517
   370
               val g = g_p
neuper@42517
   371
               fun WHILE a b d M P g = (*------------------*)
neuper@42517
   372
(*4*)            if P > M 
neuper@42517
   373
                 then g
neuper@42517
   374
                 else
neuper@42517
   375
                   let 
neuper@42517
   376
                     val p = find_next_prime_not_divide d p
neuper@42517
   377
                     val c_p = normirt_polynom ( mod_gcd_p a b p) p
neuper@42517
   378
                     val g_p = poly_centr((c_p %* (d mod p)) poly_mod p) p
neuper@42517
   379
                   in
neuper@42517
   380
                     if deg g_p < deg g
neuper@42517
   381
                     then GOTO3 a b d M p g_p
neuper@42517
   382
                     else
neuper@42517
   383
                       if deg g_p = deg g
neuper@42517
   384
                       then 
neuper@42517
   385
                         let 
neuper@42517
   386
                           val g = CRA_2_poly (P,p)(g,g_p)
neuper@42517
   387
                           val P = P*p
neuper@42517
   388
                           val g = poly_centr(g poly_mod P)P
neuper@42517
   389
                         in WHILE a b d M P g end
neuper@42517
   390
                       else WHILE a b d M P g
neuper@42517
   391
               end (*----------------------------------*)
neuper@42517
   392
              
neuper@42517
   393
               
neuper@42517
   394
               val g = WHILE a b d M P g (* << 1.Mal -----*)
neuper@42517
   395
             in g end (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
neuper@42517
   396
         
neuper@42517
   397
          val g = GOTO3 a b d M p g_p (* << 1.Mal ~~~~~~~~~~*)
neuper@42517
   398
(*5*)     val g = pp g
neuper@42517
   399
        in
neuper@42517
   400
          if (a %/% g) andalso (b %/% g)
neuper@42517
   401
          then  g
neuper@42517
   402
          else GOTO2 a b d M p
neuper@42517
   403
        end (*==============================================*)
neuper@42517
   404
      
neuper@42517
   405
neuper@42517
   406
     val  g = GOTO2 a b d (*p*)1 M (* << 1. Mal  =============*)
neuper@42517
   407
   in g end;
neuper@42517
   408
*}
neuper@42429
   409
neuper@42429
   410
neuper@42429
   411
ML{*
neuper@42517
   412
 fun GCD_MOD' a b =
neuper@42517
   413
   let
neuper@42517
   414
(*1*)val d = gcd (leading_coeff a) (leading_coeff b);
neuper@42517
   415
     val M  = 2*d*landau_mignotte_bound a b;
neuper@42517
   416
     fun GOTO2 a b d M p =   (*==============================*)
neuper@42517
   417
       let 
neuper@42517
   418
(*2*)    val p = find_next_prime_not_divide d p
neuper@42517
   419
         val c_p = normirt_polynom ( mod_gcd_p a b p) p
neuper@42517
   420
         val g_p = poly_centr((c_p %* (d mod p)) poly_mod p) p
neuper@42517
   421
         fun WHILE a b d M P p g = (*------------------*)
neuper@42517
   422
(*4*)      if P > M 
neuper@42517
   423
           then 
neuper@42517
   424
             if a %/% (pp g) andalso b %/% (pp g)
neuper@42517
   425
              then pp g
neuper@42517
   426
              else GOTO2 a b d M p
neuper@42517
   427
           else
neuper@42517
   428
             let 
neuper@42517
   429
               val p = find_next_prime_not_divide d p
neuper@42517
   430
               val c_p = normirt_polynom (mod_gcd_p a b p) p
neuper@42517
   431
               val g_p = poly_centr((c_p %* (d mod p)) poly_mod p) p
neuper@42517
   432
             in
neuper@42517
   433
              if deg g_p < deg g
neuper@42517
   434
               then 
neuper@42517
   435
(*3*)            if deg g_p = 0
neuper@42517
   436
                 then [1]
neuper@42517
   437
                 else WHILE a b d M p p g_p
neuper@42517
   438
               else
neuper@42517
   439
                 if deg g_p = deg g
neuper@42517
   440
                 then 
neuper@42517
   441
                   WHILE a b d M (P*p) p ( poly_centr(CRA_2_poly (P,p)(g,g_p))(P*p)) 
neuper@42517
   442
                 else WHILE a b d M P p g
neuper@42517
   443
         end (*--------------WHILE--------------------*)
neuper@42517
   444
       in 
neuper@42517
   445
(*3*)      if deg g_p = 0 then [1]
neuper@42517
   446
           else WHILE a b d M p p g_p
neuper@42517
   447
    end (*========================GOTO2======================*)
neuper@42517
   448
in  GOTO2 a b d (*p*)1 M end
neuper@42385
   449
*}
neuper@42385
   450
neuper@42517
   451
subsection {* GCD_MODm Algorgithmus *}
neuper@42517
   452
neuper@42517
   453
ML {*
neuper@42517
   454
type monom = (int * int list);
neuper@42517
   455
type multipoly = monom list;
neuper@42517
   456
val mpoly1 = [(~3,[0,2]),(3,[1,0]),(1,[0,5]),(~6,[1,1]),(~1,[1,3]),(2,[1,4]),(1,[2,3]),(~1,[3,1]),(2,[3,2])];
neuper@42517
   457
val mpoly2 = [(2,[3,1]),(~1,[3,0]),(~1,[2,2]),(1,[2,1]),(~1,[1,3]),(4,[1,1]),(~2,[1,0]),(2,[0,2])];
neuper@42517
   458
val (test:monom) =(22,[5,6,7]);
neuper@42517
   459
*}
neuper@42517
   460
neuper@42517
   461
neuper@42517
   462
ML {*
neuper@42517
   463
fun get_coef ((coef,var):monom) = coef;
neuper@42517
   464
fun get_varlist ((coef,var):monom) = var;
neuper@42517
   465
fun get_coeflist (poly:multipoly) = 
neuper@42517
   466
  let 
neuper@42517
   467
    fun get_coeflist' (poly:multipoly) list = 
neuper@42517
   468
      if poly = []
neuper@42517
   469
       then 
neuper@42517
   470
        list
neuper@42517
   471
       else          
neuper@42517
   472
         get_coeflist' (nth_drop 0 poly) (list @ [get_coef(nth poly 0)])
neuper@42517
   473
  in 
neuper@42517
   474
    get_coeflist' poly []
neuper@42517
   475
end
neuper@42517
   476
  
neuper@42517
   477
(* Eine Funktion für verschiedene Typen? *)
neuper@42517
   478
fun lc_mv (poly:multipoly) = 
neuper@42517
   479
  if get_coef (nth mpoly1 (length mpoly1 - 1)) <> 0
neuper@42517
   480
  then get_coef (nth poly (length poly-1))
neuper@42517
   481
  else lc_mv (nth_drop (length poly-1) poly);
neuper@42517
   482
fun deg_mv (mvp:multipoly) = 
neuper@42517
   483
  if get_coef (nth mvp (length mvp-1)) <> 0
neuper@42517
   484
  then nth (get_varlist (nth mvp (length mvp-1))) 0
neuper@42517
   485
  else  deg_mv (nth_drop (length mvp-1) mvp)
neuper@42517
   486
fun greater_deg (monom1:monom) (monom2:monom)=
neuper@42517
   487
  if  deg_mv [monom1] >  deg_mv [monom2]
neuper@42517
   488
    then 1
neuper@42517
   489
    else if  deg_mv [monom1] <  deg_mv [monom2]
neuper@42517
   490
      then 2
neuper@42517
   491
      else if length (get_varlist monom1) >0
neuper@42517
   492
        then
neuper@42517
   493
          greater_deg (1,(nth_drop 0 (get_varlist monom1))) (1,(nth_drop 0 (get_varlist monom2)))
neuper@42517
   494
        else 0
neuper@42517
   495
        
neuper@42385
   496
*}
neuper@42429
   497
neuper@42429
   498
ML {*
neuper@42517
   499
get_coef test;
neuper@42517
   500
get_varlist test;
neuper@42517
   501
val t = [[1,2,4,5],[4,5,6,7]];
neuper@42517
   502
nth (nth t 1) 1;
neuper@42517
   503
lc_mv mpoly1;
neuper@42517
   504
 deg_mv mpoly1;
neuper@42517
   505
 deg_mv [(5,[4,5,6])];
neuper@42517
   506
get_coeflist mpoly1;
neuper@42517
   507
val monom =(5,[4,5,6]) ;
neuper@42517
   508
 deg_mv [monom];
neuper@42517
   509
get_varlist monom;
neuper@42517
   510
 [(1,(nth_drop 0 (get_varlist monom)))];
neuper@42517
   511
greater_deg (5,[4,5,6]) (5,[4,5,5]);
neuper@42385
   512
*}
neuper@42429
   513
neuper@42429
   514
ML {*
neuper@42517
   515
infix %%/
neuper@42517
   516
fun (poly:multipoly) %%/ (b:int) = (* =quotient*)
neuper@42517
   517
  let fun division monom b = ((get_coef monom div b),get_varlist monom);
neuper@42517
   518
  in map2 division poly (replicate (length(poly)) b) end
neuper@42429
   519
*}
neuper@42429
   520
neuper@42429
   521
ML {*
neuper@42517
   522
mpoly1;
neuper@42517
   523
mpoly1 %%/ 2;
neuper@42517
   524
~11 div 2;
neuper@42517
   525
11 div 2;
neuper@42517
   526
[3,4,~4,~3,~1] %/ 2;
neuper@42429
   527
*}
neuper@42429
   528
neuper@42429
   529
ML {*
neuper@42517
   530
fun cont (poly1:unipoly) = gcd_n poly1
neuper@42517
   531
fun cont' (poly:multipoly) = gcd_n (get_coeflist poly)
neuper@42517
   532
*}
neuper@42517
   533
neuper@42517
   534
neuper@42517
   535
ML {*
neuper@42517
   536
[3,4,5] = [3,4,5];
neuper@42517
   537
[3,4,5]=[5,4,3];
neuper@42517
   538
[3,4,5] @ [get_coef (nth mpoly1 (length mpoly1 - 1))
neuper@42517
   539
                                - get_coef (nth mpoly2 (length mpoly2 - 1))];
neuper@42517
   540
mpoly1 = [] orelse mpoly2 =[];
neuper@42517
   541
get_varlist (nth mpoly1 (length mpoly1 - 1)) = get_varlist (nth mpoly2 (length mpoly2 - 1))
neuper@42429
   542
*}
neuper@42429
   543
neuper@42429
   544
ML {*
neuper@42517
   545
infix %%-
neuper@42517
   546
fun (mpoly1:multipoly) %%- (mpoly2:multipoly) = 
neuper@42517
   547
  let 
neuper@42517
   548
    fun min' (mpoly1:multipoly) (mpoly2:multipoly) (result:multipoly) = 
neuper@42517
   549
      if mpoly1 = [] andalso mpoly2 =[] 
neuper@42517
   550
        then result
neuper@42517
   551
        else if mpoly1 = []
neuper@42517
   552
          then let
neuper@42517
   553
            val result = [(0 - get_coef (nth mpoly2 (length mpoly2 - 1)),
neuper@42517
   554
                               get_varlist (nth mpoly2 (length mpoly2 - 1)))] @ result
neuper@42517
   555
            in 
neuper@42517
   556
               min'  mpoly1 (nth_drop (length mpoly2 - 1) mpoly2) result
neuper@42517
   557
            end
neuper@42517
   558
          else if mpoly2 = []
neuper@42517
   559
            then 
neuper@42517
   560
               mpoly1 @ result
neuper@42517
   561
            
neuper@42517
   562
       else 
neuper@42517
   563
         if get_varlist (nth mpoly1 (length mpoly1 - 1)) = get_varlist (nth mpoly2 (length mpoly2 - 1))
neuper@42517
   564
           then
neuper@42517
   565
            let
neuper@42517
   566
             val result =  [(get_coef (nth mpoly1 (length mpoly1 - 1))
neuper@42517
   567
                             - get_coef (nth mpoly2 (length mpoly2 - 1)),
neuper@42517
   568
                           get_varlist (nth mpoly1 (length mpoly1 - 1)))] @ result
neuper@42517
   569
            in 
neuper@42517
   570
              min' (nth_drop (length mpoly1 - 1) mpoly1) (nth_drop (length mpoly2 - 1) mpoly2) result
neuper@42517
   571
            end
neuper@42517
   572
         else
neuper@42517
   573
           if greater_deg (nth mpoly1 (length mpoly1 - 1)) (nth mpoly2 (length mpoly2 - 1)) = 1 
neuper@42517
   574
             then 
neuper@42517
   575
               min' (nth_drop (length mpoly1 - 1) mpoly1) mpoly2 ( [nth mpoly1 (length mpoly1 - 1)] @ result)
neuper@42517
   576
             else 
neuper@42517
   577
               let
neuper@42517
   578
                 val result =  [(0 - get_coef (nth mpoly2 (length mpoly2 - 1)),
neuper@42517
   579
                               get_varlist (nth mpoly2 (length mpoly2 - 1)))]@ result
neuper@42517
   580
               in 
neuper@42517
   581
                  min'  mpoly1 (nth_drop (length mpoly2 - 1) mpoly2) result
neuper@42517
   582
            end
neuper@42517
   583
    in 
neuper@42517
   584
      min' mpoly1 mpoly2 []
neuper@42517
   585
end
neuper@42517
   586
*}
neuper@42517
   587
neuper@42517
   588
ML {*
neuper@42517
   589
[(~6,[1,1]),(~1,[1,3])]%%-[(~4,[1,1]),(3,[1,3])];
neuper@42517
   590
[(~6,[1,1]),(~1,[1,5])]%%-[(~4,[1,1]),(3,[2,3])];
neuper@42517
   591
*}
neuper@42517
   592
neuper@42517
   593
ML {*
neuper@42517
   594
*}
neuper@42517
   595
neuper@42517
   596
ML {*
neuper@42517
   597
*}
neuper@42517
   598
neuper@42517
   599
ML {*
neuper@42517
   600
*}
neuper@42517
   601
neuper@42517
   602
ML {*
neuper@42517
   603
*}
neuper@42517
   604
neuper@42517
   605
ML {*
neuper@42517
   606
*}
neuper@42517
   607
neuper@42517
   608
ML {*
neuper@42517
   609
*}
neuper@42517
   610
neuper@42517
   611
ML {*
neuper@42517
   612
neuper@42517
   613
*}
neuper@42517
   614
text {*
neuper@42517
   615
neuper@42517
   616
fun GCD_MODm a b n s =
neuper@42517
   617
(*0*)  if s = 0
neuper@42517
   618
    then g = (gcd (cont a) (cont b)) %* (GCD_MOD pp(a) pp(b))
neuper@42517
   619
    else 
neuper@42517
   620
      let
neuper@42517
   621
(*1*)   val M = 1 + Int.min (DEG_X a, DEG_X b);
neuper@42517
   622
(*2*)     fun GOTO2 a b n s x M =
neuper@42517
   623
              let
neuper@42517
   624
                val r = AN_Integer_DEG_H;
neuper@42517
   625
                val g_r = GCD_MODm (REDUCED a)(REDUCED b) n (s-1)
neuper@42517
   626
(*3*)           fun GOTO3 a b n s x M g_r r=
neuper@42517
   627
                  let
neuper@42517
   628
                    val m = 1;
neuper@42517
   629
                    val g = g_r
neuper@42517
   630
                    fun WHILE a b n s x M m r =
neuper@42517
   631
                      if m > M
neuper@42517
   632
                        then 
neuper@42517
   633
                         if g TEILT a andalso g TEILT a
neuper@42517
   634
                          then  g
neuper@42517
   635
                          else GOTO2 a b n s x M
neuper@42517
   636
                        else
neuper@42517
   637
                        let
neuper@42517
   638
                        val r = NEW_INTEGER;
neuper@42517
   639
                        val g_r = GCD_MODm (REDUCED a)(REDUCED b) n (s-1);
neuper@42517
   640
                        in
neuper@42517
   641
                          if DEG_XN g_r < DEG_XN g
neuper@42517
   642
                            then GOTO3 a b n s x M g_r r
neuper@42517
   643
                            else if DEG_XN g_r < DEG_XN g
neuper@42517
   644
                              then INCORPORATE g_r
neuper@42517
   645
                              else WHILE a b n s x M (m+1) r
neuper@42517
   646
                        end (* WHILE *)
neuper@42517
   647
                  in (* GOTO3*)
neuper@42517
   648
                    WHILE a b n s x M m r
neuper@42517
   649
                  end (*GOTO3*)
neuper@42517
   650
              in (* GOTO2*)
neuper@42517
   651
                GOTO3 a b n s x M g_r r
neuper@42517
   652
              end (*GOTO2*)
neuper@42517
   653
            in
neuper@42517
   654
             GOTO2 a b n s x M 
neuper@42517
   655
          end (*end 0*)
neuper@42385
   656
neuper@42385
   657
*}
neuper@42385
   658
neuper@42429
   659
ML {*
neuper@42517
   660
  val a = [~18, ~15, ~20, 12, 20, ~13, 2];
neuper@42517
   661
  val b = [8, 28, 22, ~11, ~14, 1, 2];
neuper@42517
   662
  if GCD_MOD a b = [~2, ~1, 1] then ()
neuper@42517
   663
  else error "GCD_MOD a b = [~2, ~1, 1]";
neuper@42429
   664
*}
neuper@42429
   665
neuper@42429
   666
end