1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H 11 #define _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H 12 13 #include <__type_traits/is_assignable.h> 14 #include <__type_traits/is_same.h> 15 #include <__utility/forward.h> 16 #include <__utility/move.h> 17 #include <cstddef> 18 #include <experimental/__config> 19 #include <experimental/__simd/utility.h> 20 21 _LIBCPP_PUSH_MACROS 22 #include <__undef_macros> 23 24 #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) 25 26 _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL 27 inline namespace parallelism_v2 { 28 template <class _Tp, class _Storage, class _Vp> 29 class __simd_reference { 30 template <class, class> 31 friend class simd; 32 template <class, class> 33 friend class simd_mask; 34 35 _Storage& __s_; 36 size_t __idx_; 37 38 _LIBCPP_HIDE_FROM_ABI __simd_reference(_Storage& __s, size_t __idx) : __s_(__s), __idx_(__idx) {} 39 40 _LIBCPP_HIDE_FROM_ABI _Vp __get() const noexcept { return __s_.__get(__idx_); } 41 42 _LIBCPP_HIDE_FROM_ABI void __set(_Vp __v) { 43 if constexpr (is_same_v<_Vp, bool>) 44 __s_.__set(__idx_, experimental::__set_all_bits<_Tp>(__v)); 45 else 46 __s_.__set(__idx_, __v); 47 } 48 49 public: 50 using value_type = _Vp; 51 52 __simd_reference() = delete; 53 __simd_reference(const __simd_reference&) = delete; 54 55 _LIBCPP_HIDE_FROM_ABI operator value_type() const noexcept { return __get(); } 56 57 template <class _Up, enable_if_t<is_assignable_v<value_type&, _Up&&>, int> = 0> 58 _LIBCPP_HIDE_FROM_ABI __simd_reference operator=(_Up&& __v) && noexcept { 59 __set(static_cast<value_type>(std::forward<_Up>(__v))); 60 return {__s_, __idx_}; 61 } 62 63 // Note: This approach might not fully align with the specification, 64 // which might be a wording defect. (https://wg21.link/N4808 section 9.6.3) 65 template <class _Tp1, class _Storage1, class _Vp1> 66 friend void 67 swap(__simd_reference<_Tp1, _Storage1, _Vp1>&& __a, __simd_reference<_Tp1, _Storage1, _Vp1>&& __b) noexcept; 68 69 template <class _Tp1, class _Storage1, class _Vp1> 70 friend void swap(_Vp1& __a, __simd_reference<_Tp1, _Storage1, _Vp1>&& __b) noexcept; 71 72 template <class _Tp1, class _Storage1, class _Vp1> 73 friend void swap(__simd_reference<_Tp1, _Storage1, _Vp1>&& __a, _Vp1& __b) noexcept; 74 }; 75 76 template <class _Tp, class _Storage, class _Vp> 77 _LIBCPP_HIDE_FROM_ABI void 78 swap(__simd_reference<_Tp, _Storage, _Vp>&& __a, __simd_reference<_Tp, _Storage, _Vp>&& __b) noexcept { 79 _Vp __tmp(std::move(__a)); 80 std::move(__a) = std::move(__b); 81 std::move(__b) = std::move(__tmp); 82 } 83 84 template <class _Tp, class _Storage, class _Vp> 85 _LIBCPP_HIDE_FROM_ABI void swap(_Vp& __a, __simd_reference<_Tp, _Storage, _Vp>&& __b) noexcept { 86 _Vp __tmp(std::move(__a)); 87 __a = std::move(__b); 88 std::move(__b) = std::move(__tmp); 89 } 90 91 template <class _Tp, class _Storage, class _Vp> 92 _LIBCPP_HIDE_FROM_ABI void swap(__simd_reference<_Tp, _Storage, _Vp>&& __a, _Vp& __b) noexcept { 93 _Vp __tmp(std::move(__a)); 94 std::move(__a) = std::move(__b); 95 __b = std::move(__tmp); 96 } 97 98 } // namespace parallelism_v2 99 _LIBCPP_END_NAMESPACE_EXPERIMENTAL 100 101 #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) 102 103 _LIBCPP_POP_MACROS 104 105 #endif // _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H 106