Skip to content

Commit dc7d05c

Browse files
committed
Test refactoring: rouding functions
1 parent 899d236 commit dc7d05c

File tree

3 files changed

+178
-4
lines changed

3 files changed

+178
-4
lines changed

test/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ set(XSIMD_TESTS
154154
test_interface.cpp
155155
test_memory.cpp
156156
test_poly_evaluation.cpp
157+
test_power.cpp
158+
test_rounding.cpp
157159
test_utils.hpp
158160
#[[ xsimd_api_test.hpp
159161
xsimd_api_test.cpp

test/test_rounding.cpp

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
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+
template <class B>
14+
class rounding_test : public testing::Test
15+
{
16+
protected:
17+
18+
using batch_type = B;
19+
using value_type = typename B::value_type;
20+
static constexpr size_t size = B::size;
21+
static constexpr size_t nb_input = 8;
22+
static constexpr size_t nb_batches = nb_input / size;
23+
24+
std::array<value_type, nb_input> input;
25+
std::array<value_type, nb_input> expected;
26+
std::array<value_type, nb_input> res;
27+
28+
rounding_test()
29+
{
30+
input[0] = value_type(-3.5);
31+
input[1] = value_type(-2.7);
32+
input[2] = value_type(-2.5);
33+
input[3] = value_type(-2.3);
34+
input[4] = value_type(2.3);
35+
input[5] = value_type(2.5);
36+
input[6] = value_type(2.7);
37+
input[7] = value_type(3.5);
38+
}
39+
40+
void test_rounding_functions()
41+
{
42+
// ceil
43+
{
44+
std::transform(input.cbegin(), input.cend(), expected.begin(),
45+
[](const value_type& v) { return std::ceil(v); });
46+
batch_type in, out;
47+
for (size_t i = 0; i < nb_batches; i += size)
48+
{
49+
detail::load_batch(in, input, i);
50+
out = ceil(in);
51+
detail::store_batch(out, res, i);
52+
}
53+
for (size_t i = nb_batches; i < nb_input; ++i)
54+
{
55+
res[i] = std::ceil(input[i]);
56+
}
57+
size_t diff = detail::get_nb_diff(res, expected);
58+
EXPECT_EQ(diff, 0) << print_function_name("ceil");
59+
}
60+
// floor
61+
{
62+
std::transform(input.cbegin(), input.cend(), expected.begin(),
63+
[](const value_type& v) { return std::floor(v); });
64+
batch_type in, out;
65+
for (size_t i = 0; i < nb_batches; i += size)
66+
{
67+
detail::load_batch(in, input, i);
68+
out = floor(in);
69+
detail::store_batch(out, res, i);
70+
}
71+
for (size_t i = nb_batches; i < nb_input; ++i)
72+
{
73+
res[i] = std::floor(input[i]);
74+
}
75+
size_t diff = detail::get_nb_diff(res, expected);
76+
EXPECT_EQ(diff, 0) << print_function_name("floor");
77+
}
78+
// trunc
79+
{
80+
std::transform(input.cbegin(), input.cend(), expected.begin(),
81+
[](const value_type& v) { return std::trunc(v); });
82+
batch_type in, out;
83+
for (size_t i = 0; i < nb_batches; i += size)
84+
{
85+
detail::load_batch(in, input, i);
86+
out = trunc(in);
87+
detail::store_batch(out, res, i);
88+
}
89+
for (size_t i = nb_batches; i < nb_input; ++i)
90+
{
91+
res[i] = std::trunc(input[i]);
92+
}
93+
size_t diff = detail::get_nb_diff(res, expected);
94+
EXPECT_EQ(diff, 0) << print_function_name("trunc");
95+
}
96+
// round
97+
{
98+
std::transform(input.cbegin(), input.cend(), expected.begin(),
99+
[](const value_type& v) { return std::round(v); });
100+
batch_type in, out;
101+
for (size_t i = 0; i < nb_batches; i += size)
102+
{
103+
detail::load_batch(in, input, i);
104+
out = round(in);
105+
detail::store_batch(out, res, i);
106+
}
107+
for (size_t i = nb_batches; i < nb_input; ++i)
108+
{
109+
res[i] = std::round(input[i]);
110+
}
111+
size_t diff = detail::get_nb_diff(res, expected);
112+
EXPECT_EQ(diff, 0) << print_function_name("round");
113+
}
114+
// nearbyint
115+
{
116+
std::transform(input.cbegin(), input.cend(), expected.begin(),
117+
[](const value_type& v) { return std::nearbyint(v); });
118+
batch_type in, out;
119+
for (size_t i = 0; i < nb_batches; i += size)
120+
{
121+
detail::load_batch(in, input, i);
122+
out = nearbyint(in);
123+
detail::store_batch(out, res, i);
124+
}
125+
for (size_t i = nb_batches; i < nb_input; ++i)
126+
{
127+
res[i] = std::nearbyint(input[i]);
128+
}
129+
size_t diff = detail::get_nb_diff(res, expected);
130+
EXPECT_EQ(diff, 0) << print_function_name("nearbyint");
131+
}
132+
// rint
133+
{
134+
std::transform(input.cbegin(), input.cend(), expected.begin(),
135+
[](const value_type& v) { return std::rint(v); });
136+
batch_type in, out;
137+
for (size_t i = 0; i < nb_batches; i += size)
138+
{
139+
detail::load_batch(in, input, i);
140+
out = rint(in);
141+
detail::store_batch(out, res, i);
142+
}
143+
for (size_t i = nb_batches; i < nb_input; ++i)
144+
{
145+
res[i] = std::rint(input[i]);
146+
}
147+
size_t diff = detail::get_nb_diff(res, expected);
148+
EXPECT_EQ(diff, 0) << print_function_name("rint");
149+
}
150+
}
151+
};
152+
153+
TYPED_TEST_SUITE(rounding_test, batch_float_types, simd_test_names);
154+
155+
TYPED_TEST(rounding_test, rounding)
156+
{
157+
this->test_rounding_functions();
158+
}
159+

test/test_utils.hpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,20 +384,33 @@ namespace detail
384384
return expect_batch_near(lhs_expression, rhs_expression, tmp, rhs);
385385
}
386386

387-
template <class T, class A>
388-
size_t get_nb_diff(const std::vector<T, A>& lhs, const std::vector<T, A>& rhs)
387+
template <class It>
388+
size_t get_nb_diff(It lhs_begin, It lhs_end, It rhs_begin)
389389
{
390390
size_t res = 0;
391-
for (size_t i = 0; i < lhs.size(); ++i)
391+
using value_type = typename std::iterator_traits<It>::value_type;
392+
while (lhs_begin != lhs_end)
392393
{
393-
if (!scalar_comparison<T>::run(lhs[i], rhs[i]))
394+
if (!scalar_comparison<value_type>::run(*lhs_begin++, *rhs_begin++))
394395
{
395396
++res;
396397
}
397398
}
398399
return res;
399400
}
400401

402+
template <class T, class A>
403+
size_t get_nb_diff(const std::vector<T, A>& lhs, const std::vector<T, A>& rhs)
404+
{
405+
return get_nb_diff(lhs.begin(), lhs.end(), rhs.begin());
406+
}
407+
408+
template <class T, size_t N>
409+
size_t get_nb_diff(const std::array<T, N>& lhs, const std::array<T, N>& rhs)
410+
{
411+
return get_nb_diff(lhs.begin(), lhs.end(), rhs.begin());
412+
}
413+
401414
template <class B, class S>
402415
void load_batch(B& b, const S& src, size_t i = 0)
403416
{

0 commit comments

Comments
 (0)