28 #ifndef __itkMathDetail_h
29 #define __itkMathDetail_h
31 #include "vnl/vnl_math.h"
35 #ifdef ITK_HAVE_FENV_H
42 #ifdef ITK_HAVE_EMMINTRIN_H
43 #include <emmintrin.h>
47 #define USE_SSE2_64IMPL 0
48 #define USE_SSE2_32IMPL 0
52 #if defined(__APPLE__) && defined( __SSE2__ )
54 # if defined( __i386__ )
55 # undef USE_SSE2_32IMPL
56 # define USE_SSE2_32IMPL 1
59 # if defined( __x86_64 )
61 # undef USE_SSE2_64IMPL
62 # define USE_SSE2_64IMPL 1
65 # undef USE_SSE2_32IMPL
66 # define USE_SSE2_32IMPL 1
75 # if defined(ITK_COMPILER_SUPPORTS_SSE2_32) && !defined( __GCCXML__ )
76 # undef USE_SSE2_32IMPL
77 # define USE_SSE2_32IMPL 1
79 # if defined(ITK_COMPILER_SUPPORTS_SSE2_64) && !defined( __GCCXML__ )
80 # undef USE_SSE2_64IMPL
81 # define USE_SSE2_64IMPL 1
90 #if defined( __GNUC__ ) && ( !defined( __GCCXML__ ) ) && ( defined( __i386__ ) || defined( __i386 ) \
91 || defined( __x86_64__ ) || defined( __x86_64 ) )
92 #define GCC_USE_ASM_32IMPL 1
93 #define GCC_USE_ASM_64IMPL 1
95 #define GCC_USE_ASM_32IMPL 0
96 #define GCC_USE_ASM_64IMPL 0
99 #if defined( VCL_VC ) && ( !defined( __GCCXML__ ) ) && !defined( _WIN64 )
100 #define VC_USE_ASM_32IMPL 1
101 #define VC_USE_ASM_64IMPL 1
103 #define VC_USE_ASM_32IMPL 0
104 #define VC_USE_ASM_64IMPL 0
121 template<
typename TReturn,
typename TInput >
126 x +=
static_cast< TInput
>( 0.5 );
130 x -=
static_cast< TInput
>( 0.5 );
133 const TReturn r =
static_cast< TReturn
>( x );
134 return ( x != static_cast< TInput >( r ) ) ? r : static_cast< TReturn >( 2 * ( r / 2 ) );
137 template<
typename TReturn,
typename TInput >
140 x +=
static_cast< TInput
>( 0.5 );
141 const TReturn r =
static_cast< TReturn
>( x );
144 ( x == static_cast< TInput >( r ) ? r : r -
static_cast< TReturn
>( 1 ) );
147 template<
typename TReturn,
typename TInput >
150 const TReturn r =
static_cast< TReturn
>( x );
154 ( x == static_cast< TInput >( r ) ? r : r -
static_cast< TReturn
>( 1 ) );
157 template<
typename TReturn,
typename TInput >
160 const TReturn r =
static_cast< TReturn
>( x );
164 ( x == static_cast< TInput >( r ) ? r : r +
static_cast< TReturn
>( 1 ) );
170 #if USE_SSE2_32IMPL // sse2 implementation
174 #if defined( ITK_CHECK_FPU_ROUNDING_MODE ) && defined( HAVE_FENV_H )
175 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
177 return _mm_cvtsd_si32( _mm_set_sd(x) );
182 #if defined( ITK_CHECK_FPU_ROUNDING_MODE ) && defined( HAVE_FENV_H )
183 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
185 return _mm_cvtss_si32( _mm_set_ss(x) );
188 #elif GCC_USE_ASM_32IMPL // gcc asm implementation
192 #if defined( ITK_CHECK_FPU_ROUNDING_MODE ) && defined( HAVE_FENV_H )
193 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
196 __asm__ __volatile__ (
"fistpl %0" :
"=m" ( r ) :
"t" ( x ) :
"st" );
202 #if defined( ITK_CHECK_FPU_ROUNDING_MODE ) && defined( HAVE_FENV_H )
203 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
206 __asm__ __volatile__ (
"fistpl %0" :
"=m" ( r ) :
"t" ( x ) :
"st" );
210 #elif VC_USE_ASM_32IMPL // msvc asm implementation
214 #if defined( ITK_CHECK_FPU_ROUNDING_MODE ) && defined( HAVE_FENV_H )
215 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
228 #if defined( ITK_CHECK_FPU_ROUNDING_MODE ) && defined( HAVE_FENV_H )
229 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
240 #else // Base implementation
247 #if USE_SSE2_32IMPL || GCC_USE_ASM_32IMPL || VC_USE_ASM_32IMPL
258 #else // Base implementation
269 #endif // USE_SSE2_32IMPL || GCC_USE_ASM_32IMPL || VC_USE_ASM_32IMPL
274 #if USE_SSE2_64IMPL // sse2 implementation
278 #if defined( ITK_CHECK_FPU_ROUNDING_MODE ) && defined( HAVE_FENV_H )
279 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
281 return _mm_cvtsd_si64( _mm_set_sd(x) );
286 #if defined( ITK_CHECK_FPU_ROUNDING_MODE ) && defined( HAVE_FENV_H )
287 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
289 return _mm_cvtss_si64( _mm_set_ss(x) );
292 #elif GCC_USE_ASM_64IMPL // gcc asm implementation
296 #if defined( ITK_CHECK_FPU_ROUNDING_MODE ) && defined( HAVE_FENV_H )
297 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
300 __asm__ __volatile__ (
"fistpll %0" :
"=m" ( r ) :
"t" ( x ) :
"st" );
306 #if defined( ITK_CHECK_FPU_ROUNDING_MODE ) && defined( HAVE_FENV_H )
307 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
310 __asm__ __volatile__ (
"fistpll %0" :
"=m" ( r ) :
"t" ( x ) :
"st" );
314 #elif VC_USE_ASM_64IMPL // msvc asm implementation
318 #if defined( ITK_CHECK_FPU_ROUNDING_MODE ) && defined( HAVE_FENV_H )
319 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
332 #if defined( ITK_CHECK_FPU_ROUNDING_MODE ) && defined( HAVE_FENV_H )
333 itkAssertInDebugAndIgnoreInReleaseMacro(fegetround() == FE_TONEAREST);
344 #else // Base implementation
351 #if USE_SSE2_64IMPL || GCC_USE_ASM_64IMPL || VC_USE_ASM_64IMPL
362 #else // Base implementation
373 #endif // USE_SSE2_64IMPL || GCC_USE_ASM_64IMPL || VC_USE_ASM_64IMPL
375 template <
typename T>
376 struct FloatIEEETraits;
379 struct FloatIEEETraits<float>
386 struct FloatIEEETraits<double>
392 template <
typename T>
396 typedef typename FloatIEEETraits<T>::IntType
IntType;
397 typedef typename FloatIEEETraits<T>::UIntType
UIntType;
420 template<
typename T >
421 struct FloatOrDouble;
423 struct FloatOrDouble< float > {};
425 struct FloatOrDouble< double > {};
429 #undef USE_SSE2_32IMPL
430 #undef GCC_USE_ASM_32IMPL
431 #undef VC_USE_ASM_32IMPL
433 #undef USE_SSE2_64IMPL
434 #undef GCC_USE_ASM_64IMPL
435 #undef VC_USE_ASM_64IMPL
437 #endif // end of itkMathDetail.h