public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* Re: complex numbers
@ 2004-12-07 11:51 Paolo Carlini
  2004-12-07 13:07 ` Andreas Klein
  0 siblings, 1 reply; 18+ messages in thread
From: Paolo Carlini @ 2004-12-07 11:51 UTC (permalink / raw)
  To: gcc-bugs; +Cc: Gabriel Dos Reis, klein

> As you mentinon it if have missed the specilization at the end of
> std_complex.h. Sorry. I still think that we should have and other
> implementation for complex<floating_point>, but I cannot change the code
> of __complex__ T in the complier.

Interestingly, it looks like the discussed improved algorithm is
*already* implemented, just not used!

Have a look to expand_complex_division in gcc/tree-complex.c, then
gcc/toplev.c for flag_complex_divide_method.

Andreas, just for curiosity, are you willing to rebuild your gcc
with flag_complex_divide_method = 1 and report???

Thanks,
Paolo.


^ permalink raw reply	[flat|nested] 18+ messages in thread
* Re: Complex Numbers
@ 2005-01-21 12:47 Paolo Carlini
  2005-01-21 12:50 ` Paolo Carlini
  0 siblings, 1 reply; 18+ messages in thread
From: Paolo Carlini @ 2005-01-21 12:47 UTC (permalink / raw)
  To: klein; +Cc: gcc-bugs

> I have looked at the implementation of complex arithmetic in gcc.

We are already aware of this issue, since you have already reported
it ;) The relevant PR is middle-end/18902.

Indeed, our plan involves enabling the (*already available*) algorithm
due to Smith. There are still some open issues, however (see "Depends on"
and "blocks" fields, for further details).

As usual, patches are *welcome*, if prepared according to our (usual)
rules and the necessary copyright assignment is in place.

Paolo.



^ permalink raw reply	[flat|nested] 18+ messages in thread
* Complex Numbers
@ 2005-01-21 12:35 Andreas Klein
  0 siblings, 0 replies; 18+ messages in thread
From: Andreas Klein @ 2005-01-21 12:35 UTC (permalink / raw)
  To: gcc-bugs

Hello

I have looked at the implementation of complex arithmetic in gcc.

I see tree problems with naive formulas for multiplication and
division that are currently in use.

1. Problems with special values. For example (infinity+ i*NaN)^2
   should be (infinity + i*0) according to IEC 60559 and not
   (NaN + i*NaN). Please see the example code in Annex G.

2. If a is large but representable with a^2=infinity. We get
   (a+ i*a)^2=(NaN+i*infinity) with the naive formula but we want
   (0+i*infinity)

3. The are cancellation problems.
   For example if we use 3 digit decimal floating point arithmetic with
   a=4.02, b=4.00, c=4.02 and d=4.00 the exact result for the
   real part would be $ac-bd = 0.1604$. But with the naive formula
   we get a * c = 16.2, b * c = 16.0 and thus a*c - b* d = 0.2.
   This make a 25% error.

The IEC 60559 standard deal only with problem 1 but not with the
problems 2 and 3. According to Annex G the "specifications (of IEC
60559) are not normative" and therefore I think we should do better
and use code that avoid all problems mentioned above. Perhaps we should
provide the IEC 60599 code through the __STDC_IEC_559_COMPLEX__ pragma
as suggested in Annex G.

I have a solution to the problems describe above and I am willing (and
hopefully able) to write a fix. How ever the resulting code would be
about 2-3 times slower than the naive code. For example on a computer
that has an fma machine instruction

p=-b*d;
r=fma(b,d,p);
x=fma(a,c,p)-r;

computes the real part avoiding cancellation, but this needs 4
operations where the naive formula needs only 2.

p=-b*d;
x=fma(a,c,p)

So please tell me do you think we should switch to more accurate
algorithms or would you prefer the old implementation?

With best regards
     Andreas Klein

    Institute for Mathematics and Computer Science
    klein@mathematik.uni-kassel.de
    University of Kassel
    Germany

PS: I am better in math than in email. So please be patient if have
    chosen the wrong format or the wrong group.


^ permalink raw reply	[flat|nested] 18+ messages in thread
* complex numbers
@ 2004-12-06  9:11 Andreas Klein
  2004-12-06 21:52 ` Gabriel Dos Reis
  0 siblings, 1 reply; 18+ messages in thread
From: Andreas Klein @ 2004-12-06  9:11 UTC (permalink / raw)
  To: gcc-bugs

Hello

I have found a bug in the implementation of the complex library of
g++ and the complex.h library of the gcc (c99 support).

The simplest program that demonstrates the bug is:

--------------------------------

#include<iostream>
#include<complex>

using namespace std;

int main() {
  complex<double> a = 1.0/0.0;  // + infinity
  complex<double> b = 1.0;
  complex<double> c = b/a;      // should be 0 but is (NaN,NaN)

  cout << a << endl;
  cout << b << endl;
  cout << c << endl;
}

--------------------------------

Since all values are real one should expect the result 0
(the IEEE floating-point value for 1/infinity). More serious is that
if a contains a large but representable value for which |a|^2 is not
representable the implementation will yields bad results. For example
let a be the largest representable number and b be a/2 then b/a should
be 0.5 and not NaN.

The bug comes from the naive implementation

a + b I    ac + bd   bc - ad
-------  = ------- + ------- I
c + d I    c^2+d^2   c^2+d^2

We get unnecessary overflow errors if c^2+d^2 is too large.

For a better result one should use the following formula due to Smith
(see "What Every Computer Scientist Should Know About Floating-Point
Arithmetic"  http://cch.loria.fr/documentation/IEEE754/)

           |  a + b(d/c)   c - a(d/c)
           |  ---------- + ---------- I     if |d| < |c|
a + b I    |  c + d(d/c)   a + d(d/c)
-------  = |
c + d I    |  b + a(c/d)   -a+ b(c/d)
           |  ---------- + ---------- I     if |d| >= |c|
           |  d + c(c/d)   d + c(c/d)

Even better we should test for |d| = |c| and definie

a + b I       a + b s   c - a s
-------  =    ------- + -------   if |d| = |c|
c + d I       c + d s   d + c s

where s = 1 if c and d have the same sign bit and s = -1
otherwise. (Especially if c = +0.0 and d = -0.0 we must set s = -1.)
This improves the results if |c|=|d|=0 or |c|=|d|=infinity.

So my suggestion is to add template specialization for the
operator/= for the types complex<float> complex<double> and
complex<long double> that use Smith formula. (For integer types I
think we should stay with the old implementation.)

I would volunteer to fix the c++ library.
But I have less experience in C99 so it would be better if another can
fix the c library. I guess that the same bug will be present in the
libraries of the other languages (Fortan, etc.), but I have not tested it.

I am sorry but I have difficulties with the bug database, so I send
you the mail directly.

With best regards
     Andreas Klein

    Institute for Mathematics and Computer Science
    klein@mathematik.uni-kassel.de
    University of Kassel
    Germany


^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2005-01-21 12:50 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-12-07 11:51 complex numbers Paolo Carlini
2004-12-07 13:07 ` Andreas Klein
2004-12-07 13:13   ` Paolo Carlini
2004-12-07 13:39     ` Paolo Carlini
2004-12-07 15:39     ` Andreas Klein
2004-12-07 15:45       ` Paolo Carlini
2004-12-08  9:28         ` Andreas Klein
2004-12-09  0:56           ` Paolo Carlini
2004-12-09  9:31             ` Andreas Klein
2004-12-07 16:07       ` Gabriel Dos Reis
  -- strict thread matches above, loose matches on Subject: below --
2005-01-21 12:47 Complex Numbers Paolo Carlini
2005-01-21 12:50 ` Paolo Carlini
2005-01-21 12:35 Andreas Klein
2004-12-06  9:11 complex numbers Andreas Klein
2004-12-06 21:52 ` Gabriel Dos Reis
2004-12-07  8:50   ` Andreas Klein
2004-12-07 16:05     ` Gabriel Dos Reis
2004-12-08  9:37       ` Andreas Klein

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).