226 lines
		
	
	
	
		
			7.2 KiB
		
	
	
	
		
			OpenEdge ABL
		
	
	
	
	
	
			
		
		
	
	
			226 lines
		
	
	
	
		
			7.2 KiB
		
	
	
	
		
			OpenEdge ABL
		
	
	
	
	
	
{ $Id$ }
 | 
						|
 | 
						|
procedure machar (var ibeta , it , irnd , ngrd , machep , negep , iexp,
 | 
						|
  minexp , maxexp : integer ; var eps , epsneg , xmin , xmax : real ) ;
 | 
						|
var trapped:boolean;
 | 
						|
 | 
						|
procedure encaps(procedure p; procedure q(i:integer)); extern;
 | 
						|
procedure trap(i:integer); extern;
 | 
						|
 | 
						|
procedure catch(i:integer);
 | 
						|
const underflo=5;
 | 
						|
begin if i=underflo then trapped:=true else trap(i) end;
 | 
						|
 | 
						|
procedure work;
 | 
						|
var
 | 
						|
 | 
						|
 | 
						|
{     This subroutine is intended to determine the characteristics
 | 
						|
      of the floating-point arithmetic system that are specified
 | 
						|
      below.  The first three are determined according to an
 | 
						|
      algorithm due to M. Malcolm, CACM 15 (1972), pp. 949-951,
 | 
						|
      incorporating some, but not all, of the improvements
 | 
						|
      suggested by M. Gentleman and S. Marovich, CACM 17 (1974),
 | 
						|
      pp. 276-277.  The version given here is for single precision.
 | 
						|
 | 
						|
      Latest revision - October 1, 1976.
 | 
						|
 | 
						|
      Author - W. J. Cody
 | 
						|
               Argonne National Laboratory
 | 
						|
 | 
						|
      Revised for Pascal - R. A. Freak
 | 
						|
                           University of Tasmania
 | 
						|
                           Hobart
 | 
						|
                           Tasmania
 | 
						|
 | 
						|
      ibeta    is the radix of the floating-point representation
 | 
						|
      it       is the number of base ibeta digits in the floating-point
 | 
						|
                  significand
 | 
						|
      irnd     =  0 if the arithmetic chops,
 | 
						|
                  1 if the arithmetic rounds
 | 
						|
      ngrd     =  0 if  irnd=1, or if  irnd=0  and only  it  base ibeta
 | 
						|
                    digits participate in the post normalization shift
 | 
						|
                    of the floating-point significand in multiplication
 | 
						|
                  1 if  irnd=0  and more than  it  base  ibeta  digits
 | 
						|
                    participate in the post normalization shift of the
 | 
						|
                    floating-point significand in multiplication
 | 
						|
      machep   is the exponent on the smallest positive floating-point
 | 
						|
                  number  eps such that  1.0+eps <> 1.0
 | 
						|
      negeps   is the exponent on the smallest positive fl. pt. no.
 | 
						|
                  negeps such that  1.0-negeps <> 1.0, except that
 | 
						|
                  negeps is bounded below by  it-3
 | 
						|
      iexp     is the number of bits (decimal places if ibeta = 10)
 | 
						|
                  reserved for the representation of the exponent of
 | 
						|
                  a floating-point number
 | 
						|
      minexp   is the exponent of the smallest positive fl. pt. no.
 | 
						|
                  xmin
 | 
						|
      maxexp   is the exponent of the largest finite floating-point
 | 
						|
                  number  xmax
 | 
						|
      eps      is the smallest positive floating-point number such
 | 
						|
                  that  1.0+eps <> 1.0. in particular,
 | 
						|
                  eps = ibeta**machep
 | 
						|
      epsneg   is the smallest positive floating-point number such
 | 
						|
                  that  1.0-eps <> 1.0  (except that the exponent
 | 
						|
                  negeps is bounded below by it-3).  in particular
 | 
						|
                  epsneg = ibeta**negep
 | 
						|
      xmin     is the smallest positive floating-point number.  in
 | 
						|
                  particular,  xmin = ibeta ** minexp
 | 
						|
      xmax     is the largest finite floating-point number.  in
 | 
						|
                  particular   xmax = (1.0-epsneg) * ibeta ** maxexp
 | 
						|
                  note - on some machines  xmax  will be only the
 | 
						|
                  second, or perhaps third, largest number, being
 | 
						|
                  too small by 1 or 2 units in the last digit of
 | 
						|
                  the significand.
 | 
						|
 | 
						|
                                                                    }
 | 
						|
 | 
						|
   i , iz , j , k , mx : integer ;
 | 
						|
   a , b , beta , betain , betam1 , one , y , z , zero : real ;
 | 
						|
 | 
						|
begin
 | 
						|
   irnd := 1 ;
 | 
						|
   one := ( irnd );
 | 
						|
   a := one + one ;
 | 
						|
   b := a ;
 | 
						|
   zero := 0.0 ;
 | 
						|
{
 | 
						|
      determine ibeta,beta ala Malcolm
 | 
						|
                                                                    }
 | 
						|
   while ( ( ( a + one ) - a ) - one = zero ) do begin
 | 
						|
      a := a + a ;
 | 
						|
   end ;
 | 
						|
   while ( ( a + b ) - a = zero ) do begin
 | 
						|
      b := b + b ;
 | 
						|
   end ;
 | 
						|
   ibeta := trunc ( ( a + b ) - a );
 | 
						|
   beta := ( ibeta );
 | 
						|
   betam1 := beta - one ;
 | 
						|
{
 | 
						|
      determine irnd,ngrd,it
 | 
						|
                                                                    }
 | 
						|
   if ( ( a + betam1 ) - a = zero ) then irnd := 0 ;
 | 
						|
   it := 0 ;
 | 
						|
   a := one ;
 | 
						|
   repeat begin
 | 
						|
      it := it + 1 ;
 | 
						|
      a := a * beta ;
 | 
						|
   end until ( ( ( a + one ) - a ) - one <> zero ) ;
 | 
						|
{
 | 
						|
      determine negep, epsneg
 | 
						|
                                                                    }
 | 
						|
   negep := it + 3 ;
 | 
						|
   a := one ;
 | 
						|
 | 
						|
   for i := 1 to negep do begin
 | 
						|
      a := a / beta ;
 | 
						|
   end ;
 | 
						|
 | 
						|
   while ( ( one - a ) - one = zero ) do begin
 | 
						|
      a := a * beta ;
 | 
						|
      negep := negep - 1 ;
 | 
						|
   end ;
 | 
						|
   negep := - negep ;
 | 
						|
   epsneg := a ;
 | 
						|
{
 | 
						|
      determine machep, eps
 | 
						|
                                                                    }
 | 
						|
   machep := negep ;
 | 
						|
   while ( ( one + a ) - one = zero ) do begin
 | 
						|
      a := a * beta ;
 | 
						|
      machep := machep + 1 ;
 | 
						|
   end ;
 | 
						|
   eps := a ;
 | 
						|
{
 | 
						|
      determine ngrd
 | 
						|
                                                                    }
 | 
						|
   ngrd := 0 ;
 | 
						|
   if(( irnd = 0) and((( one + eps) * one - one) <> zero)) then
 | 
						|
   ngrd := 1 ;
 | 
						|
{
 | 
						|
      determine iexp, minexp, xmin
 | 
						|
 | 
						|
      loop to determine largest i such that
 | 
						|
          (1/beta) ** (2**(i))
 | 
						|
      does not underflow
 | 
						|
      exit from loop is signall by an underflow
 | 
						|
                                                                    }
 | 
						|
   i := 0 ;
 | 
						|
   betain := one / beta ;
 | 
						|
   z := betain ;
 | 
						|
   trapped:=false;
 | 
						|
   repeat begin
 | 
						|
      y := z ;
 | 
						|
      z := y * y ;
 | 
						|
{
 | 
						|
      check for underflow
 | 
						|
                                                                    }
 | 
						|
      i := i + 1 ;
 | 
						|
   end until trapped;
 | 
						|
   i := i - 1;
 | 
						|
   k := 1 ;
 | 
						|
{
 | 
						|
      determine k such that (1/beta)**k does not underflow
 | 
						|
 | 
						|
      first set k = 2 ** i
 | 
						|
                                                                    }
 | 
						|
 | 
						|
   for j := 1 to i do begin
 | 
						|
      k := k + k ;
 | 
						|
   end ;
 | 
						|
 | 
						|
   iexp := i + 1 ;
 | 
						|
   mx := k + k ;
 | 
						|
   if ( ibeta = 10 ) then begin
 | 
						|
{
 | 
						|
      for decimal machines only                                     }
 | 
						|
      iexp := 2 ;
 | 
						|
      iz := ibeta ;
 | 
						|
      while ( k >= iz ) do begin
 | 
						|
         iz := iz * ibeta ;
 | 
						|
         iexp := iexp + 1 ;
 | 
						|
      end ;
 | 
						|
      mx := iz + iz - 1 ;
 | 
						|
   end;
 | 
						|
   trapped:=false;
 | 
						|
   repeat begin
 | 
						|
{
 | 
						|
      loop to construct xmin
 | 
						|
      exit from loop is signalled by an underflow
 | 
						|
                                                                    }
 | 
						|
      xmin := y ;
 | 
						|
      y := y * betain ;
 | 
						|
      k := k + 1 ;
 | 
						|
   end until trapped;
 | 
						|
   k := k - 1;
 | 
						|
   minexp := - k ;
 | 
						|
{  determine maxexp, xmax
 | 
						|
                                                                    }
 | 
						|
   if ( ( mx <= k + k - 3 ) and ( ibeta <> 10 ) ) then begin
 | 
						|
      mx := mx + mx ;
 | 
						|
      iexp := iexp + 1 ;
 | 
						|
   end;
 | 
						|
   maxexp := mx + minexp ;
 | 
						|
{  adjust for machines with implicit leading
 | 
						|
   bit in binary significand and machines with
 | 
						|
   radix point at extreme right of significand
 | 
						|
                                                                    }
 | 
						|
   i := maxexp + minexp ;
 | 
						|
   if ( ( ibeta = 2 ) and ( i = 0 ) ) then maxexp := maxexp - 1 ;
 | 
						|
   if ( i > 20 ) then maxexp := maxexp - 3 ;
 | 
						|
   xmax := one - epsneg ;
 | 
						|
   if ( xmax * one <> xmax ) then xmax := one - beta * epsneg ;
 | 
						|
   xmax := ( xmax * betain * betain * betain ) / xmin ;
 | 
						|
   i := maxexp + minexp + 3 ;
 | 
						|
   if  ( i > 0 ) then begin
 | 
						|
 | 
						|
      for j := 1 to i do begin
 | 
						|
         xmax := xmax * beta ;
 | 
						|
      end ;
 | 
						|
   end;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
begin
 | 
						|
  trapped:=false;
 | 
						|
  encaps(work,catch);
 | 
						|
end;
 |