xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/experimental/bits/simd_scalar.h (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 // Simd scalar ABI specific implementations -*- C++ -*-
2 
3 // Copyright (C) 2020-2022 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.
37 template <typename _Tp>
decltype(auto)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 
49 struct _CommonImplScalar;
50 struct _CommonImplBuiltin;
51 struct _SimdImplScalar;
52 struct _MaskImplScalar;
53 
54 // simd_abi::_Scalar {{{
55 struct 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_Scalar78   _S_masked(bool __x)
79   { return __x; }
80 
81   using _CommonImpl = _CommonImplScalar;
82   using _SimdImpl = _SimdImplScalar;
83   using _MaskImpl = _MaskImplScalar;
84 
85   template <typename _Tp, bool = _S_is_valid_v<_Tp>>
86     struct __traits : _InvalidTraits {};
87 
88   template <typename _Tp>
89     struct __traits<_Tp, true>
90     {
91       using _IsValid = true_type;
92       using _SimdImpl = _SimdImplScalar;
93       using _MaskImpl = _MaskImplScalar;
94       using _SimdMember = _Tp;
95       using _MaskMember = bool;
96 
97       static constexpr size_t _S_simd_align = alignof(_SimdMember);
98       static constexpr size_t _S_mask_align = alignof(_MaskMember);
99 
100       // nothing the user can spell converts to/from simd/simd_mask
101       struct _SimdCastType { _SimdCastType() = delete; };
102       struct _MaskCastType { _MaskCastType() = delete; };
103       struct _SimdBase {};
104       struct _MaskBase {};
105     };
106 };
107 
108 // }}}
109 // _CommonImplScalar {{{
110 struct _CommonImplScalar
111 {
112   // _S_store {{{
113   template <typename _Tp>
114     _GLIBCXX_SIMD_INTRINSIC static void
115     _S_store(_Tp __x, void* __addr)
116     { __builtin_memcpy(__addr, &__x, sizeof(_Tp)); }
117 
118   // }}}
119   // _S_store_bool_array(_BitMask) {{{
120   template <size_t _Np, bool _Sanitized>
121     _GLIBCXX_SIMD_INTRINSIC static constexpr void
122     _S_store_bool_array(_BitMask<_Np, _Sanitized> __x, bool* __mem)
123     {
124       __make_dependent_t<decltype(__x), _CommonImplBuiltin>::_S_store_bool_array(
125 	__x, __mem);
126     }
127 
128   // }}}
129 };
130 
131 // }}}
132 // _SimdImplScalar {{{
133 struct _SimdImplScalar
134 {
135   // member types {{{2
136   using abi_type = simd_abi::scalar;
137 
138   template <typename _Tp>
139     using _TypeTag = _Tp*;
140 
141   // _S_broadcast {{{2
142   template <typename _Tp>
143     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
144     _S_broadcast(_Tp __x) noexcept
145     { return __x; }
146 
147   // _S_generator {{{2
148   template <typename _Fp, typename _Tp>
149     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
150     _S_generator(_Fp&& __gen, _TypeTag<_Tp>)
151     { return __gen(_SizeConstant<0>()); }
152 
153   // _S_load {{{2
154   template <typename _Tp, typename _Up>
155     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
156     _S_load(const _Up* __mem, _TypeTag<_Tp>) noexcept
157     { return static_cast<_Tp>(__mem[0]); }
158 
159   // _S_masked_load {{{2
160   template <typename _Tp, typename _Up>
161     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
162     _S_masked_load(_Tp __merge, bool __k, const _Up* __mem) noexcept
163     {
164       if (__k)
165 	__merge = static_cast<_Tp>(__mem[0]);
166       return __merge;
167     }
168 
169   // _S_store {{{2
170   template <typename _Tp, typename _Up>
171     _GLIBCXX_SIMD_INTRINSIC static constexpr void
172     _S_store(_Tp __v, _Up* __mem, _TypeTag<_Tp>) noexcept
173     { __mem[0] = static_cast<_Up>(__v); }
174 
175   // _S_masked_store {{{2
176   template <typename _Tp, typename _Up>
177     _GLIBCXX_SIMD_INTRINSIC static constexpr void
178     _S_masked_store(const _Tp __v, _Up* __mem, const bool __k) noexcept
179     { if (__k) __mem[0] = __v; }
180 
181   // _S_negate {{{2
182   template <typename _Tp>
183     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
184     _S_negate(_Tp __x) noexcept
185     { return !__x; }
186 
187   // _S_reduce {{{2
188   template <typename _Tp, typename _BinaryOperation>
189     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
190     _S_reduce(const simd<_Tp, simd_abi::scalar>& __x, const _BinaryOperation&)
191     { return __x._M_data; }
192 
193   // _S_min, _S_max {{{2
194   template <typename _Tp>
195     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
196     _S_min(const _Tp __a, const _Tp __b)
197     { return std::min(__a, __b); }
198 
199   template <typename _Tp>
200     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
201     _S_max(const _Tp __a, const _Tp __b)
202     { return std::max(__a, __b); }
203 
204   // _S_complement {{{2
205   template <typename _Tp>
206     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
207     _S_complement(_Tp __x) noexcept
208     { return static_cast<_Tp>(~__x); }
209 
210   // _S_unary_minus {{{2
211   template <typename _Tp>
212     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
213     _S_unary_minus(_Tp __x) noexcept
214     { return static_cast<_Tp>(-__x); }
215 
216   // arithmetic operators {{{2
217   template <typename _Tp>
218     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
219     _S_plus(_Tp __x, _Tp __y)
220     {
221       return static_cast<_Tp>(__promote_preserving_unsigned(__x)
222 			      + __promote_preserving_unsigned(__y));
223     }
224 
225   template <typename _Tp>
226     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
227     _S_minus(_Tp __x, _Tp __y)
228     {
229       return static_cast<_Tp>(__promote_preserving_unsigned(__x)
230 			      - __promote_preserving_unsigned(__y));
231     }
232 
233   template <typename _Tp>
234     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
235     _S_multiplies(_Tp __x, _Tp __y)
236     {
237       return static_cast<_Tp>(__promote_preserving_unsigned(__x)
238 			      * __promote_preserving_unsigned(__y));
239     }
240 
241   template <typename _Tp>
242     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
243     _S_divides(_Tp __x, _Tp __y)
244     {
245       return static_cast<_Tp>(__promote_preserving_unsigned(__x)
246 			      / __promote_preserving_unsigned(__y));
247     }
248 
249   template <typename _Tp>
250     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
251     _S_modulus(_Tp __x, _Tp __y)
252     {
253       return static_cast<_Tp>(__promote_preserving_unsigned(__x)
254 			      % __promote_preserving_unsigned(__y));
255     }
256 
257   template <typename _Tp>
258     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
259     _S_bit_and(_Tp __x, _Tp __y)
260     {
261       if constexpr (is_floating_point_v<_Tp>)
262 	{
263 	  using _Ip = __int_for_sizeof_t<_Tp>;
264 	  return __bit_cast<_Tp>(__bit_cast<_Ip>(__x) & __bit_cast<_Ip>(__y));
265 	}
266       else
267 	return static_cast<_Tp>(__promote_preserving_unsigned(__x)
268 				& __promote_preserving_unsigned(__y));
269     }
270 
271   template <typename _Tp>
272     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
273     _S_bit_or(_Tp __x, _Tp __y)
274     {
275       if constexpr (is_floating_point_v<_Tp>)
276 	{
277 	  using _Ip = __int_for_sizeof_t<_Tp>;
278 	  return __bit_cast<_Tp>(__bit_cast<_Ip>(__x) | __bit_cast<_Ip>(__y));
279 	}
280       else
281 	return static_cast<_Tp>(__promote_preserving_unsigned(__x)
282 				| __promote_preserving_unsigned(__y));
283     }
284 
285   template <typename _Tp>
286     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
287     _S_bit_xor(_Tp __x, _Tp __y)
288     {
289       if constexpr (is_floating_point_v<_Tp>)
290 	{
291 	  using _Ip = __int_for_sizeof_t<_Tp>;
292 	  return __bit_cast<_Tp>(__bit_cast<_Ip>(__x) ^ __bit_cast<_Ip>(__y));
293 	}
294       else
295 	return static_cast<_Tp>(__promote_preserving_unsigned(__x)
296 				^ __promote_preserving_unsigned(__y));
297     }
298 
299   template <typename _Tp>
300     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
301     _S_bit_shift_left(_Tp __x, int __y)
302     { return static_cast<_Tp>(__promote_preserving_unsigned(__x) << __y); }
303 
304   template <typename _Tp>
305     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
306     _S_bit_shift_right(_Tp __x, int __y)
307     { return static_cast<_Tp>(__promote_preserving_unsigned(__x) >> __y); }
308 
309   // math {{{2
310   // frexp, modf and copysign implemented in simd_math.h
311   template <typename _Tp>
312     using _ST = _SimdTuple<_Tp, simd_abi::scalar>;
313 
314   template <typename _Tp>
315     _GLIBCXX_SIMD_INTRINSIC static _Tp
316     _S_acos(_Tp __x)
317     { return std::acos(__x); }
318 
319   template <typename _Tp>
320     _GLIBCXX_SIMD_INTRINSIC static _Tp
321     _S_asin(_Tp __x)
322     { return std::asin(__x); }
323 
324   template <typename _Tp>
325     _GLIBCXX_SIMD_INTRINSIC static _Tp
326     _S_atan(_Tp __x)
327     { return std::atan(__x); }
328 
329   template <typename _Tp>
330     _GLIBCXX_SIMD_INTRINSIC static _Tp
331     _S_cos(_Tp __x)
332     { return std::cos(__x); }
333 
334   template <typename _Tp>
335     _GLIBCXX_SIMD_INTRINSIC static _Tp
336     _S_sin(_Tp __x)
337     { return std::sin(__x); }
338 
339   template <typename _Tp>
340     _GLIBCXX_SIMD_INTRINSIC static _Tp
341     _S_tan(_Tp __x)
342     { return std::tan(__x); }
343 
344   template <typename _Tp>
345     _GLIBCXX_SIMD_INTRINSIC static _Tp
346     _S_acosh(_Tp __x)
347     { return std::acosh(__x); }
348 
349   template <typename _Tp>
350     _GLIBCXX_SIMD_INTRINSIC static _Tp
351     _S_asinh(_Tp __x)
352     { return std::asinh(__x); }
353 
354   template <typename _Tp>
355     _GLIBCXX_SIMD_INTRINSIC static _Tp
356     _S_atanh(_Tp __x)
357     { return std::atanh(__x); }
358 
359   template <typename _Tp>
360     _GLIBCXX_SIMD_INTRINSIC static _Tp
361     _S_cosh(_Tp __x)
362     { return std::cosh(__x); }
363 
364   template <typename _Tp>
365     _GLIBCXX_SIMD_INTRINSIC static _Tp
366     _S_sinh(_Tp __x)
367     { return std::sinh(__x); }
368 
369   template <typename _Tp>
370     _GLIBCXX_SIMD_INTRINSIC static _Tp
371     _S_tanh(_Tp __x)
372     { return std::tanh(__x); }
373 
374   template <typename _Tp>
375     _GLIBCXX_SIMD_INTRINSIC static _Tp
376     _S_atan2(_Tp __x, _Tp __y)
377     { return std::atan2(__x, __y); }
378 
379   template <typename _Tp>
380     _GLIBCXX_SIMD_INTRINSIC static _Tp
381     _S_exp(_Tp __x)
382     { return std::exp(__x); }
383 
384   template <typename _Tp>
385     _GLIBCXX_SIMD_INTRINSIC static _Tp
386     _S_exp2(_Tp __x)
387     { return std::exp2(__x); }
388 
389   template <typename _Tp>
390     _GLIBCXX_SIMD_INTRINSIC static _Tp
391     _S_expm1(_Tp __x)
392     { return std::expm1(__x); }
393 
394   template <typename _Tp>
395     _GLIBCXX_SIMD_INTRINSIC static _Tp
396     _S_log(_Tp __x)
397     { return std::log(__x); }
398 
399   template <typename _Tp>
400     _GLIBCXX_SIMD_INTRINSIC static _Tp
401     _S_log10(_Tp __x)
402     { return std::log10(__x); }
403 
404   template <typename _Tp>
405     _GLIBCXX_SIMD_INTRINSIC static _Tp
406     _S_log1p(_Tp __x)
407     { return std::log1p(__x); }
408 
409   template <typename _Tp>
410     _GLIBCXX_SIMD_INTRINSIC static _Tp
411     _S_log2(_Tp __x)
412     { return std::log2(__x); }
413 
414   template <typename _Tp>
415     _GLIBCXX_SIMD_INTRINSIC static _Tp
416     _S_logb(_Tp __x)
417     { return std::logb(__x); }
418 
419   template <typename _Tp>
420     _GLIBCXX_SIMD_INTRINSIC static _ST<int>
421     _S_ilogb(_Tp __x)
422     { return {std::ilogb(__x)}; }
423 
424   template <typename _Tp>
425     _GLIBCXX_SIMD_INTRINSIC static _Tp
426     _S_pow(_Tp __x, _Tp __y)
427     { return std::pow(__x, __y); }
428 
429   template <typename _Tp>
430     _GLIBCXX_SIMD_INTRINSIC static _Tp
431     _S_abs(_Tp __x)
432     { return std::abs(__x); }
433 
434   template <typename _Tp>
435     _GLIBCXX_SIMD_INTRINSIC static _Tp
436     _S_fabs(_Tp __x)
437     { return std::fabs(__x); }
438 
439   template <typename _Tp>
440     _GLIBCXX_SIMD_INTRINSIC static _Tp
441     _S_sqrt(_Tp __x)
442     { return std::sqrt(__x); }
443 
444   template <typename _Tp>
445     _GLIBCXX_SIMD_INTRINSIC static _Tp
446     _S_cbrt(_Tp __x)
447     { return std::cbrt(__x); }
448 
449   template <typename _Tp>
450     _GLIBCXX_SIMD_INTRINSIC static _Tp
451     _S_erf(_Tp __x)
452     { return std::erf(__x); }
453 
454   template <typename _Tp>
455     _GLIBCXX_SIMD_INTRINSIC static _Tp
456     _S_erfc(_Tp __x)
457     { return std::erfc(__x); }
458 
459   template <typename _Tp>
460     _GLIBCXX_SIMD_INTRINSIC static _Tp
461     _S_lgamma(_Tp __x)
462     { return std::lgamma(__x); }
463 
464   template <typename _Tp>
465     _GLIBCXX_SIMD_INTRINSIC static _Tp
466     _S_tgamma(_Tp __x)
467     { return std::tgamma(__x); }
468 
469   template <typename _Tp>
470     _GLIBCXX_SIMD_INTRINSIC static _Tp
471     _S_trunc(_Tp __x)
472     { return std::trunc(__x); }
473 
474   template <typename _Tp>
475     _GLIBCXX_SIMD_INTRINSIC static _Tp
476     _S_floor(_Tp __x)
477     { return std::floor(__x); }
478 
479   template <typename _Tp>
480     _GLIBCXX_SIMD_INTRINSIC static _Tp
481     _S_ceil(_Tp __x)
482     { return std::ceil(__x); }
483 
484   template <typename _Tp>
485     _GLIBCXX_SIMD_INTRINSIC static _Tp
486     _S_nearbyint(_Tp __x)
487     { return std::nearbyint(__x); }
488 
489   template <typename _Tp>
490     _GLIBCXX_SIMD_INTRINSIC static _Tp
491     _S_rint(_Tp __x)
492     { return std::rint(__x); }
493 
494   template <typename _Tp>
495     _GLIBCXX_SIMD_INTRINSIC static _ST<long>
496     _S_lrint(_Tp __x)
497     { return {std::lrint(__x)}; }
498 
499   template <typename _Tp>
500     _GLIBCXX_SIMD_INTRINSIC static _ST<long long>
501     _S_llrint(_Tp __x)
502     { return {std::llrint(__x)}; }
503 
504   template <typename _Tp>
505     _GLIBCXX_SIMD_INTRINSIC static _Tp
506     _S_round(_Tp __x)
507     { return std::round(__x); }
508 
509   template <typename _Tp>
510     _GLIBCXX_SIMD_INTRINSIC static _ST<long>
511     _S_lround(_Tp __x)
512     { return {std::lround(__x)}; }
513 
514   template <typename _Tp>
515     _GLIBCXX_SIMD_INTRINSIC static _ST<long long>
516     _S_llround(_Tp __x)
517     { return {std::llround(__x)}; }
518 
519   template <typename _Tp>
520     _GLIBCXX_SIMD_INTRINSIC static _Tp
521     _S_ldexp(_Tp __x, _ST<int> __y)
522     { return std::ldexp(__x, __y.first); }
523 
524   template <typename _Tp>
525     _GLIBCXX_SIMD_INTRINSIC static _Tp
526     _S_scalbn(_Tp __x, _ST<int> __y)
527     { return std::scalbn(__x, __y.first); }
528 
529   template <typename _Tp>
530     _GLIBCXX_SIMD_INTRINSIC static _Tp
531     _S_scalbln(_Tp __x, _ST<long> __y)
532     { return std::scalbln(__x, __y.first); }
533 
534   template <typename _Tp>
535     _GLIBCXX_SIMD_INTRINSIC static _Tp
536     _S_fmod(_Tp __x, _Tp __y)
537     { return std::fmod(__x, __y); }
538 
539   template <typename _Tp>
540     _GLIBCXX_SIMD_INTRINSIC static _Tp
541     _S_remainder(_Tp __x, _Tp __y)
542     { return std::remainder(__x, __y); }
543 
544   template <typename _Tp>
545     _GLIBCXX_SIMD_INTRINSIC static _Tp
546     _S_nextafter(_Tp __x, _Tp __y)
547     { return std::nextafter(__x, __y); }
548 
549   template <typename _Tp>
550     _GLIBCXX_SIMD_INTRINSIC static _Tp
551     _S_fdim(_Tp __x, _Tp __y)
552     { return std::fdim(__x, __y); }
553 
554   template <typename _Tp>
555     _GLIBCXX_SIMD_INTRINSIC static _Tp
556     _S_fmax(_Tp __x, _Tp __y)
557     { return std::fmax(__x, __y); }
558 
559   template <typename _Tp>
560     _GLIBCXX_SIMD_INTRINSIC static _Tp
561     _S_fmin(_Tp __x, _Tp __y)
562     { return std::fmin(__x, __y); }
563 
564   template <typename _Tp>
565     _GLIBCXX_SIMD_INTRINSIC static _Tp
566     _S_fma(_Tp __x, _Tp __y, _Tp __z)
567     { return std::fma(__x, __y, __z); }
568 
569   template <typename _Tp>
570     _GLIBCXX_SIMD_INTRINSIC static _Tp
571     _S_remquo(_Tp __x, _Tp __y, _ST<int>* __z)
572     { return std::remquo(__x, __y, &__z->first); }
573 
574   template <typename _Tp>
575     _GLIBCXX_SIMD_INTRINSIC static constexpr _ST<int>
576     _S_fpclassify(_Tp __x)
577     { return {std::fpclassify(__x)}; }
578 
579   template <typename _Tp>
580     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
581     _S_isfinite(_Tp __x)
582     { return std::isfinite(__x); }
583 
584   template <typename _Tp>
585     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
586     _S_isinf(_Tp __x)
587     { return std::isinf(__x); }
588 
589   template <typename _Tp>
590     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
591     _S_isnan(_Tp __x)
592     { return std::isnan(__x); }
593 
594   template <typename _Tp>
595     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
596     _S_isnormal(_Tp __x)
597     { return std::isnormal(__x); }
598 
599   template <typename _Tp>
600     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
601     _S_signbit(_Tp __x)
602     { return std::signbit(__x); }
603 
604   template <typename _Tp>
605     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
606     _S_isgreater(_Tp __x, _Tp __y)
607     { return std::isgreater(__x, __y); }
608 
609   template <typename _Tp>
610     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
611     _S_isgreaterequal(_Tp __x, _Tp __y)
612     { return std::isgreaterequal(__x, __y); }
613 
614   template <typename _Tp>
615     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
616     _S_isless(_Tp __x, _Tp __y)
617     { return std::isless(__x, __y); }
618 
619   template <typename _Tp>
620     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
621     _S_islessequal(_Tp __x, _Tp __y)
622     { return std::islessequal(__x, __y); }
623 
624   template <typename _Tp>
625     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
626     _S_islessgreater(_Tp __x, _Tp __y)
627     { return std::islessgreater(__x, __y); }
628 
629   template <typename _Tp>
630     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
631     _S_isunordered(_Tp __x, _Tp __y)
632     { return std::isunordered(__x, __y); }
633 
634   // _S_increment & _S_decrement{{{2
635   template <typename _Tp>
636     _GLIBCXX_SIMD_INTRINSIC static constexpr void
637     _S_increment(_Tp& __x)
638     { ++__x; }
639 
640   template <typename _Tp>
641     _GLIBCXX_SIMD_INTRINSIC static constexpr void
642     _S_decrement(_Tp& __x)
643     { --__x; }
644 
645 
646   // compares {{{2
647   template <typename _Tp>
648     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
649     _S_equal_to(_Tp __x, _Tp __y)
650     { return __x == __y; }
651 
652   template <typename _Tp>
653     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
654     _S_not_equal_to(_Tp __x, _Tp __y)
655     { return __x != __y; }
656 
657   template <typename _Tp>
658     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
659     _S_less(_Tp __x, _Tp __y)
660     { return __x < __y; }
661 
662   template <typename _Tp>
663     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
664     _S_less_equal(_Tp __x, _Tp __y)
665     { return __x <= __y; }
666 
667   // smart_reference access {{{2
668   template <typename _Tp, typename _Up>
669     _GLIBCXX_SIMD_INTRINSIC static constexpr void
670     _S_set(_Tp& __v, [[maybe_unused]] int __i, _Up&& __x) noexcept
671     {
672       _GLIBCXX_DEBUG_ASSERT(__i == 0);
673       __v = static_cast<_Up&&>(__x);
674     }
675 
676   // _S_masked_assign {{{2
677   template <typename _Tp>
678     _GLIBCXX_SIMD_INTRINSIC static constexpr void
679     _S_masked_assign(bool __k, _Tp& __lhs, _Tp __rhs)
680     { if (__k) __lhs = __rhs; }
681 
682   // _S_masked_cassign {{{2
683   template <typename _Op, typename _Tp>
684     _GLIBCXX_SIMD_INTRINSIC static constexpr void
685     _S_masked_cassign(const bool __k, _Tp& __lhs, const _Tp __rhs, _Op __op)
686     { if (__k) __lhs = __op(_SimdImplScalar{}, __lhs, __rhs); }
687 
688   // _S_masked_unary {{{2
689   template <template <typename> class _Op, typename _Tp>
690     _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
691     _S_masked_unary(const bool __k, const _Tp __v)
692     { return static_cast<_Tp>(__k ? _Op<_Tp>{}(__v) : __v); }
693 
694   // }}}2
695 };
696 
697 // }}}
698 // _MaskImplScalar {{{
699 struct _MaskImplScalar
700 {
701   // member types {{{
702   template <typename _Tp>
703     using _TypeTag = _Tp*;
704 
705   // }}}
706   // _S_broadcast {{{
707   template <typename>
708     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
709     _S_broadcast(bool __x)
710     { return __x; }
711 
712   // }}}
713   // _S_load {{{
714   template <typename>
715     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
716     _S_load(const bool* __mem)
717     { return __mem[0]; }
718 
719   // }}}
720   // _S_to_bits {{{
721   _GLIBCXX_SIMD_INTRINSIC static constexpr _SanitizedBitMask<1>
722   _S_to_bits(bool __x)
723   { return __x; }
724 
725   // }}}
726   // _S_convert {{{
727   template <typename, bool _Sanitized>
728     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
729     _S_convert(_BitMask<1, _Sanitized> __x)
730     { return __x[0]; }
731 
732   template <typename, typename _Up, typename _UAbi>
733     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
734     _S_convert(simd_mask<_Up, _UAbi> __x)
735     { return __x[0]; }
736 
737   // }}}
738   // _S_from_bitmask {{{2
739   template <typename _Tp>
740     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
741     _S_from_bitmask(_SanitizedBitMask<1> __bits, _TypeTag<_Tp>) noexcept
742     { return __bits[0]; }
743 
744   // _S_masked_load {{{2
745   _GLIBCXX_SIMD_INTRINSIC static constexpr bool
746   _S_masked_load(bool __merge, bool __mask, const bool* __mem) noexcept
747   {
748     if (__mask)
749       __merge = __mem[0];
750     return __merge;
751   }
752 
753   // _S_store {{{2
754   _GLIBCXX_SIMD_INTRINSIC static constexpr void
755   _S_store(bool __v, bool* __mem) noexcept
756   { __mem[0] = __v; }
757 
758   // _S_masked_store {{{2
759   _GLIBCXX_SIMD_INTRINSIC static constexpr void
760   _S_masked_store(const bool __v, bool* __mem, const bool __k) noexcept
761   {
762     if (__k)
763       __mem[0] = __v;
764   }
765 
766   // logical and bitwise operators {{{2
767   _GLIBCXX_SIMD_INTRINSIC static constexpr bool
768   _S_logical_and(bool __x, bool __y)
769   { return __x && __y; }
770 
771   _GLIBCXX_SIMD_INTRINSIC static constexpr bool
772   _S_logical_or(bool __x, bool __y)
773   { return __x || __y; }
774 
775   _GLIBCXX_SIMD_INTRINSIC static constexpr bool
776   _S_bit_not(bool __x)
777   { return !__x; }
778 
779   _GLIBCXX_SIMD_INTRINSIC static constexpr bool
780   _S_bit_and(bool __x, bool __y)
781   { return __x && __y; }
782 
783   _GLIBCXX_SIMD_INTRINSIC static constexpr bool
784   _S_bit_or(bool __x, bool __y)
785   { return __x || __y; }
786 
787   _GLIBCXX_SIMD_INTRINSIC static constexpr bool
788   _S_bit_xor(bool __x, bool __y)
789   { return __x != __y; }
790 
791   // smart_reference access {{{2
792   _GLIBCXX_SIMD_INTRINSIC static constexpr void
793   _S_set(bool& __k, [[maybe_unused]] int __i, bool __x) noexcept
794   {
795     _GLIBCXX_DEBUG_ASSERT(__i == 0);
796     __k = __x;
797   }
798 
799   // _S_masked_assign {{{2
800   _GLIBCXX_SIMD_INTRINSIC static constexpr void
801   _S_masked_assign(bool __k, bool& __lhs, bool __rhs)
802   {
803     if (__k)
804       __lhs = __rhs;
805   }
806 
807   // }}}2
808   // _S_all_of {{{
809   template <typename _Tp, typename _Abi>
810     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
811     _S_all_of(simd_mask<_Tp, _Abi> __k)
812     { return __k._M_data; }
813 
814   // }}}
815   // _S_any_of {{{
816   template <typename _Tp, typename _Abi>
817     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
818     _S_any_of(simd_mask<_Tp, _Abi> __k)
819     { return __k._M_data; }
820 
821   // }}}
822   // _S_none_of {{{
823   template <typename _Tp, typename _Abi>
824     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
825     _S_none_of(simd_mask<_Tp, _Abi> __k)
826     { return !__k._M_data; }
827 
828   // }}}
829   // _S_some_of {{{
830   template <typename _Tp, typename _Abi>
831     _GLIBCXX_SIMD_INTRINSIC static constexpr bool
832     _S_some_of(simd_mask<_Tp, _Abi>)
833     { return false; }
834 
835   // }}}
836   // _S_popcount {{{
837   template <typename _Tp, typename _Abi>
838     _GLIBCXX_SIMD_INTRINSIC static constexpr int
839     _S_popcount(simd_mask<_Tp, _Abi> __k)
840     { return __k._M_data; }
841 
842   // }}}
843   // _S_find_first_set {{{
844   template <typename _Tp, typename _Abi>
845     _GLIBCXX_SIMD_INTRINSIC static constexpr int
846     _S_find_first_set(simd_mask<_Tp, _Abi>)
847     { return 0; }
848 
849   // }}}
850   // _S_find_last_set {{{
851   template <typename _Tp, typename _Abi>
852     _GLIBCXX_SIMD_INTRINSIC static constexpr int
853     _S_find_last_set(simd_mask<_Tp, _Abi>)
854     { return 0; }
855 
856   // }}}
857 };
858 
859 // }}}
860 
861 _GLIBCXX_SIMD_END_NAMESPACE
862 #endif // __cplusplus >= 201703L
863 #endif // _GLIBCXX_EXPERIMENTAL_SIMD_SCALAR_H_
864 
865 // vim: foldmethod=marker sw=2 noet ts=8 sts=2 tw=80
866