{: test that exp(y*ln(x)) causes a fatal error if x & y are large enough
   this tests for very large x and y just large enough to overflow }

program d08c( output );

var
   e : real;
   k : real;
   x : real;
   y : real;
   z : real;

function side : real;
begin
   side := k;
   k := k+1;
end; { side }

begin {d08c}

   k := 1;
   x := exp(1*ln(side));
   if abs(x-1) > 1.0e-37 then begin
      writeln( 'unexpected value of exp(ln(1)) is ', x);
   end;
   if k <> 2 then
      writeln( 'ln(x) in exp(y*ln(x)) has side effects' );

   k := 1;
   x := exp(side*ln(1));
   if abs(x-1) > 1.0e-37 then begin
      writeln( 'unexpected value of exp(ln(1)) is ', x);
   end;
   if k <> 2 then
      writeln( 'y in exp(y*ln(x)) for debug has side effects' );

   {find y, the smallest number > 1}
   e := 1;
   repeat
      e := 0.5*e;
      y := 1+0.5*e;
   until y = 1;
   y := y+e;
   writeln( 'e is ', e, ', 1+e = 1 is ', y=y+e );

   {write( 'checking for underflow or denormalise ... ' );}
   k := 1;
   repeat
      x := k;
      k := k/2;
      z := y*k;
   until (k = 0) or (z = k);
   writeln('min real is ', x);

   {find z, the largest number < 1}
   k := e;
   repeat
      k := k/2;
      z := 1 - k/2;
   until z <= 1;
   z := 1-k;
   writeln( 'k is ', k, ', 1-k = 1 is ', z = z-k );

   x := 4*z/x;   { assuming ieee floating point }
   writeln('max real is ', x);

   { this shouldn't overflow ... }
   writeln( 'exp((1-', 1-z, ')*ln(', x, ')) is ', exp(z*ln(x)) );

   writeln( 'checking for overflow, expecting to generate a fatal error' );
   writeln( 'exp((1+', y-1, ')*ln(', x, ')) is ', exp(y*ln(x) ));

   writeln( 'fails: exp(y*ln(x)) overflow not detected for large x' );
end. { d08c }
