{: test that exp(y*ln(x)) 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 d08g( output );

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

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

begin {d08g}

   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, 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(', y, '*ln(', x, ')) is ', exp(y*ln(x)));

   {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(', y, '*ln(', x, ')) is ', exp(y*ln(x)) );

   writeln( 'fails: exp(y*ln(x)) overflow not detected for large x' );

end. { d08g }

