Re: [Vxl-maintainers] fast floor function From: Tom Vercauteren - 2008-08-05 11:37:33 ```> The best thing to do --I believe-- is to insert at least the following 8 lines at line 181 of core/vnl/vnl_math.h : > > =============================================== > // floor -- round towards minus infinity > inline int vnl_math_floor(float x) { return (x>=0.0)?(int)(x):-(int)(-x); } > inline int vnl_math_floor(double x) { return (x>=0.0)?(int)(x):-(int)(-x); } > > // ceil -- round towards plus infinity > inline int vnl_math_ceil(float x) { return (x>=0.0)?-(int)(-x):(int)(x); } > inline int vnl_math_ceil(double x) { return (x>=0.0)?-(int)(-x):(int)(x); } > =============================================== > > and supplement these with the appropriate __asm which as you pointed out is very similar to the code for vnl_math_rnd. Seems fine to me! > Also the "divide by 2" trick in that article is interesting -- we should add it to the implementation of vnl_math_rnd: 8.50 should round to 9, not to 8, I would say. I agree that the "divide by 2" trick is great. Actually, we use such a code on both gcc and msvc by default instead of the lround calls. It proved to be faster. It might however also be interesting to allow the user to use the full int range instead of restricting it to INT_MIN/2 to INT_MAX/2. On MSVC, the round functions we use are: inline int vnl_math_rnd(double x) { int r; x = 2*x+.5; __asm { fld x fistp r } return r>>1; } inline int vnl_math_rnd(float x) { int r; x = 2*x+.5f; __asm { fld x fistp r } return r>>1; } Similarly on gcc: inline int vnl_math_rnd(double x) { // assert(fegetround()==FE_TONEAREST); // assert (x > static_cast (INT_MIN / 2) – 1.0); // assert (x < static_cast (INT_MAX / 2) + 1.0); int r; x = 2*x+.5; __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st"); return r>>1; } inline int vnl_math_rnd(float x) { int r; x = 2*x+.5f; __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st"); return r>>1; } ```