227 lines
7.2 KiB
OpenEdge ABL
227 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;
|