/* { dg-options "-O0 -std=gnu99" } */ int main (void) { _Complex double d; __real__ d = 1.0; __imag__ d = 1.0; d = d / 0.0; if (!__builtin_isinf (__real__ d) || !__builtin_isinf (__imag__ d)) __builtin_abort (); return 0; }
fails when compiled with -O0 -std=c99 but succeeds when compiled with -O2 -std=c99. ISO C99 says it should be (inf, inf) always in G.5.1 (4): "if the first operand is a nonzero finite number or an infinity and the second operand is a zero, then the result of the / operator is an infinity." The problem is that libgcc _divdc3 doesn't do logarithmic scaling: /* ??? We can get better behavior from logarithmic scaling instead of the division. But that would mean starting to link libgcc against libm. We could implement something akin to ldexp/frexp as gcc builtins fairly easily... */ if (FABS (c) < FABS (d)) { ratio = c / d; denom = (c * ratio) + d; x = ((a * ratio) + b) / denom; y = ((b * ratio) - a) / denom; } else { ratio = d / c; denom = (d * ratio) + c; x = ((b * ratio) + a) / denom; y = (b - (a * ratio)) / denom; } so when c == d == 0.0, denom is not 0.0 as later code is testing, but NaN. To fix this, I think we either need to switch to logarithmic scaling, or we need to special case FABS (c) == FABS (d) case, or the denom == 0.0 change ought should change (would c == 0.0 && d == 0.0 be enough?). -- Summary: Complex divide bug Product: gcc Version: 4.1.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: jakub at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30360