libstdc++
simd_scalar.h
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>
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  _GLIBCXX_SIMD_INTRINSIC
159  static _Tp _S_masked_load(_Tp __merge, bool __k,
160  const _Up* __mem) noexcept
161  {
162  if (__k)
163  __merge = static_cast<_Tp>(__mem[0]);
164  return __merge;
165  }
166 
167  // _S_store {{{2
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); }
172 
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; }
179 
180  // _S_negate {{{2
181  template <typename _Tp>
182  _GLIBCXX_SIMD_INTRINSIC
183  static constexpr bool _S_negate(_Tp __x) noexcept
184  { return !__x; }
185 
186  // _S_reduce {{{2
187  template <typename _Tp, typename _BinaryOperation>
188  _GLIBCXX_SIMD_INTRINSIC
189  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
196  static constexpr _Tp _S_min(const _Tp __a, const _Tp __b)
197  { return std::min(__a, __b); }
198 
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); }
203 
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); }
209 
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); }
215 
216  // arithmetic operators {{{2
217  template <typename _Tp>
218  _GLIBCXX_SIMD_INTRINSIC
219  static constexpr _Tp _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
227  static constexpr _Tp _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
235  static constexpr _Tp _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
243  static constexpr _Tp _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
251  static constexpr _Tp _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
259  static constexpr _Tp _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
273  static constexpr _Tp _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
287  static constexpr _Tp _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
301  static constexpr _Tp _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
306  static constexpr _Tp _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 _S_acos(_Tp __x)
316  { return std::acos(__x); }
317 
318  template <typename _Tp>
319  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_asin(_Tp __x)
320  { return std::asin(__x); }
321 
322  template <typename _Tp>
323  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_atan(_Tp __x)
324  { return std::atan(__x); }
325 
326  template <typename _Tp>
327  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_cos(_Tp __x)
328  { return std::cos(__x); }
329 
330  template <typename _Tp>
331  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_sin(_Tp __x)
332  { return std::sin(__x); }
333 
334  template <typename _Tp>
335  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_tan(_Tp __x)
336  { return std::tan(__x); }
337 
338  template <typename _Tp>
339  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_acosh(_Tp __x)
340  { return std::acosh(__x); }
341 
342  template <typename _Tp>
343  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_asinh(_Tp __x)
344  { return std::asinh(__x); }
345 
346  template <typename _Tp>
347  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_atanh(_Tp __x)
348  { return std::atanh(__x); }
349 
350  template <typename _Tp>
351  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_cosh(_Tp __x)
352  { return std::cosh(__x); }
353 
354  template <typename _Tp>
355  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_sinh(_Tp __x)
356  { return std::sinh(__x); }
357 
358  template <typename _Tp>
359  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_tanh(_Tp __x)
360  { return std::tanh(__x); }
361 
362  template <typename _Tp>
363  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_atan2(_Tp __x, _Tp __y)
364  { return std::atan2(__x, __y); }
365 
366  template <typename _Tp>
367  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_exp(_Tp __x)
368  { return std::exp(__x); }
369 
370  template <typename _Tp>
371  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_exp2(_Tp __x)
372  { return std::exp2(__x); }
373 
374  template <typename _Tp>
375  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_expm1(_Tp __x)
376  { return std::expm1(__x); }
377 
378  template <typename _Tp>
379  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_log(_Tp __x)
380  { return std::log(__x); }
381 
382  template <typename _Tp>
383  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_log10(_Tp __x)
384  { return std::log10(__x); }
385 
386  template <typename _Tp>
387  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_log1p(_Tp __x)
388  { return std::log1p(__x); }
389 
390  template <typename _Tp>
391  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_log2(_Tp __x)
392  { return std::log2(__x); }
393 
394  template <typename _Tp>
395  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_logb(_Tp __x)
396  { return std::logb(__x); }
397 
398  template <typename _Tp>
399  _GLIBCXX_SIMD_INTRINSIC static _ST<int> _S_ilogb(_Tp __x)
400  { return {std::ilogb(__x)}; }
401 
402  template <typename _Tp>
403  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_pow(_Tp __x, _Tp __y)
404  { return std::pow(__x, __y); }
405 
406  template <typename _Tp>
407  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_abs(_Tp __x)
408  { return std::abs(__x); }
409 
410  template <typename _Tp>
411  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fabs(_Tp __x)
412  { return std::fabs(__x); }
413 
414  template <typename _Tp>
415  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_sqrt(_Tp __x)
416  { return std::sqrt(__x); }
417 
418  template <typename _Tp>
419  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_cbrt(_Tp __x)
420  { return std::cbrt(__x); }
421 
422  template <typename _Tp>
423  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_erf(_Tp __x)
424  { return std::erf(__x); }
425 
426  template <typename _Tp>
427  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_erfc(_Tp __x)
428  { return std::erfc(__x); }
429 
430  template <typename _Tp>
431  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_lgamma(_Tp __x)
432  { return std::lgamma(__x); }
433 
434  template <typename _Tp>
435  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_tgamma(_Tp __x)
436  { return std::tgamma(__x); }
437 
438  template <typename _Tp>
439  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_trunc(_Tp __x)
440  { return std::trunc(__x); }
441 
442  template <typename _Tp>
443  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_floor(_Tp __x)
444  { return std::floor(__x); }
445 
446  template <typename _Tp>
447  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_ceil(_Tp __x)
448  { return std::ceil(__x); }
449 
450  template <typename _Tp>
451  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_nearbyint(_Tp __x)
452  { return std::nearbyint(__x); }
453 
454  template <typename _Tp>
455  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_rint(_Tp __x)
456  { return std::rint(__x); }
457 
458  template <typename _Tp>
459  _GLIBCXX_SIMD_INTRINSIC static _ST<long> _S_lrint(_Tp __x)
460  { return {std::lrint(__x)}; }
461 
462  template <typename _Tp>
463  _GLIBCXX_SIMD_INTRINSIC static _ST<long long> _S_llrint(_Tp __x)
464  { return {std::llrint(__x)}; }
465 
466  template <typename _Tp>
467  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_round(_Tp __x)
468  { return std::round(__x); }
469 
470  template <typename _Tp>
471  _GLIBCXX_SIMD_INTRINSIC static _ST<long> _S_lround(_Tp __x)
472  { return {std::lround(__x)}; }
473 
474  template <typename _Tp>
475  _GLIBCXX_SIMD_INTRINSIC static _ST<long long> _S_llround(_Tp __x)
476  { return {std::llround(__x)}; }
477 
478  template <typename _Tp>
479  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_ldexp(_Tp __x, _ST<int> __y)
480  { return std::ldexp(__x, __y.first); }
481 
482  template <typename _Tp>
483  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_scalbn(_Tp __x, _ST<int> __y)
484  { return std::scalbn(__x, __y.first); }
485 
486  template <typename _Tp>
487  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_scalbln(_Tp __x, _ST<long> __y)
488  { return std::scalbln(__x, __y.first); }
489 
490  template <typename _Tp>
491  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fmod(_Tp __x, _Tp __y)
492  { return std::fmod(__x, __y); }
493 
494  template <typename _Tp>
495  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_remainder(_Tp __x, _Tp __y)
496  { return std::remainder(__x, __y); }
497 
498  template <typename _Tp>
499  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_nextafter(_Tp __x, _Tp __y)
500  { return std::nextafter(__x, __y); }
501 
502  template <typename _Tp>
503  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fdim(_Tp __x, _Tp __y)
504  { return std::fdim(__x, __y); }
505 
506  template <typename _Tp>
507  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fmax(_Tp __x, _Tp __y)
508  { return std::fmax(__x, __y); }
509 
510  template <typename _Tp>
511  _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fmin(_Tp __x, _Tp __y)
512  { return std::fmin(__x, __y); }
513 
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); }
517 
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); }
521 
522  template <typename _Tp>
523  _GLIBCXX_SIMD_INTRINSIC constexpr static _ST<int> _S_fpclassify(_Tp __x)
524  { return {std::fpclassify(__x)}; }
525 
526  template <typename _Tp>
527  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isfinite(_Tp __x)
528  { return std::isfinite(__x); }
529 
530  template <typename _Tp>
531  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isinf(_Tp __x)
532  { return std::isinf(__x); }
533 
534  template <typename _Tp>
535  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isnan(_Tp __x)
536  { return std::isnan(__x); }
537 
538  template <typename _Tp>
539  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isnormal(_Tp __x)
540  { return std::isnormal(__x); }
541 
542  template <typename _Tp>
543  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_signbit(_Tp __x)
544  { return std::signbit(__x); }
545 
546  template <typename _Tp>
547  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isgreater(_Tp __x, _Tp __y)
548  { return std::isgreater(__x, __y); }
549 
550  template <typename _Tp>
551  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isgreaterequal(_Tp __x,
552  _Tp __y)
553  { return std::isgreaterequal(__x, __y); }
554 
555  template <typename _Tp>
556  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isless(_Tp __x, _Tp __y)
557  { return std::isless(__x, __y); }
558 
559  template <typename _Tp>
560  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_islessequal(_Tp __x, _Tp __y)
561  { return std::islessequal(__x, __y); }
562 
563  template <typename _Tp>
564  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_islessgreater(_Tp __x,
565  _Tp __y)
566  { return std::islessgreater(__x, __y); }
567 
568  template <typename _Tp>
569  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isunordered(_Tp __x,
570  _Tp __y)
571  { return std::isunordered(__x, __y); }
572 
573  // _S_increment & _S_decrement{{{2
574  template <typename _Tp>
575  _GLIBCXX_SIMD_INTRINSIC
576  constexpr static void _S_increment(_Tp& __x)
577  { ++__x; }
578 
579  template <typename _Tp>
580  _GLIBCXX_SIMD_INTRINSIC
581  constexpr static void _S_decrement(_Tp& __x)
582  { --__x; }
583 
584 
585  // compares {{{2
586  template <typename _Tp>
587  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_equal_to(_Tp __x, _Tp __y)
588  { return __x == __y; }
589 
590  template <typename _Tp>
591  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_not_equal_to(_Tp __x,
592  _Tp __y)
593  { return __x != __y; }
594 
595  template <typename _Tp>
596  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_less(_Tp __x, _Tp __y)
597  { return __x < __y; }
598 
599  template <typename _Tp>
600  _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_less_equal(_Tp __x,
601  _Tp __y)
602  { return __x <= __y; }
603 
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,
608  _Up&& __x) noexcept
609  {
610  _GLIBCXX_DEBUG_ASSERT(__i == 0);
611  __v = static_cast<_Up&&>(__x);
612  }
613 
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; }
619 
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); }
625 
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,
629  const _Tp __v)
630  { return static_cast<_Tp>(__k ? _Op<_Tp>{}(__v) : __v); }
631 
632  // }}}2
633 };
634 
635 // }}}
636 // _MaskImplScalar {{{
637 struct _MaskImplScalar
638 {
639  // member types {{{
640  template <typename _Tp>
641  using _TypeTag = _Tp*;
642 
643  // }}}
644  // _S_broadcast {{{
645  template <typename>
646  _GLIBCXX_SIMD_INTRINSIC static constexpr bool _S_broadcast(bool __x)
647  { return __x; }
648 
649  // }}}
650  // _S_load {{{
651  template <typename>
652  _GLIBCXX_SIMD_INTRINSIC static constexpr bool _S_load(const bool* __mem)
653  { return __mem[0]; }
654 
655  // }}}
656  // _S_to_bits {{{
657  _GLIBCXX_SIMD_INTRINSIC static constexpr _SanitizedBitMask<1>
658  _S_to_bits(bool __x)
659  { return __x; }
660 
661  // }}}
662  // _S_convert {{{
663  template <typename, bool _Sanitized>
664  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
665  _S_convert(_BitMask<1, _Sanitized> __x)
666  { return __x[0]; }
667 
668  template <typename, typename _Up, typename _UAbi>
669  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
670  _S_convert(simd_mask<_Up, _UAbi> __x)
671  { return __x[0]; }
672 
673  // }}}
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]; }
679 
680  // _S_masked_load {{{2
681  _GLIBCXX_SIMD_INTRINSIC constexpr static bool
682  _S_masked_load(bool __merge, bool __mask, const bool* __mem) noexcept
683  {
684  if (__mask)
685  __merge = __mem[0];
686  return __merge;
687  }
688 
689  // _S_store {{{2
690  _GLIBCXX_SIMD_INTRINSIC static void _S_store(bool __v, bool* __mem) noexcept
691  { __mem[0] = __v; }
692 
693  // _S_masked_store {{{2
694  _GLIBCXX_SIMD_INTRINSIC static void
695  _S_masked_store(const bool __v, bool* __mem, const bool __k) noexcept
696  {
697  if (__k)
698  __mem[0] = __v;
699  }
700 
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; }
705 
706  _GLIBCXX_SIMD_INTRINSIC
707  static constexpr bool _S_logical_or(bool __x, bool __y)
708  { return __x || __y; }
709 
710  _GLIBCXX_SIMD_INTRINSIC
711  static constexpr bool _S_bit_not(bool __x)
712  { return !__x; }
713 
714  _GLIBCXX_SIMD_INTRINSIC
715  static constexpr bool _S_bit_and(bool __x, bool __y)
716  { return __x && __y; }
717 
718  _GLIBCXX_SIMD_INTRINSIC
719  static constexpr bool _S_bit_or(bool __x, bool __y)
720  { return __x || __y; }
721 
722  _GLIBCXX_SIMD_INTRINSIC
723  static constexpr bool _S_bit_xor(bool __x, bool __y)
724  { return __x != __y; }
725 
726  // smart_reference access {{{2
727  _GLIBCXX_SIMD_INTRINSIC
728  constexpr static void _S_set(bool& __k, [[maybe_unused]] int __i,
729  bool __x) noexcept
730  {
731  _GLIBCXX_DEBUG_ASSERT(__i == 0);
732  __k = __x;
733  }
734 
735  // _S_masked_assign {{{2
736  _GLIBCXX_SIMD_INTRINSIC static void _S_masked_assign(bool __k, bool& __lhs,
737  bool __rhs)
738  {
739  if (__k)
740  __lhs = __rhs;
741  }
742 
743  // }}}2
744  // _S_all_of {{{
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; }
749 
750  // }}}
751  // _S_any_of {{{
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; }
756 
757  // }}}
758  // _S_none_of {{{
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; }
763 
764  // }}}
765  // _S_some_of {{{
766  template <typename _Tp, typename _Abi>
767  _GLIBCXX_SIMD_INTRINSIC constexpr static bool
768  _S_some_of(simd_mask<_Tp, _Abi>)
769  { return false; }
770 
771  // }}}
772  // _S_popcount {{{
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; }
777 
778  // }}}
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>)
783  { return 0; }
784 
785  // }}}
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>)
790  { return 0; }
791 
792  // }}}
793 };
794 
795 // }}}
796 
797 _GLIBCXX_SIMD_END_NAMESPACE
798 #endif // __cplusplus >= 201703L
799 #endif // _GLIBCXX_EXPERIMENTAL_SIMD_SCALAR_H_
800 
801 // vim: foldmethod=marker sw=2 noet ts=8 sts=2 tw=80
complex< _Tp > log10(const complex< _Tp > &)
Return complex base 10 logarithm of z.
Definition: complex:829
complex< _Tp > sin(const complex< _Tp > &)
Return complex sine of z.
Definition: complex:859
complex< _Tp > log(const complex< _Tp > &)
Return complex natural logarithm of z.
Definition: complex:824
complex< _Tp > tan(const complex< _Tp > &)
Return complex tangent of z.
Definition: complex:960
_Tp abs(const complex< _Tp > &)
Return magnitude of z.
Definition: complex:630
complex< _Tp > exp(const complex< _Tp > &)
Return complex base e exponential of z.
Definition: complex:797
complex< _Tp > cosh(const complex< _Tp > &)
Return complex hyperbolic cosine of z.
Definition: complex:771
complex< _Tp > tanh(const complex< _Tp > &)
Return complex hyperbolic tangent of z.
Definition: complex:988
complex< _Tp > pow(const complex< _Tp > &, int)
Return x to the y'th power.
Definition: complex:1019
complex< _Tp > sinh(const complex< _Tp > &)
Return complex hyperbolic sine of z.
Definition: complex:889
complex< _Tp > cos(const complex< _Tp > &)
Return complex cosine of z.
Definition: complex:741
complex< _Tp > sqrt(const complex< _Tp > &)
Return complex square root of z.
Definition: complex:933
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
Definition: type_traits:82
constexpr const _Tp & max(const _Tp &, const _Tp &)
This does what you think it does.
Definition: stl_algobase.h:254
constexpr const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
Definition: stl_algobase.h:230
_Tp fabs(const std::complex< _Tp > &)
fabs(__z) [8.1.8].
Definition: complex:1817
std::complex< _Tp > asinh(const std::complex< _Tp > &)
asinh(__z) [8.1.6].
Definition: complex:1764
std::complex< _Tp > atan(const std::complex< _Tp > &)
atan(__z) [8.1.4].
Definition: complex:1689
std::complex< _Tp > atanh(const std::complex< _Tp > &)
atanh(__z) [8.1.7].
Definition: complex:1808
std::complex< _Tp > acosh(const std::complex< _Tp > &)
acosh(__z) [8.1.5].
Definition: complex:1725
std::complex< _Tp > acos(const std::complex< _Tp > &)
acos(__z) [8.1.2].
Definition: complex:1609
std::complex< _Tp > asin(const std::complex< _Tp > &)
asin(__z) [8.1.3].
Definition: complex:1645