xref: /freebsd/contrib/llvm-project/libcxx/include/experimental/__simd/reference.h (revision b64c5a0ace59af62eff52bfe110a521dc73c937b)
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