]>
Commit | Line | Data |
---|---|---|
7adcbafe | 1 | // Copyright (C) 2020-2022 Free Software Foundation, Inc. |
02e32295 MK |
2 | // |
3 | // This file is part of the GNU ISO C++ Library. This library is free | |
4 | // software; you can redistribute it and/or modify it under the | |
5 | // terms of the GNU General Public License as published by the | |
6 | // Free Software Foundation; either version 3, or (at your option) | |
7 | // any later version. | |
8 | // | |
9 | // This library is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | // | |
14 | // You should have received a copy of the GNU General Public License along | |
15 | // with this library; see the file COPYING3. If not see | |
16 | // <http://www.gnu.org/licenses/>. | |
17 | ||
aa89c53c | 18 | // expensive: * [1-9] * * |
02e32295 MK |
19 | #include "bits/verify.h" |
20 | #include "bits/metahelpers.h" | |
21 | #include "bits/conversions.h" | |
22 | ||
23 | using std::experimental::simd_cast; | |
24 | using std::experimental::static_simd_cast; | |
25 | ||
26 | template <class T, size_t N> | |
27 | struct gen_cast | |
28 | { | |
29 | std::array<T, N> data; | |
30 | ||
31 | template <class V> | |
32 | gen_cast(const V& v) | |
33 | { | |
34 | for (size_t i = 0; i < V::size(); ++i) | |
35 | { | |
36 | data[i] = static_cast<T>(v[i]); | |
37 | } | |
38 | } | |
39 | ||
40 | template <class I> | |
41 | constexpr T | |
42 | operator()(I) | |
43 | { return data[I::value]; } | |
44 | }; | |
45 | ||
46 | template <class V, class To> | |
47 | struct gen_seq_t | |
48 | { | |
49 | using From = typename V::value_type; | |
50 | const size_t N = cvt_input_data<From, To>.size(); | |
51 | size_t offset = 0; | |
52 | ||
53 | constexpr void | |
54 | operator++() | |
55 | { offset += V::size(); } | |
56 | ||
57 | explicit constexpr operator bool() const | |
58 | { return offset < N; } | |
59 | ||
60 | template <class I> | |
61 | constexpr From | |
62 | operator()(I) const | |
63 | { | |
64 | size_t i = I::value + offset; | |
65 | return i < N ? cvt_input_data<From, To>[i] : From(i); | |
66 | } | |
67 | }; | |
68 | ||
69 | template <class To> | |
70 | struct foo | |
71 | { | |
72 | template <class T> | |
73 | auto | |
74 | operator()(const T& v) -> decltype(simd_cast<To>(v)); | |
75 | }; | |
76 | ||
77 | template <typename V, typename To> | |
78 | void | |
79 | casts() | |
80 | { | |
81 | using From = typename V::value_type; | |
82 | constexpr auto N = V::size(); | |
83 | if constexpr (N <= std::experimental::simd_abi::max_fixed_size<To>) | |
84 | { | |
85 | using W = std::experimental::fixed_size_simd<To, N>; | |
86 | ||
87 | if constexpr (std::is_integral_v<From>) | |
88 | { | |
89 | using A = typename V::abi_type; | |
90 | using TU = std::make_unsigned_t<From>; | |
91 | using TS = std::make_signed_t<From>; | |
92 | COMPARE(typeid(static_simd_cast<TU>(V())), | |
93 | typeid(std::experimental::simd<TU, A>)); | |
94 | COMPARE(typeid(static_simd_cast<TS>(V())), | |
95 | typeid(std::experimental::simd<TS, A>)); | |
96 | } | |
97 | ||
98 | using is_simd_cast_allowed | |
99 | = decltype(vir::test::sfinae_is_callable_t<const V&>(foo<To>())); | |
100 | ||
101 | COMPARE(is_simd_cast_allowed::value, | |
102 | std::__digits<From>::value <= std::__digits<To>::value | |
103 | && std::__finite_max<From>::value | |
104 | <= std::__finite_max<To>::value | |
105 | && !(std::is_signed<From>::value | |
106 | && std::is_unsigned<To>::value)); | |
107 | ||
108 | if constexpr (is_simd_cast_allowed::value) | |
109 | { | |
110 | for (gen_seq_t<V, To> gen_seq; gen_seq; ++gen_seq) | |
111 | { | |
112 | const V seq(gen_seq); | |
113 | COMPARE(simd_cast<V>(seq), seq); | |
114 | COMPARE(simd_cast<W>(seq), W(gen_cast<To, N>(seq))) | |
115 | << "seq = " << seq; | |
116 | auto test = simd_cast<To>(seq); | |
117 | // decltype(test) is not W if | |
118 | // a) V::abi_type is not fixed_size and | |
119 | // b.1) V::value_type and To are integral and of equal rank or | |
120 | // b.2) V::value_type and To are equal | |
121 | COMPARE(test, decltype(test)(gen_cast<To, N>(seq))); | |
122 | if (std::is_same<To, From>::value) | |
123 | { | |
124 | COMPARE(typeid(decltype(test)), typeid(V)); | |
125 | } | |
126 | } | |
127 | } | |
128 | ||
129 | for (gen_seq_t<V, To> gen_seq; gen_seq; ++gen_seq) | |
130 | { | |
131 | const V seq(gen_seq); | |
132 | COMPARE(static_simd_cast<V>(seq), seq); | |
133 | COMPARE(static_simd_cast<W>(seq), W(gen_cast<To, N>(seq))) << '\n' | |
134 | << seq; | |
135 | auto test = static_simd_cast<To>(seq); | |
136 | // decltype(test) is not W if | |
137 | // a) V::abi_type is not fixed_size and | |
138 | // b.1) V::value_type and To are integral and of equal rank or | |
139 | // b.2) V::value_type and To are equal | |
140 | COMPARE(test, decltype(test)(gen_cast<To, N>(seq))); | |
141 | if (std::is_same<To, From>::value) | |
142 | { | |
143 | COMPARE(typeid(decltype(test)), typeid(V)); | |
144 | } | |
145 | } | |
146 | } | |
147 | } | |
148 | ||
149 | template <typename V> | |
150 | void | |
151 | test() | |
152 | { | |
153 | casts<V, long double>(); | |
154 | casts<V, double>(); | |
155 | casts<V, float>(); | |
156 | casts<V, long long>(); | |
157 | casts<V, unsigned long long>(); | |
158 | casts<V, unsigned long>(); | |
159 | casts<V, long>(); | |
160 | casts<V, int>(); | |
161 | casts<V, unsigned int>(); | |
162 | casts<V, short>(); | |
163 | casts<V, unsigned short>(); | |
164 | casts<V, char>(); | |
165 | casts<V, signed char>(); | |
166 | casts<V, unsigned char>(); | |
167 | casts<V, char32_t>(); | |
168 | casts<V, char16_t>(); | |
169 | casts<V, wchar_t>(); | |
170 | } |