Creating complex infinity with std::complex<T> in C++

1.5k views Asked by At

I'm trying to create a complex infinity equal to Inf+Inf*j where j is the complex variable. When I do this :

#include <complex>
#include <limits>
using std;

...

complex<double> attempt1 =
   complex<double>( numeric_limits<double>::infinity(),
                    numeric_limits<double>::infinity() );

returns the complex number (NaN + Inf*j).

But

complex<double> attempt2 =
   complex<double>( numeric_limits<double>::infinity() );

returns the complex number (Inf + 0*j).

Also :

complex<double> attempt_at_imag_inf =
   complex<double>(any_value_here, numeric_limits<double>::infinity());

returns the complex number (NaN + Inf*j).

Does anybody know what's going on here? Any time I attempt to have infinty for the imaginary part, then NaN is written on the real part.

The above only applies to types that support NaN and Infinity of course. I am using g++ v4.6.1. I've looked at the numeric_limits header and there is no indication that the above should happen at all.

To put the above into context, I'm actually doing the above in a partial specialization of numeric_limits for complex. Many thanks for considering this problem.

REVISION TO ORIGINAL POST

I'm providing a complete but short program to illustrate the problem. I've also included some more qualifying information on how the program should be compiled to generate the results.

#include <iostream>
#include <complex>
#include <limits>

using namespace std;

int main(int argc, char* argv[])
{

   complex<double> my_complex_inf =
      complex<double>(numeric_limits<double>::infinity(),
                      numeric_limits<double>::infinity());

   cout << "my_complex_inf = " << my_complex_inf << endl;

   complex<double> attempt2 =
      complex<double>( numeric_limits<double>::infinity() );

   cout << "attempt2 = " << attempt2 << endl;

   double any_value_here = 0;

   complex<double> attempt_at_imag_inf =
      complex<double>(0, numeric_limits<double>::infinity());

   cout << "attempt_at_imag_inf = " << attempt_at_imag_inf << endl;

   return 0;

}

Compiling the above in g++ version 4.6.1 on Ubuntu with the -std=c++0x gives the following results :

my_complex_inf = (nan,inf)
attempt2 = (inf,0)
attempt_at_imag_inf = (nan,inf)

Without the -std=c++0x option the results are :

my_complex_inf = (inf,inf)
attempt2 = (inf,0)
attempt_at_imag_inf = (0,inf)

So the question really is WHY DOES GNU g++ V4.6.1 GIVE THE ANSWERS IT DOES WHEN C++0x IS SPECIFIED?

REVISION 2 TO ORIGINAL POST

I just tried the following in Octave (MATLAB-like numerics package) :

a=inf + j*inf

And the answer is :

a = NaN + Infi

This is exactly what I see in my C++11 code (C++0x). I don't know what Octave is compiled with (it's a combination of C++ and FORTRAN I believe) but if that package returns the result that I am getting, then I assume that this is well-known behaviour.

However, I have looked at the C++11 draft standard and cannot find any mention of this behaviour.

REVISION 3 TO ORIGINAL POST

Adding the following line

my_complex_inf.real(my_complex_inf.imag());

to just after the construction of my_complex_inf return the "correct" answer (inf, inf) when compiled for C++11. Unfortunately, this is now a 2-step process and I am unable to create this kind of complex infinity in a constexpr function.

3

There are 3 answers

1
starbolin On

A scalar Inf converted to complex is inf+0 j. Ths is correct above. A scalar Inf offset in the complex plane impliesv aa rotation and, is not calculable, therefore Nan is correct. What is the problem again?

"There be dragons."

0
emsr On

In mainline (gcc-4.8) i get with -std=c++0x the expected (no -std) answer:

my_complex_inf = (inf,inf)
attempt2 = (inf,0)
attempt_at_imag_inf = (0,inf)

gcc-4.6.3 with -std-c++11 gives the unexpected answer:

my_complex_inf = (-nan,inf)
attempt2 = (inf,0)
attempt_at_imag_inf = (-nan,inf)

I think the constructors should just set the real and imaginary types according to the corresponding arguments. There should be no nan.

0
Chris Dodd On

You're running into the way that C++11 (and C11) specify complex numbers and getting confused.

Basically, in the model mandated by the spec, there is only one infinity (represented by (inf,0)), and attempts to put an 'infinity' into the imaginary part of a complex results in Nan, because it makes no sense in that model.