1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 //                        Kokkos v. 3.0
6 //       Copyright (2020) National Technology & Engineering
7 //               Solutions of Sandia, LLC (NTESS).
8 //
9 // Under the terms of Contract DE-NA0003525 with NTESS,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Christian R. Trott (crtrott@sandia.gov)
40 //
41 // ************************************************************************
42 //@HEADER
43 */
44 
45 #include <gtest/gtest.h>
46 
47 #include <Kokkos_Core.hpp>
48 #include <stdexcept>
49 #include <sstream>
50 #include <iostream>
51 #include <type_traits>
52 
53 namespace Test {
54 struct SomeTag {};
55 
56 template <class ExecutionSpace>
57 class TestRangePolicyConstruction {
58  public:
TestRangePolicyConstruction()59   TestRangePolicyConstruction() {
60     test_compile_time_parameters();
61     test_runtime_parameters();
62   }
63 
64  private:
test_compile_time_parameters()65   void test_compile_time_parameters() {
66     {
67       using policy_t        = Kokkos::RangePolicy<>;
68       using execution_space = typename policy_t::execution_space;
69       using index_type      = typename policy_t::index_type;
70       using schedule_type   = typename policy_t::schedule_type;
71       using work_tag        = typename policy_t::work_tag;
72 
73       ASSERT_TRUE((
74           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
75       ASSERT_TRUE((std::is_same<index_type,
76                                 typename execution_space::size_type>::value));
77       ASSERT_TRUE((std::is_same<schedule_type,
78                                 Kokkos::Schedule<Kokkos::Static>>::value));
79       ASSERT_TRUE((std::is_same<work_tag, void>::value));
80     }
81 
82     {
83       using policy_t        = Kokkos::RangePolicy<ExecutionSpace>;
84       using execution_space = typename policy_t::execution_space;
85       using index_type      = typename policy_t::index_type;
86       using schedule_type   = typename policy_t::schedule_type;
87       using work_tag        = typename policy_t::work_tag;
88 
89       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
90       ASSERT_TRUE((std::is_same<index_type,
91                                 typename execution_space::size_type>::value));
92       ASSERT_TRUE((std::is_same<schedule_type,
93                                 Kokkos::Schedule<Kokkos::Static>>::value));
94       ASSERT_TRUE((std::is_same<work_tag, void>::value));
95     }
96 
97     {
98       using policy_t        = Kokkos::RangePolicy<ExecutionSpace,
99                                            Kokkos::Schedule<Kokkos::Dynamic>>;
100       using execution_space = typename policy_t::execution_space;
101       using index_type      = typename policy_t::index_type;
102       using schedule_type   = typename policy_t::schedule_type;
103       using work_tag        = typename policy_t::work_tag;
104 
105       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
106       ASSERT_TRUE((std::is_same<index_type,
107                                 typename execution_space::size_type>::value));
108       ASSERT_TRUE((std::is_same<schedule_type,
109                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
110       ASSERT_TRUE((std::is_same<work_tag, void>::value));
111     }
112 
113     {
114       using policy_t =
115           Kokkos::RangePolicy<ExecutionSpace, Kokkos::Schedule<Kokkos::Dynamic>,
116                               Kokkos::IndexType<long>>;
117       using execution_space = typename policy_t::execution_space;
118       using index_type      = typename policy_t::index_type;
119       using schedule_type   = typename policy_t::schedule_type;
120       using work_tag        = typename policy_t::work_tag;
121 
122       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
123       ASSERT_TRUE((std::is_same<index_type, long>::value));
124       ASSERT_TRUE((std::is_same<schedule_type,
125                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
126       ASSERT_TRUE((std::is_same<work_tag, void>::value));
127     }
128 
129     {
130       using policy_t =
131           Kokkos::RangePolicy<Kokkos::IndexType<long>, ExecutionSpace,
132                               Kokkos::Schedule<Kokkos::Dynamic>>;
133       using execution_space = typename policy_t::execution_space;
134       using index_type      = typename policy_t::index_type;
135       using schedule_type   = typename policy_t::schedule_type;
136       using work_tag        = typename policy_t::work_tag;
137 
138       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
139       ASSERT_TRUE((std::is_same<index_type, long>::value));
140       ASSERT_TRUE((std::is_same<schedule_type,
141                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
142       ASSERT_TRUE((std::is_same<work_tag, void>::value));
143     }
144 
145     {
146       using policy_t =
147           Kokkos::RangePolicy<ExecutionSpace, Kokkos::Schedule<Kokkos::Dynamic>,
148                               Kokkos::IndexType<long>, SomeTag>;
149       using execution_space = typename policy_t::execution_space;
150       using index_type      = typename policy_t::index_type;
151       using schedule_type   = typename policy_t::schedule_type;
152       using work_tag        = typename policy_t::work_tag;
153 
154       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
155       ASSERT_TRUE((std::is_same<index_type, long>::value));
156       ASSERT_TRUE((std::is_same<schedule_type,
157                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
158       ASSERT_TRUE((std::is_same<work_tag, SomeTag>::value));
159     }
160 
161     {
162       using policy_t =
163           Kokkos::RangePolicy<Kokkos::Schedule<Kokkos::Dynamic>, ExecutionSpace,
164                               Kokkos::IndexType<long>, SomeTag>;
165       using execution_space = typename policy_t::execution_space;
166       using index_type      = typename policy_t::index_type;
167       using schedule_type   = typename policy_t::schedule_type;
168       using work_tag        = typename policy_t::work_tag;
169 
170       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
171       ASSERT_TRUE((std::is_same<index_type, long>::value));
172       ASSERT_TRUE((std::is_same<schedule_type,
173                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
174       ASSERT_TRUE((std::is_same<work_tag, SomeTag>::value));
175     }
176 
177     {
178       using policy_t =
179           Kokkos::RangePolicy<SomeTag, Kokkos::Schedule<Kokkos::Dynamic>,
180                               Kokkos::IndexType<long>, ExecutionSpace>;
181       using execution_space = typename policy_t::execution_space;
182       using index_type      = typename policy_t::index_type;
183       using schedule_type   = typename policy_t::schedule_type;
184       using work_tag        = typename policy_t::work_tag;
185 
186       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
187       ASSERT_TRUE((std::is_same<index_type, long>::value));
188       ASSERT_TRUE((std::is_same<schedule_type,
189                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
190       ASSERT_TRUE((std::is_same<work_tag, SomeTag>::value));
191     }
192 
193     {
194       using policy_t = Kokkos::RangePolicy<Kokkos::Schedule<Kokkos::Dynamic>>;
195       using execution_space = typename policy_t::execution_space;
196       using index_type      = typename policy_t::index_type;
197       using schedule_type   = typename policy_t::schedule_type;
198       using work_tag        = typename policy_t::work_tag;
199 
200       ASSERT_TRUE((
201           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
202       ASSERT_TRUE((std::is_same<index_type,
203                                 typename execution_space::size_type>::value));
204       ASSERT_TRUE((std::is_same<schedule_type,
205                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
206       ASSERT_TRUE((std::is_same<work_tag, void>::value));
207     }
208 
209     {
210       using policy_t = Kokkos::RangePolicy<Kokkos::Schedule<Kokkos::Dynamic>,
211                                            Kokkos::IndexType<long>>;
212       using execution_space = typename policy_t::execution_space;
213       using index_type      = typename policy_t::index_type;
214       using schedule_type   = typename policy_t::schedule_type;
215       using work_tag        = typename policy_t::work_tag;
216 
217       ASSERT_TRUE((
218           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
219       ASSERT_TRUE((std::is_same<index_type, long>::value));
220       ASSERT_TRUE((std::is_same<schedule_type,
221                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
222       ASSERT_TRUE((std::is_same<work_tag, void>::value));
223     }
224 
225     {
226       using policy_t        = Kokkos::RangePolicy<Kokkos::IndexType<long>,
227                                            Kokkos::Schedule<Kokkos::Dynamic>>;
228       using execution_space = typename policy_t::execution_space;
229       using index_type      = typename policy_t::index_type;
230       using schedule_type   = typename policy_t::schedule_type;
231       using work_tag        = typename policy_t::work_tag;
232 
233       ASSERT_TRUE((
234           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
235       ASSERT_TRUE((std::is_same<index_type, long>::value));
236       ASSERT_TRUE((std::is_same<schedule_type,
237                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
238       ASSERT_TRUE((std::is_same<work_tag, void>::value));
239     }
240 
241     {
242       using policy_t = Kokkos::RangePolicy<Kokkos::Schedule<Kokkos::Dynamic>,
243                                            Kokkos::IndexType<long>, SomeTag>;
244       using execution_space = typename policy_t::execution_space;
245       using index_type      = typename policy_t::index_type;
246       using schedule_type   = typename policy_t::schedule_type;
247       using work_tag        = typename policy_t::work_tag;
248 
249       ASSERT_TRUE((
250           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
251       ASSERT_TRUE((std::is_same<index_type, long>::value));
252       ASSERT_TRUE((std::is_same<schedule_type,
253                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
254       ASSERT_TRUE((std::is_same<work_tag, SomeTag>::value));
255     }
256 
257     {
258       using policy_t = Kokkos::RangePolicy<Kokkos::Schedule<Kokkos::Dynamic>,
259                                            Kokkos::IndexType<long>, SomeTag>;
260       using execution_space = typename policy_t::execution_space;
261       using index_type      = typename policy_t::index_type;
262       using schedule_type   = typename policy_t::schedule_type;
263       using work_tag        = typename policy_t::work_tag;
264 
265       ASSERT_TRUE((
266           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
267       ASSERT_TRUE((std::is_same<index_type, long>::value));
268       ASSERT_TRUE((std::is_same<schedule_type,
269                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
270       ASSERT_TRUE((std::is_same<work_tag, SomeTag>::value));
271     }
272 
273     {
274       using policy_t =
275           Kokkos::RangePolicy<SomeTag, Kokkos::Schedule<Kokkos::Dynamic>,
276                               Kokkos::IndexType<long>>;
277       using execution_space = typename policy_t::execution_space;
278       using index_type      = typename policy_t::index_type;
279       using schedule_type   = typename policy_t::schedule_type;
280       using work_tag        = typename policy_t::work_tag;
281 
282       ASSERT_TRUE((
283           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
284       ASSERT_TRUE((std::is_same<index_type, long>::value));
285       ASSERT_TRUE((std::is_same<schedule_type,
286                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
287       ASSERT_TRUE((std::is_same<work_tag, SomeTag>::value));
288     }
289   }
test_runtime_parameters()290   void test_runtime_parameters() {
291     using policy_t = Kokkos::RangePolicy<>;
292     {
293       policy_t p(5, 15);
294       ASSERT_TRUE((p.begin() == 5));
295       ASSERT_TRUE((p.end() == 15));
296     }
297     {
298       policy_t p(Kokkos::DefaultExecutionSpace(), 5, 15);
299       ASSERT_TRUE((p.begin() == 5));
300       ASSERT_TRUE((p.end() == 15));
301     }
302     {
303       policy_t p(5, 15, Kokkos::ChunkSize(10));
304       ASSERT_TRUE((p.begin() == 5));
305       ASSERT_TRUE((p.end() == 15));
306       ASSERT_TRUE((p.chunk_size() == 10));
307     }
308     {
309       policy_t p(Kokkos::DefaultExecutionSpace(), 5, 15, Kokkos::ChunkSize(10));
310       ASSERT_TRUE((p.begin() == 5));
311       ASSERT_TRUE((p.end() == 15));
312       ASSERT_TRUE((p.chunk_size() == 10));
313     }
314     {
315       policy_t p;
316       ASSERT_TRUE((p.begin() == 0));
317       ASSERT_TRUE((p.end() == 0));
318       p = policy_t(5, 15, Kokkos::ChunkSize(10));
319       ASSERT_TRUE((p.begin() == 5));
320       ASSERT_TRUE((p.end() == 15));
321       ASSERT_TRUE((p.chunk_size() == 10));
322     }
323   }
324 };
325 
326 template <class ExecutionSpace>
327 class TestTeamPolicyConstruction {
328  public:
TestTeamPolicyConstruction()329   TestTeamPolicyConstruction() {
330     test_compile_time_parameters();
331     test_run_time_parameters();
332   }
333 
334  private:
test_compile_time_parameters()335   void test_compile_time_parameters() {
336     {
337       using policy_t        = Kokkos::TeamPolicy<>;
338       using execution_space = typename policy_t::execution_space;
339       using index_type      = typename policy_t::index_type;
340       using schedule_type   = typename policy_t::schedule_type;
341       using work_tag        = typename policy_t::work_tag;
342 
343       ASSERT_TRUE((
344           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
345       ASSERT_TRUE((std::is_same<index_type,
346                                 typename execution_space::size_type>::value));
347       ASSERT_TRUE((std::is_same<schedule_type,
348                                 Kokkos::Schedule<Kokkos::Static>>::value));
349       ASSERT_TRUE((std::is_same<work_tag, void>::value));
350     }
351 
352     {
353       using policy_t        = Kokkos::TeamPolicy<ExecutionSpace>;
354       using execution_space = typename policy_t::execution_space;
355       using index_type      = typename policy_t::index_type;
356       using schedule_type   = typename policy_t::schedule_type;
357       using work_tag        = typename policy_t::work_tag;
358 
359       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
360       ASSERT_TRUE((std::is_same<index_type,
361                                 typename execution_space::size_type>::value));
362       ASSERT_TRUE((std::is_same<schedule_type,
363                                 Kokkos::Schedule<Kokkos::Static>>::value));
364       ASSERT_TRUE((std::is_same<work_tag, void>::value));
365     }
366 
367     {
368       using policy_t =
369           Kokkos::TeamPolicy<ExecutionSpace, Kokkos::Schedule<Kokkos::Dynamic>>;
370       using execution_space = typename policy_t::execution_space;
371       using index_type      = typename policy_t::index_type;
372       using schedule_type   = typename policy_t::schedule_type;
373       using work_tag        = typename policy_t::work_tag;
374 
375       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
376       ASSERT_TRUE((std::is_same<index_type,
377                                 typename execution_space::size_type>::value));
378       ASSERT_TRUE((std::is_same<schedule_type,
379                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
380       ASSERT_TRUE((std::is_same<work_tag, void>::value));
381     }
382 
383     {
384       using policy_t =
385           Kokkos::TeamPolicy<ExecutionSpace, Kokkos::Schedule<Kokkos::Dynamic>,
386                              Kokkos::IndexType<long>>;
387       using execution_space = typename policy_t::execution_space;
388       using index_type      = typename policy_t::index_type;
389       using schedule_type   = typename policy_t::schedule_type;
390       using work_tag        = typename policy_t::work_tag;
391 
392       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
393       ASSERT_TRUE((std::is_same<index_type, long>::value));
394       ASSERT_TRUE((std::is_same<schedule_type,
395                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
396       ASSERT_TRUE((std::is_same<work_tag, void>::value));
397     }
398 
399     {
400       using policy_t =
401           Kokkos::TeamPolicy<Kokkos::IndexType<long>, ExecutionSpace,
402                              Kokkos::Schedule<Kokkos::Dynamic>>;
403       using execution_space = typename policy_t::execution_space;
404       using index_type      = typename policy_t::index_type;
405       using schedule_type   = typename policy_t::schedule_type;
406       using work_tag        = typename policy_t::work_tag;
407 
408       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
409       ASSERT_TRUE((std::is_same<index_type, long>::value));
410       ASSERT_TRUE((std::is_same<schedule_type,
411                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
412       ASSERT_TRUE((std::is_same<work_tag, void>::value));
413     }
414 
415     {
416       using policy_t =
417           Kokkos::TeamPolicy<ExecutionSpace, Kokkos::Schedule<Kokkos::Dynamic>,
418                              Kokkos::IndexType<long>, SomeTag>;
419       using execution_space = typename policy_t::execution_space;
420       using index_type      = typename policy_t::index_type;
421       using schedule_type   = typename policy_t::schedule_type;
422       using work_tag        = typename policy_t::work_tag;
423 
424       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
425       ASSERT_TRUE((std::is_same<index_type, long>::value));
426       ASSERT_TRUE((std::is_same<schedule_type,
427                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
428       ASSERT_TRUE((std::is_same<work_tag, SomeTag>::value));
429     }
430 
431     {
432       using policy_t =
433           Kokkos::TeamPolicy<Kokkos::Schedule<Kokkos::Dynamic>, ExecutionSpace,
434                              Kokkos::IndexType<long>, SomeTag>;
435       using execution_space = typename policy_t::execution_space;
436       using index_type      = typename policy_t::index_type;
437       using schedule_type   = typename policy_t::schedule_type;
438       using work_tag        = typename policy_t::work_tag;
439 
440       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
441       ASSERT_TRUE((std::is_same<index_type, long>::value));
442       ASSERT_TRUE((std::is_same<schedule_type,
443                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
444       ASSERT_TRUE((std::is_same<work_tag, SomeTag>::value));
445     }
446 
447     {
448       using policy_t =
449           Kokkos::TeamPolicy<SomeTag, Kokkos::Schedule<Kokkos::Dynamic>,
450                              Kokkos::IndexType<long>, ExecutionSpace>;
451       using execution_space = typename policy_t::execution_space;
452       using index_type      = typename policy_t::index_type;
453       using schedule_type   = typename policy_t::schedule_type;
454       using work_tag        = typename policy_t::work_tag;
455 
456       ASSERT_TRUE((std::is_same<execution_space, ExecutionSpace>::value));
457       ASSERT_TRUE((std::is_same<index_type, long>::value));
458       ASSERT_TRUE((std::is_same<schedule_type,
459                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
460       ASSERT_TRUE((std::is_same<work_tag, SomeTag>::value));
461     }
462 
463     {
464       using policy_t = Kokkos::TeamPolicy<Kokkos::Schedule<Kokkos::Dynamic>>;
465       using execution_space = typename policy_t::execution_space;
466       using index_type      = typename policy_t::index_type;
467       using schedule_type   = typename policy_t::schedule_type;
468       using work_tag        = typename policy_t::work_tag;
469 
470       ASSERT_TRUE((
471           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
472       ASSERT_TRUE((std::is_same<index_type,
473                                 typename execution_space::size_type>::value));
474       ASSERT_TRUE((std::is_same<schedule_type,
475                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
476       ASSERT_TRUE((std::is_same<work_tag, void>::value));
477     }
478 
479     {
480       using policy_t = Kokkos::TeamPolicy<Kokkos::Schedule<Kokkos::Dynamic>,
481                                           Kokkos::IndexType<long>>;
482       using execution_space = typename policy_t::execution_space;
483       using index_type      = typename policy_t::index_type;
484       using schedule_type   = typename policy_t::schedule_type;
485       using work_tag        = typename policy_t::work_tag;
486 
487       ASSERT_TRUE((
488           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
489       ASSERT_TRUE((std::is_same<index_type, long>::value));
490       ASSERT_TRUE((std::is_same<schedule_type,
491                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
492       ASSERT_TRUE((std::is_same<work_tag, void>::value));
493     }
494 
495     {
496       using policy_t        = Kokkos::TeamPolicy<Kokkos::IndexType<long>,
497                                           Kokkos::Schedule<Kokkos::Dynamic>>;
498       using execution_space = typename policy_t::execution_space;
499       using index_type      = typename policy_t::index_type;
500       using schedule_type   = typename policy_t::schedule_type;
501       using work_tag        = typename policy_t::work_tag;
502 
503       ASSERT_TRUE((
504           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
505       ASSERT_TRUE((std::is_same<index_type, long>::value));
506       ASSERT_TRUE((std::is_same<schedule_type,
507                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
508       ASSERT_TRUE((std::is_same<work_tag, void>::value));
509     }
510 
511     {
512       using policy_t = Kokkos::TeamPolicy<Kokkos::Schedule<Kokkos::Dynamic>,
513                                           Kokkos::IndexType<long>, SomeTag>;
514       using execution_space = typename policy_t::execution_space;
515       using index_type      = typename policy_t::index_type;
516       using schedule_type   = typename policy_t::schedule_type;
517       using work_tag        = typename policy_t::work_tag;
518 
519       ASSERT_TRUE((
520           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
521       ASSERT_TRUE((std::is_same<index_type, long>::value));
522       ASSERT_TRUE((std::is_same<schedule_type,
523                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
524       ASSERT_TRUE((std::is_same<work_tag, SomeTag>::value));
525     }
526 
527     {
528       using policy_t = Kokkos::TeamPolicy<Kokkos::Schedule<Kokkos::Dynamic>,
529                                           Kokkos::IndexType<long>, SomeTag>;
530       using execution_space = typename policy_t::execution_space;
531       using index_type      = typename policy_t::index_type;
532       using schedule_type   = typename policy_t::schedule_type;
533       using work_tag        = typename policy_t::work_tag;
534 
535       ASSERT_TRUE((
536           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
537       ASSERT_TRUE((std::is_same<index_type, long>::value));
538       ASSERT_TRUE((std::is_same<schedule_type,
539                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
540       ASSERT_TRUE((std::is_same<work_tag, SomeTag>::value));
541     }
542 
543     {
544       using policy_t =
545           Kokkos::TeamPolicy<SomeTag, Kokkos::Schedule<Kokkos::Dynamic>,
546                              Kokkos::IndexType<long>>;
547       using execution_space = typename policy_t::execution_space;
548       using index_type      = typename policy_t::index_type;
549       using schedule_type   = typename policy_t::schedule_type;
550       using work_tag        = typename policy_t::work_tag;
551 
552       ASSERT_TRUE((
553           std::is_same<execution_space, Kokkos::DefaultExecutionSpace>::value));
554       ASSERT_TRUE((std::is_same<index_type, long>::value));
555       ASSERT_TRUE((std::is_same<schedule_type,
556                                 Kokkos::Schedule<Kokkos::Dynamic>>::value));
557       ASSERT_TRUE((std::is_same<work_tag, SomeTag>::value));
558     }
559   }
560 
561   template <class policy_t>
test_run_time_parameters_type()562   void test_run_time_parameters_type() {
563     int league_size = 131;
564     int team_size   = 4 < policy_t::execution_space::concurrency()
565                         ? 4
566                         : policy_t::execution_space::concurrency();
567 #ifdef KOKKOS_ENABLE_HPX
568     team_size = 1;
569 #endif
570 #ifdef KOKKOS_ENABLE_OPENMPTARGET
571     if (std::is_same<typename policy_t::execution_space,
572                      Kokkos::Experimental::OpenMPTarget>::value)
573       team_size = 32;
574 #endif
575     int chunk_size         = 4;
576     int per_team_scratch   = 1024;
577     int per_thread_scratch = 16;
578     int scratch_size       = per_team_scratch + per_thread_scratch * team_size;
579 
580     policy_t p1(league_size, team_size);
581     ASSERT_EQ(p1.league_size(), league_size);
582     ASSERT_EQ(p1.team_size(), team_size);
583 // FIXME_SYCL implement chunk_size
584 #ifndef KOKKOS_ENABLE_SYCL
585     ASSERT_TRUE(p1.chunk_size() > 0);
586 #endif
587     ASSERT_EQ(p1.scratch_size(0), 0);
588 
589     policy_t p2 = p1.set_chunk_size(chunk_size);
590     ASSERT_EQ(p1.league_size(), league_size);
591     ASSERT_EQ(p1.team_size(), team_size);
592     ASSERT_EQ(p1.chunk_size(), chunk_size);
593     ASSERT_EQ(p1.scratch_size(0), 0);
594 
595     ASSERT_EQ(p2.league_size(), league_size);
596     ASSERT_EQ(p2.team_size(), team_size);
597     ASSERT_EQ(p2.chunk_size(), chunk_size);
598     ASSERT_EQ(p2.scratch_size(0), 0);
599 
600     policy_t p3 = p2.set_scratch_size(0, Kokkos::PerTeam(per_team_scratch));
601     ASSERT_EQ(p2.league_size(), league_size);
602     ASSERT_EQ(p2.team_size(), team_size);
603     ASSERT_EQ(p2.chunk_size(), chunk_size);
604     ASSERT_EQ(p2.scratch_size(0), per_team_scratch);
605     ASSERT_EQ(p3.league_size(), league_size);
606     ASSERT_EQ(p3.team_size(), team_size);
607     ASSERT_EQ(p3.chunk_size(), chunk_size);
608     ASSERT_EQ(p3.scratch_size(0), per_team_scratch);
609 
610     policy_t p4 = p2.set_scratch_size(0, Kokkos::PerThread(per_thread_scratch));
611     ASSERT_EQ(p2.league_size(), league_size);
612     ASSERT_EQ(p2.team_size(), team_size);
613     ASSERT_EQ(p2.chunk_size(), chunk_size);
614     ASSERT_EQ(p2.scratch_size(0), scratch_size);
615     ASSERT_EQ(p4.league_size(), league_size);
616     ASSERT_EQ(p4.team_size(), team_size);
617     ASSERT_EQ(p4.chunk_size(), chunk_size);
618     ASSERT_EQ(p4.scratch_size(0), scratch_size);
619 
620     policy_t p5 = p2.set_scratch_size(0, Kokkos::PerThread(per_thread_scratch),
621                                       Kokkos::PerTeam(per_team_scratch));
622     ASSERT_EQ(p2.league_size(), league_size);
623     ASSERT_EQ(p2.team_size(), team_size);
624     ASSERT_EQ(p2.chunk_size(), chunk_size);
625     ASSERT_EQ(p2.scratch_size(0), scratch_size);
626     ASSERT_EQ(p5.league_size(), league_size);
627     ASSERT_EQ(p5.team_size(), team_size);
628     ASSERT_EQ(p5.chunk_size(), chunk_size);
629     ASSERT_EQ(p5.scratch_size(0), scratch_size);
630 
631     policy_t p6 = p2.set_scratch_size(0, Kokkos::PerTeam(per_team_scratch),
632                                       Kokkos::PerThread(per_thread_scratch));
633     ASSERT_EQ(p2.league_size(), league_size);
634     ASSERT_EQ(p2.team_size(), team_size);
635     ASSERT_EQ(p2.chunk_size(), chunk_size);
636     ASSERT_EQ(p2.scratch_size(0), scratch_size);
637     ASSERT_EQ(p6.league_size(), league_size);
638     ASSERT_EQ(p6.team_size(), team_size);
639     ASSERT_EQ(p6.chunk_size(), chunk_size);
640     ASSERT_EQ(p6.scratch_size(0), scratch_size);
641 
642     policy_t p7 = p3.set_scratch_size(0, Kokkos::PerTeam(per_team_scratch),
643                                       Kokkos::PerThread(per_thread_scratch));
644     ASSERT_EQ(p3.league_size(), league_size);
645     ASSERT_EQ(p3.team_size(), team_size);
646     ASSERT_EQ(p3.chunk_size(), chunk_size);
647     ASSERT_EQ(p3.scratch_size(0), scratch_size);
648     ASSERT_EQ(p7.league_size(), league_size);
649     ASSERT_EQ(p7.team_size(), team_size);
650     ASSERT_EQ(p7.chunk_size(), chunk_size);
651     ASSERT_EQ(p7.scratch_size(0), scratch_size);
652 
653     policy_t p8;  // default constructed
654     ASSERT_EQ(p8.league_size(), 0);
655     ASSERT_EQ(p8.scratch_size(0), 0);
656     p8 = p3;  // call assignment operator
657     ASSERT_EQ(p3.league_size(), league_size);
658     ASSERT_EQ(p3.team_size(), team_size);
659     ASSERT_EQ(p3.chunk_size(), chunk_size);
660     ASSERT_EQ(p3.scratch_size(0), scratch_size);
661     ASSERT_EQ(p8.league_size(), league_size);
662     ASSERT_EQ(p8.team_size(), team_size);
663     ASSERT_EQ(p8.chunk_size(), chunk_size);
664     ASSERT_EQ(p8.scratch_size(0), scratch_size);
665   }
666 
test_run_time_parameters()667   void test_run_time_parameters() {
668     test_run_time_parameters_type<Kokkos::TeamPolicy<ExecutionSpace>>();
669     test_run_time_parameters_type<
670         Kokkos::TeamPolicy<ExecutionSpace, Kokkos::Schedule<Kokkos::Dynamic>,
671                            Kokkos::IndexType<long>>>();
672     test_run_time_parameters_type<
673         Kokkos::TeamPolicy<Kokkos::IndexType<long>, ExecutionSpace,
674                            Kokkos::Schedule<Kokkos::Dynamic>>>();
675     test_run_time_parameters_type<
676         Kokkos::TeamPolicy<Kokkos::Schedule<Kokkos::Dynamic>,
677                            Kokkos::IndexType<long>, ExecutionSpace, SomeTag>>();
678   }
679 };
680 
681 // semiregular is copyable and default initializable
682 // (regular requires equality comparable)
683 template <class Policy>
check_semiregular()684 void check_semiregular() {
685   static_assert(std::is_default_constructible<Policy>::value, "");
686   static_assert(std::is_copy_constructible<Policy>::value, "");
687   static_assert(std::is_move_constructible<Policy>::value, "");
688   static_assert(std::is_copy_assignable<Policy>::value, "");
689   static_assert(std::is_move_assignable<Policy>::value, "");
690   static_assert(std::is_destructible<Policy>::value, "");
691 }
692 
TEST(TEST_CATEGORY,policy_construction)693 TEST(TEST_CATEGORY, policy_construction) {
694   check_semiregular<Kokkos::RangePolicy<TEST_EXECSPACE>>();
695   check_semiregular<Kokkos::TeamPolicy<TEST_EXECSPACE>>();
696   check_semiregular<Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>>>();
697 
698   TestRangePolicyConstruction<TEST_EXECSPACE>();
699   TestTeamPolicyConstruction<TEST_EXECSPACE>();
700 }
701 
702 template <template <class...> class Policy, class... Args>
check_converting_constructor_add_work_tag(Policy<Args...> const & policy)703 void check_converting_constructor_add_work_tag(Policy<Args...> const& policy) {
704   // Not the greatest but at least checking it compiles
705   struct WorkTag {};
706   Policy<Args..., WorkTag> policy_with_tag = policy;
707   (void)policy_with_tag;
708 }
709 
TEST(TEST_CATEGORY,policy_converting_constructor_from_other_policy)710 TEST(TEST_CATEGORY, policy_converting_constructor_from_other_policy) {
711   check_converting_constructor_add_work_tag(
712       Kokkos::RangePolicy<TEST_EXECSPACE>{});
713   check_converting_constructor_add_work_tag(
714       Kokkos::TeamPolicy<TEST_EXECSPACE>{});
715   check_converting_constructor_add_work_tag(
716       Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>>{});
717 }
718 
719 #ifndef KOKKOS_ENABLE_OPENMPTARGET  // FIXME_OPENMPTARGET
TEST(TEST_CATEGORY_DEATH,policy_bounds_unsafe_narrowing_conversions)720 TEST(TEST_CATEGORY_DEATH, policy_bounds_unsafe_narrowing_conversions) {
721   using Policy = Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>,
722                                        Kokkos::IndexType<unsigned>>;
723 
724   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
725   ASSERT_DEATH(
726       {
727         (void)Policy({-1, 0}, {2, 3});
728       },
729       "unsafe narrowing conversion");
730 }
731 #endif
732 
733 template <class Policy>
test_prefer_desired_occupancy(Policy const & policy)734 void test_prefer_desired_occupancy(Policy const& policy) {
735   static_assert(!Policy::experimental_contains_desired_occupancy, "");
736 
737   // MaximizeOccupancy -> MaximizeOccupancy
738   auto const policy_still_no_occ = Kokkos::Experimental::prefer(
739       policy, Kokkos::Experimental::MaximizeOccupancy{});
740   static_assert(
741       !decltype(policy_still_no_occ)::experimental_contains_desired_occupancy,
742       "");
743 
744   // MaximizeOccupancy -> DesiredOccupancy
745   auto const policy_with_occ = Kokkos::Experimental::prefer(
746       policy, Kokkos::Experimental::DesiredOccupancy{33});
747   static_assert(
748       decltype(policy_with_occ)::experimental_contains_desired_occupancy, "");
749   EXPECT_EQ(policy_with_occ.impl_get_desired_occupancy().value(), 33);
750 
751   // DesiredOccupancy -> DesiredOccupancy
752   auto const policy_change_occ = Kokkos::Experimental::prefer(
753       policy_with_occ, Kokkos::Experimental::DesiredOccupancy{24});
754   static_assert(
755       decltype(policy_change_occ)::experimental_contains_desired_occupancy, "");
756   EXPECT_EQ(policy_change_occ.impl_get_desired_occupancy().value(), 24);
757 
758   // DesiredOccupancy -> MaximizeOccupancy
759   auto const policy_drop_occ = Kokkos::Experimental::prefer(
760       policy_with_occ, Kokkos::Experimental::MaximizeOccupancy{});
761   static_assert(
762       !decltype(policy_drop_occ)::experimental_contains_desired_occupancy, "");
763 }
764 
765 template <class... Args>
766 struct DummyPolicy : Kokkos::Impl::PolicyTraits<Args...> {
767   using execution_policy = DummyPolicy;
768 
769   using base_t = Kokkos::Impl::PolicyTraits<Args...>;
770   using base_t::base_t;
771 };
772 
TEST(TEST_CATEGORY,desired_occupancy_prefer)773 TEST(TEST_CATEGORY, desired_occupancy_prefer) {
774   test_prefer_desired_occupancy(DummyPolicy<TEST_EXECSPACE>{});
775   test_prefer_desired_occupancy(Kokkos::RangePolicy<TEST_EXECSPACE>{});
776   test_prefer_desired_occupancy(
777       Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>>{});
778   test_prefer_desired_occupancy(Kokkos::TeamPolicy<TEST_EXECSPACE>{});
779 }
780 
781 // For a more informative static assertion:
782 template <size_t>
783 struct static_assert_dummy_policy_must_be_size_one;
784 template <>
785 struct static_assert_dummy_policy_must_be_size_one<1> {};
786 template <size_t, size_t>
787 struct static_assert_dummy_policy_must_be_size_of_desired_occupancy;
788 template <>
789 struct static_assert_dummy_policy_must_be_size_of_desired_occupancy<
790     sizeof(Kokkos::Experimental::DesiredOccupancy),
791     sizeof(Kokkos::Experimental::DesiredOccupancy)> {};
792 
TEST(TEST_CATEGORY,desired_occupancy_empty_base_optimization)793 TEST(TEST_CATEGORY, desired_occupancy_empty_base_optimization) {
794   DummyPolicy<TEST_EXECSPACE> const policy{};
795   static_assert(sizeof(decltype(policy)) == 1, "");
796   static_assert_dummy_policy_must_be_size_one<sizeof(decltype(policy))>
797       _assert1{};
798   (void)_assert1;  // avoid unused variable warning
799 
800   using Kokkos::Experimental::DesiredOccupancy;
801   auto policy_with_occ =
802       Kokkos::Experimental::prefer(policy, DesiredOccupancy{50});
803   static_assert(sizeof(decltype(policy_with_occ)) == sizeof(DesiredOccupancy),
804                 "");
805   static_assert_dummy_policy_must_be_size_of_desired_occupancy<
806       sizeof(decltype(policy_with_occ)), sizeof(DesiredOccupancy)>
807       _assert2{};
808   (void)_assert2;  // avoid unused variable warning
809 }
810 
811 template <typename Policy>
test_desired_occupancy_converting_constructors(Policy const & policy)812 void test_desired_occupancy_converting_constructors(Policy const& policy) {
813   auto policy_with_occ = Kokkos::Experimental::prefer(
814       policy, Kokkos::Experimental::DesiredOccupancy{50});
815   EXPECT_EQ(policy_with_occ.impl_get_desired_occupancy().value(), 50);
816 
817   auto policy_with_hint = Kokkos::Experimental::require(
818       policy_with_occ, Kokkos::Experimental::WorkItemProperty::HintLightWeight);
819   EXPECT_EQ(policy_with_hint.impl_get_desired_occupancy().value(), 50);
820 }
821 
TEST(TEST_CATEGORY,desired_occupancy_converting_constructors)822 TEST(TEST_CATEGORY, desired_occupancy_converting_constructors) {
823   test_desired_occupancy_converting_constructors(
824       Kokkos::RangePolicy<TEST_EXECSPACE>{});
825   test_desired_occupancy_converting_constructors(
826       Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>>{});
827   test_desired_occupancy_converting_constructors(
828       Kokkos::TeamPolicy<TEST_EXECSPACE>{});
829 }
830 
831 template <class T>
more_md_range_policy_construction_test()832 void more_md_range_policy_construction_test() {
833   (void)Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>>{
834       Kokkos::Array<T, 2>{}, Kokkos::Array<T, 2>{}};
835 
836   (void)Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>>{{{T(0), T(0)}},
837                                                                {{T(2), T(2)}}};
838 
839   (void)Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>>{{T(0), T(0)},
840                                                                {T(2), T(2)}};
841 }
842 
TEST(TEST_CATEGORY,md_range_policy_construction_from_arrays)843 TEST(TEST_CATEGORY, md_range_policy_construction_from_arrays) {
844   {
845     // Check that construction from Kokkos::Array of long compiles for backwards
846     // compability.  This was broken in
847     // https://github.com/kokkos/kokkos/pull/3527/commits/88ea8eec6567c84739d77bdd25fdbc647fae28bb#r512323639
848     Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>> p1(
849         Kokkos::Array<long, 2>{{0, 1}}, Kokkos::Array<long, 2>{{2, 3}});
850     Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>> p2(
851         Kokkos::Array<long, 2>{{0, 1}}, Kokkos::Array<long, 2>{{2, 3}});
852     Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>> p3(
853         Kokkos::Array<long, 2>{{0, 1}}, Kokkos::Array<long, 2>{{2, 3}},
854         Kokkos::Array<long, 1>{{4}});
855   }
856   {
857     // Check that construction from Kokkos::Array of the specified index type
858     // works.
859     using index_type = unsigned long long;
860     Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>,
861                           Kokkos::IndexType<index_type>>
862         p1(Kokkos::Array<index_type, 2>{{0, 1}},
863            Kokkos::Array<index_type, 2>{{2, 3}});
864     Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>,
865                           Kokkos::IndexType<index_type>>
866         p2(Kokkos::Array<index_type, 2>{{0, 1}},
867            Kokkos::Array<index_type, 2>{{2, 3}});
868     Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>,
869                           Kokkos::IndexType<index_type>>
870         p3(Kokkos::Array<index_type, 2>{{0, 1}},
871            Kokkos::Array<index_type, 2>{{2, 3}},
872            Kokkos::Array<index_type, 1>{{4}});
873   }
874   {
875     // Check that construction from double-braced initliazer list
876     // works.
877     using index_type = unsigned long long;
878     Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>> p1({{0, 1}},
879                                                               {{2, 3}});
880     Kokkos::MDRangePolicy<TEST_EXECSPACE, Kokkos::Rank<2>,
881                           Kokkos::IndexType<index_type>>
882         p2({{0, 1}}, {{2, 3}});
883   }
884 
885   more_md_range_policy_construction_test<char>();
886   more_md_range_policy_construction_test<int>();
887   more_md_range_policy_construction_test<unsigned long>();
888   more_md_range_policy_construction_test<std::int64_t>();
889 }
890 
891 template <class WorkTag, class Policy>
set_worktag(Policy const & policy)892 constexpr auto set_worktag(Policy const& policy) {
893   static_assert(Kokkos::is_execution_policy<Policy>::value, "");
894   using PolicyWithWorkTag =
895       Kokkos::Impl::WorkTagTrait::policy_with_trait<Policy, WorkTag>;
896   return PolicyWithWorkTag{policy};
897 }
898 
TEST(TEST_CATEGORY,policy_set_worktag)899 TEST(TEST_CATEGORY, policy_set_worktag) {
900   struct SomeWorkTag {};
901   struct OtherWorkTag {};
902 
903   Kokkos::RangePolicy<> p1;
904   static_assert(std::is_void<decltype(p1)::work_tag>::value, "");
905 
906   auto p2 = set_worktag<SomeWorkTag>(p1);
907   static_assert(std::is_same<decltype(p2)::work_tag, SomeWorkTag>::value, "");
908 
909   auto p3 = set_worktag<OtherWorkTag>(p2);
910   static_assert(std::is_same<decltype(p3)::work_tag, OtherWorkTag>::value, "");
911 
912   // NOTE this does not currently compile
913   // auto p4 = set_worktag<void>(p3);
914   // static_assert(std::is_void<decltype(p4)::work_tag>::value, "");
915 }
916 }  // namespace Test
917