next: drop HAVE_TEGRA_OPTIMIZATION/TADP
[platform/upstream/opencv.git] / modules / core / include / opencv2 / core / fast_math.hpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                          License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
16 // Copyright (C) 2015, Itseez Inc., all rights reserved.
17 // Third party copyrights are property of their respective owners.
18 //
19 // Redistribution and use in source and binary forms, with or without modification,
20 // are permitted provided that the following conditions are met:
21 //
22 //   * Redistribution's of source code must retain the above copyright notice,
23 //     this list of conditions and the following disclaimer.
24 //
25 //   * Redistribution's in binary form must reproduce the above copyright notice,
26 //     this list of conditions and the following disclaimer in the documentation
27 //     and/or other materials provided with the distribution.
28 //
29 //   * The name of the copyright holders may not be used to endorse or promote products
30 //     derived from this software without specific prior written permission.
31 //
32 // This software is provided by the copyright holders and contributors "as is" and
33 // any express or implied warranties, including, but not limited to, the implied
34 // warranties of merchantability and fitness for a particular purpose are disclaimed.
35 // In no event shall the Intel Corporation or contributors be liable for any direct,
36 // indirect, incidental, special, exemplary, or consequential damages
37 // (including, but not limited to, procurement of substitute goods or services;
38 // loss of use, data, or profits; or business interruption) however caused
39 // and on any theory of liability, whether in contract, strict liability,
40 // or tort (including negligence or otherwise) arising in any way out of
41 // the use of this software, even if advised of the possibility of such damage.
42 //
43 //M*/
44
45 #ifndef OPENCV_CORE_FAST_MATH_HPP
46 #define OPENCV_CORE_FAST_MATH_HPP
47
48 #include "opencv2/core/cvdef.h"
49
50 #if ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ \
51     && defined __SSE2__ && !defined __APPLE__)) && !defined(__CUDACC__)
52 #include <emmintrin.h>
53 #endif
54
55
56 //! @addtogroup core_utils
57 //! @{
58
59 /****************************************************************************************\
60 *                                      fast math                                         *
61 \****************************************************************************************/
62
63 #ifdef __cplusplus
64 #  include <cmath>
65 #else
66 #  ifdef __BORLANDC__
67 #    include <fastmath.h>
68 #  else
69 #    include <math.h>
70 #  endif
71 #endif
72
73 #if defined __GNUC__ && defined __arm__ && (defined __ARM_PCS_VFP || defined __ARM_VFPV3__ || defined __ARM_NEON__) && !defined __SOFTFP__ && !defined(__CUDACC__)
74     // 1. general scheme
75     #define ARM_ROUND(_value, _asm_string) \
76         int res; \
77         float temp; \
78         (void)temp; \
79         __asm__(_asm_string : [res] "=r" (res), [temp] "=w" (temp) : [value] "w" (_value)); \
80         return res
81     // 2. version for double
82     #ifdef __clang__
83         #define ARM_ROUND_DBL(value) ARM_ROUND(value, "vcvtr.s32.f64 %[temp], %[value] \n vmov %[res], %[temp]")
84     #else
85         #define ARM_ROUND_DBL(value) ARM_ROUND(value, "vcvtr.s32.f64 %[temp], %P[value] \n vmov %[res], %[temp]")
86     #endif
87     // 3. version for float
88     #define ARM_ROUND_FLT(value) ARM_ROUND(value, "vcvtr.s32.f32 %[temp], %[value]\n vmov %[res], %[temp]")
89 #endif
90
91 /** @brief Rounds floating-point number to the nearest integer
92
93  @param value floating-point number. If the value is outside of INT_MIN ... INT_MAX range, the
94  result is not defined.
95  */
96 CV_INLINE int
97 cvRound( double value )
98 {
99 #if ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ \
100     && defined __SSE2__ && !defined __APPLE__) || CV_SSE2) && !defined(__CUDACC__)
101     __m128d t = _mm_set_sd( value );
102     return _mm_cvtsd_si32(t);
103 #elif defined _MSC_VER && defined _M_IX86
104     int t;
105     __asm
106     {
107         fld value;
108         fistp t;
109     }
110     return t;
111 #elif defined CV_ICC || defined __GNUC__
112 # if defined ARM_ROUND_DBL
113     ARM_ROUND_DBL(value);
114 # else
115     return (int)lrint(value);
116 # endif
117 #else
118     /* it's ok if round does not comply with IEEE754 standard;
119        the tests should allow +/-1 difference when the tested functions use round */
120     return (int)(value + (value >= 0 ? 0.5 : -0.5));
121 #endif
122 }
123
124
125 /** @brief Rounds floating-point number to the nearest integer not larger than the original.
126
127  The function computes an integer i such that:
128  \f[i \le \texttt{value} < i+1\f]
129  @param value floating-point number. If the value is outside of INT_MIN ... INT_MAX range, the
130  result is not defined.
131  */
132 CV_INLINE int cvFloor( double value )
133 {
134     int i = (int)value;
135     return i - (i > value);
136 }
137
138 /** @brief Rounds floating-point number to the nearest integer not smaller than the original.
139
140  The function computes an integer i such that:
141  \f[i \le \texttt{value} < i+1\f]
142  @param value floating-point number. If the value is outside of INT_MIN ... INT_MAX range, the
143  result is not defined.
144  */
145 CV_INLINE int cvCeil( double value )
146 {
147     int i = (int)value;
148     return i + (i < value);
149 }
150
151 /** @brief Determines if the argument is Not A Number.
152
153  @param value The input floating-point value
154
155  The function returns 1 if the argument is Not A Number (as defined by IEEE754 standard), 0
156  otherwise. */
157 CV_INLINE int cvIsNaN( double value )
158 {
159     Cv64suf ieee754;
160     ieee754.f = value;
161     return ((unsigned)(ieee754.u >> 32) & 0x7fffffff) +
162            ((unsigned)ieee754.u != 0) > 0x7ff00000;
163 }
164
165 /** @brief Determines if the argument is Infinity.
166
167  @param value The input floating-point value
168
169  The function returns 1 if the argument is a plus or minus infinity (as defined by IEEE754 standard)
170  and 0 otherwise. */
171 CV_INLINE int cvIsInf( double value )
172 {
173     Cv64suf ieee754;
174     ieee754.f = value;
175     return ((unsigned)(ieee754.u >> 32) & 0x7fffffff) == 0x7ff00000 &&
176             (unsigned)ieee754.u == 0;
177 }
178
179 #ifdef __cplusplus
180
181 /** @overload */
182 CV_INLINE int cvRound(float value)
183 {
184 #if ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ \
185     && defined __SSE2__ && !defined __APPLE__) || CV_SSE2) && !defined(__CUDACC__)
186     __m128 t = _mm_set_ss( value );
187     return _mm_cvtss_si32(t);
188 #elif defined _MSC_VER && defined _M_IX86
189     int t;
190     __asm
191     {
192         fld value;
193         fistp t;
194     }
195     return t;
196 #elif defined CV_ICC || defined __GNUC__
197 # if defined ARM_ROUND_FLT
198     ARM_ROUND_FLT(value);
199 # else
200     return (int)lrintf(value);
201 # endif
202 #else
203     /* it's ok if round does not comply with IEEE754 standard;
204      the tests should allow +/-1 difference when the tested functions use round */
205     return (int)(value + (value >= 0 ? 0.5f : -0.5f));
206 #endif
207 }
208
209 /** @overload */
210 CV_INLINE int cvRound( int value )
211 {
212     return value;
213 }
214
215 /** @overload */
216 CV_INLINE int cvFloor( float value )
217 {
218     int i = (int)value;
219     return i - (i > value);
220 }
221
222 /** @overload */
223 CV_INLINE int cvFloor( int value )
224 {
225     return value;
226 }
227
228 /** @overload */
229 CV_INLINE int cvCeil( float value )
230 {
231     int i = (int)value;
232     return i + (i < value);
233 }
234
235 /** @overload */
236 CV_INLINE int cvCeil( int value )
237 {
238     return value;
239 }
240
241 /** @overload */
242 CV_INLINE int cvIsNaN( float value )
243 {
244     Cv32suf ieee754;
245     ieee754.f = value;
246     return (ieee754.u & 0x7fffffff) > 0x7f800000;
247 }
248
249 /** @overload */
250 CV_INLINE int cvIsInf( float value )
251 {
252     Cv32suf ieee754;
253     ieee754.f = value;
254     return (ieee754.u & 0x7fffffff) == 0x7f800000;
255 }
256
257 #endif // __cplusplus
258
259 //! @} core_utils
260
261 #endif