This 'little' program behaves bad when compiled with -O. It works fine when no -O or -O0 is used.
The function is from Graphics Gem I and has been ported from C to C++ http://www.acm.org/pubs/tog/GraphicsGems/gems.html#gems Woo, Andrew, Fast Ray-Box Intersection, p. 395-396, code: p. 736-737 This is how things went when compiling on my Debian unstable (current as of 2006-06-18). The problem has also been encountererd on redhat rhel (3?) but not investigated there. No flags were used except -On (The program do compile cleanly with -Wall -W -pedantic) -O0 -O1 -O2 -O3 g++-2.95 ok error error error g++-3.3 ok error error error g++-3.4 ok ok error error g++-4.0 ok error error error g++-4.1 ok error error error g++ -v output for each compiler it further down. Have I done something wrong or is this something for the bugzilla? minus // ********** Start of program #include <iostream> #include <vector> using namespace std; class GeoPoint { public: inline GeoPoint(double east, double north, double height) {elt_[0]=east;elt_[1]=north;elt_[2]=height;} GeoPoint& operator-=(const GeoPoint& p) { elt_[0] -= p[0]; elt_[1] -= p[1]; elt_[2] -= p[2]; return *this; } GeoPoint& operator-=(const double p) { elt_[0]-=p; elt_[1]-=p; elt_[2]-=p; return *this; } GeoPoint& operator+=(const double p) { elt_[0]+=p; elt_[1]+=p; elt_[2]+=p; return *this; } double &operator[](int i) { return elt_[i]; } const double &operator[](int i) const { return elt_[i]; } private: double elt_[3]; private: friend std::ostream& operator<<(std::ostream& s,const GeoPoint& a); }; std::ostream& operator<<(std::ostream& s,const GeoPoint& a) { s << " ( " << a[0] << " " << a[1] << " " << a[2] << " ) "; return s; } /*********************************************************************/ bool rayBoxIntersection(const GeoPoint& ll, const GeoPoint& ur, const GeoPoint& start, const GeoPoint& end, GeoPoint& coord) { typedef enum {RIGHT,LEFT,MIDDLE} PlaneRelative; const int NumberOfDimensions=3; bool inside=true; PlaneRelative quadrant[NumberOfDimensions]; GeoPoint candidatePlane(0.0,0.0,0.0); GeoPoint dir(end); dir-=start; GeoPoint maxT(-1,-1,-1); // Find candidate planes for (int i=0; i<NumberOfDimensions; i++) { if (start[i]<ll[i]) { quadrant[i] = LEFT; candidatePlane[i]=ll[i]; inside=false; } else if (start[i]>ur[i]) { quadrant[i] = RIGHT; candidatePlane[i]=ur[i]; inside=false;; } else { quadrant[i] = MIDDLE; } } if (inside) { coord=start; return true; } // calculate T distances to candidate planes for (int i=0; i<NumberOfDimensions; i++) { if (quadrant[i]!=MIDDLE && dir[i] !=0.0) { maxT[i]=(candidatePlane[i]-start[i])/dir[i]; } else { maxT[i]=-1.0; } } //get largest maxT for final choice of intersection int whichPlane=0; for (int i=1; i<NumberOfDimensions; i++) { if (maxT[whichPlane]<maxT[i]) { whichPlane=i; } } if (maxT[whichPlane]<0.0) { // didn't hit the box return (false); } for (int i=0; i<NumberOfDimensions; i++) { if (whichPlane==i) { coord[i]=candidatePlane[i]; } else { coord[i]=start[i]+maxT[whichPlane]*dir[i]; // **** Uncomment one of these to make the program work. //sleep(0); //cerr << ""; if ((coord[i]<ll[i]) || (coord[i]>ur[i])) { // outside box return false; } } } return true; } /*********************************************************************/ int main(void) { vector<GeoPoint> p; // define three boxes. p.push_back(GeoPoint(1.004,1.004,1.004)); // at start of line p.push_back(GeoPoint(1.020,1.020,1.020)); // middle of line p.push_back(GeoPoint(1.046,1.046,1.046)); // at end of line GeoPoint start(1.000,1.000,1.000); GeoPoint end(1.050,1.050,1.050); for (vector<GeoPoint>::const_iterator iter=p.begin(); iter!=p.end(); ++iter) { GeoPoint ll(*iter); GeoPoint ur(*iter); ll-=0.005; ur+=0.005; GeoPoint hit(-1,-1,-1); GeoPoint hitreverse(-1,-1,-1); // find where the first hit inside the box (ll,ur) of the // line between start and end bool res1=rayBoxIntersection(ll,ur,start,end,hit); // find where the first hit inside the box (ll,ur) of the // line between end and start (the reverse direction compared // to the previous call) bool res2=rayBoxIntersection(ll,ur,end,start,hitreverse); if (res1 && res2) { cout << "ok: " << endl; } else { cout << "error" << endl; } } return 0; } // ********** End of program // ********** output from g++ -v for each compiler used. Reading specs from /usr/lib/gcc-lib/i486-linux-gnu/2.95.4/specs gcc version 2.95.4 20011002 (Debian prerelease) Reading specs from /usr/lib/gcc-lib/i486-linux-gnu/3.3.6/specs Configured with: ../src/configure -v --enable-languages=c,c++ --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-gxx-include-dir=/usr/include/c++/3.3 --enable-shared --enable-__cxa_atexit --with-system-zlib --enable-nls --without-included-gettext --enable-clocale=gnu --enable-debug i486-linux-gnu Thread model: posix gcc version 3.3.6 (Debian 1:3.3.6-13) Reading specs from /usr/lib/gcc/i486-linux-gnu/3.4.6/specs Configured with: ../src/configure -v --enable-languages=c,c++,f77,pascal --prefix=/usr --libexecdir=/usr/lib --with-gxx-include-dir=/usr/include/c++/3.4 --enable-shared --with-system-zlib --enable-nls --without-included-gettext --program-suffix=-3.4 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --with-tune=i686 i486-linux-gnu Thread model: posix gcc version 3.4.6 (Debian 3.4.6-2) Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c ++,java,f95,objc,ada,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.0 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-java-awt=gtk-default --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-4.0-1.4.2.0/jre --enable-mpfr --disable-werror --with-tune=i686 --enable-checking=release i486-linux-gnu Thread model: posix gcc version 4.0.4 20060507 (prerelease) (Debian 4.0.3-3) Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c ++,java,fortran,objc,obj-c++,ada,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-4.1-1.4.2.0/jre --enable-mpfr --with-tune=i686 --enable-checking=release i486-linux-gnu Thread model: posix gcc version 4.1.2 20060613 (prerelease) (Debian 4.1.1-5) --