669 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
		
		
			
		
	
	
			669 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								%  clp(q,r)                                         version 1.3.3 %
							 | 
						||
| 
								 | 
							
								%                                                                 %
							 | 
						||
| 
								 | 
							
								%  (c) Copyright 1992,1993,1994,1995                              %
							 | 
						||
| 
								 | 
							
								%  Austrian Research Institute for Artificial Intelligence (OFAI) %
							 | 
						||
| 
								 | 
							
								%  Schottengasse 3                                                %
							 | 
						||
| 
								 | 
							
								%  A-1010 Vienna, Austria                                         %
							 | 
						||
| 
								 | 
							
								%                                                                 %
							 | 
						||
| 
								 | 
							
								%  File:   arith.pl                                               %
							 | 
						||
| 
								 | 
							
								%  Author: Christian Holzbaur           christian@ai.univie.ac.at %
							 | 
						||
| 
								 | 
							
								%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% common code for R,Q, runtime predicates
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% linearize evaluation, collect vars
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% Todo: +) limited encoding length option
							 | 
						||
| 
								 | 
							
								%	+) 2 stage compilation: a) linearization
							 | 
						||
| 
								 | 
							
								%				b) specialization to R or Q
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								l2conj( [],	true).
							 | 
						||
| 
								 | 
							
								l2conj( [X|Xs], Conj) :-
							 | 
						||
| 
								 | 
							
								  ( Xs = [], Conj = X
							 | 
						||
| 
								 | 
							
								  ; Xs = [_|_], Conj = (X,Xc), l2conj( Xs, Xc)
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								% ----------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% float/1 coercion is allowed only at the outermost level in Q
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								compile_Q( Term, R, Code) :-
							 | 
						||
| 
								 | 
							
								  linearize( Term, Res, Linear),
							 | 
						||
| 
								 | 
							
								  specialize_Q( Linear, Code, Ct),
							 | 
						||
| 
								 | 
							
								  ( Res = boolean,  Ct = []
							 | 
						||
| 
								 | 
							
								  ; Res = float(R), Ct = []
							 | 
						||
| 
								 | 
							
								  ; Res = rat(N,D), Ct = [ putq(D,N,R) ]
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% assumes normalized params and puts a normalized result
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								compile_Qn( Term, R, Code) :-
							 | 
						||
| 
								 | 
							
								  linearize( Term, Res, Linear),
							 | 
						||
| 
								 | 
							
								  specialize_Qn( Linear, Code, Ct),
							 | 
						||
| 
								 | 
							
								  ( Res = boolean,  Ct = []
							 | 
						||
| 
								 | 
							
								  ; Res = float(R), Ct = []
							 | 
						||
| 
								 | 
							
								  ; Res = rat(N,D), Ct = [ putq(D,N,R) ]
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								compile_case_signum_Qn( Term, Lt,Z,Gt, Code) :-
							 | 
						||
| 
								 | 
							
								  linearize( Term, rat(N,_), Linear),
							 | 
						||
| 
								 | 
							
								  specialize_Qn( Linear, Code,
							 | 
						||
| 
								 | 
							
								      [
							 | 
						||
| 
								 | 
							
									  compare( Rel, N, 0),
							 | 
						||
| 
								 | 
							
									  ( Rel = <, Lt
							 | 
						||
| 
								 | 
							
									  ; Rel = =, Z
							 | 
						||
| 
								 | 
							
									  ; Rel = >, Gt
							 | 
						||
| 
								 | 
							
									  )
							 | 
						||
| 
								 | 
							
								      ]).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								specialize_Qn( []) --> [].
							 | 
						||
| 
								 | 
							
								specialize_Qn( [Op|Ops]) -->
							 | 
						||
| 
								 | 
							
								  specialize_Qn( Op),
							 | 
						||
| 
								 | 
							
								  specialize_Qn( Ops).
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								specialize_Qn( op_var(rat(N,D),Var))   --> [ Var=rat(N,D) ]. % <--- here is the difference ---
							 | 
						||
| 
								 | 
							
								specialize_Qn( op_integer(rat(I,1),I)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_Qn( op_rat(rat(N,D),N,D))   --> [].
							 | 
						||
| 
								 | 
							
								specialize_Qn( op_float(rat(N,D),X))   --> [], { float_rat( X, N,D) }.
							 | 
						||
| 
								 | 
							
								specialize_Qn( apply(R,Func)) -->
							 | 
						||
| 
								 | 
							
								  specialize_Q_fn( Func, R).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								specialize_Q( []) --> [].
							 | 
						||
| 
								 | 
							
								specialize_Q( [Op|Ops]) -->
							 | 
						||
| 
								 | 
							
								  specialize_Q( Op),
							 | 
						||
| 
								 | 
							
								  specialize_Q( Ops).
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								specialize_Q( op_var(rat(N,D),Var))   --> [ getq(Var,N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q( op_integer(rat(I,1),I)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_Q( op_rat(rat(N,D),N,D))   --> [], { D > 0 }.
							 | 
						||
| 
								 | 
							
								specialize_Q( op_float(rat(N,D),X))   --> [], { float_rat( X, N,D) }.
							 | 
						||
| 
								 | 
							
								specialize_Q( apply(R,Func)) -->
							 | 
						||
| 
								 | 
							
								  specialize_Q_fn( Func, R).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( +rat(N,D),			rat(N,D)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( numer(rat(N,_)),		rat(N,1)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( denom(rat(_,D)),		rat(D,1)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( -rat(N0,D),			rat(N,D)) --> [ N is -N0 ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( abs(rat(Nx,Dx)),		rat(N,D)) --> [ N is abs(Nx) ], {D=Dx}.
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( signum(rat(Nx,Dx)),		rat(N,D)) --> [ signumq( Nx,Dx, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( floor(rat(Nx,Dx)),		rat(N,D)) --> [ floorq( Nx,Dx, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( ceiling(rat(Nx,Dx)),		rat(N,D)) --> [ ceilingq( Nx,Dx, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( truncate(rat(Nx,Dx)),		rat(N,D)) --> [ truncateq( Nx,Dx, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( round(rat(Nx,Dx)),		rat(N,D)) --> [ roundq( Nx,Dx, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( log(rat(Nx,Dx)),		rat(N,D)) --> [ logq( Nx,Dx, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( exp(rat(Nx,Dx)),		rat(N,D)) --> [ expq( Nx,Dx, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( sin(rat(Nx,Dx)),		rat(N,D)) --> [ sinq( Nx,Dx, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( cos(rat(Nx,Dx)),		rat(N,D)) --> [ cosq( Nx,Dx, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( tan(rat(Nx,Dx)),		rat(N,D)) --> [ tanq( Nx,Dx, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( asin(rat(Nx,Dx)),		rat(N,D)) --> [ asinq( Nx,Dx, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( acos(rat(Nx,Dx)),		rat(N,D)) --> [ acosq( Nx,Dx, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( atan(rat(Nx,Dx)),		rat(N,D)) --> [ atanq( Nx,Dx, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( float(rat(Nx,Dx)),		float(F)) --> [ rat_float( Nx,Dx, F) ].
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( rat(Nx,Dx)+rat(Ny,Dy), 	rat(N,D)) --> [ addq( Nx,Dx, Ny,Dy, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( rat(Nx,Dx)-rat(Ny,Dy), 	rat(N,D)) --> [ subq( Nx,Dx, Ny,Dy, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( rat(Nx,Dx)*rat(Ny,Dy), 	rat(N,D)) --> [ mulq( Nx,Dx, Ny,Dy, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( rat(Nx,Dx)/rat(Ny,Dy), 	rat(N,D)) --> [ divq( Nx,Dx, Ny,Dy, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( exp(rat(Nx,Dx),rat(Ny,Dy)),	rat(N,D)) --> [ expq( Nx,Dx, Ny,Dy, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( min(rat(Nx,Dx),rat(Ny,Dy)),	rat(N,D)) --> [ minq( Nx,Dx, Ny,Dy, N,D) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( max(rat(Nx,Dx),rat(Ny,Dy)),	rat(N,D)) --> [ maxq( Nx,Dx, Ny,Dy, N,D) ].
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( rat(Nx,Dx)  <	rat(Ny,Dy),	boolean)  --> [ comq( Nx,Dx, Ny,Dy, <) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( rat(Nx,Dx)  >	rat(Ny,Dy),	boolean)  --> [ comq( Ny,Dy, Nx,Dx, <) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( rat(Nx,Dx)  =< rat(Ny,Dy),	boolean)  --> [ comq( Nx,Dx, Ny,Dy, Rel), Rel \== (>) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( rat(Nx,Dx)  >= rat(Ny,Dy),	boolean)  --> [ comq( Ny,Dy, Nx,Dx, Rel), Rel \== (>) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( rat(Nx,Dx) =\= rat(Ny,Dy),	boolean)  --> [ comq( Nx,Dx, Ny,Dy, Rel), Rel \== (=) ].
							 | 
						||
| 
								 | 
							
								specialize_Q_fn( rat(Nx,Dx) =:= rat(Ny,Dy),	boolean)  -->
							 | 
						||
| 
								 | 
							
								  %
							 | 
						||
| 
								 | 
							
								  % *normalized* rationals
							 | 
						||
| 
								 | 
							
								  %
							 | 
						||
| 
								 | 
							
								  ( {Nx = Ny} -> [] ; [ Nx = Ny ] ),
							 | 
						||
| 
								 | 
							
								  ( {Dx = Dy} -> [] ; [ Dx = Dy ] ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								% ----------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								compile_R( Term, R, Code) :-
							 | 
						||
| 
								 | 
							
								  linearize( Term, Res, Linear),
							 | 
						||
| 
								 | 
							
								  specialize_R( Linear, Code, Ct),
							 | 
						||
| 
								 | 
							
								  ( Res == boolean ->
							 | 
						||
| 
								 | 
							
								      Ct = [], R = boolean
							 | 
						||
| 
								 | 
							
								  ; float(Res) ->
							 | 
						||
| 
								 | 
							
								      Ct = [ R=Res ]
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								      Ct = [ R is Res ]
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								compile_case_signum_R( Term, Lt,Z,Gt, Code) :-
							 | 
						||
| 
								 | 
							
								  eps( Eps, NegEps),
							 | 
						||
| 
								 | 
							
								  linearize( Term, Res, Linear),
							 | 
						||
| 
								 | 
							
								  specialize_R( Linear, Code,
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
									Rv is Res,
							 | 
						||
| 
								 | 
							
									( Rv < NegEps -> Lt
							 | 
						||
| 
								 | 
							
									; Rv > Eps    -> Gt
							 | 
						||
| 
								 | 
							
									;		 Z
							 | 
						||
| 
								 | 
							
									)
							 | 
						||
| 
								 | 
							
								    ]).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								specialize_R( []) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R( [Op|Ops]) -->
							 | 
						||
| 
								 | 
							
								  specialize_R( Op),
							 | 
						||
| 
								 | 
							
								  specialize_R( Ops).
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								specialize_R( op_var(Var,Var)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R( op_integer(R,I)) --> [], { R is float(I) }.
							 | 
						||
| 
								 | 
							
								specialize_R( op_rat(R,N,D))   --> [], { rat_float( N,D, R) }.
							 | 
						||
| 
								 | 
							
								specialize_R( op_float(F,F))   --> [].
							 | 
						||
| 
								 | 
							
								specialize_R( apply(R,Func)) -->
							 | 
						||
| 
								 | 
							
								  specialize_R_fn( Func, R).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								specialize_R_fn( signum(X),		S) -->
							 | 
						||
| 
								 | 
							
								  ( {var(X)} ->
							 | 
						||
| 
								 | 
							
								      {Xe=X}
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								      [ Xe is X ]
							 | 
						||
| 
								 | 
							
								  ),
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    eps( Eps, NegEps)
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  [
							 | 
						||
| 
								 | 
							
								    ( Xe < NegEps -> S = -1.0
							 | 
						||
| 
								 | 
							
								    ; Xe > Eps	  -> S =  1.0
							 | 
						||
| 
								 | 
							
								    ;		     S =  0.0
							 | 
						||
| 
								 | 
							
								    )
							 | 
						||
| 
								 | 
							
								  ].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								specialize_R_fn( +X,			X) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( -X,			-X) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( abs(X),		abs(X)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( floor(X),		float(floor(/*float?*/X))) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( ceiling(X),		float(ceiling(/*float?*/X))) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( truncate(X),		float(truncate(/*float?*/X))) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( round(X),		float(round(/*float?*/X))) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( log(X),		log(X))  --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( exp(X),		exp(X)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( sin(X),		sin(X)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( cos(X),		cos(X)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( tan(X),		tan(X)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( asin(X),		asin(X)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( acos(X),		acos(X)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( atan(X),		atan(X)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( float(X),		float(X)) --> [].
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X+Y,			X+Y) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X-Y,			X-Y) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X*Y,			X*Y) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X/Y,			X/Y) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( exp(X,Y),		exp(X,Y)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( min(X,Y),		min(X,Y)) --> [].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( max(X,Y),		max(X,Y)) --> [].
							 | 
						||
| 
								 | 
							
								/**/
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% An absolute eps is of course not very meaningful.
							 | 
						||
| 
								 | 
							
								% An eps scaled by the magnitude of the operands participating
							 | 
						||
| 
								 | 
							
								% in the comparison is too expensive to support in Prolog on the
							 | 
						||
| 
								 | 
							
								% other hand ...
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								%		 -eps	0  +eps
							 | 
						||
| 
								 | 
							
								%   ---------------[----|----]----------------
							 | 
						||
| 
								 | 
							
								%	     < 0		  > 0
							 | 
						||
| 
								 | 
							
								%      <-----------]	     [----------->
							 | 
						||
| 
								 | 
							
								%	    =< 0
							 | 
						||
| 
								 | 
							
								%      <---------------------]
							 | 
						||
| 
								 | 
							
								%				  >= 0
							 | 
						||
| 
								 | 
							
								%		   [--------------------->
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X  <  Y, boolean)  -->
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    eps( Eps, NegEps)
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  ( {X==0} ->
							 | 
						||
| 
								 | 
							
								      [ Y > Eps ]
							 | 
						||
| 
								 | 
							
								  ; {Y==0} ->
							 | 
						||
| 
								 | 
							
								      [ X < NegEps ]
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								      [ X-Y < NegEps ]
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X  >  Y, boolean)  --> specialize_R_fn( Y  < X, boolean).
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X  =< Y, boolean)  -->
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    eps( Eps, _)
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  [ X-Y < Eps ].
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X  >= Y, boolean)  --> specialize_R_fn( Y =< X, boolean).
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X =:= Y, boolean)  -->
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    eps( Eps, NegEps)
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  ( {X==0} ->
							 | 
						||
| 
								 | 
							
									[ Y >= NegEps, Y =< Eps ]
							 | 
						||
| 
								 | 
							
								  ; {Y==0} ->
							 | 
						||
| 
								 | 
							
									[ X >= NegEps, X =< Eps ]
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
									[
							 | 
						||
| 
								 | 
							
									  Diff is X-Y,
							 | 
						||
| 
								 | 
							
									  Diff =< Eps,
							 | 
						||
| 
								 | 
							
									  Diff >= NegEps
							 | 
						||
| 
								 | 
							
									]
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X =\= Y, boolean)  -->
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    eps( Eps, NegEps)
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  [
							 | 
						||
| 
								 | 
							
								    Diff is X-Y,
							 | 
						||
| 
								 | 
							
								    ( Diff < NegEps -> true ; Diff > Eps )
							 | 
						||
| 
								 | 
							
								  ].
							 | 
						||
| 
								 | 
							
								/**/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% b30427, pp.218
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X  >  Y, boolean)  --> specialize_R_fn( Y  < X, boolean).
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X  <  Y, boolean)  -->
							 | 
						||
| 
								 | 
							
								  [ scaled_eps(X,Y,E), Y-X > E ].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X  >= Y, boolean)  --> specialize_R_fn( Y =< X, boolean).
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X  =< Y, boolean)  -->
							 | 
						||
| 
								 | 
							
								  [ scaled_eps(X,Y,E), X-Y =< E ].	% \+ >
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X =:= Y, boolean)  -->
							 | 
						||
| 
								 | 
							
								  [ scaled_eps(X,Y,E), abs(X-Y) =< E ].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								specialize_R_fn( X =\= Y, boolean)  -->
							 | 
						||
| 
								 | 
							
								  [ scaled_eps(X,Y,E), abs(X-Y) > E ].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								scaled_eps( X, Y, Eps) :-
							 | 
						||
| 
								 | 
							
								  exponent( X, Ex),
							 | 
						||
| 
								 | 
							
								  exponent( Y, Ey),
							 | 
						||
| 
								 | 
							
								  arith_eps( E),
							 | 
						||
| 
								 | 
							
								  Max is max(Ex,Ey),
							 | 
						||
| 
								 | 
							
								  ( Max < 0 ->
							 | 
						||
| 
								 | 
							
								     Eps is E/(1<<Max)
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								     Eps is E*(1<<Max)
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								exponent( X, E) :-
							 | 
						||
| 
								 | 
							
								  A is abs(X),
							 | 
						||
| 
								 | 
							
								  float_rat( A, N, D),
							 | 
						||
| 
								 | 
							
								  E is msb(N+1)-msb(D).
							 | 
						||
| 
								 | 
							
								**/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								% ----------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								linearize( Term, Res, Linear) :-
							 | 
						||
| 
								 | 
							
								  linearize( Term, Res, Vs,[], Lin, []),
							 | 
						||
| 
								 | 
							
								  keysort( Vs, Vss),
							 | 
						||
| 
								 | 
							
								  ( Vss = [],	  Linear = Lin
							 | 
						||
| 
								 | 
							
								  ; Vss = [V|Vt], join_vars( Vt, V, Linear, Lin)
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% flatten the evaluation, collect variables, shared by Q,R,...
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								linearize( X,	     R, [X-R|Vs],Vs) --> {var(X)}, !,	[ ].
							 | 
						||
| 
								 | 
							
								linearize( X,	     R, Vs,Vs) --> {integer(X)}, !,	[ op_integer(R,X) ].
							 | 
						||
| 
								 | 
							
								linearize( X,	     R, Vs,Vs) --> {float(X)}, !,	[ op_float(R,X) ].
							 | 
						||
| 
								 | 
							
								linearize( rat(N,D), R, Vs,Vs) --> !,			[ op_rat(R,N,D) ].
							 | 
						||
| 
								 | 
							
								linearize( Term,     R, V0,V1) -->
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    functor( Term, N, A),
							 | 
						||
| 
								 | 
							
								    functor( Skeleton, N, A)
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  linearize_args( A, Term, Skeleton, V0,V1),		[ apply(R,Skeleton) ].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								linearize_args( 0, _, _, Vs,Vs) --> [].
							 | 
						||
| 
								 | 
							
								linearize_args( N, T, S, V0,V2) -->
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    arg( N, T, Arg),
							 | 
						||
| 
								 | 
							
								    arg( N, S, Res),
							 | 
						||
| 
								 | 
							
								    N1 is N-1
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  linearize( Arg, Res, V0,V1),
							 | 
						||
| 
								 | 
							
								  linearize_args( N1, T, S, V1,V2).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								join_vars( [],	      Y-Ry) --> [ op_var(Ry,Y) ].
							 | 
						||
| 
								 | 
							
								join_vars( [X-Rx|Xs], Y-Ry) -->
							 | 
						||
| 
								 | 
							
								  ( {X==Y} ->
							 | 
						||
| 
								 | 
							
								      {Rx=Ry},
							 | 
						||
| 
								 | 
							
								      join_vars( Xs, Y-Ry)
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								      [ op_var(Ry,Y) ],
							 | 
						||
| 
								 | 
							
								      join_vars( Xs, X-Rx)
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								% ---------------------------------- runtime system ---------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% C candidate
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								limit_encoding_length( 0,D, _,	  0,D) :- !.		% msb ...
							 | 
						||
| 
								 | 
							
								limit_encoding_length( N,D, Bits, Nl,Dl) :-
							 | 
						||
| 
								 | 
							
								  Shift is min(max(msb(abs(N)),msb(D))-Bits,
							 | 
						||
| 
								 | 
							
									       min(msb(abs(N)),msb(D))),
							 | 
						||
| 
								 | 
							
								  Shift > 0,
							 | 
						||
| 
								 | 
							
								  !,
							 | 
						||
| 
								 | 
							
								  Ns is N>>Shift,
							 | 
						||
| 
								 | 
							
								  Ds is D>>Shift,
							 | 
						||
| 
								 | 
							
								  Gcd is gcd(Ns,Ds),
							 | 
						||
| 
								 | 
							
								  Nl is Ns//Gcd,
							 | 
						||
| 
								 | 
							
								  Dl is Ds//Gcd.
							 | 
						||
| 
								 | 
							
								limit_encoding_length( N,D, _, N,D).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% No longer backconvert to integer
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% putq( 1, N, N) :- !.
							 | 
						||
| 
								 | 
							
								putq( D, N, rat(N,D)).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								getq( Exp,	N,D) :- var( Exp), !, 
							 | 
						||
| 
								 | 
							
								  raise_exception( instantiation_error(getq(Exp,N,D),1)).
							 | 
						||
| 
								 | 
							
								getq( I,	I,1) :- integer(I), !.
							 | 
						||
| 
								 | 
							
								getq( F,	N,D) :- float( F), !, float_rat( F, N,D).
							 | 
						||
| 
								 | 
							
								getq( rat(N,D), N,D) :-
							 | 
						||
| 
								 | 
							
								  integer( N),
							 | 
						||
| 
								 | 
							
								  integer( D),
							 | 
						||
| 
								 | 
							
								  D > 0,
							 | 
						||
| 
								 | 
							
								  1 =:= gcd(N,D).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% actually just a joke to have this stuff in Q ...
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								 expq( N,D, N1,D1) :- rat_float( N,D, X), F is	exp(X), float_rat( F, N1,D1).
							 | 
						||
| 
								 | 
							
								 logq( N,D, N1,D1) :- rat_float( N,D, X), F is	log(X), float_rat( F, N1,D1).
							 | 
						||
| 
								 | 
							
								 sinq( N,D, N1,D1) :- rat_float( N,D, X), F is	sin(X), float_rat( F, N1,D1).
							 | 
						||
| 
								 | 
							
								 cosq( N,D, N1,D1) :- rat_float( N,D, X), F is	cos(X), float_rat( F, N1,D1).
							 | 
						||
| 
								 | 
							
								 tanq( N,D, N1,D1) :- rat_float( N,D, X), F is	tan(X), float_rat( F, N1,D1).
							 | 
						||
| 
								 | 
							
								asinq( N,D, N1,D1) :- rat_float( N,D, X), F is asin(X), float_rat( F, N1,D1).
							 | 
						||
| 
								 | 
							
								acosq( N,D, N1,D1) :- rat_float( N,D, X), F is acos(X), float_rat( F, N1,D1).
							 | 
						||
| 
								 | 
							
								atanq( N,D, N1,D1) :- rat_float( N,D, X), F is atan(X), float_rat( F, N1,D1).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% for integer powers we can do it in Q
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								expq( Nx,Dx, Ny,Dy, N,D) :-
							 | 
						||
| 
								 | 
							
								  ( Dy =:= 1 ->
							 | 
						||
| 
								 | 
							
								     ( Ny >= 0 ->
							 | 
						||
| 
								 | 
							
									powq( Ny, Nx,Dx, 1,1, N,D)
							 | 
						||
| 
								 | 
							
								     ;
							 | 
						||
| 
								 | 
							
									Nabs is -Ny,
							 | 
						||
| 
								 | 
							
									powq( Nabs, Nx,Dx, 1,1, N1,D1),
							 | 
						||
| 
								 | 
							
									( N1 < 0 ->
							 | 
						||
| 
								 | 
							
									   N is -D1, D is -N1
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									   N = D1, D = N1
							 | 
						||
| 
								 | 
							
									)
							 | 
						||
| 
								 | 
							
								     )
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								     rat_float( Nx,Dx, Fx),
							 | 
						||
| 
								 | 
							
								     rat_float( Ny,Dy, Fy),
							 | 
						||
| 
								 | 
							
								     F is exp(Fx,Fy),
							 | 
						||
| 
								 | 
							
								     float_rat( F, N, D)
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% positive integer powers of rational
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								powq( 0, _, _,	Nt,Dt, Nt,Dt) :- !.
							 | 
						||
| 
								 | 
							
								powq( 1, Nx,Dx, Nt,Dt, Nr,Dr) :- !, mulq( Nx,Dx, Nt,Dt, Nr,Dr).
							 | 
						||
| 
								 | 
							
								powq( N, Nx,Dx, Nt,Dt, Nr,Dr) :-
							 | 
						||
| 
								 | 
							
								  N1 is N >> 1,
							 | 
						||
| 
								 | 
							
								  ( N /\ 1 =:= 0 ->
							 | 
						||
| 
								 | 
							
								      Nt1 = Nt, Dt1 = Dt
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								      mulq( Nx,Dx, Nt,Dt, Nt1,Dt1)
							 | 
						||
| 
								 | 
							
								  ),
							 | 
						||
| 
								 | 
							
								  mulq( Nx,Dx, Nx,Dx, Nxx,Dxx),
							 | 
						||
| 
								 | 
							
								  powq( N1, Nxx,Dxx, Nt1,Dt1, Nr,Dr).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% the choicepoint ruins the party ...
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								mulq( Na,Da, Nb,Db, Nc,Dc) :-
							 | 
						||
| 
								 | 
							
								  Gcd1 is gcd(Na,Db),
							 | 
						||
| 
								 | 
							
								  ( Gcd1 =:= 1 -> Na1=Na,Db1=Db; Na1 is Na//Gcd1,Db1 is Db//Gcd1 ),
							 | 
						||
| 
								 | 
							
								  Gcd2 is gcd(Nb,Da),
							 | 
						||
| 
								 | 
							
								  ( Gcd2 =:= 1 -> Nb1=Nb,Da1=Da; Nb1 is Nb//Gcd2,Da1 is Da//Gcd2 ),
							 | 
						||
| 
								 | 
							
								  Nc is Na1 * Nb1,
							 | 
						||
| 
								 | 
							
								  Dc is Da1 * Db1.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								mulq( Na,Da, Nb,Db, Nc,Dc) :-
							 | 
						||
| 
								 | 
							
								  Gcd1 is gcd(Na,Db),
							 | 
						||
| 
								 | 
							
								  Na1 is Na//Gcd1,
							 | 
						||
| 
								 | 
							
								  Db1 is Db//Gcd1,
							 | 
						||
| 
								 | 
							
								  Gcd2 is gcd(Nb,Da),
							 | 
						||
| 
								 | 
							
								  Nb1 is Nb//Gcd2,
							 | 
						||
| 
								 | 
							
								  Da1 is Da//Gcd2,
							 | 
						||
| 
								 | 
							
								  Nc is Na1 * Nb1,
							 | 
						||
| 
								 | 
							
								  Dc is Da1 * Db1.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								divq( Na,Da, Nb,Db, Nc,Dc) :-
							 | 
						||
| 
								 | 
							
								  Gcd1 is gcd(Na,Nb),
							 | 
						||
| 
								 | 
							
								  ( Gcd1 =:= 1 -> Na1=Na,Nb1=Nb; Na1 is Na//Gcd1,Nb1 is Nb//Gcd1 ),
							 | 
						||
| 
								 | 
							
								  Gcd2 is gcd(Da,Db),
							 | 
						||
| 
								 | 
							
								  ( Gcd2 =:= 1 -> Da1=Da,Db1=Db; Da1 is Da//Gcd2,Db1 is Db//Gcd2 ),
							 | 
						||
| 
								 | 
							
								  ( Nb1 < 0 ->			% keep denom positive !!!
							 | 
						||
| 
								 | 
							
								     Nc is -(Na1 * Db1),
							 | 
						||
| 
								 | 
							
								     Dc is Da1 * (-Nb1)
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								     Nc is Na1 * Db1,
							 | 
						||
| 
								 | 
							
								     Dc is Da1 * Nb1
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								divq( Na,Da, Nb,Db, Nc,Dc) :-
							 | 
						||
| 
								 | 
							
								  Gcd1 is gcd(Na,Nb),
							 | 
						||
| 
								 | 
							
								  Na1 is Na//Gcd1,
							 | 
						||
| 
								 | 
							
								  Nb1 is Nb//Gcd1,
							 | 
						||
| 
								 | 
							
								  Gcd2 is gcd(Da,Db),
							 | 
						||
| 
								 | 
							
								  Da1 is Da//Gcd2,
							 | 
						||
| 
								 | 
							
								  Db1 is Db//Gcd2,
							 | 
						||
| 
								 | 
							
								  ( Nb1 < 0 ->			% keep denom positive !!!
							 | 
						||
| 
								 | 
							
								     Nc is -(Na1 * Db1),
							 | 
						||
| 
								 | 
							
								     Dc is Da1 * (-Nb1)
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								     Nc is Na1 * Db1,
							 | 
						||
| 
								 | 
							
								     Dc is Da1 * Nb1
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% divq_11( Nb,Db, Nc,Dc) :- divq( 1,1, Nb,Db, Nc,Dc).
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								divq_11( Nb,Db, Nc,Dc) :-
							 | 
						||
| 
								 | 
							
								  ( Nb < 0 ->			% keep denom positive !!!
							 | 
						||
| 
								 | 
							
								     Nc is -Db,
							 | 
						||
| 
								 | 
							
								     Dc is -Nb
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								     Nc is Db,
							 | 
						||
| 
								 | 
							
								     Dc is Nb
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'divq_-11'( Nb,Db, Nc,Dc) :-
							 | 
						||
| 
								 | 
							
								  ( Nb < 0 ->			% keep denom positive !!!
							 | 
						||
| 
								 | 
							
								     Nc is Db,
							 | 
						||
| 
								 | 
							
								     Dc is -Nb
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								     Nc is -Db,
							 | 
						||
| 
								 | 
							
								     Dc is Nb
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								addq( Na,Da, Nb,Db, Nc,Dc) :-
							 | 
						||
| 
								 | 
							
								  Gcd1 is gcd(Da,Db),
							 | 
						||
| 
								 | 
							
								  ( Gcd1 =:= 1 -> 			% This is the case (for random input) with
							 | 
						||
| 
								 | 
							
													% probability 6/(pi**2).
							 | 
						||
| 
								 | 
							
								     Nc is Na*Db + Nb*Da,
							 | 
						||
| 
								 | 
							
								     Dc is Da*Db
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								     T is Na*(Db//Gcd1) + Nb*(Da//Gcd1),
							 | 
						||
| 
								 | 
							
								     Gcd2 is gcd(T,Gcd1),
							 | 
						||
| 
								 | 
							
								     Nc is T//Gcd2,
							 | 
						||
| 
								 | 
							
								     Dc is (Da//Gcd1) * (Db//Gcd2)
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								addq( Na,Da, Nb,Db, Nc,Dc) :-
							 | 
						||
| 
								 | 
							
								  Gcd1 is gcd(Da,Db),
							 | 
						||
| 
								 | 
							
								  T is Na*(Db//Gcd1) + Nb*(Da//Gcd1),
							 | 
						||
| 
								 | 
							
								  Gcd2 is gcd(T,Gcd1),
							 | 
						||
| 
								 | 
							
								  Nc is T//Gcd2,
							 | 
						||
| 
								 | 
							
								  Dc is (Da//Gcd1) * (Db//Gcd2).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								subq( Na,Da, Nb,Db, Nc,Dc) :-
							 | 
						||
| 
								 | 
							
								  Gcd1 is gcd(Da,Db),
							 | 
						||
| 
								 | 
							
								  ( Gcd1 =:= 1 -> 			% This is the case (for random input) with
							 | 
						||
| 
								 | 
							
													% probability 6/(pi**2).
							 | 
						||
| 
								 | 
							
								     Nc is Na*Db - Nb*Da,
							 | 
						||
| 
								 | 
							
								     Dc is Da*Db
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								     T is Na*(Db//Gcd1) - Nb*(Da//Gcd1),
							 | 
						||
| 
								 | 
							
								     Gcd2 is gcd(T,Gcd1),
							 | 
						||
| 
								 | 
							
								     Nc is T//Gcd2,
							 | 
						||
| 
								 | 
							
								     Dc is (Da//Gcd1) * (Db//Gcd2)
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								subq( Na,Da, Nb,Db, Nc,Dc) :-
							 | 
						||
| 
								 | 
							
								  Gcd1 is gcd(Da,Db),
							 | 
						||
| 
								 | 
							
								  T is Na*(Db//Gcd1) - Nb*(Da//Gcd1),
							 | 
						||
| 
								 | 
							
								  Gcd2 is gcd(T,Gcd1),
							 | 
						||
| 
								 | 
							
								  Nc is T//Gcd2,
							 | 
						||
| 
								 | 
							
								  Dc is (Da//Gcd1) * (Db//Gcd2).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								comq( Na,Da, Nb,Db, S) :-	% todo: avoid multiplication by looking a signs first !!!
							 | 
						||
| 
								 | 
							
								  Xa is Na * Db,
							 | 
						||
| 
								 | 
							
								  Xb is Nb * Da,
							 | 
						||
| 
								 | 
							
								  compare( S, Xa, Xb).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								minq( Na,Da, Nb,Db, N,D) :-
							 | 
						||
| 
								 | 
							
								  comq( Na,Da, Nb,Db, Rel),
							 | 
						||
| 
								 | 
							
								  ( Rel = =, N=Na, D=Da
							 | 
						||
| 
								 | 
							
								  ; Rel = <, N=Na, D=Da
							 | 
						||
| 
								 | 
							
								  ; Rel = >, N=Nb, D=Db
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								maxq( Na,Da, Nb,Db, N,D) :-
							 | 
						||
| 
								 | 
							
								  comq( Na,Da, Nb,Db, Rel),
							 | 
						||
| 
								 | 
							
								  ( Rel = =, N=Nb, D=Db
							 | 
						||
| 
								 | 
							
								  ; Rel = <, N=Nb, D=Db
							 | 
						||
| 
								 | 
							
								  ; Rel = >, N=Na, D=Da
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								signumq( N,_, S,1) :-
							 | 
						||
| 
								 | 
							
								  compare( Rel, N, 0),
							 | 
						||
| 
								 | 
							
								  rel2sig( Rel, S).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								rel2sig( <, -1).
							 | 
						||
| 
								 | 
							
								rel2sig( >,  1).
							 | 
						||
| 
								 | 
							
								rel2sig( =,  0).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								% -----------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								truncateq( N,D, R,1) :-
							 | 
						||
| 
								 | 
							
								  R is N // D.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% returns the greatest integral  value	less  than  or
							 | 
						||
| 
								 | 
							
								% equal to x.  This corresponds to IEEE rounding toward nega-
							 | 
						||
| 
								 | 
							
								% tive infinity
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								floorq( N,1, N,1) :- !.
							 | 
						||
| 
								 | 
							
								floorq( N,D, R,1) :-
							 | 
						||
| 
								 | 
							
								  ( N < 0 ->
							 | 
						||
| 
								 | 
							
								     R is N // D - 1
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								     R is N // D
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% returns the least  integral  value  greater  than  or
							 | 
						||
| 
								 | 
							
								% equal  to x.	This corresponds to IEEE rounding toward posi-
							 | 
						||
| 
								 | 
							
								% tive infinity
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								ceilingq( N,1, N,1) :- !.
							 | 
						||
| 
								 | 
							
								ceilingq( N,D, R,1) :-
							 | 
						||
| 
								 | 
							
								  ( N > 0 ->
							 | 
						||
| 
								 | 
							
								     R is N // D + 1
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								     R is N // D
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% rounding towards zero
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								roundq( N,D, R,1) :-
							 | 
						||
| 
								 | 
							
								  % rat_float( N,D, F), 	% cheating, can do that in Q
							 | 
						||
| 
								 | 
							
								  % R is integer(round(F)).
							 | 
						||
| 
								 | 
							
								  I is N//D,
							 | 
						||
| 
								 | 
							
								  subq( N,D, I,1, Rn,Rd),
							 | 
						||
| 
								 | 
							
								  Rna is abs(Rn),
							 | 
						||
| 
								 | 
							
								  ( comq( Rna,Rd, 1,2, <) ->
							 | 
						||
| 
								 | 
							
								      R = I
							 | 
						||
| 
								 | 
							
								  ; I >= 0 ->
							 | 
						||
| 
								 | 
							
								      R is I+1
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								      R is I-1
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								% ------------------------------- rational -> float -------------------------------
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								% The problem here is that SICStus converts BIG fractions N/D into +-nan
							 | 
						||
| 
								 | 
							
								% if it does not fit into a float
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								%   | ?- X is msb(integer(1.0e+308)).
							 | 
						||
| 
								 | 
							
								%   X = 1023
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								rat_float( Nx,Dx, F) :-
							 | 
						||
| 
								 | 
							
								  limit_encoding_length( Nx,Dx, 1023, Nxl,Dxl),
							 | 
						||
| 
								 | 
							
								  F is Nxl / Dxl.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								% ------------------------------- float -> rational -------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								float_rat( F, N, D) :-
							 | 
						||
| 
								 | 
							
								  float_rat( 100, F, F, 1,0,0,1, N0,D0), 	% at most 100 iterations
							 | 
						||
| 
								 | 
							
								  ( D0 < 0 ->					% sign normalization
							 | 
						||
| 
								 | 
							
								     D is -D0,
							 | 
						||
| 
								 | 
							
								     N is -N0
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								     D = D0,
							 | 
						||
| 
								 | 
							
								     N = N0
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								float_rat( 0, _, _, Na,_,Da,_, Na,Da) :- !.
							 | 
						||
| 
								 | 
							
								float_rat( _, _, X, Na,_,Da,_, Na,Da) :-
							 | 
						||
| 
								 | 
							
								  0.0 =:= abs(X-Na/Da),
							 | 
						||
| 
								 | 
							
								  !.
							 | 
						||
| 
								 | 
							
								float_rat( N, F, X, Na,Nb,Da,Db, Nar,Dar) :-
							 | 
						||
| 
								 | 
							
								  I is integer(F),
							 | 
						||
| 
								 | 
							
								  ( I =:= F ->					% guard against zero division
							 | 
						||
| 
								 | 
							
								     Nar is Na*I+Nb,				% 1.0 -> 1/1 and not 0/1 (first iter.) !!!
							 | 
						||
| 
								 | 
							
								     Dar is Da*I+Db
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								     Na1 is Na*I+Nb,
							 | 
						||
| 
								 | 
							
								     Da1 is Da*I+Db,
							 | 
						||
| 
								 | 
							
								     F1 is 1/(F-I),
							 | 
						||
| 
								 | 
							
								     N1 is N-1,
							 | 
						||
| 
								 | 
							
								     float_rat( N1, F1, X, Na1,Na,Da1,Da, Nar,Dar)
							 | 
						||
| 
								 | 
							
								  ).
							 | 
						||
| 
								 | 
							
								
							 |