opencv on mbed

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fast_math.hpp Source File

fast_math.hpp

00001 /*M///////////////////////////////////////////////////////////////////////////////////////
00002 //
00003 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
00004 //
00005 //  By downloading, copying, installing or using the software you agree to this license.
00006 //  If you do not agree to this license, do not download, install,
00007 //  copy or use the software.
00008 //
00009 //
00010 //                          License Agreement
00011 //                For Open Source Computer Vision Library
00012 //
00013 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
00014 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
00015 // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
00016 // Copyright (C) 2015, Itseez Inc., all rights reserved.
00017 // Third party copyrights are property of their respective owners.
00018 //
00019 // Redistribution and use in source and binary forms, with or without modification,
00020 // are permitted provided that the following conditions are met:
00021 //
00022 //   * Redistribution's of source code must retain the above copyright notice,
00023 //     this list of conditions and the following disclaimer.
00024 //
00025 //   * Redistribution's in binary form must reproduce the above copyright notice,
00026 //     this list of conditions and the following disclaimer in the documentation
00027 //     and/or other materials provided with the distribution.
00028 //
00029 //   * The name of the copyright holders may not be used to endorse or promote products
00030 //     derived from this software without specific prior written permission.
00031 //
00032 // This software is provided by the copyright holders and contributors "as is" and
00033 // any express or implied warranties, including, but not limited to, the implied
00034 // warranties of merchantability and fitness for a particular purpose are disclaimed.
00035 // In no event shall the Intel Corporation or contributors be liable for any direct,
00036 // indirect, incidental, special, exemplary, or consequential damages
00037 // (including, but not limited to, procurement of substitute goods or services;
00038 // loss of use, data, or profits; or business interruption) however caused
00039 // and on any theory of liability, whether in contract, strict liability,
00040 // or tort (including negligence or otherwise) arising in any way out of
00041 // the use of this software, even if advised of the possibility of such damage.
00042 //
00043 //M*/
00044 
00045 #ifndef __OPENCV_CORE_FAST_MATH_HPP__
00046 #define __OPENCV_CORE_FAST_MATH_HPP__
00047 
00048 #include "opencv2/core/cvdef.h"
00049 
00050 //! @addtogroup core_utils
00051 //! @{
00052 
00053 /****************************************************************************************\
00054 *                                      fast math                                         *
00055 \****************************************************************************************/
00056 
00057 #if defined __BORLANDC__
00058 #  include <fastmath.h>
00059 #elif defined __cplusplus
00060 #  include <cmath>
00061 #else
00062 #  include <math.h>
00063 #endif
00064 
00065 #ifdef HAVE_TEGRA_OPTIMIZATION
00066 #  include "tegra_round.hpp"
00067 #endif
00068 
00069 #if CV_VFP
00070     // 1. general scheme
00071     #define ARM_ROUND(_value, _asm_string) \
00072         int res; \
00073         float temp; \
00074         asm(_asm_string : [res] "=r" (res), [temp] "=w" (temp) : [value] "w" (_value)); \
00075         return res
00076     // 2. version for double
00077     #ifdef __clang__
00078         #define ARM_ROUND_DBL(value) ARM_ROUND(value, "vcvtr.s32.f64 %[temp], %[value] \n vmov %[res], %[temp]")
00079     #else
00080         #define ARM_ROUND_DBL(value) ARM_ROUND(value, "vcvtr.s32.f64 %[temp], %P[value] \n vmov %[res], %[temp]")
00081     #endif
00082     // 3. version for float
00083     #define ARM_ROUND_FLT(value) ARM_ROUND(value, "vcvtr.s32.f32 %[temp], %[value]\n vmov %[res], %[temp]")
00084 #endif // CV_VFP
00085 
00086 /** @brief Rounds floating-point number to the nearest integer
00087 
00088  @param value floating-point number. If the value is outside of INT_MIN ... INT_MAX range, the
00089  result is not defined.
00090  */
00091 CV_INLINE int
00092 cvRound( double value )
00093 {
00094 #if ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ \
00095     && defined __SSE2__ && !defined __APPLE__)) && !defined(__CUDACC__)
00096     __m128d t = _mm_set_sd( value );
00097     return _mm_cvtsd_si32(t);
00098 #elif defined _MSC_VER && defined _M_IX86
00099     int t;
00100     __asm
00101     {
00102         fld value;
00103         fistp t;
00104     }
00105     return t;
00106 #elif ((defined _MSC_VER && defined _M_ARM) || defined CV_ICC || \
00107         defined __GNUC__) && defined HAVE_TEGRA_OPTIMIZATION
00108     TEGRA_ROUND_DBL(value);
00109 #elif defined CV_ICC || defined __GNUC__
00110 # if CV_VFP
00111     ARM_ROUND_DBL(value);
00112 # else
00113     return (int)lrint(value);
00114 # endif
00115 #else
00116     /* it's ok if round does not comply with IEEE754 standard;
00117        the tests should allow +/-1 difference when the tested functions use round */
00118     return (int)(value + (value >= 0 ? 0.5 : -0.5));
00119 #endif
00120 }
00121 
00122 
00123 /** @brief Rounds floating-point number to the nearest integer not larger than the original.
00124 
00125  The function computes an integer i such that:
00126  \f[i \le \texttt{value} < i+1\f]
00127  @param value floating-point number. If the value is outside of INT_MIN ... INT_MAX range, the
00128  result is not defined.
00129  */
00130 CV_INLINE int cvFloor( double value )
00131 {
00132 #if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__ && !defined __APPLE__)) && !defined(__CUDACC__)
00133     __m128d t = _mm_set_sd( value );
00134     int i = _mm_cvtsd_si32(t);
00135     return i - _mm_movemask_pd(_mm_cmplt_sd(t, _mm_cvtsi32_sd(t,i)));
00136 #elif defined __GNUC__
00137     int i = (int)value;
00138     return i - (i > value);
00139 #else
00140     int i = cvRound(value);
00141     float diff = (float)(value - i);
00142     return i - (diff < 0);
00143 #endif
00144 }
00145 
00146 /** @brief Rounds floating-point number to the nearest integer not smaller than the original.
00147 
00148  The function computes an integer i such that:
00149  \f[i \le \texttt{value} < i+1\f]
00150  @param value floating-point number. If the value is outside of INT_MIN ... INT_MAX range, the
00151  result is not defined.
00152  */
00153 CV_INLINE int cvCeil( double value )
00154 {
00155 #if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__&& !defined __APPLE__)) && !defined(__CUDACC__)
00156     __m128d t = _mm_set_sd( value );
00157     int i = _mm_cvtsd_si32(t);
00158     return i + _mm_movemask_pd(_mm_cmplt_sd(_mm_cvtsi32_sd(t,i), t));
00159 #elif defined __GNUC__
00160     int i = (int)value;
00161     return i + (i < value);
00162 #else
00163     int i = cvRound(value);
00164     float diff = (float)(i - value);
00165     return i + (diff < 0);
00166 #endif
00167 }
00168 
00169 /** @brief Determines if the argument is Not A Number.
00170 
00171  @param value The input floating-point value
00172 
00173  The function returns 1 if the argument is Not A Number (as defined by IEEE754 standard), 0
00174  otherwise. */
00175 CV_INLINE int cvIsNaN( double value )
00176 {
00177     Cv64suf ieee754;
00178     ieee754.f = value;
00179     return ((unsigned)(ieee754.u >> 32) & 0x7fffffff) +
00180            ((unsigned)ieee754.u != 0) > 0x7ff00000;
00181 }
00182 
00183 /** @brief Determines if the argument is Infinity.
00184 
00185  @param value The input floating-point value
00186 
00187  The function returns 1 if the argument is a plus or minus infinity (as defined by IEEE754 standard)
00188  and 0 otherwise. */
00189 CV_INLINE int cvIsInf( double value )
00190 {
00191     Cv64suf ieee754;
00192     ieee754.f = value;
00193     return ((unsigned)(ieee754.u >> 32) & 0x7fffffff) == 0x7ff00000 &&
00194             (unsigned)ieee754.u == 0;
00195 }
00196 
00197 #ifdef __cplusplus
00198 
00199 /** @overload */
00200 CV_INLINE int cvRound(float value)
00201 {
00202 #if ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ && \
00203       defined __SSE2__ && !defined __APPLE__)) && !defined(__CUDACC__)
00204     __m128 t = _mm_set_ss( value );
00205     return _mm_cvtss_si32(t);
00206 #elif defined _MSC_VER && defined _M_IX86
00207     int t;
00208     __asm
00209     {
00210         fld value;
00211         fistp t;
00212     }
00213     return t;
00214 #elif ((defined _MSC_VER && defined _M_ARM) || defined CV_ICC || \
00215         defined __GNUC__) && defined HAVE_TEGRA_OPTIMIZATION
00216     TEGRA_ROUND_FLT(value);
00217 #elif defined CV_ICC || defined __GNUC__
00218 # if CV_VFP
00219     ARM_ROUND_FLT(value);
00220 # else
00221     return (int)::lrintf(value);
00222 # endif
00223 #else
00224     /* it's ok if round does not comply with IEEE754 standard;
00225      the tests should allow +/-1 difference when the tested functions use round */
00226     return (int)(value + (value >= 0 ? 0.5f : -0.5f));
00227 #endif
00228 }
00229 
00230 /** @overload */
00231 CV_INLINE int cvRound( int value )
00232 {
00233     return value;
00234 }
00235 
00236 /** @overload */
00237 CV_INLINE int cvFloor( float value )
00238 {
00239 #if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__ && !defined __APPLE__)) && !defined(__CUDACC__)
00240     __m128 t = _mm_set_ss( value );
00241     int i = _mm_cvtss_si32(t);
00242     return i - _mm_movemask_ps(_mm_cmplt_ss(t, _mm_cvtsi32_ss(t,i)));
00243 #elif defined __GNUC__
00244     int i = (int)value;
00245     return i - (i > value);
00246 #else
00247     int i = cvRound(value);
00248     float diff = (float)(value - i);
00249     return i - (diff < 0);
00250 #endif
00251 }
00252 
00253 /** @overload */
00254 CV_INLINE int cvFloor( int value )
00255 {
00256     return value;
00257 }
00258 
00259 /** @overload */
00260 CV_INLINE int cvCeil( float value )
00261 {
00262 #if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__&& !defined __APPLE__)) && !defined(__CUDACC__)
00263     __m128 t = _mm_set_ss( value );
00264     int i = _mm_cvtss_si32(t);
00265     return i + _mm_movemask_ps(_mm_cmplt_ss(_mm_cvtsi32_ss(t,i), t));
00266 #elif defined __GNUC__
00267     int i = (int)value;
00268     return i + (i < value);
00269 #else
00270     int i = cvRound(value);
00271     float diff = (float)(i - value);
00272     return i + (diff < 0);
00273 #endif
00274 }
00275 
00276 /** @overload */
00277 CV_INLINE int cvCeil( int value )
00278 {
00279     return value;
00280 }
00281 
00282 /** @overload */
00283 CV_INLINE int cvIsNaN( float value )
00284 {
00285     Cv32suf ieee754;
00286     ieee754.f = value;
00287     return (ieee754.u & 0x7fffffff) > 0x7f800000;
00288 }
00289 
00290 /** @overload */
00291 CV_INLINE int cvIsInf( float value )
00292 {
00293     Cv32suf ieee754;
00294     ieee754.f = value;
00295     return (ieee754.u & 0x7fffffff) == 0x7f800000;
00296 }
00297 
00298 #endif // __cplusplus
00299 
00300 //! @} core_utils
00301 
00302 #endif
00303