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_UTILITY_H
11 #define _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H
14 #include <__cstddef/size_t.h>
15 #include <__type_traits/is_arithmetic.h>
16 #include <__type_traits/is_const.h>
17 #include <__type_traits/is_constant_evaluated.h>
18 #include <__type_traits/is_convertible.h>
19 #include <__type_traits/is_same.h>
20 #include <__type_traits/is_unsigned.h>
21 #include <__type_traits/is_volatile.h>
22 #include <__type_traits/void_t.h>
23 #include <__utility/declval.h>
24 #include <__utility/integer_sequence.h>
29 #include <__undef_macros>
31 #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
33 _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
34 inline namespace parallelism_v2
{
36 inline constexpr bool __is_vectorizable_v
=
37 is_arithmetic_v
<_Tp
> && !is_const_v
<_Tp
> && !is_volatile_v
<_Tp
> && !is_same_v
<_Tp
, bool>;
40 _LIBCPP_HIDE_FROM_ABI
auto __choose_mask_type() {
41 if constexpr (sizeof(_Tp
) == 1) {
43 } else if constexpr (sizeof(_Tp
) == 2) {
45 } else if constexpr (sizeof(_Tp
) == 4) {
47 } else if constexpr (sizeof(_Tp
) == 8) {
50 # if _LIBCPP_HAS_INT128
51 else if constexpr (sizeof(_Tp
) == 16) {
56 static_assert(sizeof(_Tp
) == 0, "Unexpected size");
60 _LIBCPP_HIDE_FROM_ABI
auto constexpr __set_all_bits(bool __v
) {
61 return __v
? (numeric_limits
<decltype(__choose_mask_type
<_Tp
>())>::max()) : 0;
64 template <class _From
, class _To
, class = void>
65 inline constexpr bool __is_non_narrowing_convertible_v
= false;
67 template <class _From
, class _To
>
68 inline constexpr bool __is_non_narrowing_convertible_v
<_From
, _To
, std::void_t
<decltype(_To
{std::declval
<_From
>()})>> =
71 template <class _Tp
, class _Up
>
72 inline constexpr bool __can_broadcast_v
=
73 (__is_vectorizable_v
<_Up
> && __is_non_narrowing_convertible_v
<_Up
, _Tp
>) ||
74 (!__is_vectorizable_v
<_Up
> && is_convertible_v
<_Up
, _Tp
>) || is_same_v
<_Up
, int> ||
75 (is_same_v
<_Up
, unsigned int> && is_unsigned_v
<_Tp
>);
77 template <class _Tp
, class _Generator
, std::size_t _Idx
, class = void>
78 inline constexpr bool __is_well_formed
= false;
80 template <class _Tp
, class _Generator
, std::size_t _Idx
>
85 std::void_t
<decltype(std::declval
<_Generator
>()(integral_constant
<size_t, _Idx
>()))>> =
86 __can_broadcast_v
<_Tp
, decltype(std::declval
<_Generator
>()(integral_constant
<size_t, _Idx
>()))>;
88 template <class _Tp
, class _Generator
, std::size_t... _Idxes
>
89 _LIBCPP_HIDE_FROM_ABI
constexpr bool __can_generate(index_sequence
<_Idxes
...>) {
90 return (true && ... && __is_well_formed
<_Tp
, _Generator
, _Idxes
>);
93 template <class _Tp
, class _Generator
, std::size_t _Size
>
94 inline constexpr bool __can_generate_v
= experimental::__can_generate
<_Tp
, _Generator
>(make_index_sequence
<_Size
>());
96 } // namespace parallelism_v2
97 _LIBCPP_END_NAMESPACE_EXPERIMENTAL
99 #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
103 #endif // _LIBCPP_EXPERIMENTAL___SIMD_UTILITY_H