28 #ifndef itkMathDetail_h
29 #define itkMathDetail_h
36 #if (defined(ITK_COMPILER_SUPPORTS_SSE2_32) || defined(ITK_COMPILER_SUPPORTS_SSE2_64)) && !defined(ITK_WRAPPING_PARSER)
37 # include <emmintrin.h>
41 #define USE_SSE2_64IMPL 0
42 #define USE_SSE2_32IMPL 0
45 #if defined(ITK_COMPILER_SUPPORTS_SSE2_32) && !defined(ITK_WRAPPING_PARSER)
46 # undef USE_SSE2_32IMPL
47 # define USE_SSE2_32IMPL 1
49 #if defined(ITK_COMPILER_SUPPORTS_SSE2_64) && !defined(ITK_WRAPPING_PARSER)
50 # undef USE_SSE2_64IMPL
51 # define USE_SSE2_64IMPL 1
57 #if defined(__GNUC__) && !defined(ITK_WRAPPING_PARSER) && \
58 (defined(__i386__) || defined(__i386) || defined(__x86_64__) || defined(__x86_64))
59 # define GCC_USE_ASM_32IMPL 1
60 # define GCC_USE_ASM_64IMPL 1
62 # define GCC_USE_ASM_32IMPL 0
63 # define GCC_USE_ASM_64IMPL 0
67 #if defined(_MSC_VER) && !defined(ITK_WRAPPING_PARSER) && !defined(_WIN64)
68 # define VC_USE_ASM_32IMPL 1
69 # define VC_USE_ASM_64IMPL 1
71 # define VC_USE_ASM_32IMPL 0
72 # define VC_USE_ASM_64IMPL 0
90 ITK_GCC_SUPPRESS_Wfloat_equal
92 template <
typename TReturn,
typename TInput>
98 x += static_cast<TInput>(0.5);
102 x -= static_cast<TInput>(0.5);
105 const auto r = static_cast<TReturn>(x);
106 return (x != static_cast<TInput>(r)) ? r : static_cast<TReturn>(2 * (r / 2));
109 template <
typename TReturn,
typename TInput>
113 x += static_cast<TInput>(0.5);
114 const auto r = static_cast<TReturn>(x);
116 : (x == static_cast<TInput>(r) ? r : r - static_cast<TReturn>(1));
119 template <
typename TReturn,
typename TInput>
123 const auto r = static_cast<TReturn>(x);
126 : (x == static_cast<TInput>(r) ? r : r - static_cast<TReturn>(1));
129 template <
typename TReturn,
typename TInput>
133 const auto r = static_cast<TReturn>(x);
143 #if USE_SSE2_32IMPL // SSE2 implementation
148 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
149 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
151 return _mm_cvtsd_si32(_mm_set_sd(x));
157 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
158 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
160 return _mm_cvtss_si32(_mm_set_ss(x));
163 #elif GCC_USE_ASM_32IMPL // GCC/clang x86 asm implementation
168 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
169 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
172 __asm__ __volatile__(
"fistpl %0" :
"=m"(r) :
"t"(x) :
"st");
179 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
180 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
183 __asm__ __volatile__(
"fistpl %0" :
"=m"(r) :
"t"(x) :
"st");
187 #elif VC_USE_ASM_32IMPL // msvc asm implementation
192 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
193 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
207 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
208 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
219 #else // Base implementation
224 return RoundHalfIntegerToEven_base<int32_t, double>(x);
229 return RoundHalfIntegerToEven_base<int32_t, float>(x);
234 #if USE_SSE2_32IMPL || GCC_USE_ASM_32IMPL || VC_USE_ASM_32IMPL
269 #else // Base implementation
274 return RoundHalfIntegerUp_base<int32_t, double>(x);
279 return RoundHalfIntegerUp_base<int32_t, float>(x);
285 return Floor_base<int32_t, double>(x);
290 return Floor_base<int32_t, float>(x);
296 return Ceil_base<int32_t, double>(x);
301 return Ceil_base<int32_t, float>(x);
304 #endif // USE_SSE2_32IMPL || GCC_USE_ASM_32IMPL || VC_USE_ASM_32IMPL
309 #if USE_SSE2_64IMPL // SSE2 implementation
314 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
315 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
317 return _mm_cvtsd_si64(_mm_set_sd(x));
323 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
324 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
326 return _mm_cvtss_si64(_mm_set_ss(x));
329 #elif GCC_USE_ASM_64IMPL // GCC/clang x86 asm implementation
334 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
335 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
338 __asm__ __volatile__(
"fistpll %0" :
"=m"(r) :
"t"(x) :
"st");
345 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
346 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
349 __asm__ __volatile__(
"fistpll %0" :
"=m"(r) :
"t"(x) :
"st");
353 #elif VC_USE_ASM_64IMPL // msvc asm implementation
358 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
359 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
373 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
374 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
385 #else // Base implementation
390 return RoundHalfIntegerToEven_base<int64_t, double>(x);
395 return RoundHalfIntegerToEven_base<int64_t, float>(x);
400 #if USE_SSE2_64IMPL || GCC_USE_ASM_64IMPL || VC_USE_ASM_64IMPL
435 #else // Base implementation
440 return RoundHalfIntegerUp_base<int64_t, double>(x);
445 return RoundHalfIntegerUp_base<int64_t, float>(x);
451 return Floor_base<int64_t, double>(x);
456 return Floor_base<int64_t, float>(x);
462 return Ceil_base<int64_t, double>(x);
467 return Ceil_base<int64_t, float>(x);
470 #endif // USE_SSE2_64IMPL || GCC_USE_ASM_64IMPL || VC_USE_ASM_64IMPL
472 template <
typename T>
489 template <
typename T>
524 template <
typename T>
535 #undef USE_SSE2_32IMPL
536 #undef GCC_USE_ASM_32IMPL
537 #undef VC_USE_ASM_32IMPL
539 #undef USE_SSE2_64IMPL
540 #undef GCC_USE_ASM_64IMPL
541 #undef VC_USE_ASM_64IMPL
543 #endif // end of itkMathDetail.h