and am just wondering if this is safe:
double xxyy = x * x + y * y;
if (xxyy != 0)
{
n = n1 / sqrt(xxyy);
}
It's always safe because floating-point math doesn't trap and you can freely divide by zero or even Inf/NaN, unless you tell the compiler to trap on those cases
Anyway if you just want to check whether the denominator is zero then the question on the title is actually different from what you're talking about in the question's content. The answer to the question
Given x>0, is it possible for sqrt(x)
to be zero?
is yes, if denormals-are-zero (DAZ) and/or flush-to-zero (FTZ) are turned on. In fact most non-x86 architectures have DAZ/FTZ enabled by default, or don't even support denormals and always turn DAZ/FTZ on, because operation on denormal numbers are very slow (see Why does changing 0.1f to 0 slow down performance by 10x?). In x86 you can also turn those flags on and some compilers will turn them on by default
For example the below sample code
f = 0x0Cp-1022;
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
printf("%a %a\n", f, sqrt(f));
may print 0x0.000000000000cp-1022 0x0p+0
because f
is treated as zero by sqrt
due to DAZ
Some demo on Godbolt. And gcc demo on ideone
The above snippet can also print 0x0p+0 0x0p+0
because f
is treated as zero by printf
due to FTZ even though it contains a non-zero denormalized value
If you set DAZ/FTZ before assigning f
like this
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
f = 0x0Cp-1022;
printf("%a %a\n", f, sqrt(f));
then it'll likely also print 0x0p+0 0x0p+0
, but in this case f
can be assigned an actual zero value instead, and printing its bit pattern will result in all zero bits
However if you've asked this
Given x and y which aren't both zero at the same time, is it possible for sqrt(x*x + y*y)
to be zero
then the answer to that question is yes even if DAZ/FTZ aren't enabled, because the numbers can be so small that their product became underflow. Try something like this and see
double x = 0x1p-1021;
double y = 0x2p-1020; // or y = 0
double xxyy = x * x + y * y;
printf("%a %a\n", x, y);
printf("%a %a\n", xxyy, sqrt(xxyy));