28 #ifndef itkMathDetail_h
29 #define itkMathDetail_h
36 #if defined(ITK_HAVE_EMMINTRIN_H) && !defined(ITK_WRAPPING_PARSER)
37 # include <emmintrin.h>
41 #define USE_SSE2_64IMPL 0
42 #define USE_SSE2_32IMPL 0
46 #if defined(__APPLE__) && defined(__SSE2__) && !defined(ITK_WRAPPING_PARSER)
48 # if defined(__i386__)
49 # undef USE_SSE2_32IMPL
50 # define USE_SSE2_32IMPL 1
53 # if defined(__x86_64)
55 # undef USE_SSE2_64IMPL
56 # define USE_SSE2_64IMPL 1
59 # undef USE_SSE2_32IMPL
60 # define USE_SSE2_32IMPL 1
69 # if defined(ITK_COMPILER_SUPPORTS_SSE2_32) && !defined(ITK_WRAPPING_PARSER)
70 # undef USE_SSE2_32IMPL
71 # define USE_SSE2_32IMPL 1
73 # if defined(ITK_COMPILER_SUPPORTS_SSE2_64) && !defined(ITK_WRAPPING_PARSER)
74 # undef USE_SSE2_64IMPL
75 # define USE_SSE2_64IMPL 1
84 #if defined(__GNUC__) && (!defined(ITK_WRAPPING_PARSER)) && \
85 (defined(__i386__) || defined(__i386) || defined(__x86_64__) || defined(__x86_64))
86 # define GCC_USE_ASM_32IMPL 1
87 # define GCC_USE_ASM_64IMPL 1
89 # define GCC_USE_ASM_32IMPL 0
90 # define GCC_USE_ASM_64IMPL 0
93 #if defined(VCL_VC) && (!defined(ITK_WRAPPING_PARSER)) && !defined(_WIN64)
94 # define VC_USE_ASM_32IMPL 1
95 # define VC_USE_ASM_64IMPL 1
97 # define VC_USE_ASM_32IMPL 0
98 # define VC_USE_ASM_64IMPL 0
116 CLANG_SUPPRESS_Wfloat_equal
118 template <
typename TReturn,
typename TInput>
124 x += static_cast<TInput>(0.5);
128 x -= static_cast<TInput>(0.5);
131 const auto r = static_cast<TReturn>(x);
132 return (x != static_cast<TInput>(r)) ? r : static_cast<TReturn>(2 * (r / 2));
135 template <
typename TReturn,
typename TInput>
139 x += static_cast<TInput>(0.5);
140 const auto r = static_cast<TReturn>(x);
142 : (x == static_cast<TInput>(r) ? r : r - static_cast<TReturn>(1));
145 template <
typename TReturn,
typename TInput>
149 const auto r = static_cast<TReturn>(x);
152 : (x == static_cast<TInput>(r) ? r : r - static_cast<TReturn>(1));
155 template <
typename TReturn,
typename TInput>
159 const auto r = static_cast<TReturn>(x);
169 #if USE_SSE2_32IMPL // sse2 implementation
174 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
175 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
177 return _mm_cvtsd_si32(_mm_set_sd(x));
183 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
184 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
186 return _mm_cvtss_si32(_mm_set_ss(x));
189 #elif GCC_USE_ASM_32IMPL // gcc asm implementation
194 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
195 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
198 __asm__ __volatile__(
"fistpl %0" :
"=m"(r) :
"t"(x) :
"st");
205 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
206 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
209 __asm__ __volatile__(
"fistpl %0" :
"=m"(r) :
"t"(x) :
"st");
213 #elif VC_USE_ASM_32IMPL // msvc asm implementation
218 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
219 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
233 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
234 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
245 #else // Base implementation
250 return RoundHalfIntegerToEven_base<int32_t, double>(x);
255 return RoundHalfIntegerToEven_base<int32_t, float>(x);
260 #if USE_SSE2_32IMPL || GCC_USE_ASM_32IMPL || VC_USE_ASM_32IMPL
295 #else // Base implementation
300 return RoundHalfIntegerUp_base<int32_t, double>(x);
305 return RoundHalfIntegerUp_base<int32_t, float>(x);
311 return Floor_base<int32_t, double>(x);
316 return Floor_base<int32_t, float>(x);
322 return Ceil_base<int32_t, double>(x);
327 return Ceil_base<int32_t, float>(x);
330 #endif // USE_SSE2_32IMPL || GCC_USE_ASM_32IMPL || VC_USE_ASM_32IMPL
335 #if USE_SSE2_64IMPL // sse2 implementation
340 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
341 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
343 return _mm_cvtsd_si64(_mm_set_sd(x));
349 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
350 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
352 return _mm_cvtss_si64(_mm_set_ss(x));
355 #elif GCC_USE_ASM_64IMPL // gcc asm implementation
360 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
361 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
364 __asm__ __volatile__(
"fistpll %0" :
"=m"(r) :
"t"(x) :
"st");
371 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
372 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
375 __asm__ __volatile__(
"fistpll %0" :
"=m"(r) :
"t"(x) :
"st");
379 #elif VC_USE_ASM_64IMPL // msvc asm implementation
384 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
385 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
399 # if defined(ITK_CHECK_FPU_ROUNDING_MODE)
400 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
411 #else // Base implementation
416 return RoundHalfIntegerToEven_base<int64_t, double>(x);
421 return RoundHalfIntegerToEven_base<int64_t, float>(x);
426 #if USE_SSE2_64IMPL || GCC_USE_ASM_64IMPL || VC_USE_ASM_64IMPL
461 #else // Base implementation
466 return RoundHalfIntegerUp_base<int64_t, double>(x);
471 return RoundHalfIntegerUp_base<int64_t, float>(x);
477 return Floor_base<int64_t, double>(x);
482 return Floor_base<int64_t, float>(x);
488 return Ceil_base<int64_t, double>(x);
493 return Ceil_base<int64_t, float>(x);
496 #endif // USE_SSE2_64IMPL || GCC_USE_ASM_64IMPL || VC_USE_ASM_64IMPL
498 template <
typename T>
515 template <
typename T>
550 template <
typename T>
561 #undef USE_SSE2_32IMPL
562 #undef GCC_USE_ASM_32IMPL
563 #undef VC_USE_ASM_32IMPL
565 #undef USE_SSE2_64IMPL
566 #undef GCC_USE_ASM_64IMPL
567 #undef VC_USE_ASM_64IMPL
569 #endif // end of itkMathDetail.h