Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7830 Discussions

Possible bugs?

Beginner
333 Views

case 1:

if (!((a>b&&c>d)||(a<b&&c<d)))

case 2:

if ((a>b&&c<d)||(a<b&&c>d)||(a==b)||(c==d))

Where, a, b, c, d are some non-NaN random double variables (between -1 and 1 in my case, I also test them with random variables generated by ippsGaussRand_Direct_64f() functions and the results for case 1 are also incorrect).

Anyone can see the above 2 experssions are of the same thing, but the complier (ICC 13.0, x86-64, highest level of optimization, Windows-64 OS) only return correct results for the second experssion, is this a bug here?

6 Replies
Black Belt
333 Views
These are not equivilent expressions. Build a truth table [cpp] (!((a > b && c > d)||(a < b && c < d))) a b c d ! 1 1 1 1 !((F...)||(F...)) T 1 2 1 1 !((F...)||(F...)) T 2 1 1 1 !((T&&F)||(F...)) T 1 1 1 2 !((F...)||(F...)) T 1 2 1 2 !((F...)||(T&&T)) F 2 1 1 2 !((T&&F)||(F...)) T 1 1 2 1 !((F...)||(F...)) T 1 2 2 1 !((F...)||(T&&F)) T 2 1 2 1 !((T&&T)||(...)) F ((a > b&&c < d)||(a < b&&c > d)||(a==b)||(c==d)) a b c d 1 1 1 1 (F...)||(F...)||(T)||(.) T 1 2 1 1 (F...)||(T&&F)||(T)||(.) T 2 1 1 1 (T&&F)||(F...)||(T)||(.) T 1 1 1 2 (F...)||(F...)||(T)||(.) T 1 2 1 2 (F...)||(T&&F)||(F)||(F) F 2 1 1 2 (T&&F)||(F...)||(F)||(F) F 1 1 2 1 (F...)||(F...)||(T)||(.) T 1 2 2 1 (F...)||(T&&T)||(.)||(.) T 2 1 2 1 (T&&F)||(F...)||(F)||(F) F [/cpp] Jim Dempsey
Black Belt
333 Views
I may need to retract the above hand written truth table. Subsiquent to the post I wrote a simple program to illustrate, the program produces the same results for the two expressions. I suspect the hand written table is incorrect.... Yes, the 2 1 1 2 was incorrect for the second table. [cpp] int _tmain(int argc, _TCHAR* argv[]) { int ia,ib,ic,id; double a,b,c,d; for(ia = 1; ia <= 2; ++ia) { a = ia; for(ib = 1; ib <= 2; ++ib) { b = ib; for(ic = 1; ic <= 2; ++ic) { c = ic; for(id = 1; id <= 2; ++id) { d = id; printf("%lf %lf %lf %lf %d %d\n", a, b, c, d, (!((a > b && c>d)||(a < b && c < d))), ((a > b&&c < d)||(a < b&&c > d)||(a==b)||(c==d))); } } } } return 0; } [/cpp] Perhaps at issue is an IPO thing (Inter-Procedural Optimization). Can you make a reproducer? Jim Dempsey
Black Belt
333 Views
Jim, There is just a simple error in line-36 of your truth table. (T&&F) should have been (T&&T) because c (=1) is less than d (=2).
Valued Contributor II
333 Views
>>...Where, a, b, c, d are some non-NaN random double variables (between -1 and 1 in my case... I agree that a complete test-case that uses IPP ippsGaussRand_Direct_64f to generate a, b, c and d values would help. >>...highest level of optimization... Could you post the C++ compiler command line options?
Beginner
333 Views
The settings are: /GS /Qopenmp /Qrestrict /W1 /QxAVX /Zi /O3 /fp:precise /Quse-intel-optimized-headers
Black Belt
333 Views
From a logical/mathematical perspective, running a test (by hand or using a short program, as Jim showed), but with one set (or many sets) of values for the real variables a,b,c,d, is sufficient to prove non-equivalence. Such a test is not sufficient to prove equivalence, given the possibility that both candidate logical expressions may yield different values for different combinations of a, b, c, d. By applying Boolean Algebra rules, I come to the same conclusion as the OP, that is, the two expressions are equivalent. The next question is: Does the Intel C compiler show a bug in this regard? I ran the following test program, which makes the four real variables cover the range (-5,+5), taking steps that are slightly larger than 0.1. [cpp] #include <stdio.h> main(){ float a,b,c,d; int r1,r2; for(a=-5.0; a<=5.0; a+=0.111) for(b=-5.0; b<=5.0; b+=0.112) for(c=-5.0; c<=5.0; c+=0.113) for(d=-5.0; d<=5.0; d+=0.114){ r1 = !((a > b && c > d)||(a < b && c < d)); r2 = (a > b && c < d) || (a < b && c > d) || (a==b) || (c==d); if(r1-r2)printf("%7.1e %7.1e %7.1e %7.1e %e %e\\n",a,b,c,d,r1,r2); } } [/cpp] Running this program showed no error after compiling with the 13.0.1.119 X64 compiler with (i) options /O3 /QxAVX and (ii) the options shown above by the OP. Here is another test program, which calls IPP to generate one million sets of normally distributed values of a, b, c, d , with mean = 0 and standard-deviation = 1. [cpp] #include <stdio.h> #include <ipp.h> #define NSAMP 1000000 #define LEN 4*NSAMP Ipp32f samp[LEN]; main(){ float a,b,c,d; int r1,r2,i,len=LEN; IppsRandGaussState_32f *pRandGaussState; ippsRandGaussInitAlloc_32f(&pRandGaussState, 0.0, 1.0, 162903); ippsRandGauss_32f(samp, len, pRandGaussState); for(i=0; i<NSAMP; i++){ a=samp[4*i]; b=samp[4*i+1]; c=samp[4*i+2]; d=samp[4*i+3]; r2 = !((a > b && c > d)||(a < b && c < d)); r1 = (a > b && c < d) || (a < b && c > d) || (a==b) || (c==d); if(r1-r2)printf("%7.1e %7.1e %7.1e %7.1e %e %e\\n",a,b,c,d,r1,r2); if((i+1)%10000==0)printf("%8d",(i+1)/10000); } } [/cpp] As I stated earlier, my test programs are inconclusive: no error was found for the several sets of values of a, b, c, d   tried in them. We need the OP to present values of a,b,c,d   for which an error is encountered.