ddemidov / vexcl
1
#define BOOST_TEST_MODULE VectorArithmetics
2
#include <boost/accumulators/accumulators.hpp>
3
#include <boost/accumulators/statistics/stats.hpp>
4
#include <boost/accumulators/statistics/sum_kahan.hpp>
5
#include <boost/test/unit_test.hpp>
6
#include <vexcl/constants.hpp>
7
#include <vexcl/vector.hpp>
8
#include <vexcl/reductor.hpp>
9
#include <vexcl/element_index.hpp>
10
#include <vexcl/tagged_terminal.hpp>
11
#include <vexcl/function.hpp>
12
#ifndef VEXCL_BACKEND_CUDA
13
#include <vexcl/vector_view.hpp>
14
#include <vexcl/constant_address_space.hpp>
15
#endif
16
#include <boost/math/constants/constants.hpp>
17
#include "context_setup.hpp"
18

19 6
BOOST_AUTO_TEST_CASE(access_element)
20
{
21 6
    vex::vector<double> x(ctx, 5);
22 6
    x = 5;
23 6
    x[2] = 2;
24 6
    x.at(3) = 3;
25

26

27 6
    BOOST_CHECK_EQUAL(x[1], 5.0);
28 6
    BOOST_CHECK_EQUAL(x.at(2), 2.0);
29 6
    BOOST_CHECK_EQUAL(x[3], 3.0);
30 6
    BOOST_CHECK_THROW(x.at(5), std::out_of_range);
31
}
32

33 6
BOOST_AUTO_TEST_CASE(assign_expression)
34
{
35
    const size_t N = 1024;
36

37 6
    vex::vector<double> x(ctx, N);
38 6
    vex::vector<double> y(ctx, N);
39 6
    vex::vector<double> z(ctx, N);
40

41 6
    y = 42;
42 6
    z = 67;
43 6
    x = 5 * sin(y) + z;
44

45 6
    check_sample(x, [](size_t, double a) {
46 6
            BOOST_CHECK_CLOSE(a, 5 * sin(42.0) + 67, 1e-12);
47 6
            });
48
}
49

50 6
BOOST_AUTO_TEST_CASE(compound_assignment)
51
{
52
    const size_t n = 1024;
53

54 6
    vex::vector<double> x(ctx, n);
55

56 6
    x = 0;
57 6
    x += 1;
58

59 6
    check_sample(x, [](size_t, double a) { BOOST_CHECK(a == 1); });
60

61 6
    x -= 2;
62

63 6
    check_sample(x, [](size_t, double a) { BOOST_CHECK(a == -1); });
64
}
65

66 6
BOOST_AUTO_TEST_CASE(reduce_expression)
67
{
68
    namespace acc = boost::accumulators;
69

70
    const size_t N = 1024;
71

72 6
    std::vector<double> x = random_vector<double>(N);
73 6
    std::transform(x.begin(), x.end(), x.begin(), [](double v){ return (v - 0.5) * 1e8; });
74

75 6
    vex::vector<double> X(ctx, x);
76

77 6
    vex::Reductor<double,vex::SUM      > sum(ctx);
78 6
    vex::Reductor<double,vex::MIN      > min(ctx);
79 6
    vex::Reductor<double,vex::MAX      > max(ctx);
80 6
    vex::Reductor<double,vex::SUM_Kahan> csum(ctx);
81

82 6
    acc::accumulator_set< double, acc::stats< acc::tag::sum_kahan > > stat;
83 6
    std::for_each(x.begin(), x.end(), std::ref(stat));
84

85 6
    BOOST_CHECK_CLOSE(sum(X),  acc::sum_kahan(stat), 1e-8);
86 6
    BOOST_CHECK_CLOSE(csum(X), acc::sum_kahan(stat), 1e-8);
87

88 6
    BOOST_CHECK_EQUAL(min(X), *std::min_element(x.begin(), x.end()));
89 6
    BOOST_CHECK_EQUAL(max(X), *std::max_element(x.begin(), x.end()));
90

91
#ifndef BOOST_NO_VARIADIC_TEMPLATES
92 6
    vex::Reductor<double,vex::MIN_MAX  > minmax(ctx);
93 6
    auto mm = minmax(X);
94 6
    BOOST_CHECK_EQUAL(mm.s[0], *std::min_element(x.begin(), x.end()));
95 6
    BOOST_CHECK_EQUAL(mm.s[1], *std::max_element(x.begin(), x.end()));
96
#endif
97

98 6
    BOOST_CHECK_EQUAL( max( fabs(X - X) ), 0.0);
99
}
100

101 6
BOOST_AUTO_TEST_CASE(builtin_functions)
102
{
103
    const size_t N = 1024;
104 6
    std::vector<double> x = random_vector<double>(N);
105 6
    vex::vector<double> X(ctx, x);
106 6
    vex::vector<double> Y(ctx, N);
107

108 6
    Y = pow(sin(X), 2.0) + pow(cos(X), 2.0);
109

110 6
    check_sample(Y, [](size_t, double a) { BOOST_CHECK_CLOSE(a, 1, 1e-8); });
111
}
112

113 6
BOOST_AUTO_TEST_CASE(user_defined_functions)
114
{
115
    const size_t N = 1024;
116

117 6
    vex::vector<double> x(ctx, N);
118 6
    vex::vector<double> y(ctx, N);
119

120 6
    x = 1;
121 6
    y = 2;
122

123 6
    VEX_FUNCTION(size_t, greater, (double, x)(double, y), return x > y;);
124

125 6
    vex::Reductor<size_t,vex::SUM> sum(ctx);
126

127 6
    BOOST_CHECK( sum( greater(x, y) ) == 0U);
128 6
    BOOST_CHECK( sum( greater(y, x) ) == N);
129
}
130

131 6
BOOST_AUTO_TEST_CASE(user_defined_functions_same_signature)
132
{
133
    const size_t N = 1024;
134 6
    vex::vector<double> x(ctx, N);
135

136 6
    x = 1;
137

138 6
    VEX_FUNCTION(double, times2, (double, x), return x * 2;);
139 6
    VEX_FUNCTION(double, times4, (double, x), return x * 4;);
140

141 6
    vex::Reductor<size_t,vex::SUM> sum(ctx);
142

143 6
    BOOST_CHECK( sum( times2(x) ) == 2 * N );
144 6
    BOOST_CHECK( sum( times4(x) ) == 4 * N );
145
}
146

147 6
BOOST_AUTO_TEST_CASE(element_index)
148
{
149
    const size_t N = 1024;
150

151 6
    vex::vector<double> x(ctx, N);
152

153 6
    x = sin(0.5 * vex::element_index());
154

155 6
    check_sample(x, [](size_t idx, double a) { BOOST_CHECK_CLOSE(a, sin(0.5 * idx), 1e-6); });
156
}
157

158
#if !defined(VEXCL_BACKEND_CUDA) && !defined(VEXCL_BACKEND_JIT) && !defined(__APPLE__)
159
BOOST_AUTO_TEST_CASE(vector_values)
160
{
161
    const size_t N = 1024;
162

163
    VEX_FUNCTION(cl_int4, make_int4, (int, x), return (int4)(x, x, x, x););
164

165
    cl_int4 c = {{1, 2, 3, 4}};
166

167
    vex::vector<cl_int4> X(ctx, N);
168
    X = c * (make_int4(5 + vex::element_index()));
169

170
    check_sample(X, [c](size_t idx, cl_int4 v) {
171
            for(int j = 0; j < 4; ++j)
172
                BOOST_CHECK(v.s[j] == c.s[j] * (5 + static_cast<int>(idx)));
173
            });
174
}
175
#endif
176

177 6
BOOST_AUTO_TEST_CASE(nested_functions)
178
{
179
    const size_t N = 1024;
180

181 6
    VEX_FUNCTION(int, f, (int, x), return 2 * x;);
182 6
    VEX_FUNCTION(int, g, (int, x), return 3 * x;);
183

184 6
    vex::vector<int> x(ctx, N);
185

186 6
    x = 1;
187 6
    x = f(f(x));
188 6
    check_sample(x, [](size_t, int a) { BOOST_CHECK(a == 4); });
189

190 6
    x = 1;
191 6
    x = g(f(x));
192 6
    check_sample(x, [](size_t, int a) { BOOST_CHECK(a == 6); });
193
}
194

195 6
BOOST_AUTO_TEST_CASE(custom_header)
196
{
197
    const size_t n = 1024;
198

199 6
    vex::vector<int> x(ctx, n);
200

201 6
    vex::push_program_header(ctx, "#define THE_ANSWER 42\n");
202

203 6
    VEX_FUNCTION(int, answer, (int, x), return x * THE_ANSWER;);
204

205 6
    x = answer(1);
206

207 6
    check_sample(x, [](size_t, int a) {
208 6
            BOOST_CHECK(a == 42);
209 6
            });
210

211 6
    vex::pop_program_header(ctx);
212
}
213

214
// Have to define these outside of the following test case scope.
215
// In Visual C++ is not types defined in enclosing function scope
216
// are not able to refeence each other.
217 6
VEX_FUNCTION(double, sin2, (double, x), return pow(sin(x), 2.0););
218 6
VEX_FUNCTION(double, cos2, (double, x), return pow(cos(x), 2.0););
219

220 6
BOOST_AUTO_TEST_CASE(function_with_preamble)
221
{
222
    const size_t n = 1024;
223

224 6
    vex::vector<double> x(ctx, random_vector<double>(n));
225 6
    vex::vector<double> y(ctx, n);
226

227 6
    VEX_FUNCTION_D(double, one, (double, x), (sin2)(cos2),
228
            return sin2(x) + cos2(x);
229
            );
230

231 6
    y = one(x);
232

233 6
    check_sample(y, [](size_t, double a) {
234 6
            BOOST_CHECK_CLOSE(a, 1.0, 1e-8);
235 6
            });
236
}
237

238 6
BOOST_AUTO_TEST_CASE(ternary_operator)
239
{
240
    const size_t n = 1024;
241

242 6
    vex::vector<double> x(ctx, random_vector<double>(n));
243 6
    vex::vector<double> y(ctx, n);
244

245 6
    y = if_else(x > 0.5, sin(x), cos(x));
246

247 6
    check_sample(x, y, [&](size_t, double X, double Y) {
248 6
            BOOST_CHECK_CLOSE(Y, X > 0.5 ? sin(X) : cos(X), 1e-8);
249 6
            });
250
}
251

252 6
BOOST_AUTO_TEST_CASE(assign_to_ternary_operator)
253
{
254
    const size_t n = 32;
255

256 6
    vex::vector<double> x(ctx, random_vector<double>(n));
257 6
    vex::vector<double> y(ctx, n);
258 6
    vex::vector<double> z(ctx, n);
259

260 6
    y = 0;
261 6
    z = 0;
262

263 6
    vex::tie( *if_else(x < 0.5, &y, &z) ) = 42;
264

265 6
    check_sample(x, y, z, [&](size_t, double X, double Y, double Z) {
266 6
            BOOST_CHECK_EQUAL(X < 0.5 ? Y : Z, 42);
267 6
            BOOST_CHECK_EQUAL(X < 0.5 ? Z : Y, 0);
268 6
            });
269
}
270

271 6
BOOST_AUTO_TEST_CASE(combine_expressions)
272
{
273
    const size_t n = 1024;
274

275 6
    vex::vector<double> x(ctx, n);
276

277 6
    auto alpha  = vex::constants::two_pi() * vex::tag<1>(vex::element_index());
278 6
    auto sine   = sin(alpha);
279 6
    auto cosine = cos(alpha);
280

281 6
    x = pow(sine, 2.0) + pow(cosine, 2.0);
282

283 6
    check_sample(x, [](size_t, double v) { BOOST_CHECK_CLOSE(v, 1.0, 1e-8); });
284
}
285

286 6
BOOST_AUTO_TEST_CASE(constants)
287
{
288
    const size_t n = 1024;
289

290 6
    vex::vector<double> x(ctx, n);
291

292 6
    x = std::integral_constant<int, 42>();
293 6
    check_sample(x, [](size_t, double v) { BOOST_CHECK_EQUAL(v, 42); });
294

295 6
    x = vex::constants::pi();
296 6
    check_sample(x, [](size_t, double v) { BOOST_CHECK_CLOSE(v, boost::math::constants::pi<double>(), 1e-8); });
297
}
298

299
#ifndef VEXCL_BACKEND_CUDA
300 6
BOOST_AUTO_TEST_CASE(constant_address_space)
301
{
302 6
    std::vector<vex::command_queue> queue(1, ctx.queue(0));
303

304
    const size_t N = 1024;
305

306 6
    int host_data[] = {1, 2, 3, 4};
307

308 6
    vex::vector<int> x(queue, 4, host_data, vex::backend::MEM_READ_ONLY);
309 6
    vex::vector<int> y(queue, N);
310

311 6
    y = vex::permutation(vex::element_index() % 4)( vex::constant(x) );
312

313 6
    check_sample(y, [&](size_t idx, int v) {
314 6
            BOOST_CHECK_EQUAL(v, host_data[idx % 4]);
315 6
            });
316
}
317
#endif
318

319
#if (VEXCL_CHECK_SIZES > 0)
320
BOOST_AUTO_TEST_CASE(expression_size_check)
321
{
322
    vex::vector<int> x(ctx, 16);
323
    vex::vector<int> y(ctx, 32);
324

325
    BOOST_CHECK_THROW(x = y, std::runtime_error);
326
}
327
#endif
328

329 6
BOOST_AUTO_TEST_SUITE_END()

Read our documentation on viewing source code .

Loading