- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This code:
#include <complex.h>
complex double f(complex double x, complex double y) {
return x*y;
}
when compiled with -O3 -march=core-avx2 -fp-model strict using Intel Compiler version 17 gives
f:
vunpcklpd xmm5, xmm0, xmm1
vmovddup xmm4, xmm2
vmovddup xmm6, xmm3
vshufpd xmm7, xmm5, xmm5, 1
vmulpd xmm8, xmm4, xmm5
vmulpd xmm9, xmm6, xmm7
vaddsubpd xmm0, xmm8, xmm9
vunpckhpd xmm1, xmm0, xmm0
ret
According to Annex G, Section 5.1, Paragraph 4 of the specs:
if x = a * ib is infinite and y = c * id is infinite, the number x * y must be infinite.
But if we let x = inf + i inf (an infinite value) and y = i inf (an infinite value) the result for the Intel code is x * y = NaN + iNaN due to the inf times 0 intermediates. This does not conform to the C99 specs as far as I can see.
Is this a bug and/or is there another set of flags to make complex multiplication C99 compliant?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, Raphael
Please try add option -std=c99 to align with C99 standard. By default the C compiler conforms to ISO C90 plus GNU extension on Linux.
Hope this helps.
Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Adding -std=c99 does not change the assembly code at all.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is full code to reproduce the problem:
#include <stdio.h>
#include <math.h>
#include <complex.h>
double complex f(double complex x, double complex y) {
return x*y;
}
int main(void)
{
double complex z1 = INFINITY + INFINITY * I;
double complex z2 = INFINITY * I;
complex double result = f(z1, z2);
printf("%f + i%f\n", creal(result), cimag(result));
}
With icc -std=c99 -Wall test-inf.c -o test-inf-icc you get
-nan + i-nan
which is not correct.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I meant
icc -std=c99 -fp-model strict test-inf.c -o test-inf-icc
which still gives the same incorrect output.
Raphael
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, Raphael
Thank you for the small reproducer.
I can reproduce the issue you reported. There are two warnings which shows INFINITY*I is treated as an out of range number for complex type. This should be incorrect.
I have escalated this issue and entered it in our problem tracking system. I will let you know when I have an update on this issue.
Thank you.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you very much. I look forward to hearing about any updates.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for all this Sergey Kostrov. An answer and a comment.
> The function f is declared as double complex f( double complex x, double complex y ) but a result variable is declared as complex double instead of double complex. Is that an error in your test case?
Quoting from http://stackoverflow.com/a/41679314/2179021 ,
"complex
is a macro from complex.h which expands into the type specifier _Complex
. This behaves as all other type specifiers, for example int, bool, double
. For all type specifiers belonging to the same "group", you can combine them in various orders. This is specified by C11 6.7.2[...]"
In other words, double complex and complex double are equivalent.
In relation yto our other comments about the behaviour of different C compilers, you might also be interested in the output of this code:
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
#include <math.h>
complex double f(complex double x, complex double y) {
return x*y;
}
int main(void){
complex double x = INFINITY + INFINITY * I;
complex double y = 0.0 + INFINITY * I;
complex double ret;
printf("x = %g + %g*I\n", creal(x), cimag(x));
printf("y = %g + %g*I\n", creal(y), cimag(y));
ret = f(x,y);
printf("f = %g + %g*I\n", creal(ret), cimag(ret));
exit(EXIT_SUCCESS);
}
In both gcc 5.4.0 and clang 3.8 you get:
x = nan + inf*I
y = nan + inf*I
f = -inf + -nan*I
icc outputs:
x = -nan + inf*I
y = -nan + inf*I
f = -nan + -nan*I
The output " f = -inf + -nan*I" that gcc and clang give is arguably strictly speaking correct as C99 defines any complex value with a part that is inf to be an infinity.
http://stackoverflow.com/a/42122851/2179021 shows what you have to do if you want to get x = inf + inf*I in gcc/clang/icc. That post also finishes with:
"Now this is not actually supposed to be a problem because in C, there is only one Complex Infinity, and every complex number whose one component is infinite is considered to be that infinity, even if the other component is NaN. All built-in arithmetic is supposed to honor that: so in my list above, only Intel appears to have a bug here where multiplication of two complex infinities gave a complex nan."
Note that my query is 100% about C and not C++.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
While I don't disagree with what Sergey says, in this case it appears to be a "constant folding" problem, internal to the compiler, not evident in the assembly. We'll work on it. Thanks for the report. --Melanie

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page