Skip to content

Commit bcbbe33

Browse files
committed
Test refactoring: batch cast
1 parent 83b900c commit bcbbe33

File tree

2 files changed

+351
-0
lines changed

2 files changed

+351
-0
lines changed

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ set(XSIMD_TESTS
146146
test_basic_math.cpp
147147
test_batch.cpp
148148
test_batch_bool.cpp
149+
test_batch_cast.cpp
149150
test_batch_complex.cpp
150151
test_batch_float.cpp
151152
test_batch_int.cpp

test/test_batch_cast.cpp

Lines changed: 350 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,350 @@
1+
/***************************************************************************
2+
* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
3+
* Martin Renou *
4+
* Copyright (c) QuantStack *
5+
* *
6+
* Distributed under the terms of the BSD 3-Clause License. *
7+
* *
8+
* The full license is in the file LICENSE, distributed with this software. *
9+
****************************************************************************/
10+
11+
#include "test_utils.hpp"
12+
13+
namespace detail
14+
{
15+
template <class T_out, class T_in>
16+
inline typename std::enable_if<std::is_unsigned<T_in>::value && std::is_integral<T_out>::value, bool>::type
17+
is_convertible(T_in value)
18+
{
19+
return static_cast<uint64_t>(value) <= static_cast<uint64_t>(std::numeric_limits<T_out>::max());
20+
}
21+
22+
template <class T_out, class T_in>
23+
inline typename std::enable_if<std::is_integral<T_in>::value && std::is_signed<T_in>::value && std::is_integral<T_out>::value && std::is_signed<T_out>::value, bool>::type
24+
is_convertible(T_in value)
25+
{
26+
int64_t signed_value = static_cast<int64_t>(value);
27+
return signed_value <= static_cast<int64_t>(std::numeric_limits<T_out>::max()) &&
28+
signed_value >= static_cast<int64_t>(std::numeric_limits<T_out>::lowest());
29+
}
30+
31+
template <class T_out, class T_in>
32+
inline typename std::enable_if<std::is_integral<T_in>::value && std::is_signed<T_in>::value && std::is_unsigned<T_out>::value, bool>::type
33+
is_convertible(T_in value)
34+
{
35+
return value >= 0 && is_convertible<T_out>(static_cast<uint64_t>(value));
36+
}
37+
38+
template <class T_out, class T_in>
39+
inline typename std::enable_if<std::is_floating_point<T_in>::value && std::is_integral<T_out>::value, bool>::type
40+
is_convertible(T_in value)
41+
{
42+
return value <= static_cast<T_in>(std::numeric_limits<T_out>::max()) &&
43+
value >= static_cast<T_in>(std::numeric_limits<T_out>::lowest());
44+
}
45+
46+
template <class T_out, class T_in>
47+
inline typename std::enable_if<std::is_floating_point<T_out>::value, bool>::type
48+
is_convertible(T_in)
49+
{
50+
return true;
51+
}
52+
}
53+
54+
template <class CP>
55+
class batch_cast_test : public testing::Test
56+
{
57+
protected:
58+
59+
static constexpr size_t N = CP::size;
60+
static constexpr size_t A = CP::alignment;
61+
62+
using int8_batch = xsimd::batch<int8_t, N * 8>;
63+
using uint8_batch = xsimd::batch<uint8_t, N * 8>;
64+
using int16_batch = xsimd::batch<int16_t, N * 4>;
65+
using uint16_batch = xsimd::batch<uint16_t, N * 4>;
66+
using int32_batch = xsimd::batch<int32_t, N * 2>;
67+
using uint32_batch = xsimd::batch<uint32_t, N * 2>;
68+
using int64_batch = xsimd::batch<int64_t, N>;
69+
using uint64_batch = xsimd::batch<uint64_t, N>;
70+
using float_batch = xsimd::batch<float, N * 2>;
71+
using double_batch = xsimd::batch<double, N>;
72+
73+
std::vector<uint64_t> int_test_values;
74+
std::vector<float> float_test_values;
75+
std::vector<double> double_test_values;
76+
77+
batch_cast_test()
78+
{
79+
int_test_values =
80+
{
81+
0,
82+
0x01,
83+
0x7f,
84+
0x80,
85+
0xff,
86+
0x0100,
87+
0x7fff,
88+
0x8000,
89+
0xffff,
90+
0x00010000,
91+
0x7fffffff,
92+
0x80000000,
93+
0xffffffff,
94+
0x0000000100000000,
95+
0x7fffffffffffffff,
96+
0x8000000000000000,
97+
0xffffffffffffffff
98+
};
99+
100+
float_test_values =
101+
{
102+
0.0f,
103+
1.0f,
104+
-1.0f,
105+
127.0f,
106+
128.0f,
107+
-128.0f,
108+
255.0f,
109+
256.0f,
110+
-256.0f,
111+
32767.0f,
112+
32768.0f,
113+
-32768.0f,
114+
65535.0f,
115+
65536.0f,
116+
-65536.0f,
117+
2147483647.0f,
118+
2147483648.0f,
119+
-2147483648.0f,
120+
4294967167.0f
121+
};
122+
123+
double_test_values =
124+
{
125+
0.0,
126+
1.0,
127+
-1.0,
128+
127.0,
129+
128.0,
130+
-128.0,
131+
255.0,
132+
256.0,
133+
-256.0,
134+
32767.0,
135+
32768.0,
136+
-32768.0,
137+
65535.0,
138+
65536.0,
139+
-65536.0,
140+
2147483647.0,
141+
2147483648.0,
142+
-2147483648.0,
143+
4294967295.0,
144+
4294967296.0,
145+
-4294967296.0,
146+
9223372036854775807.0,
147+
9223372036854775808.0,
148+
-9223372036854775808.0,
149+
18446744073709550591.0
150+
};
151+
}
152+
153+
void test_cast() const
154+
{
155+
for (const auto& test_value : int_test_values)
156+
{
157+
test_cast_impl<int8_batch, int8_batch>(test_value, "batch cast int8 -> int8");
158+
test_cast_impl<int8_batch, uint8_batch>(test_value, "batch cast int8 -> uint8");
159+
test_cast_impl<uint8_batch, int8_batch>(test_value, "batch cast uint8 -> int8");
160+
test_cast_impl<uint8_batch, uint8_batch>(test_value, "batch cast uint8 -> uint8");
161+
162+
test_cast_impl<int16_batch, int16_batch>(test_value, "batch cast int16 -> int16");
163+
test_cast_impl<int16_batch, uint16_batch>(test_value, "batch cast int16 -> uint16");
164+
test_cast_impl<uint16_batch, int16_batch>(test_value, "batch cast uint16 -> int16");
165+
test_cast_impl<uint16_batch, uint16_batch>(test_value, "batch cast uint16 -> uint16");
166+
167+
test_cast_impl<int32_batch, int32_batch>(test_value, "batch cast int32 -> int32");
168+
test_cast_impl<int32_batch, uint32_batch>(test_value, "batch cast int32 -> uint32");
169+
test_cast_impl<int32_batch, float_batch>(test_value, "batch cast int32 -> float");
170+
test_cast_impl<uint32_batch, int32_batch>(test_value, "batch cast uint32 -> int32");
171+
test_cast_impl<uint32_batch, uint32_batch>(test_value, "batch cast uint32 -> uint32");
172+
test_cast_impl<uint32_batch, float_batch>(test_value, "batch cast uint32 -> float");
173+
174+
test_cast_impl<int64_batch, int64_batch>(test_value, "batch cast int64 -> int64");
175+
test_cast_impl<int64_batch, uint64_batch>(test_value, "batch cast int64 -> uint64");
176+
test_cast_impl<int64_batch, double_batch>(test_value, "batch cast int64 -> double");
177+
test_cast_impl<uint64_batch, int64_batch>(test_value, "batch cast uint64 -> int64");
178+
test_cast_impl<uint64_batch, uint64_batch>(test_value, "batch cast uint64 -> uint64");
179+
test_cast_impl<uint64_batch, double_batch>(test_value, "batch cast uint64 -> double");
180+
}
181+
182+
for (const auto& test_value : float_test_values)
183+
{
184+
test_cast_impl<float_batch, int32_batch>(test_value, "batch cast float -> int32");
185+
test_cast_impl<float_batch, uint32_batch>(test_value, "batch cast float -> uint32");
186+
test_cast_impl<float_batch, float_batch>(test_value, "batch cast float -> float");
187+
}
188+
189+
for (const auto& test_value : double_test_values)
190+
{
191+
test_cast_impl<double_batch, int64_batch>(test_value, "batch cast double -> int64");
192+
test_cast_impl<double_batch, uint64_batch>(test_value, "batch cast double -> uint64");
193+
test_cast_impl<double_batch, double_batch>(test_value, "batch cast double -> double");
194+
}
195+
}
196+
197+
#if XSIMD_X86_INSTR_SET >= XSIMD_X86_AVX_VERSION
198+
template <size_t Align = A>
199+
typename std::enable_if<Align >= 32, void>::type test_cast_sizeshift1() const
200+
{
201+
for (const auto& test_value : int_test_values)
202+
{
203+
test_cast_impl<int8_batch, int16_batch>(test_value, "batch cast int8 -> int16");
204+
test_cast_impl<int8_batch, uint16_batch>(test_value, "batch cast int8 -> uint16");
205+
test_cast_impl<uint8_batch, int16_batch>(test_value, "batch cast uint8 -> int16");
206+
test_cast_impl<uint8_batch, uint16_batch>(test_value, "batch cast uint8 -> uint16");
207+
208+
test_cast_impl<int16_batch, int8_batch>(test_value, "batch cast int16 -> int8");
209+
test_cast_impl<int16_batch, uint8_batch>(test_value, "batch cast int16 -> uint8");
210+
test_cast_impl<int16_batch, int32_batch>(test_value, "batch cast int16 -> int32");
211+
test_cast_impl<int16_batch, uint32_batch>(test_value, "batch cast int16 -> uint32");
212+
test_cast_impl<int16_batch, float_batch>(test_value, "batch cast int16 -> float");
213+
test_cast_impl<uint16_batch, int8_batch>(test_value, "batch cast uint16 -> int8");
214+
test_cast_impl<uint16_batch, uint8_batch>(test_value, "batch cast uint16 -> uint8");
215+
test_cast_impl<uint16_batch, int32_batch>(test_value, "batch cast uint16 -> int32");
216+
test_cast_impl<uint16_batch, uint32_batch>(test_value, "batch cast uint16 -> uint32");
217+
test_cast_impl<uint16_batch, float_batch>(test_value, "batch cast uint16 -> float");
218+
219+
test_cast_impl<int32_batch, int16_batch>(test_value, "batch cast int32 -> int16");
220+
test_cast_impl<int32_batch, uint16_batch>(test_value, "batch cast int32 -> uint16");
221+
test_cast_impl<int32_batch, int64_batch>(test_value, "batch cast int32 -> int64");
222+
test_cast_impl<int32_batch, uint64_batch>(test_value, "batch cast int32 -> uint64");
223+
test_cast_impl<int32_batch, double_batch>(test_value, "batch cast int32 -> double");
224+
test_cast_impl<uint32_batch, int16_batch>(test_value, "batch cast uint32 -> int16");
225+
test_cast_impl<uint32_batch, uint16_batch>(test_value, "batch cast uint32 -> uint16");
226+
test_cast_impl<uint32_batch, int64_batch>(test_value, "batch cast uint32 -> int64");
227+
test_cast_impl<uint32_batch, uint64_batch>(test_value, "batch cast uint32 -> uint64");
228+
test_cast_impl<uint32_batch, double_batch>(test_value, "batch cast uint32 -> double");
229+
230+
test_cast_impl<int64_batch, int32_batch>(test_value, "batch cast int64 -> int32");
231+
test_cast_impl<int64_batch, uint32_batch>(test_value, "batch cast int64 -> uint32");
232+
test_cast_impl<int64_batch, float_batch>(test_value, "batch cast int64 -> float");
233+
test_cast_impl<uint64_batch, int32_batch>(test_value, "batch cast uint64 -> int32");
234+
test_cast_impl<uint64_batch, uint32_batch>(test_value, "batch cast uint64 -> uint32");
235+
test_cast_impl<uint64_batch, float_batch>(test_value, "batch cast uint64 -> float");
236+
}
237+
238+
for (const auto& test_value : float_test_values)
239+
{
240+
test_cast_impl<float_batch, int16_batch>(test_value, "batch cast float -> int16");
241+
test_cast_impl<float_batch, uint16_batch>(test_value, "batch cast float -> uint16");
242+
test_cast_impl<float_batch, int64_batch>(test_value, "batch cast float -> int64");
243+
test_cast_impl<float_batch, uint64_batch>(test_value, "batch cast float -> uint64");
244+
test_cast_impl<float_batch, double_batch>(test_value, "batch cast float -> double");
245+
}
246+
247+
for (const auto& test_value : double_test_values)
248+
{
249+
test_cast_impl<double_batch, int32_batch>(test_value, "batch cast double -> int32");
250+
test_cast_impl<double_batch, uint32_batch>(test_value, "batch cast double -> uint32");
251+
test_cast_impl<double_batch, float_batch>(test_value, "batch cast double -> float");
252+
}
253+
}
254+
255+
template <size_t Align = A>
256+
typename std::enable_if<Align < 32, void>::type test_cast_sizeshift1() const
257+
{
258+
}
259+
#endif
260+
261+
#if XSIMD_X86_INSTR_SET >= XSIMD_X86_AVX512_VERSION
262+
template <size_t Align = A>
263+
typename std::enable_if<Align >= 64, void>::type test_cast_sizeshift2() const
264+
{
265+
for (const auto& test_value : int_test_values)
266+
{
267+
test_cast_impl<int8_batch, int32_batch>(test_value, "batch cast int8 -> int32");
268+
test_cast_impl<int8_batch, uint32_batch>(test_value, "batch cast int8 -> uint32");
269+
test_cast_impl<int8_batch, float_batch>(test_value, "batch cast int8 -> float");
270+
test_cast_impl<uint8_batch, int32_batch>(test_value, "batch cast uint8 -> int32");
271+
test_cast_impl<uint8_batch, uint32_batch>(test_value, "batch cast uint8 -> uint32");
272+
test_cast_impl<uint8_batch, float_batch>(test_value, "batch cast uint8 -> float");
273+
274+
test_cast_impl<int16_batch, int64_batch>(test_value, "batch cast int16 -> int64");
275+
test_cast_impl<int16_batch, uint64_batch>(test_value, "batch cast int16 -> uint64");
276+
test_cast_impl<int16_batch, double_batch>(test_value, "batch cast int16 -> double");
277+
test_cast_impl<uint16_batch, int64_batch>(test_value, "batch cast uint16 -> int64");
278+
test_cast_impl<uint16_batch, uint64_batch>(test_value, "batch cast uint16 -> uint64");
279+
test_cast_impl<uint16_batch, double_batch>(test_value, "batch cast uint16 -> double");
280+
281+
test_cast_impl<int32_batch, int8_batch>(test_value, "batch cast int32 -> int8");
282+
test_cast_impl<int32_batch, uint8_batch>(test_value, "batch cast int32 -> uint8");
283+
test_cast_impl<uint32_batch, int8_batch>(test_value, "batch cast uint32 -> int8");
284+
test_cast_impl<uint32_batch, uint8_batch>(test_value, "batch cast uint32 -> uint8");
285+
286+
test_cast_impl<int64_batch, int16_batch>(test_value, "batch cast int64 -> int16");
287+
test_cast_impl<int64_batch, uint16_batch>(test_value, "batch cast int64 -> uint16");
288+
test_cast_impl<uint64_batch, int16_batch>(test_value, "batch cast uint64 -> int16");
289+
test_cast_impl<uint64_batch, uint16_batch>(test_value, "batch cast uint64 -> uint16");
290+
}
291+
292+
for (const auto& test_value : float_test_values)
293+
{
294+
test_cast_impl<float_batch, int8_batch>(test_value, "batch cast float -> int8");
295+
test_cast_impl<float_batch, uint8_batch>(test_value, "batch cast float -> uint8");
296+
}
297+
298+
for (const auto& test_value : double_test_values)
299+
{
300+
test_cast_impl<double_batch, int16_batch>(test_value, "batch cast double -> int16");
301+
test_cast_impl<double_batch, uint16_batch>(test_value, "batch cast double -> uint16");
302+
}
303+
}
304+
305+
template <size_t Align = A>
306+
typename std::enable_if<Align < 64, void>::type test_cast_sizeshift2() const
307+
{
308+
}
309+
#endif
310+
311+
private:
312+
313+
template <class B_in, class B_out, class T>
314+
void test_cast_impl(T test_value, const std::string& name) const
315+
{
316+
using T_in = typename B_in::value_type;
317+
using T_out = typename B_out::value_type;
318+
static constexpr std::size_t N_common = B_in::size < B_out::size ? B_in::size : B_out::size;
319+
using B_common_in = xsimd::batch<T_in, N_common>;
320+
using B_common_out = xsimd::batch<T_out, N_common>;
321+
322+
T_in in_test_value = static_cast<T_in>(test_value);
323+
if (detail::is_convertible<T_out>(in_test_value))
324+
{
325+
B_common_out res = xsimd::batch_cast<T_out>(B_common_in(in_test_value));
326+
EXPECT_SCALAR_EQ(res[0], static_cast<T_out>(in_test_value)) << print_function_name(name);
327+
}
328+
}
329+
};
330+
331+
TYPED_TEST_SUITE(batch_cast_test, conversion_types, conversion_test_names);
332+
333+
TYPED_TEST(batch_cast_test, cast)
334+
{
335+
this->test_cast();
336+
}
337+
338+
#if XSIMD_X86_INSTR_SET >= XSIMD_X86_AVX_VERSION
339+
TYPED_TEST(batch_cast_test, cast_sizeshift1)
340+
{
341+
this->test_cast_sizeshift1();
342+
}
343+
#endif
344+
345+
#if XSIMD_X86_INSTR_SET >= XSIMD_X86_AVX512_VERSION
346+
TYPED_TEST(batch_cast_test, cast_sizeshift2)
347+
{
348+
this->test_cast_sizeshift2();
349+
}
350+
#endif

0 commit comments

Comments
 (0)