1 | /* Copyright (C) 2011-2014 Povilas Kanapickas <povilas@radix.lt> |
2 | |
3 | Distributed under the Boost Software License, Version 1.0. |
4 | (See accompanying file LICENSE_1_0.txt or copy at |
5 | http://www.boost.org/LICENSE_1_0.txt) |
6 | */ |
7 | |
8 | #ifndef LIBSIMDPP_SIMDPP_TYPES_INT32X4_H |
9 | #define LIBSIMDPP_SIMDPP_TYPES_INT32X4_H |
10 | |
11 | #ifndef LIBSIMDPP_SIMD_H |
12 | #error "This file must be included through simd.h" |
13 | #endif |
14 | |
15 | #include <simdpp/setup_arch.h> |
16 | #include <simdpp/types/fwd.h> |
17 | #include <simdpp/types/any.h> |
18 | #include <simdpp/core/cast.h> |
19 | #include <simdpp/detail/construct_eval.h> |
20 | #include <simdpp/detail/array.h> |
21 | #include <simdpp/detail/null/mask.h> |
22 | #include <cstdint> |
23 | |
24 | namespace simdpp { |
25 | namespace SIMDPP_ARCH_NAMESPACE { |
26 | |
27 | /** Class representing 4x 32-bit signed integer vector |
28 | */ |
29 | template<> |
30 | class int32<4, void> : public any_int32<4, int32<4,void>> { |
31 | public: |
32 | static const unsigned type_tag = SIMDPP_TAG_INT; |
33 | using element_type = int32_t; |
34 | using base_vector_type = int32<4,void>; |
35 | using expr_type = void; |
36 | |
37 | #if SIMDPP_USE_SSE2 |
38 | using native_type = __m128i; |
39 | #elif SIMDPP_USE_NEON |
40 | using native_type = int32x4_t; |
41 | #elif SIMDPP_USE_ALTIVEC |
42 | using native_type = __vector int32_t; |
43 | #elif SIMDPP_USE_MSA |
44 | using native_type = v4i32; |
45 | #else |
46 | using native_type = detail::vararray<int32_t,4>; |
47 | #endif |
48 | |
49 | SIMDPP_INL int32<4>() = default; |
50 | SIMDPP_INL int32<4>(const int32<4> &) = default; |
51 | SIMDPP_INL int32<4> &operator=(const int32<4> &) = default; |
52 | |
53 | template<class E> SIMDPP_INL int32<4>(const int32<4,E>& d) { *this = d.eval(); } |
54 | template<class E> SIMDPP_INL int32<4>(const uint32<4,E>& d) { *this = d.eval(); } |
55 | template<class V> SIMDPP_INL explicit int32<4>(const any_vec<16,V>& d) |
56 | { |
57 | *this = bit_cast<int32<4>>(d.wrapped().eval()); |
58 | } |
59 | template<class V> SIMDPP_INL int32<4>& operator=(const any_vec<16,V>& d) |
60 | { |
61 | *this = bit_cast<int32<4>>(d.wrapped().eval()); return *this; |
62 | } |
63 | |
64 | /// Construct from the underlying vector type |
65 | SIMDPP_INL int32<4>(const native_type& d) : d_(d) {} |
66 | SIMDPP_INL int32<4>& operator=(const native_type& d) { d_ = d; return *this; } |
67 | |
68 | /// Convert to the underlying vector type |
69 | #if !SIMDPP_DISABLE_DEPRECATED_CONVERSION_OPERATOR_TO_NATIVE_TYPES |
70 | SIMDPP_INL operator native_type() const SIMDPP_IMPLICIT_CONVERSION_DEPRECATION_MSG |
71 | { return d_; } |
72 | #endif |
73 | SIMDPP_INL native_type native() const { return d_; } |
74 | |
75 | template<class E> SIMDPP_INL int32<4>(const expr_vec_construct<E>& e) |
76 | { |
77 | detail::construct_eval_wrapper(*this, e.expr()); |
78 | } |
79 | template<class E> SIMDPP_INL int32<4>& operator=(const expr_vec_construct<E>& e) |
80 | { |
81 | detail::construct_eval_wrapper(*this, e.expr()); return *this; |
82 | } |
83 | |
84 | /// Access base vectors |
85 | SIMDPP_INL const int32<4>& vec(unsigned) const { return *this; } |
86 | SIMDPP_INL int32<4>& vec(unsigned) { return *this; } |
87 | |
88 | SIMDPP_INL int32<4> eval() const { return *this; } |
89 | |
90 | #if SIMDPP_USE_NULL |
91 | /// For internal use only |
92 | SIMDPP_INL const int32_t& el(unsigned i) const { return d_[i]; } |
93 | SIMDPP_INL int32_t& el(unsigned i) { return d_[i]; } |
94 | #endif |
95 | |
96 | private: |
97 | native_type d_; |
98 | }; |
99 | |
100 | /** Class representing 4x 32-bit unsigned integer vector |
101 | */ |
102 | template<> |
103 | class uint32<4, void> : public any_int32<4, uint32<4,void>> { |
104 | public: |
105 | static const unsigned type_tag = SIMDPP_TAG_UINT; |
106 | using element_type = uint32_t; |
107 | using base_vector_type = uint32<4,void>; |
108 | using expr_type = void; |
109 | |
110 | #if SIMDPP_USE_SSE2 |
111 | using native_type = __m128i; |
112 | #elif SIMDPP_USE_NEON |
113 | using native_type = uint32x4_t; |
114 | #elif SIMDPP_USE_ALTIVEC |
115 | using native_type = __vector uint32_t; |
116 | #elif SIMDPP_USE_MSA |
117 | using native_type = v4u32; |
118 | #else |
119 | using native_type = detail::vararray<uint32_t,4>; |
120 | #endif |
121 | |
122 | SIMDPP_INL uint32<4>() = default; |
123 | SIMDPP_INL uint32<4>(const uint32<4> &) = default; |
124 | SIMDPP_INL uint32<4> &operator=(const uint32<4> &) = default; |
125 | |
126 | template<class E> SIMDPP_INL uint32<4>(const uint32<4,E>& d) { *this = d.eval(); } |
127 | template<class E> SIMDPP_INL uint32<4>(const int32<4,E>& d) { *this = d.eval(); } |
128 | template<class V> SIMDPP_INL explicit uint32<4>(const any_vec<16,V>& d) |
129 | { |
130 | *this = bit_cast<uint32<4>>(d.wrapped().eval()); |
131 | } |
132 | template<class V> SIMDPP_INL uint32<4>& operator=(const any_vec<16,V>& d) |
133 | { |
134 | *this = bit_cast<uint32<4>>(d.wrapped().eval()); return *this; |
135 | } |
136 | |
137 | /// Construct from the underlying vector type |
138 | SIMDPP_INL uint32<4>(const native_type& d) : d_(d) {} |
139 | SIMDPP_INL uint32<4>& operator=(const native_type& d) { d_ = d; return *this; } |
140 | |
141 | /// Convert to the underlying vector type |
142 | #if !SIMDPP_DISABLE_DEPRECATED_CONVERSION_OPERATOR_TO_NATIVE_TYPES |
143 | SIMDPP_INL operator native_type() const SIMDPP_IMPLICIT_CONVERSION_DEPRECATION_MSG |
144 | { return d_; } |
145 | #endif |
146 | SIMDPP_INL native_type native() const { return d_; } |
147 | |
148 | template<class E> SIMDPP_INL uint32<4>(const expr_vec_construct<E>& e) |
149 | { |
150 | detail::construct_eval_wrapper(*this, e.expr()); |
151 | } |
152 | template<class E> SIMDPP_INL uint32<4>& operator=(const expr_vec_construct<E>& e) |
153 | { |
154 | detail::construct_eval_wrapper(*this, e.expr()); return *this; |
155 | } |
156 | |
157 | /// Access base vectors |
158 | SIMDPP_INL const uint32<4>& vec(unsigned) const { return *this; } |
159 | SIMDPP_INL uint32<4>& vec(unsigned) { return *this; } |
160 | |
161 | SIMDPP_INL uint32<4> eval() const { return *this; } |
162 | |
163 | #if SIMDPP_USE_NULL |
164 | /// For uinternal use only |
165 | SIMDPP_INL const uint32_t& el(unsigned i) const { return d_[i]; } |
166 | SIMDPP_INL uint32_t& el(unsigned i) { return d_[i]; } |
167 | #endif |
168 | |
169 | private: |
170 | native_type d_; |
171 | }; |
172 | |
173 | /// Class representing possibly optimized mask data for 4x 32-bit integer |
174 | /// vector |
175 | template<> |
176 | class mask_int32<4, void> : public any_int32<4, mask_int32<4,void>> { |
177 | public: |
178 | static const unsigned type_tag = SIMDPP_TAG_MASK_INT; |
179 | using base_vector_type = mask_int32<4,void>; |
180 | using expr_type = void; |
181 | |
182 | #if SIMDPP_USE_AVX512VL |
183 | using native_type = __mmask8; |
184 | #elif SIMDPP_USE_SSE2 |
185 | using native_type = __m128i; |
186 | #elif SIMDPP_USE_NEON |
187 | using native_type = uint32x4_t; |
188 | #elif SIMDPP_USE_ALTIVEC |
189 | using native_type = __vector uint32_t; |
190 | #elif SIMDPP_USE_MSA |
191 | using native_type = v4u32; |
192 | #else |
193 | using native_type = detail::vararray<uint8_t,4>; |
194 | #endif |
195 | |
196 | SIMDPP_INL mask_int32<4>() = default; |
197 | SIMDPP_INL mask_int32<4>(const mask_int32<4> &) = default; |
198 | SIMDPP_INL mask_int32<4> &operator=(const mask_int32<4> &) = default; |
199 | |
200 | SIMDPP_INL mask_int32<4>(const native_type& d) : d_(d) {} |
201 | |
202 | #if SIMDPP_USE_ALTIVEC |
203 | SIMDPP_INL mask_int32<4>(const __vector __bool int& d) : d_((__vector uint32_t)d) {} |
204 | #endif |
205 | |
206 | #if (SIMDPP_USE_SSE2 && !SIMDPP_USE_AVX512VL) || SIMDPP_USE_NEON || SIMDPP_USE_ALTIVEC |
207 | SIMDPP_INL mask_int32<4>(const uint32<4>& d) : d_(d.native()) {} |
208 | #endif |
209 | |
210 | template<class E> SIMDPP_INL explicit mask_int32<4>(const mask_float32<4,E>& d) |
211 | { |
212 | *this = bit_cast<mask_int32<4>>(d.eval()); |
213 | } |
214 | template<class E> SIMDPP_INL mask_int32<4>& operator=(const mask_float32<4,E>& d) |
215 | { |
216 | *this = bit_cast<mask_int32<4>>(d.eval()); return *this; |
217 | } |
218 | |
219 | /// Convert to the underlying vector type |
220 | #if !SIMDPP_DISABLE_DEPRECATED_CONVERSION_OPERATOR_TO_NATIVE_TYPES |
221 | SIMDPP_INL operator native_type() const SIMDPP_IMPLICIT_CONVERSION_DEPRECATION_MSG |
222 | { return d_; } |
223 | #endif |
224 | SIMDPP_INL native_type native() const { return d_; } |
225 | |
226 | /// Access the underlying type |
227 | SIMDPP_INL uint32<4> unmask() const |
228 | { |
229 | #if SIMDPP_USE_NULL |
230 | return detail::null::unmask_mask<uint32<4>>(*this); |
231 | #elif SIMDPP_USE_AVX512VL |
232 | return _mm_movm_epi32(d_); |
233 | #else |
234 | return uint32<4>(d_); |
235 | #endif |
236 | } |
237 | |
238 | #if SIMDPP_USE_NULL |
239 | SIMDPP_INL uint8_t& el(unsigned id) { return d_[id]; } |
240 | SIMDPP_INL const uint8_t& el(unsigned id) const { return d_[id]; } |
241 | #endif |
242 | |
243 | SIMDPP_INL const mask_int32<4>& vec(unsigned) const { return *this; } |
244 | SIMDPP_INL mask_int32<4>& vec(unsigned) { return *this; } |
245 | |
246 | SIMDPP_INL mask_int32<4> eval() const { return *this; } |
247 | |
248 | private: |
249 | native_type d_; |
250 | }; |
251 | |
252 | } // namespace SIMDPP_ARCH_NAMESPACE |
253 | } // namespace simdpp |
254 | |
255 | #endif |
256 | |