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