Small .C program shows a problem where a value of 1.0 is calculated, but that value falls through 2 if-checks ... one checks for "if (val <= 1.0)" , the next checks for "if (val > 1.0)" ... one of these if checks must be true but neither true leg is taken. problem surfaces at optimization level -O1 (also tested -O2 and -O3 ... same problem) problem goes away with -ffloat-store , although I feel this is a logic problem and not a precision problem. problem goes away if compiled as .c (with pass-by-reference removed) g++ -v -save-temps -O1 -o tmp1 tmp1.C This is my first bug ... I am going to committ ... may add attachments later if not given the opportunity now
*** This bug has been marked as a duplicate of 323 ***
Created attachment 8473 [details] output of g++ -v -save-temps
Created attachment 8474 [details] preprocess output from g++ -v -save-temps
I do not think this is a precision problem. Although -ffloat-store resolves the problem, I feel this has changed the behavior of the program sufficiently to avoid the problem ... I should not have mentioned that -ffloat-store resolved the problem in my earlier note // following is pseudocode ... run actual testcase to see problem float i=1.0; // actually, a bunch of math that = 1.0 if ( i <= 1.0 ) return 0; if ( ( i > 1.0 ) && ( i < 1.0001 ) ) return 0; return 1; I should never get a 1 for a return code. Change 1.0001 in my testcase to 1.1, you still see the problem.
If you write the function like so: enum myRC doSomeMath ( int i1, float *f1, float* f2, float* f3, float* f4 ) { int i; float f5=0.0; float f6=0.0; float f7=0.0; for(i=0; i<i1global; i++){ f5+=f1[i]*f1[i]; f6+=f2global[i1][i]*f2global[i1][i]; f7+=f1[i]*f2global[i1][i]; } *f2=sqrt(f5); *f3=sqrt(f6); *f4=f7/(*f2* *f3); if((*f4>=-1.0)&&(*f4<=1.0))return(mySuccess); if((*f4>1.0)&&(*f4<1.000001)){ *f4=1.0; return(mySuccess); } if((*f4<-1.0)&&(*f4>-1.000001)){ *f4=-1.0; return(mySuccess); } if ( chkWithEqual == 1 ) { if((*f4>=1.0)&&(*f4<1.000001)){ *f4=1.0; return(mySuccess); } if((*f4<=-1.0)&&(*f4>-1.000001)){ *f4=-1.0; return(mySuccess); } } printf("%f is out of range -1.0 to 1.0\n",*f4); return(myFailure); } You still get the fail even with the C front-end in 3.4.0. Note this does not fail in 4.0.0 and above (though there might be a way get a simlar failure if you have time to fiind one. But I think this is still a precission problem.
I tried this on a 64-bit system, and noticed I needed to compile -m32 to get the error (this was on an older gcc level, though. 3.2.3) I don't understand how this can be a precision problem. How can both if checks be true? val <= 1.0 and val > 1.0
my mistake in the previous post how can both if-checks be false? val <= 1.0 and val > 1.0
(In reply to comment #6) > I tried this on a 64-bit system, and noticed I needed to compile -m32 to get > the error (this was on an older gcc level, though. 3.2.3) Well considering x86_64 uses the sse register math by default and not x87, I really doubt that it would be effect that. I would try it on a sane target first like say PPC where you have no excusive precission. Oh the reason is because one checks before the precission is truncated and the next one is after. Look at the example of 323 to give you an idea where this can happen.
323 compares 2 values across a function call ... somthing a programmer can reasonably consider. My problem occurs with 2 successive lines of code admittedly with 2 compares per line). I don't have a problem that the value of the variable changes after precision truncation ... but it seems like a bug that the compiler uses a full precision value for the 1st test and a truncated value for the 2nd test (the 2nd test being the next line of C++ code).
Subject: Re: unexpected result from floating compare On Mon, 2005-03-28 at 23:05 +0000, piaget at us dot ibm dot com wrote: > ------- Additional Comments From piaget at us dot ibm dot com 2005-03-28 23:05 ------- > 323 compares 2 values across a function call ... somthing a programmer can > reasonably consider. My problem occurs with 2 successive lines of code > admittedly with 2 compares per line). I don't have a problem that the value of > the variable changes after precision truncation ... but it seems like a bug > that the compiler uses a full precision value for the 1st test and a truncated > value for the 2nd test (the 2nd test being the next line of C++ code). Except, the value could have been spilled and reloaded from registers between those two source lines, which on x86, is where the problem comes from. The problem is no different simply because the *source* lines happen to be right next to each other.
(In reply to comment #10) > Except, the value could have been spilled and reloaded from registers > between those two source lines, which on x86, is where the problem comes > from. > The problem is no different simply because the *source* lines happen to > be right next to each other. I would have expected a compiler to identify these situations and produce code that logically matches the code being compiled. If this is not the case, then maybe -ffloat-store should be the default behavior with appropriate warnings about turning -ffloat-store off.