@ -1,3 +1,4 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
@ -48,6 +49,8 @@
# define _CRT_SECURE_NO_DEPRECATE /* to avoid multiple Visual Studio warnings */
# endif
# include <limits.h>
# if defined __ICL
# define CV_ICC __ICL
# elif defined __ICC
@ -60,12 +63,30 @@
# define CV_ICC __INTEL_COMPILER
# endif
# ifndef CV_INLINE
# if defined __cplusplus
# define CV_INLINE static inline
# elif defined _MSC_VER
# define CV_INLINE __inline
# else
# define CV_INLINE static
# endif
# endif
# if defined CV_ICC && !defined CV_ENABLE_UNROLLED
# define CV_ENABLE_UNROLLED 0
# else
# define CV_ENABLE_UNROLLED 1
# endif
# ifdef __GNUC__
# define CV_DECL_ALIGNED(x) __attribute__ ((aligned (x)))
# elif defined _MSC_VER
# define CV_DECL_ALIGNED(x) __declspec(align(x))
# else
# define CV_DECL_ALIGNED(x)
# endif
/* CPU features and intrinsics support */
# define CV_CPU_NONE 0
# define CV_CPU_MMX 1
@ -99,7 +120,7 @@
// do not include SSE/AVX/NEON headers for NVCC compiler
# ifndef __CUDACC__
# if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2)
# if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2)
# include <emmintrin.h>
# define CV_MMX 1
# define CV_SSE 1
@ -281,4 +302,372 @@ typedef signed char schar;
# define CV_2PI 6.283185307179586476925286766559
# define CV_LOG2 0.69314718055994530941723212145818
typedef union Cv32suf
{
int i ;
unsigned u ;
float f ;
}
Cv32suf ;
typedef union Cv64suf
{
int64 i ;
uint64 u ;
double f ;
}
Cv64suf ;
/****************************************************************************************\
* fast math *
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if defined __BORLANDC__
# include <fastmath.h>
# elif defined __cplusplus
# include <cmath>
# else
# include <math.h>
# endif
# ifdef HAVE_TEGRA_OPTIMIZATION
# include "tegra_round.hpp"
# endif
//! @addtogroup core_utils
//! @{
# if CV_VFP
// 1. general scheme
# define ARM_ROUND(_value, _asm_string) \
int res ; \
float temp ; \
asm ( _asm_string : [ res ] " =r " ( res ) , [ temp ] " =w " ( temp ) : [ value ] " w " ( _value ) ) ; \
return res
// 2. version for double
# ifdef __clang__
# define ARM_ROUND_DBL(value) ARM_ROUND(value, "vcvtr.s32.f64 %[temp], %[value] \n vmov %[res], %[temp]")
# else
# define ARM_ROUND_DBL(value) ARM_ROUND(value, "vcvtr.s32.f64 %[temp], %P[value] \n vmov %[res], %[temp]")
# endif
// 3. version for float
# define ARM_ROUND_FLT(value) ARM_ROUND(value, "vcvtr.s32.f32 %[temp], %[value]\n vmov %[res], %[temp]")
# endif // CV_VFP
/** @brief Rounds floating-point number to the nearest integer
@ param value floating - point number . If the value is outside of INT_MIN . . . INT_MAX range , the
result is not defined .
*/
CV_INLINE int
cvRound ( double value )
{
# if ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ \
& & defined __SSE2__ & & ! defined __APPLE__ ) ) & & ! defined ( __CUDACC__ )
__m128d t = _mm_set_sd ( value ) ;
return _mm_cvtsd_si32 ( t ) ;
# elif defined _MSC_VER && defined _M_IX86
int t ;
__asm
{
fld value ;
fistp t ;
}
return t ;
# elif ((defined _MSC_VER && defined _M_ARM) || defined CV_ICC || \
defined __GNUC__ ) & & defined HAVE_TEGRA_OPTIMIZATION
TEGRA_ROUND_DBL ( value ) ;
# elif defined CV_ICC || defined __GNUC__
# if CV_VFP
ARM_ROUND_DBL ( value )
# else
return ( int ) lrint ( value ) ;
# endif
# else
/* it's ok if round does not comply with IEEE754 standard;
the tests should allow + / - 1 difference when the tested functions use round */
return ( int ) ( value + ( value > = 0 ? 0.5 : - 0.5 ) ) ;
# endif
}
/** @brief Rounds floating-point number to the nearest integer not larger than the original.
The function computes an integer i such that :
\ f [ i \ le \ texttt { value } < i + 1 \ f ]
@ param value floating - point number . If the value is outside of INT_MIN . . . INT_MAX range , the
result is not defined .
*/
CV_INLINE int cvFloor ( double value )
{
# if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__ && !defined __APPLE__)) && !defined(__CUDACC__)
__m128d t = _mm_set_sd ( value ) ;
int i = _mm_cvtsd_si32 ( t ) ;
return i - _mm_movemask_pd ( _mm_cmplt_sd ( t , _mm_cvtsi32_sd ( t , i ) ) ) ;
# elif defined __GNUC__
int i = ( int ) value ;
return i - ( i > value ) ;
# else
int i = cvRound ( value ) ;
float diff = ( float ) ( value - i ) ;
return i - ( diff < 0 ) ;
# endif
}
/** @brief Rounds floating-point number to the nearest integer not larger than the original.
The function computes an integer i such that :
\ f [ i \ le \ texttt { value } < i + 1 \ f ]
@ param value floating - point number . If the value is outside of INT_MIN . . . INT_MAX range , the
result is not defined .
*/
CV_INLINE int cvCeil ( double value )
{
# if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__&& !defined __APPLE__)) && !defined(__CUDACC__)
__m128d t = _mm_set_sd ( value ) ;
int i = _mm_cvtsd_si32 ( t ) ;
return i + _mm_movemask_pd ( _mm_cmplt_sd ( _mm_cvtsi32_sd ( t , i ) , t ) ) ;
# elif defined __GNUC__
int i = ( int ) value ;
return i + ( i < value ) ;
# else
int i = cvRound ( value ) ;
float diff = ( float ) ( i - value ) ;
return i + ( diff < 0 ) ;
# endif
}
/** @brief Determines if the argument is Not A Number.
@ param value The input floating - point value
The function returns 1 if the argument is Not A Number ( as defined by IEEE754 standard ) , 0
otherwise . */
CV_INLINE int cvIsNaN ( double value )
{
Cv64suf ieee754 ;
ieee754 . f = value ;
return ( ( unsigned ) ( ieee754 . u > > 32 ) & 0x7fffffff ) +
( ( unsigned ) ieee754 . u ! = 0 ) > 0x7ff00000 ;
}
/** @brief Determines if the argument is Infinity.
@ param value The input floating - point value
The function returns 1 if the argument is a plus or minus infinity ( as defined by IEEE754 standard )
and 0 otherwise . */
CV_INLINE int cvIsInf ( double value )
{
Cv64suf ieee754 ;
ieee754 . f = value ;
return ( ( unsigned ) ( ieee754 . u > > 32 ) & 0x7fffffff ) = = 0x7ff00000 & &
( unsigned ) ieee754 . u = = 0 ;
}
# ifdef __cplusplus
/** @overload */
CV_INLINE int cvRound ( float value )
{
# if ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ && \
defined __SSE2__ & & ! defined __APPLE__ ) ) & & ! defined ( __CUDACC__ )
__m128 t = _mm_set_ss ( value ) ;
return _mm_cvtss_si32 ( t ) ;
# elif defined _MSC_VER && defined _M_IX86
int t ;
__asm
{
fld value ;
fistp t ;
}
return t ;
# elif ((defined _MSC_VER && defined _M_ARM) || defined CV_ICC || \
defined __GNUC__ ) & & defined HAVE_TEGRA_OPTIMIZATION
TEGRA_ROUND_FLT ( value ) ;
# elif defined CV_ICC || defined __GNUC__
# if CV_VFP
ARM_ROUND_FLT ( value )
# else
return ( int ) lrintf ( value ) ;
# endif
# else
/* it's ok if round does not comply with IEEE754 standard;
the tests should allow + / - 1 difference when the tested functions use round */
return ( int ) ( value + ( value > = 0 ? 0.5f : - 0.5f ) ) ;
# endif
}
/** @overload */
CV_INLINE int cvRound ( int value )
{
return value ;
}
/** @overload */
CV_INLINE int cvFloor ( float value )
{
# if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__ && !defined __APPLE__)) && !defined(__CUDACC__)
__m128 t = _mm_set_ss ( value ) ;
int i = _mm_cvtss_si32 ( t ) ;
return i - _mm_movemask_ps ( _mm_cmplt_ss ( t , _mm_cvtsi32_ss ( t , i ) ) ) ;
# elif defined __GNUC__
int i = ( int ) value ;
return i - ( i > value ) ;
# else
int i = cvRound ( value ) ;
float diff = ( float ) ( value - i ) ;
return i - ( diff < 0 ) ;
# endif
}
/** @overload */
CV_INLINE int cvFloor ( int value )
{
return value ;
}
/** @overload */
CV_INLINE int cvCeil ( float value )
{
# if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__&& !defined __APPLE__)) && !defined(__CUDACC__)
__m128 t = _mm_set_ss ( value ) ;
int i = _mm_cvtss_si32 ( t ) ;
return i + _mm_movemask_ps ( _mm_cmplt_ss ( _mm_cvtsi32_ss ( t , i ) , t ) ) ;
# elif defined __GNUC__
int i = ( int ) value ;
return i + ( i < value ) ;
# else
int i = cvRound ( value ) ;
float diff = ( float ) ( i - value ) ;
return i + ( diff < 0 ) ;
# endif
}
/** @overload */
CV_INLINE int cvCeil ( int value )
{
return value ;
}
/** @overload */
CV_INLINE int cvIsNaN ( float value )
{
Cv32suf ieee754 ;
ieee754 . f = value ;
return ( ieee754 . u & 0x7fffffff ) > 0x7f800000 ;
}
/** @overload */
CV_INLINE int cvIsInf ( float value )
{
Cv32suf ieee754 ;
ieee754 . f = value ;
return ( ieee754 . u & 0x7fffffff ) = = 0x7f800000 ;
}
# include <algorithm>
namespace cv
{
/////////////// saturate_cast (used in image & signal processing) ///////////////////
/**
Template function for accurate conversion from one primitive type to another .
The functions saturate_cast resemble the standard C + + cast operations , such as static_cast \ < T \ > ( )
and others . They perform an efficient and accurate conversion from one primitive type to another
( see the introduction chapter ) . saturate in the name means that when the input value v is out of the
range of the target type , the result is not formed just by taking low bits of the input , but instead
the value is clipped . For example :
@ code
uchar a = saturate_cast < uchar > ( - 100 ) ; // a = 0 (UCHAR_MIN)
short b = saturate_cast < short > ( 33333.33333 ) ; // b = 32767 (SHRT_MAX)
@ endcode
Such clipping is done when the target type is unsigned char , signed char , unsigned short or
signed short . For 32 - bit integers , no clipping is done .
When the parameter is a floating - point value and the target type is an integer ( 8 - , 16 - or 32 - bit ) ,
the floating - point value is first rounded to the nearest integer and then clipped if needed ( when
the target type is 8 - or 16 - bit ) .
This operation is used in the simplest or most complex image processing functions in OpenCV .
@ param v Function parameter .
@ sa add , subtract , multiply , divide , Mat : : convertTo
*/
template < typename _Tp > static inline _Tp saturate_cast ( uchar v ) { return _Tp ( v ) ; }
/** @overload */
template < typename _Tp > static inline _Tp saturate_cast ( schar v ) { return _Tp ( v ) ; }
/** @overload */
template < typename _Tp > static inline _Tp saturate_cast ( ushort v ) { return _Tp ( v ) ; }
/** @overload */
template < typename _Tp > static inline _Tp saturate_cast ( short v ) { return _Tp ( v ) ; }
/** @overload */
template < typename _Tp > static inline _Tp saturate_cast ( unsigned v ) { return _Tp ( v ) ; }
/** @overload */
template < typename _Tp > static inline _Tp saturate_cast ( int v ) { return _Tp ( v ) ; }
/** @overload */
template < typename _Tp > static inline _Tp saturate_cast ( float v ) { return _Tp ( v ) ; }
/** @overload */
template < typename _Tp > static inline _Tp saturate_cast ( double v ) { return _Tp ( v ) ; }
/** @overload */
template < typename _Tp > static inline _Tp saturate_cast ( int64 v ) { return _Tp ( v ) ; }
/** @overload */
template < typename _Tp > static inline _Tp saturate_cast ( uint64 v ) { return _Tp ( v ) ; }
//! @cond IGNORED
template < > inline uchar saturate_cast < uchar > ( schar v ) { return ( uchar ) std : : max ( ( int ) v , 0 ) ; }
template < > inline uchar saturate_cast < uchar > ( ushort v ) { return ( uchar ) std : : min ( ( unsigned ) v , ( unsigned ) UCHAR_MAX ) ; }
template < > inline uchar saturate_cast < uchar > ( int v ) { return ( uchar ) ( ( unsigned ) v < = UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0 ) ; }
template < > inline uchar saturate_cast < uchar > ( short v ) { return saturate_cast < uchar > ( ( int ) v ) ; }
template < > inline uchar saturate_cast < uchar > ( unsigned v ) { return ( uchar ) std : : min ( v , ( unsigned ) UCHAR_MAX ) ; }
template < > inline uchar saturate_cast < uchar > ( float v ) { int iv = cvRound ( v ) ; return saturate_cast < uchar > ( iv ) ; }
template < > inline uchar saturate_cast < uchar > ( double v ) { int iv = cvRound ( v ) ; return saturate_cast < uchar > ( iv ) ; }
template < > inline uchar saturate_cast < uchar > ( int64 v ) { return ( uchar ) ( ( uint64 ) v < = ( uint64 ) UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0 ) ; }
template < > inline uchar saturate_cast < uchar > ( uint64 v ) { return ( uchar ) std : : min ( v , ( uint64 ) UCHAR_MAX ) ; }
template < > inline schar saturate_cast < schar > ( uchar v ) { return ( schar ) std : : min ( ( int ) v , SCHAR_MAX ) ; }
template < > inline schar saturate_cast < schar > ( ushort v ) { return ( schar ) std : : min ( ( unsigned ) v , ( unsigned ) SCHAR_MAX ) ; }
template < > inline schar saturate_cast < schar > ( int v ) { return ( schar ) ( ( unsigned ) ( v - SCHAR_MIN ) < = ( unsigned ) UCHAR_MAX ? v : v > 0 ? SCHAR_MAX : SCHAR_MIN ) ; }
template < > inline schar saturate_cast < schar > ( short v ) { return saturate_cast < schar > ( ( int ) v ) ; }
template < > inline schar saturate_cast < schar > ( unsigned v ) { return ( schar ) std : : min ( v , ( unsigned ) SCHAR_MAX ) ; }
template < > inline schar saturate_cast < schar > ( float v ) { int iv = cvRound ( v ) ; return saturate_cast < schar > ( iv ) ; }
template < > inline schar saturate_cast < schar > ( double v ) { int iv = cvRound ( v ) ; return saturate_cast < schar > ( iv ) ; }
template < > inline schar saturate_cast < schar > ( int64 v ) { return ( schar ) ( ( uint64 ) ( ( int64 ) v - SCHAR_MIN ) < = ( uint64 ) UCHAR_MAX ? v : v > 0 ? SCHAR_MAX : SCHAR_MIN ) ; }
template < > inline schar saturate_cast < schar > ( uint64 v ) { return ( schar ) std : : min ( v , ( uint64 ) SCHAR_MAX ) ; }
template < > inline ushort saturate_cast < ushort > ( schar v ) { return ( ushort ) std : : max ( ( int ) v , 0 ) ; }
template < > inline ushort saturate_cast < ushort > ( short v ) { return ( ushort ) std : : max ( ( int ) v , 0 ) ; }
template < > inline ushort saturate_cast < ushort > ( int v ) { return ( ushort ) ( ( unsigned ) v < = ( unsigned ) USHRT_MAX ? v : v > 0 ? USHRT_MAX : 0 ) ; }
template < > inline ushort saturate_cast < ushort > ( unsigned v ) { return ( ushort ) std : : min ( v , ( unsigned ) USHRT_MAX ) ; }
template < > inline ushort saturate_cast < ushort > ( float v ) { int iv = cvRound ( v ) ; return saturate_cast < ushort > ( iv ) ; }
template < > inline ushort saturate_cast < ushort > ( double v ) { int iv = cvRound ( v ) ; return saturate_cast < ushort > ( iv ) ; }
template < > inline ushort saturate_cast < ushort > ( int64 v ) { return ( ushort ) ( ( uint64 ) v < = ( uint64 ) USHRT_MAX ? v : v > 0 ? USHRT_MAX : 0 ) ; }
template < > inline ushort saturate_cast < ushort > ( uint64 v ) { return ( ushort ) std : : min ( v , ( uint64 ) USHRT_MAX ) ; }
template < > inline short saturate_cast < short > ( ushort v ) { return ( short ) std : : min ( ( int ) v , SHRT_MAX ) ; }
template < > inline short saturate_cast < short > ( int v ) { return ( short ) ( ( unsigned ) ( v - SHRT_MIN ) < = ( unsigned ) USHRT_MAX ? v : v > 0 ? SHRT_MAX : SHRT_MIN ) ; }
template < > inline short saturate_cast < short > ( unsigned v ) { return ( short ) std : : min ( v , ( unsigned ) SHRT_MAX ) ; }
template < > inline short saturate_cast < short > ( float v ) { int iv = cvRound ( v ) ; return saturate_cast < short > ( iv ) ; }
template < > inline short saturate_cast < short > ( double v ) { int iv = cvRound ( v ) ; return saturate_cast < short > ( iv ) ; }
template < > inline short saturate_cast < short > ( int64 v ) { return ( short ) ( ( uint64 ) ( ( int64 ) v - SHRT_MIN ) < = ( uint64 ) USHRT_MAX ? v : v > 0 ? SHRT_MAX : SHRT_MIN ) ; }
template < > inline short saturate_cast < short > ( uint64 v ) { return ( short ) std : : min ( v , ( uint64 ) SHRT_MAX ) ; }
template < > inline int saturate_cast < int > ( float v ) { return cvRound ( v ) ; }
template < > inline int saturate_cast < int > ( double v ) { return cvRound ( v ) ; }
// we intentionally do not clip negative numbers, to make -1 become 0xffffffff etc.
template < > inline unsigned saturate_cast < unsigned > ( float v ) { return cvRound ( v ) ; }
template < > inline unsigned saturate_cast < unsigned > ( double v ) { return cvRound ( v ) ; }
//! @endcond
}
# endif // __cplusplus
# endif //__OPENCV_HAL_H__