Use cpack() and the gcc extension __imag__ to implement cimag() and

conj() instead of using expressions like z * I. The latter is bad for
several reasons:

1. It is implemented using arithmetic, which is unnecessary, and can
   generate floating point exceptions, contrary to the requirements on
   these functions.

2. gcc implements complex multiplication using a formula that breaks
   down for infinities, e.g., it gives INFINITY * I == nan + inf I.
This commit is contained in:
David Schultz 2008-08-07 14:39:56 +00:00
parent 5cb2685a59
commit ad5e21e24b
6 changed files with 18 additions and 6 deletions

View File

@ -31,5 +31,6 @@
double
cimag(double complex z)
{
return -z * I;
return (__imag__ z);
}

View File

@ -31,5 +31,6 @@
float
cimagf(float complex z)
{
return -z * I;
return (__imag__ z);
}

View File

@ -31,5 +31,6 @@
long double
cimagl(long double complex z)
{
return -z * I;
return (__imag__ z);
}

View File

@ -28,8 +28,11 @@
#include <complex.h>
#include "math_private.h"
double complex
conj(double complex z)
{
return creal(z) - I * cimag(z);
return (cpack(creal(z), -cimag(z)));
}

View File

@ -28,8 +28,11 @@
#include <complex.h>
#include "math_private.h"
float complex
conjf(float complex z)
{
return crealf(z) - I * cimagf(z);
return (cpackf(crealf(z), -cimagf(z)));
}

View File

@ -28,8 +28,11 @@
#include <complex.h>
#include "math_private.h"
long double complex
conjl(long double complex z)
{
return creall(z) - I * cimagl(z);
return (cpackl(creall(z), -cimagl(z)));
}