When I compile the following code with g++ (4.8.1 or 4.9.0) or clang++ (3.4) I get different outputs.
#include
#include
int mai
Ok so I have this wild guess, that in clang the complex number division is implemented like described on wiki: http://en.wikipedia.org/wiki/Complex_number#Multiplication_and_division.
One can see that the denominator is in the form c^2 + d^2
. So 1.e-162
squared actually falls out of the IEE754 representable range for double
which is std::numeric_limits
- 2.22507e-308
, and we have an underflow.
gcc
somehow works this out, but if clang
does simple square, as per @40two's standard quotation it enters into UB, and treats it as 0
after performing 1.e-162^2 + 0.0^2
.
I tested clang
and gcc
for a number that should not result with underflow when squared.
#include
#include
int main() {
std::complex c = {1.e-104,0};
std::cout << 1.0/c << std::endl;
return 0;
}
Results are fine:
luk32:~/projects/tests$ g++ --std=c++11 ./complex_div.cpp
luk32:~/projects/tests$ ./a.out
(1e+104,0)
luk32:~/projects/tests$ clang++ --std=c++11 ./complex_div.cpp
luk32:~/projects/tests$ ./a.out
(1e+104,0)
Not sure if this is a bug. But I think this is what is going on.
Addendum:
(inf,-nan)
is also consistent if one evaluates those expressions by hand
We get:
real = (ac+bd) / (o) - real part
imag = (bc-ad) / (o) - imaginary part
{a,b} = {1.0, 0.0}
{c,d} = {1.e-104, 0.0}
o is (c^2 + d^2) and we assume it is 0.0.
real / o = (1.e-104 * 1.0 + 0.0 * 0.0) / o = 1/o = inf
imag / o = (0.0 * 1.e-104 - 1.0 * 0.0) / o = -0.0 / o = -nan
I am just not absolutetly sure about the sign of -0.0
and -nan
, I don't know IEE754 enough to evaluate (0.0 * 1.e-104 - 1.0 * 0.0)
. But everything seems consistent.