further improvements in split & merge; started using non-temporary store instructions...
[platform/upstream/opencv.git] / modules / core / include / opencv2 / core / hal / intrin.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_HAL_INTRIN_HPP
46 #define OPENCV_HAL_INTRIN_HPP
47
48 #include <cmath>
49 #include <float.h>
50 #include <stdlib.h>
51 #include "opencv2/core/cvdef.h"
52
53 #define OPENCV_HAL_ADD(a, b) ((a) + (b))
54 #define OPENCV_HAL_AND(a, b) ((a) & (b))
55 #define OPENCV_HAL_NOP(a) (a)
56 #define OPENCV_HAL_1ST(a, b) (a)
57
58 // unlike HAL API, which is in cv::hal,
59 // we put intrinsics into cv namespace to make its
60 // access from within opencv code more accessible
61 namespace cv {
62
63 namespace hal {
64
65 enum StoreMode
66 {
67     STORE_UNALIGNED = 0,
68     STORE_ALIGNED = 1,
69     STORE_ALIGNED_NOCACHE = 2
70 };
71
72 }
73
74 template<typename _Tp> struct V_TypeTraits
75 {
76 };
77
78 #define CV_INTRIN_DEF_TYPE_TRAITS(type, int_type_, uint_type_, abs_type_, w_type_, q_type_, sum_type_, nlanes128_) \
79     template<> struct V_TypeTraits<type> \
80     { \
81         typedef type value_type; \
82         typedef int_type_ int_type; \
83         typedef abs_type_ abs_type; \
84         typedef uint_type_ uint_type; \
85         typedef w_type_ w_type; \
86         typedef q_type_ q_type; \
87         typedef sum_type_ sum_type; \
88         enum { nlanes128 = nlanes128_ }; \
89     \
90         static inline int_type reinterpret_int(type x) \
91         { \
92             union { type l; int_type i; } v; \
93             v.l = x; \
94             return v.i; \
95         } \
96     \
97         static inline type reinterpret_from_int(int_type x) \
98         { \
99             union { type l; int_type i; } v; \
100             v.i = x; \
101             return v.l; \
102         } \
103     }
104
105 CV_INTRIN_DEF_TYPE_TRAITS(uchar, schar, uchar, uchar, ushort, unsigned, unsigned, 16);
106 CV_INTRIN_DEF_TYPE_TRAITS(schar, schar, uchar, uchar, short, int, int, 16);
107 CV_INTRIN_DEF_TYPE_TRAITS(ushort, short, ushort, ushort, unsigned, uint64, unsigned, 8);
108 CV_INTRIN_DEF_TYPE_TRAITS(short, short, ushort, ushort, int, int64, int, 8);
109 CV_INTRIN_DEF_TYPE_TRAITS(unsigned, int, unsigned, unsigned, uint64, void, unsigned, 4);
110 CV_INTRIN_DEF_TYPE_TRAITS(int, int, unsigned, unsigned, int64, void, int, 4);
111 CV_INTRIN_DEF_TYPE_TRAITS(float, int, unsigned, float, double, void, float, 4);
112 CV_INTRIN_DEF_TYPE_TRAITS(uint64, int64, uint64, uint64, void, void, uint64, 2);
113 CV_INTRIN_DEF_TYPE_TRAITS(int64, int64, uint64, uint64, void, void, int64, 2);
114 CV_INTRIN_DEF_TYPE_TRAITS(double, int64, uint64, double, void, void, double, 2);
115
116 #ifndef CV_DOXYGEN
117
118 #ifdef CV_CPU_DISPATCH_MODE
119     #define CV_CPU_OPTIMIZATION_HAL_NAMESPACE __CV_CAT(hal_, CV_CPU_DISPATCH_MODE)
120     #define CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN namespace __CV_CAT(hal_, CV_CPU_DISPATCH_MODE) {
121     #define CV_CPU_OPTIMIZATION_HAL_NAMESPACE_END }
122 #else
123     #define CV_CPU_OPTIMIZATION_HAL_NAMESPACE hal_baseline
124     #define CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN namespace hal_baseline {
125     #define CV_CPU_OPTIMIZATION_HAL_NAMESPACE_END }
126 #endif
127
128 CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN
129 CV_CPU_OPTIMIZATION_HAL_NAMESPACE_END
130 using namespace CV_CPU_OPTIMIZATION_HAL_NAMESPACE;
131 #endif
132 }
133
134 #ifdef CV_DOXYGEN
135 #   undef CV_AVX2
136 #   undef CV_SSE2
137 #   undef CV_NEON
138 #   undef CV_VSX
139 #   undef CV_FP16
140 #endif
141
142 #if CV_SSE2
143
144 #include "opencv2/core/hal/intrin_sse.hpp"
145
146 #elif CV_NEON
147
148 #include "opencv2/core/hal/intrin_neon.hpp"
149
150 #elif CV_VSX
151
152 #include "opencv2/core/hal/intrin_vsx.hpp"
153
154 #else
155
156 #define CV_SIMD128_CPP 1
157 #include "opencv2/core/hal/intrin_cpp.hpp"
158
159 #endif
160
161 // AVX2 can be used together with SSE2, so
162 // we define those two sets of intrinsics at once.
163 // Most of the intrinsics do not conflict (the proper overloaded variant is
164 // resolved by the argument types, e.g. v_float32x4 ~ SSE2, v_float32x8 ~ AVX2),
165 // but some of AVX2 intrinsics get v256_ prefix instead of v_, e.g. v256_load() vs v_load().
166 // Correspondingly, the wide intrinsics (which are mapped to the "widest"
167 // available instruction set) will get vx_ prefix
168 // (and will be mapped to v256_ counterparts) (e.g. vx_load() => v245_load())
169 #if CV_AVX2
170
171 #include "opencv2/core/hal/intrin_avx.hpp"
172
173 #endif
174
175 //! @cond IGNORED
176
177 namespace cv {
178
179 #ifndef CV_DOXYGEN
180 CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN
181 #endif
182
183 #ifndef CV_SIMD128
184 #define CV_SIMD128 0
185 #endif
186
187 #ifndef CV_SIMD128_64F
188 #define CV_SIMD128_64F 0
189 #endif
190
191 #ifndef CV_SIMD256
192 #define CV_SIMD256 0
193 #endif
194
195 #ifndef CV_SIMD256_64F
196 #define CV_SIMD256_64F 0
197 #endif
198
199 #ifndef CV_SIMD512
200 #define CV_SIMD512 0
201 #endif
202
203 #ifndef CV_SIMD512_64F
204 #define CV_SIMD512_64F 0
205 #endif
206
207 #if CV_SIMD512
208     #define CV_SIMD 1
209     #define CV_SIMD_64F CV_SIMD512_64F
210     #define CV_SIMD_WIDTH 64
211 #elif CV_SIMD256
212     #define CV_SIMD 1
213     #define CV_SIMD_64F CV_SIMD256_64F
214     #define CV_SIMD_WIDTH 32
215 #else
216     #define CV_SIMD CV_SIMD128
217     #define CV_SIMD_64F CV_SIMD128_64F
218     #define CV_SIMD_WIDTH 16
219 #endif
220
221 //==================================================================================================
222
223 #define CV_INTRIN_DEFINE_WIDE_INTRIN(typ, vtyp, short_typ, prefix, loadsfx) \
224     inline vtyp vx_setall_##short_typ(typ v) { return prefix##_setall_##short_typ(v); } \
225     inline vtyp vx_setzero_##short_typ() { return prefix##_setzero_##short_typ(); } \
226     inline vtyp vx_##loadsfx(const typ* ptr) { return prefix##_##loadsfx(ptr); } \
227     inline vtyp vx_##loadsfx##_aligned(const typ* ptr) { return prefix##_##loadsfx##_aligned(ptr); } \
228     inline void vx_store(typ* ptr, const vtyp& v) { return v_store(ptr, v); } \
229     inline void vx_store_aligned(typ* ptr, const vtyp& v) { return v_store_aligned(ptr, v); }
230
231 #define CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(typ, wtyp, prefix) \
232 inline wtyp vx_load_expand(const typ* ptr) { return prefix##_load_expand(ptr); }
233
234 #define CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND_Q(typ, qtyp, prefix) \
235 inline qtyp vx_load_expand_q(const typ* ptr) { return prefix##_load_expand_q(ptr); }
236
237 #define CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(typ, vtyp, short_typ, wtyp, qtyp, prefix, loadsfx) \
238     CV_INTRIN_DEFINE_WIDE_INTRIN(typ, vtyp, short_typ, prefix, loadsfx) \
239     CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(typ, wtyp, prefix) \
240     CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND_Q(typ, qtyp, prefix)
241
242 #define CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(prefix) \
243     CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(uchar, v_uint8, u8, v_uint16, v_uint32, prefix, load) \
244     CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(schar, v_int8, s8, v_int16, v_int32, prefix, load) \
245     CV_INTRIN_DEFINE_WIDE_INTRIN(ushort, v_uint16, u16, prefix, load) \
246     CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(ushort, v_uint32, prefix) \
247     CV_INTRIN_DEFINE_WIDE_INTRIN(short, v_int16, s16, prefix, load) \
248     CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(short, v_int32, prefix) \
249     CV_INTRIN_DEFINE_WIDE_INTRIN(int, v_int32, s32, prefix, load) \
250     CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(int, v_int64, prefix) \
251     CV_INTRIN_DEFINE_WIDE_INTRIN(unsigned, v_uint32, u32, prefix, load) \
252     CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(unsigned, v_uint64, prefix) \
253     CV_INTRIN_DEFINE_WIDE_INTRIN(float, v_float32, f32, prefix, load) \
254     CV_INTRIN_DEFINE_WIDE_INTRIN(int64, v_int64, s64, prefix, load) \
255     CV_INTRIN_DEFINE_WIDE_INTRIN(uint64, v_uint64, u64, prefix, load)
256
257 template<typename _Tp> struct V_RegTraits
258 {
259 };
260
261 #define CV_DEF_REG_TRAITS(prefix, _reg, lane_type, suffix, _u_reg, _w_reg, _q_reg, _int_reg, _round_reg) \
262     template<> struct V_RegTraits<_reg> \
263     { \
264         typedef _reg reg; \
265         typedef _u_reg u_reg; \
266         typedef _w_reg w_reg; \
267         typedef _q_reg q_reg; \
268         typedef _int_reg int_reg; \
269         typedef _round_reg round_reg; \
270     }
271
272 #if CV_SIMD128 || CV_SIMD128_CPP
273     CV_DEF_REG_TRAITS(v, v_uint8x16, uchar, u8, v_uint8x16, v_uint16x8, v_uint32x4, v_int8x16, void);
274     CV_DEF_REG_TRAITS(v, v_int8x16, schar, s8, v_uint8x16, v_int16x8, v_int32x4, v_int8x16, void);
275     CV_DEF_REG_TRAITS(v, v_uint16x8, ushort, u16, v_uint16x8, v_uint32x4, v_uint64x2, v_int16x8, void);
276     CV_DEF_REG_TRAITS(v, v_int16x8, short, s16, v_uint16x8, v_int32x4, v_int64x2, v_int16x8, void);
277     CV_DEF_REG_TRAITS(v, v_uint32x4, unsigned, u32, v_uint32x4, v_uint64x2, void, v_int32x4, void);
278     CV_DEF_REG_TRAITS(v, v_int32x4, int, s32, v_uint32x4, v_int64x2, void, v_int32x4, void);
279 #if CV_SIMD128_64F
280     CV_DEF_REG_TRAITS(v, v_float32x4, float, f32, v_float32x4, v_float64x2, void, v_int32x4, v_int32x4);
281 #else
282     CV_DEF_REG_TRAITS(v, v_float32x4, float, f32, v_float32x4, void, void, v_int32x4, v_int32x4);
283 #endif
284     CV_DEF_REG_TRAITS(v, v_uint64x2, uint64, u64, v_uint64x2, void, void, v_int64x2, void);
285     CV_DEF_REG_TRAITS(v, v_int64x2, int64, s64, v_uint64x2, void, void, v_int64x2, void);
286 #if CV_SIMD128_64F
287     CV_DEF_REG_TRAITS(v, v_float64x2, double, f64, v_float64x2, void, void, v_int64x2, v_int32x4);
288 #endif
289 #if CV_FP16
290     CV_DEF_REG_TRAITS(v, v_float16x8, short, f16, v_float32x4, void, void, v_int16x8, v_int16x8);
291 #endif
292 #endif
293
294 #if CV_SIMD256
295     CV_DEF_REG_TRAITS(v256, v_uint8x32, uchar, u8, v_uint8x32, v_uint16x16, v_uint32x8, v_int8x32, void);
296     CV_DEF_REG_TRAITS(v256, v_int8x32, schar, s8, v_uint8x32, v_int16x16, v_int32x8, v_int8x32, void);
297     CV_DEF_REG_TRAITS(v256, v_uint16x16, ushort, u16, v_uint16x16, v_uint32x8, v_uint64x4, v_int16x16, void);
298     CV_DEF_REG_TRAITS(v256, v_int16x16, short, s16, v_uint16x16, v_int32x8, v_int64x4, v_int16x16, void);
299     CV_DEF_REG_TRAITS(v256, v_uint32x8, unsigned, u32, v_uint32x8, v_uint64x4, void, v_int32x8, void);
300     CV_DEF_REG_TRAITS(v256, v_int32x8, int, s32, v_uint32x8, v_int64x4, void, v_int32x8, void);
301     CV_DEF_REG_TRAITS(v256, v_float32x8, float, f32, v_float32x8, v_float64x4, void, v_int32x8, v_int32x8);
302     CV_DEF_REG_TRAITS(v256, v_uint64x4, uint64, u64, v_uint64x4, void, void, v_int64x4, void);
303     CV_DEF_REG_TRAITS(v256, v_int64x4, int64, s64, v_uint64x4, void, void, v_int64x4, void);
304     CV_DEF_REG_TRAITS(v256, v_float64x4, double, f64, v_float64x4, void, void, v_int64x4, v_int32x8);
305 #if CV_FP16
306     CV_DEF_REG_TRAITS(v256, v_float16x16, short, f16, v_float32x8, void, void, v_int16x16, void);
307 #endif
308 #endif
309
310 #if CV_SIMD256
311     typedef v_uint8x32   v_uint8;
312     typedef v_int8x32    v_int8;
313     typedef v_uint16x16  v_uint16;
314     typedef v_int16x16   v_int16;
315     typedef v_uint32x8   v_uint32;
316     typedef v_int32x8    v_int32;
317     typedef v_uint64x4   v_uint64;
318     typedef v_int64x4    v_int64;
319     typedef v_float32x8  v_float32;
320     #if CV_SIMD256_64F
321     typedef v_float64x4  v_float64;
322     #endif
323     #if CV_FP16
324     typedef v_float16x16  v_float16;
325     CV_INTRIN_DEFINE_WIDE_INTRIN(short, v_float16, f16, v256, load_f16)
326     #endif
327     CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v256)
328     CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v256, load)
329     inline void vx_cleanup() { v256_cleanup(); }
330 #elif CV_SIMD128
331     typedef v_uint8x16  v_uint8;
332     typedef v_int8x16   v_int8;
333     typedef v_uint16x8  v_uint16;
334     typedef v_int16x8   v_int16;
335     typedef v_uint32x4  v_uint32;
336     typedef v_int32x4   v_int32;
337     typedef v_uint64x2  v_uint64;
338     typedef v_int64x2   v_int64;
339     typedef v_float32x4 v_float32;
340     #if CV_SIMD128_64F
341     typedef v_float64x2 v_float64;
342     #endif
343     #if CV_FP16
344     typedef v_float16x8  v_float16;
345     CV_INTRIN_DEFINE_WIDE_INTRIN(short, v_float16, f16, v, load_f16)
346     #endif
347     CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v)
348     #if CV_SIMD128_64F
349     CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v, load)
350     #endif
351     inline void vx_cleanup() { v_cleanup(); }
352 #endif
353
354 inline unsigned int trailingZeros32(unsigned int value) {
355 #if defined(_MSC_VER)
356 #if (_MSC_VER < 1700) || defined(_M_ARM)
357     unsigned long index = 0;
358     _BitScanForward(&index, value);
359     return (unsigned int)index;
360 #else
361     return _tzcnt_u32(value);
362 #endif
363 #elif defined(__GNUC__) || defined(__GNUG__)
364     return __builtin_ctz(value);
365 #elif defined(__ICC) || defined(__INTEL_COMPILER)
366     return _bit_scan_forward(value);
367 #elif defined(__clang__)
368     return llvm.cttz.i32(value, true);
369 #else
370     static const int MultiplyDeBruijnBitPosition[32] = {
371         0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
372         31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 };
373     return MultiplyDeBruijnBitPosition[((uint32_t)((value & -value) * 0x077CB531U)) >> 27];
374 #endif
375 }
376
377 #ifndef CV_DOXYGEN
378 CV_CPU_OPTIMIZATION_HAL_NAMESPACE_END
379 #endif
380
381 } // cv::
382
383 //! @endcond
384
385 #endif