[Bug fortran/40318] Complex division by zero in gfortran returns wrong results

dominiq at lps dot ens dot fr gcc-bugzilla@gcc.gnu.org
Mon Jun 1 10:19:00 GMT 2009



------- Comment #3 from dominiq at lps dot ens dot fr  2009-06-01 10:19 -------
In http://gcc.gnu.org/ml/fortran/2009-06/msg00006.html, Dennis Wassel 
wrote:
> Complex numbers have a well-defined concept of infinity, which I like to
> visualise as the "infinite-diameter" ring around the finite complex
> numbers, so its argument is, of course, not well-defined.  This is
> conceptually somewhat different from the two points +/-Inf on the real
> line, and it is not signed.

My understanding of infinity in the complex plane is what is called (I
call?)  "directed inifinity": if abs((a,b)) goes to +Inf and atan2(a,b) has
a defined value in this limit, then (a,b) goes to infinity in the direction
given by atan2(a,b).  However (+/-Inf,+/-Inf) defines only four directions
and is unable to represent general "directed inifinity".  So I think that
from a "mathematical" point of view the problem is ill-posed,
(+/-Inf,+/-Inf) is in the same class of "undefined" values as 0/0 or
Inf/Inf, and should give NaNs.

Now atan2(a,b) is DEFINED such that atan2(+0,+/-0)=+/-0,
atan2(-0,+/-0)=+/-Pi, atan2(+Inf,+/-Inf)=+/-Pi/4,
atan2(-Inf,+/-Inf)=+/-3*Pi/4 (it seems that it is even built in the Intel
hardware).  With this definition of atan2, it is possible to give a
definition of (+/-Inf,+/-Inf) as the directions of the corners of the
"infinite square".  I have nothing against this defintion, except it should
be documented.

Part of the problem originates from the optimization of (a,b)/(c,0.0) as
(a/c,b/c), see pr30482, and it limit when c goes to 0 (the latter giving
(+/-Inf,+/-Inf) if b/=0.0 or has a unknown value at compile time,
(+/-Inf,+/-0) if b known to be zero at compile time, optimized as
(a/c,+/-0.0), or (+/-Inf,-/+Nan) if b==0 at run time).

Note that due to the definition of atan2(+/-0,+/-0),
(+/-0,+/-0)=0*exp((+/-k*Pi,+/-0)) (k being 0 or 1), then to be consistent
1.0/(+/-0.0,+/-0.0) should give 1/0.0*exp((-/+k*Pi,-/+0))=(+/-Inf,-/+Nan).

Last remark, if I remember correctly (I cannot find the right pointer) C99 
defines precisely how complex multiplications should behave in the 
exception limits, with the drawback of a large increase of the computation 
cost avoided with the -fcx-fortran-rules option.

As far as I can tell:

(1) Without the IEEE module, using or producing Inf or NaN makes the code 
non (fortran) standard comforming, so the "processor" can give any answer.

(2) With the IEEE module, Inf and NaN are part of the numerical model, 
however I did not find any definition of the values that intrinsincs 
should return in such cases.

To conclude, I'll repeat that in my opinion the only relevant answer for
overflow, divide by zero, or invalid argument exceptions is "call abort()".
Since I know that it is a lost battle, I think at least the behavior shall
not increase the computation time with complex numbers (or provide a way to
avoid the penalty).  Now if the fxxxx standard does not define the expected
result, but the C99 does, the best answer to this ill-posed problem is
probably to follow the C99 standard if possible (I have no idea of what
does mpc).  In this case the results at compile and run times should be the
same ("least surprising approach").


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40318



More information about the Gcc-bugs mailing list