1 // Copyright (c) 2015 Daniel Bourgeois
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #include <hpx/hpx_init.hpp>
7 #include <hpx/hpx.hpp>
8 #include <hpx/include/parallel_is_partitioned.hpp>
9 #include <hpx/util/lightweight_test.hpp>
10
11 #include <cstddef>
12 #include <iterator>
13 #include <iostream>
14 #include <string>
15 #include <random>
16 #include <vector>
17
18 #include "test_utils.hpp"
19
20 ////////////////////////////////////////////////////////////////////////////////
21 int seed = std::random_device{}();
22 std::mt19937 gen(seed);
23 std::uniform_int_distribution<> dis(0,99);
24
25 template <typename ExPolicy, typename IteratorTag>
test_partitioned1(ExPolicy policy,IteratorTag)26 void test_partitioned1(ExPolicy policy, IteratorTag)
27 {
28 static_assert(
29 hpx::parallel::execution::is_execution_policy<ExPolicy>::value,
30 "hpx::parallel::execution::is_execution_policy<ExPolicy>::value");
31
32 typedef std::vector<std::size_t>::iterator base_iterator;
33 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
34
35 std::vector<std::size_t> c(10007);
36 //fill first half of array with even numbers and second half
37 //with odd numbers
38 std::fill(std::begin(c), std::begin(c) + c.size()/2,
39 2*(dis(gen)));
40 std::fill(std::begin(c) + c.size()/2, std::end(c),
41 2*(dis(gen)) + 1);
42
43 bool parted = hpx::parallel::is_partitioned(policy,
44 iterator(std::begin(c)), iterator(std::end(c)),
45 [](std::size_t n){ return n % 2 == 0; });
46
47 HPX_TEST(parted);
48 }
49
50 template <typename ExPolicy, typename IteratorTag>
test_partitioned1_async(ExPolicy p,IteratorTag)51 void test_partitioned1_async(ExPolicy p, IteratorTag)
52 {
53 typedef std::vector<std::size_t>::iterator base_iterator;
54 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
55
56 std::vector<std::size_t> c(10007);
57 //fill first half of array with even numbers and second half
58 //with odd numbers
59 std::fill(std::begin(c), std::begin(c) + c.size()/2,
60 2*(dis(gen)));
61 std::fill(std::begin(c) + c.size()/2, std::end(c),
62 2*(dis(gen)) + 1);
63
64 hpx::future<bool> f =
65 hpx::parallel::is_partitioned(p,
66 iterator(std::begin(c)), iterator(std::end(c)),
67 [](std::size_t n){ return n % 2 == 0; });
68 f.wait();
69
70 HPX_TEST(f.get());
71 }
72
73 template <typename IteratorTag>
test_partitioned1()74 void test_partitioned1()
75 {
76 using namespace hpx::parallel;
77 test_partitioned1(execution::seq, IteratorTag());
78 test_partitioned1(execution::par, IteratorTag());
79 test_partitioned1(execution::par_unseq, IteratorTag());
80
81 test_partitioned1_async(execution::seq(execution::task), IteratorTag());
82 test_partitioned1_async(execution::par(execution::task), IteratorTag());
83 }
84
partitioned_test1()85 void partitioned_test1()
86 {
87 test_partitioned1<std::random_access_iterator_tag>();
88 test_partitioned1<std::forward_iterator_tag>();
89 #if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
90 test_partitioned1<std::input_iterator_tag>();
91 #endif
92 }
93
94 ////////////////////////////////////////////////////////////////////////////////
95 template <typename ExPolicy, typename IteratorTag>
test_partitioned2(ExPolicy policy,IteratorTag)96 void test_partitioned2(ExPolicy policy, IteratorTag)
97 {
98 static_assert(
99 hpx::parallel::execution::is_execution_policy<ExPolicy>::value,
100 "hpx::parallel::execution::is_execution_policy<ExPolicy>::value");
101
102 typedef std::vector<std::size_t>::iterator base_iterator;
103 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
104
105 std::vector<std::size_t> c_odd(10007);
106 //fill all of array with odds
107 std::fill(std::begin(c_odd), std::end(c_odd),
108 2*(dis(gen)) + 1);
109 std::vector<std::size_t> c_even(10007);
110 //fill all of array with evens
111 std::fill(std::begin(c_odd), std::end(c_odd),
112 2*(dis(gen)));
113
114 bool parted_odd = hpx::parallel::is_partitioned(policy,
115 iterator(std::begin(c_odd)), iterator(std::end(c_odd)),
116 [](std::size_t n){ return n % 2 == 0; });
117 bool parted_even = hpx::parallel::is_partitioned(policy,
118 iterator(std::begin(c_even)), iterator(std::end(c_even)),
119 [](std::size_t n){ return n % 2 == 0; });
120
121 HPX_TEST(parted_odd);
122 HPX_TEST(parted_even);
123 }
124
125 template <typename ExPolicy, typename IteratorTag>
test_partitioned2_async(ExPolicy p,IteratorTag)126 void test_partitioned2_async(ExPolicy p, IteratorTag)
127 {
128 typedef std::vector<std::size_t>::iterator base_iterator;
129 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
130
131 std::vector<std::size_t> c_odd(10007);
132 //fill all of array with odds
133 std::fill(std::begin(c_odd), std::end(c_odd),
134 2*(dis(gen)) + 1);
135 std::vector<std::size_t> c_even(10007);
136 //fill all of array with evens
137 std::fill(std::begin(c_odd), std::end(c_odd),
138 2*(dis(gen)));
139
140 hpx::future<bool> f_odd = hpx::parallel::is_partitioned(p,
141 iterator(std::begin(c_odd)), iterator(std::end(c_odd)),
142 [](std::size_t n){ return n % 2 == 0; });
143 hpx::future<bool> f_even = hpx::parallel::is_partitioned(p,
144 iterator(std::begin(c_even)), iterator(std::end(c_even)),
145 [](std::size_t n){ return n % 2 == 0; });
146
147 f_odd.wait();
148 HPX_TEST(f_odd.get());
149 f_even.wait();
150 HPX_TEST(f_even.get());
151 }
152
153 template <typename IteratorTag>
test_partitioned2()154 void test_partitioned2()
155 {
156 using namespace hpx::parallel;
157 test_partitioned2(execution::seq, IteratorTag());
158 test_partitioned2(execution::par, IteratorTag());
159 test_partitioned2(execution::par_unseq, IteratorTag());
160
161 test_partitioned2_async(execution::seq(execution::task), IteratorTag());
162 test_partitioned2_async(execution::par(execution::task), IteratorTag());
163 }
164
partitioned_test2()165 void partitioned_test2()
166 {
167 test_partitioned2<std::random_access_iterator_tag>();
168 test_partitioned2<std::forward_iterator_tag>();
169 #if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
170 test_partitioned2<std::input_iterator_tag>();
171 #endif
172 }
173
174 ////////////////////////////////////////////////////////////////////////////////
175 template <typename ExPolicy, typename IteratorTag>
test_partitioned3(ExPolicy policy,IteratorTag)176 void test_partitioned3(ExPolicy policy, IteratorTag)
177 {
178 static_assert(
179 hpx::parallel::execution::is_execution_policy<ExPolicy>::value,
180 "hpx::parallel::execution::is_execution_policy<ExPolicy>::value");
181
182 typedef std::vector<std::size_t>::iterator base_iterator;
183 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
184
185 std::vector<std::size_t> c_beg(10007);
186 //fill first half of array with even numbers and second half
187 //with odd numbers
188 std::fill(std::begin(c_beg), std::begin(c_beg) + c_beg.size()/2,
189 2*(dis(gen)));
190 std::fill(std::begin(c_beg) + c_beg.size()/2, std::end(c_beg),
191 2*(dis(gen)) + 1);
192 std::vector<size_t> c_end = c_beg;
193 //add odd number to the beginning
194 c_beg[0] -= 1;
195 //add even number to end
196 c_end[c_end.size()-1] -= 1;
197
198 bool parted1 = hpx::parallel::is_partitioned(policy,
199 iterator(std::begin(c_beg)), iterator(std::end(c_beg)),
200 [](std::size_t n){ return n % 2 == 0; });
201 bool parted2 = hpx::parallel::is_partitioned(policy,
202 iterator(std::begin(c_end)), iterator(std::end(c_end)),
203 [](std::size_t n){ return n % 2 == 0; });
204
205 HPX_TEST(!parted1);
206 HPX_TEST(!parted2);
207 }
208
209 template <typename ExPolicy, typename IteratorTag>
test_partitioned3_async(ExPolicy p,IteratorTag)210 void test_partitioned3_async(ExPolicy p, IteratorTag)
211 {
212 static_assert(
213 hpx::parallel::execution::is_execution_policy<ExPolicy>::value,
214 "hpx::parallel::execution::is_execution_policy<ExPolicy>::value");
215
216 typedef std::vector<std::size_t>::iterator base_iterator;
217 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
218
219 typedef std::vector<std::size_t>::iterator base_iterator;
220 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
221
222 std::vector<std::size_t> c_beg(10007);
223 //fill first half of array with even numbers and second half
224 //with odd numbers
225 std::fill(std::begin(c_beg), std::begin(c_beg) + c_beg.size()/2,
226 2*(dis(gen)));
227 std::fill(std::begin(c_beg) + c_beg.size()/2, std::end(c_beg),
228 2*(dis(gen)) + 1);
229 std::vector<size_t> c_end = c_beg;
230 //add odd number to the beginning
231 c_beg[0] -= 1;
232 //add even number to end
233 c_end[c_end.size()-1] -= 1;
234
235 hpx::future<bool> f_beg = hpx::parallel::is_partitioned(p,
236 iterator(std::begin(c_beg)), iterator(std::end(c_beg)),
237 [](std::size_t n){ return n % 2 == 0; });
238 hpx::future<bool> f_end = hpx::parallel::is_partitioned(p,
239 iterator(std::begin(c_end)), iterator(std::end(c_end)),
240 [](std::size_t n){ return n % 2 == 0; });
241
242 f_beg.wait();
243 HPX_TEST(!f_beg.get());
244 f_end.wait();
245 HPX_TEST(!f_end.get());
246 }
247
248 template <typename IteratorTag>
test_partitioned3()249 void test_partitioned3()
250 {
251 using namespace hpx::parallel;
252 test_partitioned3(execution::seq, IteratorTag());
253 test_partitioned3(execution::par, IteratorTag());
254 test_partitioned3(execution::par_unseq, IteratorTag());
255
256 test_partitioned3_async(execution::seq(execution::task), IteratorTag());
257 test_partitioned3_async(execution::par(execution::task), IteratorTag());
258 }
259
partitioned_test3()260 void partitioned_test3()
261 {
262 test_partitioned3<std::random_access_iterator_tag>();
263 test_partitioned3<std::forward_iterator_tag>();
264 #if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
265 test_partitioned3<std::input_iterator_tag>();
266 #endif
267 }
268
269 ////////////////////////////////////////////////////////////////////////////////
270 template <typename ExPolicy, typename IteratorTag>
test_partitioned_exception(ExPolicy policy,IteratorTag)271 void test_partitioned_exception(ExPolicy policy, IteratorTag)
272 {
273 static_assert(
274 hpx::parallel::execution::is_execution_policy<ExPolicy>::value,
275 "hpx::parallel::execution::is_execution_policy<ExPolicy>::value");
276
277 typedef std::vector<std::size_t>::iterator base_iterator;
278 typedef test::decorated_iterator<base_iterator, IteratorTag>
279 decorated_iterator;
280
281 std::vector<std::size_t> c(10007);
282 //fill first half of array with even numbers and second half
283 //with odd numbers
284 std::fill(std::begin(c), std::begin(c) + c.size()/2,
285 2*(dis(gen)));
286 std::fill(std::begin(c) + c.size()/2, std::end(c),
287 2*(dis(gen)) + 1);
288
289 bool caught_exception = false;
290 try{
291 hpx::parallel::is_partitioned(policy,
292 decorated_iterator(
293 std::begin(c),
294 [](){ throw std::runtime_error("test"); }),
295 decorated_iterator(
296 std::end(c),
297 [](){ throw std::runtime_error("test"); }),
298 [](std::size_t n){ return n % 2 == 0; });
299 }
300 catch(hpx::exception_list const& e) {
301 caught_exception = true;
302 test::test_num_exceptions<ExPolicy, IteratorTag>::call(policy, e);
303 }
304 catch(...) {
305 HPX_TEST(false);
306 }
307
308 HPX_TEST(caught_exception);
309 }
310
311 template <typename ExPolicy, typename IteratorTag>
test_partitioned_async_exception(ExPolicy p,IteratorTag)312 void test_partitioned_async_exception(ExPolicy p, IteratorTag)
313 {
314 typedef std::vector<std::size_t>::iterator base_iterator;
315 typedef test::decorated_iterator<base_iterator, IteratorTag>
316 decorated_iterator;
317
318 std::vector<std::size_t> c(10007);
319 //fill first half of array with even numbers and second half
320 //with odd numbers
321 std::fill(std::begin(c), std::begin(c) + c.size()/2,
322 2*(dis(gen)));
323 std::fill(std::begin(c) + c.size()/2, std::end(c),
324 2*(dis(gen)) + 1);
325
326 bool caught_exception = false;
327 try {
328 hpx::future<bool> f =
329 hpx::parallel::is_partitioned(p,
330 decorated_iterator(
331 std::begin(c),
332 [](){ throw std::runtime_error("test"); }),
333 decorated_iterator(
334 std::end(c),
335 [](){ throw std::runtime_error("test"); }),
336 [](std::size_t n){ return n % 2 == 0; });
337 f.get();
338
339 HPX_TEST(false);
340 }
341 catch(hpx::exception_list const& e) {
342 caught_exception = true;
343 test::test_num_exceptions<
344 ExPolicy, IteratorTag
345 >::call(p, e);
346 }
347 catch(...) {
348 HPX_TEST(false);
349 }
350
351 HPX_TEST(caught_exception);
352 }
353
354 template <typename IteratorTag>
test_partitioned_exception()355 void test_partitioned_exception()
356 {
357 using namespace hpx::parallel;
358 //If the execution policy object is of type vector_execution_policy,
359 // std::terminate shall be called. Therefore we do not test exceptions
360 // with a vector execution policy
361 test_partitioned_exception(execution::seq, IteratorTag());
362 test_partitioned_exception(execution::par, IteratorTag());
363
364 test_partitioned_async_exception(execution::seq(execution::task), IteratorTag());
365 test_partitioned_async_exception(execution::par(execution::task), IteratorTag());
366 }
367
partitioned_exception_test()368 void partitioned_exception_test()
369 {
370 test_partitioned_exception<std::random_access_iterator_tag>();
371 test_partitioned_exception<std::forward_iterator_tag>();
372 #if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
373 test_partitioned_exception<std::input_iterator_tag>();
374 #endif
375 }
376
377 ////////////////////////////////////////////////////////////////////////////////
378 template <typename ExPolicy, typename IteratorTag>
test_partitioned_bad_alloc(ExPolicy policy,IteratorTag)379 void test_partitioned_bad_alloc(ExPolicy policy, IteratorTag)
380 {
381 static_assert(
382 hpx::parallel::execution::is_execution_policy<ExPolicy>::value,
383 "hpx::parallel::execution::is_execution_policy<ExPolicy>::value");
384
385 typedef std::vector<std::size_t>::iterator base_iterator;
386 typedef test::decorated_iterator<base_iterator, IteratorTag>
387 decorated_iterator;
388
389 std::vector<std::size_t> c(10007);
390 //fill first half of array with even numbers and second half
391 //with odd numbers
392 std::fill(std::begin(c), std::begin(c) + c.size()/2,
393 2*(dis(gen)));
394 std::fill(std::begin(c) + c.size()/2, std::end(c),
395 2*(dis(gen)) + 1);
396
397 bool caught_bad_alloc = false;
398 try {
399 hpx::parallel::is_partitioned(policy,
400 decorated_iterator(
401 std::begin(c),
402 [](){ throw std::bad_alloc(); }),
403 decorated_iterator(
404 std::end(c),
405 [](){ throw std::bad_alloc(); }),
406 [](std::size_t n){ return n % 2 == 0; });
407 HPX_TEST(false);
408 }
409 catch(std::bad_alloc const&) {
410 caught_bad_alloc = true;
411 }
412 catch(...) {
413 HPX_TEST(false);
414 }
415
416 HPX_TEST(caught_bad_alloc);
417 }
418
419 template <typename ExPolicy, typename IteratorTag>
test_partitioned_async_bad_alloc(ExPolicy p,IteratorTag)420 void test_partitioned_async_bad_alloc(ExPolicy p, IteratorTag)
421 {
422 typedef std::vector<std::size_t>::iterator base_iterator;
423 typedef test::decorated_iterator<base_iterator, IteratorTag>
424 decorated_iterator;
425
426 std::vector<std::size_t> c(10007);
427 //fill first half of array with even numbers and second half
428 //with odd numbers
429 std::fill(std::begin(c), std::begin(c) + c.size()/2,
430 2*(dis(gen)));
431 std::fill(std::begin(c) + c.size()/2, std::end(c),
432 2*(dis(gen)) + 1);
433
434 bool caught_bad_alloc = false;
435 try {
436 hpx::future<bool> f =
437 hpx::parallel::is_partitioned(p,
438 decorated_iterator(
439 std::begin(c),
440 [](){ throw std::bad_alloc(); }),
441 decorated_iterator(
442 std::end(c),
443 [](){ throw std::bad_alloc(); }),
444 [](std::size_t n){ return n % 2 == 0; });
445
446 f.get();
447 HPX_TEST(false);
448 }
449 catch(std::bad_alloc const&) {
450 caught_bad_alloc = true;
451 }
452 catch(...) {
453 HPX_TEST(false);
454 }
455
456 HPX_TEST(caught_bad_alloc);
457 }
458
459 template <typename IteratorTag>
test_partitioned_bad_alloc()460 void test_partitioned_bad_alloc()
461 {
462 using namespace hpx::parallel;
463
464 // If the execution policy object is of type vector_execution_policy,
465 // std::terminate shall be called. therefore we do not test exceptions
466 // with a vector execution policy
467 test_partitioned_bad_alloc(execution::par, IteratorTag());
468 test_partitioned_bad_alloc(execution::seq, IteratorTag());
469
470 test_partitioned_async_bad_alloc(execution::seq(execution::task), IteratorTag());
471 test_partitioned_async_bad_alloc(execution::par(execution::task), IteratorTag());
472 }
473
partitioned_bad_alloc_test()474 void partitioned_bad_alloc_test()
475 {
476 test_partitioned_bad_alloc<std::random_access_iterator_tag>();
477 test_partitioned_bad_alloc<std::forward_iterator_tag>();
478 #if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
479 test_partitioned_bad_alloc<std::input_iterator_tag>();
480 #endif
481 }
482
483
hpx_main(boost::program_options::variables_map & vm)484 int hpx_main(boost::program_options::variables_map& vm)
485 {
486 partitioned_test1();
487 partitioned_test2();
488 partitioned_test3();
489 partitioned_exception_test();
490 partitioned_bad_alloc_test();
491
492 return hpx::finalize();
493 }
494
main(int argc,char * argv[])495 int main(int argc, char* argv[])
496 {
497 using namespace boost::program_options;
498 options_description desc_commandline(
499 "Usage: " HPX_APPLICATION_STRING " [options]");
500
501 std::vector<std::string> const cfg = {
502 "hpx.os_threads=all"
503 };
504
505 HPX_TEST_EQ_MSG(hpx::init(desc_commandline, argc, argv, cfg), 0,
506 "HPX main exited with non-zero status");
507
508 return hpx::util::report_errors();
509 }
510