src/Tools/isac/Knowledge/Rational.ML
author Walther Neuper <neuper@ist.tugraz.at>
Wed, 25 Aug 2010 16:20:07 +0200
branchisac-update-Isa09-2
changeset 37947 22235e4dbe5f
parent 37938 src/Tools/isac/IsacKnowledge/Rational.ML@f6164be9280d
permissions -rw-r--r--
renamed isac's directories and Build_Isac.thy

Scripts --> ProgLang
ME --> Interpret
IsacKnowledge --> Knowledge
neuper@37906
     1
(*.calculate in rationals: gcd, lcm, etc.
neuper@37906
     2
   (c) Stefan Karnel 2002
neuper@37906
     3
   Institute for Mathematics D and Institute for Software Technology, 
neuper@37906
     4
   TU-Graz SS 2002 
neuper@37906
     5
   Use is subject to license terms.
neuper@37906
     6
neuper@37947
     7
use"Knowledge/Rational.ML";
neuper@37906
     8
use"Rational.ML";
neuper@37906
     9
neuper@37906
    10
remove_thy"Rational";
neuper@37947
    11
use_thy"Knowledge/Isac";
neuper@37906
    12
****************************************************************.*)
neuper@37906
    13
neuper@37906
    14
(*.*****************************************************************
neuper@37906
    15
  Remark on notions in the documentation below:
neuper@37906
    16
    referring to the remark on 'polynomials' in Poly.sml we use
neuper@37906
    17
    [2] 'polynomial' normalform (Polynom)
neuper@37906
    18
    [3] 'expanded_term' normalform (Ausmultiplizierter Term),
neuper@37906
    19
    where normalform [2] is a special case of [3], i.e. [3] implies [2].
neuper@37906
    20
    Instead of 
neuper@37906
    21
      'fraction with numerator and nominator both in normalform [2]'
neuper@37906
    22
      'fraction with numerator and nominator both in normalform [3]' 
neuper@37906
    23
    we say: 
neuper@37906
    24
      'fraction in normalform [2]'
neuper@37906
    25
      'fraction in normalform [3]' 
neuper@37906
    26
    or
neuper@37906
    27
      'fraction [2]'
neuper@37906
    28
      'fraction [3]'.
neuper@37906
    29
    a 'simple fraction' is a term with '/' as outmost operator and
neuper@37906
    30
    numerator and nominator in normalform [2] or [3].
neuper@37906
    31
****************************************************************.*)
neuper@37906
    32
neuper@37906
    33
signature RATIONALI =
neuper@37906
    34
sig
neuper@37906
    35
  type mv_monom
neuper@37906
    36
  type mv_poly 
neuper@37906
    37
  val add_fraction_ : theory -> term -> (term * term list) option      
neuper@37906
    38
  val add_fraction_p_ : theory -> term -> (term * term list) option       
neuper@37906
    39
  val calculate_Rational : rls
neuper@37906
    40
  val calc_rat_erls:rls
neuper@37906
    41
  val cancel : rls
neuper@37906
    42
  val cancel_ : theory -> term -> (term * term list) option    
neuper@37906
    43
  val cancel_p : rls   
neuper@37906
    44
  val cancel_p_ : theory -> term -> (term * term list) option
neuper@37906
    45
  val common_nominator : rls              
neuper@37906
    46
  val common_nominator_ : theory -> term -> (term * term list) option
neuper@37906
    47
  val common_nominator_p : rls              
neuper@37906
    48
  val common_nominator_p_ : theory -> term -> (term * term list) option
neuper@37906
    49
  val eval_is_expanded : string -> 'a -> term -> theory -> 
neuper@37906
    50
			 (string * term) option                    
neuper@37906
    51
  val expanded2polynomial : term -> term option
neuper@37906
    52
  val factout_ : theory -> term -> (term * term list) option
neuper@37906
    53
  val factout_p_ : theory -> term -> (term * term list) option
neuper@37906
    54
  val is_expanded : term -> bool
neuper@37906
    55
  val is_polynomial : term -> bool
neuper@37906
    56
neuper@37906
    57
  val mv_gcd : (int * int list) list -> mv_poly -> mv_poly
neuper@37906
    58
  val mv_lcm : mv_poly -> mv_poly -> mv_poly
neuper@37906
    59
neuper@37906
    60
  val norm_expanded_rat_ : theory -> term -> (term * term list) option
neuper@37906
    61
(*WN0602.2.6.pull into struct !!!
neuper@37906
    62
  val norm_Rational : rls(*.normalizes an arbitrary rational term without
neuper@37906
    63
                           roots into a simple and canceled fraction
neuper@37906
    64
                           with normalform [2].*)
neuper@37906
    65
*)
neuper@37906
    66
(*val norm_rational_p : 19.10.02 missing FIXXXXXXXXXXXXME
neuper@37906
    67
      rls               (*.normalizes an rational term [2] without
neuper@37906
    68
                           roots into a simple and canceled fraction
neuper@37906
    69
                           with normalform [2].*)
neuper@37906
    70
*)
neuper@37906
    71
  val norm_rational_ : theory -> term -> (term * term list) option
neuper@37906
    72
  val polynomial2expanded : term -> term option
neuper@37906
    73
  val rational_erls : 
neuper@37906
    74
      rls             (*.evaluates an arbitrary rational term with numerals.*)
neuper@37906
    75
neuper@37906
    76
(*WN0210???SK: fehlen Funktionen, die exportiert werden sollen ? *)
neuper@37906
    77
end
neuper@37906
    78
neuper@37906
    79
(*.**************************************************************************
neuper@37906
    80
survey on the functions
neuper@37906
    81
~~~~~~~~~~~~~~~~~~~~~~~
neuper@37906
    82
 [2] 'polynomial'   :rls               | [3]'expanded_term':rls
neuper@37906
    83
--------------------:------------------+-------------------:-----------------
neuper@37906
    84
 factout_p_         :                  | factout_          :
neuper@37906
    85
 cancel_p_          :                  | cancel_           :
neuper@37906
    86
                    :cancel_p          |                   :cancel
neuper@37906
    87
--------------------:------------------+-------------------:-----------------
neuper@37906
    88
 common_nominator_p_:                  | common_nominator_ :
neuper@37906
    89
                    :common_nominator_p|                   :common_nominator
neuper@37906
    90
 add_fraction_p_    :                  | add_fraction_     :
neuper@37906
    91
--------------------:------------------+-------------------:-----------------
neuper@37906
    92
???SK                 :norm_rational_p   |                   :norm_rational
neuper@37906
    93
neuper@37906
    94
This survey shows only the principal functions for reuse, and the identifiers 
neuper@37906
    95
of the rls exported. The list below shows some more useful functions.
neuper@37906
    96
neuper@37906
    97
neuper@37906
    98
conversion from Isabelle-term to internal representation
neuper@37906
    99
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
neuper@37906
   100
neuper@37906
   101
... BITTE FORTSETZEN ...
neuper@37906
   102
neuper@37906
   103
polynomial2expanded = ...
neuper@37906
   104
expanded2polynomial = ...
neuper@37906
   105
neuper@37906
   106
remark: polynomial2expanded o expanded2polynomial = I, 
neuper@37906
   107
        where 'o' is function chaining, and 'I' is identity WN0210???SK
neuper@37906
   108
neuper@37906
   109
functions for greatest common divisor and canceling
neuper@37906
   110
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
neuper@37906
   111
mv_gcd
neuper@37906
   112
factout_
neuper@37906
   113
factout_p_
neuper@37906
   114
cancel_
neuper@37906
   115
cancel_p_
neuper@37906
   116
neuper@37906
   117
functions for least common multiple and addition of fractions
neuper@37906
   118
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
neuper@37906
   119
mv_lcm
neuper@37906
   120
common_nominator_
neuper@37906
   121
common_nominator_p_
neuper@37906
   122
add_fraction_       (*.add 2 or more fractions.*)
neuper@37906
   123
add_fraction_p_     (*.add 2 or more fractions.*)
neuper@37906
   124
neuper@37906
   125
functions for normalform of rationals
neuper@37906
   126
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
neuper@37906
   127
WN0210???SK interne Funktionen f"ur norm_rational: 
neuper@37906
   128
          schaffen diese SML-Funktionen wirklich ganz allgemeine Terme ?
neuper@37906
   129
neuper@37906
   130
norm_rational_
neuper@37906
   131
norm_expanded_rat_
neuper@37906
   132
neuper@37906
   133
**************************************************************************.*)
neuper@37906
   134
neuper@37906
   135
neuper@37906
   136
(*##*)
neuper@37906
   137
structure RationalI : RATIONALI = 
neuper@37906
   138
struct 
neuper@37906
   139
(*##*)
neuper@37906
   140
neuper@37930
   141
infix mem ins union; (*WN100819 updating to Isabelle2009-2*)
neuper@37930
   142
fun x mem [] = false
neuper@37930
   143
  | x mem (y :: ys) = x = y orelse x mem ys;
neuper@37930
   144
fun (x ins xs) = if x mem xs then xs else x :: xs;
neuper@37930
   145
fun xs union [] = xs
neuper@37930
   146
  | [] union ys = ys
neuper@37930
   147
  | (x :: xs) union ys = xs union (x ins ys);
neuper@37930
   148
neuper@37906
   149
(*. gcd of integers .*)
neuper@37906
   150
(* die gcd Funktion von Isabelle funktioniert nicht richtig !!! *)
neuper@37906
   151
fun gcd_int a b = if b=0 then a
neuper@37906
   152
		  else gcd_int b (a mod b);
neuper@37906
   153
neuper@37906
   154
(*. univariate polynomials (uv) .*)
neuper@37906
   155
(*. univariate polynomials are represented as a list of the coefficent in reverse maximum degree order .*)
neuper@37906
   156
(*. 5 * x^5 + 4 * x^3 + 2 * x^2 + x + 19 => [19,1,2,4,0,5] .*)
neuper@37906
   157
type uv_poly = int list;
neuper@37906
   158
neuper@37906
   159
(*. adds two uv polynomials .*)
neuper@37906
   160
fun uv_mod_add_poly ([]:uv_poly,p2:uv_poly) = p2:uv_poly 
neuper@37906
   161
  | uv_mod_add_poly (p1,[]) = p1
neuper@37906
   162
  | uv_mod_add_poly (x::p1,y::p2) = (x+y)::(uv_mod_add_poly(p1,p2)); 
neuper@37906
   163
neuper@37906
   164
(*. multiplies a uv polynomial with a skalar s .*)
neuper@37906
   165
fun uv_mod_smul_poly ([]:uv_poly,s:int) = []:uv_poly 
neuper@37906
   166
  | uv_mod_smul_poly (x::p,s) = (x*s)::(uv_mod_smul_poly(p,s)); 
neuper@37906
   167
neuper@37906
   168
(*. calculates the remainder of a polynomial divided by a skalar s .*)
neuper@37906
   169
fun uv_mod_rem_poly ([]:uv_poly,s) = []:uv_poly 
neuper@37906
   170
  | uv_mod_rem_poly (x::p,s) = (x mod s)::(uv_mod_smul_poly(p,s)); 
neuper@37906
   171
neuper@37906
   172
(*. calculates the degree of a uv polynomial .*)
neuper@37906
   173
fun uv_mod_deg ([]:uv_poly) = 0  
neuper@37906
   174
  | uv_mod_deg p = length(p)-1;
neuper@37906
   175
neuper@37906
   176
(*. calculates the remainder of x/p and represents it as value between -p/2 and p/2 .*)
neuper@37906
   177
fun uv_mod_mod2(x,p)=
neuper@37906
   178
    let
neuper@37906
   179
	val y=(x mod p);
neuper@37906
   180
    in
neuper@37906
   181
	if (y)>(p div 2) then (y)-p else 
neuper@37906
   182
	    (
neuper@37906
   183
	     if (y)<(~p div 2) then p+(y) else (y)
neuper@37906
   184
	     )
neuper@37906
   185
    end;
neuper@37906
   186
neuper@37906
   187
(*.calculates the remainder for each element of a integer list divided by p.*)  
neuper@37906
   188
fun uv_mod_list_modp [] p = [] 
neuper@37906
   189
  | uv_mod_list_modp (x::xs) p = (uv_mod_mod2(x,p))::(uv_mod_list_modp xs p);
neuper@37906
   190
neuper@37906
   191
(*. appends an integer at the end of a integer list .*)
neuper@37906
   192
fun uv_mod_null (p1:int list,0) = p1 
neuper@37906
   193
  | uv_mod_null (p1:int list,n1:int) = uv_mod_null(p1,n1-1) @ [0];
neuper@37906
   194
neuper@37906
   195
(*. uv polynomial division, result is (quotient, remainder) .*)
neuper@37906
   196
(*. only for uv_mod_divides .*)
neuper@37906
   197
(* FIXME: Division von x^9+x^5+1 durch x-1000 funktioniert nicht integer zu klein  *)
neuper@37906
   198
fun uv_mod_pdiv (p1:uv_poly) ([]:uv_poly) = raise error ("RATIONALS_UV_MOD_PDIV_EXCEPTION: division by zero")
neuper@37906
   199
  | uv_mod_pdiv p1 [x] = 
neuper@37906
   200
    let
neuper@37906
   201
	val xs=ref [];
neuper@37906
   202
    in
neuper@37906
   203
	if x<>0 then 
neuper@37906
   204
	    (
neuper@37906
   205
	     xs:=(uv_mod_rem_poly(p1,x));
neuper@37906
   206
	     while length(!xs)>0 andalso hd(!xs)=0 do xs:=tl(!xs)
neuper@37906
   207
	     )
neuper@37906
   208
	else raise error ("RATIONALS_UV_MOD_PDIV_EXCEPTION: division by zero");
neuper@37906
   209
	([]:uv_poly,!xs:uv_poly)
neuper@37906
   210
    end
neuper@37906
   211
  | uv_mod_pdiv p1 p2 =  
neuper@37906
   212
    let
neuper@37906
   213
	val n= uv_mod_deg(p2);
neuper@37906
   214
	val m= ref (uv_mod_deg(p1));
neuper@37906
   215
	val p1'=ref (rev(p1));
neuper@37906
   216
	val p2'=(rev(p2));
neuper@37906
   217
	val lc2=hd(p2');
neuper@37906
   218
	val q=ref [];
neuper@37906
   219
	val c=ref 0;
neuper@37906
   220
	val output=ref ([],[]);
neuper@37906
   221
    in
neuper@37906
   222
	(
neuper@37906
   223
	 if (!m)=0 orelse p2=[0] then raise error ("RATIONALS_UV_MOD_PDIV_EXCEPTION: Division by zero") 
neuper@37906
   224
	 else
neuper@37906
   225
	     (
neuper@37906
   226
	      if (!m)<n then 
neuper@37906
   227
		  (
neuper@37906
   228
		   output:=([0],p1) 
neuper@37906
   229
		   ) 
neuper@37906
   230
	      else
neuper@37906
   231
		  (
neuper@37906
   232
		   while (!m)>=n do
neuper@37906
   233
		       (
neuper@37906
   234
			c:=hd(!p1') div hd(p2');
neuper@37906
   235
			if !c<>0 then
neuper@37906
   236
			    (
neuper@37906
   237
			     p1':=uv_mod_add_poly(!p1',uv_mod_null(uv_mod_smul_poly(p2',~(!c)),!m-n));
neuper@37906
   238
			     while length(!p1')>0 andalso hd(!p1')=0  do p1':= tl(!p1');
neuper@37906
   239
			     m:=uv_mod_deg(!p1')
neuper@37906
   240
			     )
neuper@37906
   241
			else m:=0
neuper@37906
   242
			);
neuper@37906
   243
    		   output:=(rev(!q),rev(!p1'))
neuper@37906
   244
		   )
neuper@37906
   245
	      );
neuper@37906
   246
	     !output
neuper@37906
   247
	 )
neuper@37906
   248
    end;
neuper@37906
   249
neuper@37906
   250
(*. divides p1 by p2 in Zp .*)
neuper@37906
   251
fun uv_mod_pdivp (p1:uv_poly) (p2:uv_poly) p =  
neuper@37906
   252
    let
neuper@37906
   253
	val n=uv_mod_deg(p2);
neuper@37906
   254
	val m=ref (uv_mod_deg(uv_mod_list_modp p1 p));
neuper@37906
   255
	val p1'=ref (rev(p1));
neuper@37906
   256
	val p2'=(rev(uv_mod_list_modp p2 p));
neuper@37906
   257
	val lc2=hd(p2');
neuper@37906
   258
	val q=ref [];
neuper@37906
   259
	val c=ref 0;
neuper@37906
   260
	val output=ref ([],[]);
neuper@37906
   261
    in
neuper@37906
   262
	(
neuper@37906
   263
	 if (!m)=0 orelse p2=[0] then raise error ("RATIONALS_UV_MOD_PDIVP_EXCEPTION: Division by zero") 
neuper@37906
   264
	 else
neuper@37906
   265
	     (
neuper@37906
   266
	      if (!m)<n then 
neuper@37906
   267
		  (
neuper@37906
   268
		   output:=([0],p1) 
neuper@37906
   269
		   ) 
neuper@37906
   270
	      else
neuper@37906
   271
		  (
neuper@37906
   272
		   while (!m)>=n do
neuper@37906
   273
		       (
neuper@37906
   274
			c:=uv_mod_mod2(hd(!p1')*(power lc2 1), p);
neuper@37906
   275
			q:=(!c)::(!q);
neuper@37906
   276
			p1':=uv_mod_list_modp(tl(uv_mod_add_poly(uv_mod_smul_poly(!p1',lc2),
neuper@37906
   277
								  uv_mod_smul_poly(uv_mod_smul_poly(p2',hd(!p1')),~1)))) p;
neuper@37906
   278
			m:=(!m)-1
neuper@37906
   279
			);
neuper@37906
   280
		   
neuper@37906
   281
		   while !p1'<>[] andalso hd(!p1')=0 do
neuper@37906
   282
		       (
neuper@37906
   283
			p1':=tl(!p1')
neuper@37906
   284
			);
neuper@37906
   285
neuper@37906
   286
    		   output:=(rev(uv_mod_list_modp (!q) (p)),rev(!p1'))
neuper@37906
   287
		   )
neuper@37906
   288
	      );
neuper@37906
   289
	     !output:uv_poly * uv_poly
neuper@37906
   290
	 )
neuper@37906
   291
    end;
neuper@37906
   292
neuper@37906
   293
(*. calculates the remainder of p1/p2 .*)
neuper@37906
   294
fun uv_mod_prest (p1:uv_poly) ([]:uv_poly) = raise error("UV_MOD_PREST_EXCEPTION: Division by zero") 
neuper@37906
   295
  | uv_mod_prest [] p2 = []:uv_poly
neuper@37906
   296
  | uv_mod_prest p1 p2 = (#2(uv_mod_pdiv p1 p2));
neuper@37906
   297
neuper@37906
   298
(*. calculates the remainder of p1/p2 in Zp .*)
neuper@37906
   299
fun uv_mod_prestp (p1:uv_poly) ([]:uv_poly) p= raise error("UV_MOD_PRESTP_EXCEPTION: Division by zero") 
neuper@37906
   300
  | uv_mod_prestp [] p2 p= []:uv_poly 
neuper@37906
   301
  | uv_mod_prestp p1 p2 p = #2(uv_mod_pdivp p1 p2 p); 
neuper@37906
   302
neuper@37906
   303
(*. calculates the content of a uv polynomial .*)
neuper@37906
   304
fun uv_mod_cont ([]:uv_poly) = 0  
neuper@37906
   305
  | uv_mod_cont (x::p)= gcd_int x (uv_mod_cont(p));
neuper@37906
   306
neuper@37906
   307
(*. divides each coefficient of a uv polynomial by y .*)
neuper@37906
   308
fun uv_mod_div_list (p:uv_poly,0) = raise error("UV_MOD_DIV_LIST_EXCEPTION: Division by zero") 
neuper@37906
   309
  | uv_mod_div_list ([],y)   = []:uv_poly
neuper@37906
   310
  | uv_mod_div_list (x::p,y) = (x div y)::uv_mod_div_list(p,y); 
neuper@37906
   311
neuper@37906
   312
(*. calculates the primitiv part of a uv polynomial .*)
neuper@37906
   313
fun uv_mod_pp ([]:uv_poly) = []:uv_poly
neuper@37906
   314
  | uv_mod_pp p =  
neuper@37906
   315
    let
neuper@37906
   316
	val c=ref 0;
neuper@37906
   317
    in
neuper@37906
   318
	(
neuper@37906
   319
	 c:=uv_mod_cont(p);
neuper@37906
   320
	 
neuper@37906
   321
	 if !c=0 then raise error ("RATIONALS_UV_MOD_PP_EXCEPTION: content is 0")
neuper@37906
   322
	 else uv_mod_div_list(p,!c)
neuper@37906
   323
	)
neuper@37906
   324
    end;
neuper@37906
   325
neuper@37906
   326
(*. gets the leading coefficient of a uv polynomial .*)
neuper@37906
   327
fun uv_mod_lc ([]:uv_poly) = 0 
neuper@37906
   328
  | uv_mod_lc p  = hd(rev(p)); 
neuper@37906
   329
neuper@37906
   330
(*. calculates the euklidean polynomial remainder sequence in Zp .*)
neuper@37906
   331
fun uv_mod_prs_euklid_p(p1:uv_poly,p2:uv_poly,p)= 
neuper@37906
   332
    let
neuper@37906
   333
	val f =ref [];
neuper@37906
   334
	val f'=ref p2;
neuper@37906
   335
	val fi=ref [];
neuper@37906
   336
    in
neuper@37906
   337
	( 
neuper@37906
   338
	 f:=p2::p1::[]; 
neuper@37906
   339
 	 while uv_mod_deg(!f')>0 do
neuper@37906
   340
	     (
neuper@37906
   341
	      f':=uv_mod_prestp (hd(tl(!f))) (hd(!f)) p;
neuper@37906
   342
	      if (!f')<>[] then 
neuper@37906
   343
		  (
neuper@37906
   344
		   fi:=(!f');
neuper@37906
   345
		   f:=(!fi)::(!f)
neuper@37906
   346
		   )
neuper@37906
   347
	      else ()
neuper@37906
   348
	      );
neuper@37906
   349
	      (!f)
neuper@37906
   350
	 
neuper@37906
   351
	 )
neuper@37906
   352
    end;
neuper@37906
   353
neuper@37906
   354
(*. calculates the gcd of p1 and p2 in Zp .*)
neuper@37906
   355
fun uv_mod_gcd_modp ([]:uv_poly) (p2:uv_poly) p = p2:uv_poly 
neuper@37906
   356
  | uv_mod_gcd_modp p1 [] p= p1
neuper@37906
   357
  | uv_mod_gcd_modp p1 p2 p=
neuper@37906
   358
    let
neuper@37906
   359
	val p1'=ref[];
neuper@37906
   360
	val p2'=ref[];
neuper@37906
   361
	val pc=ref[];
neuper@37906
   362
	val g=ref [];
neuper@37906
   363
	val d=ref 0;
neuper@37906
   364
	val prs=ref [];
neuper@37906
   365
    in
neuper@37906
   366
	(
neuper@37906
   367
	 if uv_mod_deg(p1)>=uv_mod_deg(p2) then
neuper@37906
   368
	     (
neuper@37906
   369
	      p1':=uv_mod_list_modp (uv_mod_pp(p1)) p;
neuper@37906
   370
	      p2':=uv_mod_list_modp (uv_mod_pp(p2)) p
neuper@37906
   371
	      )
neuper@37906
   372
	 else 
neuper@37906
   373
	     (
neuper@37906
   374
	      p1':=uv_mod_list_modp (uv_mod_pp(p2)) p;
neuper@37906
   375
	      p2':=uv_mod_list_modp (uv_mod_pp(p1)) p
neuper@37906
   376
	      );
neuper@37906
   377
	 d:=uv_mod_mod2((gcd_int (uv_mod_cont(p1))) (uv_mod_cont(p2)), p) ;
neuper@37906
   378
	 if !d>(p div 2) then d:=(!d)-p else ();
neuper@37906
   379
	 
neuper@37906
   380
	 prs:=uv_mod_prs_euklid_p(!p1',!p2',p);
neuper@37906
   381
neuper@37906
   382
	 if hd(!prs)=[] then pc:=hd(tl(!prs))
neuper@37906
   383
	 else pc:=hd(!prs);
neuper@37906
   384
neuper@37906
   385
	 g:=uv_mod_smul_poly(uv_mod_pp(!pc),!d);
neuper@37906
   386
	 !g
neuper@37906
   387
	 )
neuper@37906
   388
    end;
neuper@37906
   389
neuper@37906
   390
(*. calculates the minimum of two real values x and y .*)
neuper@37906
   391
fun uv_mod_r_min(x,y):BasisLibrary.Real.real = if x>y then y else x;
neuper@37906
   392
neuper@37906
   393
(*. calculates the minimum of two integer values x and y .*)
neuper@37906
   394
fun uv_mod_min(x,y) = if x>y then y else x;
neuper@37906
   395
neuper@37906
   396
(*. adds the squared values of a integer list .*)
neuper@37906
   397
fun uv_mod_add_qu [] = 0.0 
neuper@37906
   398
  | uv_mod_add_qu (x::p) =  BasisLibrary.Real.fromInt(x)*BasisLibrary.Real.fromInt(x) + uv_mod_add_qu p;
neuper@37906
   399
neuper@37906
   400
(*. calculates the euklidean norm .*)
neuper@37906
   401
fun uv_mod_norm ([]:uv_poly) = 0.0
neuper@37906
   402
  | uv_mod_norm p = Math.sqrt(uv_mod_add_qu(p));
neuper@37906
   403
neuper@37906
   404
(*. multipies two values a and b .*)
neuper@37906
   405
fun uv_mod_multi a b = a * b;
neuper@37906
   406
neuper@37906
   407
(*. decides if x is a prim, the list contains all primes which are lower then x .*)
neuper@37906
   408
fun uv_mod_prim(x,[])= false 
neuper@37906
   409
  | uv_mod_prim(x,[y])=if ((x mod y) <> 0) then true
neuper@37906
   410
		else false
neuper@37906
   411
  | uv_mod_prim(x,y::ys) = if uv_mod_prim(x,[y])
neuper@37906
   412
			then 
neuper@37906
   413
			    if uv_mod_prim(x,ys) then true 
neuper@37906
   414
			    else false
neuper@37906
   415
		    else false;
neuper@37906
   416
neuper@37906
   417
(*. gets the first prime, which is greater than p and does not divide g .*)
neuper@37906
   418
fun uv_mod_nextprime(g,p)= 
neuper@37906
   419
    let
neuper@37906
   420
	val list=ref [2];
neuper@37906
   421
	val exit=ref 0;
neuper@37906
   422
	val i = ref 2
neuper@37906
   423
    in
neuper@37906
   424
	while (!i<p) do (* calculates the primes lower then p *)
neuper@37906
   425
	    (
neuper@37906
   426
	     if uv_mod_prim(!i,!list) then
neuper@37906
   427
		 (
neuper@37906
   428
		  if (p mod !i <> 0)
neuper@37906
   429
		      then
neuper@37906
   430
			  (
neuper@37906
   431
			   list:= (!i)::(!list);
neuper@37906
   432
			   i:= (!i)+1
neuper@37906
   433
			   )
neuper@37906
   434
		  else i:=(!i)+1
neuper@37906
   435
		  )
neuper@37906
   436
	     else i:= (!i)+1
neuper@37906
   437
		 );
neuper@37906
   438
	    i:=(p+1);
neuper@37906
   439
	    while (!exit=0) do   (* calculate next prime which does not divide g *)
neuper@37906
   440
	    (
neuper@37906
   441
	     if uv_mod_prim(!i,!list) then
neuper@37906
   442
		 (
neuper@37906
   443
		  if (g mod !i <> 0)
neuper@37906
   444
		      then
neuper@37906
   445
			  (
neuper@37906
   446
			   list:= (!i)::(!list);
neuper@37906
   447
			   exit:= (!i)
neuper@37906
   448
			   )
neuper@37906
   449
		  else i:=(!i)+1
neuper@37906
   450
		      )
neuper@37906
   451
	     else i:= (!i)+1
neuper@37906
   452
		 ); 
neuper@37906
   453
	    !exit
neuper@37906
   454
    end;
neuper@37906
   455
neuper@37906
   456
(*. decides if p1 is a factor of p2 in Zp .*)
neuper@37906
   457
fun uv_mod_dividesp ([]:uv_poly) (p2:uv_poly) p= raise error("UV_MOD_DIVIDESP: Division by zero") 
neuper@37906
   458
  | uv_mod_dividesp p1 p2 p= if uv_mod_prestp p2 p1 p = [] then true else false;
neuper@37906
   459
neuper@37906
   460
(*. decides if p1 is a factor of p2 .*)
neuper@37906
   461
fun uv_mod_divides ([]:uv_poly) (p2:uv_poly) = raise error("UV_MOD_DIVIDES: Division by zero")
neuper@37906
   462
  | uv_mod_divides p1 p2 = if uv_mod_prest p2 p1  = [] then true else false;
neuper@37906
   463
neuper@37906
   464
(*. chinese remainder algorithm .*)
neuper@37906
   465
fun uv_mod_cra2(r1,r2,m1,m2)=     
neuper@37906
   466
    let 
neuper@37906
   467
	val c=ref 0;
neuper@37906
   468
	val r1'=ref 0;
neuper@37906
   469
	val d=ref 0;
neuper@37906
   470
	val a=ref 0;
neuper@37906
   471
    in
neuper@37906
   472
	(
neuper@37906
   473
	 while (uv_mod_mod2((!c)*m1,m2))<>1 do 
neuper@37906
   474
	     (
neuper@37906
   475
	      c:=(!c)+1
neuper@37906
   476
	      );
neuper@37906
   477
	 r1':= uv_mod_mod2(r1,m1);
neuper@37906
   478
	 d:=uv_mod_mod2(((r2-(!r1'))*(!c)),m2);
neuper@37906
   479
	 !r1'+(!d)*m1    
neuper@37906
   480
	 )
neuper@37906
   481
    end;
neuper@37906
   482
neuper@37906
   483
(*. applies the chinese remainder algorithmen to the coefficients of x1 and x2 .*)
neuper@37906
   484
fun uv_mod_cra_2 ([],[],m1,m2) = [] 
neuper@37906
   485
  | uv_mod_cra_2 ([],x2,m1,m2) = raise error("UV_MOD_CRA_2_EXCEPTION: invalid call x1")
neuper@37906
   486
  | uv_mod_cra_2 (x1,[],m1,m2) = raise error("UV_MOD_CRA_2_EXCEPTION: invalid call x2")
neuper@37906
   487
  | uv_mod_cra_2 (x1::x1s,x2::x2s,m1,m2) = (uv_mod_cra2(x1,x2,m1,m2))::(uv_mod_cra_2(x1s,x2s,m1,m2));
neuper@37906
   488
neuper@37906
   489
(*. calculates the gcd of two uv polynomials p1' and p2' with the modular algorithm .*)
neuper@37906
   490
fun uv_mod_gcd (p1':uv_poly) (p2':uv_poly) =
neuper@37906
   491
    let 
neuper@37906
   492
	val p1=ref (uv_mod_pp(p1'));
neuper@37906
   493
	val p2=ref (uv_mod_pp(p2'));
neuper@37906
   494
	val c=gcd_int (uv_mod_cont(p1')) (uv_mod_cont(p2'));
neuper@37906
   495
	val temp=ref [];
neuper@37906
   496
	val cp=ref [];
neuper@37906
   497
	val qp=ref [];
neuper@37906
   498
	val q=ref[];
neuper@37906
   499
	val pn=ref 0;
neuper@37906
   500
	val d=ref 0;
neuper@37906
   501
	val g1=ref 0;
neuper@37906
   502
	val p=ref 0;    
neuper@37906
   503
	val m=ref 0;
neuper@37906
   504
	val exit=ref 0;
neuper@37906
   505
	val i=ref 1;
neuper@37906
   506
    in
neuper@37906
   507
	if length(!p1)>length(!p2) then ()
neuper@37906
   508
	else 
neuper@37906
   509
	    (
neuper@37906
   510
	     temp:= !p1;
neuper@37906
   511
	     p1:= !p2;
neuper@37906
   512
	     p2:= !temp
neuper@37906
   513
	     );
neuper@37906
   514
neuper@37906
   515
	 
neuper@37906
   516
	d:=gcd_int (uv_mod_lc(!p1)) (uv_mod_lc(!p2));
neuper@37906
   517
	g1:=uv_mod_lc(!p1)*uv_mod_lc(!p2);
neuper@37906
   518
	p:=4;
neuper@37906
   519
	
neuper@37906
   520
	m:=BasisLibrary.Real.ceil(2.0 *   
neuper@37906
   521
				  BasisLibrary.Real.fromInt(!d) *
neuper@37906
   522
				  BasisLibrary.Real.fromInt(power 2 (uv_mod_min(uv_mod_deg(!p2),uv_mod_deg(!p1)))) *  
neuper@37906
   523
				  BasisLibrary.Real.fromInt(!d) * 
neuper@37906
   524
				  uv_mod_r_min(uv_mod_norm(!p1) / BasisLibrary.Real.fromInt(abs(uv_mod_lc(!p1))),
neuper@37906
   525
					uv_mod_norm(!p2) / BasisLibrary.Real.fromInt(abs(uv_mod_lc(!p2))))); 
neuper@37906
   526
neuper@37906
   527
	while (!exit=0) do  
neuper@37906
   528
	    (
neuper@37906
   529
	     p:=uv_mod_nextprime(!d,!p);
neuper@37906
   530
	     cp:=(uv_mod_gcd_modp (uv_mod_list_modp(!p1) (!p)) (uv_mod_list_modp(!p2) (!p)) (!p)) ;
neuper@37906
   531
	     if abs(uv_mod_lc(!cp))<>1 then  (* leading coefficient = 1 ? *)
neuper@37906
   532
		 (
neuper@37906
   533
		  i:=1;
neuper@37906
   534
		  while (!i)<(!p) andalso (abs(uv_mod_mod2((uv_mod_lc(!cp)*(!i)),(!p)))<>1) do
neuper@37906
   535
		      (
neuper@37906
   536
		       i:=(!i)+1
neuper@37906
   537
		       );
neuper@37906
   538
		      cp:=uv_mod_list_modp (map (uv_mod_multi (!i)) (!cp)) (!p) 
neuper@37906
   539
		  )
neuper@37906
   540
	     else ();
neuper@37906
   541
neuper@37906
   542
	     qp:= ((map (uv_mod_multi (uv_mod_mod2(!d,!p)))) (!cp));
neuper@37906
   543
neuper@37906
   544
	     if uv_mod_deg(!qp)=0 then (q:=[1]; exit:=1) else ();
neuper@37906
   545
neuper@37906
   546
	     pn:=(!p);
neuper@37906
   547
	     q:=(!qp);
neuper@37906
   548
neuper@37906
   549
	     while !pn<= !m andalso !m>(!p) andalso !exit=0 do
neuper@37906
   550
		 (
neuper@37906
   551
		  p:=uv_mod_nextprime(!d,!p);
neuper@37906
   552
 		  cp:=(uv_mod_gcd_modp (uv_mod_list_modp(!p1) (!p)) (uv_mod_list_modp(!p2) (!p)) (!p)); 
neuper@37906
   553
 		  if uv_mod_lc(!cp)<>1 then  (* leading coefficient = 1 ? *)
neuper@37906
   554
 		      (
neuper@37906
   555
 		       i:=1;
neuper@37906
   556
 		       while (!i)<(!p) andalso ((uv_mod_mod2((uv_mod_lc(!q)*(!i)),(!p)))<>1) do
neuper@37906
   557
 			   (
neuper@37906
   558
 			    i:=(!i)+1
neuper@37906
   559
		           );
neuper@37906
   560
		       cp:=uv_mod_list_modp (map (uv_mod_multi (!i)) (!cp)) (!p)
neuper@37906
   561
 		      )
neuper@37906
   562
 		  else ();    
neuper@37906
   563
 		 
neuper@37906
   564
		  qp:=uv_mod_list_modp ((map (uv_mod_multi (uv_mod_mod2(!d,!p)))) (!cp)  ) (!p);
neuper@37906
   565
 		  if uv_mod_deg(!qp)>uv_mod_deg(!q) then
neuper@37906
   566
 		      (
neuper@37906
   567
 		       (*print("degree to high!!!\n")*)
neuper@37906
   568
 		       )
neuper@37906
   569
 		  else
neuper@37906
   570
 		      (
neuper@37906
   571
 		       if uv_mod_deg(!qp)=uv_mod_deg(!q) then
neuper@37906
   572
 			   (
neuper@37906
   573
 			    q:=uv_mod_cra_2(!q,!qp,!pn,!p);
neuper@37906
   574
			    pn:=(!pn) * !p;
neuper@37906
   575
			    q:=uv_mod_pp(uv_mod_list_modp (!q) (!pn)); (* found already gcd ? *)
neuper@37906
   576
			    if (uv_mod_divides (!q) (p1')) andalso (uv_mod_divides (!q) (p2')) then (exit:=1) else ()
neuper@37906
   577
		 	    )
neuper@37906
   578
		       else
neuper@37906
   579
			   (
neuper@37906
   580
			    if  uv_mod_deg(!qp)<uv_mod_deg(!q) then
neuper@37906
   581
				(
neuper@37906
   582
				 pn:= !p;
neuper@37906
   583
				 q:= !qp
neuper@37906
   584
				 )
neuper@37906
   585
			    else ()
neuper@37906
   586
			    )
neuper@37906
   587
		       )
neuper@37906
   588
		  );
neuper@37906
   589
 	     q:=uv_mod_pp(uv_mod_list_modp (!q) (!pn));
neuper@37906
   590
	     if (uv_mod_divides (!q) (p1')) andalso (uv_mod_divides (!q) (p2')) then exit:=1 else ()
neuper@37906
   591
	     );
neuper@37906
   592
	    uv_mod_smul_poly(!q,c):uv_poly
neuper@37906
   593
    end;
neuper@37906
   594
neuper@37906
   595
(*. multivariate polynomials .*)
neuper@37906
   596
(*. multivariate polynomials are represented as a list of the pairs, 
neuper@37906
   597
 first is the coefficent and the second is a list of the exponents .*)
neuper@37906
   598
(*. 5 * x^5 * y^3 + 4 * x^3 * z^2 + 2 * x^2 * y * z^3 - z - 19 
neuper@37906
   599
 => [(5,[5,3,0]),(4,[3,0,2]),(2,[2,1,3]),(~1,[0,0,1]),(~19,[0,0,0])] .*)
neuper@37906
   600
neuper@37906
   601
(*. global variables .*)
neuper@37906
   602
(*. order indicators .*)
neuper@37906
   603
val LEX_=0; (* lexicographical term order *)
neuper@37906
   604
val GGO_=1; (* greatest degree order *)
neuper@37906
   605
neuper@37906
   606
(*. datatypes for internal representation.*)
neuper@37906
   607
type mv_monom = (int *      (*.coefficient or the monom.*)
neuper@37906
   608
		 int list); (*.list of exponents)      .*)
neuper@37906
   609
fun mv_monom2str (i, is) = "("^ int2str i^"," ^ ints2str' is ^ ")";
neuper@37906
   610
neuper@37906
   611
type mv_poly = mv_monom list; 
neuper@37906
   612
fun mv_poly2str p = (strs2str' o (map mv_monom2str)) p;
neuper@37906
   613
neuper@37906
   614
(*. help function for monom_greater and geq .*)
neuper@37906
   615
fun mv_mg_hlp([]) = EQUAL 
neuper@37906
   616
  | mv_mg_hlp(x::list)=if x<0 then LESS
neuper@37906
   617
		    else if x>0 then GREATER
neuper@37906
   618
			 else mv_mg_hlp(list);
neuper@37906
   619
neuper@37906
   620
(*. adds a list of values .*)
neuper@37906
   621
fun mv_addlist([]) = 0
neuper@37906
   622
  | mv_addlist(p1) = hd(p1)+mv_addlist(tl(p1));
neuper@37906
   623
			   
neuper@37906
   624
(*. tests if the monomial M1 is greater as the monomial M2 and returns a boolean value .*)
neuper@37906
   625
(*. 2 orders are implemented LEX_/GGO_ (lexigraphical/greatest degree order) .*)
neuper@37906
   626
fun mv_monom_greater((M1x,M1l):mv_monom,(M2x,M2l):mv_monom,order)=
neuper@37906
   627
    if order=LEX_ then
neuper@37906
   628
	( 
neuper@37906
   629
	 if length(M1l)<>length(M2l) then raise error ("RATIONALS_MV_MONOM_GREATER_EXCEPTION: Order error")
neuper@37906
   630
	 else if (mv_mg_hlp((map op- (M1l~~M2l)))<>GREATER) then false else true
neuper@37906
   631
	     )
neuper@37906
   632
    else
neuper@37906
   633
	if order=GGO_ then
neuper@37906
   634
	    ( 
neuper@37906
   635
	     if length(M1l)<>length(M2l) then raise error ("RATIONALS_MV_MONOM_GREATER_EXCEPTION: Order error")
neuper@37906
   636
	     else 
neuper@37906
   637
		 if mv_addlist(M1l)=mv_addlist(M2l)  then if (mv_mg_hlp((map op- (M1l~~M2l)))<>GREATER) then false else true
neuper@37906
   638
		 else if mv_addlist(M1l)>mv_addlist(M2l) then true else false
neuper@37906
   639
	     )
neuper@37906
   640
	else raise error ("RATIONALS_MV_MONOM_GREATER_EXCEPTION: Wrong Order");
neuper@37906
   641
		   
neuper@37906
   642
(*. tests if the monomial X is greater as the monomial Y and returns a order value (GREATER,EQUAL,LESS) .*)
neuper@37906
   643
(*. 2 orders are implemented LEX_/GGO_ (lexigraphical/greatest degree order) .*)
neuper@37906
   644
fun mv_geq order ((x1,x):mv_monom,(x2,y):mv_monom) =
neuper@37906
   645
let 
neuper@37906
   646
    val temp=ref EQUAL;
neuper@37906
   647
in
neuper@37906
   648
    if order=LEX_ then
neuper@37906
   649
	(
neuper@37906
   650
	 if length(x)<>length(y) then 
neuper@37906
   651
	     raise error ("RATIONALS_MV_GEQ_EXCEPTION: Order error")
neuper@37906
   652
	 else 
neuper@37906
   653
	     (
neuper@37906
   654
	      temp:=mv_mg_hlp((map op- (x~~y)));
neuper@37906
   655
	      if !temp=EQUAL then 
neuper@37906
   656
		  ( if x1=x2 then EQUAL 
neuper@37906
   657
		    else if x1>x2 then GREATER
neuper@37906
   658
			 else LESS
neuper@37906
   659
			     )
neuper@37906
   660
	      else (!temp)
neuper@37906
   661
	      )
neuper@37906
   662
	     )
neuper@37906
   663
    else 
neuper@37906
   664
	if order=GGO_ then 
neuper@37906
   665
	    (
neuper@37906
   666
	     if length(x)<>length(y) then 
neuper@37906
   667
	      raise error ("RATIONALS_MV_GEQ_EXCEPTION: Order error")
neuper@37906
   668
	     else 
neuper@37906
   669
		 if mv_addlist(x)=mv_addlist(y) then 
neuper@37906
   670
		     (mv_mg_hlp((map op- (x~~y))))
neuper@37906
   671
		 else if mv_addlist(x)>mv_addlist(y) then GREATER else LESS
neuper@37906
   672
		     )
neuper@37906
   673
	else raise error ("RATIONALS_MV_GEQ_EXCEPTION: Wrong Order")
neuper@37906
   674
end;
neuper@37906
   675
neuper@37906
   676
(*. cuts the first variable from a polynomial .*)
neuper@37906
   677
fun mv_cut([]:mv_poly)=[]:mv_poly
neuper@37906
   678
  | mv_cut((x,[])::list) = raise error ("RATIONALS_MV_CUT_EXCEPTION: Invalid list ")
neuper@37906
   679
  | mv_cut((x,y::ys)::list)=(x,ys)::mv_cut(list);
neuper@37906
   680
	    
neuper@37906
   681
(*. leading power product .*)
neuper@37906
   682
fun mv_lpp([]:mv_poly,order)  = []
neuper@37906
   683
  | mv_lpp([(x,y)],order) = y
neuper@37906
   684
  | mv_lpp(p1,order)  = #2(hd(rev(sort (mv_geq order) p1)));
neuper@37906
   685
    
neuper@37906
   686
(*. leading monomial .*)
neuper@37906
   687
fun mv_lm([]:mv_poly,order)  = (0,[]):mv_monom
neuper@37906
   688
  | mv_lm([x],order) = x 
neuper@37906
   689
  | mv_lm(p1,order)  = hd(rev(sort (mv_geq order) p1));
neuper@37906
   690
    
neuper@37906
   691
(*. leading coefficient in term order .*)
neuper@37906
   692
fun mv_lc2([]:mv_poly,order)  = 0
neuper@37906
   693
  | mv_lc2([(x,y)],order) = x
neuper@37906
   694
  | mv_lc2(p1,order)  = #1(hd(rev(sort (mv_geq order) p1)));
neuper@37906
   695
neuper@37906
   696
neuper@37906
   697
(*. reverse the coefficients in mv polynomial .*)
neuper@37906
   698
fun mv_rev_to([]:mv_poly) = []:mv_poly
neuper@37906
   699
  | mv_rev_to((c,e)::xs) = (c,rev(e))::mv_rev_to(xs);
neuper@37906
   700
neuper@37906
   701
(*. leading coefficient in reverse term order .*)
neuper@37906
   702
fun mv_lc([]:mv_poly,order)  = []:mv_poly 
neuper@37906
   703
  | mv_lc([(x,y)],order) = mv_rev_to(mv_cut(mv_rev_to([(x,y)])))
neuper@37906
   704
  | mv_lc(p1,order)  = 
neuper@37906
   705
    let
neuper@37906
   706
	val p1o=ref (rev(sort (mv_geq order) (mv_rev_to(p1))));
neuper@37906
   707
	val lp=hd(#2(hd(!p1o)));
neuper@37906
   708
	val lc=ref [];
neuper@37906
   709
    in
neuper@37906
   710
	(
neuper@37906
   711
	 while (length(!p1o)>0 andalso hd(#2(hd(!p1o)))=lp) do
neuper@37906
   712
	     (
neuper@37906
   713
	      lc:=hd(mv_cut([hd(!p1o)]))::(!lc);
neuper@37906
   714
	      p1o:=tl(!p1o)
neuper@37906
   715
	      );
neuper@37906
   716
	 if !lc=[] then raise error ("RATIONALS_MV_LC_EXCEPTION: lc is empty") else ();
neuper@37906
   717
	 mv_rev_to(!lc)
neuper@37906
   718
	 )
neuper@37906
   719
    end;
neuper@37906
   720
neuper@37906
   721
(*. compares two powerproducts .*)
neuper@37906
   722
fun mv_monom_equal((_,xlist):mv_monom,(_,ylist):mv_monom) = (foldr and_) (((map op=) (xlist~~ylist)),true);
neuper@37906
   723
    
neuper@37906
   724
(*. help function for mv_add .*)
neuper@37906
   725
fun mv_madd([]:mv_poly,[]:mv_poly,order) = []:mv_poly
neuper@37906
   726
  | mv_madd([(0,_)],p2,order) = p2
neuper@37906
   727
  | mv_madd(p1,[(0,_)],order) = p1  
neuper@37906
   728
  | mv_madd([],p2,order) = p2
neuper@37906
   729
  | mv_madd(p1,[],order) = p1
neuper@37906
   730
  | mv_madd(p1,p2,order) = 
neuper@37906
   731
    (
neuper@37906
   732
     if mv_monom_greater(hd(p1),hd(p2),order) 
neuper@37906
   733
	 then hd(p1)::mv_madd(tl(p1),p2,order)
neuper@37906
   734
     else if mv_monom_equal(hd(p1),hd(p2)) 
neuper@37906
   735
	      then if mv_lc2(p1,order)+mv_lc2(p2,order)<>0 
neuper@37906
   736
		       then (mv_lc2(p1,order)+mv_lc2(p2,order),mv_lpp(p1,order))::mv_madd(tl(p1),tl(p2),order)
neuper@37906
   737
		   else mv_madd(tl(p1),tl(p2),order)
neuper@37906
   738
	  else hd(p2)::mv_madd(p1,tl(p2),order)
neuper@37906
   739
	      )
neuper@37906
   740
	      
neuper@37906
   741
(*. adds two multivariate polynomials .*)
neuper@37906
   742
fun mv_add([]:mv_poly,p2:mv_poly,order) = p2
neuper@37906
   743
  | mv_add(p1,[],order) = p1
neuper@37906
   744
  | mv_add(p1,p2,order) = mv_madd(rev(sort (mv_geq order) p1),rev(sort (mv_geq order) p2), order);
neuper@37906
   745
neuper@37906
   746
(*. monom multiplication .*)
neuper@37906
   747
fun mv_mmul((x1,y1):mv_monom,(x2,y2):mv_monom)=(x1*x2,(map op+) (y1~~y2)):mv_monom;
neuper@37906
   748
neuper@37906
   749
(*. deletes all monomials with coefficient 0 .*)
neuper@37906
   750
fun mv_shorten([]:mv_poly,order) = []:mv_poly
neuper@37906
   751
  | mv_shorten(x::xs,order)=mv_madd([x],mv_shorten(xs,order),order);
neuper@37906
   752
neuper@37906
   753
(*. zeros a list .*)
neuper@37906
   754
fun mv_null2([])=[]
neuper@37906
   755
  | mv_null2(x::l)=0::mv_null2(l);
neuper@37906
   756
neuper@37906
   757
(*. multiplies two multivariate polynomials .*)
neuper@37906
   758
fun mv_mul([]:mv_poly,[]:mv_poly,_) = []:mv_poly
neuper@37906
   759
  | mv_mul([],y::p2,_) = [(0,mv_null2(#2(y)))]
neuper@37906
   760
  | mv_mul(x::p1,[],_) = [(0,mv_null2(#2(x)))] 
neuper@37906
   761
  | mv_mul(x::p1,y::p2,order) = mv_shorten(rev(sort (mv_geq order) (mv_mmul(x,y) :: (mv_mul(p1,y::p2,order) @
neuper@37906
   762
									    mv_mul([x],p2,order)))),order);
neuper@37906
   763
neuper@37906
   764
(*. gets the maximum value of a list .*)
neuper@37906
   765
fun mv_getmax([])=0
neuper@37906
   766
  | mv_getmax(x::p1)= let 
neuper@37906
   767
		       val m=mv_getmax(p1);
neuper@37906
   768
		   in
neuper@37906
   769
		       if m>x then m
neuper@37906
   770
		       else x
neuper@37906
   771
		   end;
neuper@37906
   772
(*. calculates the maximum degree of an multivariate polynomial .*)
neuper@37906
   773
fun mv_grad([]:mv_poly) = 0 
neuper@37906
   774
  | mv_grad(p1:mv_poly)= mv_getmax((map mv_addlist) ((map #2) p1));
neuper@37906
   775
neuper@37906
   776
(*. converts the sign of a value .*)
neuper@37906
   777
fun mv_minus(x)=(~1) * x;
neuper@37906
   778
neuper@37906
   779
(*. converts the sign of all coefficients of a polynomial .*)
neuper@37906
   780
fun mv_minus2([]:mv_poly)=[]:mv_poly
neuper@37906
   781
  | mv_minus2(p1)=(mv_minus(#1(hd(p1))),#2(hd(p1)))::(mv_minus2(tl(p1)));
neuper@37906
   782
neuper@37906
   783
(*. searches for a negativ value in a list .*)
neuper@37906
   784
fun mv_is_negativ([])=false
neuper@37906
   785
  | mv_is_negativ(x::xs)=if x<0 then true else mv_is_negativ(xs);
neuper@37906
   786
neuper@37906
   787
(*. division of monomials .*)
neuper@37906
   788
fun mv_mdiv((0,[]):mv_monom,_:mv_monom)=(0,[]):mv_monom
neuper@37906
   789
  | mv_mdiv(_,(0,[]))= raise error ("RATIONALS_MV_MDIV_EXCEPTION Division by 0 ")
neuper@37906
   790
  | mv_mdiv(p1:mv_monom,p2:mv_monom)= 
neuper@37906
   791
    let
neuper@37906
   792
	val c=ref (#1(p2));
neuper@37906
   793
	val pp=ref [];
neuper@37906
   794
    in 
neuper@37906
   795
	(
neuper@37906
   796
	 if !c=0 then raise error("MV_MDIV_EXCEPTION Dividing by zero")
neuper@37906
   797
	 else c:=(#1(p1) div #1(p2));
neuper@37906
   798
	     if #1(p2)<>0 then 
neuper@37906
   799
		 (
neuper@37906
   800
		  pp:=(#2(mv_mmul((1,#2(p1)),(1,(map mv_minus) (#2(p2))))));
neuper@37906
   801
		  if mv_is_negativ(!pp) then (0,!pp)
neuper@37906
   802
		  else (!c,!pp) 
neuper@37906
   803
		      )
neuper@37906
   804
	     else raise error("MV_MDIV_EXCEPTION Dividing by empty Polynom")
neuper@37906
   805
		 )
neuper@37906
   806
    end;
neuper@37906
   807
neuper@37906
   808
(*. prints a polynom for (internal use only) .*)
neuper@37906
   809
fun mv_print_poly([]:mv_poly)=print("[]\n")
neuper@37906
   810
  | mv_print_poly((x,y)::[])= print("("^BasisLibrary.Int.toString(x)^","^ints2str(y)^")\n")
neuper@37906
   811
  | mv_print_poly((x,y)::p1) = (print("("^BasisLibrary.Int.toString(x)^","^ints2str(y)^"),");mv_print_poly(p1));
neuper@37906
   812
neuper@37906
   813
neuper@37906
   814
(*. division of two multivariate polynomials .*) 
neuper@37906
   815
fun mv_division([]:mv_poly,g:mv_poly,order)=([]:mv_poly,[]:mv_poly)
neuper@37906
   816
  | mv_division(f,[],order)= raise error ("RATIONALS_MV_DIVISION_EXCEPTION Division by zero")
neuper@37906
   817
  | mv_division(f,g,order)=
neuper@37906
   818
    let 
neuper@37906
   819
	val r=ref [];
neuper@37906
   820
	val q=ref [];
neuper@37906
   821
	val g'=ref [];
neuper@37906
   822
	val k=ref 0;
neuper@37906
   823
	val m=ref (0,[0]);
neuper@37906
   824
	val exit=ref 0;
neuper@37906
   825
    in
neuper@37906
   826
	r := rev(sort (mv_geq order) (mv_shorten(f,order)));
neuper@37906
   827
	g':= rev(sort (mv_geq order) (mv_shorten(g,order)));
neuper@37906
   828
	if #1(hd(!g'))=0 then raise error("RATIONALS_MV_DIVISION_EXCEPTION: Dividing by zero") else ();
neuper@37906
   829
	if  (mv_monom_greater (hd(!g'),hd(!r),order)) then ([(0,mv_null2(#2(hd(f))))],(!r))
neuper@37906
   830
	else
neuper@37906
   831
	    (
neuper@37906
   832
	     exit:=0;
neuper@37906
   833
	     while (if (!exit)=0 then not(mv_monom_greater (hd(!g'),hd(!r),order)) else false) do
neuper@37906
   834
		 (
neuper@37906
   835
		  if (#1(mv_lm(!g',order)))<>0 then m:=mv_mdiv(mv_lm(!r,order),mv_lm(!g',order))
neuper@37906
   836
		  else raise error ("RATIONALS_MV_DIVISION_EXCEPTION: Dividing by zero");	  
neuper@37906
   837
		  if #1(!m)<>0 then
neuper@37906
   838
		      ( 
neuper@37906
   839
		       q:=(!m)::(!q);
neuper@37906
   840
		       r:=mv_add((!r),mv_minus2(mv_mul(!g',[!m],order)),order)
neuper@37906
   841
		       )
neuper@37906
   842
		  else exit:=1;
neuper@37906
   843
		  if (if length(!r)<>0 then length(!g')<>0 else false) then ()
neuper@37906
   844
		  else (exit:=1)
neuper@37906
   845
		  );
neuper@37906
   846
		 (rev(!q),!r)
neuper@37906
   847
		 )
neuper@37906
   848
    end;
neuper@37906
   849
neuper@37906
   850
(*. multiplies a polynomial with an integer .*)
neuper@37906
   851
fun mv_skalar_mul([]:mv_poly,c) = []:mv_poly
neuper@37906
   852
  | mv_skalar_mul((x,y)::p1,c) = ((x * c),y)::mv_skalar_mul(p1,c); 
neuper@37906
   853
neuper@37906
   854
(*. inserts the a first variable into an polynomial with exponent v .*)
neuper@37906
   855
fun mv_correct([]:mv_poly,v:int)=[]:mv_poly
neuper@37906
   856
  | mv_correct((x,y)::list,v:int)=(x,v::y)::mv_correct(list,v);
neuper@37906
   857
neuper@37906
   858
(*. multivariate case .*)
neuper@37906
   859
neuper@37906
   860
(*. decides if x is a factor of y .*)
neuper@37906
   861
fun mv_divides([]:mv_poly,[]:mv_poly)=  raise error("RATIONALS_MV_DIVIDES_EXCEPTION: division by zero")
neuper@37906
   862
  | mv_divides(x,[]) =  raise error("RATIONALS_MV_DIVIDES_EXCEPTION: division by zero")
neuper@37906
   863
  | mv_divides(x:mv_poly,y:mv_poly) = #2(mv_division(y,x,LEX_))=[];
neuper@37906
   864
neuper@37906
   865
(*. gets the maximum of a and b .*)
neuper@37906
   866
fun mv_max(a,b) = if a>b then a else b;
neuper@37906
   867
neuper@37906
   868
(*. gets the maximum exponent of a mv polynomial in the lexicographic term order .*)
neuper@37906
   869
fun mv_deg([]:mv_poly) = 0  
neuper@37906
   870
  | mv_deg(p1)=
neuper@37906
   871
    let
neuper@37906
   872
	val p1'=mv_shorten(p1,LEX_);
neuper@37906
   873
    in
neuper@37906
   874
	if length(p1')=0 then 0 
neuper@37906
   875
	else mv_max(hd(#2(hd(p1'))),mv_deg(tl(p1')))
neuper@37906
   876
    end;
neuper@37906
   877
neuper@37906
   878
(*. gets the maximum exponent of a mv polynomial in the reverse lexicographic term order .*)
neuper@37906
   879
fun mv_deg2([]:mv_poly) = 0
neuper@37906
   880
  | mv_deg2(p1)=
neuper@37906
   881
    let
neuper@37906
   882
	val p1'=mv_shorten(p1,LEX_);
neuper@37906
   883
    in
neuper@37906
   884
	if length(p1')=0 then 0 
neuper@37906
   885
	else mv_max(hd(rev(#2(hd(p1')))),mv_deg2(tl(p1')))
neuper@37906
   886
    end;
neuper@37906
   887
neuper@37906
   888
(*. evaluates the mv polynomial at the value v of the main variable .*)
neuper@37906
   889
fun mv_subs([]:mv_poly,v) = []:mv_poly
neuper@37906
   890
  | mv_subs((c,e)::p1:mv_poly,v) = mv_skalar_mul(mv_cut([(c,e)]),power v (hd(e))) @ mv_subs(p1,v);
neuper@37906
   891
neuper@37906
   892
(*. calculates the content of a uv-polynomial in mv-representation .*)
neuper@37906
   893
fun uv_content2([]:mv_poly) = 0
neuper@37906
   894
  | uv_content2((c,e)::p1) = (gcd_int c (uv_content2(p1)));
neuper@37906
   895
neuper@37906
   896
(*. converts a uv-polynomial from mv-representation to  uv-representation .*)
neuper@37906
   897
fun uv_to_list ([]:mv_poly)=[]:uv_poly
neuper@37906
   898
  | uv_to_list ((c1,e1)::others) = 
neuper@37906
   899
    let
neuper@37906
   900
	val count=ref 0;
neuper@37906
   901
	val max=mv_grad((c1,e1)::others); 
neuper@37906
   902
	val help=ref ((c1,e1)::others);
neuper@37906
   903
	val list=ref [];
neuper@37906
   904
    in
neuper@37906
   905
	if length(e1)>1 then raise error ("RATIONALS_TO_LIST_EXCEPTION: not univariate")
neuper@37906
   906
	else if length(e1)=0 then [c1]
neuper@37906
   907
	     else
neuper@37906
   908
		 (
neuper@37906
   909
		  count:=0;
neuper@37906
   910
		  while (!count)<=max do
neuper@37906
   911
		      (
neuper@37906
   912
		       if length(!help)>0 andalso hd(#2(hd(!help)))=max-(!count) then 
neuper@37906
   913
			   (
neuper@37906
   914
			    list:=(#1(hd(!help)))::(!list);		       
neuper@37906
   915
			    help:=tl(!help) 
neuper@37906
   916
			    )
neuper@37906
   917
		       else 
neuper@37906
   918
			   (
neuper@37906
   919
			    list:= 0::(!list)
neuper@37906
   920
			    );
neuper@37906
   921
		       count := (!count) + 1
neuper@37906
   922
		       );
neuper@37906
   923
		      (!list)
neuper@37906
   924
		      )
neuper@37906
   925
    end;
neuper@37906
   926
neuper@37906
   927
(*. converts a uv-polynomial from uv-representation to mv-representation .*)
neuper@37906
   928
fun uv_to_poly ([]:uv_poly) = []:mv_poly
neuper@37906
   929
  | uv_to_poly p1 = 
neuper@37906
   930
    let
neuper@37906
   931
	val count=ref 0;
neuper@37906
   932
	val help=ref p1;
neuper@37906
   933
	val list=ref [];
neuper@37906
   934
    in
neuper@37906
   935
	while length(!help)>0 do
neuper@37906
   936
	    (
neuper@37906
   937
	     if hd(!help)=0 then ()
neuper@37906
   938
	     else list:=(hd(!help),[!count])::(!list);
neuper@37906
   939
	     count:=(!count)+1;
neuper@37906
   940
	     help:=tl(!help)
neuper@37906
   941
	     );
neuper@37906
   942
	    (!list)
neuper@37906
   943
    end;
neuper@37906
   944
neuper@37906
   945
(*. univariate gcd calculation from polynomials in multivariate representation .*)
neuper@37906
   946
fun uv_gcd ([]:mv_poly) p2 = p2
neuper@37906
   947
  | uv_gcd p1 ([]:mv_poly) = p1
neuper@37906
   948
  | uv_gcd p1 [(c,[e])] = 
neuper@37906
   949
    let 
neuper@37906
   950
	val list=ref (rev(sort (mv_geq LEX_) (mv_shorten(p1,LEX_))));
neuper@37906
   951
	val min=uv_mod_min(e,(hd(#2(hd(rev(!list))))));
neuper@37906
   952
    in
neuper@37906
   953
	[(gcd_int (uv_content2(p1)) c,[min])]
neuper@37906
   954
    end
neuper@37906
   955
  | uv_gcd [(c,[e])] p2 = 
neuper@37906
   956
    let 
neuper@37906
   957
	val list=ref (rev(sort (mv_geq LEX_) (mv_shorten(p2,LEX_))));
neuper@37906
   958
	val min=uv_mod_min(e,(hd(#2(hd(rev(!list))))));
neuper@37906
   959
    in
neuper@37906
   960
	[(gcd_int (uv_content2(p2)) c,[min])]
neuper@37906
   961
    end 
neuper@37906
   962
  | uv_gcd p11 p22 = uv_to_poly(uv_mod_gcd (uv_to_list(mv_shorten(p11,LEX_))) (uv_to_list(mv_shorten(p22,LEX_))));
neuper@37906
   963
neuper@37906
   964
(*. help function for the newton interpolation .*)
neuper@37906
   965
fun mv_newton_help ([]:mv_poly list,k:int) = []:mv_poly list
neuper@37906
   966
  | mv_newton_help (pl:mv_poly list,k) = 
neuper@37906
   967
    let
neuper@37906
   968
	val x=ref (rev(pl));
neuper@37906
   969
	val t=ref [];
neuper@37906
   970
	val y=ref [];
neuper@37906
   971
	val n=ref 1;
neuper@37906
   972
	val n1=ref[];
neuper@37906
   973
    in
neuper@37906
   974
	(
neuper@37906
   975
	 while length(!x)>1 do 
neuper@37906
   976
	     (
neuper@37906
   977
	      if length(hd(!x))>0 then n1:=mv_null2(#2(hd(hd(!x))))
neuper@37906
   978
	      else if length(hd(tl(!x)))>0 then n1:=mv_null2(#2(hd(hd(tl(!x)))))
neuper@37906
   979
		   else n1:=[]; 
neuper@37906
   980
	      t:= #1(mv_division(mv_add(hd(!x),mv_skalar_mul(hd(tl(!x)),~1),LEX_),[(k,!n1)],LEX_)); 
neuper@37906
   981
	      y:=(!t)::(!y);
neuper@37906
   982
	      x:=tl(!x)
neuper@37906
   983
	      );
neuper@37906
   984
	 (!y)
neuper@37906
   985
	 )
neuper@37906
   986
    end;
neuper@37906
   987
    
neuper@37906
   988
(*. help function for the newton interpolation .*)
neuper@37906
   989
fun mv_newton_add ([]:mv_poly list) t = []:mv_poly
neuper@37906
   990
  | mv_newton_add [x:mv_poly] t = x 
neuper@37906
   991
  | mv_newton_add (pl:mv_poly list) t = 
neuper@37906
   992
    let
neuper@37906
   993
	val expos=ref [];
neuper@37906
   994
	val pll=ref pl;
neuper@37906
   995
    in
neuper@37906
   996
	(
neuper@37906
   997
neuper@37906
   998
	 while length(!pll)>0 andalso hd(!pll)=[]  do 
neuper@37906
   999
	     ( 
neuper@37906
  1000
	      pll:=tl(!pll)
neuper@37906
  1001
	      ); 
neuper@37906
  1002
	 if length(!pll)>0 then expos:= #2(hd(hd(!pll))) else expos:=[];
neuper@37906
  1003
	 mv_add(hd(pl),
neuper@37906
  1004
		mv_mul(
neuper@37906
  1005
		       mv_add(mv_correct(mv_cut([(1,mv_null2(!expos))]),1),[(~t,mv_null2(!expos))],LEX_),
neuper@37906
  1006
		       mv_newton_add (tl(pl)) (t+1),
neuper@37906
  1007
		       LEX_
neuper@37906
  1008
		       ),
neuper@37906
  1009
		LEX_)
neuper@37906
  1010
	 )
neuper@37906
  1011
    end;
neuper@37906
  1012
neuper@37906
  1013
(*. calculates the newton interpolation with polynomial coefficients .*)
neuper@37906
  1014
(*. step-depth is 1 and if the result is not an integerpolynomial .*)
neuper@37906
  1015
(*. this function returns [] .*)
neuper@37906
  1016
fun mv_newton ([]:(mv_poly) list) = []:mv_poly 
neuper@37906
  1017
  | mv_newton ([mp]:(mv_poly) list) = mp:mv_poly
neuper@37906
  1018
  | mv_newton pl =
neuper@37906
  1019
    let
neuper@37906
  1020
	val c=ref pl;
neuper@37906
  1021
	val c1=ref [];
neuper@37906
  1022
	val n=length(pl);
neuper@37906
  1023
	val k=ref 1;
neuper@37906
  1024
	val i=ref n;
neuper@37906
  1025
	val ppl=ref [];
neuper@37906
  1026
    in
neuper@37906
  1027
	c1:=hd(pl)::[];
neuper@37906
  1028
	c:=mv_newton_help(!c,!k);
neuper@37906
  1029
	c1:=(hd(!c))::(!c1);
neuper@37906
  1030
	while(length(!c)>1 andalso !k<n) do
neuper@37906
  1031
	    (	 
neuper@37906
  1032
	     k:=(!k)+1; 
neuper@37906
  1033
	     while  length(!c)>0 andalso hd(!c)=[] do c:=tl(!c); 	  
neuper@37906
  1034
	     if !c=[] then () else c:=mv_newton_help(!c,!k);
neuper@37906
  1035
	     ppl:= !c;
neuper@37906
  1036
	     if !c=[] then () else  c1:=(hd(!c))::(!c1)
neuper@37906
  1037
	     );
neuper@37906
  1038
	while  hd(!c1)=[] do c1:=tl(!c1);
neuper@37906
  1039
	c1:=rev(!c1);
neuper@37906
  1040
	ppl:= !c1;
neuper@37906
  1041
	mv_newton_add (!c1) 1
neuper@37906
  1042
    end;
neuper@37906
  1043
neuper@37906
  1044
(*. sets the exponents of the first variable to zero .*)
neuper@37906
  1045
fun mv_null3([]:mv_poly)    = []:mv_poly
neuper@37906
  1046
  | mv_null3((x,y)::xs) = (x,0::tl(y))::mv_null3(xs);
neuper@37906
  1047
neuper@37906
  1048
(*. calculates the minimum exponents of a multivariate polynomial .*)
neuper@37906
  1049
fun mv_min_pp([]:mv_poly)=[]
neuper@37906
  1050
  | mv_min_pp((c,e)::xs)=
neuper@37906
  1051
    let
neuper@37906
  1052
	val y=ref xs;
neuper@37906
  1053
	val x=ref [];
neuper@37906
  1054
    in
neuper@37906
  1055
	(
neuper@37906
  1056
	 x:=e;
neuper@37906
  1057
	 while length(!y)>0 do
neuper@37906
  1058
	     (
neuper@37906
  1059
	      x:=(map uv_mod_min) ((!x) ~~ (#2(hd(!y))));
neuper@37906
  1060
	      y:=tl(!y)
neuper@37906
  1061
	      );
neuper@37906
  1062
	 !x
neuper@37906
  1063
	 )
neuper@37906
  1064
    end;
neuper@37906
  1065
neuper@37906
  1066
(*. checks if all elements of the list have value zero .*)
neuper@37906
  1067
fun list_is_null [] = true 
neuper@37906
  1068
  | list_is_null (x::xs) = (x=0 andalso list_is_null(xs)); 
neuper@37906
  1069
neuper@37906
  1070
(* check if main variable is zero*)
neuper@37906
  1071
fun main_zero (ms : mv_poly) = (list_is_null o (map (hd o #2))) ms;
neuper@37906
  1072
neuper@37906
  1073
(*. calculates the content of an polynomial .*)
neuper@37906
  1074
fun mv_content([]:mv_poly) = []:mv_poly
neuper@37906
  1075
  | mv_content(p1) = 
neuper@37906
  1076
    let
neuper@37906
  1077
	val list=ref (rev(sort (mv_geq LEX_) (mv_shorten(p1,LEX_))));
neuper@37906
  1078
	val test=ref (hd(#2(hd(!list))));
neuper@37906
  1079
	val result=ref []; 
neuper@37906
  1080
	val min=(hd(#2(hd(rev(!list)))));
neuper@37906
  1081
    in
neuper@37906
  1082
	(
neuper@37906
  1083
	 if length(!list)>1 then
neuper@37906
  1084
	     (
neuper@37906
  1085
	      while (if length(!list)>0 then (hd(#2(hd(!list)))=(!test)) else false) do
neuper@37906
  1086
		  (
neuper@37906
  1087
		   result:=(#1(hd(!list)),tl(#2(hd(!list))))::(!result);
neuper@37906
  1088
		   
neuper@37906
  1089
		   if length(!list)<1 then list:=[]
neuper@37906
  1090
		   else list:=tl(!list) 
neuper@37906
  1091
		       
neuper@37906
  1092
		       );		  
neuper@37906
  1093
		  if length(!list)>0 then  
neuper@37906
  1094
		   ( 
neuper@37906
  1095
		    list:=mv_gcd (!result) (mv_cut(mv_content(!list))) 
neuper@37906
  1096
		    ) 
neuper@37906
  1097
		  else list:=(!result); 
neuper@37906
  1098
		  list:=mv_correct(!list,0);  
neuper@37906
  1099
		  (!list) 
neuper@37906
  1100
		  )
neuper@37906
  1101
	 else
neuper@37906
  1102
	     (
neuper@37906
  1103
	      mv_null3(!list) 
neuper@37906
  1104
	      )
neuper@37906
  1105
	     )
neuper@37906
  1106
    end
neuper@37906
  1107
neuper@37906
  1108
(*. calculates the primitiv part of a polynomial .*)
neuper@37906
  1109
and mv_pp([]:mv_poly) = []:mv_poly
neuper@37906
  1110
  | mv_pp(p1) = let
neuper@37906
  1111
		    val cont=ref []; 
neuper@37906
  1112
		    val pp=ref[];
neuper@37906
  1113
		in
neuper@37906
  1114
		    cont:=mv_content(p1);
neuper@37906
  1115
		    pp:=(#1(mv_division(p1,!cont,LEX_)));
neuper@37906
  1116
		    if !pp=[] 
neuper@37906
  1117
			then raise error("RATIONALS_MV_PP_EXCEPTION: Invalid Content ")
neuper@37906
  1118
		    else (!pp)
neuper@37906
  1119
		end
neuper@37906
  1120
neuper@37906
  1121
(*. calculates the gcd of two multivariate polynomials with a modular approach .*)
neuper@37906
  1122
and mv_gcd ([]:mv_poly) ([]:mv_poly) :mv_poly= []:mv_poly
neuper@37906
  1123
  | mv_gcd ([]:mv_poly) (p2) :mv_poly= p2:mv_poly
neuper@37906
  1124
  | mv_gcd (p1:mv_poly) ([]) :mv_poly= p1:mv_poly
neuper@37906
  1125
  | mv_gcd ([(x,xs)]:mv_poly) ([(y,ys)]):mv_poly = 
neuper@37906
  1126
     let
neuper@37906
  1127
      val xpoly:mv_poly = [(x,xs)];
neuper@37906
  1128
      val ypoly:mv_poly = [(y,ys)];
neuper@37906
  1129
     in 
neuper@37906
  1130
	(
neuper@37906
  1131
	 if xs=ys then [((gcd_int x y),xs)]
neuper@37906
  1132
	 else [((gcd_int x y),(map uv_mod_min)(xs~~ys))]:mv_poly
neuper@37906
  1133
        )
neuper@37906
  1134
    end 
neuper@37906
  1135
  | mv_gcd (p1:mv_poly) ([(y,ys)]) :mv_poly= 
neuper@37906
  1136
	(
neuper@37906
  1137
	 [(gcd_int (uv_content2(p1)) (y),(map  uv_mod_min)(mv_min_pp(p1)~~ys))]:mv_poly
neuper@37906
  1138
	)
neuper@37906
  1139
  | mv_gcd ([(y,ys)]:mv_poly) (p2):mv_poly = 
neuper@37906
  1140
	(
neuper@37906
  1141
         [(gcd_int (uv_content2(p2)) (y),(map  uv_mod_min)(mv_min_pp(p2)~~ys))]:mv_poly
neuper@37906
  1142
        )
neuper@37906
  1143
  | mv_gcd (p1':mv_poly) (p2':mv_poly):mv_poly=
neuper@37906
  1144
    let
neuper@37906
  1145
	val vc=length(#2(hd(p1')));
neuper@37906
  1146
	val cont = 
neuper@37906
  1147
		  (
neuper@37906
  1148
                   if main_zero(mv_content(p1')) andalso 
neuper@37906
  1149
                     (main_zero(mv_content(p2'))) then
neuper@37906
  1150
                     mv_correct((mv_gcd (mv_cut(mv_content(p1'))) (mv_cut(mv_content(p2')))),0)
neuper@37906
  1151
                   else 
neuper@37906
  1152
                     mv_gcd (mv_content(p1')) (mv_content(p2'))
neuper@37906
  1153
                  );
neuper@37906
  1154
	val p1= #1(mv_division(p1',mv_content(p1'),LEX_));
neuper@37906
  1155
	val p2= #1(mv_division(p2',mv_content(p2'),LEX_)); 
neuper@37906
  1156
	val gcd=ref [];
neuper@37906
  1157
	val candidate=ref [];
neuper@37906
  1158
	val interpolation_list=ref [];
neuper@37906
  1159
	val delta=ref [];
neuper@37906
  1160
        val p1r = ref [];
neuper@37906
  1161
        val p2r = ref [];
neuper@37906
  1162
        val p1r' = ref [];
neuper@37906
  1163
        val p2r' = ref [];
neuper@37906
  1164
	val factor=ref [];
neuper@37906
  1165
	val r=ref 0;
neuper@37906
  1166
	val gcd_r=ref [];
neuper@37906
  1167
	val d=ref 0;
neuper@37906
  1168
	val exit=ref 0;
neuper@37906
  1169
	val current_degree=ref 99999; (*. FIXME: unlimited ! .*)
neuper@37906
  1170
    in
neuper@37906
  1171
	(
neuper@37906
  1172
	 if vc<2 then (* areUnivariate(p1',p2') *)
neuper@37906
  1173
	     (
neuper@37906
  1174
	      gcd:=uv_gcd (mv_shorten(p1',LEX_)) (mv_shorten(p2',LEX_))
neuper@37906
  1175
	      )
neuper@37906
  1176
	 else
neuper@37906
  1177
	     (
neuper@37906
  1178
	      while !exit=0 do
neuper@37906
  1179
		  (
neuper@37906
  1180
		   r:=(!r)+1;
neuper@37906
  1181
                   p1r := mv_lc(p1,LEX_);
neuper@37906
  1182
		   p2r := mv_lc(p2,LEX_);
neuper@37906
  1183
                   if main_zero(!p1r) andalso
neuper@37906
  1184
                      main_zero(!p2r) 
neuper@37906
  1185
                   then
neuper@37906
  1186
                       (
neuper@37906
  1187
                        delta := mv_correct((mv_gcd (mv_cut (!p1r)) (mv_cut (!p2r))),0)
neuper@37906
  1188
                       )
neuper@37906
  1189
                   else
neuper@37906
  1190
                       (
neuper@37906
  1191
		        delta := mv_gcd (!p1r) (!p2r)
neuper@37906
  1192
                       );
neuper@37906
  1193
		   (*if mv_shorten(mv_subs(!p1r,!r),LEX_)=[] andalso 
neuper@37906
  1194
		      mv_shorten(mv_subs(!p2r,!r),LEX_)=[] *)
neuper@37906
  1195
		   if mv_lc2(mv_shorten(mv_subs(!p1r,!r),LEX_),LEX_)=0 andalso 
neuper@37906
  1196
		      mv_lc2(mv_shorten(mv_subs(!p2r,!r),LEX_),LEX_)=0 
neuper@37906
  1197
                   then 
neuper@37906
  1198
                       (
neuper@37906
  1199
		       )
neuper@37906
  1200
		   else 
neuper@37906
  1201
		       (
neuper@37906
  1202
			gcd_r:=mv_shorten(mv_gcd (mv_shorten(mv_subs(p1,!r),LEX_)) 
neuper@37906
  1203
					         (mv_shorten(mv_subs(p2,!r),LEX_)) ,LEX_);
neuper@37906
  1204
			gcd_r:= #1(mv_division(mv_mul(mv_correct(mv_subs(!delta,!r),0),!gcd_r,LEX_),
neuper@37906
  1205
					       mv_correct(mv_lc(!gcd_r,LEX_),0),LEX_));
neuper@37906
  1206
			d:=mv_deg2(!gcd_r); (* deg(gcd_r,z) *)
neuper@37906
  1207
			if (!d < !current_degree) then 
neuper@37906
  1208
			    (
neuper@37906
  1209
			     current_degree:= !d;
neuper@37906
  1210
			     interpolation_list:=mv_correct(!gcd_r,0)::(!interpolation_list)
neuper@37906
  1211
			     )
neuper@37906
  1212
			else
neuper@37906
  1213
			    (
neuper@37906
  1214
			     if (!d = !current_degree) then
neuper@37906
  1215
				 (
neuper@37906
  1216
				  interpolation_list:=mv_correct(!gcd_r,0)::(!interpolation_list)
neuper@37906
  1217
				  )
neuper@37906
  1218
			     else () 
neuper@37906
  1219
				 )
neuper@37906
  1220
			    );
neuper@37906
  1221
		      if length(!interpolation_list)> uv_mod_min(mv_deg(p1),mv_deg(p2)) then 
neuper@37906
  1222
			  (
neuper@37906
  1223
			   candidate := mv_newton(rev(!interpolation_list));
neuper@37906
  1224
			   if !candidate=[] then ()
neuper@37906
  1225
			   else
neuper@37906
  1226
			       (
neuper@37906
  1227
				candidate:=mv_pp(!candidate);
neuper@37906
  1228
				if mv_divides(!candidate,p1) andalso mv_divides(!candidate,p2) then
neuper@37906
  1229
				    (
neuper@37906
  1230
				     gcd:= mv_mul(!candidate,cont,LEX_);
neuper@37906
  1231
				     exit:=1
neuper@37906
  1232
				     )
neuper@37906
  1233
				else ()
neuper@37906
  1234
				    );
neuper@37906
  1235
			       interpolation_list:=[mv_correct(!gcd_r,0)]
neuper@37906
  1236
			       )
neuper@37906
  1237
		      else ()
neuper@37906
  1238
			  )
neuper@37906
  1239
	     );
neuper@37906
  1240
	     (!gcd):mv_poly
neuper@37906
  1241
	     )
neuper@37906
  1242
    end;	
neuper@37906
  1243
neuper@37906
  1244
neuper@37906
  1245
(*. calculates the least common divisor of two polynomials .*)
neuper@37906
  1246
fun mv_lcm (p1:mv_poly) (p2:mv_poly) :mv_poly = 
neuper@37906
  1247
    (
neuper@37906
  1248
     #1(mv_division(mv_mul(p1,p2,LEX_),mv_gcd p1 p2,LEX_))
neuper@37906
  1249
     );
neuper@37906
  1250
neuper@37906
  1251
(*. gets the variables (strings) of a term .*)
neuper@37906
  1252
fun get_vars(term1) = (map free2str) (vars term1); (*["a","b","c"]; *)
neuper@37906
  1253
neuper@37906
  1254
(*. counts the negative coefficents in a polynomial .*)
neuper@37906
  1255
fun count_neg ([]:mv_poly) = 0 
neuper@37906
  1256
  | count_neg ((c,e)::xs) = if c<0 then 1+count_neg xs
neuper@37906
  1257
			  else count_neg xs;
neuper@37906
  1258
neuper@37906
  1259
(*. help function for is_polynomial  
neuper@37906
  1260
    checks the order of the operators .*)
neuper@37906
  1261
fun test_polynomial (Const ("uminus",_) $ Free (str,_)) _ = true (*WN.13.3.03*)
neuper@37906
  1262
  | test_polynomial (t as Free(str,_)) v = true
neuper@37906
  1263
  | test_polynomial (t as Const ("op *",_) $ t1 $ t2) v = if v="^" then false
neuper@37906
  1264
						     else (test_polynomial t1 "*") andalso (test_polynomial t2 "*")
neuper@37906
  1265
  | test_polynomial (t as Const ("op +",_) $ t1 $ t2) v = if v="*" orelse v="^" then false 
neuper@37906
  1266
							  else (test_polynomial t1 " ") andalso (test_polynomial t2 " ")
neuper@37906
  1267
  | test_polynomial (t as Const ("Atools.pow",_) $ t1 $ t2) v = (test_polynomial t1 "^") andalso (test_polynomial t2 "^")
neuper@37906
  1268
  | test_polynomial _ v = false;  
neuper@37906
  1269
neuper@37906
  1270
(*. tests if a term is a polynomial .*)  
neuper@37906
  1271
fun is_polynomial t = test_polynomial t " ";
neuper@37906
  1272
neuper@37906
  1273
(*. help function for is_expanded 
neuper@37906
  1274
    checks the order of the operators .*)
neuper@37906
  1275
fun test_exp (t as Free(str,_)) v = true 
neuper@37906
  1276
  | test_exp (t as Const ("op *",_) $ t1 $ t2) v = if v="^" then false
neuper@37906
  1277
						     else (test_exp t1 "*") andalso (test_exp t2 "*")
neuper@37906
  1278
  | test_exp (t as Const ("op +",_) $ t1 $ t2) v = if v="*" orelse v="^" then false 
neuper@37906
  1279
							  else (test_exp t1 " ") andalso (test_exp t2 " ") 
neuper@37906
  1280
  | test_exp (t as Const ("op -",_) $ t1 $ t2) v = if v="*" orelse v="^" then false 
neuper@37906
  1281
							  else (test_exp t1 " ") andalso (test_exp t2 " ")
neuper@37906
  1282
  | test_exp (t as Const ("Atools.pow",_) $ t1 $ t2) v = (test_exp t1 "^") andalso (test_exp t2 "^")
neuper@37906
  1283
  | test_exp  _ v = false;
neuper@37906
  1284
neuper@37906
  1285
neuper@37906
  1286
(*. help function for check_coeff: 
neuper@37906
  1287
    converts the term to a list of coefficients .*) 
neuper@37906
  1288
fun term2coef' (t as Free(str,_(*typ*))) v :mv_poly option = 
neuper@37906
  1289
    let
neuper@37926
  1290
	val x=ref NONE;
neuper@37906
  1291
	val len=ref 0;
neuper@37906
  1292
	val vl=ref [];
neuper@37906
  1293
	val vh=ref [];
neuper@37906
  1294
	val i=ref 0;
neuper@37906
  1295
    in 
neuper@37906
  1296
	if is_numeral str then
neuper@37906
  1297
	    (
neuper@37926
  1298
	     SOME [(((the o int_of_str) str),mv_null2(v))] handle _ => NONE
neuper@37906
  1299
		 )
neuper@37906
  1300
	else (* variable *)
neuper@37906
  1301
	    (
neuper@37906
  1302
	     len:=length(v);
neuper@37906
  1303
	     vh:=v;
neuper@37906
  1304
	     while ((!len)>(!i)) do
neuper@37906
  1305
		 (
neuper@37906
  1306
		  if str=hd((!vh)) then
neuper@37906
  1307
		      (
neuper@37906
  1308
		       vl:=1::(!vl)
neuper@37906
  1309
		       )
neuper@37906
  1310
		  else 
neuper@37906
  1311
		      (
neuper@37906
  1312
		       vl:=0::(!vl)
neuper@37906
  1313
		       );
neuper@37906
  1314
		      vh:=tl(!vh);
neuper@37906
  1315
		      i:=(!i)+1    
neuper@37906
  1316
		      );		
neuper@37926
  1317
		 SOME [(1,rev(!vl))] handle _ => NONE
neuper@37906
  1318
	    )
neuper@37906
  1319
    end
neuper@37906
  1320
  | term2coef' (Const ("op *",_) $ t1 $ t2) v :mv_poly option= 
neuper@37906
  1321
    let
neuper@37906
  1322
	val t1pp=ref [];
neuper@37906
  1323
	val t2pp=ref [];
neuper@37906
  1324
	val t1c=ref 0;
neuper@37906
  1325
	val t2c=ref 0;
neuper@37906
  1326
    in
neuper@37906
  1327
	(
neuper@37906
  1328
	 t1pp:=(#2(hd(the(term2coef' t1 v))));
neuper@37906
  1329
	 t2pp:=(#2(hd(the(term2coef' t2 v))));
neuper@37906
  1330
	 t1c:=(#1(hd(the(term2coef' t1 v))));
neuper@37906
  1331
	 t2c:=(#1(hd(the(term2coef' t2 v))));
neuper@37906
  1332
	
neuper@37926
  1333
	 SOME [( (!t1c)*(!t2c) ,( (map op+) ((!t1pp)~~(!t2pp)) ) )] handle _ => NONE 
neuper@37906
  1334
		
neuper@37906
  1335
	 )
neuper@37906
  1336
    end
neuper@37906
  1337
  | term2coef' (Const ("Atools.pow",_) $ (t1 as Free (str1,_)) $ (t2 as Free (str2,_))) v :mv_poly option= 
neuper@37906
  1338
    let
neuper@37926
  1339
	val x=ref NONE;
neuper@37906
  1340
	val len=ref 0;
neuper@37906
  1341
	val vl=ref [];
neuper@37906
  1342
	val vh=ref [];
neuper@37906
  1343
	val vtemp=ref [];
neuper@37906
  1344
	val i=ref 0;	 
neuper@37906
  1345
    in
neuper@37906
  1346
    (
neuper@37906
  1347
     if (not o is_numeral) str1 andalso is_numeral str2 then
neuper@37906
  1348
	 (
neuper@37906
  1349
	  len:=length(v);
neuper@37906
  1350
	  vh:=v;
neuper@37906
  1351
neuper@37906
  1352
	  while ((!len)>(!i)) do
neuper@37906
  1353
	      (
neuper@37906
  1354
	       if str1=hd((!vh)) then
neuper@37906
  1355
		   (
neuper@37906
  1356
		    vl:=((the o int_of_str) str2)::(!vl)
neuper@37906
  1357
		    )
neuper@37906
  1358
	       else 
neuper@37906
  1359
		   (
neuper@37906
  1360
		    vl:=0::(!vl)
neuper@37906
  1361
		    );
neuper@37906
  1362
		   vh:=tl(!vh);
neuper@37906
  1363
		   i:=(!i)+1     
neuper@37906
  1364
		   );
neuper@37926
  1365
	      SOME [(1,rev(!vl))] handle _ => NONE
neuper@37906
  1366
	      )
neuper@37906
  1367
     else raise error ("RATIONALS_TERM2COEF_EXCEPTION 1: Invalid term")
neuper@37906
  1368
	 )
neuper@37906
  1369
    end
neuper@37906
  1370
  | term2coef' (Const ("op +",_) $ t1 $ t2) v :mv_poly option= 
neuper@37906
  1371
    (
neuper@37926
  1372
     SOME ((the(term2coef' t1 v)) @ (the(term2coef' t2 v))) handle _ => NONE
neuper@37906
  1373
	 )
neuper@37906
  1374
  | term2coef' (Const ("op -",_) $ t1 $ t2) v :mv_poly option= 
neuper@37906
  1375
    (
neuper@37926
  1376
     SOME ((the(term2coef' t1 v)) @ mv_skalar_mul((the(term2coef' t2 v)),1)) handle _ => NONE
neuper@37906
  1377
	 )
neuper@37906
  1378
  | term2coef' (term) v = raise error ("RATIONALS_TERM2COEF_EXCEPTION 2: Invalid term");
neuper@37906
  1379
neuper@37906
  1380
(*. checks if all coefficients of a polynomial are positiv (except the first) .*)
neuper@37906
  1381
fun check_coeff t = (* erste Koeffizient kann <0 sein !!! *)
neuper@37906
  1382
    if count_neg(tl(the(term2coef' t (get_vars(t)))))=0 then true 
neuper@37906
  1383
    else false;
neuper@37906
  1384
neuper@37906
  1385
(*. checks for expanded term [3] .*)
neuper@37906
  1386
fun is_expanded t = test_exp t " " andalso check_coeff(t); 
neuper@37906
  1387
neuper@37906
  1388
(*WN.7.3.03 Hilfsfunktion f"ur term2poly'*)
neuper@37906
  1389
fun mk_monom v' p vs = 
neuper@37906
  1390
    let fun conv p (v: string) = if v'= v then p else 0
neuper@37906
  1391
    in map (conv p) vs end;
neuper@37906
  1392
(* mk_monom "y" 5 ["a","b","x","y","z"];
neuper@37906
  1393
val it = [0,0,0,5,0] : int list*)
neuper@37906
  1394
neuper@37906
  1395
(*. this function converts the term representation into the internal representation mv_poly .*)
neuper@37906
  1396
fun term2poly' (Const ("uminus",_) $ Free (str,_)) v = (*WN.7.3.03*)
neuper@37906
  1397
    if is_numeral str 
neuper@37926
  1398
    then SOME [((the o int_of_str) ("-"^str), mk_monom "#" 0 v)]
neuper@37926
  1399
    else SOME [(~1, mk_monom str 1 v)]
neuper@37906
  1400
neuper@37906
  1401
  | term2poly' (Free(str,_)) v :mv_poly option = 
neuper@37906
  1402
    let
neuper@37926
  1403
	val x=ref NONE;
neuper@37906
  1404
	val len=ref 0;
neuper@37906
  1405
	val vl=ref [];
neuper@37906
  1406
	val vh=ref [];
neuper@37906
  1407
	val i=ref 0;
neuper@37906
  1408
    in 
neuper@37906
  1409
	if is_numeral str then
neuper@37906
  1410
	    (
neuper@37926
  1411
	     SOME [(((the o int_of_str) str),mv_null2 v)] handle _ => NONE
neuper@37906
  1412
		 )
neuper@37906
  1413
	else (* variable *)
neuper@37906
  1414
	    (
neuper@37906
  1415
	     len:=length v;
neuper@37906
  1416
	     vh:= v;
neuper@37906
  1417
	     while ((!len)>(!i)) do
neuper@37906
  1418
		 (
neuper@37906
  1419
		  if str=hd((!vh)) then
neuper@37906
  1420
		      (
neuper@37906
  1421
		       vl:=1::(!vl)
neuper@37906
  1422
		       )
neuper@37906
  1423
		  else 
neuper@37906
  1424
		      (
neuper@37906
  1425
		       vl:=0::(!vl)
neuper@37906
  1426
		       );
neuper@37906
  1427
		      vh:=tl(!vh);
neuper@37906
  1428
		      i:=(!i)+1    
neuper@37906
  1429
		      );		
neuper@37926
  1430
		 SOME [(1,rev(!vl))] handle _ => NONE
neuper@37906
  1431
	    )
neuper@37906
  1432
    end
neuper@37906
  1433
  | term2poly' (Const ("op *",_) $ t1 $ t2) v :mv_poly option= 
neuper@37906
  1434
    let
neuper@37906
  1435
	val t1pp=ref [];
neuper@37906
  1436
	val t2pp=ref [];
neuper@37906
  1437
	val t1c=ref 0;
neuper@37906
  1438
	val t2c=ref 0;
neuper@37906
  1439
    in
neuper@37906
  1440
	(
neuper@37906
  1441
	 t1pp:=(#2(hd(the(term2poly' t1 v))));
neuper@37906
  1442
	 t2pp:=(#2(hd(the(term2poly' t2 v))));
neuper@37906
  1443
	 t1c:=(#1(hd(the(term2poly' t1 v))));
neuper@37906
  1444
	 t2c:=(#1(hd(the(term2poly' t2 v))));
neuper@37906
  1445
	
neuper@37926
  1446
	 SOME [( (!t1c)*(!t2c) ,( (map op+) ((!t1pp)~~(!t2pp)) ) )] 
neuper@37926
  1447
	 handle _ => NONE 
neuper@37906
  1448
		
neuper@37906
  1449
	 )
neuper@37906
  1450
    end
neuper@37906
  1451
  | term2poly' (Const ("Atools.pow",_) $ (t1 as Free (str1,_)) $ 
neuper@37906
  1452
		      (t2 as Free (str2,_))) v :mv_poly option= 
neuper@37906
  1453
    let
neuper@37926
  1454
	val x=ref NONE;
neuper@37906
  1455
	val len=ref 0;
neuper@37906
  1456
	val vl=ref [];
neuper@37906
  1457
	val vh=ref [];
neuper@37906
  1458
	val vtemp=ref [];
neuper@37906
  1459
	val i=ref 0;	 
neuper@37906
  1460
    in
neuper@37906
  1461
    (
neuper@37906
  1462
     if (not o is_numeral) str1 andalso is_numeral str2 then
neuper@37906
  1463
	 (
neuper@37906
  1464
	  len:=length(v);
neuper@37906
  1465
	  vh:=v;
neuper@37906
  1466
neuper@37906
  1467
	  while ((!len)>(!i)) do
neuper@37906
  1468
	      (
neuper@37906
  1469
	       if str1=hd((!vh)) then
neuper@37906
  1470
		   (
neuper@37906
  1471
		    vl:=((the o int_of_str) str2)::(!vl)
neuper@37906
  1472
		    )
neuper@37906
  1473
	       else 
neuper@37906
  1474
		   (
neuper@37906
  1475
		    vl:=0::(!vl)
neuper@37906
  1476
		    );
neuper@37906
  1477
		   vh:=tl(!vh);
neuper@37906
  1478
		   i:=(!i)+1     
neuper@37906
  1479
		   );
neuper@37926
  1480
	      SOME [(1,rev(!vl))] handle _ => NONE
neuper@37906
  1481
	      )
neuper@37906
  1482
     else raise error ("RATIONALS_TERM2POLY_EXCEPTION 1: Invalid term")
neuper@37906
  1483
	 )
neuper@37906
  1484
    end
neuper@37906
  1485
  | term2poly' (Const ("op +",_) $ t1 $ t2) v :mv_poly option = 
neuper@37906
  1486
    (
neuper@37926
  1487
     SOME ((the(term2poly' t1 v)) @ (the(term2poly' t2 v))) handle _ => NONE
neuper@37906
  1488
	 )
neuper@37906
  1489
  | term2poly' (Const ("op -",_) $ t1 $ t2) v :mv_poly option = 
neuper@37906
  1490
    (
neuper@37926
  1491
     SOME ((the(term2poly' t1 v)) @ mv_skalar_mul((the(term2poly' t2 v)),~1)) handle _ => NONE
neuper@37906
  1492
	 )
neuper@37906
  1493
  | term2poly' (term) v = raise error ("RATIONALS_TERM2POLY_EXCEPTION 2: Invalid term");
neuper@37906
  1494
neuper@37906
  1495
(*. translates an Isabelle term into internal representation.
neuper@37906
  1496
    term2poly
neuper@37906
  1497
    fn : term ->              (*normalform [2]                    *)
neuper@37906
  1498
    	 string list ->       (*for ...!!! BITTE DIE ERKLÄRUNG, 
neuper@37906
  1499
    			       DIE DU MIR LETZTES MAL GEGEBEN HAST*)
neuper@37906
  1500
    	 mv_monom list        (*internal representation           *)
neuper@37926
  1501
    		  option      (*the translation may fail with NONE*)
neuper@37906
  1502
.*)
neuper@37906
  1503
fun term2poly (t:term) v = 
neuper@37906
  1504
     if is_polynomial t then term2poly' t v
neuper@37906
  1505
     else raise error ("term2poly: invalid = "^(term2str t));
neuper@37906
  1506
neuper@37906
  1507
(*. same as term2poly with automatic detection of the variables .*)
neuper@37906
  1508
fun term2polyx t = term2poly t (((map free2str) o vars) t); 
neuper@37906
  1509
neuper@37906
  1510
(*. checks if the term is in expanded polynomial form and converts it into the internal representation .*)
neuper@37906
  1511
fun expanded2poly (t:term) v = 
neuper@37906
  1512
    (*if is_expanded t then*) term2poly' t v
neuper@37906
  1513
    (*else raise error ("RATIONALS_EXPANDED2POLY_EXCEPTION: Invalid Polynomial")*);
neuper@37906
  1514
neuper@37906
  1515
(*. same as expanded2poly with automatic detection of the variables .*)
neuper@37906
  1516
fun expanded2polyx t = expanded2poly t (((map free2str) o vars) t);
neuper@37906
  1517
neuper@37906
  1518
(*. converts a powerproduct into term representation .*)
neuper@37906
  1519
fun powerproduct2term(xs,v) =  
neuper@37906
  1520
    let
neuper@37906
  1521
	val xss=ref xs;
neuper@37906
  1522
	val vv=ref v;
neuper@37906
  1523
    in
neuper@37906
  1524
	(
neuper@37906
  1525
	 while hd(!xss)=0 do 
neuper@37906
  1526
	     (
neuper@37906
  1527
	      xss:=tl(!xss);
neuper@37906
  1528
	      vv:=tl(!vv)
neuper@37906
  1529
	      );
neuper@37906
  1530
	     
neuper@37906
  1531
	 if list_is_null(tl(!xss)) then 
neuper@37906
  1532
	     (
neuper@37906
  1533
	      if hd(!xss)=1 then Free(hd(!vv), HOLogic.realT)
neuper@37906
  1534
	      else
neuper@37906
  1535
		  (
neuper@37906
  1536
		   Const("Atools.pow",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  1537
		   Free(hd(!vv), HOLogic.realT) $  Free(str_of_int (hd(!xss)),HOLogic.realT)
neuper@37906
  1538
		   )
neuper@37906
  1539
	      )
neuper@37906
  1540
	 else
neuper@37906
  1541
	     (
neuper@37906
  1542
	      if hd(!xss)=1 then 
neuper@37906
  1543
		  ( 
neuper@37906
  1544
		   Const("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  1545
		   Free(hd(!vv), HOLogic.realT) $
neuper@37906
  1546
		   powerproduct2term(tl(!xss),tl(!vv))
neuper@37906
  1547
		   )
neuper@37906
  1548
	      else
neuper@37906
  1549
		  (
neuper@37906
  1550
		   Const("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  1551
		   (
neuper@37906
  1552
		    Const("Atools.pow",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  1553
		    Free(hd(!vv), HOLogic.realT) $  Free(str_of_int (hd(!xss)),HOLogic.realT)
neuper@37906
  1554
		    ) $
neuper@37906
  1555
		    powerproduct2term(tl(!xss),tl(!vv))
neuper@37906
  1556
		   )
neuper@37906
  1557
	      )
neuper@37906
  1558
	 )
neuper@37906
  1559
    end;
neuper@37906
  1560
neuper@37906
  1561
(*. converts a monom into term representation .*)
neuper@37906
  1562
(*fun monom2term ((c,e):mv_monom, v:string list) = 
neuper@37906
  1563
    if c=0 then Free(str_of_int 0,HOLogic.realT)  
neuper@37906
  1564
    else
neuper@37906
  1565
	(
neuper@37906
  1566
	 if list_is_null(e) then
neuper@37906
  1567
	     ( 
neuper@37906
  1568
	      Free(str_of_int c,HOLogic.realT)  
neuper@37906
  1569
	      )
neuper@37906
  1570
	 else
neuper@37906
  1571
	     (
neuper@37906
  1572
	      if c=1 then 
neuper@37906
  1573
		  (
neuper@37906
  1574
		   powerproduct2term(e,v)
neuper@37906
  1575
		   )
neuper@37906
  1576
	      else
neuper@37906
  1577
		  (
neuper@37906
  1578
		   Const("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
neuper@37906
  1579
		   Free(str_of_int c,HOLogic.realT)  $
neuper@37906
  1580
		   powerproduct2term(e,v)
neuper@37906
  1581
		   )
neuper@37906
  1582
		  )
neuper@37906
  1583
	     );*)
neuper@37906
  1584
neuper@37906
  1585
neuper@37906
  1586
(*fun monom2term ((i, is):mv_monom, v) = 
neuper@37906
  1587
    if list_is_null is 
neuper@37906
  1588
    then 
neuper@37906
  1589
	if i >= 0 
neuper@37906
  1590
	then Free (str_of_int i, HOLogic.realT)
neuper@37906
  1591
	else Const ("uminus", HOLogic.realT --> HOLogic.realT) $
neuper@37906
  1592
		   Free ((str_of_int o abs) i, HOLogic.realT)
neuper@37906
  1593
    else
neuper@37906
  1594
	if i > 0 
neuper@37906
  1595
	then Const ("op *", [HOLogic.realT,HOLogic.realT]---> HOLogic.realT) $
neuper@37906
  1596
		   (Free (str_of_int i, HOLogic.realT)) $
neuper@37906
  1597
		   powerproduct2term(is, v)
neuper@37906
  1598
	else Const ("op *", [HOLogic.realT,HOLogic.realT]---> HOLogic.realT) $
neuper@37906
  1599
		   (Const ("uminus", HOLogic.realT --> HOLogic.realT) $
neuper@37906
  1600
		   Free ((str_of_int o abs) i, HOLogic.realT)) $
neuper@37906
  1601
		   powerproduct2term(is, vs);---------------------------*)
neuper@37906
  1602
fun monom2term ((i, is) : mv_monom, vs) = 
neuper@37906
  1603
    if list_is_null is 
neuper@37906
  1604
    then Free (str_of_int i, HOLogic.realT)
neuper@37906
  1605
    else if i = 1
neuper@37906
  1606
    then powerproduct2term (is, vs)
neuper@37906
  1607
    else Const ("op *", [HOLogic.realT, HOLogic.realT] ---> HOLogic.realT) $
neuper@37906
  1608
	       (Free (str_of_int i, HOLogic.realT)) $
neuper@37906
  1609
	       powerproduct2term (is, vs);
neuper@37906
  1610
    
neuper@37906
  1611
(*. converts the internal polynomial representation into an Isabelle term.*)
neuper@37906
  1612
fun poly2term' ([] : mv_poly, vs) = Free(str_of_int 0, HOLogic.realT)  
neuper@37906
  1613
  | poly2term' ([(c, e) : mv_monom], vs) = monom2term ((c, e), vs)
neuper@37906
  1614
  | poly2term' ((c, e) :: ces, vs) =  
neuper@37906
  1615
    Const("op +", [HOLogic.realT, HOLogic.realT] ---> HOLogic.realT) $
neuper@37906
  1616
         poly2term (ces, vs) $ monom2term ((c, e), vs)
neuper@37906
  1617
and poly2term (xs, vs) = poly2term' (rev (sort (mv_geq LEX_) (xs)), vs);
neuper@37906
  1618
neuper@37906
  1619
neuper@37906
  1620
(*. converts a monom into term representation .*)
neuper@37906
  1621
(*. ignores the sign of the coefficients => use only for exp-poly functions .*)
neuper@37906
  1622
fun monom2term2((c,e):mv_monom, v:string list) =  
neuper@37906
  1623
    if c=0 then Free(str_of_int 0,HOLogic.realT)  
neuper@37906
  1624
    else
neuper@37906
  1625
	(
neuper@37906
  1626
	 if list_is_null(e) then
neuper@37906
  1627
	     ( 
neuper@37906
  1628
	      Free(str_of_int (abs(c)),HOLogic.realT)  
neuper@37906
  1629
	      )
neuper@37906
  1630
	 else
neuper@37906
  1631
	     (
neuper@37906
  1632
	      if abs(c)=1 then 
neuper@37906
  1633
		  (
neuper@37906
  1634
		   powerproduct2term(e,v)
neuper@37906
  1635
		   )
neuper@37906
  1636
	      else
neuper@37906
  1637
		  (
neuper@37906
  1638
		   Const("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
neuper@37906
  1639
		   Free(str_of_int (abs(c)),HOLogic.realT)  $
neuper@37906
  1640
		   powerproduct2term(e,v)
neuper@37906
  1641
		   )
neuper@37906
  1642
		  )
neuper@37906
  1643
	     );
neuper@37906
  1644
neuper@37906
  1645
(*. converts the expanded polynomial representation into the term representation .*)
neuper@37906
  1646
fun exp2term' ([]:mv_poly,vars) =  Free(str_of_int 0,HOLogic.realT)  
neuper@37906
  1647
  | exp2term' ([(c,e)],vars) =     monom2term((c,e),vars) 			     
neuper@37906
  1648
  | exp2term' ((c1,e1)::others,vars) =  
neuper@37906
  1649
    if c1<0 then 	
neuper@37906
  1650
	Const("op -",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
neuper@37906
  1651
	exp2term'(others,vars) $
neuper@37906
  1652
	( 
neuper@37906
  1653
	 monom2term2((c1,e1),vars)
neuper@37906
  1654
	 ) 
neuper@37906
  1655
    else
neuper@37906
  1656
	Const("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
neuper@37906
  1657
	exp2term'(others,vars) $
neuper@37906
  1658
	( 
neuper@37906
  1659
	 monom2term2((c1,e1),vars)
neuper@37906
  1660
	 );
neuper@37906
  1661
	
neuper@37906
  1662
(*. sorts the powerproduct by lexicographic termorder and converts them into 
neuper@37906
  1663
    a term in polynomial representation .*)
neuper@37906
  1664
fun poly2expanded (xs,vars) = exp2term'(rev(sort (mv_geq LEX_) (xs)),vars);
neuper@37906
  1665
neuper@37906
  1666
(*. converts a polynomial into expanded form .*)
neuper@37906
  1667
fun polynomial2expanded t =  
neuper@37906
  1668
    (let 
neuper@37906
  1669
	val vars=(((map free2str) o vars) t);
neuper@37906
  1670
    in
neuper@37926
  1671
	SOME (poly2expanded (the (term2poly t vars), vars))
neuper@37926
  1672
    end) handle _ => NONE;
neuper@37906
  1673
neuper@37906
  1674
(*. converts a polynomial into polynomial form .*)
neuper@37906
  1675
fun expanded2polynomial t =  
neuper@37906
  1676
    (let 
neuper@37906
  1677
	val vars=(((map free2str) o vars) t);
neuper@37906
  1678
    in
neuper@37926
  1679
	SOME (poly2term (the (expanded2poly t vars), vars))
neuper@37926
  1680
    end) handle _ => NONE;
neuper@37906
  1681
neuper@37906
  1682
neuper@37906
  1683
(*. calculates the greatest common divisor of numerator and denominator and seperates it from each .*)
neuper@37906
  1684
fun step_cancel (t as Const ("HOL.divide",_) $ p1 $ p2) = 
neuper@37906
  1685
    let
neuper@37906
  1686
	val p1' = ref [];
neuper@37906
  1687
	val p2' = ref [];
neuper@37906
  1688
	val p3  = ref []
neuper@37906
  1689
	val vars = rev(get_vars(p1) union get_vars(p2));
neuper@37906
  1690
    in
neuper@37906
  1691
	(
neuper@37906
  1692
         p1':= sort (mv_geq LEX_) (the (term2poly p1 vars ));
neuper@37906
  1693
       	 p2':= sort (mv_geq LEX_) (the (term2poly p2 vars ));
neuper@37906
  1694
	 p3:= sort (mv_geq LEX_) (mv_gcd (!p1') (!p2'));
neuper@37906
  1695
	 if (!p3)=[(1,mv_null2(vars))] then 
neuper@37906
  1696
	     (
neuper@37906
  1697
	      Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ p1 $ p2
neuper@37906
  1698
	      )
neuper@37906
  1699
	 else
neuper@37906
  1700
	     (
neuper@37906
  1701
neuper@37906
  1702
	      p1':=sort (mv_geq LEX_) (#1(mv_division((!p1'),(!p3),LEX_)));
neuper@37906
  1703
	      p2':=sort (mv_geq LEX_) (#1(mv_division((!p2'),(!p3),LEX_)));
neuper@37906
  1704
	      
neuper@37906
  1705
	      if #1(hd(sort (mv_geq LEX_) (!p2'))) (*mv_lc2(!p2',LEX_)*)>0 then
neuper@37906
  1706
	      (
neuper@37906
  1707
	       Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  1708
	       $ 
neuper@37906
  1709
	       (
neuper@37906
  1710
		Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  1711
		poly2term(!p1',vars) $ 
neuper@37906
  1712
		poly2term(!p3,vars) 
neuper@37906
  1713
		) 
neuper@37906
  1714
	       $ 
neuper@37906
  1715
	       (
neuper@37906
  1716
		Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  1717
		poly2term(!p2',vars) $ 
neuper@37906
  1718
		poly2term(!p3,vars)
neuper@37906
  1719
		) 	
neuper@37906
  1720
	       )	
neuper@37906
  1721
	      else
neuper@37906
  1722
	      (
neuper@37906
  1723
	       p1':=mv_skalar_mul(!p1',~1);
neuper@37906
  1724
	       p2':=mv_skalar_mul(!p2',~1);
neuper@37906
  1725
	       p3:=mv_skalar_mul(!p3,~1);
neuper@37906
  1726
	       (
neuper@37906
  1727
		Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  1728
		$ 
neuper@37906
  1729
		(
neuper@37906
  1730
		 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  1731
		 poly2term(!p1',vars) $ 
neuper@37906
  1732
		 poly2term(!p3,vars) 
neuper@37906
  1733
		 ) 
neuper@37906
  1734
		$ 
neuper@37906
  1735
		(
neuper@37906
  1736
		 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  1737
		 poly2term(!p2',vars) $ 
neuper@37906
  1738
		 poly2term(!p3,vars)
neuper@37906
  1739
		 ) 	
neuper@37906
  1740
		)	
neuper@37906
  1741
	       )	  
neuper@37906
  1742
	      )
neuper@37906
  1743
	     )
neuper@37906
  1744
    end
neuper@37906
  1745
| step_cancel _ = raise error ("RATIONALS_STEP_CANCEL_EXCEPTION: Invalid fraction"); 
neuper@37906
  1746
neuper@37906
  1747
neuper@37906
  1748
(*. same as step_cancel, this time for expanded forms (input+output) .*)
neuper@37906
  1749
fun step_cancel_expanded (t as Const ("HOL.divide",_) $ p1 $ p2) = 
neuper@37906
  1750
    let
neuper@37906
  1751
	val p1' = ref [];
neuper@37906
  1752
	val p2' = ref [];
neuper@37906
  1753
	val p3  = ref []
neuper@37906
  1754
	val vars = rev(get_vars(p1) union get_vars(p2));
neuper@37906
  1755
    in
neuper@37906
  1756
	(
neuper@37906
  1757
         p1':= sort (mv_geq LEX_) (the (expanded2poly p1 vars ));
neuper@37906
  1758
       	 p2':= sort (mv_geq LEX_) (the (expanded2poly p2 vars ));
neuper@37906
  1759
	 p3:= sort (mv_geq LEX_) (mv_gcd (!p1') (!p2'));
neuper@37906
  1760
	 if (!p3)=[(1,mv_null2(vars))] then 
neuper@37906
  1761
	     (
neuper@37906
  1762
	      Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ p1 $ p2
neuper@37906
  1763
	      )
neuper@37906
  1764
	 else
neuper@37906
  1765
	     (
neuper@37906
  1766
neuper@37906
  1767
	      p1':=sort (mv_geq LEX_) (#1(mv_division((!p1'),(!p3),LEX_)));
neuper@37906
  1768
	      p2':=sort (mv_geq LEX_) (#1(mv_division((!p2'),(!p3),LEX_)));
neuper@37906
  1769
	      
neuper@37906
  1770
	      if #1(hd(sort (mv_geq LEX_) (!p2')))(* mv_lc2(!p2',LEX_)*)>0 then
neuper@37906
  1771
	      (
neuper@37906
  1772
	       Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  1773
	       $ 
neuper@37906
  1774
	       (
neuper@37906
  1775
		Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  1776
		poly2expanded(!p1',vars) $ 
neuper@37906
  1777
		poly2expanded(!p3,vars) 
neuper@37906
  1778
		) 
neuper@37906
  1779
	       $ 
neuper@37906
  1780
	       (
neuper@37906
  1781
		Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  1782
		poly2expanded(!p2',vars) $ 
neuper@37906
  1783
		poly2expanded(!p3,vars)
neuper@37906
  1784
		) 	
neuper@37906
  1785
	       )	
neuper@37906
  1786
	      else
neuper@37906
  1787
	      (
neuper@37906
  1788
	       p1':=mv_skalar_mul(!p1',~1);
neuper@37906
  1789
	       p2':=mv_skalar_mul(!p2',~1);
neuper@37906
  1790
	       p3:=mv_skalar_mul(!p3,~1);
neuper@37906
  1791
	       (
neuper@37906
  1792
		Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  1793
		$ 
neuper@37906
  1794
		(
neuper@37906
  1795
		 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  1796
		 poly2expanded(!p1',vars) $ 
neuper@37906
  1797
		 poly2expanded(!p3,vars) 
neuper@37906
  1798
		 ) 
neuper@37906
  1799
		$ 
neuper@37906
  1800
		(
neuper@37906
  1801
		 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  1802
		 poly2expanded(!p2',vars) $ 
neuper@37906
  1803
		 poly2expanded(!p3,vars)
neuper@37906
  1804
		 ) 	
neuper@37906
  1805
		)	
neuper@37906
  1806
	       )	  
neuper@37906
  1807
	      )
neuper@37906
  1808
	     )
neuper@37906
  1809
    end
neuper@37906
  1810
| step_cancel_expanded _ = raise error ("RATIONALS_STEP_CANCEL_EXCEPTION: Invalid fraction"); 
neuper@37906
  1811
neuper@37906
  1812
(*. calculates the greatest common divisor of numerator and denominator and divides each through it .*)
neuper@37906
  1813
fun direct_cancel (t as Const ("HOL.divide",_) $ p1 $ p2) = 
neuper@37906
  1814
    let
neuper@37906
  1815
	val p1' = ref [];
neuper@37906
  1816
	val p2' = ref [];
neuper@37906
  1817
	val p3  = ref []
neuper@37906
  1818
	val vars = rev(get_vars(p1) union get_vars(p2));
neuper@37906
  1819
    in
neuper@37906
  1820
	(
neuper@37906
  1821
	 p1':=sort (mv_geq LEX_) (mv_shorten((the (term2poly p1 vars )),LEX_));
neuper@37906
  1822
	 p2':=sort (mv_geq LEX_) (mv_shorten((the (term2poly p2 vars )),LEX_));	 
neuper@37906
  1823
	 p3 :=sort (mv_geq LEX_) (mv_gcd (!p1') (!p2'));
neuper@37906
  1824
neuper@37906
  1825
	 if (!p3)=[(1,mv_null2(vars))] then 
neuper@37906
  1826
	     (
neuper@37906
  1827
	      (Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ p1 $ p2,[])
neuper@37906
  1828
	      )
neuper@37906
  1829
	 else
neuper@37906
  1830
	     (
neuper@37906
  1831
	      p1':=sort (mv_geq LEX_) (#1(mv_division((!p1'),(!p3),LEX_)));
neuper@37906
  1832
	      p2':=sort (mv_geq LEX_) (#1(mv_division((!p2'),(!p3),LEX_)));
neuper@37906
  1833
	      if #1(hd(sort (mv_geq LEX_) (!p2'))) (*mv_lc2(!p2',LEX_)*)>0 then	      
neuper@37906
  1834
	      (
neuper@37906
  1835
	       (
neuper@37906
  1836
		Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  1837
		$ 
neuper@37906
  1838
		(
neuper@37906
  1839
		 poly2term((!p1'),vars)
neuper@37906
  1840
		 ) 
neuper@37906
  1841
		$ 
neuper@37906
  1842
		( 
neuper@37906
  1843
		 poly2term((!p2'),vars)
neuper@37906
  1844
		 ) 	
neuper@37906
  1845
		)
neuper@37906
  1846
	       ,
neuper@37906
  1847
	       if mv_grad(!p3)>0 then 
neuper@37906
  1848
		   [
neuper@37906
  1849
		    (
neuper@37906
  1850
		     Const ("Not",[bool]--->bool) $
neuper@37906
  1851
		     (
neuper@37906
  1852
		      Const("op =",[HOLogic.realT,HOLogic.realT]--->bool) $
neuper@37906
  1853
		      poly2term((!p3),vars) $
neuper@37906
  1854
		      Free("0",HOLogic.realT)
neuper@37906
  1855
		      )
neuper@37906
  1856
		     )
neuper@37906
  1857
		    ]
neuper@37906
  1858
	       else
neuper@37906
  1859
		   []
neuper@37906
  1860
		   )
neuper@37906
  1861
	      else
neuper@37906
  1862
		  (
neuper@37906
  1863
		   p1':=mv_skalar_mul(!p1',~1);
neuper@37906
  1864
		   p2':=mv_skalar_mul(!p2',~1);
neuper@37906
  1865
		   if length(!p3)> 2*(count_neg(!p3)) then () else p3 :=mv_skalar_mul(!p3,~1); 
neuper@37906
  1866
		       (
neuper@37906
  1867
			Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  1868
			$ 
neuper@37906
  1869
			(
neuper@37906
  1870
			 poly2term((!p1'),vars)
neuper@37906
  1871
			 ) 
neuper@37906
  1872
			$ 
neuper@37906
  1873
			( 
neuper@37906
  1874
			 poly2term((!p2'),vars)
neuper@37906
  1875
			 ) 	
neuper@37906
  1876
			,
neuper@37906
  1877
			if mv_grad(!p3)>0 then 
neuper@37906
  1878
			    [
neuper@37906
  1879
			     (
neuper@37906
  1880
			      Const ("Not",[bool]--->bool) $
neuper@37906
  1881
			      (
neuper@37906
  1882
			       Const("op =",[HOLogic.realT,HOLogic.realT]--->bool) $
neuper@37906
  1883
			       poly2term((!p3),vars) $
neuper@37906
  1884
			       Free("0",HOLogic.realT)
neuper@37906
  1885
			       )
neuper@37906
  1886
			      )
neuper@37906
  1887
			     ]
neuper@37906
  1888
			else
neuper@37906
  1889
			    []
neuper@37906
  1890
			    )
neuper@37906
  1891
		       )
neuper@37906
  1892
		  )
neuper@37906
  1893
	     )
neuper@37906
  1894
    end
neuper@37906
  1895
  | direct_cancel _ = raise error ("RATIONALS_DIRECT_CANCEL_EXCEPTION: Invalid fraction"); 
neuper@37906
  1896
neuper@37906
  1897
(*. same es direct_cancel, this time for expanded forms (input+output).*) 
neuper@37906
  1898
fun direct_cancel_expanded (t as Const ("HOL.divide",_) $ p1 $ p2) =  
neuper@37906
  1899
    let
neuper@37906
  1900
	val p1' = ref [];
neuper@37906
  1901
	val p2' = ref [];
neuper@37906
  1902
	val p3  = ref []
neuper@37906
  1903
	val vars = rev(get_vars(p1) union get_vars(p2));
neuper@37906
  1904
    in
neuper@37906
  1905
	(
neuper@37906
  1906
	 p1':=sort (mv_geq LEX_) (mv_shorten((the (expanded2poly p1 vars )),LEX_));
neuper@37906
  1907
	 p2':=sort (mv_geq LEX_) (mv_shorten((the (expanded2poly p2 vars )),LEX_));	 
neuper@37906
  1908
	 p3 :=sort (mv_geq LEX_) (mv_gcd (!p1') (!p2'));
neuper@37906
  1909
neuper@37906
  1910
	 if (!p3)=[(1,mv_null2(vars))] then 
neuper@37906
  1911
	     (
neuper@37906
  1912
	      (Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ p1 $ p2,[])
neuper@37906
  1913
	      )
neuper@37906
  1914
	 else
neuper@37906
  1915
	     (
neuper@37906
  1916
	      p1':=sort (mv_geq LEX_) (#1(mv_division((!p1'),(!p3),LEX_)));
neuper@37906
  1917
	      p2':=sort (mv_geq LEX_) (#1(mv_division((!p2'),(!p3),LEX_)));
neuper@37906
  1918
	      if #1(hd(sort (mv_geq LEX_) (!p2'))) (*mv_lc2(!p2',LEX_)*)>0 then	      
neuper@37906
  1919
	      (
neuper@37906
  1920
	       (
neuper@37906
  1921
		Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  1922
		$ 
neuper@37906
  1923
		(
neuper@37906
  1924
		 poly2expanded((!p1'),vars)
neuper@37906
  1925
		 ) 
neuper@37906
  1926
		$ 
neuper@37906
  1927
		( 
neuper@37906
  1928
		 poly2expanded((!p2'),vars)
neuper@37906
  1929
		 ) 	
neuper@37906
  1930
		)
neuper@37906
  1931
	       ,
neuper@37906
  1932
	       if mv_grad(!p3)>0 then 
neuper@37906
  1933
		   [
neuper@37906
  1934
		    (
neuper@37906
  1935
		     Const ("Not",[bool]--->bool) $
neuper@37906
  1936
		     (
neuper@37906
  1937
		      Const("op =",[HOLogic.realT,HOLogic.realT]--->bool) $
neuper@37906
  1938
		      poly2expanded((!p3),vars) $
neuper@37906
  1939
		      Free("0",HOLogic.realT)
neuper@37906
  1940
		      )
neuper@37906
  1941
		     )
neuper@37906
  1942
		    ]
neuper@37906
  1943
	       else
neuper@37906
  1944
		   []
neuper@37906
  1945
		   )
neuper@37906
  1946
	      else
neuper@37906
  1947
		  (
neuper@37906
  1948
		   p1':=mv_skalar_mul(!p1',~1);
neuper@37906
  1949
		   p2':=mv_skalar_mul(!p2',~1);
neuper@37906
  1950
		   if length(!p3)> 2*(count_neg(!p3)) then () else p3 :=mv_skalar_mul(!p3,~1); 
neuper@37906
  1951
		       (
neuper@37906
  1952
			Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  1953
			$ 
neuper@37906
  1954
			(
neuper@37906
  1955
			 poly2expanded((!p1'),vars)
neuper@37906
  1956
			 ) 
neuper@37906
  1957
			$ 
neuper@37906
  1958
			( 
neuper@37906
  1959
			 poly2expanded((!p2'),vars)
neuper@37906
  1960
			 ) 	
neuper@37906
  1961
			,
neuper@37906
  1962
			if mv_grad(!p3)>0 then 
neuper@37906
  1963
			    [
neuper@37906
  1964
			     (
neuper@37906
  1965
			      Const ("Not",[bool]--->bool) $
neuper@37906
  1966
			      (
neuper@37906
  1967
			       Const("op =",[HOLogic.realT,HOLogic.realT]--->bool) $
neuper@37906
  1968
			       poly2expanded((!p3),vars) $
neuper@37906
  1969
			       Free("0",HOLogic.realT)
neuper@37906
  1970
			       )
neuper@37906
  1971
			      )
neuper@37906
  1972
			     ]
neuper@37906
  1973
			else
neuper@37906
  1974
			    []
neuper@37906
  1975
			    )
neuper@37906
  1976
		       )
neuper@37906
  1977
		  )
neuper@37906
  1978
	     )
neuper@37906
  1979
    end
neuper@37906
  1980
  | direct_cancel_expanded _ = raise error ("RATIONALS_DIRECT_CANCEL_EXCEPTION: Invalid fraction"); 
neuper@37906
  1981
neuper@37906
  1982
neuper@37906
  1983
(*. adds two fractions .*)
neuper@37906
  1984
fun add_fract ((Const("HOL.divide",_) $ t11 $ t12),(Const("HOL.divide",_) $ t21 $ t22)) =
neuper@37906
  1985
    let
neuper@37906
  1986
	val vars=get_vars(t11) union get_vars(t12) union get_vars(t21) union get_vars(t22);
neuper@37906
  1987
	val t11'=ref (the(term2poly t11 vars));
neuper@37906
  1988
val _= writeln"### add_fract: done t11"
neuper@37906
  1989
	val t12'=ref (the(term2poly t12 vars));
neuper@37906
  1990
val _= writeln"### add_fract: done t12"
neuper@37906
  1991
	val t21'=ref (the(term2poly t21 vars));
neuper@37906
  1992
val _= writeln"### add_fract: done t21"
neuper@37906
  1993
	val t22'=ref (the(term2poly t22 vars));
neuper@37906
  1994
val _= writeln"### add_fract: done t22"
neuper@37906
  1995
	val den=ref [];
neuper@37906
  1996
	val nom=ref [];
neuper@37906
  1997
	val m1=ref [];
neuper@37906
  1998
	val m2=ref [];
neuper@37906
  1999
    in
neuper@37906
  2000
	
neuper@37906
  2001
	(
neuper@37906
  2002
	 den :=sort (mv_geq LEX_) (mv_lcm (!t12') (!t22'));
neuper@37906
  2003
writeln"### add_fract: done sort mv_lcm";
neuper@37906
  2004
	 m1  :=sort (mv_geq LEX_) (#1(mv_division(!den,!t12',LEX_)));
neuper@37906
  2005
writeln"### add_fract: done sort mv_division t12";
neuper@37906
  2006
	 m2  :=sort (mv_geq LEX_) (#1(mv_division(!den,!t22',LEX_)));
neuper@37906
  2007
writeln"### add_fract: done sort mv_division t22";
neuper@37906
  2008
	 nom :=sort (mv_geq LEX_) 
neuper@37906
  2009
		    (mv_shorten(mv_add(mv_mul(!t11',!m1,LEX_),
neuper@37906
  2010
				       mv_mul(!t21',!m2,LEX_),
neuper@37906
  2011
				       LEX_),
neuper@37906
  2012
				LEX_));
neuper@37906
  2013
writeln"### add_fract: done sort mv_add";
neuper@37906
  2014
	 (
neuper@37906
  2015
	  Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  2016
	  $ 
neuper@37906
  2017
	  (
neuper@37906
  2018
	   poly2term((!nom),vars)
neuper@37906
  2019
	   ) 
neuper@37906
  2020
	  $ 
neuper@37906
  2021
	  ( 
neuper@37906
  2022
	   poly2term((!den),vars)
neuper@37906
  2023
	   )	      
neuper@37906
  2024
	  )
neuper@37906
  2025
	 )	     
neuper@37906
  2026
    end 
neuper@37906
  2027
  | add_fract (_,_) = raise error ("RATIONALS_ADD_FRACTION_EXCEPTION: Invalid add_fraction call");
neuper@37906
  2028
neuper@37906
  2029
(*. adds two expanded fractions .*)
neuper@37906
  2030
fun add_fract_exp ((Const("HOL.divide",_) $ t11 $ t12),(Const("HOL.divide",_) $ t21 $ t22)) =
neuper@37906
  2031
    let
neuper@37906
  2032
	val vars=get_vars(t11) union get_vars(t12) union get_vars(t21) union get_vars(t22);
neuper@37906
  2033
	val t11'=ref (the(expanded2poly t11 vars));
neuper@37906
  2034
	val t12'=ref (the(expanded2poly t12 vars));
neuper@37906
  2035
	val t21'=ref (the(expanded2poly t21 vars));
neuper@37906
  2036
	val t22'=ref (the(expanded2poly t22 vars));
neuper@37906
  2037
	val den=ref [];
neuper@37906
  2038
	val nom=ref [];
neuper@37906
  2039
	val m1=ref [];
neuper@37906
  2040
	val m2=ref [];
neuper@37906
  2041
    in
neuper@37906
  2042
	
neuper@37906
  2043
	(
neuper@37906
  2044
	 den :=sort (mv_geq LEX_) (mv_lcm (!t12') (!t22'));
neuper@37906
  2045
	 m1  :=sort (mv_geq LEX_) (#1(mv_division(!den,!t12',LEX_)));
neuper@37906
  2046
	 m2  :=sort (mv_geq LEX_) (#1(mv_division(!den,!t22',LEX_)));
neuper@37906
  2047
	 nom :=sort (mv_geq LEX_) (mv_shorten(mv_add(mv_mul(!t11',!m1,LEX_),mv_mul(!t21',!m2,LEX_),LEX_),LEX_));
neuper@37906
  2048
	 (
neuper@37906
  2049
	  Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  2050
	  $ 
neuper@37906
  2051
	  (
neuper@37906
  2052
	   poly2expanded((!nom),vars)
neuper@37906
  2053
	   ) 
neuper@37906
  2054
	  $ 
neuper@37906
  2055
	  ( 
neuper@37906
  2056
	   poly2expanded((!den),vars)
neuper@37906
  2057
	   )	      
neuper@37906
  2058
	  )
neuper@37906
  2059
	 )	     
neuper@37906
  2060
    end 
neuper@37906
  2061
  | add_fract_exp (_,_) = raise error ("RATIONALS_ADD_FRACTION_EXP_EXCEPTION: Invalid add_fraction call");
neuper@37906
  2062
neuper@37906
  2063
(*. adds a list of terms .*)
neuper@37906
  2064
fun add_list_of_fractions []= (Free("0",HOLogic.realT),[])
neuper@37906
  2065
  | add_list_of_fractions [x]= direct_cancel x
neuper@37906
  2066
  | add_list_of_fractions (x::y::xs) = 
neuper@37906
  2067
    let
neuper@37906
  2068
	val (t1a,rest1)=direct_cancel(x);
neuper@37906
  2069
val _= writeln"### add_list_of_fractions xs: has done direct_cancel(x)";
neuper@37906
  2070
	val (t2a,rest2)=direct_cancel(y);
neuper@37906
  2071
val _= writeln"### add_list_of_fractions xs: has done direct_cancel(y)";
neuper@37906
  2072
	val (t3a,rest3)=(add_list_of_fractions (add_fract(t1a,t2a)::xs));
neuper@37906
  2073
val _= writeln"### add_list_of_fractions xs: has done add_list_of_fraction xs";
neuper@37906
  2074
	val (t4a,rest4)=direct_cancel(t3a);
neuper@37906
  2075
val _= writeln"### add_list_of_fractions xs: has done direct_cancel(t3a)";
neuper@37906
  2076
	val rest=rest1 union rest2 union rest3 union rest4;
neuper@37906
  2077
    in
neuper@37906
  2078
	(writeln"### add_list_of_fractions in";
neuper@37906
  2079
	 (
neuper@37906
  2080
	 (t4a,rest) 
neuper@37906
  2081
	 )
neuper@37906
  2082
	 )
neuper@37906
  2083
    end;
neuper@37906
  2084
neuper@37906
  2085
(*. adds a list of expanded terms .*)
neuper@37906
  2086
fun add_list_of_fractions_exp []= (Free("0",HOLogic.realT),[])
neuper@37906
  2087
  | add_list_of_fractions_exp [x]= direct_cancel_expanded x
neuper@37906
  2088
  | add_list_of_fractions_exp (x::y::xs) = 
neuper@37906
  2089
    let
neuper@37906
  2090
	val (t1a,rest1)=direct_cancel_expanded(x);
neuper@37906
  2091
	val (t2a,rest2)=direct_cancel_expanded(y);
neuper@37906
  2092
	val (t3a,rest3)=(add_list_of_fractions_exp (add_fract_exp(t1a,t2a)::xs));
neuper@37906
  2093
	val (t4a,rest4)=direct_cancel_expanded(t3a);
neuper@37906
  2094
	val rest=rest1 union rest2 union rest3 union rest4;
neuper@37906
  2095
    in
neuper@37906
  2096
	(
neuper@37906
  2097
	 (t4a,rest) 
neuper@37906
  2098
	 )
neuper@37906
  2099
    end;
neuper@37906
  2100
neuper@37906
  2101
(*. calculates the lcm of a list of mv_poly .*)
neuper@37906
  2102
fun calc_lcm ([x],var)= (x,var) 
neuper@37906
  2103
  | calc_lcm ((x::xs),var) = (mv_lcm x (#1(calc_lcm (xs,var))),var);
neuper@37906
  2104
neuper@37906
  2105
(*. converts a list of terms to a list of mv_poly .*)
neuper@37906
  2106
fun t2d([],_)=[] 
neuper@37906
  2107
  | t2d((t as (Const("HOL.divide",_) $ p1 $ p2))::xs,vars)= (the(term2poly p2 vars)) :: t2d(xs,vars); 
neuper@37906
  2108
neuper@37906
  2109
(*. same as t2d, this time for expanded forms .*)
neuper@37906
  2110
fun t2d_exp([],_)=[]  
neuper@37906
  2111
  | t2d_exp((t as (Const("HOL.divide",_) $ p1 $ p2))::xs,vars)= (the(expanded2poly p2 vars)) :: t2d_exp(xs,vars);
neuper@37906
  2112
neuper@37906
  2113
(*. converts a list of fract terms to a list of their denominators .*)
neuper@37906
  2114
fun termlist2denominators [] = ([],[])
neuper@37906
  2115
  | termlist2denominators xs = 
neuper@37906
  2116
    let	
neuper@37906
  2117
	val xxs=ref xs;
neuper@37906
  2118
	val var=ref [];
neuper@37906
  2119
    in
neuper@37906
  2120
	var:=[];
neuper@37906
  2121
	while length(!xxs)>0 do
neuper@37906
  2122
	    (
neuper@37906
  2123
	     let 
neuper@37906
  2124
		 val (t as Const ("HOL.divide",_) $ p1x $ p2x)=hd(!xxs);
neuper@37906
  2125
	     in
neuper@37906
  2126
		 (
neuper@37906
  2127
		  xxs:=tl(!xxs);
neuper@37906
  2128
		  var:=((get_vars(p2x)) union (get_vars(p1x)) union (!var))
neuper@37906
  2129
		  )
neuper@37906
  2130
	     end
neuper@37906
  2131
	     );
neuper@37906
  2132
	    (t2d(xs,!var),!var)
neuper@37906
  2133
    end;
neuper@37906
  2134
neuper@37906
  2135
(*. calculates the lcm of a list of mv_poly .*)
neuper@37906
  2136
fun calc_lcm ([x],var)= (x,var) 
neuper@37906
  2137
  | calc_lcm ((x::xs),var) = (mv_lcm x (#1(calc_lcm (xs,var))),var);
neuper@37906
  2138
neuper@37906
  2139
(*. converts a list of terms to a list of mv_poly .*)
neuper@37906
  2140
fun t2d([],_)=[] 
neuper@37906
  2141
  | t2d((t as (Const("HOL.divide",_) $ p1 $ p2))::xs,vars)= (the(term2poly p2 vars)) :: t2d(xs,vars); 
neuper@37906
  2142
neuper@37906
  2143
(*. same as t2d, this time for expanded forms .*)
neuper@37906
  2144
fun t2d_exp([],_)=[]  
neuper@37906
  2145
  | t2d_exp((t as (Const("HOL.divide",_) $ p1 $ p2))::xs,vars)= (the(expanded2poly p2 vars)) :: t2d_exp(xs,vars);
neuper@37906
  2146
neuper@37906
  2147
(*. converts a list of fract terms to a list of their denominators .*)
neuper@37906
  2148
fun termlist2denominators [] = ([],[])
neuper@37906
  2149
  | termlist2denominators xs = 
neuper@37906
  2150
    let	
neuper@37906
  2151
	val xxs=ref xs;
neuper@37906
  2152
	val var=ref [];
neuper@37906
  2153
    in
neuper@37906
  2154
	var:=[];
neuper@37906
  2155
	while length(!xxs)>0 do
neuper@37906
  2156
	    (
neuper@37906
  2157
	     let 
neuper@37906
  2158
		 val (t as Const ("HOL.divide",_) $ p1x $ p2x)=hd(!xxs);
neuper@37906
  2159
	     in
neuper@37906
  2160
		 (
neuper@37906
  2161
		  xxs:=tl(!xxs);
neuper@37906
  2162
		  var:=((get_vars(p2x)) union (get_vars(p1x)) union (!var))
neuper@37906
  2163
		  )
neuper@37906
  2164
	     end
neuper@37906
  2165
	     );
neuper@37906
  2166
	    (t2d(xs,!var),!var)
neuper@37906
  2167
    end;
neuper@37906
  2168
neuper@37906
  2169
(*. same as termlist2denminators, this time for expanded forms .*)
neuper@37906
  2170
fun termlist2denominators_exp [] = ([],[])
neuper@37906
  2171
  | termlist2denominators_exp xs = 
neuper@37906
  2172
    let	
neuper@37906
  2173
	val xxs=ref xs;
neuper@37906
  2174
	val var=ref [];
neuper@37906
  2175
    in
neuper@37906
  2176
	var:=[];
neuper@37906
  2177
	while length(!xxs)>0 do
neuper@37906
  2178
	    (
neuper@37906
  2179
	     let 
neuper@37906
  2180
		 val (t as Const ("HOL.divide",_) $ p1x $ p2x)=hd(!xxs);
neuper@37906
  2181
	     in
neuper@37906
  2182
		 (
neuper@37906
  2183
		  xxs:=tl(!xxs);
neuper@37906
  2184
		  var:=((get_vars(p2x)) union (get_vars(p1x)) union (!var))
neuper@37906
  2185
		  )
neuper@37906
  2186
	     end
neuper@37906
  2187
	     );
neuper@37906
  2188
	    (t2d_exp(xs,!var),!var)
neuper@37906
  2189
    end;
neuper@37906
  2190
neuper@37906
  2191
(*. reduces all fractions to the least common denominator .*)
neuper@37906
  2192
fun com_den(x::xs,denom,den,var)=
neuper@37906
  2193
    let 
neuper@37906
  2194
	val (t as Const ("HOL.divide",_) $ p1' $ p2')=x;
neuper@37906
  2195
	val p2= sort (mv_geq LEX_) (the(term2poly p2' var));
neuper@37906
  2196
	val p3= #1(mv_division(denom,p2,LEX_));
neuper@37906
  2197
	val p1var=get_vars(p1');
neuper@37906
  2198
    in     
neuper@37906
  2199
	if length(xs)>0 then 
neuper@37906
  2200
	    if p3=[(1,mv_null2(var))] then
neuper@37906
  2201
		(
neuper@37906
  2202
		 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
neuper@37906
  2203
		 $ 
neuper@37906
  2204
		 (
neuper@37906
  2205
		  Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  2206
		  $ 
neuper@37906
  2207
		  poly2term(the (term2poly p1' p1var),p1var)
neuper@37906
  2208
		  $ 
neuper@37906
  2209
		  den	
neuper@37906
  2210
		  )    
neuper@37906
  2211
		 $ 
neuper@37906
  2212
		 #1(com_den(xs,denom,den,var))
neuper@37906
  2213
		,
neuper@37906
  2214
		[]
neuper@37906
  2215
		)
neuper@37906
  2216
	    else
neuper@37906
  2217
		(
neuper@37906
  2218
		 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  2219
		 $ 
neuper@37906
  2220
		 (
neuper@37906
  2221
		  Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  2222
		  $ 
neuper@37906
  2223
		  (
neuper@37906
  2224
		   Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2225
		   poly2term(the (term2poly p1' p1var),p1var) $ 
neuper@37906
  2226
		   poly2term(p3,var)
neuper@37906
  2227
		   ) 
neuper@37906
  2228
		  $ 
neuper@37906
  2229
		  (
neuper@37906
  2230
		   den
neuper@37906
  2231
		   ) 	
neuper@37906
  2232
		  )
neuper@37906
  2233
		 $ 
neuper@37906
  2234
		 #1(com_den(xs,denom,den,var))
neuper@37906
  2235
		,
neuper@37906
  2236
		[]
neuper@37906
  2237
		)
neuper@37906
  2238
	else
neuper@37906
  2239
	    if p3=[(1,mv_null2(var))] then
neuper@37906
  2240
		(
neuper@37906
  2241
		 (
neuper@37906
  2242
		  Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  2243
		  $ 
neuper@37906
  2244
		  poly2term(the (term2poly p1' p1var),p1var)
neuper@37906
  2245
		  $ 
neuper@37906
  2246
		  den	
neuper@37906
  2247
		  )
neuper@37906
  2248
		 ,
neuper@37906
  2249
		 []
neuper@37906
  2250
		 )
neuper@37906
  2251
	     else
neuper@37906
  2252
		 (
neuper@37906
  2253
		  Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  2254
		  $ 
neuper@37906
  2255
		  (
neuper@37906
  2256
		   Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2257
		   poly2term(the (term2poly p1' p1var),p1var) $ 
neuper@37906
  2258
		   poly2term(p3,var)
neuper@37906
  2259
		   ) 
neuper@37906
  2260
		  $ 
neuper@37906
  2261
		  den 	
neuper@37906
  2262
		  ,
neuper@37906
  2263
		  []
neuper@37906
  2264
		  )
neuper@37906
  2265
    end;
neuper@37906
  2266
neuper@37906
  2267
(*. same as com_den, this time for expanded forms .*)
neuper@37906
  2268
fun com_den_exp(x::xs,denom,den,var)=
neuper@37906
  2269
    let 
neuper@37906
  2270
	val (t as Const ("HOL.divide",_) $ p1' $ p2')=x;
neuper@37906
  2271
	val p2= sort (mv_geq LEX_) (the(expanded2poly p2' var));
neuper@37906
  2272
	val p3= #1(mv_division(denom,p2,LEX_));
neuper@37906
  2273
	val p1var=get_vars(p1');
neuper@37906
  2274
    in     
neuper@37906
  2275
	if length(xs)>0 then 
neuper@37906
  2276
	    if p3=[(1,mv_null2(var))] then
neuper@37906
  2277
		(
neuper@37906
  2278
		 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
neuper@37906
  2279
		 $ 
neuper@37906
  2280
		 (
neuper@37906
  2281
		  Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  2282
		  $ 
neuper@37906
  2283
		  poly2expanded(the(expanded2poly p1' p1var),p1var)
neuper@37906
  2284
		  $ 
neuper@37906
  2285
		  den	
neuper@37906
  2286
		  )    
neuper@37906
  2287
		 $ 
neuper@37906
  2288
		 #1(com_den_exp(xs,denom,den,var))
neuper@37906
  2289
		,
neuper@37906
  2290
		[]
neuper@37906
  2291
		)
neuper@37906
  2292
	    else
neuper@37906
  2293
		(
neuper@37906
  2294
		 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  2295
		 $ 
neuper@37906
  2296
		 (
neuper@37906
  2297
		  Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  2298
		  $ 
neuper@37906
  2299
		  (
neuper@37906
  2300
		   Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2301
		   poly2expanded(the(expanded2poly p1' p1var),p1var) $ 
neuper@37906
  2302
		   poly2expanded(p3,var)
neuper@37906
  2303
		   ) 
neuper@37906
  2304
		  $ 
neuper@37906
  2305
		  (
neuper@37906
  2306
		   den
neuper@37906
  2307
		   ) 	
neuper@37906
  2308
		  )
neuper@37906
  2309
		 $ 
neuper@37906
  2310
		 #1(com_den_exp(xs,denom,den,var))
neuper@37906
  2311
		,
neuper@37906
  2312
		[]
neuper@37906
  2313
		)
neuper@37906
  2314
	else
neuper@37906
  2315
	    if p3=[(1,mv_null2(var))] then
neuper@37906
  2316
		(
neuper@37906
  2317
		 (
neuper@37906
  2318
		  Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  2319
		  $ 
neuper@37906
  2320
		  poly2expanded(the(expanded2poly p1' p1var),p1var)
neuper@37906
  2321
		  $ 
neuper@37906
  2322
		  den	
neuper@37906
  2323
		  )
neuper@37906
  2324
		 ,
neuper@37906
  2325
		 []
neuper@37906
  2326
		 )
neuper@37906
  2327
	     else
neuper@37906
  2328
		 (
neuper@37906
  2329
		  Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) 
neuper@37906
  2330
		  $ 
neuper@37906
  2331
		  (
neuper@37906
  2332
		   Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2333
		   poly2expanded(the(expanded2poly p1' p1var),p1var) $ 
neuper@37906
  2334
		   poly2expanded(p3,var)
neuper@37906
  2335
		   ) 
neuper@37906
  2336
		  $ 
neuper@37906
  2337
		  den 	
neuper@37906
  2338
		  ,
neuper@37906
  2339
		  []
neuper@37906
  2340
		  )
neuper@37906
  2341
    end;
neuper@37906
  2342
neuper@37906
  2343
(* wird aktuell nicht mehr gebraucht, bei rückänderung schon 
neuper@37906
  2344
-------------------------------------------------------------
neuper@37906
  2345
(* WN0210???SK brauch ma des überhaupt *)
neuper@37906
  2346
fun com_den2(x::xs,denom,den,var)=
neuper@37906
  2347
    let 
neuper@37906
  2348
	val (t as Const ("HOL.divide",_) $ p1' $ p2')=x;
neuper@37906
  2349
	val p2= sort (mv_geq LEX_) (the(term2poly p2' var));
neuper@37906
  2350
	val p3= #1(mv_division(denom,p2,LEX_));
neuper@37906
  2351
	val p1var=get_vars(p1');
neuper@37906
  2352
    in     
neuper@37906
  2353
	if length(xs)>0 then 
neuper@37906
  2354
	    if p3=[(1,mv_null2(var))] then
neuper@37906
  2355
		(
neuper@37906
  2356
		 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2357
		 poly2term(the(term2poly p1' p1var),p1var) $ 
neuper@37906
  2358
		 com_den2(xs,denom,den,var)
neuper@37906
  2359
		)
neuper@37906
  2360
	    else
neuper@37906
  2361
		(
neuper@37906
  2362
		 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2363
		 (
neuper@37906
  2364
		   let 
neuper@37906
  2365
		       val p3'=poly2term(p3,var);
neuper@37906
  2366
		       val vars= (((map free2str) o vars) p1') union (((map free2str) o vars) p3');
neuper@37906
  2367
		   in
neuper@37906
  2368
		       poly2term(sort (mv_geq LEX_) (mv_mul(the(term2poly p1' vars) ,the(term2poly p3' vars),LEX_)),vars)
neuper@37906
  2369
		   end
neuper@37906
  2370
		  ) $ 
neuper@37906
  2371
		 com_den2(xs,denom,den,var)
neuper@37906
  2372
		)
neuper@37906
  2373
	else
neuper@37906
  2374
	    if p3=[(1,mv_null2(var))] then
neuper@37906
  2375
		(
neuper@37906
  2376
		 poly2term(the(term2poly p1' p1var),p1var)
neuper@37906
  2377
		 )
neuper@37906
  2378
	     else
neuper@37906
  2379
		 (
neuper@37906
  2380
		   let 
neuper@37906
  2381
		       val p3'=poly2term(p3,var);
neuper@37906
  2382
		       val vars= (((map free2str) o vars) p1') union (((map free2str) o vars) p3');
neuper@37906
  2383
		   in
neuper@37906
  2384
		       poly2term(sort (mv_geq LEX_) (mv_mul(the(term2poly p1' vars) ,the(term2poly p3' vars),LEX_)),vars)
neuper@37906
  2385
		   end
neuper@37906
  2386
		  )
neuper@37906
  2387
    end;
neuper@37906
  2388
neuper@37906
  2389
(* WN0210???SK brauch ma des überhaupt *)
neuper@37906
  2390
fun com_den_exp2(x::xs,denom,den,var)=
neuper@37906
  2391
    let 
neuper@37906
  2392
	val (t as Const ("HOL.divide",_) $ p1' $ p2')=x;
neuper@37906
  2393
	val p2= sort (mv_geq LEX_) (the(expanded2poly p2' var));
neuper@37906
  2394
	val p3= #1(mv_division(denom,p2,LEX_));
neuper@37906
  2395
	val p1var=get_vars p1';
neuper@37906
  2396
    in     
neuper@37906
  2397
	if length(xs)>0 then 
neuper@37906
  2398
	    if p3=[(1,mv_null2(var))] then
neuper@37906
  2399
		(
neuper@37906
  2400
		 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2401
		 poly2expanded(the (expanded2poly p1' p1var),p1var) $ 
neuper@37906
  2402
		 com_den_exp2(xs,denom,den,var)
neuper@37906
  2403
		)
neuper@37906
  2404
	    else
neuper@37906
  2405
		(
neuper@37906
  2406
		 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2407
		 (
neuper@37906
  2408
		   let 
neuper@37906
  2409
		       val p3'=poly2expanded(p3,var);
neuper@37906
  2410
		       val vars= (((map free2str) o vars) p1') union (((map free2str) o vars) p3');
neuper@37906
  2411
		   in
neuper@37906
  2412
		       poly2expanded(sort (mv_geq LEX_) (mv_mul(the(expanded2poly p1' vars) ,the(expanded2poly p3' vars),LEX_)),vars)
neuper@37906
  2413
		   end
neuper@37906
  2414
		  ) $ 
neuper@37906
  2415
		 com_den_exp2(xs,denom,den,var)
neuper@37906
  2416
		)
neuper@37906
  2417
	else
neuper@37906
  2418
	    if p3=[(1,mv_null2(var))] then
neuper@37906
  2419
		(
neuper@37906
  2420
		 poly2expanded(the (expanded2poly p1' p1var),p1var)
neuper@37906
  2421
		 )
neuper@37906
  2422
	     else
neuper@37906
  2423
		 (
neuper@37906
  2424
		   let 
neuper@37906
  2425
		       val p3'=poly2expanded(p3,var);
neuper@37906
  2426
		       val vars= (((map free2str) o vars) p1') union (((map free2str) o vars) p3');
neuper@37906
  2427
		   in
neuper@37906
  2428
		       poly2expanded(sort (mv_geq LEX_) (mv_mul(the(expanded2poly p1' vars) ,the(expanded2poly p3' vars),LEX_)),vars)
neuper@37906
  2429
		   end
neuper@37906
  2430
		  )
neuper@37906
  2431
    end;
neuper@37906
  2432
---------------------------------------------------------*)
neuper@37906
  2433
neuper@37906
  2434
neuper@37906
  2435
(*. searches for an element y of a list ys, which has an gcd not 1 with x .*) 
neuper@37906
  2436
fun exists_gcd (x,[]) = false 
neuper@37906
  2437
  | exists_gcd (x,y::ys) = if mv_gcd x y = [(1,mv_null2(#2(hd(x))))] then  exists_gcd (x,ys)
neuper@37906
  2438
			   else true;
neuper@37906
  2439
neuper@37906
  2440
(*. divides each element of the list xs with y .*)
neuper@37906
  2441
fun list_div ([],y) = [] 
neuper@37906
  2442
  | list_div (x::xs,y) = 
neuper@37906
  2443
    let
neuper@37906
  2444
	val (d,r)=mv_division(x,y,LEX_);
neuper@37906
  2445
    in
neuper@37906
  2446
	if r=[] then 
neuper@37906
  2447
	    d::list_div(xs,y)
neuper@37906
  2448
	else x::list_div(xs,y)
neuper@37906
  2449
    end;
neuper@37906
  2450
    
neuper@37906
  2451
(*. checks if x is in the list ys .*)
neuper@37906
  2452
fun in_list (x,[]) = false 
neuper@37906
  2453
  | in_list (x,y::ys) = if x=y then true
neuper@37906
  2454
			else in_list(x,ys);
neuper@37906
  2455
neuper@37906
  2456
(*. deletes all equal elements of the list xs .*)
neuper@37906
  2457
fun kill_equal [] = [] 
neuper@37906
  2458
  | kill_equal (x::xs) = if in_list(x,xs) orelse x=[(1,mv_null2(#2(hd(x))))] then kill_equal(xs)
neuper@37906
  2459
			 else x::kill_equal(xs);
neuper@37906
  2460
neuper@37906
  2461
(*. searches for new factors .*)
neuper@37906
  2462
fun new_factors [] = []
neuper@37906
  2463
  | new_factors (list:mv_poly list):mv_poly list = 
neuper@37906
  2464
    let
neuper@37906
  2465
	val l = kill_equal list;
neuper@37906
  2466
	val len = length(l);
neuper@37906
  2467
    in
neuper@37906
  2468
	if len>=2 then
neuper@37906
  2469
	    (
neuper@37906
  2470
	     let
neuper@37906
  2471
		 val x::y::xs=l;
neuper@37906
  2472
		 val gcd=mv_gcd x y;
neuper@37906
  2473
	     in
neuper@37906
  2474
		 if gcd=[(1,mv_null2(#2(hd(x))))] then 
neuper@37906
  2475
		     ( 
neuper@37906
  2476
		      if exists_gcd(x,xs) then new_factors (y::xs @ [x])
neuper@37906
  2477
		      else x::new_factors(y::xs)
neuper@37906
  2478
	             )
neuper@37906
  2479
		 else gcd::new_factors(kill_equal(list_div(x::y::xs,gcd)))
neuper@37906
  2480
	     end
neuper@37906
  2481
	     )
neuper@37906
  2482
	else
neuper@37906
  2483
	    if len=1 then [hd(l)]
neuper@37906
  2484
	    else []
neuper@37906
  2485
    end;
neuper@37906
  2486
neuper@37906
  2487
(*. gets the factors of a list .*)
neuper@37906
  2488
fun get_factors x = new_factors x; 
neuper@37906
  2489
neuper@37906
  2490
(*. multiplies the elements of the list .*)
neuper@37906
  2491
fun multi_list [] = []
neuper@37906
  2492
  | multi_list (x::xs) = if xs=[] then x
neuper@37906
  2493
			 else mv_mul(x,multi_list xs,LEX_);
neuper@37906
  2494
neuper@37906
  2495
(*. makes a term out of the elements of the list (polynomial representation) .*)
neuper@37906
  2496
fun make_term ([],vars) = Free(str_of_int 0,HOLogic.realT) 
neuper@37906
  2497
  | make_term ((x::xs),vars) = if length(xs)=0 then poly2term(sort (mv_geq LEX_) (x),vars)
neuper@37906
  2498
			       else
neuper@37906
  2499
				   (
neuper@37906
  2500
				    Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2501
				    poly2term(sort (mv_geq LEX_) (x),vars) $ 
neuper@37906
  2502
				    make_term(xs,vars)
neuper@37906
  2503
				    );
neuper@37906
  2504
neuper@37906
  2505
(*. factorizes the denominator (polynomial representation) .*)				
neuper@37906
  2506
fun factorize_den (l,den,vars) = 
neuper@37906
  2507
    let
neuper@37906
  2508
	val factor_list=kill_equal( (get_factors l));
neuper@37906
  2509
	val mlist=multi_list(factor_list);
neuper@37906
  2510
	val (last,rest)=mv_division(den,multi_list(factor_list),LEX_);
neuper@37906
  2511
    in
neuper@37906
  2512
	if rest=[] then
neuper@37906
  2513
	    (
neuper@37906
  2514
	     if last=[(1,mv_null2(vars))] then make_term(factor_list,vars)
neuper@37906
  2515
	     else make_term(last::factor_list,vars)
neuper@37906
  2516
	     )
neuper@37906
  2517
	else raise error ("RATIONALS_FACTORIZE_DEN_EXCEPTION: Invalid factor by division")
neuper@37906
  2518
    end; 
neuper@37906
  2519
neuper@37906
  2520
(*. makes a term out of the elements of the list (expanded polynomial representation) .*)
neuper@37906
  2521
fun make_exp ([],vars) = Free(str_of_int 0,HOLogic.realT) 
neuper@37906
  2522
  | make_exp ((x::xs),vars) = if length(xs)=0 then poly2expanded(sort (mv_geq LEX_) (x),vars)
neuper@37906
  2523
			       else
neuper@37906
  2524
				   (
neuper@37906
  2525
				    Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2526
				    poly2expanded(sort (mv_geq LEX_) (x),vars) $ 
neuper@37906
  2527
				    make_exp(xs,vars)
neuper@37906
  2528
				    );
neuper@37906
  2529
neuper@37906
  2530
(*. factorizes the denominator (expanded polynomial representation) .*)	
neuper@37906
  2531
fun factorize_den_exp (l,den,vars) = 
neuper@37906
  2532
    let
neuper@37906
  2533
	val factor_list=kill_equal( (get_factors l));
neuper@37906
  2534
	val mlist=multi_list(factor_list);
neuper@37906
  2535
	val (last,rest)=mv_division(den,multi_list(factor_list),LEX_);
neuper@37906
  2536
    in
neuper@37906
  2537
	if rest=[] then
neuper@37906
  2538
	    (
neuper@37906
  2539
	     if last=[(1,mv_null2(vars))] then make_exp(factor_list,vars)
neuper@37906
  2540
	     else make_exp(last::factor_list,vars)
neuper@37906
  2541
	     )
neuper@37906
  2542
	else raise error ("RATIONALS_FACTORIZE_DEN_EXP_EXCEPTION: Invalid factor by division")
neuper@37906
  2543
    end; 
neuper@37906
  2544
neuper@37906
  2545
(*. calculates the common denominator of all elements of the list and multiplies .*)
neuper@37906
  2546
(*. the nominators and denominators with the correct factor .*)
neuper@37906
  2547
(*. (polynomial representation) .*)
neuper@37906
  2548
fun step_add_list_of_fractions []=(Free("0",HOLogic.realT),[]:term list)
neuper@37906
  2549
  | step_add_list_of_fractions [x]= raise error ("RATIONALS_STEP_ADD_LIST_OF_FRACTIONS_EXCEPTION: Nothing to add")
neuper@37906
  2550
  | step_add_list_of_fractions (xs) = 
neuper@37906
  2551
    let
neuper@37906
  2552
        val den_list=termlist2denominators (xs); (* list of denominators *)
neuper@37906
  2553
	val (denom,var)=calc_lcm(den_list);      (* common denominator *)
neuper@37906
  2554
	val den=factorize_den(#1(den_list),denom,var); (* faktorisierter Nenner !!! *)
neuper@37906
  2555
    in
neuper@37906
  2556
	com_den(xs,denom,den,var)
neuper@37906
  2557
    end;
neuper@37906
  2558
neuper@37906
  2559
(*. calculates the common denominator of all elements of the list and multiplies .*)
neuper@37906
  2560
(*. the nominators and denominators with the correct factor .*)
neuper@37906
  2561
(*. (expanded polynomial representation) .*)
neuper@37906
  2562
fun step_add_list_of_fractions_exp []  = (Free("0",HOLogic.realT),[]:term list)
neuper@37906
  2563
  | step_add_list_of_fractions_exp [x] = raise error ("RATIONALS_STEP_ADD_LIST_OF_FRACTIONS_EXP_EXCEPTION: Nothing to add")
neuper@37906
  2564
  | step_add_list_of_fractions_exp (xs)= 
neuper@37906
  2565
    let
neuper@37906
  2566
        val den_list=termlist2denominators_exp (xs); (* list of denominators *)
neuper@37906
  2567
	val (denom,var)=calc_lcm(den_list);      (* common denominator *)
neuper@37906
  2568
	val den=factorize_den_exp(#1(den_list),denom,var); (* faktorisierter Nenner !!! *)
neuper@37906
  2569
    in
neuper@37906
  2570
	com_den_exp(xs,denom,den,var)
neuper@37906
  2571
    end;
neuper@37906
  2572
neuper@37906
  2573
(* wird aktuell nicht mehr gebraucht, bei rückänderung schon 
neuper@37906
  2574
-------------------------------------------------------------
neuper@37906
  2575
(* WN0210???SK brauch ma des überhaupt *)
neuper@37906
  2576
fun step_add_list_of_fractions2 []=(Free("0",HOLogic.realT),[]:term list)
neuper@37906
  2577
  | step_add_list_of_fractions2 [x]=(x,[])
neuper@37906
  2578
  | step_add_list_of_fractions2 (xs) = 
neuper@37906
  2579
    let
neuper@37906
  2580
        val den_list=termlist2denominators (xs); (* list of denominators *)
neuper@37906
  2581
	val (denom,var)=calc_lcm(den_list);      (* common denominator *)
neuper@37906
  2582
	val den=factorize_den(#1(den_list),denom,var);  (* faktorisierter Nenner !!! *)
neuper@37906
  2583
    in
neuper@37906
  2584
	(
neuper@37906
  2585
	 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2586
	 com_den2(xs,denom, poly2term(denom,var)(*den*),var) $
neuper@37906
  2587
	 poly2term(denom,var)
neuper@37906
  2588
	,
neuper@37906
  2589
	[]
neuper@37906
  2590
	)
neuper@37906
  2591
    end;
neuper@37906
  2592
neuper@37906
  2593
(* WN0210???SK brauch ma des überhaupt *)
neuper@37906
  2594
fun step_add_list_of_fractions2_exp []=(Free("0",HOLogic.realT),[]:term list)
neuper@37906
  2595
  | step_add_list_of_fractions2_exp [x]=(x,[])
neuper@37906
  2596
  | step_add_list_of_fractions2_exp (xs) = 
neuper@37906
  2597
    let
neuper@37906
  2598
        val den_list=termlist2denominators_exp (xs); (* list of denominators *)
neuper@37906
  2599
	val (denom,var)=calc_lcm(den_list);      (* common denominator *)
neuper@37906
  2600
	val den=factorize_den_exp(#1(den_list),denom,var);  (* faktorisierter Nenner !!! *)
neuper@37906
  2601
    in
neuper@37906
  2602
	(
neuper@37906
  2603
	 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2604
	 com_den_exp2(xs,denom, poly2term(denom,var)(*den*),var) $
neuper@37906
  2605
	 poly2expanded(denom,var)
neuper@37906
  2606
	,
neuper@37906
  2607
	[]
neuper@37906
  2608
	)
neuper@37906
  2609
    end;
neuper@37906
  2610
---------------------------------------------- *)
neuper@37906
  2611
neuper@37906
  2612
neuper@37906
  2613
(*. converts a term, which contains severel terms seperated by +, into a list of these terms .*)
neuper@37906
  2614
fun term2list (t as (Const("HOL.divide",_) $ _ $ _)) = [t]
neuper@37906
  2615
  | term2list (t as (Const("Atools.pow",_) $ _ $ _)) = 
neuper@37906
  2616
    [Const("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2617
	  t $ Free("1",HOLogic.realT)
neuper@37906
  2618
     ]
neuper@37906
  2619
  | term2list (t as (Free(_,_))) = 
neuper@37906
  2620
    [Const("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2621
	  t $  Free("1",HOLogic.realT)
neuper@37906
  2622
     ]
neuper@37906
  2623
  | term2list (t as (Const("op *",_) $ _ $ _)) = 
neuper@37906
  2624
    [Const("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ 
neuper@37906
  2625
	  t $ Free("1",HOLogic.realT)
neuper@37906
  2626
     ]
neuper@37906
  2627
  | term2list (Const("op +",_) $ t1 $ t2) = term2list(t1) @ term2list(t2)
neuper@37906
  2628
  | term2list (Const("op -",_) $ t1 $ t2) = 
neuper@37906
  2629
    raise error ("RATIONALS_TERM2LIST_EXCEPTION: - not implemented yet")
neuper@37906
  2630
  | term2list _ = raise error ("RATIONALS_TERM2LIST_EXCEPTION: invalid term");
neuper@37906
  2631
neuper@37906
  2632
(*.factors out the gcd of nominator and denominator:
neuper@37906
  2633
   a/b = (a' * gcd)/(b' * gcd),  a,b,gcd  are poly[2].*)
neuper@37926
  2634
fun factout_p_  (thy:theory) t = SOME (step_cancel t,[]:term list); 
neuper@37926
  2635
fun factout_ (thy:theory) t = SOME (step_cancel_expanded t,[]:term list); 
neuper@37906
  2636
neuper@37906
  2637
(*.cancels a single fraction with normalform [2]
neuper@37906
  2638
   resulting in a canceled fraction [2], see factout_ .*)
neuper@37926
  2639
fun cancel_p_ (thy:theory) t = (*WN.2.6.03 no rewrite -> NONE !*)
neuper@37906
  2640
    (let val (t',asm) = direct_cancel(*_expanded ... corrected MG.21.8.03*) t
neuper@37926
  2641
     in if t = t' then NONE else SOME (t',asm) 
neuper@37926
  2642
     end) handle _ => NONE;
neuper@37906
  2643
(*.the same as above with normalform [3]
neuper@37906
  2644
  val cancel_ :
neuper@37906
  2645
      theory ->        (*10.02 unused                                    *)
neuper@37906
  2646
      term -> 	       (*fraction in normalform [3]                      *)
neuper@37906
  2647
      (term * 	       (*fraction in normalform [3]                      *)
neuper@37906
  2648
       term list)      (*casual asumptions in normalform [3]             *)
neuper@37926
  2649
	  option       (*NONE: the function is not applicable            *).*)
neuper@37926
  2650
fun cancel_ (thy:theory) t = SOME (direct_cancel_expanded t) handle _ => NONE;
neuper@37906
  2651
neuper@37906
  2652
(*.transforms sums of at least 2 fractions [3] to
neuper@37906
  2653
   sums with the least common multiple as nominator.*)
neuper@37906
  2654
fun common_nominator_p_ (thy:theory) t =
neuper@37906
  2655
((*writeln("### common_nominator_p_ called");*)
neuper@37926
  2656
    SOME (step_add_list_of_fractions(term2list(t))) handle _ => NONE
neuper@37906
  2657
);
neuper@37906
  2658
fun common_nominator_ (thy:theory) t =
neuper@37926
  2659
    SOME (step_add_list_of_fractions_exp(term2list(t))) handle _ => NONE;
neuper@37906
  2660
neuper@37906
  2661
(*.add 2 or more fractions
neuper@37906
  2662
val add_fraction_p_ :
neuper@37906
  2663
      theory ->        (*10.02 unused                                    *)
neuper@37906
  2664
      term -> 	       (*2 or more fractions with normalform [2]         *)
neuper@37906
  2665
      (term * 	       (*one fraction with normalform [2]                *)
neuper@37906
  2666
       term list)      (*casual assumptions in normalform [2] WN0210???SK  *)
neuper@37926
  2667
	  option       (*NONE: the function is not applicable            *).*)
neuper@37906
  2668
fun add_fraction_p_ (thy:theory) t = 
neuper@37906
  2669
(writeln("### add_fraction_p_ called");
neuper@37906
  2670
    (let val ts = term2list t
neuper@37906
  2671
     in if 1 < length ts
neuper@37926
  2672
	then SOME (add_list_of_fractions ts)
neuper@37926
  2673
	else NONE (*raise error ("RATIONALS_ADD_EXCEPTION: nothing to add")*)
neuper@37926
  2674
     end) handle _ => NONE
neuper@37906
  2675
);
neuper@37906
  2676
(*.same as add_fraction_p_ but with normalform [3].*)
neuper@37926
  2677
(*SOME (step_add_list_of_fractions2(term2list(t))); *)
neuper@37906
  2678
fun add_fraction_ (thy:theory) t = 
neuper@37906
  2679
    if length(term2list(t))>1 
neuper@37926
  2680
    then SOME (add_list_of_fractions_exp(term2list(t))) handle _ => NONE
neuper@37906
  2681
    else (*raise error ("RATIONALS_ADD_FRACTION_EXCEPTION: nothing to add")*)
neuper@37926
  2682
	NONE;
neuper@37906
  2683
fun add_fraction_ (thy:theory) t = 
neuper@37906
  2684
    (if 1 < length (term2list t)
neuper@37926
  2685
     then SOME (add_list_of_fractions_exp (term2list t))
neuper@37906
  2686
     else (*raise error ("RATIONALS_ADD_FRACTION_EXCEPTION: nothing to add")*)
neuper@37926
  2687
	 NONE) handle _ => NONE;
neuper@37926
  2688
neuper@37926
  2689
(*SOME (step_add_list_of_fractions2_exp(term2list(t))); *)
neuper@37906
  2690
neuper@37906
  2691
(*. brings the term into a normal form .*)
neuper@37906
  2692
fun norm_rational_ (thy:theory) t = 
neuper@37926
  2693
    SOME (add_list_of_fractions(term2list(t))) handle _ => NONE; 
neuper@37906
  2694
fun norm_expanded_rat_ (thy:theory) t = 
neuper@37926
  2695
    SOME (add_list_of_fractions_exp(term2list(t))) handle _ => NONE; 
neuper@37906
  2696
neuper@37906
  2697
neuper@37906
  2698
(*.evaluates conditions in calculate_Rational.*)
neuper@37906
  2699
(*make local with FIXX@ME result:term *term list*)
neuper@37906
  2700
val calc_rat_erls = prep_rls(
neuper@37906
  2701
  Rls {id = "calc_rat_erls", preconds = [], rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  2702
	 erls = e_rls, srls = Erls, calc = [], (*asm_thm = [], *)
neuper@37906
  2703
	 rules = 
neuper@37906
  2704
	 [Calc ("op =",eval_equal "#equal_"),
neuper@37906
  2705
	  Calc ("Atools.is'_const",eval_const "#is_const_"),
neuper@37906
  2706
	  Thm ("not_true",num_str not_true),
neuper@37906
  2707
	  Thm ("not_false",num_str not_false)
neuper@37906
  2708
	  ], 
neuper@37906
  2709
	 scr = EmptyScr});
neuper@37906
  2710
neuper@37906
  2711
neuper@37906
  2712
(*.simplifies expressions with numerals;
neuper@37906
  2713
   does NOT rearrange the term by AC-rewriting; thus terms with variables 
neuper@37906
  2714
   need to have constants to be commuted together respectively.*)
neuper@37906
  2715
val calculate_Rational = prep_rls(
neuper@37906
  2716
    merge_rls "calculate_Rational"
neuper@37906
  2717
	(Rls {id = "divide", preconds = [], rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  2718
	      erls = calc_rat_erls, srls = Erls, (*asm_thm = [],*) 
neuper@37906
  2719
	      calc = [], 
neuper@37906
  2720
	      rules = 
neuper@37906
  2721
	      [Calc ("HOL.divide"  ,eval_cancel "#divide_"),
neuper@37906
  2722
	       
neuper@37906
  2723
	       Thm ("sym_real_minus_divide_eq",
neuper@37906
  2724
		    num_str (real_minus_divide_eq RS sym)),
neuper@37906
  2725
	       (*SYM - ?x / ?y = - (?x / ?y)  may come from subst*)
neuper@37906
  2726
	       
neuper@37906
  2727
	       Thm ("rat_add",num_str rat_add),
neuper@37906
  2728
	       (*"[| a is_const; b is_const; c is_const; d is_const |] ==> \
neuper@37906
  2729
		 \"a / c + b / d = (a * d) / (c * d) + (b * c ) / (d * c)"*)
neuper@37906
  2730
	       Thm ("rat_add1",num_str rat_add1),
neuper@37906
  2731
	       (*"[| a is_const; b is_const; c is_const |] ==> \
neuper@37906
  2732
		 \"a / c + b / c = (a + b) / c"*)
neuper@37906
  2733
	       Thm ("rat_add2",num_str rat_add2),
neuper@37906
  2734
	       (*"[| ?a is_const; ?b is_const; ?c is_const |] ==> \
neuper@37906
  2735
		 \?a / ?c + ?b = (?a + ?b * ?c) / ?c"*)
neuper@37906
  2736
	       Thm ("rat_add3",num_str rat_add3),
neuper@37906
  2737
	       (*"[| a is_const; b is_const; c is_const |] ==> \
neuper@37906
  2738
		 \"a + b / c = (a * c) / c + b / c"\
neuper@37906
  2739
		 \.... is_const to be omitted here FIXME*)
neuper@37906
  2740
	       
neuper@37906
  2741
	       Thm ("rat_mult",num_str rat_mult),
neuper@37906
  2742
	       (*a / b * (c / d) = a * c / (b * d)*)
neuper@37906
  2743
	       Thm ("real_times_divide1_eq",num_str real_times_divide1_eq),
neuper@37906
  2744
	       (*?x * (?y / ?z) = ?x * ?y / ?z*)
neuper@37906
  2745
	       Thm ("real_times_divide2_eq",num_str real_times_divide2_eq),
neuper@37906
  2746
	       (*?y / ?z * ?x = ?y * ?x / ?z*)
neuper@37906
  2747
	       
neuper@37906
  2748
	       Thm ("real_divide_divide1",num_str real_divide_divide1),
neuper@37906
  2749
	       (*"?y ~= 0 ==> ?u / ?v / (?y / ?z) = ?u / ?v * (?z / ?y)"*)
neuper@37906
  2750
	       Thm ("real_divide_divide2_eq",num_str real_divide_divide2_eq),
neuper@37906
  2751
	       (*"?x / ?y / ?z = ?x / (?y * ?z)"*)
neuper@37906
  2752
	       
neuper@37906
  2753
	       Thm ("rat_power", num_str rat_power),
neuper@37906
  2754
	       (*"(?a / ?b) ^^^ ?n = ?a ^^^ ?n / ?b ^^^ ?n"*)
neuper@37906
  2755
	       
neuper@37906
  2756
	       Thm ("mult_cross",num_str mult_cross),
neuper@37906
  2757
	       (*"[| b ~= 0; d ~= 0 |] ==> (a / b = c / d) = (a * d = b * c)*)
neuper@37906
  2758
	       Thm ("mult_cross1",num_str mult_cross1),
neuper@37906
  2759
	       (*"   b ~= 0            ==> (a / b = c    ) = (a     = b * c)*)
neuper@37906
  2760
	       Thm ("mult_cross2",num_str mult_cross2)
neuper@37906
  2761
	       (*"           d ~= 0    ==> (a     = c / d) = (a * d =     c)*)
neuper@37906
  2762
	       ], scr = EmptyScr})
neuper@37906
  2763
	calculate_Poly);
neuper@37906
  2764
neuper@37906
  2765
neuper@37906
  2766
(*("is_expanded", ("Rational.is'_expanded", eval_is_expanded ""))*)
neuper@37906
  2767
fun eval_is_expanded (thmid:string) _ 
neuper@37906
  2768
		       (t as (Const("Rational.is'_expanded", _) $ arg)) thy = 
neuper@37906
  2769
    if is_expanded arg
neuper@37926
  2770
    then SOME (mk_thmid thmid "" 
neuper@37938
  2771
			((Syntax.string_of_term (thy2ctxt thy)) arg) "", 
neuper@37906
  2772
	       Trueprop $ (mk_equality (t, HOLogic.true_const)))
neuper@37926
  2773
    else SOME (mk_thmid thmid "" 
neuper@37938
  2774
			((Syntax.string_of_term (thy2ctxt thy)) arg) "", 
neuper@37906
  2775
	       Trueprop $ (mk_equality (t, HOLogic.false_const)))
neuper@37926
  2776
  | eval_is_expanded _ _ _ _ = NONE; 
neuper@37906
  2777
neuper@37906
  2778
val rational_erls = 
neuper@37906
  2779
    merge_rls "rational_erls" calculate_Rational 
neuper@37906
  2780
	      (append_rls "is_expanded" Atools_erls 
neuper@37906
  2781
			  [Calc ("Rational.is'_expanded", eval_is_expanded "")
neuper@37906
  2782
			   ]);
neuper@37906
  2783
neuper@37906
  2784
neuper@37906
  2785
neuper@37906
  2786
(*.3 'reverse-rewrite-sets' for symbolic computation on rationals:
neuper@37906
  2787
 =================================================================
neuper@37906
  2788
 A[2] 'cancel_p': .
neuper@37906
  2789
 A[3] 'cancel': .
neuper@37906
  2790
 B[2] 'common_nominator_p': transforms summands in a term [2]
neuper@37906
  2791
         to fractions with the (least) common multiple as nominator.
neuper@37906
  2792
 B[3] 'norm_rational': normalizes arbitrary algebraic terms (without 
neuper@37906
  2793
         radicals and transzendental functions) to one canceled fraction,
neuper@37906
  2794
	 nominator and denominator in polynomial form.
neuper@37906
  2795
neuper@37906
  2796
In order to meet isac's requirements for interactive and stepwise calculation,
neuper@37906
  2797
each 'reverse-rewerite-set' consists of an initialization for the interpreter 
neuper@37906
  2798
state and of 4 functions, each of which employs rewriting as much as possible.
neuper@37906
  2799
The signature of these functions are the same in each 'reverse-rewrite-set' 
neuper@37906
  2800
respectively.*)
neuper@37906
  2801
neuper@37906
  2802
(* ************************************************************************* *)
neuper@37906
  2803
neuper@37906
  2804
neuper@37906
  2805
local(*. cancel_p
neuper@37906
  2806
------------------------
neuper@37906
  2807
cancels a single fraction consisting of two (uni- or multivariate)
neuper@37906
  2808
polynomials WN0609???SK[2] into another such a fraction; examples:
neuper@37906
  2809
neuper@37906
  2810
	   a^2 + -1*b^2         a + b
neuper@37906
  2811
        -------------------- = ---------
neuper@37906
  2812
	a^2 + -2*a*b + b^2     a + -1*b
neuper@37906
  2813
neuper@37906
  2814
        a^2    a
neuper@37906
  2815
        --- = ---
neuper@37906
  2816
         a     1
neuper@37906
  2817
neuper@37906
  2818
Remark: the reverse ruleset does _NOT_ work properly with other input !.*)
neuper@37906
  2819
(*WN020824 wir werden "uberlegen, wie wir ungeeignete inputs zur"uckweisen*)
neuper@37906
  2820
neuper@37906
  2821
val {rules, rew_ord=(_,ro),...} =
neuper@37906
  2822
    rep_rls (assoc_rls "make_polynomial");
neuper@37906
  2823
(*WN060829 ... make_deriv does not terminate with 1st expl above,
neuper@37906
  2824
           see rational.sml --- investigate rulesets for cancel_p ---*)
neuper@37906
  2825
val {rules, rew_ord=(_,ro),...} =
neuper@37906
  2826
    rep_rls (assoc_rls "rev_rew_p");
neuper@37906
  2827
neuper@37906
  2828
val thy = Rational.thy;
neuper@37906
  2829
neuper@37906
  2830
(*.init_state = fn : term -> istate
neuper@37906
  2831
initialzies the state of the script interpreter. The state is:
neuper@37906
  2832
neuper@37906
  2833
type rrlsstate =      (*state for reverse rewriting*)
neuper@37906
  2834
     (term *          (*the current formula*)
neuper@37906
  2835
      term *          (*the final term*)
neuper@37906
  2836
      rule list       (*'reverse rule list' (#)*)
neuper@37906
  2837
	    list *    (*may be serveral, eg. in norm_rational*)
neuper@37906
  2838
      (rule *         (*Thm (+ Thm generated from Calc) resulting in ...*)
neuper@37906
  2839
       (term *        (*... rewrite with ...*)
neuper@37906
  2840
	term list))   (*... assumptions*)
neuper@37906
  2841
	  list);      (*derivation from given term to normalform
neuper@37906
  2842
		       in reverse order with sym_thm;
neuper@37906
  2843
                       (#) could be extracted from here by (map #1)*).*)
neuper@37906
  2844
(* val {rules, rew_ord=(_,ro),...} =
neuper@37906
  2845
       rep_rls (assoc_rls "rev_rew_p")        (*USE ALWAYS, SEE val cancel_p*);
neuper@37906
  2846
   val (thy, eval_rls, ro) =(Rational.thy, Atools_erls, ro) (*..val cancel_p*);
neuper@37906
  2847
   val t = t;
neuper@37906
  2848
   *)
neuper@37906
  2849
fun init_state thy eval_rls ro t =
neuper@37926
  2850
    let val SOME (t',_) = factout_p_ thy t
neuper@37926
  2851
        val SOME (t'',asm) = cancel_p_ thy t
neuper@37926
  2852
        val der = reverse_deriv thy eval_rls rules ro NONE t'
neuper@37906
  2853
        val der = der @ [(Thm ("real_mult_div_cancel2",
neuper@37906
  2854
			       num_str real_mult_div_cancel2),
neuper@37906
  2855
			  (t'',asm))]
neuper@37906
  2856
        val rs = (distinct_Thm o (map #1)) der
neuper@37906
  2857
	val rs = filter_out (eq_Thms ["sym_real_add_zero_left",
neuper@37906
  2858
				      "sym_real_mult_0",
neuper@37906
  2859
				      "sym_real_mult_1"
neuper@37906
  2860
				      (*..insufficient,eg.make_Polynomial*)])rs
neuper@37906
  2861
    in (t,t'',[rs(*here only _ONE_ to ease locate_rule*)],der) end;
neuper@37906
  2862
neuper@37906
  2863
(*.locate_rule = fn : rule list -> term -> rule
neuper@37906
  2864
		      -> (rule * (term * term list) option) list.
neuper@37906
  2865
  checks a rule R for being a cancel-rule, and if it is,
neuper@37906
  2866
  then return the list of rules (+ the terms they are rewriting to)
neuper@37906
  2867
  which need to be applied before R should be applied.
neuper@37906
  2868
  precondition: the rule is applicable to the argument-term.
neuper@37906
  2869
arguments:
neuper@37906
  2870
  rule list: the reverse rule list
neuper@37906
  2871
  -> term  : ... to which the rule shall be applied
neuper@37906
  2872
  -> rule  : ... to be applied to term
neuper@37906
  2873
value:
neuper@37906
  2874
  -> (rule           : a rule rewriting to ...
neuper@37906
  2875
      * (term        : ... the resulting term ...
neuper@37906
  2876
         * term list): ... with the assumptions ( //#0).
neuper@37906
  2877
      ) list         : there may be several such rules;
neuper@37906
  2878
		       the list is empty, if the rule has nothing to do
neuper@37906
  2879
		       with cancelation.*)
neuper@37906
  2880
(* val () = ();
neuper@37906
  2881
   *)
neuper@37906
  2882
fun locate_rule thy eval_rls ro [rs] t r =
neuper@37906
  2883
    if (id_of_thm r) mem (map (id_of_thm)) rs
neuper@37906
  2884
    then let val ropt =
neuper@37906
  2885
		 rewrite_ thy ro eval_rls true (thm_of_thm r) t;
neuper@37906
  2886
	 in case ropt of
neuper@37926
  2887
		SOME ta => [(r, ta)]
neuper@37926
  2888
	      | NONE => (writeln("### locate_rule:  rewrite "^
neuper@37926
  2889
				 (id_of_thm r)^" "^(term2str t)^" = NONE");
neuper@37906
  2890
			 []) end
neuper@37906
  2891
    else (writeln("### locate_rule:  "^(id_of_thm r)^" not mem rrls");[])
neuper@37906
  2892
  | locate_rule _ _ _ _ _ _ =
neuper@37906
  2893
    raise error ("locate_rule: doesnt match rev-sets in istate");
neuper@37906
  2894
neuper@37906
  2895
(*.next_rule = fn : rule list -> term -> rule option
neuper@37906
  2896
  for a given term return the next rules to be done for cancelling.
neuper@37906
  2897
arguments:
neuper@37906
  2898
  rule list     : the reverse rule list
neuper@37906
  2899
  term          : the term for which ...
neuper@37906
  2900
value:
neuper@37906
  2901
  -> rule option: ... this rule is appropriate for cancellation;
neuper@37906
  2902
		  there may be no such rule (if the term is canceled already.*)
neuper@37906
  2903
(* val thy = Rational.thy;
neuper@37906
  2904
   val Rrls {rew_ord=(_,ro),...} = cancel;
neuper@37906
  2905
   val ([rs],t) = (rss,f);
neuper@37906
  2906
   next_rule thy eval_rls ro [rs] t;(*eval fun next_rule ... before!*)
neuper@37906
  2907
neuper@37906
  2908
   val (thy, [rs]) = (Rational.thy, revsets);
neuper@37906
  2909
   val Rrls {rew_ord=(_,ro),...} = cancel;
neuper@37906
  2910
   nex [rs] t;
neuper@37906
  2911
   *)
neuper@37906
  2912
fun next_rule thy eval_rls ro [rs] t =
neuper@37926
  2913
    let val der = make_deriv thy eval_rls rs ro NONE t;
neuper@37906
  2914
    in case der of
neuper@37906
  2915
(* val (_,r,_)::_ = der;
neuper@37906
  2916
   *)
neuper@37926
  2917
	   (_,r,_)::_ => SOME r
neuper@37926
  2918
	 | _ => NONE
neuper@37906
  2919
    end
neuper@37906
  2920
  | next_rule _ _ _ _ _ =
neuper@37906
  2921
    raise error ("next_rule: doesnt match rev-sets in istate");
neuper@37906
  2922
neuper@37906
  2923
(*.val attach_form = f : rule list -> term -> term
neuper@37906
  2924
			 -> (rule * (term * term list)) list
neuper@37906
  2925
  checks an input term TI, if it may belong to a current cancellation, by
neuper@37906
  2926
  trying to derive it from the given term TG.
neuper@37906
  2927
arguments:
neuper@37906
  2928
  term   : TG, the last one in the cancellation agreed upon by user + math-eng
neuper@37906
  2929
  -> term: TI, the next one input by the user
neuper@37906
  2930
value:
neuper@37906
  2931
  -> (rule           : the rule to be applied in order to reach TI
neuper@37906
  2932
      * (term        : ... obtained by applying the rule ...
neuper@37906
  2933
         * term list): ... and the respective assumptions.
neuper@37906
  2934
      ) list         : there may be several such rules;
neuper@37906
  2935
                       the list is empty, if the users term does not belong
neuper@37906
  2936
		       to a cancellation of the term last agreed upon.*)
neuper@37906
  2937
fun attach_form (_:rule list list) (_:term) (_:term) = (*still missing*)
neuper@37906
  2938
    []:(rule * (term * term list)) list;
neuper@37906
  2939
neuper@37906
  2940
in
neuper@37906
  2941
neuper@37906
  2942
val cancel_p =
neuper@37906
  2943
    Rrls {id = "cancel_p", prepat=[],
neuper@37906
  2944
	  rew_ord=("ord_make_polynomial",
neuper@37906
  2945
		   ord_make_polynomial false Rational.thy),
neuper@37906
  2946
	  erls = rational_erls,
neuper@37922
  2947
	  calc = [("PLUS"    ,("op +"        ,eval_binop "#add_")),
neuper@37922
  2948
		  ("TIMES"   ,("op *"        ,eval_binop "#mult_")),
neuper@37922
  2949
		  ("DIVIDE" ,("HOL.divide"  ,eval_cancel "#divide_")),
neuper@37922
  2950
		  ("POWER"  ,("Atools.pow"  ,eval_binop "#power_"))],
neuper@37906
  2951
	  (*asm_thm=[("real_mult_div_cancel2","")],*)
neuper@37906
  2952
	  scr=Rfuns {init_state  = init_state thy Atools_erls ro,
neuper@37906
  2953
		     normal_form = cancel_p_ thy,
neuper@37906
  2954
		     locate_rule = locate_rule thy Atools_erls ro,
neuper@37906
  2955
		     next_rule   = next_rule thy Atools_erls ro,
neuper@37906
  2956
		     attach_form = attach_form}}
neuper@37906
  2957
end;(*local*)
neuper@37906
  2958
neuper@37906
  2959
neuper@37906
  2960
local(*.ad (1) 'cancel'
neuper@37906
  2961
------------------------------
neuper@37906
  2962
cancels a single fraction consisting of two (uni- or multivariate)
neuper@37906
  2963
polynomials WN0609???SK[3] into another such a fraction; examples:
neuper@37906
  2964
neuper@37906
  2965
	   a^2 - b^2           a + b
neuper@37906
  2966
        -------------------- = ---------
neuper@37906
  2967
	a^2 - 2*a*b + b^2      a - *b
neuper@37906
  2968
neuper@37906
  2969
Remark: the reverse ruleset does _NOT_ work properly with other input !.*)
neuper@37906
  2970
(*WN 24.8.02: wir werden "uberlegen, wie wir ungeeignete inputs zur"uckweisen*)
neuper@37906
  2971
neuper@37906
  2972
(*
neuper@37926
  2973
val SOME (Rls {rules=rules,rew_ord=(_,ro),...}) = 
neuper@37906
  2974
    assoc'(!ruleset',"expand_binoms");
neuper@37906
  2975
*)
neuper@37906
  2976
val {rules=rules,rew_ord=(_,ro),...} =
neuper@37906
  2977
    rep_rls (assoc_rls "expand_binoms");
neuper@37906
  2978
val thy = Rational.thy;
neuper@37906
  2979
neuper@37906
  2980
fun init_state thy eval_rls ro t =
neuper@37926
  2981
    let val SOME (t',_) = factout_ thy t;
neuper@37926
  2982
        val SOME (t'',asm) = cancel_ thy t;
neuper@37926
  2983
        val der = reverse_deriv thy eval_rls rules ro NONE t';
neuper@37906
  2984
        val der = der @ [(Thm ("real_mult_div_cancel2",
neuper@37906
  2985
			       num_str real_mult_div_cancel2),
neuper@37906
  2986
			  (t'',asm))]
neuper@37906
  2987
        val rs = map #1 der;
neuper@37906
  2988
    in (t,t'',[rs],der) end;
neuper@37906
  2989
neuper@37906
  2990
fun locate_rule thy eval_rls ro [rs] t r =
neuper@37906
  2991
    if (id_of_thm r) mem (map (id_of_thm)) rs
neuper@37906
  2992
    then let val ropt = 
neuper@37906
  2993
		 rewrite_ thy ro eval_rls true (thm_of_thm r) t;
neuper@37906
  2994
	 in case ropt of
neuper@37926
  2995
		SOME ta => [(r, ta)]
neuper@37926
  2996
	      | NONE => (writeln("### locate_rule:  rewrite "^
neuper@37926
  2997
				 (id_of_thm r)^" "^(term2str t)^" = NONE");
neuper@37906
  2998
			 []) end
neuper@37906
  2999
    else (writeln("### locate_rule:  "^(id_of_thm r)^" not mem rrls");[])
neuper@37906
  3000
  | locate_rule _ _ _ _ _ _ = 
neuper@37906
  3001
    raise error ("locate_rule: doesnt match rev-sets in istate");
neuper@37906
  3002
neuper@37906
  3003
fun next_rule thy eval_rls ro [rs] t =
neuper@37926
  3004
    let val der = make_deriv thy eval_rls rs ro NONE t;
neuper@37906
  3005
    in case der of 
neuper@37906
  3006
(* val (_,r,_)::_ = der;
neuper@37906
  3007
   *)
neuper@37926
  3008
	   (_,r,_)::_ => SOME r
neuper@37926
  3009
	 | _ => NONE
neuper@37906
  3010
    end
neuper@37906
  3011
  | next_rule _ _ _ _ _ = 
neuper@37906
  3012
    raise error ("next_rule: doesnt match rev-sets in istate");
neuper@37906
  3013
neuper@37906
  3014
fun attach_form (_:rule list list) (_:term) (_:term) = (*still missing*)
neuper@37906
  3015
    []:(rule * (term * term list)) list;
neuper@37906
  3016
neuper@37906
  3017
val pat = (term_of o the o (parse thy)) "?r/?s";
neuper@37906
  3018
val pre1 = (term_of o the o (parse thy)) "?r is_expanded";
neuper@37906
  3019
val pre2 = (term_of o the o (parse thy)) "?s is_expanded";
neuper@37906
  3020
val prepat = [([pre1, pre2], pat)];
neuper@37906
  3021
neuper@37906
  3022
in
neuper@37906
  3023
neuper@37906
  3024
neuper@37906
  3025
val cancel = 
neuper@37906
  3026
    Rrls {id = "cancel", prepat=prepat,
neuper@37906
  3027
	  rew_ord=("ord_make_polynomial",
neuper@37906
  3028
		   ord_make_polynomial false Rational.thy),
neuper@37906
  3029
	  erls = rational_erls, 
neuper@37922
  3030
	  calc = [("PLUS"    ,("op +"        ,eval_binop "#add_")),
neuper@37922
  3031
		  ("TIMES"   ,("op *"        ,eval_binop "#mult_")),
neuper@37922
  3032
		  ("DIVIDE" ,("HOL.divide"  ,eval_cancel "#divide_")),
neuper@37922
  3033
		  ("POWER"  ,("Atools.pow"  ,eval_binop "#power_"))],
neuper@37906
  3034
	  scr=Rfuns {init_state  = init_state thy Atools_erls ro,
neuper@37906
  3035
		     normal_form = cancel_ thy, 
neuper@37906
  3036
		     locate_rule = locate_rule thy Atools_erls ro,
neuper@37906
  3037
		     next_rule   = next_rule thy Atools_erls ro,
neuper@37906
  3038
		     attach_form = attach_form}}
neuper@37906
  3039
end;(*local*)
neuper@37906
  3040
neuper@37906
  3041
neuper@37906
  3042
neuper@37906
  3043
local(*.ad [2] 'common_nominator_p'
neuper@37906
  3044
---------------------------------
neuper@37906
  3045
FIXME Beschreibung .*)
neuper@37906
  3046
neuper@37906
  3047
neuper@37906
  3048
val {rules=rules,rew_ord=(_,ro),...} =
neuper@37906
  3049
    rep_rls (assoc_rls "make_polynomial");
neuper@37906
  3050
(*WN060829 ... make_deriv does not terminate with 1st expl above,
neuper@37906
  3051
           see rational.sml --- investigate rulesets for cancel_p ---*)
neuper@37906
  3052
val {rules, rew_ord=(_,ro),...} =
neuper@37906
  3053
    rep_rls (assoc_rls "rev_rew_p");
neuper@37906
  3054
val thy = Rational.thy;
neuper@37906
  3055
neuper@37906
  3056
neuper@37906
  3057
(*.common_nominator_p_ = fn : theory -> term -> (term * term list) option
neuper@37906
  3058
  as defined above*)
neuper@37906
  3059
neuper@37906
  3060
(*.init_state = fn : term -> istate
neuper@37906
  3061
initialzies the state of the interactive interpreter. The state is:
neuper@37906
  3062
neuper@37906
  3063
type rrlsstate =      (*state for reverse rewriting*)
neuper@37906
  3064
     (term *          (*the current formula*)
neuper@37906
  3065
      term *          (*the final term*)
neuper@37906
  3066
      rule list       (*'reverse rule list' (#)*)
neuper@37906
  3067
	    list *    (*may be serveral, eg. in norm_rational*)
neuper@37906
  3068
      (rule *         (*Thm (+ Thm generated from Calc) resulting in ...*)
neuper@37906
  3069
       (term *        (*... rewrite with ...*)
neuper@37906
  3070
	term list))   (*... assumptions*)
neuper@37906
  3071
	  list);      (*derivation from given term to normalform
neuper@37906
  3072
		       in reverse order with sym_thm;
neuper@37906
  3073
                       (#) could be extracted from here by (map #1)*).*)
neuper@37906
  3074
fun init_state thy eval_rls ro t =
neuper@37926
  3075
    let val SOME (t',_) = common_nominator_p_ thy t;
neuper@37926
  3076
        val SOME (t'',asm) = add_fraction_p_ thy t;
neuper@37926
  3077
        val der = reverse_deriv thy eval_rls rules ro NONE t';
neuper@37906
  3078
        val der = der @ [(Thm ("real_mult_div_cancel2",
neuper@37906
  3079
			       num_str real_mult_div_cancel2),
neuper@37906
  3080
			  (t'',asm))]
neuper@37906
  3081
        val rs = (distinct_Thm o (map #1)) der;
neuper@37906
  3082
	val rs = filter_out (eq_Thms ["sym_real_add_zero_left",
neuper@37906
  3083
				      "sym_real_mult_0",
neuper@37906
  3084
				      "sym_real_mult_1"]) rs;
neuper@37906
  3085
    in (t,t'',[rs(*here only _ONE_*)],der) end;
neuper@37906
  3086
neuper@37906
  3087
(* use"knowledge/Rational.ML";
neuper@37906
  3088
   *)
neuper@37906
  3089
neuper@37906
  3090
(*.locate_rule = fn : rule list -> term -> rule
neuper@37906
  3091
		      -> (rule * (term * term list) option) list.
neuper@37906
  3092
  checks a rule R for being a cancel-rule, and if it is,
neuper@37906
  3093
  then return the list of rules (+ the terms they are rewriting to)
neuper@37906
  3094
  which need to be applied before R should be applied.
neuper@37906
  3095
  precondition: the rule is applicable to the argument-term.
neuper@37906
  3096
arguments:
neuper@37906
  3097
  rule list: the reverse rule list
neuper@37906
  3098
  -> term  : ... to which the rule shall be applied
neuper@37906
  3099
  -> rule  : ... to be applied to term
neuper@37906
  3100
value:
neuper@37906
  3101
  -> (rule           : a rule rewriting to ...
neuper@37906
  3102
      * (term        : ... the resulting term ...
neuper@37906
  3103
         * term list): ... with the assumptions ( //#0).
neuper@37906
  3104
      ) list         : there may be several such rules;
neuper@37906
  3105
		       the list is empty, if the rule has nothing to do
neuper@37906
  3106
		       with cancelation.*)
neuper@37906
  3107
(* val () = ();
neuper@37906
  3108
   *)
neuper@37906
  3109
fun locate_rule thy eval_rls ro [rs] t r =
neuper@37906
  3110
    if (id_of_thm r) mem (map (id_of_thm)) rs
neuper@37906
  3111
    then let val ropt =
neuper@37906
  3112
		 rewrite_ thy ro eval_rls true (thm_of_thm r) t;
neuper@37906
  3113
	 in case ropt of
neuper@37926
  3114
		SOME ta => [(r, ta)]
neuper@37926
  3115
	      | NONE => (writeln("### locate_rule:  rewrite "^
neuper@37926
  3116
				 (id_of_thm r)^" "^(term2str t)^" = NONE");
neuper@37906
  3117
			 []) end
neuper@37906
  3118
    else (writeln("### locate_rule:  "^(id_of_thm r)^" not mem rrls");[])
neuper@37906
  3119
  | locate_rule _ _ _ _ _ _ =
neuper@37906
  3120
    raise error ("locate_rule: doesnt match rev-sets in istate");
neuper@37906
  3121
neuper@37906
  3122
(*.next_rule = fn : rule list -> term -> rule option
neuper@37906
  3123
  for a given term return the next rules to be done for cancelling.
neuper@37906
  3124
arguments:
neuper@37906
  3125
  rule list     : the reverse rule list
neuper@37906
  3126
  term          : the term for which ...
neuper@37906
  3127
value:
neuper@37906
  3128
  -> rule option: ... this rule is appropriate for cancellation;
neuper@37906
  3129
		  there may be no such rule (if the term is canceled already.*)
neuper@37906
  3130
(* val thy = Rational.thy;
neuper@37906
  3131
   val Rrls {rew_ord=(_,ro),...} = cancel;
neuper@37906
  3132
   val ([rs],t) = (rss,f);
neuper@37906
  3133
   next_rule thy eval_rls ro [rs] t;(*eval fun next_rule ... before!*)
neuper@37906
  3134
neuper@37906
  3135
   val (thy, [rs]) = (Rational.thy, revsets);
neuper@37906
  3136
   val Rrls {rew_ord=(_,ro),...} = cancel;
neuper@37906
  3137
   nex [rs] t;
neuper@37906
  3138
   *)
neuper@37906
  3139
fun next_rule thy eval_rls ro [rs] t =
neuper@37926
  3140
    let val der = make_deriv thy eval_rls rs ro NONE t;
neuper@37906
  3141
    in case der of
neuper@37906
  3142
(* val (_,r,_)::_ = der;
neuper@37906
  3143
   *)
neuper@37926
  3144
	   (_,r,_)::_ => SOME r
neuper@37926
  3145
	 | _ => NONE
neuper@37906
  3146
    end
neuper@37906
  3147
  | next_rule _ _ _ _ _ =
neuper@37906
  3148
    raise error ("next_rule: doesnt match rev-sets in istate");
neuper@37906
  3149
neuper@37906
  3150
(*.val attach_form = f : rule list -> term -> term
neuper@37906
  3151
			 -> (rule * (term * term list)) list
neuper@37906
  3152
  checks an input term TI, if it may belong to a current cancellation, by
neuper@37906
  3153
  trying to derive it from the given term TG.
neuper@37906
  3154
arguments:
neuper@37906
  3155
  term   : TG, the last one in the cancellation agreed upon by user + math-eng
neuper@37906
  3156
  -> term: TI, the next one input by the user
neuper@37906
  3157
value:
neuper@37906
  3158
  -> (rule           : the rule to be applied in order to reach TI
neuper@37906
  3159
      * (term        : ... obtained by applying the rule ...
neuper@37906
  3160
         * term list): ... and the respective assumptions.
neuper@37906
  3161
      ) list         : there may be several such rules;
neuper@37906
  3162
                       the list is empty, if the users term does not belong
neuper@37906
  3163
		       to a cancellation of the term last agreed upon.*)
neuper@37906
  3164
fun attach_form (_:rule list list) (_:term) (_:term) = (*still missing*)
neuper@37906
  3165
    []:(rule * (term * term list)) list;
neuper@37906
  3166
neuper@37906
  3167
val pat0 = (term_of o the o (parse thy)) "?r/?s+?u/?v";
neuper@37906
  3168
val pat1 = (term_of o the o (parse thy)) "?r/?s+?u   ";
neuper@37906
  3169
val pat2 = (term_of o the o (parse thy)) "?r   +?u/?v";
neuper@37906
  3170
val prepat = [([HOLogic.true_const], pat0),
neuper@37906
  3171
	      ([HOLogic.true_const], pat1),
neuper@37906
  3172
	      ([HOLogic.true_const], pat2)];
neuper@37906
  3173
neuper@37906
  3174
in
neuper@37906
  3175
neuper@37906
  3176
(*11.02 schnelle L"osung f"ur RL: Bruch auch gek"urzt;
neuper@37906
  3177
  besser w"are: auf 1 gemeinsamen Bruchstrich, Nenner und Z"ahler unvereinfacht
neuper@37906
  3178
  dh. wie common_nominator_p_, aber auf 1 Bruchstrich*)
neuper@37906
  3179
val common_nominator_p =
neuper@37906
  3180
    Rrls {id = "common_nominator_p", prepat=prepat,
neuper@37906
  3181
	  rew_ord=("ord_make_polynomial",
neuper@37906
  3182
		   ord_make_polynomial false Rational.thy),
neuper@37906
  3183
	  erls = rational_erls,
neuper@37922
  3184
	  calc = [("PLUS"    ,("op +"        ,eval_binop "#add_")),
neuper@37922
  3185
		  ("TIMES"   ,("op *"        ,eval_binop "#mult_")),
neuper@37922
  3186
		  ("DIVIDE" ,("HOL.divide"  ,eval_cancel "#divide_")),
neuper@37922
  3187
		  ("POWER"  ,("Atools.pow"  ,eval_binop "#power_"))],
neuper@37906
  3188
	  scr=Rfuns {init_state  = init_state thy Atools_erls ro,
neuper@37906
  3189
		     normal_form = add_fraction_p_ thy,(*FIXME.WN0211*)
neuper@37906
  3190
		     locate_rule = locate_rule thy Atools_erls ro,
neuper@37906
  3191
		     next_rule   = next_rule thy Atools_erls ro,
neuper@37906
  3192
		     attach_form = attach_form}}
neuper@37906
  3193
end;(*local*)
neuper@37906
  3194
neuper@37906
  3195
neuper@37906
  3196
local(*.ad [2] 'common_nominator'
neuper@37906
  3197
---------------------------------
neuper@37906
  3198
FIXME Beschreibung .*)
neuper@37906
  3199
neuper@37906
  3200
neuper@37906
  3201
val {rules=rules,rew_ord=(_,ro),...} =
neuper@37906
  3202
    rep_rls (assoc_rls "make_polynomial");
neuper@37906
  3203
val thy = Rational.thy;
neuper@37906
  3204
neuper@37906
  3205
neuper@37906
  3206
(*.common_nominator_ = fn : theory -> term -> (term * term list) option
neuper@37906
  3207
  as defined above*)
neuper@37906
  3208
neuper@37906
  3209
(*.init_state = fn : term -> istate
neuper@37906
  3210
initialzies the state of the interactive interpreter. The state is:
neuper@37906
  3211
neuper@37906
  3212
type rrlsstate =      (*state for reverse rewriting*)
neuper@37906
  3213
     (term *          (*the current formula*)
neuper@37906
  3214
      term *          (*the final term*)
neuper@37906
  3215
      rule list       (*'reverse rule list' (#)*)
neuper@37906
  3216
	    list *    (*may be serveral, eg. in norm_rational*)
neuper@37906
  3217
      (rule *         (*Thm (+ Thm generated from Calc) resulting in ...*)
neuper@37906
  3218
       (term *        (*... rewrite with ...*)
neuper@37906
  3219
	term list))   (*... assumptions*)
neuper@37906
  3220
	  list);      (*derivation from given term to normalform
neuper@37906
  3221
		       in reverse order with sym_thm;
neuper@37906
  3222
                       (#) could be extracted from here by (map #1)*).*)
neuper@37906
  3223
fun init_state thy eval_rls ro t =
neuper@37926
  3224
    let val SOME (t',_) = common_nominator_ thy t;
neuper@37926
  3225
        val SOME (t'',asm) = add_fraction_ thy t;
neuper@37926
  3226
        val der = reverse_deriv thy eval_rls rules ro NONE t';
neuper@37906
  3227
        val der = der @ [(Thm ("real_mult_div_cancel2",
neuper@37906
  3228
			       num_str real_mult_div_cancel2),
neuper@37906
  3229
			  (t'',asm))]
neuper@37906
  3230
        val rs = (distinct_Thm o (map #1)) der;
neuper@37906
  3231
	val rs = filter_out (eq_Thms ["sym_real_add_zero_left",
neuper@37906
  3232
				      "sym_real_mult_0",
neuper@37906
  3233
				      "sym_real_mult_1"]) rs;
neuper@37906
  3234
    in (t,t'',[rs(*here only _ONE_*)],der) end;
neuper@37906
  3235
neuper@37906
  3236
(* use"knowledge/Rational.ML";
neuper@37906
  3237
   *)
neuper@37906
  3238
neuper@37906
  3239
(*.locate_rule = fn : rule list -> term -> rule
neuper@37906
  3240
		      -> (rule * (term * term list) option) list.
neuper@37906
  3241
  checks a rule R for being a cancel-rule, and if it is,
neuper@37906
  3242
  then return the list of rules (+ the terms they are rewriting to)
neuper@37906
  3243
  which need to be applied before R should be applied.
neuper@37906
  3244
  precondition: the rule is applicable to the argument-term.
neuper@37906
  3245
arguments:
neuper@37906
  3246
  rule list: the reverse rule list
neuper@37906
  3247
  -> term  : ... to which the rule shall be applied
neuper@37906
  3248
  -> rule  : ... to be applied to term
neuper@37906
  3249
value:
neuper@37906
  3250
  -> (rule           : a rule rewriting to ...
neuper@37906
  3251
      * (term        : ... the resulting term ...
neuper@37906
  3252
         * term list): ... with the assumptions ( //#0).
neuper@37906
  3253
      ) list         : there may be several such rules;
neuper@37906
  3254
		       the list is empty, if the rule has nothing to do
neuper@37906
  3255
		       with cancelation.*)
neuper@37906
  3256
(* val () = ();
neuper@37906
  3257
   *)
neuper@37906
  3258
fun locate_rule thy eval_rls ro [rs] t r =
neuper@37906
  3259
    if (id_of_thm r) mem (map (id_of_thm)) rs
neuper@37906
  3260
    then let val ropt =
neuper@37906
  3261
		 rewrite_ thy ro eval_rls true (thm_of_thm r) t;
neuper@37906
  3262
	 in case ropt of
neuper@37926
  3263
		SOME ta => [(r, ta)]
neuper@37926
  3264
	      | NONE => (writeln("### locate_rule:  rewrite "^
neuper@37926
  3265
				 (id_of_thm r)^" "^(term2str t)^" = NONE");
neuper@37906
  3266
			 []) end
neuper@37906
  3267
    else (writeln("### locate_rule:  "^(id_of_thm r)^" not mem rrls");[])
neuper@37906
  3268
  | locate_rule _ _ _ _ _ _ =
neuper@37906
  3269
    raise error ("locate_rule: doesnt match rev-sets in istate");
neuper@37906
  3270
neuper@37906
  3271
(*.next_rule = fn : rule list -> term -> rule option
neuper@37906
  3272
  for a given term return the next rules to be done for cancelling.
neuper@37906
  3273
arguments:
neuper@37906
  3274
  rule list     : the reverse rule list
neuper@37906
  3275
  term          : the term for which ...
neuper@37906
  3276
value:
neuper@37906
  3277
  -> rule option: ... this rule is appropriate for cancellation;
neuper@37906
  3278
		  there may be no such rule (if the term is canceled already.*)
neuper@37906
  3279
(* val thy = Rational.thy;
neuper@37906
  3280
   val Rrls {rew_ord=(_,ro),...} = cancel;
neuper@37906
  3281
   val ([rs],t) = (rss,f);
neuper@37906
  3282
   next_rule thy eval_rls ro [rs] t;(*eval fun next_rule ... before!*)
neuper@37906
  3283
neuper@37906
  3284
   val (thy, [rs]) = (Rational.thy, revsets);
neuper@37906
  3285
   val Rrls {rew_ord=(_,ro),...} = cancel_p;
neuper@37906
  3286
   nex [rs] t;
neuper@37906
  3287
   *)
neuper@37906
  3288
fun next_rule thy eval_rls ro [rs] t =
neuper@37926
  3289
    let val der = make_deriv thy eval_rls rs ro NONE t;
neuper@37906
  3290
    in case der of
neuper@37906
  3291
(* val (_,r,_)::_ = der;
neuper@37906
  3292
   *)
neuper@37926
  3293
	   (_,r,_)::_ => SOME r
neuper@37926
  3294
	 | _ => NONE
neuper@37906
  3295
    end
neuper@37906
  3296
  | next_rule _ _ _ _ _ =
neuper@37906
  3297
    raise error ("next_rule: doesnt match rev-sets in istate");
neuper@37906
  3298
neuper@37906
  3299
(*.val attach_form = f : rule list -> term -> term
neuper@37906
  3300
			 -> (rule * (term * term list)) list
neuper@37906
  3301
  checks an input term TI, if it may belong to a current cancellation, by
neuper@37906
  3302
  trying to derive it from the given term TG.
neuper@37906
  3303
arguments:
neuper@37906
  3304
  term   : TG, the last one in the cancellation agreed upon by user + math-eng
neuper@37906
  3305
  -> term: TI, the next one input by the user
neuper@37906
  3306
value:
neuper@37906
  3307
  -> (rule           : the rule to be applied in order to reach TI
neuper@37906
  3308
      * (term        : ... obtained by applying the rule ...
neuper@37906
  3309
         * term list): ... and the respective assumptions.
neuper@37906
  3310
      ) list         : there may be several such rules;
neuper@37906
  3311
                       the list is empty, if the users term does not belong
neuper@37906
  3312
		       to a cancellation of the term last agreed upon.*)
neuper@37906
  3313
fun attach_form (_:rule list list) (_:term) (_:term) = (*still missing*)
neuper@37906
  3314
    []:(rule * (term * term list)) list;
neuper@37906
  3315
neuper@37906
  3316
val pat0 =  (term_of o the o (parse thy)) "?r/?s+?u/?v";
neuper@37906
  3317
val pat01 = (term_of o the o (parse thy)) "?r/?s-?u/?v";
neuper@37906
  3318
val pat1 =  (term_of o the o (parse thy)) "?r/?s+?u   ";
neuper@37906
  3319
val pat11 = (term_of o the o (parse thy)) "?r/?s-?u   ";
neuper@37906
  3320
val pat2 =  (term_of o the o (parse thy)) "?r   +?u/?v";
neuper@37906
  3321
val pat21 = (term_of o the o (parse thy)) "?r   -?u/?v";
neuper@37906
  3322
val prepat = [([HOLogic.true_const], pat0),
neuper@37906
  3323
	      ([HOLogic.true_const], pat01),
neuper@37906
  3324
	      ([HOLogic.true_const], pat1),
neuper@37906
  3325
	      ([HOLogic.true_const], pat11),
neuper@37906
  3326
	      ([HOLogic.true_const], pat2),
neuper@37906
  3327
	      ([HOLogic.true_const], pat21)];
neuper@37906
  3328
neuper@37906
  3329
neuper@37906
  3330
in
neuper@37906
  3331
neuper@37906
  3332
val common_nominator =
neuper@37906
  3333
    Rrls {id = "common_nominator", prepat=prepat,
neuper@37906
  3334
	  rew_ord=("ord_make_polynomial",
neuper@37906
  3335
		   ord_make_polynomial false Rational.thy),
neuper@37906
  3336
	  erls = rational_erls,
neuper@37922
  3337
	  calc = [("PLUS"    ,("op +"        ,eval_binop "#add_")),
neuper@37922
  3338
		  ("TIMES"   ,("op *"        ,eval_binop "#mult_")),
neuper@37922
  3339
		  ("DIVIDE" ,("HOL.divide"  ,eval_cancel "#divide_")),
neuper@37922
  3340
		  ("POWER"  ,("Atools.pow"  ,eval_binop "#power_"))],
neuper@37906
  3341
	  (*asm_thm=[("real_mult_div_cancel2","")],*)
neuper@37906
  3342
	  scr=Rfuns {init_state  = init_state thy Atools_erls ro,
neuper@37906
  3343
		     normal_form = add_fraction_ (*NOT common_nominator_*) thy,
neuper@37906
  3344
		     locate_rule = locate_rule thy Atools_erls ro,
neuper@37906
  3345
		     next_rule   = next_rule thy Atools_erls ro,
neuper@37906
  3346
		     attach_form = attach_form}}
neuper@37906
  3347
neuper@37906
  3348
end;(*local*)
neuper@37906
  3349
neuper@37906
  3350
neuper@37906
  3351
(*##*)
neuper@37906
  3352
end;(*struct*)
neuper@37906
  3353
neuper@37906
  3354
open RationalI;
neuper@37906
  3355
(*##*)
neuper@37906
  3356
neuper@37906
  3357
(*.the expression contains + - * ^ / only ?.*)
neuper@37906
  3358
fun is_ratpolyexp (Free _) = true
neuper@37906
  3359
  | is_ratpolyexp (Const ("op +",_) $ Free _ $ Free _) = true
neuper@37906
  3360
  | is_ratpolyexp (Const ("op -",_) $ Free _ $ Free _) = true
neuper@37906
  3361
  | is_ratpolyexp (Const ("op *",_) $ Free _ $ Free _) = true
neuper@37906
  3362
  | is_ratpolyexp (Const ("Atools.pow",_) $ Free _ $ Free _) = true
neuper@37906
  3363
  | is_ratpolyexp (Const ("HOL.divide",_) $ Free _ $ Free _) = true
neuper@37906
  3364
  | is_ratpolyexp (Const ("op +",_) $ t1 $ t2) = 
neuper@37906
  3365
               ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
neuper@37906
  3366
  | is_ratpolyexp (Const ("op -",_) $ t1 $ t2) = 
neuper@37906
  3367
               ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
neuper@37906
  3368
  | is_ratpolyexp (Const ("op *",_) $ t1 $ t2) = 
neuper@37906
  3369
               ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
neuper@37906
  3370
  | is_ratpolyexp (Const ("Atools.pow",_) $ t1 $ t2) = 
neuper@37906
  3371
               ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
neuper@37906
  3372
  | is_ratpolyexp (Const ("HOL.divide",_) $ t1 $ t2) = 
neuper@37906
  3373
               ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
neuper@37906
  3374
  | is_ratpolyexp _ = false;
neuper@37906
  3375
neuper@37906
  3376
(*("is_ratpolyexp", ("Rational.is'_ratpolyexp", eval_is_ratpolyexp ""))*)
neuper@37906
  3377
fun eval_is_ratpolyexp (thmid:string) _ 
neuper@37906
  3378
		       (t as (Const("Rational.is'_ratpolyexp", _) $ arg)) thy =
neuper@37906
  3379
    if is_ratpolyexp arg
neuper@37926
  3380
    then SOME (mk_thmid thmid "" 
neuper@37938
  3381
			((Syntax.string_of_term (thy2ctxt thy)) arg) "", 
neuper@37906
  3382
	       Trueprop $ (mk_equality (t, HOLogic.true_const)))
neuper@37926
  3383
    else SOME (mk_thmid thmid "" 
neuper@37938
  3384
			((Syntax.string_of_term (thy2ctxt thy)) arg) "", 
neuper@37906
  3385
	       Trueprop $ (mk_equality (t, HOLogic.false_const)))
neuper@37926
  3386
  | eval_is_ratpolyexp _ _ _ _ = NONE; 
neuper@37906
  3387
neuper@37906
  3388
neuper@37906
  3389
neuper@37906
  3390
(*-------------------18.3.03 --> struct <-----------vvv--*)
neuper@37906
  3391
val add_fractions_p = common_nominator_p; (*FIXXXME:eilig f"ur norm_Rational*)
neuper@37906
  3392
neuper@37906
  3393
(*.discard binary minus, shift unary minus into -1*; 
neuper@37906
  3394
   unary minus before numerals are put into the numeral by parsing;
neuper@37906
  3395
   contains absolute minimum of thms for context in norm_Rational .*)
neuper@37906
  3396
val discard_minus = prep_rls(
neuper@37906
  3397
  Rls {id = "discard_minus", preconds = [], rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  3398
      erls = e_rls, srls = Erls, calc = [], (*asm_thm = [],*)
neuper@37906
  3399
      rules = [Thm ("real_diff_minus", num_str real_diff_minus),
neuper@37906
  3400
	       (*"a - b = a + -1 * b"*)
neuper@37906
  3401
	       Thm ("sym_real_mult_minus1",num_str (real_mult_minus1 RS sym))
neuper@37906
  3402
	       (*- ?z = "-1 * ?z"*)
neuper@37906
  3403
	       ],
neuper@37906
  3404
      scr = Script ((term_of o the o (parse thy)) 
neuper@37906
  3405
      "empty_script")
neuper@37906
  3406
      }):rls;
neuper@37906
  3407
(*erls for calculate_Rational; make local with FIXX@ME result:term *term list*)
neuper@37906
  3408
val powers_erls = prep_rls(
neuper@37906
  3409
  Rls {id = "powers_erls", preconds = [], rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  3410
      erls = e_rls, srls = Erls, calc = [], (*asm_thm = [],*)
neuper@37906
  3411
      rules = [Calc ("Atools.is'_atom",eval_is_atom "#is_atom_"),
neuper@37906
  3412
	       Calc ("Atools.is'_even",eval_is_even "#is_even_"),
neuper@37906
  3413
	       Calc ("op <",eval_equ "#less_"),
neuper@37906
  3414
	       Thm ("not_false", not_false),
neuper@37906
  3415
	       Thm ("not_true", not_true),
neuper@37906
  3416
	       Calc ("op +",eval_binop "#add_")
neuper@37906
  3417
	       ],
neuper@37906
  3418
      scr = Script ((term_of o the o (parse thy)) 
neuper@37906
  3419
      "empty_script")
neuper@37906
  3420
      }:rls);
neuper@37906
  3421
(*.all powers over + distributed; atoms over * collected, other distributed
neuper@37906
  3422
   contains absolute minimum of thms for context in norm_Rational .*)
neuper@37906
  3423
val powers = prep_rls(
neuper@37906
  3424
  Rls {id = "powers", preconds = [], rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  3425
      erls = powers_erls, srls = Erls, calc = [], (*asm_thm = [],*)
neuper@37906
  3426
      rules = [Thm ("realpow_multI", num_str realpow_multI),
neuper@37906
  3427
	       (*"(r * s) ^^^ n = r ^^^ n * s ^^^ n"*)
neuper@37906
  3428
	       Thm ("realpow_pow",num_str realpow_pow),
neuper@37906
  3429
	       (*"(a ^^^ b) ^^^ c = a ^^^ (b * c)"*)
neuper@37906
  3430
	       Thm ("realpow_oneI",num_str realpow_oneI),
neuper@37906
  3431
	       (*"r ^^^ 1 = r"*)
neuper@37906
  3432
	       Thm ("realpow_minus_even",num_str realpow_minus_even),
neuper@37906
  3433
	       (*"n is_even ==> (- r) ^^^ n = r ^^^ n" ?-->discard_minus?*)
neuper@37906
  3434
	       Thm ("realpow_minus_odd",num_str realpow_minus_odd),
neuper@37906
  3435
	       (*"Not (n is_even) ==> (- r) ^^^ n = -1 * r ^^^ n"*)
neuper@37906
  3436
	       
neuper@37906
  3437
	       (*----- collect atoms over * -----*)
neuper@37906
  3438
	       Thm ("realpow_two_atom",num_str realpow_two_atom),	
neuper@37906
  3439
	       (*"r is_atom ==> r * r = r ^^^ 2"*)
neuper@37906
  3440
	       Thm ("realpow_plus_1",num_str realpow_plus_1),		
neuper@37906
  3441
	       (*"r is_atom ==> r * r ^^^ n = r ^^^ (n + 1)"*)
neuper@37906
  3442
	       Thm ("realpow_addI_atom",num_str realpow_addI_atom),
neuper@37906
  3443
	       (*"r is_atom ==> r ^^^ n * r ^^^ m = r ^^^ (n + m)"*)
neuper@37906
  3444
neuper@37906
  3445
	       (*----- distribute none-atoms -----*)
neuper@37906
  3446
	       Thm ("realpow_def_atom",num_str realpow_def_atom),
neuper@37906
  3447
	       (*"[| 1 < n; not(r is_atom) |]==>r ^^^ n = r * r ^^^ (n + -1)"*)
neuper@37906
  3448
	       Thm ("realpow_eq_oneI",num_str realpow_eq_oneI),
neuper@37906
  3449
	       (*"1 ^^^ n = 1"*)
neuper@37906
  3450
	       Calc ("op +",eval_binop "#add_")
neuper@37906
  3451
	       ],
neuper@37906
  3452
      scr = Script ((term_of o the o (parse thy)) 
neuper@37906
  3453
      "empty_script")
neuper@37906
  3454
      }:rls);
neuper@37906
  3455
(*.contains absolute minimum of thms for context in norm_Rational.*)
neuper@37906
  3456
val rat_mult_divide = prep_rls(
neuper@37906
  3457
  Rls {id = "rat_mult_divide", preconds = [], 
neuper@37906
  3458
       rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  3459
      erls = e_rls, srls = Erls, calc = [], (*asm_thm = [],*)
neuper@37906
  3460
      rules = [Thm ("rat_mult",num_str rat_mult),
neuper@37906
  3461
	       (*(1)"?a / ?b * (?c / ?d) = ?a * ?c / (?b * ?d)"*)
neuper@37906
  3462
	       Thm ("real_times_divide1_eq",num_str real_times_divide1_eq),
neuper@37906
  3463
	       (*(2)"?a * (?c / ?d) = ?a * ?c / ?d" must be [2],
neuper@37906
  3464
	       otherwise inv.to a / b / c = ...*)
neuper@37906
  3465
	       Thm ("real_times_divide2_eq",num_str real_times_divide2_eq),
neuper@37906
  3466
	       (*"?a / ?b * ?c = ?a * ?c / ?b" order weights x^^^n too much
neuper@37906
  3467
		     and does not commute a / b * c ^^^ 2 !*)
neuper@37906
  3468
	       
neuper@37906
  3469
	       Thm ("real_divide_divide1_eq", real_divide_divide1_eq),
neuper@37906
  3470
	       (*"?x / (?y / ?z) = ?x * ?z / ?y"*)
neuper@37906
  3471
	       Thm ("real_divide_divide2_eq", real_divide_divide2_eq),
neuper@37906
  3472
	       (*"?x / ?y / ?z = ?x / (?y * ?z)"*)
neuper@37906
  3473
	       Calc ("HOL.divide"  ,eval_cancel "#divide_")
neuper@37906
  3474
	       ],
neuper@37906
  3475
      scr = Script ((term_of o the o (parse thy)) "empty_script")
neuper@37906
  3476
      }:rls);
neuper@37906
  3477
(*.contains absolute minimum of thms for context in norm_Rational.*)
neuper@37906
  3478
val reduce_0_1_2 = prep_rls(
neuper@37906
  3479
  Rls{id = "reduce_0_1_2", preconds = [], rew_ord = ("dummy_ord", dummy_ord),
neuper@37906
  3480
      erls = e_rls,srls = Erls,calc = [],(*asm_thm = [],*)
neuper@37906
  3481
      rules = [(*Thm ("real_divide_1",num_str real_divide_1),
neuper@37906
  3482
		 "?x / 1 = ?x" unnecess.for normalform*)
neuper@37906
  3483
	       Thm ("real_mult_1",num_str real_mult_1),                 
neuper@37906
  3484
	       (*"1 * z = z"*)
neuper@37906
  3485
	       (*Thm ("real_mult_minus1",num_str real_mult_minus1),
neuper@37906
  3486
	       "-1 * z = - z"*)
neuper@37906
  3487
	       (*Thm ("real_minus_mult_cancel",num_str real_minus_mult_cancel),
neuper@37906
  3488
	       "- ?x * - ?y = ?x * ?y"*)
neuper@37906
  3489
neuper@37906
  3490
	       Thm ("real_mult_0",num_str real_mult_0),        
neuper@37906
  3491
	       (*"0 * z = 0"*)
neuper@37906
  3492
	       Thm ("real_add_zero_left",num_str real_add_zero_left),
neuper@37906
  3493
	       (*"0 + z = z"*)
neuper@37906
  3494
	       (*Thm ("real_add_minus",num_str real_add_minus),
neuper@37906
  3495
	       "?z + - ?z = 0"*)
neuper@37906
  3496
neuper@37906
  3497
	       Thm ("sym_real_mult_2",num_str (real_mult_2 RS sym)),	
neuper@37906
  3498
	       (*"z1 + z1 = 2 * z1"*)
neuper@37906
  3499
	       Thm ("real_mult_2_assoc",num_str real_mult_2_assoc),
neuper@37906
  3500
	       (*"z1 + (z1 + k) = 2 * z1 + k"*)
neuper@37906
  3501
neuper@37906
  3502
	       Thm ("real_0_divide",num_str real_0_divide)
neuper@37906
  3503
	       (*"0 / ?x = 0"*)
neuper@37906
  3504
	       ], scr = EmptyScr}:rls);
neuper@37906
  3505
neuper@37906
  3506
(*erls for calculate_Rational; 
neuper@37906
  3507
  make local with FIXX@ME result:term *term list WN0609???SKMG*)
neuper@37906
  3508
val norm_rat_erls = prep_rls(
neuper@37906
  3509
  Rls {id = "norm_rat_erls", preconds = [], rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  3510
      erls = e_rls, srls = Erls, calc = [], (*asm_thm = [],*)
neuper@37906
  3511
      rules = [Calc ("Atools.is'_const",eval_const "#is_const_")
neuper@37906
  3512
	       ],
neuper@37906
  3513
      scr = Script ((term_of o the o (parse thy)) 
neuper@37906
  3514
      "empty_script")
neuper@37906
  3515
      }:rls);
neuper@37906
  3516
(*.consists of rls containing the absolute minimum of thms.*)
neuper@37906
  3517
(*040209: this version has been used by RL for his equations,
neuper@37906
  3518
which is now replaced by MGs version below
neuper@37906
  3519
vvv OLD VERSION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*)
neuper@37906
  3520
val norm_Rational = prep_rls(
neuper@37906
  3521
  Rls {id = "norm_Rational", preconds = [], rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  3522
      erls = norm_rat_erls, srls = Erls, calc = [], (*asm_thm = [],*)
neuper@37906
  3523
      rules = [(*sequence given by operator precedence*)
neuper@37906
  3524
	       Rls_ discard_minus,
neuper@37906
  3525
	       Rls_ powers,
neuper@37906
  3526
	       Rls_ rat_mult_divide,
neuper@37906
  3527
	       Rls_ expand,
neuper@37906
  3528
	       Rls_ reduce_0_1_2,
neuper@37906
  3529
	       (*^^^^^^^^^ from RL -- not the latest one vvvvvvvvv*)
neuper@37906
  3530
	       Rls_ order_add_mult,
neuper@37906
  3531
	       Rls_ collect_numerals,
neuper@37906
  3532
	       Rls_ add_fractions_p,
neuper@37906
  3533
	       Rls_ cancel_p
neuper@37906
  3534
	       ],
neuper@37906
  3535
      scr = Script ((term_of o the o (parse thy)) 
neuper@37906
  3536
      "empty_script")
neuper@37906
  3537
      }:rls);
neuper@37906
  3538
val norm_Rational_parenthesized = prep_rls(
neuper@37906
  3539
  Seq {id = "norm_Rational_parenthesized", preconds = []:term list, 
neuper@37906
  3540
       rew_ord = ("dummy_ord", dummy_ord),
neuper@37906
  3541
      erls = Atools_erls, srls = Erls,
neuper@37906
  3542
      calc = [], (*asm_thm = [],*)
neuper@37906
  3543
      rules = [Rls_  norm_Rational, (*from RL -- not the latest one*)
neuper@37906
  3544
	       Rls_ discard_parentheses
neuper@37906
  3545
	       ],
neuper@37906
  3546
      scr = EmptyScr
neuper@37906
  3547
      }:rls);      
neuper@37906
  3548
neuper@37906
  3549
neuper@37906
  3550
(*-------------------18.3.03 --> struct <-----------^^^--*)
neuper@37906
  3551
neuper@37906
  3552
neuper@37906
  3553
neuper@37906
  3554
theory' := overwritel (!theory', [("Rational.thy",Rational.thy)]);
neuper@37906
  3555
neuper@37906
  3556
neuper@37906
  3557
(*WN030318???SK: simplifies all but cancel and common_nominator*)
neuper@37906
  3558
val simplify_rational = 
neuper@37906
  3559
    merge_rls "simplify_rational" expand_binoms
neuper@37906
  3560
    (append_rls "divide" calculate_Rational
neuper@37906
  3561
		[Thm ("real_divide_1",num_str real_divide_1),
neuper@37906
  3562
		 (*"?x / 1 = ?x"*)
neuper@37906
  3563
		 Thm ("rat_mult",num_str rat_mult),
neuper@37906
  3564
		 (*(1)"?a / ?b * (?c / ?d) = ?a * ?c / (?b * ?d)"*)
neuper@37906
  3565
		 Thm ("real_times_divide1_eq",num_str real_times_divide1_eq),
neuper@37906
  3566
		 (*(2)"?a * (?c / ?d) = ?a * ?c / ?d" must be [2],
neuper@37906
  3567
		 otherwise inv.to a / b / c = ...*)
neuper@37906
  3568
		 Thm ("real_times_divide2_eq",num_str real_times_divide2_eq),
neuper@37906
  3569
		 (*"?a / ?b * ?c = ?a * ?c / ?b"*)
neuper@37906
  3570
		 Thm ("add_minus",num_str add_minus),
neuper@37906
  3571
		 (*"?a + ?b - ?b = ?a"*)
neuper@37906
  3572
		 Thm ("add_minus1",num_str add_minus1),
neuper@37906
  3573
		 (*"?a - ?b + ?b = ?a"*)
neuper@37906
  3574
		 Thm ("real_divide_minus1",num_str real_divide_minus1)
neuper@37906
  3575
		 (*"?x / -1 = - ?x"*)
neuper@37906
  3576
(*
neuper@37906
  3577
,
neuper@37906
  3578
		 Thm ("",num_str )
neuper@37906
  3579
*)
neuper@37906
  3580
		 ]);
neuper@37906
  3581
neuper@37906
  3582
(*---------vvv-------------MG ab 1.07.2003--------------vvv-----------*)
neuper@37906
  3583
neuper@37906
  3584
(* ------------------------------------------------------------------ *)
neuper@37906
  3585
(*                  Simplifier für beliebige Buchterme                *) 
neuper@37906
  3586
(* ------------------------------------------------------------------ *)
neuper@37906
  3587
(*----------------------- norm_Rational_mg ---------------------------*)
neuper@37906
  3588
(*. description of the simplifier see MG-DA.p.56ff .*)
neuper@37906
  3589
(* ------------------------------------------------------------------- *)
neuper@37906
  3590
val common_nominator_p_rls = prep_rls(
neuper@37906
  3591
  Rls {id = "common_nominator_p_rls", preconds = [],
neuper@37906
  3592
       rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  3593
	 erls = e_rls, srls = Erls, calc = [],
neuper@37906
  3594
	 rules = 
neuper@37906
  3595
	 [Rls_ common_nominator_p
neuper@37906
  3596
	  (*FIXME.WN0401 ? redesign Rrls - use exhaustively on a term ?
neuper@37906
  3597
	    FIXME.WN0510 unnecessary nesting: introduce RRls_ : rls -> rule*)
neuper@37906
  3598
	  ], 
neuper@37906
  3599
	 scr = EmptyScr});
neuper@37906
  3600
(* ------------------------------------------------------------------- *)
neuper@37906
  3601
val cancel_p_rls = prep_rls(
neuper@37906
  3602
  Rls {id = "cancel_p_rls", preconds = [],
neuper@37906
  3603
       rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  3604
	 erls = e_rls, srls = Erls, calc = [],
neuper@37906
  3605
	 rules = 
neuper@37906
  3606
	 [Rls_ cancel_p
neuper@37906
  3607
	  (*FIXME.WN.0401 ? redesign Rrls - use exhaustively on a term ?*)
neuper@37906
  3608
	  ], 
neuper@37906
  3609
	 scr = EmptyScr});
neuper@37906
  3610
(* -------------------------------------------------------------------- *)
neuper@37906
  3611
(*. makes 'normal' fractions; 'is_polyexp' inhibits double fractions;
neuper@37906
  3612
    used in initial part norm_Rational_mg, see example DA-M02-main.p.60.*)
neuper@37906
  3613
val rat_mult_poly = prep_rls(
neuper@37906
  3614
  Rls {id = "rat_mult_poly", preconds = [],
neuper@37906
  3615
       rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  3616
	 erls =  append_rls "e_rls-is_polyexp" e_rls
neuper@37906
  3617
	         [Calc ("Poly.is'_polyexp", eval_is_polyexp "")], 
neuper@37906
  3618
	 srls = Erls, calc = [],
neuper@37906
  3619
	 rules = 
neuper@37906
  3620
	 [Thm ("rat_mult_poly_l",num_str rat_mult_poly_l),
neuper@37906
  3621
	  (*"?c is_polyexp ==> ?c * (?a / ?b) = ?c * ?a / ?b"*)
neuper@37906
  3622
	  Thm ("rat_mult_poly_r",num_str rat_mult_poly_r)
neuper@37906
  3623
	  (*"?c is_polyexp ==> ?a / ?b * ?c = ?a * ?c / ?b"*)
neuper@37906
  3624
	  ], 
neuper@37906
  3625
	 scr = EmptyScr});
neuper@37906
  3626
(* ------------------------------------------------------------------ *)
neuper@37906
  3627
(*. makes 'normal' fractions; 'is_polyexp' inhibits double fractions;
neuper@37906
  3628
    used in looping part norm_Rational_rls, see example DA-M02-main.p.60 
neuper@37906
  3629
    .. WHERE THE LATTER DOES ALWAYS WORK, BECAUSE erls = e_rls, 
neuper@37906
  3630
    I.E. THE RESPECTIVE ASSUMPTION IS STORED AND Thm APPLIED; WN051028 
neuper@37906
  3631
    ... WN0609???MG.*)
neuper@37906
  3632
val rat_mult_div_pow = prep_rls(
neuper@37906
  3633
  Rls {id = "rat_mult_div_pow", preconds = [], 
neuper@37906
  3634
       rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  3635
       erls = e_rls,
neuper@37906
  3636
       (*FIXME.WN051028 append_rls "e_rls-is_polyexp" e_rls
neuper@37906
  3637
			[Calc ("Poly.is'_polyexp", eval_is_polyexp "")],
neuper@37906
  3638
         with this correction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ we get 
neuper@37906
  3639
	 error "rational.sml.sml: diff.behav. in norm_Rational_mg 29" etc.
neuper@37906
  3640
         thus we decided to go on with this flaw*)
neuper@37906
  3641
		 srls = Erls, calc = [],
neuper@37906
  3642
      rules = [Thm ("rat_mult",num_str rat_mult),
neuper@37906
  3643
	       (*"?a / ?b * (?c / ?d) = ?a * ?c / (?b * ?d)"*)
neuper@37906
  3644
	       Thm ("rat_mult_poly_l",num_str rat_mult_poly_l),
neuper@37906
  3645
	       (*"?c is_polyexp ==> ?c * (?a / ?b) = ?c * ?a / ?b"*)
neuper@37906
  3646
	       Thm ("rat_mult_poly_r",num_str rat_mult_poly_r),
neuper@37906
  3647
	       (*"?c is_polyexp ==> ?a / ?b * ?c = ?a * ?c / ?b"*)
neuper@37906
  3648
neuper@37906
  3649
	       Thm ("real_divide_divide1_mg", real_divide_divide1_mg),
neuper@37906
  3650
	       (*"y ~= 0 ==> (u / v) / (y / z) = (u * z) / (y * v)"*)
neuper@37906
  3651
	       Thm ("real_divide_divide1_eq", real_divide_divide1_eq),
neuper@37906
  3652
	       (*"?x / (?y / ?z) = ?x * ?z / ?y"*)
neuper@37906
  3653
	       Thm ("real_divide_divide2_eq", real_divide_divide2_eq),
neuper@37906
  3654
	       (*"?x / ?y / ?z = ?x / (?y * ?z)"*)
neuper@37906
  3655
	       Calc ("HOL.divide"  ,eval_cancel "#divide_"),
neuper@37906
  3656
	      
neuper@37906
  3657
	       Thm ("rat_power", num_str rat_power)
neuper@37906
  3658
		(*"(?a / ?b) ^^^ ?n = ?a ^^^ ?n / ?b ^^^ ?n"*)
neuper@37906
  3659
	       ],
neuper@37906
  3660
      scr = Script ((term_of o the o (parse thy)) "empty_script")
neuper@37906
  3661
      }:rls);
neuper@37906
  3662
(* ------------------------------------------------------------------ *)
neuper@37906
  3663
val rat_reduce_1 = prep_rls(
neuper@37906
  3664
  Rls {id = "rat_reduce_1", preconds = [], 
neuper@37906
  3665
       rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  3666
       erls = e_rls, srls = Erls, calc = [], 
neuper@37906
  3667
       rules = [Thm ("real_divide_1",num_str real_divide_1),
neuper@37906
  3668
		(*"?x / 1 = ?x"*)
neuper@37906
  3669
		Thm ("real_mult_1",num_str real_mult_1)           
neuper@37906
  3670
		(*"1 * z = z"*)
neuper@37906
  3671
		],
neuper@37906
  3672
       scr = Script ((term_of o the o (parse thy)) "empty_script")
neuper@37906
  3673
       }:rls);
neuper@37906
  3674
(* ------------------------------------------------------------------ *)
neuper@37906
  3675
(*. looping part of norm_Rational(*_mg*) .*)
neuper@37906
  3676
val norm_Rational_rls = prep_rls(
neuper@37906
  3677
   Rls {id = "norm_Rational_rls", preconds = [], 
neuper@37906
  3678
       rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  3679
       erls = norm_rat_erls, srls = Erls, calc = [],
neuper@37906
  3680
       rules = [Rls_ common_nominator_p_rls,
neuper@37906
  3681
		Rls_ rat_mult_div_pow,
neuper@37906
  3682
		Rls_ make_rat_poly_with_parentheses,
neuper@37906
  3683
		Rls_ cancel_p_rls,(*FIXME:cancel_p does NOT order sometimes*)
neuper@37906
  3684
		Rls_ rat_reduce_1
neuper@37906
  3685
		],
neuper@37906
  3686
       scr = Script ((term_of o the o (parse thy)) "empty_script")
neuper@37906
  3687
       }:rls);
neuper@37906
  3688
(* ------------------------------------------------------------------ *)
neuper@37906
  3689
(*040109 'norm_Rational'(by RL) replaced by 'norm_Rational_mg'(MG)
neuper@37906
  3690
 just be renaming:*)
neuper@37906
  3691
val norm_Rational(*_mg*) = prep_rls(
neuper@37906
  3692
   Seq {id = "norm_Rational"(*_mg*), preconds = [], 
neuper@37906
  3693
       rew_ord = ("dummy_ord",dummy_ord), 
neuper@37906
  3694
       erls = norm_rat_erls, srls = Erls, calc = [],
neuper@37906
  3695
       rules = [Rls_ discard_minus_,
neuper@37906
  3696
		Rls_ rat_mult_poly,(* removes double fractions like a/b/c    *)
neuper@37906
  3697
		Rls_ make_rat_poly_with_parentheses, (*WN0510 also in(#)below*)
neuper@37906
  3698
		Rls_ cancel_p_rls, (*FIXME.MG:cancel_p does NOT order sometim*)
neuper@37906
  3699
		Rls_ norm_Rational_rls,   (* the main rls, looping (#)       *)
neuper@37906
  3700
		Rls_ discard_parentheses_ (* mult only                       *)
neuper@37906
  3701
		],
neuper@37906
  3702
       scr = Script ((term_of o the o (parse thy)) "empty_script")
neuper@37906
  3703
       }:rls);
neuper@37906
  3704
(* ------------------------------------------------------------------ *)
neuper@37906
  3705
neuper@37906
  3706
neuper@37906
  3707
ruleset' := overwritelthy thy (!ruleset',
neuper@37906
  3708
  [("calculate_Rational", calculate_Rational),
neuper@37906
  3709
   ("calc_rat_erls",calc_rat_erls),
neuper@37906
  3710
   ("rational_erls", rational_erls),
neuper@37906
  3711
   ("cancel_p", cancel_p),
neuper@37906
  3712
   ("cancel", cancel),
neuper@37906
  3713
   ("common_nominator_p", common_nominator_p),
neuper@37906
  3714
   ("common_nominator_p_rls", common_nominator_p_rls),
neuper@37906
  3715
   ("common_nominator"  , common_nominator),
neuper@37906
  3716
   ("discard_minus", discard_minus),
neuper@37906
  3717
   ("powers_erls", powers_erls),
neuper@37906
  3718
   ("powers", powers),
neuper@37906
  3719
   ("rat_mult_divide", rat_mult_divide),
neuper@37906
  3720
   ("reduce_0_1_2", reduce_0_1_2),
neuper@37906
  3721
   ("rat_reduce_1", rat_reduce_1),
neuper@37906
  3722
   ("norm_rat_erls", norm_rat_erls),
neuper@37906
  3723
   ("norm_Rational", norm_Rational),
neuper@37906
  3724
   ("norm_Rational_rls", norm_Rational_rls),
neuper@37906
  3725
   ("norm_Rational_parenthesized", norm_Rational_parenthesized),
neuper@37906
  3726
   ("rat_mult_poly", rat_mult_poly),
neuper@37906
  3727
   ("rat_mult_div_pow", rat_mult_div_pow),
neuper@37906
  3728
   ("cancel_p_rls", cancel_p_rls)
neuper@37906
  3729
   ]);
neuper@37906
  3730
neuper@37906
  3731
calclist':= overwritel (!calclist', 
neuper@37906
  3732
   [("is_expanded", ("Rational.is'_expanded", eval_is_expanded ""))
neuper@37906
  3733
    ]);
neuper@37906
  3734
neuper@37906
  3735
(** problems **)
neuper@37906
  3736
neuper@37906
  3737
store_pbt
neuper@37906
  3738
 (prep_pbt Rational.thy "pbl_simp_rat" [] e_pblID
neuper@37906
  3739
 (["rational","simplification"],
neuper@37906
  3740
  [("#Given" ,["term t_"]),
neuper@37906
  3741
   ("#Where" ,["t_ is_ratpolyexp"]),
neuper@37906
  3742
   ("#Find"  ,["normalform n_"])
neuper@37906
  3743
  ],
neuper@37906
  3744
  append_rls "e_rls" e_rls [(*for preds in where_*)], 
neuper@37926
  3745
  SOME "Simplify t_", 
neuper@37906
  3746
  [["simplification","of_rationals"]]));
neuper@37906
  3747
neuper@37906
  3748
(** methods **)
neuper@37906
  3749
neuper@37906
  3750
(*WN061025 this methods script is copied from (auto-generated) script
neuper@37906
  3751
  of norm_Rational in order to ease repair on inform*)
neuper@37906
  3752
store_met
neuper@37906
  3753
    (prep_met Rational.thy "met_simp_rat" [] e_metID
neuper@37906
  3754
	      (["simplification","of_rationals"],
neuper@37906
  3755
	       [("#Given" ,["term t_"]),
neuper@37906
  3756
		("#Where" ,["t_ is_ratpolyexp"]),
neuper@37906
  3757
		("#Find"  ,["normalform n_"])
neuper@37906
  3758
		],
neuper@37906
  3759
	       {rew_ord'="tless_true",
neuper@37906
  3760
		rls' = e_rls,
neuper@37906
  3761
		calc = [], srls = e_rls, 
neuper@37906
  3762
		prls = append_rls "simplification_of_rationals_prls" e_rls 
neuper@37906
  3763
				[(*for preds in where_*)
neuper@37906
  3764
				 Calc ("Rational.is'_ratpolyexp", 
neuper@37906
  3765
				       eval_is_ratpolyexp "")],
neuper@37906
  3766
		crls = e_rls, nrls = norm_Rational_rls},
neuper@37906
  3767
"Script SimplifyScript (t_::real) =                              \
neuper@37906
  3768
\  ((Try (Rewrite_Set discard_minus_ False) @@                   \
neuper@37906
  3769
\    Try (Rewrite_Set rat_mult_poly False) @@                    \
neuper@37906
  3770
\    Try (Rewrite_Set make_rat_poly_with_parentheses False) @@   \
neuper@37906
  3771
\    Try (Rewrite_Set cancel_p_rls False) @@                     \
neuper@37906
  3772
\    (Repeat                                                     \
neuper@37906
  3773
\     ((Try (Rewrite_Set common_nominator_p_rls False) @@        \
neuper@37906
  3774
\       Try (Rewrite_Set rat_mult_div_pow False) @@              \
neuper@37906
  3775
\       Try (Rewrite_Set make_rat_poly_with_parentheses False) @@\
neuper@37906
  3776
\       Try (Rewrite_Set cancel_p_rls False) @@                  \
neuper@37906
  3777
\       Try (Rewrite_Set rat_reduce_1 False)))) @@               \
neuper@37906
  3778
\    Try (Rewrite_Set discard_parentheses_ False))               \
neuper@37906
  3779
\    t_)"
neuper@37906
  3780
	       ));
neuper@37906
  3781
neuper@37947
  3782
(* use"../Knowledge/Rational.ML";
neuper@37947
  3783
   use"Knowledge/Rational.ML";
neuper@37906
  3784
   use"Rational.ML";
neuper@37906
  3785
   *)
neuper@37906
  3786