Possible bugs?

Possible bugs?

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?

7 post / 0 nuovi
Ultimo contenuto
Per informazioni complete sulle ottimizzazioni del compilatore, consultare l'Avviso sull'ottimizzazione

These are not equivilent expressions. Build a truth table


				(!((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

Jim Dempsey

www.quickthreadprogramming.com

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.


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 %dn", 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;

}

Perhaps at issue is an IPO thing (Inter-Procedural Optimization).
Can you make a reproducer?

Jim Dempsey

www.quickthreadprogramming.com

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).

>>...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?

The settings are: /GS /Qopenmp /Qrestrict /W1 /QxAVX /Zi /O3 /fp:precise /Quse-intel-optimized-headers

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.


#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);

            }

}

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.


#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);

   }

}

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.

Lascia un commento

Eseguire l'accesso per aggiungere un commento. Non siete membri? Iscriviti oggi