Issue Details (XML | Word | Printable)

Key: PCC-413
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Anders Magnusson
Reporter: Fred J. Tydeman
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
pcc

complex divide wrong

Created: 25/Dec/12 06:45 PM   Updated: 02/Jul/14 02:15 PM
Component/s: None
Affects Version/s: None
Fix Version/s: None

Environment: Intel x86/x87, Fedora Core 16, pcc 2011/12/16


 Description  « Hide
Complex divide gets wrong answer. Either divide is bad or alignment is wrong. The imaginary part of the result
has the exponent in the wrong place. So, instead of a NaN, it gets a denormal number. Complex numbers are
supposed to be treated as an array of two floating-point numbers.

static _Complex double res, left, right;
  res = left / right; /* both left and right are 0.0+0.0*I */

Produces:
res .im=00000000fff80000=+2.12173675827594550e-314
want .im=fff8000000000000=-nan
left .re=0000000000000000=+0.00000000000000000e+00
left .im=0000000000000000=+0.00000000000000000e+00
right.re=0000000000000000=+0.00000000000000000e+00
right.im=0000000000000000=+0.00000000000000000e+00


 All   Comments   Change History      Sort Order: Descending order - Click to sort in ascending order
Anders Magnusson added a comment - 02/Jul/14 02:15 PM
Now these tests at least works. I rewrote the complex div logic, following the C99 guidelines.

Fred J. Tydeman added a comment - 23/Jun/14 07:44 PM
A related problem in pcc and clang, is real / complex.

http://llvm.org/bugs/show_bug.cgi?id=20083

Anders Magnusson added a comment - 23/Jun/14 06:09 PM - edited
Interesting, the last of your examples failed with clang (but worked with gcc 4.8).

minint-rmn60om:/Users/ragge/tmp >clang -O cmplxdiv.c
minint-rmn60om:/Users/ragge/tmp >./a.out
fc1=(0,0)
fc2=(0,1.17549e-38)
fc3=(nan,nan)
Bad
minint-rmn60om:/Users/ragge/tmp >clang --version
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix

Anders Magnusson added a comment - 06/Jun/14 05:31 PM
Thanks for the pointers.
I need to find a way to deal with this compiler-wise without needing to add -lm for complex numbers.

Fred J. Tydeman added a comment - 06/Jun/14 05:00 PM
Look at C99 or C11 G.5.1 on some of the special cases. Also,
http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1399.txt

Anders Magnusson added a comment - 06/Jun/14 01:25 PM
The syntax for div seems a little more complicated than was initially thought, have to rewrite div handling.

Fred J. Tydeman added a comment - 04/Jun/14 08:25 PM
Here is another failure:

#include <float.h>
#include <complex.h>
#include <stdio.h>

int main(void){
  float complex fc1, fc2, fc3;
  fc1 = 0.f + I*0.f;
  fc2 = 0.f + I*FLT_MIN;
  fc3 = fc1 / fc2; /* zero / non-zero should be zero */
  (void)printf("fc1=(%g,%g)\n", creal(fc1), cimag(fc1));
  (void)printf("fc2=(%g,%g)\n", creal(fc2), cimag(fc2));
  (void)printf("fc3=(%g,%g)\n", creal(fc3), cimag(fc3));
  if( (0.f != creal(fc3)) || (0.f != cimag(fc3)) ){
    (void)printf("Bad\n");
  }
  return 0;
}

Fred J. Tydeman added a comment - 02/Jun/14 08:03 PM
Here is a test that fails 2012/04/20 version

#include <complex.h>
#include <stdio.h>
static float complex fc1; /* 0.f + 0.f*I */
static float f; /* 0.f */
int main(void){
  fc1 = fc1 / f;
  (void)printf("%g, %g\n", creal(fc1), cimag(fc1)); /* should be nan, nan */
  return 0;
}

Fred J. Tydeman added a comment - 02/Jun/14 03:37 PM
This still has problems in 2014/04/20 version of pcc.
I am now testing the 64-bit version on an Intel Core 2 Duo.
The OS is Linux Fedora Core 20.

Anders Magnusson added a comment - 30/Apr/14 05:57 PM
Complex div fixed now.

Fred J. Tydeman added a comment - 28/Dec/12 06:10 PM
Another failure:
#include <float.h>
 float _Complex res, left, right;
  left = 0.f + FLT_EPSILON * I;
  right = left;
  res = left / right;

 res should be 1.f + 0.f*I
Instead my test program gets garbage for the imaginary part of res:
res .im=4e706848=+1.00834150400000000e+09
want .im=00000000=+0.00000000000000000e+00
left .re=00000000=+0.00000000000000000e+00
left .im=34000000=+1.19209289550781250e-07
right.re=00000000=+0.00000000000000000e+00
right.im=34000000=+1.19209289550781250e-07

Letting
 left = right = 0.f + 1.f/3.f * I;
gets the same wrong imaginary part for res:
res .im=4e706848=+1.00834150400000000e+09
want .im=00000000=+0.00000000000000000e+00
left .re=00000000=+0.00000000000000000e+00
left .im=3eaaaaaa=+3.33333313465118408e-01
right.re=00000000=+0.00000000000000000e+00
right.im=3eaaaaaa=+3.33333313465118408e-01


The same kind of issue happens with
 double _Complex res, left, right;
 left = right = 0.0 + DBL_EPSILON * I;
 res = left / right;
gets:
res .im=08048a2ebfdf204c=+4.85992534235132247e-270
want .im=0000000000000000=+0.00000000000000000e+00
left .re=0000000000000000=+0.00000000000000000e+00
left .im=3cb0000000000000=+2.22044604925031308e-16
right.re=0000000000000000=+0.00000000000000000e+00
right.im=3cb0000000000000=+2.22044604925031308e-16