25#ifndef _GLIBCXX_SIMD_COMPLEX_H
26#define _GLIBCXX_SIMD_COMPLEX_H 1
29#pragma GCC system_header
32#if __cplusplus >= 202400L
38#pragma GCC diagnostic push
39#pragma GCC diagnostic ignored "-Wpsabi"
41namespace std _GLIBCXX_VISIBILITY(default)
43_GLIBCXX_BEGIN_NAMESPACE_VERSION
52 template <
size_t _Bytes,
typename _Ap, __abi_tag _Aret
53 =
decltype(__abi_rebind<complex<__float_from<_Bytes>>, _Ap::_S_size / 2, _Ap>())>
54 [[__gnu__::__always_inline__]]
55 constexpr basic_mask<_Bytes * 2, _Aret>
56 __to_cx_ileav(
const basic_mask<_Bytes, _Ap>& __k)
58 static_assert(_Ap::_S_size % 2 == 0
59 && (__filter_abi_variant(_Ap::_S_variant, _AbiVariant::_CxVariants)
61 if constexpr (_Aret::_S_size == 1)
62 return basic_mask<_Bytes * 2, _Aret>(__k[0]);
64 return basic_mask<_Bytes * 2, _Aret>::_S_init(__k);
68 __check_hi_bits_for_zero(unsigned_integral
auto __x)
70 __glibcxx_simd_precondition(__x == 0,
71 "to_ullong called on mask with 'true' elements at indices"
75 template <
typename _T0,
typename _T1>
77 __check_hi_bits_for_zero(
const __trivial_pair<_T0, _T1>& __p)
79 std::simd::__check_hi_bits_for_zero(__p._M_first);
80 std::simd::__check_hi_bits_for_zero(__p._M_second);
83 constexpr unsigned long long
84 __unwrap_pairs_to_ullong(unsigned_integral
auto __x)
87 template <
typename _T0,
typename _T1>
88 constexpr unsigned long long
89 __unwrap_pairs_to_ullong(
const __trivial_pair<_T0, _T1>& __p)
91 std::simd::__check_hi_bits_for_zero(__p._M_second);
92 return std::simd::__unwrap_pairs_to_ullong(__p._M_first);
97 __unwrap_pairs_to_bitset(unsigned_integral
auto __x)
99 static_assert(_Np <= 64);
103 template <
size_t _Np,
typename _T0,
typename _T1>
104 constexpr bitset<_Np>
105 __unwrap_pairs_to_bitset(
const __trivial_pair<_T0, _T1>& __p)
107 constexpr size_t _N0 = __bit_floor(_Np);
108 constexpr size_t _N1 = _Np - _N0;
109 static_assert(_N0 % 64 == 0);
112 bitset<__bit_floor(_Np)> _M_lo;
113 bitset<_Np - __bit_floor(_Np)> _M_hi;
115 _Tmp __tmp = {std::simd::__unwrap_pairs_to_bitset<_N0>(__p._M_first),
116 std::simd::__unwrap_pairs_to_bitset<_N1>(__p._M_second)};
117 return __builtin_bit_cast(bitset<_Np>, __tmp);
120 template <
size_t _Bytes>
124 static constexpr size_t _N0 = __bit_floor(_Bytes - 1);
125 static constexpr size_t _N1 = _Bytes - _N0;
126 if constexpr (_Bytes <=
sizeof(
unsigned long))
129 return __trivial_pair {__tree_of_ulong<_N0>(), __tree_of_ulong<_N1>()};
132 template <
size_t _Bytes>
133 using __tree_of_ulong_t =
decltype(__tree_of_ulong<_Bytes>());
135 template <
size_t _Np>
137 __bitset_to_pairs(
const bitset<_Np>& __b)
noexcept
139 if constexpr (_Np <= 64)
140 return __b.to_ullong();
142 return __builtin_bit_cast(__tree_of_ulong_t<__div_ceil(_Np,
size_t(__CHAR_BIT__))>, __b);
156 template <
typename _Tp,
typename _Ap>
157 [[__gnu__::__always_inline__]]
159 __set_real(basic_vec<_Tp, _Ap>& __x,
160 const __similar_vec<_Tp, _Ap::_S_size / 2, _Ap>& __re)
noexcept
162 if constexpr (__scalar_abi_tag<_Ap> && _Ap::_S_size == 2)
163 __x._M_get_low() = __re;
164 else if constexpr (_Ap::_S_nreg >= 2)
166 constexpr int __n0 = __x._M_get_low().size();
167 const auto& [__lo, __hi] = __re.template _M_chunk<
168 __similar_vec<_Tp, __n0 / 2, _Ap>>();
169 __set_real(__x._M_get_low(), __lo);
170 __set_real(__x._M_get_high(), __hi);
174 using _DataType =
typename _Ap::template _DataType<_Tp>;
175 _DataType& __xv = __x._M_get();
176 const auto __rv = __re._M_get();
177 if constexpr (_Ap::_S_size == 2)
178 __vec_set(__xv, 0, __rv);
179 else if (__is_const_known(__x, __re))
181 constexpr auto [...__is] = _IotaArray<_Ap::_S_size>;
182 __xv = _DataType {((__is & 1) == 0 ? __rv[__is / 2] : __xv[__is])...};
185 _VecOps<_DataType>::_S_overwrite_even_elements(__xv, __rv);
192 template <
typename _Tp,
typename _Ap>
193 [[__gnu__::__always_inline__]]
195 __set_imag(basic_vec<_Tp, _Ap>& __x,
196 const __similar_vec<_Tp, _Ap::_S_size / 2, _Ap>& __im)
noexcept
198 if constexpr (__scalar_abi_tag<_Ap> && _Ap::_S_size == 2)
199 __x._M_get_high() = __im;
200 else if constexpr (_Ap::_S_nreg >= 2)
202 constexpr int __n0 = __x._M_get_low().size();
203 const auto& [__lo, __hi] = __im.template _M_chunk<
204 __similar_vec<_Tp, __n0 / 2, _Ap>>();
205 __set_imag(__x._M_get_low(), __lo);
206 __set_imag(__x._M_get_high(), __hi);
210 using _DataType =
typename _Ap::template _DataType<_Tp>;
211 _DataType& __xv = __x._M_get();
212 const auto __iv = __im._M_get();
213 if constexpr (_Ap::_S_size == 2)
214 __vec_set(__xv, 1, __iv);
215 else if (__is_const_known(__x, __im))
217 constexpr auto [...__is] = _IotaArray<_Ap::_S_size>;
218 __xv = _DataType {((__is & 1) == 1 ? __iv[__is / 2] : __xv[__is])...};
221 _VecOps<_DataType>::_S_overwrite_odd_elements(__xv, __iv);
228 template <
typename _Tp,
typename _Ap>
229 [[__gnu__::__always_inline__]]
230 constexpr basic_vec<_Tp, _Ap>
231 __negate_imag(
const basic_vec<_Tp, _Ap>& __x)
233 if constexpr (__scalar_abi_tag<_Ap> && _Ap::_S_size == 2)
234 return basic_vec<_Tp, _Ap>::_S_init(__x._M_get_low(), -__x._M_get_high());
235 else if constexpr (_Ap::_S_nreg >= 2)
236 return basic_vec<_Tp, _Ap>::_S_init(__negate_imag(__x._M_get_low()),
237 __negate_imag(__x._M_get_high()));
239 return _VecOps<typename _Ap::template _DataType<_Tp>>
240 ::_S_complex_negate_imag(__x._M_get());
249 template <
typename _Cx, _TargetTraits, __vec_builtin _TV>
250 [[__gnu__::__cold__]]
252 __redo_mul(_TV __r,
const _TV __x,
const _TV __y,
const auto __nan,
const int __n)
255 for (
int __i = 0; __i < __n; __i += 2)
257 if (__nan[__i] && __nan[__i + 1])
259 using _Tc =
typename _Cx::value_type;
260 const _Cx __cx(_Tc(__x[__i]), _Tc(__x[__i + 1]));
261 const _Cx __cy(_Tc(__y[__i]), _Tc(__y[__i + 1]));
262 const _Cx __cr = __cx * __cy;
263 __vec_set(__r, __i, __cr.real());
264 __vec_set(__r, __i + 1, __cr.imag());
273 template <
typename _Cx, _TargetTraits _Traits,
typename _Tp,
typename _Ap>
274 [[__gnu__::__always_inline__]]
276 __mul(basic_vec<_Tp, _Ap>& __x,
const basic_vec<_Tp, _Ap>& __y)
278 static_assert(__complex_like<_Cx>);
279 if constexpr (__scalar_abi_tag<_Ap> && _Ap::_S_size == 2)
281 const _Cx __c = _Cx(__x[0], __x[1]) * _Cx(__y[0], __y[1]);
282 __x._M_get_low() = __c.real();
283 __x._M_get_high() = __c.imag();
285 else if constexpr (_Ap::_S_nreg >= 2)
287 __mul<_Cx, _Traits>(__x._M_get_low(), __y._M_get_low());
288 __mul<_Cx, _Traits>(__x._M_get_high(), __y._M_get_high());
290 else if constexpr (_Traits.template _M_eval_as_f32<_Tp>())
292 using _Vf32 = rebind_t<float, basic_vec<_Tp, _Ap>>;
294 __mul<_Cx, _Traits>(__xf32, _Vf32(__y));
295 __x =
static_cast<basic_vec<_Tp, _Ap>
>(__xf32);
299 using _DataType =
typename _Ap::template _DataType<_Tp>;
300 const _DataType __xv = __x._M_get();
301 const _DataType __yv = __y._M_get();
302 using _VO = _VecOps<_DataType>;
303 using _VOS = _VecOps<_DataType, _Ap::_S_size>;
304 if (_VOS::_S_complex_imag_is_const_known_zero(__xv))
306 if (_VOS::_S_complex_imag_is_const_known_zero(__yv))
310 if (_Traits._M_conforming_to_STDC_annex_G())
312 auto __a = _VO::_S_dup_even(__xv) * __yv;
313 auto __b = _DataType() * _VO::_S_swap_neighbors(__yv);
314 __x = _VO::_S_addsub(__a, __b);
317 __x = _VO::_S_dup_even(__xv) * __yv;
320 else if (_VOS::_S_complex_imag_is_const_known_zero(__yv))
322 if (_Traits._M_conforming_to_STDC_annex_G())
323 __x = _VO::_S_addsub(_VO::_S_dup_even(__yv) * __xv,
324 _DataType() * _VO::_S_swap_neighbors(__xv));
326 __x = _VO::_S_dup_even(__yv) * __xv;
328 else if (_VOS::_S_complex_real_is_const_known_zero(__yv))
330 if (_Traits._M_conforming_to_STDC_annex_G())
331 __x = _VO::_S_addsub(_DataType(), _VO::_S_dup_odd(__yv)
332 * _VO::_S_swap_neighbors(__xv));
334 __x = _VO::_S_dup_odd(__yv)
335 * _VO::_S_complex_negate_real(_VO::_S_swap_neighbors(__xv));
337 else if (_VOS::_S_complex_real_is_const_known_zero(__xv))
339 if (_Traits._M_conforming_to_STDC_annex_G())
340 __x = _VO::_S_addsub(_DataType(), _VO::_S_dup_odd(__xv)
341 * _VO::_S_swap_neighbors(__yv));
343 __x = _VO::_S_dup_odd(__xv)
344 * _VO::_S_complex_negate_real(_VO::_S_swap_neighbors(__yv));
349 if (_Traits._M_have_fma() && !__is_const_known(__xv, __yv))
351 if constexpr (_Traits._M_have_fma())
352 __x = __x86_complex_multiplies(__xv, __yv);
356 __x = _VO::_S_addsub(_VO::_S_dup_even(__xv) * __yv,
357 _VO::_S_dup_odd(__xv) * _VO::_S_swap_neighbors(__yv));
358 const auto __nan = __x._M_isnan();
359 if (_Traits._M_conforming_to_STDC_annex_G() && __nan._M_any_of())
360 __x = __redo_mul<_Cx, _Traits>(__x._M_get(), __xv, __yv, __nan, _Ap::_S_size);
366 template <
size_t _Bytes, __abi_tag _Ap>
367 requires _Ap::_S_is_cx_ileav && (_Ap::_S_size >= 2)
368 class basic_mask<_Bytes, _Ap>
369 : public _MaskBase<_Bytes, _Ap>
371 using _Base = _MaskBase<_Bytes, _Ap>;
373 using _VecType = _Base::_VecType;
375 template <
size_t,
typename>
376 friend class basic_mask;
378 template <
typename,
typename>
379 friend class basic_vec;
381 static constexpr int _S_size = _Ap::_S_size;
383 using _DataType = __component_mask_for_ileav<_Bytes, _Ap>;
385 static constexpr bool _S_is_scalar = _DataType::_S_is_scalar;
387 static constexpr bool _S_use_bitmask = _DataType::_S_use_bitmask;
389 static constexpr int _S_full_size = _DataType::_S_full_size / 2;
391 static constexpr bool _S_is_partial = _DataType::_S_is_partial;
393 static constexpr bool _S_has_bool_member = _DataType::_S_has_bool_member;
395 static constexpr size_t _S_padding_bytes = _DataType::_S_padding_bytes;
400 using value_type = bool;
402 using abi_type = _Ap;
404 using iterator = _Base::iterator;
406 using const_iterator = _Base::const_iterator;
409 [[__gnu__::__always_inline__]]
410 static constexpr basic_mask
411 _S_init(
const _DataType& __x)
418 [[__gnu__::__always_inline__]]
420 _M_concat_data()
const
421 {
return _M_data._M_concat_data(); }
423 [[__gnu__::__always_inline__]]
424 constexpr const _DataType&
425 _M_get_ileav_data()
const
428 template <_ArchTraits _Traits = {}>
429 [[__gnu__::__always_inline__]]
430 static constexpr basic_mask
431 _S_partial_mask_of_n(
int __n)
432 {
return _S_init(_DataType::_S_partial_mask_of_n(__n * 2)); }
434 [[__gnu__::__always_inline__]]
435 static constexpr basic_mask
436 _S_and_neighbors(_DataType __k)
437 {
return _S_init(__k._M_and_neighbors()); }
439 [[__gnu__::__always_inline__]]
440 static constexpr basic_mask
441 _S_or_neighbors(_DataType __k)
442 {
return _S_init(__k._M_or_neighbors()); }
444 template <
typename _Mp>
445 [[__gnu__::__always_inline__]]
447 _M_chunk() const noexcept
449 if constexpr (_Mp::abi_type::_S_variant != _Ap::_S_variant)
451 using _M2 = resize_t<_S_size, _Mp>;
452 static_assert(!is_same_v<_M2, basic_mask>);
453 return static_cast<_M2
>(*this).template _M_chunk<_Mp>();
455 else if constexpr (_Mp::_S_size == 1)
457 constexpr auto [...__is] = _IotaArray<_S_size>;
458 return array{_Mp(_M_data[__is])...};
462 constexpr int __rem = _S_size % _Mp::_S_size;
463 const auto [...__xs] = _M_data.template _M_chunk<typename _Mp::_DataType>();
464 static_assert(is_same_v<
decltype(__to_cx_ileav(__xs...[0])), _Mp>);
465 if constexpr (__rem == 0)
466 return array{__to_cx_ileav(__xs)...};
468 return tuple(__to_cx_ileav(__xs)...);
472 [[__gnu__::__always_inline__]]
473 static constexpr const basic_mask&
474 _S_concat(
const basic_mask& __x0)
noexcept
477 template <
typename... _As>
478 requires (
sizeof...(_As) > 1)
479 [[__gnu__::__always_inline__]]
480 static constexpr basic_mask
481 _S_concat(
const basic_mask<_Bytes, _As>&... __xs)
noexcept
482 {
return basic_mask::_S_init(_DataType::_S_concat(__xs._M_get_ileav_data()...)); }
485 basic_mask() =
default;
488 template <__vec_builtin _TV>
489 [[__gnu__::__always_inline__]]
491 basic_mask(
const _TV& __x)
requires convertible_to<_TV, _DataType>
495 template <__vec_builtin _TV>
496 [[__gnu__::__always_inline__]]
498 operator _TV()
requires convertible_to<_DataType, _TV>
502 [[__gnu__::__always_inline__]]
504 basic_mask(same_as<bool>
auto __x)
noexcept
509 template <
size_t _UBytes,
typename _UAbi>
510 requires (_S_size == _UAbi::_S_size)
511 [[__gnu__::__always_inline__]]
512 constexpr explicit(__is_mask_conversion_explicit<_Ap, _UAbi>(_Bytes, _UBytes))
513 basic_mask(
const basic_mask<_UBytes, _UAbi>& __x) noexcept
515 using _UV = basic_mask<_UBytes, _UAbi>;
516 if constexpr (_UAbi::_S_is_cx_ileav)
521 else if constexpr (_S_use_bitmask || _UV::_S_use_bitmask)
522 return _DataType::_S_init(__duplicate_each_bit<_S_size>(__x._M_to_uint()));
525 else if constexpr (_UAbi::_S_is_cx_ctgus)
527 return basic_mask(__x._M_data)._M_data;
529 else if constexpr (_UV::_S_is_scalar || _S_is_scalar)
531 return _DataType([&](
int __i) {
return __x[__i / 2]; });
533 else if constexpr (_Bytes == _UBytes)
534 return _DataType::_S_recursive_bit_cast(__x);
535 else if constexpr (_Bytes <=
sizeof(0ll))
537 using _U2 = __similar_mask<__integer_from<_Bytes>, _S_size, _UAbi>;
538 return _DataType::_S_recursive_bit_cast(_U2(__x));
540 else if constexpr (_UBytes > 1)
542 using _U2 = __similar_mask<__integer_from<_UBytes / 2>, _S_size * 2, _UAbi>;
543 return _U2::_S_recursive_bit_cast(__x);
549 return basic_mask(__similar_mask<short, _UV::_S_size, _UAbi>(__x))._M_data;
553 using _Base::_MaskBase;
556 template <__simd_generator_invokable<
bool, _S_size> _Fp>
557 [[__gnu__::__always_inline__]]
559 basic_mask(_Fp&& __gen)
560 : _M_data([&] [[__gnu__::__always_inline__]] {
563 constexpr auto [...__is] = _IotaArray<_S_size>;
564 bool __tmp[_S_size] = {__gen(__simd_size_c<__is>)...};
565 return _DataType([&] [[__gnu__::__always_inline__]] (
size_t __i) {
566 return __tmp[__i / 2];
572 [[__gnu__::__always_inline__]]
574 basic_mask(
const same_as<bitset<_S_size>>
auto& __b)
noexcept
575 : _M_data(_DataType::_S_init(__duplicate_each_bit<_S_size>(
576 std::simd::__bitset_to_pairs(__b))))
580 template <
unsigned_
integral _Tp>
581 requires (!same_as<_Tp, bool>)
582 [[__gnu__::__always_inline__]]
584 basic_mask(_Tp __val) noexcept
585 : _M_data(__duplicate_each_bit<_S_size>(__val))
589 [[__gnu__::__always_inline__]]
591 operator[](__simd_size_type __i)
const
592 {
return _M_data[__i * 2]; }
595 [[__gnu__::__always_inline__]]
597 operator!() const noexcept
598 {
return _S_init(!_M_data); }
600 [[__gnu__::__always_inline__]]
602 operator+() const noexcept requires destructible<_VecType>
603 {
return operator _VecType(); }
608 [[__gnu__::__always_inline__]]
610 operator-() const noexcept requires destructible<_VecType>
612 using _Ip =
typename _VecType::value_type;
613 if constexpr (_S_use_bitmask)
614 return __select_impl(*
this, _Ip(-1), _Ip());
616 return __builtin_bit_cast(_VecType, -_M_data);
622 [[__gnu__::__always_inline__]]
624 operator~() const noexcept requires destructible<_VecType>
626 using _Ip =
typename _VecType::value_type;
627 if constexpr (_S_use_bitmask)
628 return __select_impl(*
this, _Ip(-2), _Ip(-1));
630 return __builtin_bit_cast(_VecType, _M_data) - _Ip(1);
634 operator~() const noexcept = delete;
637 template <typename _Up, typename _UAbi>
638 requires (_UAbi::_S_size == _S_size)
639 [[__gnu__::__always_inline__]]
640 constexpr explicit(sizeof(_Up) != _Bytes)
641 operator basic_vec<_Up, _UAbi>() const noexcept
643 using _Mp =
typename basic_vec<_Up, _UAbi>::mask_type;
644 return __select_impl(_Mp(*
this), basic_vec<_Up, _UAbi>(1), basic_vec<_Up, _UAbi>(0));
647 using _Base::operator basic_vec;
650 [[__gnu__::__always_inline__]]
651 constexpr bitset<_S_size>
652 to_bitset() const noexcept
653 {
return std::simd::__unwrap_pairs_to_bitset<_S_size>(_M_to_uint()); }
655 template <
int _Offset = 0, _ArchTraits _Traits = {}>
656 [[__gnu__::__always_inline__]]
659 {
return _M_data.template _M_to_uint<_Offset, true>(); }
661 [[__gnu__::__always_inline__]]
662 constexpr unsigned long long
664 {
return std::simd::__unwrap_pairs_to_ullong(_M_to_uint()); }
667 [[__gnu__::__always_inline__]]
668 friend constexpr basic_mask
669 operator&&(
const basic_mask& __x,
const basic_mask& __y)
noexcept
670 {
return _S_init(__x._M_data & __y._M_data); }
672 [[__gnu__::__always_inline__]]
673 friend constexpr basic_mask
674 operator||(
const basic_mask& __x,
const basic_mask& __y)
noexcept
675 {
return _S_init(__x._M_data | __y._M_data); }
677 [[__gnu__::__always_inline__]]
678 friend constexpr basic_mask
679 operator&(
const basic_mask& __x,
const basic_mask& __y)
noexcept
680 {
return _S_init(__x._M_data & __y._M_data); }
682 [[__gnu__::__always_inline__]]
683 friend constexpr basic_mask
684 operator|(
const basic_mask& __x,
const basic_mask& __y)
noexcept
685 {
return _S_init(__x._M_data | __y._M_data); }
687 [[__gnu__::__always_inline__]]
688 friend constexpr basic_mask
689 operator^(
const basic_mask& __x,
const basic_mask& __y)
noexcept
690 {
return _S_init(__x._M_data ^ __y._M_data); }
693 [[__gnu__::__always_inline__]]
694 friend constexpr basic_mask&
695 operator&=(basic_mask& __x,
const basic_mask& __y)
noexcept
697 __x._M_data &= __y._M_data;
701 [[__gnu__::__always_inline__]]
702 friend constexpr basic_mask&
703 operator|=(basic_mask& __x,
const basic_mask& __y)
noexcept
705 __x._M_data |= __y._M_data;
709 [[__gnu__::__always_inline__]]
710 friend constexpr basic_mask&
711 operator^=(basic_mask& __x,
const basic_mask& __y)
noexcept
713 __x._M_data ^= __y._M_data;
718 [[__gnu__::__always_inline__]]
719 friend constexpr basic_mask
720 operator==(
const basic_mask& __x,
const basic_mask& __y)
noexcept
721 {
return _S_init(__x._M_data == __y._M_data); }
723 [[__gnu__::__always_inline__]]
724 friend constexpr basic_mask
725 operator!=(
const basic_mask& __x,
const basic_mask& __y)
noexcept
726 {
return _S_init(__x._M_data != __y._M_data); }
728 [[__gnu__::__always_inline__]]
729 friend constexpr basic_mask
730 operator>=(
const basic_mask& __x,
const basic_mask& __y)
noexcept
731 {
return _S_init(__x._M_data >= __y._M_data); }
733 [[__gnu__::__always_inline__]]
734 friend constexpr basic_mask
735 operator<=(
const basic_mask& __x,
const basic_mask& __y)
noexcept
736 {
return _S_init(__x._M_data <= __y._M_data); }
738 [[__gnu__::__always_inline__]]
739 friend constexpr basic_mask
740 operator>(
const basic_mask& __x,
const basic_mask& __y)
noexcept
741 {
return _S_init(__x._M_data > __y._M_data); }
743 [[__gnu__::__always_inline__]]
744 friend constexpr basic_mask
745 operator<(
const basic_mask& __x,
const basic_mask& __y)
noexcept
746 {
return _S_init(__x._M_data < __y._M_data); }
749 [[__gnu__::__always_inline__]]
750 friend constexpr basic_mask
751 __select_impl(
const basic_mask& __k,
const basic_mask& __t,
const basic_mask& __f)
noexcept
752 {
return _S_init(__select_impl(__k._M_data, __t._M_data, __f._M_data)); }
754 [[__gnu__::__always_inline__]]
755 friend constexpr basic_mask
756 __select_impl(
const basic_mask& __k, same_as<bool>
auto __t, same_as<bool>
auto __f)
noexcept
757 {
return _S_init(__select_impl(__k._M_data, __t, __f)); }
759 template <__vectorizable _T0, same_as<_T0> _T1>
760 requires (
sizeof(_T0) == _Bytes)
761 [[__gnu__::__always_inline__]]
762 friend constexpr vec<_T0, _S_size>
763 __select_impl(
const basic_mask& __k,
const _T0& __t,
const _T1& __f)
noexcept
765 using _Vp = vec<_T0, _S_size>;
766 return __select_impl(
static_cast<typename _Vp::mask_type
>(__k), _Vp(__t), _Vp(__f));
770 [[__gnu__::__always_inline__]]
772 _M_all_of() const noexcept
773 {
return _M_data._M_all_of(); }
775 [[__gnu__::__always_inline__]]
777 _M_any_of() const noexcept
778 {
return _M_data._M_any_of(); }
780 [[__gnu__::__always_inline__]]
782 _M_none_of() const noexcept
783 {
return _M_data._M_none_of(); }
785 [[__gnu__::__always_inline__]]
786 constexpr __simd_size_type
787 _M_reduce_count() const noexcept
788 {
return _M_data._M_reduce_count() / 2; }
790 [[__gnu__::__always_inline__]]
791 constexpr __simd_size_type
792 _M_reduce_min_index()
const
793 {
return _M_data._M_reduce_min_index() / 2; }
795 [[__gnu__::__always_inline__]]
796 constexpr __simd_size_type
797 _M_reduce_max_index()
const
798 {
return _M_data._M_reduce_max_index() / 2; }
800 [[__gnu__::__always_inline__]]
801 friend constexpr bool
802 __is_const_known(
const basic_mask& __x)
803 {
return __is_const_known(__x._M_data); }
806 template <__vectorizable _Tp, __abi_tag _Ap>
807 requires __complex_like<_Tp> && _Ap::_S_is_cx_ileav && (_Ap::_S_size >= 2)
808 class basic_vec<_Tp, _Ap>
809 : public _VecBase<_Tp, _Ap>
811 template <
typename,
typename>
812 friend class basic_vec;
814 static constexpr int _S_size = _Ap::_S_size;
816 static constexpr int _S_full_size = __bit_ceil(
unsigned(_S_size));
818 using _T0 =
typename _Tp::value_type;
820 using _TSimd = __similar_vec<_T0, 2 * _S_size, _Ap>;
822 using _RealSimd = __similar_vec<_T0, _S_size, _Ap>;
826 static constexpr bool _S_use_bitmask = _TSimd::_S_use_bitmask;
828 static constexpr bool _S_is_partial =
sizeof(_M_data) >
sizeof(_Tp) * _S_size;
830 [[__gnu__::__always_inline__]]
831 static constexpr basic_vec
832 _S_init(
const _TSimd& __x)
840 using value_type = _Tp;
842 using mask_type = _VecBase<_Tp, _Ap>::mask_type;
845 [[__gnu__::__always_inline__]]
846 constexpr const _TSimd&
847 _M_get_ileav_data()
const
850 [[__gnu__::__always_inline__]]
851 constexpr const auto&
852 _M_get_low() const requires (_Ap::_S_nreg >= 2)
853 {
return _M_data._M_get_low(); }
855 [[__gnu__::__always_inline__]]
856 constexpr const auto&
857 _M_get_high() const requires (_Ap::_S_nreg >= 2)
858 {
return _M_data._M_get_high(); }
860 [[__gnu__::__always_inline__]]
861 friend constexpr bool
862 __is_const_known(
const basic_vec& __x)
863 {
return __is_const_known(__x._M_data); }
865 template <
typename _Vp>
866 [[__gnu__::__always_inline__]]
868 _M_chunk() const noexcept
870 if constexpr (_Vp::abi_type::_S_is_cx_ileav)
872 constexpr int __n = _S_size / _Vp::_S_size;
873 constexpr int __rem = _S_size % _Vp::_S_size;
874 const auto __chunked = _M_data.template _M_chunk<resize_t<_Vp::_S_size * 2,
876 constexpr auto [...__is] = _IotaArray<__n>;
877 if constexpr (__rem == 0)
878 return array<_Vp, __n> {_Vp::_S_init(__chunked[__is])...};
881 using _Rest = resize_t<__rem, _Vp>;
882 return tuple(_Vp::_S_init(get<__is>(__chunked))...,
883 _Rest::_S_init(get<__n>(__chunked)));
887 return resize_t<_S_size, _Vp>(*this).template _M_chunk<_Vp>();
890 [[__gnu__::__always_inline__]]
891 static constexpr const basic_vec&
892 _S_concat(
const basic_vec& __x0)
noexcept
895 template <
typename... _As>
896 requires (
sizeof...(_As) > 1)
897 [[__gnu__::__always_inline__]]
898 static constexpr basic_vec
899 _S_concat(
const basic_vec<value_type, _As>&... __xs)
noexcept
900 {
return basic_vec::_S_init(_TSimd::_S_concat(__xs._M_get_ileav_data()...)); }
902 template <
typename _BinaryOp>
903 [[__gnu__::__always_inline__]]
905 _M_reduce_to_register(_BinaryOp __binary_op)
const
907 if constexpr (_TSimd::abi_type::_S_nreg == 1)
911 auto [__lo, __hi] = _M_chunk<resize_t<__bit_ceil(
unsigned(_S_size)) / 2,
913 auto __a = __lo._M_reduce_to_register(__binary_op);
914 auto __b = __hi._M_reduce_to_register(__binary_op);
915 if constexpr (__a._S_size == __b._S_size)
916 return __binary_op(__a, __b);
919 using _V1 = resize_t<1, basic_vec>;
920 return __binary_op(_V1(__a._M_reduce(__binary_op)),
921 _V1(__b._M_reduce(__binary_op)));
926 template <
typename _BinaryOp, _ArchTraits _Traits = {}>
927 [[__gnu__::__always_inline__]]
929 _M_reduce(_BinaryOp __binary_op)
const
931 if constexpr (_S_size == 1)
932 return operator[](0);
933 else if constexpr (_Traits.template _M_eval_as_f32<_T0>())
934 return value_type(rebind_t<complex<float>, basic_vec>(*this)._M_reduce(__binary_op));
935 else if constexpr (_TSimd::abi_type::_S_nreg >= 2)
936 return _M_reduce_to_register(__binary_op)._M_reduce(__binary_op);
937 else if constexpr (__has_single_bit(
unsigned(_S_size)))
939 const auto [__a, __b] = _M_chunk<resize_t<_S_size / 2, basic_vec>>();
940 return __binary_op(__a, __b)._M_reduce(__binary_op);
944 const auto [__a, __b, __c, ...__rest]
945 = _M_chunk<resize_t<__bit_floor(
unsigned(_S_size)) / 2, basic_vec>>();
946 const auto __ab = __binary_op(__a, __b);
947 static_assert(
sizeof...(__rest) <= 1);
948 if constexpr (__a._S_size != __c._S_size)
949 return cat(__ab, __c)._M_reduce(__binary_op);
951 return cat(__binary_op(__ab, __c), __rest...)._M_reduce(__binary_op);
955 template <
typename _Up>
956 [[__gnu__::__always_inline__]]
957 static inline basic_vec
958 _S_partial_load(
const _Up* __mem,
size_t __n)
960 if constexpr (__complex_like<_Up>)
961 return _S_init(_TSimd::_S_partial_load(
962 reinterpret_cast<const typename _Up::value_type*
>(__mem), __n * 2));
964 return basic_vec(_RealSimd::_S_partial_load(__mem, __n));
967 template <
typename _Up, _ArchTraits _Traits = {}>
968 static inline basic_vec
969 _S_masked_load(
const _Up* __mem, mask_type __k)
971 if constexpr (__complex_like<_Up>)
972 return _S_init(_TSimd::_S_masked_load(
973 reinterpret_cast<const typename _Up::value_type*
>(__mem),
976 return basic_vec(_RealSimd::_S_masked_load(__mem,
typename _RealSimd::mask_type(__k)));
979 template <
typename _Up>
980 [[__gnu__::__always_inline__]]
982 _M_store(_Up* __mem)
const
984 static_assert(__complex_like<_Up>);
985 _M_data._M_store(
reinterpret_cast<typename _Up::value_type*
>(__mem));
988 template <
typename _Up>
989 [[__gnu__::__always_inline__]]
991 _S_partial_store(
const basic_vec& __v, _Up* __mem,
size_t __n)
993 static_assert(__complex_like<_Up>);
994 _TSimd::_S_partial_store(__v._M_data,
reinterpret_cast<typename _Up::value_type*
>(__mem),
998 template <
typename _Up>
999 [[__gnu__::__always_inline__]]
1001 _S_masked_store(
const basic_vec& __v, _Up* __mem,
const mask_type& __k)
1003 static_assert(__complex_like<_Up>);
1004 _TSimd::_S_masked_store(__v._M_data,
reinterpret_cast<typename _Up::value_type*
>(__mem),
1008 basic_vec() =
default;
1013 template <__broadcast_constructible<value_type> _Up>
1014 [[__gnu__::__always_inline__]]
1016 basic_vec(_Up&& __x) noexcept
1017 : _M_data([&](
int __i) {
1018 if constexpr (__complex_like<_Up>)
1019 return (__i & 1) == 0 ? __x.real() : __x.imag();
1021 return (__i & 1) == 0 ? __x : _T0();
1026 template <__complex_like _Up,
typename _UAbi>
1027 requires (_S_size == _UAbi::_S_size)
1028 && __explicitly_convertible_to<_Up, value_type>
1029 && _UAbi::_S_is_cx_ileav
1030 [[__gnu__::__always_inline__]]
1032 explicit(!convertible_to<_Up, value_type>)
1033 basic_vec(
const basic_vec<_Up, _UAbi>& __x) noexcept
1034 : _M_data(__x._M_data)
1037 template <__complex_like _Up,
typename _UAbi>
1038 requires (_S_size == _UAbi::_S_size)
1039 && __explicitly_convertible_to<_Up, value_type>
1040 && (!_UAbi::_S_is_cx_ileav)
1041 [[__gnu__::__always_inline__]]
1043 explicit(!convertible_to<_Up, value_type>)
1044 basic_vec(
const basic_vec<_Up, _UAbi>& __x) noexcept
1045 : basic_vec(
static_cast<_RealSimd
>(__x._M_real),
static_cast<_RealSimd
>(__x._M_imag))
1048 template <
typename _Up,
typename _UAbi>
1049 requires (!__complex_like<_Up>)
1050 && (_S_size == _UAbi::_S_size)
1051 && __explicitly_convertible_to<_Up, value_type>
1052 [[__gnu__::__always_inline__]]
1054 explicit(!convertible_to<_Up, value_type>)
1055 basic_vec(
const basic_vec<_Up, _UAbi>& __x) noexcept
1056 : basic_vec(_RealSimd(__x))
1059 using _VecBase<_Tp, _Ap>::_VecBase;
1062 template <__simd_generator_invokable<value_type, _S_size> _Fp>
1063 [[__gnu__::__always_inline__]]
1065 basic_vec(_Fp&& __gen)
1067 using _Arr =
std::array<value_type,
sizeof(_TSimd) /
sizeof(value_type)>;
1068 constexpr auto [...__is] = _IotaArray<_S_size>;
1069 const _Arr __tmp = {
static_cast<value_type
>(__gen(__simd_size_c<__is>))... };
1070 return __builtin_bit_cast(_TSimd, __tmp);
1075 template <__complex_like _Up>
1076 [[__gnu__::__always_inline__]]
1078 basic_vec(_LoadCtorTag,
const _Up* __ptr)
1082 return _TSimd([&](
int __i) {
1083 const _Up& __cx = __ptr[__i / 2];
1084 return static_cast<_T0
>(__i % 2 == 0 ? __cx.real() : __cx.imag());
1089 return _TSimd(_LoadCtorTag(),
1090 reinterpret_cast<const typename _Up::value_type*
>(__ptr));
1095 template <
typename _Up>
1096 [[__gnu__::__always_inline__]]
1098 basic_vec(_LoadCtorTag,
const _Up* __ptr)
1099 : basic_vec(_RealSimd(_LoadCtorTag(), __ptr))
1102 template <ranges::contiguous_range _Rg,
typename... _Flags>
1103 requires ranges::__static_sized_range<_Rg> && (ranges::__static_size<_Rg>() == _S_size)
1104 && __vectorizable<ranges::range_value_t<_Rg>>
1105 && __explicitly_convertible_to<ranges::range_value_t<_Rg>, value_type>
1106 [[__gnu__::__always_inline__]]
1108 basic_vec(_Rg&& __range, flags<_Flags...> __flags = {})
1109 : basic_vec(_LoadCtorTag(), __flags.template _S_adjust_pointer<basic_vec>(
1110 ranges::data(__range)))
1112 static_assert(__loadstore_convertible_to<ranges::range_value_t<_Rg>, value_type,
1118 [[__gnu__::__always_inline__]]
1120 basic_vec(
const _RealSimd& __re,
const _RealSimd& __im = {})
noexcept
1122 __cxileav::__set_real(_M_data, __re);
1123 __cxileav::__set_imag(_M_data, __im);
1127 [[__gnu__::__always_inline__]]
1128 constexpr value_type
1129 operator[](__simd_size_type __i)
const
1130 {
return value_type(_M_data[__i * 2], _M_data[__i * 2 + 1]); }
1133 [[__gnu__::__always_inline__]]
1134 constexpr basic_vec&
1135 operator++() noexcept requires requires(value_type __a) { ++__a; }
1137 _M_data += value_type(_T0(1));
1141 [[__gnu__::__always_inline__]]
1143 operator++(
int)
noexcept requires requires(value_type __a) { __a++; }
1145 basic_vec __r = *
this;
1146 _M_data += value_type(_T0(1));
1150 [[__gnu__::__always_inline__]]
1151 constexpr basic_vec&
1152 operator--() noexcept requires requires(value_type __a) { --__a; }
1154 _M_data -= value_type(_T0(1));
1158 [[__gnu__::__always_inline__]]
1160 operator--(
int)
noexcept requires requires(value_type __a) { __a--; }
1162 basic_vec __r = *
this;
1163 _M_data -= value_type(_T0(1));
1167 [[__gnu__::__always_inline__]]
1169 operator!() const noexcept requires requires(value_type __a) { !__a; }
1170 {
return _S_init(!_M_data); }
1172 [[__gnu__::__always_inline__]]
1174 operator+() const noexcept requires requires(value_type __a) { +__a; }
1177 [[__gnu__::__always_inline__]]
1179 operator-() const noexcept requires requires(value_type __a) { -__a; }
1181 basic_vec __r = *
this;
1182 __r._M_data = -_M_data;
1187 [[__gnu__::__always_inline__]]
1188 friend constexpr basic_vec&
1189 operator+=(basic_vec& __x,
const basic_vec& __y)
noexcept
1190 requires requires(value_type __a) { __a + __a; }
1192 __x._M_data += __y._M_data;
1196 [[__gnu__::__always_inline__]]
1197 friend constexpr basic_vec&
1198 operator-=(basic_vec& __x,
const basic_vec& __y)
noexcept
1199 requires requires(value_type __a) { __a - __a; }
1201 __x._M_data -= __y._M_data;
1205 template <_TargetTraits _Traits = {}>
1206 [[__gnu__::__always_inline__]]
1207 friend constexpr basic_vec&
1208 operator*=(basic_vec& __x,
const basic_vec& __y)
noexcept
1209 requires requires(value_type __a) { __a * __a; }
1211 __cxileav::__mul<value_type, _Traits>(__x._M_data, __y._M_data);
1215 template <
int _RemoveMe = 0>
1216 [[__gnu__::__always_inline__]]
1217 friend constexpr basic_vec&
1218 operator/=(basic_vec& __x,
const basic_vec& __y)
noexcept
1219 requires requires(value_type __a) { __a / __a; }
1221 static_assert(
false,
"TODO");
1225 [[__gnu__::__always_inline__]]
1226 friend constexpr mask_type
1227 operator==(
const basic_vec& __x,
const basic_vec& __y)
noexcept
1228 {
return mask_type::_S_and_neighbors(__x._M_data == __y._M_data); }
1230 [[__gnu__::__always_inline__]]
1231 friend constexpr mask_type
1232 operator!=(
const basic_vec& __x,
const basic_vec& __y)
noexcept
1233 {
return mask_type::_S_or_neighbors(__x._M_data != __y._M_data); }
1237 [[__gnu__::__always_inline__]]
1239 real() const noexcept
1240 {
return permute<_S_size>(_M_data, [](
int __i) {
return __i * 2; }); }
1242 [[__gnu__::__always_inline__]]
1244 imag() const noexcept
1245 {
return permute<_S_size>(_M_data, [](
int __i) {
return __i * 2 + 1; }); }
1247 [[__gnu__::__always_inline__]]
1249 real(
const _RealSimd& __x)
noexcept
1250 { __cxileav::__set_real(_M_data, __x); }
1252 [[__gnu__::__always_inline__]]
1254 imag(
const _RealSimd& __x)
noexcept
1255 { __cxileav::__set_imag(_M_data, __x); }
1258 [[__gnu__::__always_inline__]]
1259 friend constexpr basic_vec
1260 __select_impl(
const mask_type& __k,
const basic_vec& __t,
const basic_vec& __f)
noexcept
1261 {
return _S_init(__select_impl(__k._M_data, __t._M_data, __f._M_data)); }
1264 [[__gnu__::__always_inline__]]
1269 [[__gnu__::__always_inline__]]
1275 return __re * __re + __im * __im;
1278 [[__gnu__::__always_inline__]]
1281 {
return _S_init(__cxileav::__negate_imag(_M_data)); }
1299 template <
typename _Cx, _TargetTraits, __vec_builtin _TV,
typename _Kp>
1300 [[__gnu__::__cold__, __gnu__::__noinline__]]
1302 __redo_mul(_TV& __re, _TV& __im,
const _TV __re0,
const _TV __im0,
1303 const _TV __re1,
const _TV __im1,
const _Kp __nan,
int __n)
1305 for (
int __i = 0; __i < __n; ++__i)
1308 if constexpr (is_integral_v<_Kp>)
1309 __isnan = (__nan & (_Kp(1) << __i)) != 0;
1311 __isnan = __nan[__i] != 0;
1314 const _Cx __c0(__re0[__i], __im0[__i]);
1315 const _Cx __c1(__re1[__i], __im1[__i]);
1316 const _Cx __cr = __c0 * __c1;
1317 __vec_set(__re, __i, __cr.real());
1318 __vec_set(__im, __i, __cr.imag());
1327 template <
typename _Cx, _TargetTraits _Traits,
typename _Tp,
typename _Ap>
1328 [[__gnu__::__always_inline__]]
1330 __mul(basic_vec<_Tp, _Ap>& __re0, basic_vec<_Tp, _Ap>& __im0,
1331 const basic_vec<_Tp, _Ap>& __re1,
const basic_vec<_Tp, _Ap>& __im1)
1333 static_assert(__complex_like<_Cx>);
1334 if constexpr (_Ap::_S_nreg >= 2)
1336 __mul<_Cx, _Traits>(__re0._M_get_low(), __im0._M_get_low(),
1337 __re1._M_get_low(), __im1._M_get_low());
1338 __mul<_Cx, _Traits>(__re0._M_get_high(), __im0._M_get_high(),
1339 __re1._M_get_high(), __im1._M_get_high());
1341 else if constexpr (_Ap::_S_size == 1)
1343 const _Cx __c0(__re0._M_get(), __im0._M_get());
1344 const _Cx __c1(__re1._M_get(), __im1._M_get());
1345 const _Cx __cr = __c0 * __c1;
1346 __re0._M_get() = __cr.real();
1347 __im0._M_get() = __cr.imag();
1349 else if constexpr (_Traits.template _M_eval_as_f32<_Tp>())
1351 using _Vf = rebind_t<float, basic_vec<_Tp, _Ap>>;
1352 using _Cf = complex<float>;
1355 __mul<_Cf, _Traits, float, typename _Vf::abi_type>(__re0f, __im0f, __re1, __im1);
1356 __re0 =
static_cast<basic_vec<_Tp, _Ap>
>(__re0f);
1357 __im0 =
static_cast<basic_vec<_Tp, _Ap>
>(__im0f);
1361 basic_vec<_Tp, _Ap> __re = __re0 * __re1 - __im0 * __im1;
1362 basic_vec<_Tp, _Ap> __im = __re0 * __im1 + __im0 * __re1;
1363 const auto __nan = __re._M_isunordered(__im);
1364 if (__nan._M_any_of()) [[unlikely]]
1365 __redo_mul<_Cx, _Traits>(__re._M_get(), __im._M_get(), __re0._M_get(), __im0._M_get(),
1366 __re1._M_get(), __im1._M_get(),
1367 __nan._M_concat_data(), _Ap::_S_size);
1374 template <
size_t _Bytes, __abi_tag _Ap>
1375 requires _Ap::_S_is_cx_ctgus && (_Ap::_S_size >= 2)
1376 class basic_mask<_Bytes, _Ap>
1377 : public _MaskBase<_Bytes, _Ap>
1379 using _Base = _MaskBase<_Bytes, _Ap>;
1381 using _VecType = _Base::_VecType;
1383 template <
size_t,
typename>
1384 friend class basic_mask;
1386 template <
typename,
typename>
1387 friend class basic_vec;
1389 static constexpr int _S_size = _Ap::_S_size;
1391 using _DataType = __component_mask_for_ctgus<_Bytes, _Ap>;
1393 static_assert(_DataType::abi_type::_S_nreg == _Ap::_S_nreg);
1395 static constexpr bool _S_is_scalar = _DataType::_S_is_scalar;
1397 static constexpr bool _S_use_bitmask = _DataType::_S_use_bitmask;
1399 static constexpr int _S_full_size = _DataType::_S_full_size;
1401 static constexpr bool _S_is_partial = _DataType::_S_is_partial;
1403 static constexpr bool _S_has_bool_member = _DataType::_S_has_bool_member;
1405 static constexpr size_t _S_padding_bytes = _DataType::_S_padding_bytes;
1410 using value_type = bool;
1412 using abi_type = _Ap;
1415 [[__gnu__::__always_inline__]]
1416 static constexpr basic_mask
1417 _S_init(
const _DataType& __x)
1424 [[__gnu__::__always_inline__]]
1425 constexpr const _DataType&
1429 [[__gnu__::__always_inline__]]
1431 _M_concat_data()
const
1432 {
return _M_data._M_concat_data(); }
1434 template <_ArchTraits _Traits = {}>
1435 [[__gnu__::__always_inline__]]
1436 static constexpr basic_mask
1437 _S_partial_mask_of_n(
int __n)
1438 {
return _S_init(_DataType::_S_partial_mask_of_n(__n)); }
1440 template <
typename _Mp>
1441 [[__gnu__::__always_inline__]]
1443 _M_chunk() const noexcept
1445 if constexpr (_Mp::abi_type::_S_variant != _Ap::_S_variant)
1447 using _M2 = resize_t<_S_size, _Mp>;
1448 static_assert(!is_same_v<_M2, basic_mask>);
1449 return static_cast<_M2
>(*this).template _M_chunk<_Mp>();
1451 else if constexpr (_Mp::_S_size == 1)
1453 constexpr auto [...__is] = _IotaArray<_S_size>;
1454 return array{_Mp(_M_data[__is])...};
1458 constexpr int __rem = _S_size % _Mp::_S_size;
1459 const auto [...__xs, __last] = _M_data.template _M_chunk<typename _Mp::_DataType>();
1460 if constexpr (__rem == 0)
1461 return array{_Mp::_S_init(__xs)..., _Mp::_S_init(__last)};
1463 return tuple(_Mp::_S_init(__xs)..., resize_t<__rem, _Mp>(__last));
1467 [[__gnu__::__always_inline__]]
1468 static constexpr const basic_mask&
1469 _S_concat(
const basic_mask& __x0)
noexcept
1478 [[__gnu__::__always_inline__]]
1479 constexpr const _DataType&
1480 _M_get_ctgus_data() const noexcept
1483 template <
typename... _As>
1484 requires (
sizeof...(_As) > 1)
1485 [[__gnu__::__always_inline__]]
1486 static constexpr basic_mask
1487 _S_concat(
const basic_mask<_Bytes, _As>&... __xs)
noexcept
1488 {
return basic_mask::_S_init(_DataType::_S_concat(__xs._M_get_ctgus_data()...)); }
1491 basic_mask() =
default;
1494 template <__vec_builtin _TV>
1495 [[__gnu__::__always_inline__]]
1497 basic_mask(
const _TV& __x)
requires convertible_to<_TV, _DataType>
1501 template <__vec_builtin _TV>
1502 [[__gnu__::__always_inline__]]
1504 operator _TV()
requires convertible_to<_DataType, _TV>
1508 [[__gnu__::__always_inline__]]
1510 basic_mask(same_as<bool>
auto __x)
noexcept
1515 template <
size_t _UBytes,
typename _UAbi>
1516 requires (_S_size == _UAbi::_S_size)
1517 [[__gnu__::__always_inline__]]
1518 constexpr explicit(__is_mask_conversion_explicit<_Ap, _UAbi>(_Bytes, _UBytes))
1519 basic_mask(
const basic_mask<_UBytes, _UAbi>& __x) noexcept
1523 using _Base::_MaskBase;
1526 template <__simd_generator_invokable<
bool, _S_size> _Fp>
1527 [[__gnu__::__always_inline__]]
1529 basic_mask(_Fp&& __gen)
1534 [[__gnu__::__always_inline__]]
1536 basic_mask(
const same_as<bitset<_S_size>>
auto& __b)
noexcept
1541 template <
unsigned_
integral _Tp>
1542 requires (!same_as<_Tp, bool>)
1543 [[__gnu__::__always_inline__]]
1545 basic_mask(_Tp __val) noexcept
1550 [[__gnu__::__always_inline__]]
1551 constexpr value_type
1552 operator[](__simd_size_type __i)
const
1553 {
return _M_data[__i]; }
1556 [[__gnu__::__always_inline__]]
1557 constexpr basic_mask
1558 operator!() const noexcept
1559 {
return _S_init(!_M_data); }
1561 [[__gnu__::__always_inline__]]
1563 operator+() const noexcept requires destructible<_VecType>
1564 {
return static_cast<_VecType
>(_M_data); }
1569 [[__gnu__::__always_inline__]]
1571 operator-() const noexcept requires destructible<_VecType>
1573 using _Ip =
typename _VecType::value_type;
1574 if constexpr (_S_use_bitmask)
1575 return __select_impl(*
this, _Ip(-1), _Ip());
1583 [[__gnu__::__always_inline__]]
1585 operator~() const noexcept requires destructible<_VecType>
1587 using _Ip =
typename _VecType::value_type;
1588 if constexpr (_S_use_bitmask)
1589 return __select_impl(*
this, _Ip(-2), _Ip(-1));
1595 operator~() const noexcept = delete;
1598 template <typename _Up, typename _UAbi>
1599 requires (_UAbi::_S_size == _S_size)
1600 [[__gnu__::__always_inline__]]
1601 constexpr explicit(sizeof(_Up) != _Bytes)
1602 operator basic_vec<_Up, _UAbi>() const noexcept
1604 using _UV = basic_vec<_Up, _UAbi>;
1605 using _Mp =
typename _UV::mask_type;
1606 return __select_impl(
static_cast<_Mp
>(_M_data), _UV(1), _UV(0));
1609 using _Base::operator basic_vec;
1612 [[__gnu__::__always_inline__]]
1613 constexpr bitset<_S_size>
1614 to_bitset() const noexcept
1615 {
return _M_data.to_bitset(); }
1617 template <
int _Offset = 0, _ArchTraits _Traits = {}>
1618 [[__gnu__::__always_inline__]]
1621 {
return _M_data.template _M_to_uint<_Offset>(); }
1623 [[__gnu__::__always_inline__]]
1624 constexpr unsigned long long
1626 {
return _M_data.to_ullong(); }
1629 [[__gnu__::__always_inline__]]
1630 friend constexpr basic_mask
1631 operator&&(
const basic_mask& __x,
const basic_mask& __y)
noexcept
1632 {
return _S_init(__x._M_data & __y._M_data); }
1634 [[__gnu__::__always_inline__]]
1635 friend constexpr basic_mask
1636 operator||(
const basic_mask& __x,
const basic_mask& __y)
noexcept
1637 {
return _S_init(__x._M_data | __y._M_data); }
1639 [[__gnu__::__always_inline__]]
1640 friend constexpr basic_mask
1641 operator&(
const basic_mask& __x,
const basic_mask& __y)
noexcept
1642 {
return _S_init(__x._M_data & __y._M_data); }
1644 [[__gnu__::__always_inline__]]
1645 friend constexpr basic_mask
1646 operator|(
const basic_mask& __x,
const basic_mask& __y)
noexcept
1647 {
return _S_init(__x._M_data | __y._M_data); }
1649 [[__gnu__::__always_inline__]]
1650 friend constexpr basic_mask
1651 operator^(
const basic_mask& __x,
const basic_mask& __y)
noexcept
1652 {
return _S_init(__x._M_data ^ __y._M_data); }
1655 [[__gnu__::__always_inline__]]
1656 friend constexpr basic_mask&
1657 operator&=(basic_mask& __x,
const basic_mask& __y)
noexcept
1659 __x._M_data &= __y._M_data;
1663 [[__gnu__::__always_inline__]]
1664 friend constexpr basic_mask&
1665 operator|=(basic_mask& __x,
const basic_mask& __y)
noexcept
1667 __x._M_data |= __y._M_data;
1671 [[__gnu__::__always_inline__]]
1672 friend constexpr basic_mask&
1673 operator^=(basic_mask& __x,
const basic_mask& __y)
noexcept
1675 __x._M_data ^= __y._M_data;
1680 [[__gnu__::__always_inline__]]
1681 friend constexpr basic_mask
1682 operator==(
const basic_mask& __x,
const basic_mask& __y)
noexcept
1683 {
return _S_init(__x._M_data == __y._M_data); }
1685 [[__gnu__::__always_inline__]]
1686 friend constexpr basic_mask
1687 operator!=(
const basic_mask& __x,
const basic_mask& __y)
noexcept
1688 {
return _S_init(__x._M_data != __y._M_data); }
1690 [[__gnu__::__always_inline__]]
1691 friend constexpr basic_mask
1692 operator>=(
const basic_mask& __x,
const basic_mask& __y)
noexcept
1693 {
return _S_init(__x._M_data >= __y._M_data); }
1695 [[__gnu__::__always_inline__]]
1696 friend constexpr basic_mask
1697 operator<=(
const basic_mask& __x,
const basic_mask& __y)
noexcept
1698 {
return _S_init(__x._M_data <= __y._M_data); }
1700 [[__gnu__::__always_inline__]]
1701 friend constexpr basic_mask
1702 operator>(
const basic_mask& __x,
const basic_mask& __y)
noexcept
1703 {
return _S_init(__x._M_data > __y._M_data); }
1705 [[__gnu__::__always_inline__]]
1706 friend constexpr basic_mask
1707 operator<(
const basic_mask& __x,
const basic_mask& __y)
noexcept
1708 {
return _S_init(__x._M_data < __y._M_data); }
1711 [[__gnu__::__always_inline__]]
1712 friend constexpr basic_mask
1713 __select_impl(
const basic_mask& __k,
const basic_mask& __t,
const basic_mask& __f)
noexcept
1714 {
return __select_impl(__k._M_data, __t._M_data, __f._M_data); }
1716 [[__gnu__::__always_inline__]]
1717 friend constexpr basic_mask
1718 __select_impl(
const basic_mask& __k, same_as<bool>
auto __t, same_as<bool>
auto __f)
noexcept
1719 {
return _S_init(__select_impl(__k._M_data, __t, __f)); }
1721 template <__vectorizable _T0, same_as<_T0> _T1>
1722 requires (
sizeof(_T0) == _Bytes)
1723 [[__gnu__::__always_inline__]]
1724 friend constexpr vec<_T0, _S_size>
1725 __select_impl(
const basic_mask& __k,
const _T0& __t,
const _T1& __f)
noexcept
1727 using _Vp = vec<_T0, _S_size>;
1728 return __select_impl(
static_cast<typename _Vp::mask_type
>(__k), _Vp(__t), _Vp(__f));
1732 [[__gnu__::__always_inline__]]
1734 _M_all_of() const noexcept
1735 {
return _M_data._M_all_of(); }
1737 [[__gnu__::__always_inline__]]
1739 _M_any_of() const noexcept
1740 {
return _M_data._M_any_of(); }
1742 [[__gnu__::__always_inline__]]
1744 _M_none_of() const noexcept
1745 {
return _M_data._M_none_of(); }
1747 [[__gnu__::__always_inline__]]
1748 constexpr __simd_size_type
1749 _M_reduce_count() const noexcept
1750 {
return _M_data._M_reduce_count(); }
1752 [[__gnu__::__always_inline__]]
1753 constexpr __simd_size_type
1754 _M_reduce_min_index()
const
1755 {
return _M_data._M_reduce_min_index(); }
1757 [[__gnu__::__always_inline__]]
1758 constexpr __simd_size_type
1759 _M_reduce_max_index()
const
1760 {
return _M_data._M_reduce_max_index(); }
1762 [[__gnu__::__always_inline__]]
1763 friend constexpr bool
1764 __is_const_known(
const basic_mask& __x)
1765 {
return __is_const_known(__x._M_data); }
1768 template <__vectorizable _Tp, __abi_tag _Ap>
1769 requires __complex_like<_Tp> && (_Ap::_S_is_cx_ctgus || _Ap::_S_size == 1)
1770 class basic_vec<_Tp, _Ap>
1771 : public _VecBase<_Tp, _Ap>
1773 template <
typename,
typename>
1774 friend class basic_vec;
1776 static constexpr int _S_size = _Ap::_S_size;
1778 static constexpr int _S_full_size = __bit_ceil(
unsigned(_S_size));
1780 using _T0 =
typename _Tp::value_type;
1782 using _RealSimd = __similar_vec<_T0, _S_size, _Ap>;
1784 _RealSimd _M_real = {};
1786 _RealSimd _M_imag = {};
1788 static constexpr bool _S_is_scalar = _RealSimd::_S_is_scalar;
1790 static constexpr bool _S_use_bitmask = _RealSimd::_S_use_bitmask;
1792 static constexpr bool _S_is_partial = _RealSimd::_S_is_partial;
1795 using value_type = _Tp;
1797 using mask_type = _VecBase<_Tp, _Ap>::mask_type;
1800 [[__gnu__::__always_inline__]]
1801 constexpr _RealSimd&
1802 _M_get_real() noexcept
1805 [[__gnu__::__always_inline__]]
1806 constexpr const _RealSimd&
1807 _M_get_real() const noexcept
1810 [[__gnu__::__always_inline__]]
1811 constexpr _RealSimd&
1812 _M_get_imag() noexcept
1815 [[__gnu__::__always_inline__]]
1816 constexpr const _RealSimd&
1817 _M_get_imag() const noexcept
1820 [[__gnu__::__always_inline__]]
1822 _M_get_low() const requires (_Ap::_S_nreg >= 2)
1824 return resize_t<_M_real._N0, basic_vec>(
1825 _M_real._M_get_low(), _M_imag._M_get_low());
1828 [[__gnu__::__always_inline__]]
1830 _M_get_high() const requires (_Ap::_S_nreg >= 2)
1832 return resize_t<_M_real._N1, basic_vec>(
1833 _M_real._M_get_high(), _M_imag._M_get_high());
1836 [[__gnu__::__always_inline__]]
1838 _M_concat_data(
bool =
false) const
1839 requires (_S_size == 1)
1841 return __vec_builtin_type<__canonical_vec_type_t<_T0>, 2>{
1842 _M_real._M_data, _M_imag._M_data
1846 [[__gnu__::__always_inline__]]
1848 _M_get_ileav_data() const
1849 requires (_S_size == 1 && _Ap::_S_is_cx_ileav)
1850 {
return __builtin_bit_cast(__similar_vec<_T0, 2, _Ap>, *
this); }
1852 [[__gnu__::__always_inline__]]
1853 static constexpr basic_vec
1854 _S_init(
const __similar_vec<_T0, 2, _Ap>& __x)
1855 requires (_S_size == 1 && _Ap::_S_is_cx_ileav)
1856 {
return __builtin_bit_cast(basic_vec, __x); }
1858 [[__gnu__::__always_inline__]]
1859 friend constexpr bool
1860 __is_const_known(
const basic_vec& __x)
1861 {
return __is_const_known(__x._M_real) && __is_const_known(__x._M_imag); }
1863 template <
typename _Vp>
1864 [[__gnu__::__always_inline__]]
1866 _M_chunk() const noexcept
1868 constexpr int __n = _S_size / _Vp::_S_size;
1869 constexpr int __rem = _S_size % _Vp::_S_size;
1870 const auto [...__rs, __rN] = _M_real.template _M_chunk<typename _Vp::_RealSimd>();
1871 const auto [...__is, __iN] = _M_imag.template _M_chunk<typename _Vp::_RealSimd>();
1872 if constexpr (__rem == 0)
1873 return array<_Vp, __n>{_Vp(__rs, __is)..., _Vp(__rN, __iN)};
1875 return tuple(_Vp(__rs, __is)..., resize_t<__rem, _Vp>(__rN, __iN));
1878 template <
typename _A0>
1879 [[__gnu__::__always_inline__]]
1880 static constexpr basic_vec
1881 _S_concat(
const basic_vec<value_type, _A0>& __x0)
noexcept
1882 {
return static_cast<basic_vec
>(__x0); }
1884 template <
typename... _As>
1885 requires (
sizeof...(_As) > 1)
1886 [[__gnu__::__always_inline__]]
1887 static constexpr basic_vec
1888 _S_concat(
const basic_vec<value_type, _As>&... __xs)
noexcept
1889 {
return {_RealSimd::_S_concat(__xs._M_real...), _RealSimd::_S_concat(__xs._M_imag...) }; }
1891 template <
typename _BinaryOp>
1892 [[__gnu__::__always_inline__]]
1894 _M_reduce_to_register(_BinaryOp __binary_op)
const
1896 if constexpr (_RealSimd::abi_type::_S_nreg == 1)
1900 auto [__lo, __hi] = _M_chunk<resize_t<_RealSimd::_N0, basic_vec>>();
1901 auto __a = __lo._M_reduce_to_register(__binary_op);
1902 auto __b = __hi._M_reduce_to_register(__binary_op);
1903 if constexpr (__a._S_size == __b._S_size)
1904 return __binary_op(__a, __b);
1907 using _V1 = resize_t<1, basic_vec>;
1908 return __binary_op(_V1(__a._M_reduce(__binary_op)),
1909 _V1(__b._M_reduce(__binary_op)));
1914 template <
typename _BinaryOp, _ArchTraits _Traits = {}>
1915 [[__gnu__::__always_inline__]]
1916 constexpr value_type
1917 _M_reduce(_BinaryOp __binary_op)
const
1919 if constexpr (_S_size == 1)
1920 return operator[](0);
1921 else if constexpr (_Traits.template _M_eval_as_f32<_T0>())
1922 return value_type(rebind_t<complex<float>, basic_vec>(*this)._M_reduce(__binary_op));
1923 else if constexpr (_RealSimd::abi_type::_S_nreg >= 2)
1924 return _M_reduce_to_register(__binary_op)._M_reduce(__binary_op);
1925 else if constexpr (__has_single_bit(
unsigned(_S_size)))
1927 const auto [__a, __b] = _M_chunk<resize_t<_S_size / 2, basic_vec>>();
1928 return __binary_op(__a, __b)._M_reduce(__binary_op);
1932 const auto [__a, __b, __c, ...__rest]
1933 = _M_chunk<resize_t<__bit_floor(
unsigned(_S_size)) / 2, basic_vec>>();
1934 const auto __ab = __binary_op(__a, __b);
1935 static_assert(
sizeof...(__rest) <= 1);
1936 if constexpr (__a._S_size != __c._S_size)
1937 return cat(__ab, __c)._M_reduce(__binary_op);
1939 return cat(__binary_op(__ab, __c), __rest...)._M_reduce(__binary_op);
1954 template <
typename _Up>
1955 [[__gnu__::__always_inline__]]
1956 static inline basic_vec
1957 _S_partial_load(
const _Up* __mem,
size_t __n)
1959 if constexpr (__complex_like<_Up>)
1961 _RealSimd([&](
size_t __i) -> _T0 {
1962 return __i < __n ? __mem[__i].real() : _T0();
1964 _RealSimd([&](
size_t __i) -> _T0 {
1965 return __i < __n ? __mem[__i].imag() : _T0();
1968 return basic_vec(_RealSimd::_S_partial_load(__mem, __n));
1975 template <
typename _Up, _ArchTraits _Traits = {}>
1976 static inline basic_vec
1977 _S_masked_load(
const _Up* __mem, mask_type __k)
1979 if constexpr (__complex_like<_Up>)
1981 return basic_vec(_RealSimd([&](
int __i) {
1982 return __k[__i] ? __mem[__i].real() : _T0();
1984 _RealSimd([&](
int __i) {
1985 return __k[__i] ? __mem[__i].imag() : _T0();
1989 return basic_vec(_RealSimd::_S_masked_load(__mem,
typename _RealSimd::mask_type(__k)));
1992 template <
typename _Up>
1993 [[__gnu__::__always_inline__]]
1995 _M_store(_Up* __mem)
const
1997 static_assert(__complex_like<_Up>);
1998 for (
int __i = 0; __i < _S_size; ++__i)
2000 __mem[__i].real(_M_real[__i]);
2001 __mem[__i].imag(_M_imag[__i]);
2005 template <
typename _Up>
2006 [[__gnu__::__always_inline__]]
2008 _S_partial_store(
const basic_vec& __v, _Up* __mem,
size_t __n)
2010 static_assert(__complex_like<_Up>);
2011 for (
size_t __i = 0; __i <
std::min(__n,
size_t(_S_size)); ++__i)
2013 __mem[__i].real(__v._M_real[__i]);
2014 __mem[__i].imag(__v._M_imag[__i]);
2018 template <
typename _Up>
2019 [[__gnu__::__always_inline__]]
2021 _S_masked_store(
const basic_vec& __v, _Up* __mem,
const mask_type& __k)
2024 static_assert(__complex_like<_Up>);
2025 for (
int __i = 0; __i < _S_size; ++__i)
2028 __mem[__i] = __v[__i];
2032 basic_vec() =
default;
2037 template <__broadcast_constructible<value_type> _Up>
2038 requires __complex_like<_Up>
2039 [[__gnu__::__always_inline__]]
2041 basic_vec(_Up&& __x) noexcept
2042 : _M_real(__x.real()), _M_imag(__x.imag())
2045 template <__broadcast_constructible<value_type> _Up>
2046 [[__gnu__::__always_inline__]]
2048 basic_vec(_Up&& __x) noexcept
2049 : _M_real(__x), _M_imag()
2053 template <__complex_like _Up,
typename _UAbi>
2054 requires (_S_size == _UAbi::_S_size)
2055 && __explicitly_convertible_to<_Up, value_type>
2056 && _UAbi::_S_is_cx_ileav
2057 [[__gnu__::__always_inline__]]
2059 explicit(!convertible_to<_Up, value_type>)
2060 basic_vec(
const basic_vec<_Up, _UAbi>& __x) noexcept
2061 : _M_real(__x.real()), _M_imag(__x.imag())
2064 template <__complex_like _Up,
typename _UAbi>
2065 requires (_S_size == _UAbi::_S_size)
2066 && __explicitly_convertible_to<_Up, value_type>
2067 && (!_UAbi::_S_is_cx_ileav)
2068 [[__gnu__::__always_inline__]]
2070 explicit(!convertible_to<_Up, value_type>)
2071 basic_vec(
const basic_vec<_Up, _UAbi>& __x) noexcept
2072 : _M_real(__x._M_real), _M_imag(__x._M_imag)
2076 template <
typename _Up,
typename _UAbi>
2077 requires (!__complex_like<_Up>)
2078 && (_S_size == _UAbi::_S_size)
2079 && __explicitly_convertible_to<_Up, value_type>
2080 [[__gnu__::__always_inline__]]
2082 explicit(!convertible_to<_Up, value_type>)
2083 basic_vec(
const basic_vec<_Up, _UAbi>& __x) noexcept
2084 : _M_real(__x), _M_imag()
2087 using _VecBase<_Tp, _Ap>::_VecBase;
2090 template <__simd_generator_invokable<value_type, _S_size> _Fp>
2091 [[__gnu__::__always_inline__]]
2093 basic_vec(_Fp&& __gen)
2096 _T0 __re[
sizeof(_RealSimd) /
sizeof(_T0)] = {};
2097 _T0 __im[
sizeof(_RealSimd) /
sizeof(_T0)] = {};
2098 template for (
constexpr int __i : _IotaArray<_S_size>)
2100 const value_type __c =
static_cast<value_type
>(__gen(__simd_size_c<__i>));
2101 __re[__i] = __c.real();
2102 __im[__i] = __c.imag();
2104 _M_real = __builtin_bit_cast(_RealSimd, __re);
2105 return __builtin_bit_cast(_RealSimd, __im);
2110 template <__complex_like _Up>
2111 [[__gnu__::__always_inline__]]
2113 basic_vec(_LoadCtorTag,
const _Up* __ptr)
2114 : _M_real([&](int __i) -> _T0 { return __ptr[__i].real(); }),
2115 _M_imag([&](
int __i) -> _T0 {
return __ptr[__i].imag(); })
2118 template <
typename _Up>
2119 [[__gnu__::__always_inline__]]
2121 basic_vec(_LoadCtorTag,
const _Up* __ptr)
2122 : _M_real(_LoadCtorTag(), __ptr), _M_imag()
2125 template <ranges::contiguous_range _Rg,
typename... _Flags>
2126 requires ranges::__static_sized_range<_Rg> && (ranges::__static_size<_Rg>() == _S_size)
2127 && __vectorizable<ranges::range_value_t<_Rg>>
2128 && __explicitly_convertible_to<ranges::range_value_t<_Rg>, value_type>
2129 [[__gnu__::__always_inline__]]
2131 basic_vec(_Rg&& __range, flags<_Flags...> __flags = {})
2132 : basic_vec(_LoadCtorTag(), __flags.template _S_adjust_pointer<basic_vec>(
2133 ranges::data(__range)))
2135 static_assert(__loadstore_convertible_to<ranges::range_value_t<_Rg>, value_type,
2141 [[__gnu__::__always_inline__]]
2143 basic_vec(
const _RealSimd& __re,
const _RealSimd& __im = {})
noexcept
2144 : _M_real(__re), _M_imag(__im)
2148 [[__gnu__::__always_inline__]]
2149 constexpr value_type
2150 operator[](__simd_size_type __i)
const
2151 {
return value_type(_M_real[__i], _M_imag[__i]); }
2154 [[__gnu__::__always_inline__]]
2155 constexpr basic_vec&
2156 operator++() noexcept requires requires(value_type __a) { ++__a; }
2162 [[__gnu__::__always_inline__]]
2164 operator++(
int)
noexcept requires requires(value_type __a) { __a++; }
2166 basic_vec __r = *
this;
2171 [[__gnu__::__always_inline__]]
2172 constexpr basic_vec&
2173 operator--() noexcept requires requires(value_type __a) { --__a; }
2179 [[__gnu__::__always_inline__]]
2181 operator--(
int)
noexcept requires requires(value_type __a) { __a--; }
2183 basic_vec __r = *
this;
2188 [[__gnu__::__always_inline__]]
2190 operator!() const noexcept requires requires(value_type __a) { !__a; }
2191 {
return !_M_real && !_M_imag; }
2193 [[__gnu__::__always_inline__]]
2195 operator+() const noexcept requires requires(value_type __a) { +__a; }
2198 [[__gnu__::__always_inline__]]
2200 operator-() const noexcept requires requires(value_type __a) { -__a; }
2201 {
return basic_vec(-_M_real, -_M_imag); }
2204 [[__gnu__::__always_inline__]]
2205 friend constexpr basic_vec&
2206 operator+=(basic_vec& __x,
const basic_vec& __y)
noexcept
2207 requires requires(value_type __a) { __a + __a; }
2209 __x._M_real += __y._M_real;
2210 __x._M_imag += __y._M_imag;
2214 [[__gnu__::__always_inline__]]
2215 friend constexpr basic_vec&
2216 operator-=(basic_vec& __x,
const basic_vec& __y)
noexcept
2217 requires requires(value_type __a) { __a - __a; }
2219 __x._M_real -= __y._M_real;
2220 __x._M_imag -= __y._M_imag;
2225 template <_TargetTraits _Traits = {}>
2226 [[__gnu__::__always_inline__]]
2227 friend constexpr basic_vec&
2228 operator*=(basic_vec& __x,
const basic_vec& __y)
noexcept
2229 requires requires(value_type __a) { __a * __a; }
2231 __cxctgus::__mul<value_type, _Traits>(__x._M_real, __x._M_imag, __y._M_real, __y._M_imag);
2235 [[__gnu__::__always_inline__]]
2236 friend constexpr basic_vec&
2237 operator/=(basic_vec& __x,
const basic_vec& __y)
noexcept
2238 requires requires(value_type __a) { __a / __a; }
2240 const _RealSimd __r = __x._M_real * __y._M_real + __x._M_imag * __y._M_imag;
2241 const _RealSimd __n = __y._M_norm();
2242 __x._M_imag = (__x._M_imag * __y._M_real - __x._M_real * __y._M_imag) / __n;
2243 __x._M_real = __r / __n;
2248 [[__gnu__::__always_inline__]]
2249 friend constexpr mask_type
2250 operator==(
const basic_vec& __x,
const basic_vec& __y)
noexcept
2251 {
return mask_type(__x._M_real == __y._M_real && __x._M_imag == __y._M_imag); }
2253 [[__gnu__::__always_inline__]]
2254 friend constexpr mask_type
2255 operator!=(
const basic_vec& __x,
const basic_vec& __y)
noexcept
2256 {
return mask_type(__x._M_real != __y._M_real || __x._M_imag != __y._M_imag); }
2260 [[__gnu__::__always_inline__]]
2262 real() const noexcept
2265 [[__gnu__::__always_inline__]]
2267 imag() const noexcept
2270 [[__gnu__::__always_inline__]]
2272 real(
const _RealSimd& __x)
noexcept
2275 [[__gnu__::__always_inline__]]
2277 imag(
const _RealSimd& __x)
noexcept
2281 [[__gnu__::__always_inline__]]
2282 friend constexpr basic_vec
2283 __select_impl(
const mask_type& __k,
const basic_vec& __t,
const basic_vec& __f)
noexcept
2285 typename basic_vec::_RealSimd::mask_type __kk(__k);
2286 return basic_vec(__select_impl(__kk, __t._M_real, __f._M_real),
2287 __select_impl(__kk, __t._M_imag, __f._M_imag));
2291 [[__gnu__::__always_inline__]]
2296 [[__gnu__::__always_inline__]]
2299 {
return _M_real * _M_real + _M_imag * _M_imag; }
2301 [[__gnu__::__always_inline__]]
2304 {
return basic_vec(_M_real, -_M_imag); }
2308 template <__complex_like _Tp,
typename _Ap>
2309 inline constexpr basic_vec<_Tp, _Ap>
2310 __iota<basic_vec<_Tp, _Ap>> = basic_vec<_Tp, _Ap>([](
typename _Tp::value_type __i)
2311 ->
typename _Tp::value_type {
2312 static_assert(_Ap::_S_size - 1 <= numeric_limits<typename _Tp::value_type>::max(),
2313 "iota object would overflow");
2317_GLIBCXX_END_NAMESPACE_VERSION
2320#pragma GCC diagnostic pop
constexpr bool operator<=(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
constexpr bool operator>=(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
constexpr bool operator<(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
constexpr bool operator>(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
constexpr complex< _Tp > operator-(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x minus y.
constexpr complex< _Tp > operator+(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x plus y.
constexpr const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
ISO C++ entities toplevel namespace is std.
constexpr bitset< _Nb > operator^(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
constexpr bitset< _Nb > operator|(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
constexpr bitset< _Nb > operator&(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
A standard container for storing a fixed size sequence of elements.