source: Daodan/MSYS2/mingw32/include/c++/11.2.0/experimental/bits/simd_scalar.h@ 1181

Last change on this file since 1181 was 1166, checked in by rossy, 3 years ago

Daodan: Replace MinGW build env with an up-to-date MSYS2 env

File size: 22.3 KB
Line 
1// Simd scalar ABI specific implementations -*- C++ -*-
2
3// Copyright (C) 2020-2021 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25#ifndef _GLIBCXX_EXPERIMENTAL_SIMD_SCALAR_H_
26#define _GLIBCXX_EXPERIMENTAL_SIMD_SCALAR_H_
27#if __cplusplus >= 201703L
28
29#include <cmath>
30
31_GLIBCXX_SIMD_BEGIN_NAMESPACE
32
33// __promote_preserving_unsigned{{{
34// work around crazy semantics of unsigned integers of lower rank than int:
35// Before applying an operator the operands are promoted to int. In which case
36// over- or underflow is UB, even though the operand types were unsigned.
37template <typename _Tp>
38 _GLIBCXX_SIMD_INTRINSIC constexpr decltype(auto)
39 __promote_preserving_unsigned(const _Tp& __x)
40 {
41 if constexpr (is_signed_v<decltype(+__x)> && is_unsigned_v<_Tp>)
42 return static_cast<unsigned int>(__x);
43 else
44 return __x;
45 }
46
47// }}}
48
49struct _CommonImplScalar;
50struct _CommonImplBuiltin;
51struct _SimdImplScalar;
52struct _MaskImplScalar;
53
54// simd_abi::_Scalar {{{
55struct simd_abi::_Scalar
56{
57 template <typename _Tp>
58 static constexpr size_t _S_size = 1;
59
60 template <typename _Tp>
61 static constexpr size_t _S_full_size = 1;
62
63 template <typename _Tp>
64 static constexpr bool _S_is_partial = false;
65
66 struct _IsValidAbiTag : true_type {};
67
68 template <typename _Tp>
69 struct _IsValidSizeFor : true_type {};
70
71 template <typename _Tp>
72 struct _IsValid : __is_vectorizable<_Tp> {};
73
74 template <typename _Tp>
75 static constexpr bool _S_is_valid_v = _IsValid<_Tp>::value;
76
77 _GLIBCXX_SIMD_INTRINSIC static constexpr bool _S_masked(bool __x)
78 { return __x; }
79
80 using _CommonImpl = _CommonImplScalar;
81 using _SimdImpl = _SimdImplScalar;
82 using _MaskImpl = _MaskImplScalar;
83
84 template <typename _Tp, bool = _S_is_valid_v<_Tp>>
85 struct __traits : _InvalidTraits {};
86
87 template <typename _Tp>
88 struct __traits<_Tp, true>
89 {
90 using _IsValid = true_type;
91 using _SimdImpl = _SimdImplScalar;
92 using _MaskImpl = _MaskImplScalar;
93 using _SimdMember = _Tp;
94 using _MaskMember = bool;
95
96 static constexpr size_t _S_simd_align = alignof(_SimdMember);
97 static constexpr size_t _S_mask_align = alignof(_MaskMember);
98
99 // nothing the user can spell converts to/from simd/simd_mask
100 struct _SimdCastType { _SimdCastType() = delete; };
101 struct _MaskCastType { _MaskCastType() = delete; };
102 struct _SimdBase {};
103 struct _MaskBase {};
104 };
105};
106
107// }}}
108// _CommonImplScalar {{{
109struct _CommonImplScalar
110{
111 // _S_store {{{
112 template <typename _Tp>
113 _GLIBCXX_SIMD_INTRINSIC static void _S_store(_Tp __x, void* __addr)
114 { __builtin_memcpy(__addr, &__x, sizeof(_Tp)); }
115
116 // }}}
117 // _S_store_bool_array(_BitMask) {{{
118 template <size_t _Np, bool _Sanitized>
119 _GLIBCXX_SIMD_INTRINSIC static constexpr void
120 _S_store_bool_array(_BitMask<_Np, _Sanitized> __x, bool* __mem)
121 {
122 __make_dependent_t<decltype(__x), _CommonImplBuiltin>::_S_store_bool_array(
123 __x, __mem);
124 }
125
126 // }}}
127};
128
129// }}}
130// _SimdImplScalar {{{
131struct _SimdImplScalar
132{
133 // member types {{{2
134 using abi_type = simd_abi::scalar;
135
136 template <typename _Tp>
137 using _TypeTag = _Tp*;
138
139 // _S_broadcast {{{2
140 template <typename _Tp>
141 _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp _S_broadcast(_Tp __x) noexcept
142 { return __x; }
143
144 // _S_generator {{{2
145 template <typename _Fp, typename _Tp>
146 _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp _S_generator(_Fp&& __gen,
147 _TypeTag<_Tp>)
148 { return __gen(_SizeConstant<0>()); }
149
150 // _S_load {{{2
151 template <typename _Tp, typename _Up>
152 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_load(const _Up* __mem,
153 _TypeTag<_Tp>) noexcept
154 { return static_cast<_Tp>(__mem[0]); }
155
156 // _S_masked_load {{{2
157 template <typename _Tp, typename _Up>
158 static inline _Tp _S_masked_load(_Tp __merge, bool __k,
159 const _Up* __mem) noexcept
160 {
161 if (__k)
162 __merge = static_cast<_Tp>(__mem[0]);
163 return __merge;
164 }
165
166 // _S_store {{{2
167 template <typename _Tp, typename _Up>
168 static inline void _S_store(_Tp __v, _Up* __mem, _TypeTag<_Tp>) noexcept
169 { __mem[0] = static_cast<_Up>(__v); }
170
171 // _S_masked_store {{{2
172 template <typename _Tp, typename _Up>
173 static inline void _S_masked_store(const _Tp __v, _Up* __mem,
174 const bool __k) noexcept
175 { if (__k) __mem[0] = __v; }
176
177 // _S_negate {{{2
178 template <typename _Tp>
179 static constexpr inline bool _S_negate(_Tp __x) noexcept
180 { return !__x; }
181
182 // _S_reduce {{{2
183 template <typename _Tp, typename _BinaryOperation>
184 static constexpr inline _Tp
185 _S_reduce(const simd<_Tp, simd_abi::scalar>& __x, const _BinaryOperation&)
186 { return __x._M_data; }
187
188 // _S_min, _S_max {{{2
189 template <typename _Tp>
190 static constexpr inline _Tp _S_min(const _Tp __a, const _Tp __b)
191 { return std::min(__a, __b); }
192
193 template <typename _Tp>
194 static constexpr inline _Tp _S_max(const _Tp __a, const _Tp __b)
195 { return std::max(__a, __b); }
196
197 // _S_complement {{{2
198 template <typename _Tp>
199 static constexpr inline _Tp _S_complement(_Tp __x) noexcept
200 { return static_cast<_Tp>(~__x); }
201
202 // _S_unary_minus {{{2
203 template <typename _Tp>
204 static constexpr inline _Tp _S_unary_minus(_Tp __x) noexcept
205 { return static_cast<_Tp>(-__x); }
206
207 // arithmetic operators {{{2
208 template <typename _Tp>
209 static constexpr inline _Tp _S_plus(_Tp __x, _Tp __y)
210 {
211 return static_cast<_Tp>(__promote_preserving_unsigned(__x)
212 + __promote_preserving_unsigned(__y));
213 }
214
215 template <typename _Tp>
216 static constexpr inline _Tp _S_minus(_Tp __x, _Tp __y)
217 {
218 return static_cast<_Tp>(__promote_preserving_unsigned(__x)
219 - __promote_preserving_unsigned(__y));
220 }
221
222 template <typename _Tp>
223 static constexpr inline _Tp _S_multiplies(_Tp __x, _Tp __y)
224 {
225 return static_cast<_Tp>(__promote_preserving_unsigned(__x)
226 * __promote_preserving_unsigned(__y));
227 }
228
229 template <typename _Tp>
230 static constexpr inline _Tp _S_divides(_Tp __x, _Tp __y)
231 {
232 return static_cast<_Tp>(__promote_preserving_unsigned(__x)
233 / __promote_preserving_unsigned(__y));
234 }
235
236 template <typename _Tp>
237 static constexpr inline _Tp _S_modulus(_Tp __x, _Tp __y)
238 {
239 return static_cast<_Tp>(__promote_preserving_unsigned(__x)
240 % __promote_preserving_unsigned(__y));
241 }
242
243 template <typename _Tp>
244 static constexpr inline _Tp _S_bit_and(_Tp __x, _Tp __y)
245 {
246 if constexpr (is_floating_point_v<_Tp>)
247 {
248 using _Ip = __int_for_sizeof_t<_Tp>;
249 return __bit_cast<_Tp>(__bit_cast<_Ip>(__x) & __bit_cast<_Ip>(__y));
250 }
251 else
252 return static_cast<_Tp>(__promote_preserving_unsigned(__x)
253 & __promote_preserving_unsigned(__y));
254 }
255
256 template <typename _Tp>
257 static constexpr inline _Tp _S_bit_or(_Tp __x, _Tp __y)
258 {
259 if constexpr (is_floating_point_v<_Tp>)
260 {
261 using _Ip = __int_for_sizeof_t<_Tp>;
262 return __bit_cast<_Tp>(__bit_cast<_Ip>(__x) | __bit_cast<_Ip>(__y));
263 }
264 else
265 return static_cast<_Tp>(__promote_preserving_unsigned(__x)
266 | __promote_preserving_unsigned(__y));
267 }
268
269 template <typename _Tp>
270 static constexpr inline _Tp _S_bit_xor(_Tp __x, _Tp __y)
271 {
272 if constexpr (is_floating_point_v<_Tp>)
273 {
274 using _Ip = __int_for_sizeof_t<_Tp>;
275 return __bit_cast<_Tp>(__bit_cast<_Ip>(__x) ^ __bit_cast<_Ip>(__y));
276 }
277 else
278 return static_cast<_Tp>(__promote_preserving_unsigned(__x)
279 ^ __promote_preserving_unsigned(__y));
280 }
281
282 template <typename _Tp>
283 static constexpr inline _Tp _S_bit_shift_left(_Tp __x, int __y)
284 { return static_cast<_Tp>(__promote_preserving_unsigned(__x) << __y); }
285
286 template <typename _Tp>
287 static constexpr inline _Tp _S_bit_shift_right(_Tp __x, int __y)
288 { return static_cast<_Tp>(__promote_preserving_unsigned(__x) >> __y); }
289
290 // math {{{2
291 // frexp, modf and copysign implemented in simd_math.h
292 template <typename _Tp>
293 using _ST = _SimdTuple<_Tp, simd_abi::scalar>;
294
295 template <typename _Tp>
296 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_acos(_Tp __x)
297 { return std::acos(__x); }
298
299 template <typename _Tp>
300 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_asin(_Tp __x)
301 { return std::asin(__x); }
302
303 template <typename _Tp>
304 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_atan(_Tp __x)
305 { return std::atan(__x); }
306
307 template <typename _Tp>
308 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_cos(_Tp __x)
309 { return std::cos(__x); }
310
311 template <typename _Tp>
312 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_sin(_Tp __x)
313 { return std::sin(__x); }
314
315 template <typename _Tp>
316 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_tan(_Tp __x)
317 { return std::tan(__x); }
318
319 template <typename _Tp>
320 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_acosh(_Tp __x)
321 { return std::acosh(__x); }
322
323 template <typename _Tp>
324 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_asinh(_Tp __x)
325 { return std::asinh(__x); }
326
327 template <typename _Tp>
328 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_atanh(_Tp __x)
329 { return std::atanh(__x); }
330
331 template <typename _Tp>
332 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_cosh(_Tp __x)
333 { return std::cosh(__x); }
334
335 template <typename _Tp>
336 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_sinh(_Tp __x)
337 { return std::sinh(__x); }
338
339 template <typename _Tp>
340 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_tanh(_Tp __x)
341 { return std::tanh(__x); }
342
343 template <typename _Tp>
344 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_atan2(_Tp __x, _Tp __y)
345 { return std::atan2(__x, __y); }
346
347 template <typename _Tp>
348 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_exp(_Tp __x)
349 { return std::exp(__x); }
350
351 template <typename _Tp>
352 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_exp2(_Tp __x)
353 { return std::exp2(__x); }
354
355 template <typename _Tp>
356 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_expm1(_Tp __x)
357 { return std::expm1(__x); }
358
359 template <typename _Tp>
360 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_log(_Tp __x)
361 { return std::log(__x); }
362
363 template <typename _Tp>
364 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_log10(_Tp __x)
365 { return std::log10(__x); }
366
367 template <typename _Tp>
368 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_log1p(_Tp __x)
369 { return std::log1p(__x); }
370
371 template <typename _Tp>
372 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_log2(_Tp __x)
373 { return std::log2(__x); }
374
375 template <typename _Tp>
376 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_logb(_Tp __x)
377 { return std::logb(__x); }
378
379 template <typename _Tp>
380 _GLIBCXX_SIMD_INTRINSIC static _ST<int> _S_ilogb(_Tp __x)
381 { return {std::ilogb(__x)}; }
382
383 template <typename _Tp>
384 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_pow(_Tp __x, _Tp __y)
385 { return std::pow(__x, __y); }
386
387 template <typename _Tp>
388 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_abs(_Tp __x)
389 { return std::abs(__x); }
390
391 template <typename _Tp>
392 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fabs(_Tp __x)
393 { return std::fabs(__x); }
394
395 template <typename _Tp>
396 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_sqrt(_Tp __x)
397 { return std::sqrt(__x); }
398
399 template <typename _Tp>
400 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_cbrt(_Tp __x)
401 { return std::cbrt(__x); }
402
403 template <typename _Tp>
404 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_erf(_Tp __x)
405 { return std::erf(__x); }
406
407 template <typename _Tp>
408 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_erfc(_Tp __x)
409 { return std::erfc(__x); }
410
411 template <typename _Tp>
412 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_lgamma(_Tp __x)
413 { return std::lgamma(__x); }
414
415 template <typename _Tp>
416 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_tgamma(_Tp __x)
417 { return std::tgamma(__x); }
418
419 template <typename _Tp>
420 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_trunc(_Tp __x)
421 { return std::trunc(__x); }
422
423 template <typename _Tp>
424 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_floor(_Tp __x)
425 { return std::floor(__x); }
426
427 template <typename _Tp>
428 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_ceil(_Tp __x)
429 { return std::ceil(__x); }
430
431 template <typename _Tp>
432 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_nearbyint(_Tp __x)
433 { return std::nearbyint(__x); }
434
435 template <typename _Tp>
436 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_rint(_Tp __x)
437 { return std::rint(__x); }
438
439 template <typename _Tp>
440 _GLIBCXX_SIMD_INTRINSIC static _ST<long> _S_lrint(_Tp __x)
441 { return {std::lrint(__x)}; }
442
443 template <typename _Tp>
444 _GLIBCXX_SIMD_INTRINSIC static _ST<long long> _S_llrint(_Tp __x)
445 { return {std::llrint(__x)}; }
446
447 template <typename _Tp>
448 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_round(_Tp __x)
449 { return std::round(__x); }
450
451 template <typename _Tp>
452 _GLIBCXX_SIMD_INTRINSIC static _ST<long> _S_lround(_Tp __x)
453 { return {std::lround(__x)}; }
454
455 template <typename _Tp>
456 _GLIBCXX_SIMD_INTRINSIC static _ST<long long> _S_llround(_Tp __x)
457 { return {std::llround(__x)}; }
458
459 template <typename _Tp>
460 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_ldexp(_Tp __x, _ST<int> __y)
461 { return std::ldexp(__x, __y.first); }
462
463 template <typename _Tp>
464 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_scalbn(_Tp __x, _ST<int> __y)
465 { return std::scalbn(__x, __y.first); }
466
467 template <typename _Tp>
468 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_scalbln(_Tp __x, _ST<long> __y)
469 { return std::scalbln(__x, __y.first); }
470
471 template <typename _Tp>
472 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fmod(_Tp __x, _Tp __y)
473 { return std::fmod(__x, __y); }
474
475 template <typename _Tp>
476 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_remainder(_Tp __x, _Tp __y)
477 { return std::remainder(__x, __y); }
478
479 template <typename _Tp>
480 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_nextafter(_Tp __x, _Tp __y)
481 { return std::nextafter(__x, __y); }
482
483 template <typename _Tp>
484 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fdim(_Tp __x, _Tp __y)
485 { return std::fdim(__x, __y); }
486
487 template <typename _Tp>
488 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fmax(_Tp __x, _Tp __y)
489 { return std::fmax(__x, __y); }
490
491 template <typename _Tp>
492 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fmin(_Tp __x, _Tp __y)
493 { return std::fmin(__x, __y); }
494
495 template <typename _Tp>
496 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fma(_Tp __x, _Tp __y, _Tp __z)
497 { return std::fma(__x, __y, __z); }
498
499 template <typename _Tp>
500 _GLIBCXX_SIMD_INTRINSIC static _Tp _S_remquo(_Tp __x, _Tp __y, _ST<int>* __z)
501 { return std::remquo(__x, __y, &__z->first); }
502
503 template <typename _Tp>
504 _GLIBCXX_SIMD_INTRINSIC constexpr static _ST<int> _S_fpclassify(_Tp __x)
505 { return {std::fpclassify(__x)}; }
506
507 template <typename _Tp>
508 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isfinite(_Tp __x)
509 { return std::isfinite(__x); }
510
511 template <typename _Tp>
512 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isinf(_Tp __x)
513 { return std::isinf(__x); }
514
515 template <typename _Tp>
516 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isnan(_Tp __x)
517 { return std::isnan(__x); }
518
519 template <typename _Tp>
520 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isnormal(_Tp __x)
521 { return std::isnormal(__x); }
522
523 template <typename _Tp>
524 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_signbit(_Tp __x)
525 { return std::signbit(__x); }
526
527 template <typename _Tp>
528 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isgreater(_Tp __x, _Tp __y)
529 { return std::isgreater(__x, __y); }
530
531 template <typename _Tp>
532 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isgreaterequal(_Tp __x,
533 _Tp __y)
534 { return std::isgreaterequal(__x, __y); }
535
536 template <typename _Tp>
537 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isless(_Tp __x, _Tp __y)
538 { return std::isless(__x, __y); }
539
540 template <typename _Tp>
541 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_islessequal(_Tp __x, _Tp __y)
542 { return std::islessequal(__x, __y); }
543
544 template <typename _Tp>
545 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_islessgreater(_Tp __x,
546 _Tp __y)
547 { return std::islessgreater(__x, __y); }
548
549 template <typename _Tp>
550 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isunordered(_Tp __x,
551 _Tp __y)
552 { return std::isunordered(__x, __y); }
553
554 // _S_increment & _S_decrement{{{2
555 template <typename _Tp>
556 constexpr static inline void _S_increment(_Tp& __x)
557 { ++__x; }
558
559 template <typename _Tp>
560 constexpr static inline void _S_decrement(_Tp& __x)
561 { --__x; }
562
563
564 // compares {{{2
565 template <typename _Tp>
566 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_equal_to(_Tp __x, _Tp __y)
567 { return __x == __y; }
568
569 template <typename _Tp>
570 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_not_equal_to(_Tp __x,
571 _Tp __y)
572 { return __x != __y; }
573
574 template <typename _Tp>
575 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_less(_Tp __x, _Tp __y)
576 { return __x < __y; }
577
578 template <typename _Tp>
579 _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_less_equal(_Tp __x,
580 _Tp __y)
581 { return __x <= __y; }
582
583 // smart_reference access {{{2
584 template <typename _Tp, typename _Up>
585 constexpr static void _S_set(_Tp& __v, [[maybe_unused]] int __i,
586 _Up&& __x) noexcept
587 {
588 _GLIBCXX_DEBUG_ASSERT(__i == 0);
589 __v = static_cast<_Up&&>(__x);
590 }
591
592 // _S_masked_assign {{{2
593 template <typename _Tp>
594 _GLIBCXX_SIMD_INTRINSIC constexpr static void
595 _S_masked_assign(bool __k, _Tp& __lhs, _Tp __rhs)
596 { if (__k) __lhs = __rhs; }
597
598 // _S_masked_cassign {{{2
599 template <typename _Op, typename _Tp>
600 _GLIBCXX_SIMD_INTRINSIC constexpr static void
601 _S_masked_cassign(const bool __k, _Tp& __lhs, const _Tp __rhs, _Op __op)
602 { if (__k) __lhs = __op(_SimdImplScalar{}, __lhs, __rhs); }
603
604 // _S_masked_unary {{{2
605 template <template <typename> class _Op, typename _Tp>
606 _GLIBCXX_SIMD_INTRINSIC constexpr static _Tp _S_masked_unary(const bool __k,
607 const _Tp __v)
608 { return static_cast<_Tp>(__k ? _Op<_Tp>{}(__v) : __v); }
609
610 // }}}2
611};
612
613// }}}
614// _MaskImplScalar {{{
615struct _MaskImplScalar
616{
617 // member types {{{
618 template <typename _Tp>
619 using _TypeTag = _Tp*;
620
621 // }}}
622 // _S_broadcast {{{
623 template <typename>
624 _GLIBCXX_SIMD_INTRINSIC static constexpr bool _S_broadcast(bool __x)
625 { return __x; }
626
627 // }}}
628 // _S_load {{{
629 template <typename>
630 _GLIBCXX_SIMD_INTRINSIC static constexpr bool _S_load(const bool* __mem)
631 { return __mem[0]; }
632
633 // }}}
634 // _S_to_bits {{{
635 _GLIBCXX_SIMD_INTRINSIC static constexpr _SanitizedBitMask<1>
636 _S_to_bits(bool __x)
637 { return __x; }
638
639 // }}}
640 // _S_convert {{{
641 template <typename, bool _Sanitized>
642 _GLIBCXX_SIMD_INTRINSIC static constexpr bool
643 _S_convert(_BitMask<1, _Sanitized> __x)
644 { return __x[0]; }
645
646 template <typename, typename _Up, typename _UAbi>
647 _GLIBCXX_SIMD_INTRINSIC static constexpr bool
648 _S_convert(simd_mask<_Up, _UAbi> __x)
649 { return __x[0]; }
650
651 // }}}
652 // _S_from_bitmask {{{2
653 template <typename _Tp>
654 _GLIBCXX_SIMD_INTRINSIC constexpr static bool
655 _S_from_bitmask(_SanitizedBitMask<1> __bits, _TypeTag<_Tp>) noexcept
656 { return __bits[0]; }
657
658 // _S_masked_load {{{2
659 _GLIBCXX_SIMD_INTRINSIC constexpr static bool
660 _S_masked_load(bool __merge, bool __mask, const bool* __mem) noexcept
661 {
662 if (__mask)
663 __merge = __mem[0];
664 return __merge;
665 }
666
667 // _S_store {{{2
668 _GLIBCXX_SIMD_INTRINSIC static void _S_store(bool __v, bool* __mem) noexcept
669 { __mem[0] = __v; }
670
671 // _S_masked_store {{{2
672 _GLIBCXX_SIMD_INTRINSIC static void
673 _S_masked_store(const bool __v, bool* __mem, const bool __k) noexcept
674 {
675 if (__k)
676 __mem[0] = __v;
677 }
678
679 // logical and bitwise operators {{{2
680 static constexpr bool _S_logical_and(bool __x, bool __y)
681 { return __x && __y; }
682
683 static constexpr bool _S_logical_or(bool __x, bool __y)
684 { return __x || __y; }
685
686 static constexpr bool _S_bit_not(bool __x)
687 { return !__x; }
688
689 static constexpr bool _S_bit_and(bool __x, bool __y)
690 { return __x && __y; }
691
692 static constexpr bool _S_bit_or(bool __x, bool __y)
693 { return __x || __y; }
694
695 static constexpr bool _S_bit_xor(bool __x, bool __y)
696 { return __x != __y; }
697
698 // smart_reference access {{{2
699 constexpr static void _S_set(bool& __k, [[maybe_unused]] int __i,
700 bool __x) noexcept
701 {
702 _GLIBCXX_DEBUG_ASSERT(__i == 0);
703 __k = __x;
704 }
705
706 // _S_masked_assign {{{2
707 _GLIBCXX_SIMD_INTRINSIC static void _S_masked_assign(bool __k, bool& __lhs,
708 bool __rhs)
709 {
710 if (__k)
711 __lhs = __rhs;
712 }
713
714 // }}}2
715 // _S_all_of {{{
716 template <typename _Tp, typename _Abi>
717 _GLIBCXX_SIMD_INTRINSIC constexpr static bool
718 _S_all_of(simd_mask<_Tp, _Abi> __k)
719 { return __k._M_data; }
720
721 // }}}
722 // _S_any_of {{{
723 template <typename _Tp, typename _Abi>
724 _GLIBCXX_SIMD_INTRINSIC constexpr static bool
725 _S_any_of(simd_mask<_Tp, _Abi> __k)
726 { return __k._M_data; }
727
728 // }}}
729 // _S_none_of {{{
730 template <typename _Tp, typename _Abi>
731 _GLIBCXX_SIMD_INTRINSIC constexpr static bool
732 _S_none_of(simd_mask<_Tp, _Abi> __k)
733 { return !__k._M_data; }
734
735 // }}}
736 // _S_some_of {{{
737 template <typename _Tp, typename _Abi>
738 _GLIBCXX_SIMD_INTRINSIC constexpr static bool
739 _S_some_of(simd_mask<_Tp, _Abi>)
740 { return false; }
741
742 // }}}
743 // _S_popcount {{{
744 template <typename _Tp, typename _Abi>
745 _GLIBCXX_SIMD_INTRINSIC constexpr static int
746 _S_popcount(simd_mask<_Tp, _Abi> __k)
747 { return __k._M_data; }
748
749 // }}}
750 // _S_find_first_set {{{
751 template <typename _Tp, typename _Abi>
752 _GLIBCXX_SIMD_INTRINSIC constexpr static int
753 _S_find_first_set(simd_mask<_Tp, _Abi>)
754 { return 0; }
755
756 // }}}
757 // _S_find_last_set {{{
758 template <typename _Tp, typename _Abi>
759 _GLIBCXX_SIMD_INTRINSIC constexpr static int
760 _S_find_last_set(simd_mask<_Tp, _Abi>)
761 { return 0; }
762
763 // }}}
764};
765
766// }}}
767
768_GLIBCXX_SIMD_END_NAMESPACE
769#endif // __cplusplus >= 201703L
770#endif // _GLIBCXX_EXPERIMENTAL_SIMD_SCALAR_H_
771
772// vim: foldmethod=marker sw=2 noet ts=8 sts=2 tw=80
Note: See TracBrowser for help on using the repository browser.