1 // Simd scalar ABI specific implementations -*- C++ -*-
3 // Copyright (C) 2020-2023 Free Software Foundation, Inc.
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)
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.
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.
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/>.
25 #ifndef _GLIBCXX_EXPERIMENTAL_SIMD_SCALAR_H_
26 #define _GLIBCXX_EXPERIMENTAL_SIMD_SCALAR_H_
27 #if __cplusplus >= 201703L
31 _GLIBCXX_SIMD_BEGIN_NAMESPACE
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.
37 template <typename _Tp
>
38 _GLIBCXX_SIMD_INTRINSIC
constexpr decltype(auto)
39 __promote_preserving_unsigned(const _Tp
& __x
)
41 if constexpr (is_signed_v
<decltype(+__x
)> && is_unsigned_v
<_Tp
>)
42 return static_cast<unsigned int>(__x
);
49 struct _CommonImplScalar
;
50 struct _CommonImplBuiltin
;
51 struct _SimdImplScalar
;
52 struct _MaskImplScalar
;
54 // simd_abi::_Scalar {{{
55 struct simd_abi::_Scalar
57 template <typename _Tp
>
58 static constexpr size_t _S_size
= 1;
60 template <typename _Tp
>
61 static constexpr size_t _S_full_size
= 1;
63 template <typename _Tp
>
64 static constexpr bool _S_is_partial
= false;
66 struct _IsValidAbiTag
: true_type
{};
68 template <typename _Tp
>
69 struct _IsValidSizeFor
: true_type
{};
71 template <typename _Tp
>
72 struct _IsValid
: __is_vectorizable
<_Tp
> {};
74 template <typename _Tp
>
75 static constexpr bool _S_is_valid_v
= _IsValid
<_Tp
>::value
;
77 _GLIBCXX_SIMD_INTRINSIC
static constexpr bool _S_masked(bool __x
)
80 using _CommonImpl
= _CommonImplScalar
;
81 using _SimdImpl
= _SimdImplScalar
;
82 using _MaskImpl
= _MaskImplScalar
;
84 template <typename _Tp
, bool = _S_is_valid_v
<_Tp
>>
85 struct __traits
: _InvalidTraits
{};
87 template <typename _Tp
>
88 struct __traits
<_Tp
, true>
90 using _IsValid
= true_type
;
91 using _SimdImpl
= _SimdImplScalar
;
92 using _MaskImpl
= _MaskImplScalar
;
93 using _SimdMember
= _Tp
;
94 using _MaskMember
= bool;
96 static constexpr size_t _S_simd_align
= alignof(_SimdMember
);
97 static constexpr size_t _S_mask_align
= alignof(_MaskMember
);
99 // nothing the user can spell converts to/from simd/simd_mask
100 struct _SimdCastType
{ _SimdCastType() = delete; };
101 struct _MaskCastType
{ _MaskCastType() = delete; };
108 // _CommonImplScalar {{{
109 struct _CommonImplScalar
112 template <typename _Tp
>
113 _GLIBCXX_SIMD_INTRINSIC
static void _S_store(_Tp __x
, void* __addr
)
114 { __builtin_memcpy(__addr
, &__x
, sizeof(_Tp
)); }
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
)
122 __make_dependent_t
<decltype(__x
), _CommonImplBuiltin
>::_S_store_bool_array(
130 // _SimdImplScalar {{{
131 struct _SimdImplScalar
134 using abi_type
= simd_abi::scalar
;
136 template <typename _Tp
>
137 using _TypeTag
= _Tp
*;
140 template <typename _Tp
>
141 _GLIBCXX_SIMD_INTRINSIC
static constexpr _Tp
_S_broadcast(_Tp __x
) noexcept
145 template <typename _Fp
, typename _Tp
>
146 _GLIBCXX_SIMD_INTRINSIC
static constexpr _Tp
_S_generator(_Fp
&& __gen
,
148 { return __gen(_SizeConstant
<0>()); }
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]); }
156 // _S_masked_load {{{2
157 template <typename _Tp
, typename _Up
>
158 _GLIBCXX_SIMD_INTRINSIC
159 static _Tp
_S_masked_load(_Tp __merge
, bool __k
,
160 const _Up
* __mem
) noexcept
163 __merge
= static_cast<_Tp
>(__mem
[0]);
168 template <typename _Tp
, typename _Up
>
169 _GLIBCXX_SIMD_INTRINSIC
170 static void _S_store(_Tp __v
, _Up
* __mem
, _TypeTag
<_Tp
>) noexcept
171 { __mem
[0] = static_cast<_Up
>(__v
); }
173 // _S_masked_store {{{2
174 template <typename _Tp
, typename _Up
>
175 _GLIBCXX_SIMD_INTRINSIC
176 static void _S_masked_store(const _Tp __v
, _Up
* __mem
,
177 const bool __k
) noexcept
178 { if (__k
) __mem
[0] = __v
; }
181 template <typename _Tp
>
182 _GLIBCXX_SIMD_INTRINSIC
183 static constexpr bool _S_negate(_Tp __x
) noexcept
187 template <typename _Tp
, typename _BinaryOperation
>
188 _GLIBCXX_SIMD_INTRINSIC
190 _S_reduce(const simd
<_Tp
, simd_abi::scalar
>& __x
, const _BinaryOperation
&)
191 { return __x
._M_data
; }
193 // _S_min, _S_max {{{2
194 template <typename _Tp
>
195 _GLIBCXX_SIMD_INTRINSIC
196 static constexpr _Tp
_S_min(const _Tp __a
, const _Tp __b
)
197 { return std::min(__a
, __b
); }
199 template <typename _Tp
>
200 _GLIBCXX_SIMD_INTRINSIC
201 static constexpr _Tp
_S_max(const _Tp __a
, const _Tp __b
)
202 { return std::max(__a
, __b
); }
204 // _S_complement {{{2
205 template <typename _Tp
>
206 _GLIBCXX_SIMD_INTRINSIC
207 static constexpr _Tp
_S_complement(_Tp __x
) noexcept
208 { return static_cast<_Tp
>(~__x
); }
210 // _S_unary_minus {{{2
211 template <typename _Tp
>
212 _GLIBCXX_SIMD_INTRINSIC
213 static constexpr _Tp
_S_unary_minus(_Tp __x
) noexcept
214 { return static_cast<_Tp
>(-__x
); }
216 // arithmetic operators {{{2
217 template <typename _Tp
>
218 _GLIBCXX_SIMD_INTRINSIC
219 static constexpr _Tp
_S_plus(_Tp __x
, _Tp __y
)
221 return static_cast<_Tp
>(__promote_preserving_unsigned(__x
)
222 + __promote_preserving_unsigned(__y
));
225 template <typename _Tp
>
226 _GLIBCXX_SIMD_INTRINSIC
227 static constexpr _Tp
_S_minus(_Tp __x
, _Tp __y
)
229 return static_cast<_Tp
>(__promote_preserving_unsigned(__x
)
230 - __promote_preserving_unsigned(__y
));
233 template <typename _Tp
>
234 _GLIBCXX_SIMD_INTRINSIC
235 static constexpr _Tp
_S_multiplies(_Tp __x
, _Tp __y
)
237 return static_cast<_Tp
>(__promote_preserving_unsigned(__x
)
238 * __promote_preserving_unsigned(__y
));
241 template <typename _Tp
>
242 _GLIBCXX_SIMD_INTRINSIC
243 static constexpr _Tp
_S_divides(_Tp __x
, _Tp __y
)
245 return static_cast<_Tp
>(__promote_preserving_unsigned(__x
)
246 / __promote_preserving_unsigned(__y
));
249 template <typename _Tp
>
250 _GLIBCXX_SIMD_INTRINSIC
251 static constexpr _Tp
_S_modulus(_Tp __x
, _Tp __y
)
253 return static_cast<_Tp
>(__promote_preserving_unsigned(__x
)
254 % __promote_preserving_unsigned(__y
));
257 template <typename _Tp
>
258 _GLIBCXX_SIMD_INTRINSIC
259 static constexpr _Tp
_S_bit_and(_Tp __x
, _Tp __y
)
261 if constexpr (is_floating_point_v
<_Tp
>)
263 using _Ip
= __int_for_sizeof_t
<_Tp
>;
264 return __bit_cast
<_Tp
>(__bit_cast
<_Ip
>(__x
) & __bit_cast
<_Ip
>(__y
));
267 return static_cast<_Tp
>(__promote_preserving_unsigned(__x
)
268 & __promote_preserving_unsigned(__y
));
271 template <typename _Tp
>
272 _GLIBCXX_SIMD_INTRINSIC
273 static constexpr _Tp
_S_bit_or(_Tp __x
, _Tp __y
)
275 if constexpr (is_floating_point_v
<_Tp
>)
277 using _Ip
= __int_for_sizeof_t
<_Tp
>;
278 return __bit_cast
<_Tp
>(__bit_cast
<_Ip
>(__x
) | __bit_cast
<_Ip
>(__y
));
281 return static_cast<_Tp
>(__promote_preserving_unsigned(__x
)
282 | __promote_preserving_unsigned(__y
));
285 template <typename _Tp
>
286 _GLIBCXX_SIMD_INTRINSIC
287 static constexpr _Tp
_S_bit_xor(_Tp __x
, _Tp __y
)
289 if constexpr (is_floating_point_v
<_Tp
>)
291 using _Ip
= __int_for_sizeof_t
<_Tp
>;
292 return __bit_cast
<_Tp
>(__bit_cast
<_Ip
>(__x
) ^ __bit_cast
<_Ip
>(__y
));
295 return static_cast<_Tp
>(__promote_preserving_unsigned(__x
)
296 ^ __promote_preserving_unsigned(__y
));
299 template <typename _Tp
>
300 _GLIBCXX_SIMD_INTRINSIC
301 static constexpr _Tp
_S_bit_shift_left(_Tp __x
, int __y
)
302 { return static_cast<_Tp
>(__promote_preserving_unsigned(__x
) << __y
); }
304 template <typename _Tp
>
305 _GLIBCXX_SIMD_INTRINSIC
306 static constexpr _Tp
_S_bit_shift_right(_Tp __x
, int __y
)
307 { return static_cast<_Tp
>(__promote_preserving_unsigned(__x
) >> __y
); }
310 // frexp, modf and copysign implemented in simd_math.h
311 template <typename _Tp
>
312 using _ST
= _SimdTuple
<_Tp
, simd_abi::scalar
>;
314 template <typename _Tp
>
315 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_acos(_Tp __x
)
316 { return std::acos(__x
); }
318 template <typename _Tp
>
319 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_asin(_Tp __x
)
320 { return std::asin(__x
); }
322 template <typename _Tp
>
323 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_atan(_Tp __x
)
324 { return std::atan(__x
); }
326 template <typename _Tp
>
327 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_cos(_Tp __x
)
328 { return std::cos(__x
); }
330 template <typename _Tp
>
331 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_sin(_Tp __x
)
332 { return std::sin(__x
); }
334 template <typename _Tp
>
335 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_tan(_Tp __x
)
336 { return std::tan(__x
); }
338 template <typename _Tp
>
339 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_acosh(_Tp __x
)
340 { return std::acosh(__x
); }
342 template <typename _Tp
>
343 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_asinh(_Tp __x
)
344 { return std::asinh(__x
); }
346 template <typename _Tp
>
347 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_atanh(_Tp __x
)
348 { return std::atanh(__x
); }
350 template <typename _Tp
>
351 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_cosh(_Tp __x
)
352 { return std::cosh(__x
); }
354 template <typename _Tp
>
355 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_sinh(_Tp __x
)
356 { return std::sinh(__x
); }
358 template <typename _Tp
>
359 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_tanh(_Tp __x
)
360 { return std::tanh(__x
); }
362 template <typename _Tp
>
363 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_atan2(_Tp __x
, _Tp __y
)
364 { return std::atan2(__x
, __y
); }
366 template <typename _Tp
>
367 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_exp(_Tp __x
)
368 { return std::exp(__x
); }
370 template <typename _Tp
>
371 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_exp2(_Tp __x
)
372 { return std::exp2(__x
); }
374 template <typename _Tp
>
375 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_expm1(_Tp __x
)
376 { return std::expm1(__x
); }
378 template <typename _Tp
>
379 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_log(_Tp __x
)
380 { return std::log(__x
); }
382 template <typename _Tp
>
383 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_log10(_Tp __x
)
384 { return std::log10(__x
); }
386 template <typename _Tp
>
387 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_log1p(_Tp __x
)
388 { return std::log1p(__x
); }
390 template <typename _Tp
>
391 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_log2(_Tp __x
)
392 { return std::log2(__x
); }
394 template <typename _Tp
>
395 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_logb(_Tp __x
)
396 { return std::logb(__x
); }
398 template <typename _Tp
>
399 _GLIBCXX_SIMD_INTRINSIC
static _ST
<int> _S_ilogb(_Tp __x
)
400 { return {std::ilogb(__x
)}; }
402 template <typename _Tp
>
403 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_pow(_Tp __x
, _Tp __y
)
404 { return std::pow(__x
, __y
); }
406 template <typename _Tp
>
407 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_abs(_Tp __x
)
408 { return std::abs(__x
); }
410 template <typename _Tp
>
411 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_fabs(_Tp __x
)
412 { return std::fabs(__x
); }
414 template <typename _Tp
>
415 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_sqrt(_Tp __x
)
416 { return std::sqrt(__x
); }
418 template <typename _Tp
>
419 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_cbrt(_Tp __x
)
420 { return std::cbrt(__x
); }
422 template <typename _Tp
>
423 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_erf(_Tp __x
)
424 { return std::erf(__x
); }
426 template <typename _Tp
>
427 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_erfc(_Tp __x
)
428 { return std::erfc(__x
); }
430 template <typename _Tp
>
431 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_lgamma(_Tp __x
)
432 { return std::lgamma(__x
); }
434 template <typename _Tp
>
435 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_tgamma(_Tp __x
)
436 { return std::tgamma(__x
); }
438 template <typename _Tp
>
439 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_trunc(_Tp __x
)
440 { return std::trunc(__x
); }
442 template <typename _Tp
>
443 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_floor(_Tp __x
)
444 { return std::floor(__x
); }
446 template <typename _Tp
>
447 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_ceil(_Tp __x
)
448 { return std::ceil(__x
); }
450 template <typename _Tp
>
451 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_nearbyint(_Tp __x
)
452 { return std::nearbyint(__x
); }
454 template <typename _Tp
>
455 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_rint(_Tp __x
)
456 { return std::rint(__x
); }
458 template <typename _Tp
>
459 _GLIBCXX_SIMD_INTRINSIC
static _ST
<long> _S_lrint(_Tp __x
)
460 { return {std::lrint(__x
)}; }
462 template <typename _Tp
>
463 _GLIBCXX_SIMD_INTRINSIC
static _ST
<long long> _S_llrint(_Tp __x
)
464 { return {std::llrint(__x
)}; }
466 template <typename _Tp
>
467 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_round(_Tp __x
)
468 { return std::round(__x
); }
470 template <typename _Tp
>
471 _GLIBCXX_SIMD_INTRINSIC
static _ST
<long> _S_lround(_Tp __x
)
472 { return {std::lround(__x
)}; }
474 template <typename _Tp
>
475 _GLIBCXX_SIMD_INTRINSIC
static _ST
<long long> _S_llround(_Tp __x
)
476 { return {std::llround(__x
)}; }
478 template <typename _Tp
>
479 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_ldexp(_Tp __x
, _ST
<int> __y
)
480 { return std::ldexp(__x
, __y
.first
); }
482 template <typename _Tp
>
483 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_scalbn(_Tp __x
, _ST
<int> __y
)
484 { return std::scalbn(__x
, __y
.first
); }
486 template <typename _Tp
>
487 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_scalbln(_Tp __x
, _ST
<long> __y
)
488 { return std::scalbln(__x
, __y
.first
); }
490 template <typename _Tp
>
491 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_fmod(_Tp __x
, _Tp __y
)
492 { return std::fmod(__x
, __y
); }
494 template <typename _Tp
>
495 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_remainder(_Tp __x
, _Tp __y
)
496 { return std::remainder(__x
, __y
); }
498 template <typename _Tp
>
499 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_nextafter(_Tp __x
, _Tp __y
)
500 { return std::nextafter(__x
, __y
); }
502 template <typename _Tp
>
503 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_fdim(_Tp __x
, _Tp __y
)
504 { return std::fdim(__x
, __y
); }
506 template <typename _Tp
>
507 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_fmax(_Tp __x
, _Tp __y
)
508 { return std::fmax(__x
, __y
); }
510 template <typename _Tp
>
511 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_fmin(_Tp __x
, _Tp __y
)
512 { return std::fmin(__x
, __y
); }
514 template <typename _Tp
>
515 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_fma(_Tp __x
, _Tp __y
, _Tp __z
)
516 { return std::fma(__x
, __y
, __z
); }
518 template <typename _Tp
>
519 _GLIBCXX_SIMD_INTRINSIC
static _Tp
_S_remquo(_Tp __x
, _Tp __y
, _ST
<int>* __z
)
520 { return std::remquo(__x
, __y
, &__z
->first
); }
522 template <typename _Tp
>
523 _GLIBCXX_SIMD_INTRINSIC
constexpr static _ST
<int> _S_fpclassify(_Tp __x
)
524 { return {std::fpclassify(__x
)}; }
526 template <typename _Tp
>
527 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_isfinite(_Tp __x
)
528 { return std::isfinite(__x
); }
530 template <typename _Tp
>
531 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_isinf(_Tp __x
)
532 { return std::isinf(__x
); }
534 template <typename _Tp
>
535 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_isnan(_Tp __x
)
536 { return std::isnan(__x
); }
538 template <typename _Tp
>
539 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_isnormal(_Tp __x
)
540 { return std::isnormal(__x
); }
542 template <typename _Tp
>
543 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_signbit(_Tp __x
)
544 { return std::signbit(__x
); }
546 template <typename _Tp
>
547 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_isgreater(_Tp __x
, _Tp __y
)
548 { return std::isgreater(__x
, __y
); }
550 template <typename _Tp
>
551 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_isgreaterequal(_Tp __x
,
553 { return std::isgreaterequal(__x
, __y
); }
555 template <typename _Tp
>
556 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_isless(_Tp __x
, _Tp __y
)
557 { return std::isless(__x
, __y
); }
559 template <typename _Tp
>
560 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_islessequal(_Tp __x
, _Tp __y
)
561 { return std::islessequal(__x
, __y
); }
563 template <typename _Tp
>
564 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_islessgreater(_Tp __x
,
566 { return std::islessgreater(__x
, __y
); }
568 template <typename _Tp
>
569 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_isunordered(_Tp __x
,
571 { return std::isunordered(__x
, __y
); }
573 // _S_increment & _S_decrement{{{2
574 template <typename _Tp
>
575 _GLIBCXX_SIMD_INTRINSIC
576 constexpr static void _S_increment(_Tp
& __x
)
579 template <typename _Tp
>
580 _GLIBCXX_SIMD_INTRINSIC
581 constexpr static void _S_decrement(_Tp
& __x
)
586 template <typename _Tp
>
587 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_equal_to(_Tp __x
, _Tp __y
)
588 { return __x
== __y
; }
590 template <typename _Tp
>
591 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_not_equal_to(_Tp __x
,
593 { return __x
!= __y
; }
595 template <typename _Tp
>
596 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_less(_Tp __x
, _Tp __y
)
597 { return __x
< __y
; }
599 template <typename _Tp
>
600 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool _S_less_equal(_Tp __x
,
602 { return __x
<= __y
; }
604 // smart_reference access {{{2
605 template <typename _Tp
, typename _Up
>
606 _GLIBCXX_SIMD_INTRINSIC
607 constexpr static void _S_set(_Tp
& __v
, [[maybe_unused
]] int __i
,
610 _GLIBCXX_DEBUG_ASSERT(__i
== 0);
611 __v
= static_cast<_Up
&&>(__x
);
614 // _S_masked_assign {{{2
615 template <typename _Tp
>
616 _GLIBCXX_SIMD_INTRINSIC
constexpr static void
617 _S_masked_assign(bool __k
, _Tp
& __lhs
, _Tp __rhs
)
618 { if (__k
) __lhs
= __rhs
; }
620 // _S_masked_cassign {{{2
621 template <typename _Op
, typename _Tp
>
622 _GLIBCXX_SIMD_INTRINSIC
constexpr static void
623 _S_masked_cassign(const bool __k
, _Tp
& __lhs
, const _Tp __rhs
, _Op __op
)
624 { if (__k
) __lhs
= __op(_SimdImplScalar
{}, __lhs
, __rhs
); }
626 // _S_masked_unary {{{2
627 template <template <typename
> class _Op
, typename _Tp
>
628 _GLIBCXX_SIMD_INTRINSIC
constexpr static _Tp
_S_masked_unary(const bool __k
,
630 { return static_cast<_Tp
>(__k
? _Op
<_Tp
>{}(__v
) : __v
); }
636 // _MaskImplScalar {{{
637 struct _MaskImplScalar
640 template <typename _Tp
>
641 using _TypeTag
= _Tp
*;
646 _GLIBCXX_SIMD_INTRINSIC
static constexpr bool _S_broadcast(bool __x
)
652 _GLIBCXX_SIMD_INTRINSIC
static constexpr bool _S_load(const bool* __mem
)
657 _GLIBCXX_SIMD_INTRINSIC
static constexpr _SanitizedBitMask
<1>
663 template <typename
, bool _Sanitized
>
664 _GLIBCXX_SIMD_INTRINSIC
static constexpr bool
665 _S_convert(_BitMask
<1, _Sanitized
> __x
)
668 template <typename
, typename _Up
, typename _UAbi
>
669 _GLIBCXX_SIMD_INTRINSIC
static constexpr bool
670 _S_convert(simd_mask
<_Up
, _UAbi
> __x
)
674 // _S_from_bitmask {{{2
675 template <typename _Tp
>
676 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool
677 _S_from_bitmask(_SanitizedBitMask
<1> __bits
, _TypeTag
<_Tp
>) noexcept
678 { return __bits
[0]; }
680 // _S_masked_load {{{2
681 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool
682 _S_masked_load(bool __merge
, bool __mask
, const bool* __mem
) noexcept
690 _GLIBCXX_SIMD_INTRINSIC
static void _S_store(bool __v
, bool* __mem
) noexcept
693 // _S_masked_store {{{2
694 _GLIBCXX_SIMD_INTRINSIC
static void
695 _S_masked_store(const bool __v
, bool* __mem
, const bool __k
) noexcept
701 // logical and bitwise operators {{{2
702 _GLIBCXX_SIMD_INTRINSIC
703 static constexpr bool _S_logical_and(bool __x
, bool __y
)
704 { return __x
&& __y
; }
706 _GLIBCXX_SIMD_INTRINSIC
707 static constexpr bool _S_logical_or(bool __x
, bool __y
)
708 { return __x
|| __y
; }
710 _GLIBCXX_SIMD_INTRINSIC
711 static constexpr bool _S_bit_not(bool __x
)
714 _GLIBCXX_SIMD_INTRINSIC
715 static constexpr bool _S_bit_and(bool __x
, bool __y
)
716 { return __x
&& __y
; }
718 _GLIBCXX_SIMD_INTRINSIC
719 static constexpr bool _S_bit_or(bool __x
, bool __y
)
720 { return __x
|| __y
; }
722 _GLIBCXX_SIMD_INTRINSIC
723 static constexpr bool _S_bit_xor(bool __x
, bool __y
)
724 { return __x
!= __y
; }
726 // smart_reference access {{{2
727 _GLIBCXX_SIMD_INTRINSIC
728 constexpr static void _S_set(bool& __k
, [[maybe_unused
]] int __i
,
731 _GLIBCXX_DEBUG_ASSERT(__i
== 0);
735 // _S_masked_assign {{{2
736 _GLIBCXX_SIMD_INTRINSIC
static void _S_masked_assign(bool __k
, bool& __lhs
,
745 template <typename _Tp
, typename _Abi
>
746 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool
747 _S_all_of(simd_mask
<_Tp
, _Abi
> __k
)
748 { return __k
._M_data
; }
752 template <typename _Tp
, typename _Abi
>
753 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool
754 _S_any_of(simd_mask
<_Tp
, _Abi
> __k
)
755 { return __k
._M_data
; }
759 template <typename _Tp
, typename _Abi
>
760 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool
761 _S_none_of(simd_mask
<_Tp
, _Abi
> __k
)
762 { return !__k
._M_data
; }
766 template <typename _Tp
, typename _Abi
>
767 _GLIBCXX_SIMD_INTRINSIC
constexpr static bool
768 _S_some_of(simd_mask
<_Tp
, _Abi
>)
773 template <typename _Tp
, typename _Abi
>
774 _GLIBCXX_SIMD_INTRINSIC
constexpr static int
775 _S_popcount(simd_mask
<_Tp
, _Abi
> __k
)
776 { return __k
._M_data
; }
779 // _S_find_first_set {{{
780 template <typename _Tp
, typename _Abi
>
781 _GLIBCXX_SIMD_INTRINSIC
constexpr static int
782 _S_find_first_set(simd_mask
<_Tp
, _Abi
>)
786 // _S_find_last_set {{{
787 template <typename _Tp
, typename _Abi
>
788 _GLIBCXX_SIMD_INTRINSIC
constexpr static int
789 _S_find_last_set(simd_mask
<_Tp
, _Abi
>)
797 _GLIBCXX_SIMD_END_NAMESPACE
798 #endif // __cplusplus >= 201703L
799 #endif // _GLIBCXX_EXPERIMENTAL_SIMD_SCALAR_H_
801 // vim: foldmethod=marker sw=2 noet ts=8 sts=2 tw=80