Skip to content

Commit a346faf

Browse files
committed
Test refactoring: algorithms
1 parent d54a63d commit a346faf

File tree

2 files changed

+270
-0
lines changed

2 files changed

+270
-0
lines changed

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ include_directories(${GTEST_INCLUDE_DIRS})
142142

143143
set(XSIMD_TESTS
144144
main.cpp
145+
test_algorithms.cpp
145146
test_basic_math.cpp
146147
test_batch.cpp
147148
test_batch_bool.cpp

test/test_algorithms.cpp

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
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 <numeric>
12+
#include "test_utils.hpp"
13+
14+
struct binary_functor
15+
{
16+
template <class T>
17+
T operator()(const T& a, const T& b) const
18+
{
19+
return a + b;
20+
}
21+
};
22+
23+
struct unary_functor
24+
{
25+
template <class T>
26+
T operator()(const T& a) const
27+
{
28+
return -a;
29+
}
30+
};
31+
32+
#ifdef XSIMD_DEFAULT_ALIGNMENT
33+
template <class T>
34+
using test_allocator_type = xsimd::aligned_allocator<T, XSIMD_DEFAULT_ALIGNMENT>;
35+
#else
36+
template <class T>
37+
using test_allocator_type = std::allocator<T>;
38+
#endif
39+
40+
TEST(algorithms, binary_transform)
41+
{
42+
std::vector<double> expected(93);
43+
44+
std::vector<double> a(93, 123), b(93, 123), c(93);
45+
std::vector<double, test_allocator_type<double>> aa(93, 123), ba(93, 123), ca(93);
46+
47+
std::transform(a.begin(), a.end(), b.begin(), expected.begin(),
48+
binary_functor{});
49+
50+
xsimd::transform(a.begin(), a.end(), b.begin(), c.begin(),
51+
binary_functor{});
52+
EXPECT_TRUE(std::equal(expected.begin(), expected.end(), c.begin()) && expected.size() == c.size());
53+
std::fill(c.begin(), c.end(), -1); // erase
54+
55+
xsimd::transform(aa.begin(), aa.end(), ba.begin(), c.begin(),
56+
binary_functor{});
57+
EXPECT_TRUE(std::equal(expected.begin(), expected.end(), c.begin()) && expected.size() == c.size());
58+
std::fill(c.begin(), c.end(), -1); // erase
59+
60+
xsimd::transform(aa.begin(), aa.end(), b.begin(), c.begin(),
61+
binary_functor{});
62+
EXPECT_TRUE(std::equal(expected.begin(), expected.end(), c.begin()) && expected.size() == c.size());
63+
std::fill(c.begin(), c.end(), -1); // erase
64+
65+
xsimd::transform(a.begin(), a.end(), ba.begin(), c.begin(),
66+
binary_functor{});
67+
EXPECT_TRUE(std::equal(expected.begin(), expected.end(), c.begin()) && expected.size() == c.size());
68+
std::fill(c.begin(), c.end(), -1); // erase
69+
70+
xsimd::transform(aa.begin(), aa.end(), ba.begin(), ca.begin(),
71+
binary_functor{});
72+
EXPECT_TRUE(std::equal(expected.begin(), expected.end(), ca.begin()) && expected.size() == ca.size());
73+
std::fill(ca.begin(), ca.end(), -1); // erase
74+
75+
xsimd::transform(aa.begin(), aa.end(), b.begin(), ca.begin(),
76+
binary_functor{});
77+
EXPECT_TRUE(std::equal(expected.begin(), expected.end(), ca.begin()) && expected.size() == ca.size());
78+
std::fill(ca.begin(), ca.end(), -1); // erase
79+
80+
xsimd::transform(a.begin(), a.end(), ba.begin(), ca.begin(),
81+
binary_functor{});
82+
EXPECT_TRUE(std::equal(expected.begin(), expected.end(), ca.begin()) && expected.size() == ca.size());
83+
std::fill(ca.begin(), ca.end(), -1); // erase
84+
}
85+
86+
87+
TEST(algorithms, unary_transform)
88+
{
89+
std::vector<double> expected(93);
90+
std::vector<double> a(93, 123), c(93);
91+
std::vector<double, test_allocator_type<double>> aa(93, 123), ca(93);
92+
93+
std::transform(a.begin(), a.end(), expected.begin(),
94+
unary_functor{});
95+
96+
xsimd::transform(a.begin(), a.end(), c.begin(),
97+
unary_functor{});
98+
EXPECT_TRUE(std::equal(expected.begin(), expected.end(), c.begin()) && expected.size() == c.size());
99+
std::fill(c.begin(), c.end(), -1); // erase
100+
101+
xsimd::transform(aa.begin(), aa.end(), c.begin(),
102+
unary_functor{});
103+
EXPECT_TRUE(std::equal(expected.begin(), expected.end(), c.begin()) && expected.size() == c.size());
104+
std::fill(c.begin(), c.end(), -1); // erase
105+
106+
xsimd::transform(a.begin(), a.end(), ca.begin(),
107+
unary_functor{});
108+
EXPECT_TRUE(std::equal(expected.begin(), expected.end(), ca.begin()) && expected.size() == ca.size());
109+
std::fill(ca.begin(), ca.end(), -1); // erase
110+
111+
xsimd::transform(aa.begin(), aa.end(), ca.begin(),
112+
unary_functor{});
113+
EXPECT_TRUE(std::equal(expected.begin(), expected.end(), ca.begin()) && expected.size() == ca.size());
114+
std::fill(ca.begin(), ca.end(), -1); // erase
115+
}
116+
117+
class xsimd_reduce : public ::testing::Test
118+
{
119+
public:
120+
using aligned_vec_t = std::vector<double, test_allocator_type<double>>;
121+
122+
static constexpr std::size_t num_elements = 4 * xsimd::simd_traits<double>::size;
123+
static constexpr std::size_t small_num = xsimd::simd_traits<double>::size - 1;
124+
125+
aligned_vec_t vec = aligned_vec_t(num_elements, 123.);
126+
aligned_vec_t small_vec = aligned_vec_t(small_num, 42.);
127+
double init = 1337.;
128+
129+
struct multiply
130+
{
131+
template <class T>
132+
T operator()(const T& a, const T& b) const
133+
{
134+
return a * b;
135+
}
136+
};
137+
};
138+
139+
TEST_F(xsimd_reduce, unaligned_begin_unaligned_end)
140+
{
141+
auto const begin = std::next(vec.begin());
142+
auto const end = std::prev(vec.end());
143+
144+
EXPECT_EQ(std::accumulate(begin, end, init), xsimd::reduce(begin, end, init));
145+
146+
if(small_vec.size() > 1)
147+
{
148+
auto const sbegin = std::next(small_vec.begin());
149+
auto const send = std::prev(small_vec.end());
150+
151+
EXPECT_EQ(std::accumulate(sbegin, send, init), xsimd::reduce(sbegin, send, init));
152+
}
153+
}
154+
155+
TEST_F(xsimd_reduce, unaligned_begin_aligned_end)
156+
{
157+
auto const begin = std::next(vec.begin());
158+
auto const end = vec.end();
159+
160+
EXPECT_EQ(std::accumulate(begin, end, init), xsimd::reduce(begin, end, init));
161+
162+
if(small_vec.size() > 1)
163+
{
164+
auto const sbegin = std::next(small_vec.begin());
165+
auto const send = small_vec.end();
166+
167+
EXPECT_EQ(std::accumulate(sbegin, send, init), xsimd::reduce(sbegin, send, init));
168+
}
169+
}
170+
171+
TEST_F(xsimd_reduce, aligned_begin_unaligned_end)
172+
{
173+
auto const begin = vec.begin();
174+
auto const end = std::prev(vec.end());
175+
176+
EXPECT_EQ(std::accumulate(begin, end, init), xsimd::reduce(begin, end, init));
177+
178+
if(small_vec.size() > 1)
179+
{
180+
auto const sbegin = small_vec.begin();
181+
auto const send = std::prev(small_vec.end());
182+
183+
EXPECT_EQ(std::accumulate(sbegin, send, init), xsimd::reduce(sbegin, send, init));
184+
}
185+
}
186+
187+
TEST_F(xsimd_reduce, aligned_begin_aligned_end)
188+
{
189+
auto const begin = vec.begin();
190+
auto const end = vec.end();
191+
192+
EXPECT_EQ(std::accumulate(begin, end, init), xsimd::reduce(begin, end, init));
193+
194+
if(small_vec.size() > 1)
195+
{
196+
auto const sbegin = small_vec.begin();
197+
auto const send = small_vec.end();
198+
199+
EXPECT_EQ(std::accumulate(sbegin, send, init), xsimd::reduce(sbegin, send, init));
200+
}
201+
}
202+
203+
TEST_F(xsimd_reduce, using_custom_binary_function)
204+
{
205+
auto const begin = vec.begin();
206+
auto const end = vec.end();
207+
208+
EXPECT_DOUBLE_EQ(std::accumulate(begin, end, init, multiply{}), xsimd::reduce(begin, end, init, multiply{}));
209+
210+
if(small_vec.size() > 1)
211+
{
212+
auto const sbegin = small_vec.begin();
213+
auto const send = small_vec.end();
214+
215+
EXPECT_DOUBLE_EQ(std::accumulate(sbegin, send, init, multiply{}), xsimd::reduce(sbegin, send, init, multiply{}));
216+
}
217+
}
218+
219+
#if XSIMD_X86_INSTR_SET > XSIMD_VERSION_NUMBER_NOT_AVAILABLE || XSIMD_ARM_INSTR_SET > XSIMD_VERSION_NUMBER_NOT_AVAILABLE
220+
TEST(algorithms, iterator)
221+
{
222+
std::vector<float, test_allocator_type<float>> a(10 * 16, 0.2), b(1000, 2.), c(1000, 3.);
223+
224+
std::iota(a.begin(), a.end(), 0.f);
225+
std::vector<float> a_cpy(a.begin(), a.end());
226+
227+
using batch_type = typename xsimd::simd_traits<float>::type;
228+
auto begin = xsimd::aligned_iterator<batch_type>(&a[0]);
229+
auto end = xsimd::aligned_iterator<batch_type>(&a[0] + a.size());
230+
231+
for (; begin != end; ++begin)
232+
{
233+
*begin = *begin / 2.f;
234+
}
235+
236+
for (auto& el : a_cpy)
237+
{
238+
el /= 2.f;
239+
}
240+
241+
EXPECT_TRUE(a.size() == a_cpy.size() && std::equal(a.begin(), a.end(), a_cpy.begin()));
242+
243+
begin = xsimd::aligned_iterator<batch_type>(&a[0]);
244+
*begin = sin(*begin);
245+
246+
for (std::size_t i = 0; i < batch_type::size; ++i)
247+
{
248+
EXPECT_NEAR(a[i], sinf(a_cpy[i]), 1e-6);
249+
}
250+
251+
#ifdef XSIMD_BATCH_DOUBLE_SIZE
252+
std::vector<std::complex<double>, test_allocator_type<std::complex<double>>> ca(10 * 16, std::complex<double>(0.2));
253+
using cbatch_type = typename xsimd::simd_traits<std::complex<double>>::type;
254+
auto cbegin = xsimd::aligned_iterator<cbatch_type>(&ca[0]);
255+
auto cend = xsimd::aligned_iterator<cbatch_type>(&ca[0] + a.size());
256+
257+
for (; cbegin != cend; ++cbegin)
258+
{
259+
*cbegin = (*cbegin + std::complex<double>(0, .3)) / 2.;
260+
}
261+
262+
cbegin = xsimd::aligned_iterator<cbatch_type>(&ca[0]);
263+
*cbegin = sin(*cbegin);
264+
*cbegin = sqrt(*cbegin);
265+
auto real_part = abs(*(cbegin));
266+
#endif
267+
268+
}
269+
#endif

0 commit comments

Comments
 (0)