Infinite loop in frexp
Summary
There is an error, or at least an oversight, in one of the generic mathematical functions, namely frexp on line 351 of rtl/inc/genmath.inc
.
procedure frexp(X: Real; out Mantissa: Real; out Exponent: longint);
{* frexp() extracts the exponent from x. It returns an integer *}
{* power of two to expnt and the significand between 0.5 and 1 *}
{* to y. Thus x = y * 2**expn. *}
begin
exponent:=0;
if (abs(x)<0.5) then
While (abs(x)<0.5) do
begin
x := x*2;
Dec(exponent);
end
else
While (abs(x)>1) do
begin
x := x/2;
Inc(exponent);
end;
Mantissa := x;
end;
This gets used in the generic fpc_sqrt_real
function (if a platform-specific square root instruction isn't supported). The bug is that if X is infinity, it lives up to its name as the function enters an infinite loop, because all operations upon X keep it set to infinity. NaNs should logically exit very quickly with the exponent set to zero because all of the conditions will evaluate to false.
System Information
- Processor architecture: Cross-platform (no native SQRT)
- Compiler version: Trunk
Steps to reproduce
On any system without a native floating-point square root (FPC_SYSTEM_HAS_SQRT
is not defined), call Sqrt(1.0/0.0)
and note that the program never makes progress beyond this point.
Possible fixes
Since the format of the floating-point number cannot be guaranteed to be of a IEEE 754 standard, the input of frexp
must explicitly check against ±∞, likely via if Abs(X)=1.0/0.0 then
.