libstdc++
simd_scalar.h
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.
37 template <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 
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(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 {{{
109 struct _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 {{{
131 struct _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 {{{
615 struct _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
_Tp fabs(const std::complex< _Tp > &)
fabs(__z) [8.1.8].
Definition: complex:1846
complex< _Tp > exp(const complex< _Tp > &)
Return complex base e exponential of z.
Definition: complex:797
complex< _Tp > sqrt(const complex< _Tp > &)
Return complex square root of z.
Definition: complex:933
std::complex< _Tp > atanh(const std::complex< _Tp > &)
atanh(__z) [8.1.7].
Definition: complex:1837
std::complex< _Tp > acos(const std::complex< _Tp > &)
acos(__z) [8.1.2].
Definition: complex:1638
complex< _Tp > pow(const complex< _Tp > &, int)
Return x to the y&#39;th power.
Definition: complex:1019
complex< _Tp > cosh(const complex< _Tp > &)
Return complex hyperbolic cosine of z.
Definition: complex:771
std::complex< _Tp > asinh(const std::complex< _Tp > &)
asinh(__z) [8.1.6].
Definition: complex:1793
complex< _Tp > sin(const complex< _Tp > &)
Return complex sine of z.
Definition: complex:859
complex< _Tp > sinh(const complex< _Tp > &)
Return complex hyperbolic sine of z.
Definition: complex:889
complex< _Tp > tanh(const complex< _Tp > &)
Return complex hyperbolic tangent of z.
Definition: complex:988
complex< _Tp > log10(const complex< _Tp > &)
Return complex base 10 logarithm of z.
Definition: complex:829
complex< _Tp > log(const complex< _Tp > &)
Return complex natural logarithm of z.
Definition: complex:824
std::complex< _Tp > acosh(const std::complex< _Tp > &)
acosh(__z) [8.1.5].
Definition: complex:1754
constexpr const _Tp & max(const _Tp &, const _Tp &)
This does what you think it does.
Definition: stl_algobase.h:254
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
Definition: type_traits:83
constexpr const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
Definition: stl_algobase.h:230
std::complex< _Tp > asin(const std::complex< _Tp > &)
asin(__z) [8.1.3].
Definition: complex:1674
_Tp abs(const complex< _Tp > &)
Return magnitude of z.
Definition: complex:630
complex< _Tp > cos(const complex< _Tp > &)
Return complex cosine of z.
Definition: complex:741
std::complex< _Tp > atan(const std::complex< _Tp > &)
atan(__z) [8.1.4].
Definition: complex:1718
complex< _Tp > tan(const complex< _Tp > &)
Return complex tangent of z.
Definition: complex:960