xref: /aosp_15_r20/external/cronet/third_party/libc++/src/test/std/experimental/simd/test_utils.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LIBCXX_TEST_STD_EXPERIMENTAL_SIMD_TEST_UTILS_H
10 #define LIBCXX_TEST_STD_EXPERIMENTAL_SIMD_TEST_UTILS_H
11 
12 #include <algorithm>
13 #include <array>
14 #include <cassert>
15 #include <type_traits>
16 #include <utility>
17 #include <experimental/simd>
18 #include "type_algorithms.h"
19 
20 namespace ex = std::experimental::parallelism_v2;
21 
22 constexpr std::size_t max_simd_size = 32;
23 
24 template <template <class T, std::size_t N> class F>
25 struct TestAllSimdAbiFunctor {
26   template <class T, std::size_t N>
27   using sized_abis = types::type_list<ex::simd_abi::fixed_size<N>, ex::simd_abi::deduce_t<T, N>>;
28 
29   template <class T, std::size_t... Ns>
instantiate_with_nTestAllSimdAbiFunctor30   void instantiate_with_n(std::index_sequence<Ns...>) {
31     (types::for_each(sized_abis<T, Ns>{}, F<T, Ns>{}), ...);
32   }
33 
34   template <class T>
operatorTestAllSimdAbiFunctor35   void operator()() {
36     using abis = types::type_list<ex::simd_abi::scalar, ex::simd_abi::native<T>, ex::simd_abi::compatible<T>>;
37     types::for_each(abis{}, F<T, 1>());
38 
39     instantiate_with_n<T>(
40         std::index_sequence<1, 2, 3, 4, 8, 16, max_simd_size - 2, max_simd_size - 1, max_simd_size>{});
41   }
42 };
43 
44 // TODO: Support long double (12 bytes) for 32-bits x86
45 #ifdef __i386__
46 using arithmetic_no_bool_types = types::concatenate_t<types::integer_types, types::type_list<float, double>>;
47 #else
48 using arithmetic_no_bool_types = types::concatenate_t<types::integer_types, types::floating_point_types>;
49 #endif
50 
51 // For interfaces with vectorizable type template parameters, we only use some common or boundary types
52 // as template parameters for testing to ensure that the compilation time of a single test does not exceed.
53 using simd_test_types =
54     types::type_list<char,
55                      unsigned,
56                      int,
57 #ifndef TEST_HAS_NO_INT128
58                      __int128_t,
59 #endif
60                      float,
61                      double>;
62 
63 template <template <class T, std::size_t N> class Func>
test_all_simd_abi()64 void test_all_simd_abi() {
65   types::for_each(arithmetic_no_bool_types(), TestAllSimdAbiFunctor<Func>());
66 }
67 
bit_ceil(size_t val)68 constexpr size_t bit_ceil(size_t val) {
69   size_t pow = 1;
70   while (pow < val)
71     pow <<= 1;
72   return pow;
73 }
74 
75 template <class From, class To, class = void>
76 inline constexpr bool is_non_narrowing_convertible_v = false;
77 
78 template <class From, class To>
79 inline constexpr bool is_non_narrowing_convertible_v<From, To, std::void_t<decltype(To{std::declval<From>()})>> = true;
80 
81 template <std::size_t ArraySize, class SimdAbi, class T, class U = T>
assert_simd_values_equal(const ex::simd<T,SimdAbi> & origin_simd,const std::array<U,ArraySize> & expected_value)82 void assert_simd_values_equal(const ex::simd<T, SimdAbi>& origin_simd, const std::array<U, ArraySize>& expected_value) {
83   for (std::size_t i = 0; i < origin_simd.size(); ++i)
84     assert(origin_simd[i] == static_cast<T>(expected_value[i]));
85 }
86 
87 template <std::size_t ArraySize, class T, class SimdAbi>
assert_simd_mask_values_equal(const ex::simd_mask<T,SimdAbi> & origin_mask,const std::array<bool,ArraySize> & expected_value)88 void assert_simd_mask_values_equal(const ex::simd_mask<T, SimdAbi>& origin_mask,
89                                    const std::array<bool, ArraySize>& expected_value) {
90   for (std::size_t i = 0; i < origin_mask.size(); ++i)
91     assert(origin_mask[i] == expected_value[i]);
92 }
93 
94 template <class SimdAbi, class T, class U = T>
assert_simd_values_equal(const ex::simd<T,SimdAbi> & origin_simd,U * expected_value)95 void assert_simd_values_equal(const ex::simd<T, SimdAbi>& origin_simd, U* expected_value) {
96   for (size_t i = 0; i < origin_simd.size(); ++i)
97     assert(origin_simd[i] == static_cast<T>(expected_value[i]));
98 }
99 
100 template <class SimdAbi, class T>
assert_simd_mask_values_equal(const ex::simd_mask<T,SimdAbi> & origin_mask,bool * expected_value)101 void assert_simd_mask_values_equal(const ex::simd_mask<T, SimdAbi>& origin_mask, bool* expected_value) {
102   for (size_t i = 0; i < origin_mask.size(); ++i)
103     assert(origin_mask[i] == expected_value[i]);
104 }
105 
106 #endif // LIBCXX_TEST_STD_EXPERIMENTAL_SIMD_TEST_UTILS_H
107