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