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
78  _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  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  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  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  static constexpr inline bool
184  _S_negate(_Tp __x) noexcept
185  { return !__x; }
186 
187  // _S_reduce {{{2
188  template <typename _Tp, typename _BinaryOperation>
189  static constexpr inline _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  static constexpr inline _Tp
196  _S_min(const _Tp __a, const _Tp __b)
197  { return std::min(__a, __b); }
198 
199  template <typename _Tp>
200  static constexpr inline _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  static constexpr inline _Tp
207  _S_complement(_Tp __x) noexcept
208  { return static_cast<_Tp>(~__x); }
209 
210  // _S_unary_minus {{{2
211  template <typename _Tp>
212  static constexpr inline _Tp
213  _S_unary_minus(_Tp __x) noexcept
214  { return static_cast<_Tp>(-__x); }
215 
216  // arithmetic operators {{{2
217  template <typename _Tp>
218  static constexpr inline _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  static constexpr inline _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  static constexpr inline _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  static constexpr inline _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  static constexpr inline _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  static constexpr inline _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  static constexpr inline _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  static constexpr inline _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  static constexpr inline _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  static constexpr inline _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  static constexpr void
637  _S_increment(_Tp& __x)
638  { ++__x; }
639 
640  template <typename _Tp>
641  static constexpr void
642  _S_decrement(_Tp& __x)
643  { --__x; }
644 
645  // compares {{{2
646  template <typename _Tp>
647  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
648  _S_equal_to(_Tp __x, _Tp __y)
649  { return __x == __y; }
650 
651  template <typename _Tp>
652  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
653  _S_not_equal_to(_Tp __x, _Tp __y)
654  { return __x != __y; }
655 
656  template <typename _Tp>
657  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
658  _S_less(_Tp __x, _Tp __y)
659  { return __x < __y; }
660 
661  template <typename _Tp>
662  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
663  _S_less_equal(_Tp __x, _Tp __y)
664  { return __x <= __y; }
665 
666  // smart_reference access {{{2
667  template <typename _Tp, typename _Up>
668  static constexpr void
669  _S_set(_Tp& __v, [[maybe_unused]] int __i, _Up&& __x) noexcept
670  {
671  _GLIBCXX_DEBUG_ASSERT(__i == 0);
672  __v = static_cast<_Up&&>(__x);
673  }
674 
675  // _S_masked_assign {{{2
676  template <typename _Tp>
677  _GLIBCXX_SIMD_INTRINSIC static constexpr void
678  _S_masked_assign(bool __k, _Tp& __lhs, _Tp __rhs)
679  { if (__k) __lhs = __rhs; }
680 
681  // _S_masked_cassign {{{2
682  template <typename _Op, typename _Tp>
683  _GLIBCXX_SIMD_INTRINSIC static constexpr void
684  _S_masked_cassign(const bool __k, _Tp& __lhs, const _Tp __rhs, _Op __op)
685  { if (__k) __lhs = __op(_SimdImplScalar{}, __lhs, __rhs); }
686 
687  // _S_masked_unary {{{2
688  template <template <typename> class _Op, typename _Tp>
689  _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
690  _S_masked_unary(const bool __k, const _Tp __v)
691  { return static_cast<_Tp>(__k ? _Op<_Tp>{}(__v) : __v); }
692 
693  // }}}2
694 };
695 
696 // }}}
697 // _MaskImplScalar {{{
698 struct _MaskImplScalar
699 {
700  // member types {{{
701  template <typename _Tp>
702  using _TypeTag = _Tp*;
703 
704  // }}}
705  // _S_broadcast {{{
706  template <typename>
707  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
708  _S_broadcast(bool __x)
709  { return __x; }
710 
711  // }}}
712  // _S_load {{{
713  template <typename>
714  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
715  _S_load(const bool* __mem)
716  { return __mem[0]; }
717 
718  // }}}
719  // _S_to_bits {{{
720  _GLIBCXX_SIMD_INTRINSIC static constexpr _SanitizedBitMask<1>
721  _S_to_bits(bool __x)
722  { return __x; }
723 
724  // }}}
725  // _S_convert {{{
726  template <typename, bool _Sanitized>
727  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
728  _S_convert(_BitMask<1, _Sanitized> __x)
729  { return __x[0]; }
730 
731  template <typename, typename _Up, typename _UAbi>
732  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
733  _S_convert(simd_mask<_Up, _UAbi> __x)
734  { return __x[0]; }
735 
736  // }}}
737  // _S_from_bitmask {{{2
738  template <typename _Tp>
739  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
740  _S_from_bitmask(_SanitizedBitMask<1> __bits, _TypeTag<_Tp>) noexcept
741  { return __bits[0]; }
742 
743  // _S_masked_load {{{2
744  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
745  _S_masked_load(bool __merge, bool __mask, const bool* __mem) noexcept
746  {
747  if (__mask)
748  __merge = __mem[0];
749  return __merge;
750  }
751 
752  // _S_store {{{2
753  _GLIBCXX_SIMD_INTRINSIC static constexpr void
754  _S_store(bool __v, bool* __mem) noexcept
755  { __mem[0] = __v; }
756 
757  // _S_masked_store {{{2
758  _GLIBCXX_SIMD_INTRINSIC static constexpr void
759  _S_masked_store(const bool __v, bool* __mem, const bool __k) noexcept
760  {
761  if (__k)
762  __mem[0] = __v;
763  }
764 
765  // logical and bitwise operators {{{2
766  static constexpr bool
767  _S_logical_and(bool __x, bool __y)
768  { return __x && __y; }
769 
770  static constexpr bool
771  _S_logical_or(bool __x, bool __y)
772  { return __x || __y; }
773 
774  static constexpr bool
775  _S_bit_not(bool __x)
776  { return !__x; }
777 
778  static constexpr bool
779  _S_bit_and(bool __x, bool __y)
780  { return __x && __y; }
781 
782  static constexpr bool
783  _S_bit_or(bool __x, bool __y)
784  { return __x || __y; }
785 
786  static constexpr bool
787  _S_bit_xor(bool __x, bool __y)
788  { return __x != __y; }
789 
790  // smart_reference access {{{2
791  static constexpr void
792  _S_set(bool& __k, [[maybe_unused]] int __i, bool __x) noexcept
793  {
794  _GLIBCXX_DEBUG_ASSERT(__i == 0);
795  __k = __x;
796  }
797 
798  // _S_masked_assign {{{2
799  _GLIBCXX_SIMD_INTRINSIC static constexpr void
800  _S_masked_assign(bool __k, bool& __lhs, bool __rhs)
801  {
802  if (__k)
803  __lhs = __rhs;
804  }
805 
806  // }}}2
807  // _S_all_of {{{
808  template <typename _Tp, typename _Abi>
809  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
810  _S_all_of(simd_mask<_Tp, _Abi> __k)
811  { return __k._M_data; }
812 
813  // }}}
814  // _S_any_of {{{
815  template <typename _Tp, typename _Abi>
816  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
817  _S_any_of(simd_mask<_Tp, _Abi> __k)
818  { return __k._M_data; }
819 
820  // }}}
821  // _S_none_of {{{
822  template <typename _Tp, typename _Abi>
823  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
824  _S_none_of(simd_mask<_Tp, _Abi> __k)
825  { return !__k._M_data; }
826 
827  // }}}
828  // _S_some_of {{{
829  template <typename _Tp, typename _Abi>
830  _GLIBCXX_SIMD_INTRINSIC static constexpr bool
831  _S_some_of(simd_mask<_Tp, _Abi>)
832  { return false; }
833 
834  // }}}
835  // _S_popcount {{{
836  template <typename _Tp, typename _Abi>
837  _GLIBCXX_SIMD_INTRINSIC static constexpr int
838  _S_popcount(simd_mask<_Tp, _Abi> __k)
839  { return __k._M_data; }
840 
841  // }}}
842  // _S_find_first_set {{{
843  template <typename _Tp, typename _Abi>
844  _GLIBCXX_SIMD_INTRINSIC static constexpr int
845  _S_find_first_set(simd_mask<_Tp, _Abi>)
846  { return 0; }
847 
848  // }}}
849  // _S_find_last_set {{{
850  template <typename _Tp, typename _Abi>
851  _GLIBCXX_SIMD_INTRINSIC static constexpr int
852  _S_find_last_set(simd_mask<_Tp, _Abi>)
853  { return 0; }
854 
855  // }}}
856 };
857 
858 // }}}
859 
860 _GLIBCXX_SIMD_END_NAMESPACE
861 #endif // __cplusplus >= 201703L
862 #endif // _GLIBCXX_EXPERIMENTAL_SIMD_SCALAR_H_
863 
864 // 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:83
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:1846
std::complex< _Tp > asinh(const std::complex< _Tp > &)
asinh(__z) [8.1.6].
Definition: complex:1793
std::complex< _Tp > atan(const std::complex< _Tp > &)
atan(__z) [8.1.4].
Definition: complex:1718
std::complex< _Tp > atanh(const std::complex< _Tp > &)
atanh(__z) [8.1.7].
Definition: complex:1837
std::complex< _Tp > acosh(const std::complex< _Tp > &)
acosh(__z) [8.1.5].
Definition: complex:1754
std::complex< _Tp > acos(const std::complex< _Tp > &)
acos(__z) [8.1.2].
Definition: complex:1638
std::complex< _Tp > asin(const std::complex< _Tp > &)
asin(__z) [8.1.3].
Definition: complex:1674