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

program d08e( output );

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

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

begin {d08e}

   k := 1;
   x := exp(ln(side)*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( 'ln(x) in exp(ln(x)*y) has side effects' );

   k := 1;
   x := exp(ln(1)*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( 'y in exp(ln(x)*y) for debug has side effects' );

   {find y, largest nr < -1}
   e := 1;
   repeat
      e := 0.5*e;
      y := -1-e/2;
   until y >= -1;
   y := y-e;
   writeln( 'e is ', e, ', y-e = y is ', y=y-e );

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

   {for ieee floating point, maxreal = f/x, where f is largest nr < 4.
    find y, the smallest number > (ln(4) - ln(x))/ln(x)}
   k := 1;
   z := (ln(4)-ln(x))/ln(x);
   repeat
      k := 0.5*k;
      y := z + k/2;
   until y <= z;
   y := z + k;
   writeln( 'k is ', k, ', y+k = y is ', y = y+k );

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

   {find y, the largest number < (ln(4) - ln(x))/ln(x)}
   k := 1;
   repeat
      k := 0.5*k;
      y := z - k/2;
   until y >= z;
   y := z - k;

   y := y-k;
   writeln( 'k is ', k, ', y-k = y is ', y = y-k );

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

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

