1*5f757f3fSDimitry Andric // -*- C++ -*-
2*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
3*5f757f3fSDimitry Andric //
4*5f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*5f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6*5f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*5f757f3fSDimitry Andric //
8*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
9*5f757f3fSDimitry Andric 
10*5f757f3fSDimitry Andric #ifndef _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H
11*5f757f3fSDimitry Andric #define _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H
12*5f757f3fSDimitry Andric 
13*5f757f3fSDimitry Andric #include <__type_traits/is_assignable.h>
14*5f757f3fSDimitry Andric #include <__type_traits/is_same.h>
15*5f757f3fSDimitry Andric #include <__utility/forward.h>
16*5f757f3fSDimitry Andric #include <cstddef>
17*5f757f3fSDimitry Andric #include <experimental/__config>
18*5f757f3fSDimitry Andric #include <experimental/__simd/utility.h>
19*5f757f3fSDimitry Andric 
20*5f757f3fSDimitry Andric #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
21*5f757f3fSDimitry Andric 
22*5f757f3fSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
23*5f757f3fSDimitry Andric inline namespace parallelism_v2 {
24*5f757f3fSDimitry Andric template <class _Tp, class _Storage, class _Vp>
25*5f757f3fSDimitry Andric class __simd_reference {
26*5f757f3fSDimitry Andric   template <class, class>
27*5f757f3fSDimitry Andric   friend class simd;
28*5f757f3fSDimitry Andric   template <class, class>
29*5f757f3fSDimitry Andric   friend class simd_mask;
30*5f757f3fSDimitry Andric 
31*5f757f3fSDimitry Andric   _Storage& __s_;
32*5f757f3fSDimitry Andric   size_t __idx_;
33*5f757f3fSDimitry Andric 
__simd_reference(_Storage & __s,size_t __idx)34*5f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI __simd_reference(_Storage& __s, size_t __idx) : __s_(__s), __idx_(__idx) {}
35*5f757f3fSDimitry Andric 
__get()36*5f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _Vp __get() const noexcept { return __s_.__get(__idx_); }
37*5f757f3fSDimitry Andric 
__set(_Vp __v)38*5f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void __set(_Vp __v) {
39*5f757f3fSDimitry Andric     if constexpr (is_same_v<_Vp, bool>)
40*5f757f3fSDimitry Andric       __s_.__set(__idx_, experimental::__set_all_bits<_Tp>(__v));
41*5f757f3fSDimitry Andric     else
42*5f757f3fSDimitry Andric       __s_.__set(__idx_, __v);
43*5f757f3fSDimitry Andric   }
44*5f757f3fSDimitry Andric 
45*5f757f3fSDimitry Andric public:
46*5f757f3fSDimitry Andric   using value_type = _Vp;
47*5f757f3fSDimitry Andric 
48*5f757f3fSDimitry Andric   __simd_reference()                        = delete;
49*5f757f3fSDimitry Andric   __simd_reference(const __simd_reference&) = delete;
50*5f757f3fSDimitry Andric 
value_type()51*5f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI operator value_type() const noexcept { return __get(); }
52*5f757f3fSDimitry Andric 
53*5f757f3fSDimitry Andric   template <class _Up, enable_if_t<is_assignable_v<value_type&, _Up&&>, int> = 0>
54*5f757f3fSDimitry Andric   _LIBCPP_HIDE_FROM_ABI __simd_reference operator=(_Up&& __v) && noexcept {
55*5f757f3fSDimitry Andric     __set(static_cast<value_type>(std::forward<_Up>(__v)));
56*5f757f3fSDimitry Andric     return {__s_, __idx_};
57*5f757f3fSDimitry Andric   }
58*5f757f3fSDimitry Andric };
59*5f757f3fSDimitry Andric 
60*5f757f3fSDimitry Andric } // namespace parallelism_v2
61*5f757f3fSDimitry Andric _LIBCPP_END_NAMESPACE_EXPERIMENTAL
62*5f757f3fSDimitry Andric 
63*5f757f3fSDimitry Andric #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
64*5f757f3fSDimitry Andric #endif // _LIBCPP_EXPERIMENTAL___SIMD_REFERENCE_H
65