Skip to content

Commit e41a75b

Browse files
committed
Test refactoring: load and store functions
1 parent a346faf commit e41a75b

File tree

3 files changed

+204
-12
lines changed

3 files changed

+204
-12
lines changed

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ set(XSIMD_TESTS
158158
test_fp_manipulation.cpp
159159
test_hyperbolic.cpp
160160
test_interface.cpp
161+
test_load_store.cpp
161162
test_memory.cpp
162163
test_poly_evaluation.cpp
163164
test_power.cpp

test/test_load_store.cpp

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
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 <random>
12+
13+
#include "test_utils.hpp"
14+
15+
template <class B>
16+
class load_store_test : public testing::Test
17+
{
18+
protected:
19+
20+
using batch_type = B;
21+
using value_type = typename B::value_type;
22+
static constexpr size_t size = B::size;
23+
using array_type = std::array<value_type, size>;
24+
using int8_vector_type = std::vector<int8_t, XSIMD_DEFAULT_ALLOCATOR(int8_t)>;
25+
using uint8_vector_type = std::vector<uint8_t, XSIMD_DEFAULT_ALLOCATOR(uint8_t)>;
26+
using int16_vector_type = std::vector<int16_t, XSIMD_DEFAULT_ALLOCATOR(int16_t)>;
27+
using uint16_vector_type = std::vector<uint16_t, XSIMD_DEFAULT_ALLOCATOR(uint16_t)>;
28+
using int32_vector_type = std::vector<int32_t, XSIMD_DEFAULT_ALLOCATOR(int32_t)>;
29+
using uint32_vector_type = std::vector<uint32_t, XSIMD_DEFAULT_ALLOCATOR(uint32_t)>;
30+
using int64_vector_type = std::vector<int64_t, XSIMD_DEFAULT_ALLOCATOR(int64_t)>;
31+
using uint64_vector_type = std::vector<uint64_t, XSIMD_DEFAULT_ALLOCATOR(uint64_t)>;
32+
#ifdef XSIMD_32_BIT_ABI
33+
using long_vector_type = std::vector<long, XSIMD_DEFAULT_ALLOCATOR(long)>;
34+
using ulong_vector_type = std::vector<unsigned long, XSIMD_DEFAULT_ALLOCATOR(unsigned long)>;
35+
#endif
36+
using float_vector_type = std::vector<float, XSIMD_DEFAULT_ALLOCATOR(float)>;
37+
using double_vector_type = std::vector<double, XSIMD_DEFAULT_ALLOCATOR(double)>;
38+
39+
int8_vector_type i8_vec;
40+
uint8_vector_type ui8_vec;
41+
int16_vector_type i16_vec;
42+
uint16_vector_type ui16_vec;
43+
int32_vector_type i32_vec;
44+
uint32_vector_type ui32_vec;
45+
int64_vector_type i64_vec;
46+
uint64_vector_type ui64_vec;
47+
#ifdef XSIMD_32_BIT_ABI
48+
long_vector_type l_vec;
49+
ulong_vector_type ul_vec;
50+
#endif
51+
float_vector_type f_vec;
52+
double_vector_type d_vec;
53+
54+
array_type expected;
55+
56+
load_store_test()
57+
{
58+
init_test_vector(i8_vec);
59+
init_test_vector(ui8_vec);
60+
init_test_vector(i16_vec);
61+
init_test_vector(ui16_vec);
62+
init_test_vector(i32_vec);
63+
init_test_vector(ui32_vec);
64+
init_test_vector(i64_vec);
65+
init_test_vector(ui64_vec);
66+
#ifdef XSIMD_32_BIT_ABI
67+
init_test_vector(l_vec);
68+
init_test_vector(ul_vec);
69+
#endif
70+
init_test_vector(f_vec);
71+
init_test_vector(d_vec);
72+
}
73+
74+
void test_load()
75+
{
76+
test_load_impl(i8_vec, "load int8_t");
77+
test_load_impl(ui8_vec, "load uint8_t");
78+
test_load_impl(i16_vec, "load int16_t");
79+
test_load_impl(ui16_vec, "load uint16_t");
80+
test_load_impl(i32_vec, "load int32_t");
81+
test_load_impl(ui32_vec, "load uint32_t");
82+
test_load_impl(i64_vec, "load int64_t");
83+
test_load_impl(ui64_vec, "load uint64_t");
84+
#ifdef XSIMD_32_BIT_ABI
85+
test_load_impl(l_vec, "load long");
86+
test_load_impl(ul_vec, "load unsigned long");
87+
#endif
88+
test_load_impl(f_vec, "load float");
89+
test_load_impl(d_vec, "load double");
90+
}
91+
92+
void test_store()
93+
{
94+
test_store_impl(i8_vec, "load int8_t");
95+
test_store_impl(ui8_vec, "load uint8_t");
96+
test_store_impl(i16_vec, "load int16_t");
97+
test_store_impl(ui16_vec, "load uint16_t");
98+
test_store_impl(i32_vec, "load int32_t");
99+
test_store_impl(ui32_vec, "load uint32_t");
100+
test_store_impl(i64_vec, "load int64_t");
101+
test_store_impl(ui64_vec, "load uint64_t");
102+
#ifdef XSIMD_32_BIT_ABI
103+
test_store_impl(l_vec, "load long");
104+
test_store_impl(ul_vec, "load unsigned long");
105+
#endif
106+
test_store_impl(f_vec, "load float");
107+
test_store_impl(d_vec, "load double");
108+
109+
}
110+
111+
private:
112+
113+
template <class V>
114+
void test_load_impl(const V& v, const std::string& name)
115+
{
116+
batch_type b;
117+
std::copy(v.cbegin(), v.cend(), expected.begin());
118+
119+
b.load_unaligned(v.data());
120+
EXPECT_BATCH_EQ(b, expected) << print_function_name(name + " unaligned");
121+
122+
b.load_aligned(v.data());
123+
EXPECT_BATCH_EQ(b, expected) << print_function_name(name + " aligned");
124+
}
125+
126+
template <class V>
127+
void test_store_impl(const V& v, const std::string& name)
128+
{
129+
batch_type b;
130+
b.load_aligned(v.data());
131+
V res(size);
132+
133+
b.store_unaligned(res.data());
134+
EXPECT_VECTOR_EQ(res, v) << print_function_name(name + " unaligned");
135+
136+
b.store_aligned(res.data());
137+
EXPECT_VECTOR_EQ(res, v) << print_function_name(name + " aligned");
138+
}
139+
140+
template <class V>
141+
void init_test_vector(V& vec)
142+
{
143+
vec.resize(size);
144+
145+
value_type min = value_type(0);
146+
value_type max = value_type(100);
147+
148+
std::default_random_engine generator;
149+
std::uniform_int_distribution<int> distribution(min, max);
150+
151+
auto gen = [&distribution, &generator](){
152+
return static_cast<value_type>(distribution(generator));
153+
};
154+
155+
std::generate(vec.begin(), vec.end(), gen);
156+
}
157+
};
158+
159+
TYPED_TEST_SUITE(load_store_test, batch_types, simd_test_names);
160+
161+
TYPED_TEST(load_store_test, load)
162+
{
163+
this->test_load();
164+
}
165+
166+
TYPED_TEST(load_store_test, store)
167+
{
168+
this->test_store();
169+
}
170+

test/test_utils.hpp

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,15 @@ namespace detail
272272
};
273273
#endif
274274

275-
template <class T, size_t N>
275+
template <class V>
276276
struct vector_comparison
277277
{
278-
static bool run(const std::array<T, N>& lhs, const std::array<T, N>& rhs)
278+
static bool run(const V& lhs, const V& rhs)
279279
{
280-
for (size_t i = 0; i < N; ++i)
280+
using value_type = typename V::value_type;
281+
for (size_t i = 0; i < lhs.size(); ++i)
281282
{
282-
if (!scalar_comparison<T>::run(lhs[i], rhs[i]))
283+
if (!scalar_comparison<value_type>::run(lhs[i], rhs[i]))
283284
return false;
284285
}
285286
return true;
@@ -312,23 +313,24 @@ namespace detail
312313
false);
313314
}
314315

315-
template <class T, size_t N>
316-
testing::AssertionResult expect_array_near(const char* lhs_expression,
317-
const char* rhs_expression,
318-
const std::array<T, N>& lhs,
319-
const std::array<T, N>& rhs)
316+
template <class V>
317+
testing::AssertionResult expect_container_near(const char* lhs_expression,
318+
const char* rhs_expression,
319+
const V& lhs,
320+
const V& rhs)
320321
{
321-
if (vector_comparison<T, N>::run(lhs, rhs))
322+
if (vector_comparison<V>::run(lhs, rhs))
322323
{
323324
return testing::AssertionSuccess();
324325
}
325326

327+
using value_type = typename V::value_type;
326328
std::stringstream lhs_ss;
327-
lhs_ss << std::setprecision(std::numeric_limits<T>::digits10 + 2);
329+
lhs_ss << std::setprecision(std::numeric_limits<value_type>::digits10 + 2);
328330
testing::internal::PrintTo(lhs, &lhs_ss);
329331

330332
std::stringstream rhs_ss;
331-
rhs_ss << std::setprecision(std::numeric_limits<T>::digits10 + 2);
333+
rhs_ss << std::setprecision(std::numeric_limits<value_type>::digits10 + 2);
332334
testing::internal::PrintTo(rhs, &rhs_ss);
333335

334336
return testing::internal::EqFailure(lhs_expression,
@@ -338,6 +340,24 @@ namespace detail
338340
false);
339341
}
340342

343+
template <class T, size_t N>
344+
testing::AssertionResult expect_array_near(const char* lhs_expression,
345+
const char* rhs_expression,
346+
const std::array<T, N>& lhs,
347+
const std::array<T, N>& rhs)
348+
{
349+
return expect_container_near(lhs_expression, rhs_expression, lhs, rhs);
350+
}
351+
352+
template <class T, class A>
353+
testing::AssertionResult expect_vector_near(const char* lhs_expression,
354+
const char* rhs_expression,
355+
const std::vector<T, A>& lhs,
356+
const std::vector<T, A>& rhs)
357+
{
358+
return expect_container_near(lhs_expression, rhs_expression, lhs, rhs);
359+
}
360+
341361
template <class T, size_t N>
342362
testing::AssertionResult expect_batch_near(const char* lhs_expression,
343363
const char* rhs_expression,
@@ -447,6 +467,7 @@ namespace detail
447467

448468
#define EXPECT_BATCH_EQ(b1, b2) EXPECT_PRED_FORMAT2(::detail::expect_batch_near, b1, b2)
449469
#define EXPECT_SCALAR_EQ(s1, s2) EXPECT_PRED_FORMAT2(::detail::expect_scalar_near, s1, s2)
470+
#define EXPECT_VECTOR_EQ(v1, v2) EXPECT_PRED_FORMAT2(::detail::expect_vector_near, v1, v2)
450471

451472
namespace xsimd
452473
{

0 commit comments

Comments
 (0)