Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:14:08

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H
0011 #define _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H
0012 
0013 #include <__config>
0014 #include <__cstddef/size_t.h>
0015 #include <__type_traits/enable_if.h>
0016 #include <__type_traits/is_assignable.h>
0017 #include <__type_traits/is_same.h>
0018 #include <__utility/declval.h>
0019 #include <__utility/forward.h>
0020 #include <__utility/move.h>
0021 #include <experimental/__simd/utility.h>
0022 
0023 _LIBCPP_PUSH_MACROS
0024 #include <__undef_macros>
0025 
0026 #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
0027 
0028 _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
0029 inline namespace parallelism_v2 {
0030 template <class _Tp, class _Storage, class _Vp>
0031 class __simd_reference {
0032   template <class, class>
0033   friend class simd;
0034   template <class, class>
0035   friend class simd_mask;
0036 
0037   _Storage& __s_;
0038   size_t __idx_;
0039 
0040   _LIBCPP_HIDE_FROM_ABI __simd_reference(_Storage& __s, size_t __idx) : __s_(__s), __idx_(__idx) {}
0041 
0042   _LIBCPP_HIDE_FROM_ABI _Vp __get() const noexcept { return __s_.__get(__idx_); }
0043 
0044   _LIBCPP_HIDE_FROM_ABI void __set(_Vp __v) {
0045     if constexpr (is_same_v<_Vp, bool>)
0046       __s_.__set(__idx_, experimental::__set_all_bits<_Tp>(__v));
0047     else
0048       __s_.__set(__idx_, __v);
0049   }
0050 
0051 public:
0052   using value_type = _Vp;
0053 
0054   __simd_reference()                        = delete;
0055   __simd_reference(const __simd_reference&) = delete;
0056 
0057   _LIBCPP_HIDE_FROM_ABI operator value_type() const noexcept { return __get(); }
0058 
0059   template <class _Up, enable_if_t<is_assignable_v<value_type&, _Up&&>, int> = 0>
0060   _LIBCPP_HIDE_FROM_ABI __simd_reference operator=(_Up&& __v) && noexcept {
0061     __set(static_cast<value_type>(std::forward<_Up>(__v)));
0062     return {__s_, __idx_};
0063   }
0064 
0065   // Note: This approach might not fully align with the specification,
0066   // which might be a wording defect. (https://wg21.link/N4808 section 9.6.3)
0067   template <class _Tp1, class _Storage1, class _Vp1>
0068   friend void
0069   swap(__simd_reference<_Tp1, _Storage1, _Vp1>&& __a, __simd_reference<_Tp1, _Storage1, _Vp1>&& __b) noexcept;
0070 
0071   template <class _Tp1, class _Storage1, class _Vp1>
0072   friend void swap(_Vp1& __a, __simd_reference<_Tp1, _Storage1, _Vp1>&& __b) noexcept;
0073 
0074   template <class _Tp1, class _Storage1, class _Vp1>
0075   friend void swap(__simd_reference<_Tp1, _Storage1, _Vp1>&& __a, _Vp1& __b) noexcept;
0076 
0077   template <class _Up, class = decltype(std::declval<value_type&>() += std::declval<_Up>())>
0078   _LIBCPP_HIDE_FROM_ABI __simd_reference operator+=(_Up&& __v) && noexcept {
0079     __set(__get() + static_cast<value_type>(std::forward<_Up>(__v)));
0080     return {__s_, __idx_};
0081   }
0082 
0083   template <class _Up, class = decltype(std::declval<value_type&>() -= std::declval<_Up>())>
0084   _LIBCPP_HIDE_FROM_ABI __simd_reference operator-=(_Up&& __v) && noexcept {
0085     __set(__get() - static_cast<value_type>(std::forward<_Up>(__v)));
0086     return {__s_, __idx_};
0087   }
0088 
0089   template <class _Up, class = decltype(std::declval<value_type&>() *= std::declval<_Up>())>
0090   _LIBCPP_HIDE_FROM_ABI __simd_reference operator*=(_Up&& __v) && noexcept {
0091     __set(__get() * static_cast<value_type>(std::forward<_Up>(__v)));
0092     return {__s_, __idx_};
0093   }
0094 
0095   template <class _Up, class = decltype(std::declval<value_type&>() /= std::declval<_Up>())>
0096   _LIBCPP_HIDE_FROM_ABI __simd_reference operator/=(_Up&& __v) && noexcept {
0097     __set(__get() / static_cast<value_type>(std::forward<_Up>(__v)));
0098     return {__s_, __idx_};
0099   }
0100 
0101   template <class _Up, class = decltype(std::declval<value_type&>() %= std::declval<_Up>())>
0102   _LIBCPP_HIDE_FROM_ABI __simd_reference operator%=(_Up&& __v) && noexcept {
0103     __set(__get() % static_cast<value_type>(std::forward<_Up>(__v)));
0104     return {__s_, __idx_};
0105   }
0106 
0107   template <class _Up, class = decltype(std::declval<value_type&>() &= std::declval<_Up>())>
0108   _LIBCPP_HIDE_FROM_ABI __simd_reference operator&=(_Up&& __v) && noexcept {
0109     __set(__get() & static_cast<value_type>(std::forward<_Up>(__v)));
0110     return {__s_, __idx_};
0111   }
0112 
0113   template <class _Up, class = decltype(std::declval<value_type&>() |= std::declval<_Up>())>
0114   _LIBCPP_HIDE_FROM_ABI __simd_reference operator|=(_Up&& __v) && noexcept {
0115     __set(__get() | static_cast<value_type>(std::forward<_Up>(__v)));
0116     return {__s_, __idx_};
0117   }
0118 
0119   template <class _Up, class = decltype(std::declval<value_type&>() ^= std::declval<_Up>())>
0120   _LIBCPP_HIDE_FROM_ABI __simd_reference operator^=(_Up&& __v) && noexcept {
0121     __set(__get() ^ static_cast<value_type>(std::forward<_Up>(__v)));
0122     return {__s_, __idx_};
0123   }
0124 
0125   template <class _Up, class = decltype(std::declval<value_type&>() <<= std::declval<_Up>())>
0126   _LIBCPP_HIDE_FROM_ABI __simd_reference operator<<=(_Up&& __v) && noexcept {
0127     __set(__get() << static_cast<value_type>(std::forward<_Up>(__v)));
0128     return {__s_, __idx_};
0129   }
0130 
0131   template <class _Up, class = decltype(std::declval<value_type&>() >>= std::declval<_Up>())>
0132   _LIBCPP_HIDE_FROM_ABI __simd_reference operator>>=(_Up&& __v) && noexcept {
0133     __set(__get() >> static_cast<value_type>(std::forward<_Up>(__v)));
0134     return {__s_, __idx_};
0135   }
0136 
0137   // Note: All legal vectorizable types support operator++/--.
0138   // There doesn't seem to be a way to trigger the constraint.
0139   // Therefore, no SFINAE check is added here.
0140   __simd_reference _LIBCPP_HIDE_FROM_ABI operator++() && noexcept {
0141     __set(__get() + 1);
0142     return {__s_, __idx_};
0143   }
0144 
0145   value_type _LIBCPP_HIDE_FROM_ABI operator++(int) && noexcept {
0146     auto __r = __get();
0147     __set(__get() + 1);
0148     return __r;
0149   }
0150 
0151   __simd_reference _LIBCPP_HIDE_FROM_ABI operator--() && noexcept {
0152     __set(__get() - 1);
0153     return {__s_, __idx_};
0154   }
0155 
0156   value_type _LIBCPP_HIDE_FROM_ABI operator--(int) && noexcept {
0157     auto __r = __get();
0158     __set(__get() - 1);
0159     return __r;
0160   }
0161 };
0162 
0163 template <class _Tp, class _Storage, class _Vp>
0164 _LIBCPP_HIDE_FROM_ABI void
0165 swap(__simd_reference<_Tp, _Storage, _Vp>&& __a, __simd_reference<_Tp, _Storage, _Vp>&& __b) noexcept {
0166   _Vp __tmp(std::move(__a));
0167   std::move(__a) = std::move(__b);
0168   std::move(__b) = std::move(__tmp);
0169 }
0170 
0171 template <class _Tp, class _Storage, class _Vp>
0172 _LIBCPP_HIDE_FROM_ABI void swap(_Vp& __a, __simd_reference<_Tp, _Storage, _Vp>&& __b) noexcept {
0173   _Vp __tmp(std::move(__a));
0174   __a            = std::move(__b);
0175   std::move(__b) = std::move(__tmp);
0176 }
0177 
0178 template <class _Tp, class _Storage, class _Vp>
0179 _LIBCPP_HIDE_FROM_ABI void swap(__simd_reference<_Tp, _Storage, _Vp>&& __a, _Vp& __b) noexcept {
0180   _Vp __tmp(std::move(__a));
0181   std::move(__a) = std::move(__b);
0182   __b            = std::move(__tmp);
0183 }
0184 
0185 } // namespace parallelism_v2
0186 _LIBCPP_END_NAMESPACE_EXPERIMENTAL
0187 
0188 #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
0189 
0190 _LIBCPP_POP_MACROS
0191 
0192 #endif // _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H