2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H
11 #define _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H
13 #include <__type_traits/is_same.h>
14 #include <__type_traits/remove_cvref.h>
15 #include <__utility/forward.h>
17 #include <experimental/__config>
18 #include <experimental/__simd/declaration.h>
19 #include <experimental/__simd/reference.h>
20 #include <experimental/__simd/traits.h>
21 #include <experimental/__simd/utility.h>
23 #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
25 _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
26 inline namespace parallelism_v2
{
28 // class template simd [simd.class]
29 // TODO: implement simd class
30 template <class _Tp
, class _Abi
>
32 using _Impl
= __simd_operations
<_Tp
, _Abi
>;
33 using _Storage
= typename
_Impl::_SimdStorage
;
38 using value_type
= _Tp
;
39 using reference
= __simd_reference
<_Tp
, _Storage
, value_type
>;
40 using mask_type
= simd_mask
<_Tp
, _Abi
>;
41 using abi_type
= _Abi
;
43 static _LIBCPP_HIDE_FROM_ABI
constexpr size_t size() noexcept
{ return simd_size_v
<value_type
, abi_type
>; }
45 _LIBCPP_HIDE_FROM_ABI
simd() noexcept
= default;
47 // broadcast constructor
48 template <class _Up
, enable_if_t
<__can_broadcast_v
<value_type
, __remove_cvref_t
<_Up
>>, int> = 0>
49 _LIBCPP_HIDE_FROM_ABI
simd(_Up
&& __v
) noexcept
: __s_(_Impl::__broadcast(static_cast<value_type
>(__v
))) {}
51 // implicit type conversion constructor
53 enable_if_t
<!is_same_v
<_Up
, _Tp
> && is_same_v
<abi_type
, simd_abi::fixed_size
<size()>> &&
54 __is_non_narrowing_convertible_v
<_Up
, value_type
>,
56 _LIBCPP_HIDE_FROM_ABI
simd(const simd
<_Up
, simd_abi::fixed_size
<size()>>& __v
) noexcept
{
57 for (size_t __i
= 0; __i
< size(); __i
++) {
58 (*this)[__i
] = static_cast<value_type
>(__v
[__i
]);
62 // generator constructor
63 template <class _Generator
, enable_if_t
<__can_generate_v
<value_type
, _Generator
, size()>, int> = 0>
64 explicit _LIBCPP_HIDE_FROM_ABI
simd(_Generator
&& __g
) noexcept
65 : __s_(_Impl::__generate(std::forward
<_Generator
>(__g
))) {}
68 template <class _Up
, class _Flags
, enable_if_t
<__is_vectorizable_v
<_Up
> && is_simd_flag_type_v
<_Flags
>, int> = 0>
69 _LIBCPP_HIDE_FROM_ABI
simd(const _Up
* __mem
, _Flags
) {
70 _Impl::__load(__s_
, _Flags::template __apply
<simd
>(__mem
));
73 // scalar access [simd.subscr]
74 _LIBCPP_HIDE_FROM_ABI reference
operator[](size_t __i
) noexcept
{ return reference(__s_
, __i
); }
75 _LIBCPP_HIDE_FROM_ABI value_type
operator[](size_t __i
) const noexcept
{ return __s_
.__get(__i
); }
78 template <class _Tp
, class _Abi
>
79 inline constexpr bool is_simd_v
<simd
<_Tp
, _Abi
>> = true;
82 using native_simd
= simd
<_Tp
, simd_abi::native
<_Tp
>>;
84 template <class _Tp
, int _Np
>
85 using fixed_size_simd
= simd
<_Tp
, simd_abi::fixed_size
<_Np
>>;
87 } // namespace parallelism_v2
88 _LIBCPP_END_NAMESPACE_EXPERIMENTAL
90 #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
91 #endif // _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H