Go to the documentation of this file.00001
00002 #ifndef vil_round_h_
00003 #define vil_round_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007
00008
00009
00010
00011
00012
00013 #include <vxl_config.h>
00014 #include <vil/vil_config.h>
00015 #ifdef VNL_CHECK_FPU_ROUNDING_MODE
00016 # include <vcl_cassert.h>
00017 #endif
00018
00019
00020 #if VIL_CONFIG_ENABLE_SSE2_ROUNDING
00021 # if !VXL_HAS_EMMINTRIN_H
00022 # error "Required file emmintrin.h for SSE2 not found"
00023 # else
00024 # include <emmintrin.h>
00025 # endif
00026 #endif
00027
00028
00029
00030 #if defined(__GNUC__) && (!defined(__APPLE__) || !defined(__ppc__) )
00031 # define GCC_USE_FAST_IMPL 1
00032 #else
00033 # define GCC_USE_FAST_IMPL 0
00034 #endif
00035
00036 #if defined(VCL_VC) && !defined(_WIN64)
00037 # define VC_USE_FAST_IMPL 1
00038 #else
00039 # define VC_USE_FAST_IMPL 0
00040 #endif
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #if VIL_CONFIG_ENABLE_SSE2_ROUNDING // Fast sse2 implementation
00056
00057 inline int vil_round_rnd_halfinttoeven(float x)
00058 {
00059 # if defined(VIL_CHECK_FPU_ROUNDING_MODE) && defined(__GNUC__)
00060 assert(fegetround()==FE_TONEAREST);
00061 # endif
00062 return _mm_cvtss_si32(_mm_set_ss(x));
00063 }
00064 inline int vil_round_rnd_halfinttoeven(double x)
00065 {
00066 # if defined(VIL_CHECK_FPU_ROUNDING_MODE) && defined(__GNUC__)
00067 assert(fegetround()==FE_TONEAREST);
00068 # endif
00069 return _mm_cvtsd_si32(_mm_set_sd(x));
00070 }
00071
00072 #elif GCC_USE_FAST_IMPL // Fast gcc asm implementation
00073
00074 inline int vil_round_rnd_halfinttoeven(float x)
00075 {
00076 # ifdef VIL_CHECK_FPU_ROUNDING_MODE
00077 assert(fegetround()==FE_TONEAREST);
00078 # endif
00079 int r;
00080 __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
00081 return r;
00082 }
00083 inline int vil_round_rnd_halfinttoeven(double x)
00084 {
00085 # ifdef VIL_CHECK_FPU_ROUNDING_MODE
00086 assert(fegetround()==FE_TONEAREST);
00087 # endif
00088 int r;
00089 __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
00090 return r;
00091 }
00092
00093 #elif VC_USE_FAST_IMPL // Fast msvc asm implementation
00094
00095 inline int vil_round_rnd_halfinttoeven(float x)
00096 {
00097 int r;
00098 __asm {
00099 fld x
00100 fistp r
00101 }
00102 return r;
00103 }
00104 inline int vil_round_rnd_halfinttoeven(double x)
00105 {
00106 int r;
00107 __asm {
00108 fld x
00109 fistp r
00110 }
00111 return r;
00112 }
00113
00114 #else // Vanilla implementation
00115
00116 inline int vil_round_rnd_halfinttoeven(float x)
00117 {
00118 if (x>=0.f)
00119 {
00120 x+=0.5f;
00121 const int r = static_cast<int>(x);
00122 if ( x != static_cast<float>(r) ) return r;
00123 return 2*(r/2);
00124 }
00125 else
00126 {
00127 x-=0.5f;
00128 const int r = static_cast<int>(x);
00129 if ( x != static_cast<float>(r) ) return r;
00130 return 2*(r/2);
00131 }
00132 }
00133 inline int vil_round_rnd_halfinttoeven(double x)
00134 {
00135 if (x>=0.)
00136 {
00137 x+=0.5;
00138 const int r = static_cast<int>(x);
00139 if ( x != static_cast<double>(r) ) return r;
00140 return 2*(r/2);
00141 }
00142 else
00143 {
00144 x-=0.5;
00145 const int r = static_cast<int>(x);
00146 if ( x != static_cast<double>(r) ) return r;
00147 return 2*(r/2);
00148 }
00149 }
00150
00151 #endif
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 #if VIL_CONFIG_ENABLE_SSE2_ROUNDING || GCC_USE_FAST_IMPL || VC_USE_FAST_IMPL
00167
00168 inline int vil_round_rnd_halfintup(float x) { return vil_round_rnd_halfinttoeven(2*x+0.5f)>>1; }
00169 inline int vil_round_rnd_halfintup(double x) { return vil_round_rnd_halfinttoeven(2*x+0.5)>>1; }
00170
00171 #else // Vanilla implementation
00172
00173 inline int vil_round_rnd_halfintup(float x)
00174 {
00175 x+=0.5f;
00176 return static_cast<int>(x>=0.f?x:(x==static_cast<int>(x)?x:x-1.f));
00177 }
00178 inline int vil_round_rnd_halfintup(double x)
00179 {
00180 x+=0.5;
00181 return static_cast<int>(x>=0.?x:(x==static_cast<int>(x)?x:x-1.));
00182 }
00183
00184 #endif
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 #if VIL_CONFIG_ENABLE_SSE2_ROUNDING || GCC_USE_FAST_IMPL || VC_USE_FAST_IMPL
00200
00201 inline int vil_round_rnd(float x) { return vil_round_rnd_halfinttoeven(x); }
00202 inline int vil_round_rnd(double x) { return vil_round_rnd_halfinttoeven(x); }
00203
00204 #else // Vanilla implementation
00205
00206 inline int vil_round_rnd(float x) { return x>=0.f?static_cast<int>(x+.5f):static_cast<int>(x-.5f); }
00207 inline int vil_round_rnd(double x) { return x>=0.0?static_cast<int>(x+0.5):static_cast<int>(x-0.5); }
00208
00209
00210 #endif
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 #if VIL_CONFIG_ENABLE_SSE2_ROUNDING // Fast sse2 implementation
00222
00223 inline int vil_round_floor(float x)
00224 {
00225 # if defined(VIL_CHECK_FPU_ROUNDING_MODE) && defined(__GNUC__)
00226 assert(fegetround()==FE_TONEAREST);
00227 # endif
00228 return _mm_cvtss_si32(_mm_set_ss(2*x-.5f))>>1;
00229 }
00230 inline int vil_round_floor(double x)
00231 {
00232 # if defined(VIL_CHECK_FPU_ROUNDING_MODE) && defined(__GNUC__)
00233 assert(fegetround()==FE_TONEAREST);
00234 # endif
00235 return _mm_cvtsd_si32(_mm_set_sd(2*x-.5))>>1;
00236 }
00237
00238 #elif GCC_USE_FAST_IMPL // Fast gcc asm implementation
00239
00240 inline int vil_round_floor(float x)
00241 {
00242 # ifdef VIL_CHECK_FPU_ROUNDING_MODE
00243 assert(fegetround()==FE_TONEAREST);
00244 # endif
00245 int r;
00246 x = 2*x-.5f;
00247 __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
00248 return r>>1;
00249 }
00250 inline int vil_round_floor(double x)
00251 {
00252 # ifdef VIL_CHECK_FPU_ROUNDING_MODE
00253 assert(fegetround()==FE_TONEAREST);
00254 # endif
00255 int r;
00256 x = 2*x-.5;
00257 __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
00258 return r>>1;
00259 }
00260
00261 #elif VC_USE_FAST_IMPL // Fast msvc asm implementation
00262
00263 inline int vil_round_floor(float x)
00264 {
00265 int r;
00266 x = 2*x-.5f;
00267 __asm {
00268 fld x
00269 fistp r
00270 }
00271 return r>>1;
00272 }
00273 inline int vil_round_floor(double x)
00274 {
00275 int r;
00276 x = 2*x-.5;
00277 __asm {
00278 fld x
00279 fistp r
00280 }
00281 return r>>1;
00282 }
00283
00284 #else // Vanilla implementation
00285
00286 inline int vil_round_floor(float x)
00287 {
00288 return static_cast<int>(x>=0.f?x:(x==static_cast<int>(x)?x:x-1.f));
00289 }
00290 inline int vil_round_floor(double x)
00291 {
00292 return static_cast<int>(x>=0.0?x:(x==static_cast<int>(x)?x:x-1.0));
00293 }
00294
00295 #endif
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 #if VIL_CONFIG_ENABLE_SSE2_ROUNDING // Fast sse2 implementation
00307
00308 inline int vil_round_ceil(float x)
00309 {
00310 # if defined(VIL_CHECK_FPU_ROUNDING_MODE) && defined(__GNUC__)
00311 assert(fegetround()==FE_TONEAREST);
00312 # endif
00313 return -(_mm_cvtss_si32(_mm_set_ss(-.5f-2*x))>>1);
00314 }
00315 inline int vil_round_ceil(double x)
00316 {
00317 # if defined(VIL_CHECK_FPU_ROUNDING_MODE) && defined(__GNUC__)
00318 assert(fegetround()==FE_TONEAREST);
00319 # endif
00320 return -(_mm_cvtsd_si32(_mm_set_sd(-.5-2*x))>>1);
00321 }
00322
00323 #elif GCC_USE_FAST_IMPL // Fast gcc asm implementation
00324
00325 inline int vil_round_ceil(float x)
00326 {
00327 # ifdef VIL_CHECK_FPU_ROUNDING_MODE
00328 assert(fegetround()==FE_TONEAREST);
00329 # endif
00330 int r;
00331 x = -.5f-2*x;
00332 __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
00333 return -(r>>1);
00334 }
00335 inline int vil_round_ceil(double x)
00336 {
00337 # ifdef VIL_CHECK_FPU_ROUNDING_MODE
00338 assert(fegetround()==FE_TONEAREST);
00339 # endif
00340 int r;
00341 x = -.5-2*x;
00342 __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
00343 return -(r>>1);
00344 }
00345
00346 #elif VC_USE_FAST_IMPL // Fast msvc asm implementation
00347
00348 inline int vil_round_ceil(float x)
00349 {
00350 int r;
00351 x = -.5f-2*x;
00352 __asm {
00353 fld x
00354 fistp r
00355 }
00356 return -(r>>1);
00357 }
00358 inline int vil_round_ceil(double x)
00359 {
00360 int r;
00361 x = -.5-2*x;
00362 __asm {
00363 fld x
00364 fistp r
00365 }
00366 return -(r>>1);
00367 }
00368
00369 #else // Vanilla implementation
00370
00371 inline int vil_round_ceil(float x)
00372 {
00373 return static_cast<int>(x<0.f?x:(x==static_cast<int>(x)?x:x+1.f));
00374 }
00375 inline int vil_round_ceil(double x)
00376 {
00377 return static_cast<int>(x<0.0?x:(x==static_cast<int>(x)?x:x+1.0));
00378 }
00379
00380 #endif
00381
00382
00383 #endif // vil_round_h_