1 //@HEADER
2 // ************************************************************************
3 //
4 //                        Kokkos v. 3.0
5 //       Copyright (2020) National Technology & Engineering
6 //               Solutions of Sandia, LLC (NTESS).
7 //
8 // Under the terms of Contract DE-NA0003525 with NTESS,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Christian R. Trott (crtrott@sandia.gov)
39 //
40 // ************************************************************************
41 //@HEADER
42 
43 #ifndef KOKKOS_TEST_DUALVIEW_HPP
44 #define KOKKOS_TEST_DUALVIEW_HPP
45 
46 #include <gtest/gtest.h>
47 #include <iostream>
48 #include <cstdlib>
49 #include <cstdio>
50 #include <impl/Kokkos_Timer.hpp>
51 #include <Kokkos_Core.hpp>
52 #include <Kokkos_Random.hpp>
53 #include <cmath>
54 #include <chrono>
55 
56 namespace Test {
57 
58 namespace Impl {
59 
60 // This test runs the random number generators and uses some statistic tests to
61 // check the 'goodness' of the random numbers:
62 //    (i)   mean:         the mean is expected to be 0.5*RAND_MAX
63 //    (ii)  variance:     the variance is 1/3*mean*mean
64 //    (iii) covariance:   the covariance is 0
65 //    (iv)  1-tupledistr: the mean, variance and covariance of a 1D Histrogram
66 //    of random numbers (v)   3-tupledistr: the mean, variance and covariance of
67 //    a 3D Histrogram of random numbers
68 
69 #define HIST_DIM3D 24
70 #define HIST_DIM1D (HIST_DIM3D * HIST_DIM3D * HIST_DIM3D)
71 
72 struct RandomProperties {
73   uint64_t count;
74   double mean;
75   double variance;
76   double covariance;
77   double min;
78   double max;
79 
80   KOKKOS_INLINE_FUNCTION
RandomPropertiesTest::Impl::RandomProperties81   RandomProperties() {
82     count      = 0;
83     mean       = 0.0;
84     variance   = 0.0;
85     covariance = 0.0;
86     min        = 1e64;
87     max        = -1e64;
88   }
89 
90   KOKKOS_INLINE_FUNCTION
operator +=Test::Impl::RandomProperties91   RandomProperties& operator+=(const RandomProperties& add) {
92     count += add.count;
93     mean += add.mean;
94     variance += add.variance;
95     covariance += add.covariance;
96     min = add.min < min ? add.min : min;
97     max = add.max > max ? add.max : max;
98     return *this;
99   }
100 
101   KOKKOS_INLINE_FUNCTION
operator +=Test::Impl::RandomProperties102   void operator+=(const volatile RandomProperties& add) volatile {
103     count += add.count;
104     mean += add.mean;
105     variance += add.variance;
106     covariance += add.covariance;
107     min = add.min < min ? add.min : min;
108     max = add.max > max ? add.max : max;
109   }
110 };
111 
112 // FIXME_OPENMPTARGET: Need this for OpenMPTarget because contra to the standard
113 // llvm requires the binary operator defined not just the +=
114 KOKKOS_INLINE_FUNCTION
operator +(const RandomProperties & org,const RandomProperties & add)115 RandomProperties operator+(const RandomProperties& org,
116                            const RandomProperties& add) {
117   RandomProperties val = org;
118   val += add;
119   return val;
120 }
121 
122 template <class GeneratorPool, class Scalar>
123 struct test_random_functor {
124   using rnd_type = typename GeneratorPool::generator_type;
125 
126   using value_type  = RandomProperties;
127   using device_type = typename GeneratorPool::device_type;
128 
129   GeneratorPool rand_pool;
130   const double mean;
131 
132   // NOTE (mfh 03 Nov 2014): Kokkos::rand::max() is supposed to define
133   // an exclusive upper bound on the range of random numbers that
134   // draw() can generate.  However, for the float specialization, some
135   // implementations might violate this upper bound, due to rounding
136   // error.  Just in case, we leave an extra space at the end of each
137   // dimension, in the View types below.
138   using type_1d =
139       Kokkos::View<int[HIST_DIM1D + 1], typename GeneratorPool::device_type>;
140   type_1d density_1d;
141   using type_3d =
142       Kokkos::View<int[HIST_DIM3D + 1][HIST_DIM3D + 1][HIST_DIM3D + 1],
143                    typename GeneratorPool::device_type>;
144   type_3d density_3d;
145 
test_random_functorTest::Impl::test_random_functor146   test_random_functor(GeneratorPool rand_pool_, type_1d d1d, type_3d d3d)
147       : rand_pool(rand_pool_),
148         mean(0.5 * Kokkos::rand<rnd_type, Scalar>::max()),
149         density_1d(d1d),
150         density_3d(d3d) {}
151 
152   KOKKOS_INLINE_FUNCTION
operator ()Test::Impl::test_random_functor153   void operator()(int /*i*/, RandomProperties& prop) const {
154     using Kokkos::atomic_fetch_add;
155 
156     rnd_type rand_gen = rand_pool.get_state();
157     for (int k = 0; k < 1024; ++k) {
158       const Scalar tmp = Kokkos::rand<rnd_type, Scalar>::draw(rand_gen);
159       prop.count++;
160       prop.mean += tmp;
161       prop.variance += (tmp - mean) * (tmp - mean);
162       const Scalar tmp2 = Kokkos::rand<rnd_type, Scalar>::draw(rand_gen);
163       prop.count++;
164       prop.mean += tmp2;
165       prop.variance += (tmp2 - mean) * (tmp2 - mean);
166       prop.covariance += (tmp - mean) * (tmp2 - mean);
167       const Scalar tmp3 = Kokkos::rand<rnd_type, Scalar>::draw(rand_gen);
168       prop.count++;
169       prop.mean += tmp3;
170       prop.variance += (tmp3 - mean) * (tmp3 - mean);
171       prop.covariance += (tmp2 - mean) * (tmp3 - mean);
172 
173       // NOTE (mfh 03 Nov 2014): Kokkos::rand::max() is supposed to
174       // define an exclusive upper bound on the range of random
175       // numbers that draw() can generate.  However, for the float
176       // specialization, some implementations might violate this upper
177       // bound, due to rounding error.  Just in case, we have left an
178       // extra space at the end of each dimension of density_1d and
179       // density_3d.
180       //
181       // Please note that those extra entries might not get counted in
182       // the histograms.  However, if Kokkos::rand is broken and only
183       // returns values of max(), the histograms will still catch this
184       // indirectly, since none of the other values will be filled in.
185 
186       const Scalar theMax = Kokkos::rand<rnd_type, Scalar>::max();
187 
188       const uint64_t ind1_1d =
189           static_cast<uint64_t>(1.0 * HIST_DIM1D * tmp / theMax);
190       const uint64_t ind2_1d =
191           static_cast<uint64_t>(1.0 * HIST_DIM1D * tmp2 / theMax);
192       const uint64_t ind3_1d =
193           static_cast<uint64_t>(1.0 * HIST_DIM1D * tmp3 / theMax);
194 
195       const uint64_t ind1_3d =
196           static_cast<uint64_t>(1.0 * HIST_DIM3D * tmp / theMax);
197       const uint64_t ind2_3d =
198           static_cast<uint64_t>(1.0 * HIST_DIM3D * tmp2 / theMax);
199       const uint64_t ind3_3d =
200           static_cast<uint64_t>(1.0 * HIST_DIM3D * tmp3 / theMax);
201 
202       atomic_fetch_add(&density_1d(ind1_1d), 1);
203       atomic_fetch_add(&density_1d(ind2_1d), 1);
204       atomic_fetch_add(&density_1d(ind3_1d), 1);
205       atomic_fetch_add(&density_3d(ind1_3d, ind2_3d, ind3_3d), 1);
206     }
207     rand_pool.free_state(rand_gen);
208   }
209 };
210 
211 template <class DeviceType>
212 struct test_histogram1d_functor {
213   using value_type      = RandomProperties;
214   using execution_space = typename DeviceType::execution_space;
215   using memory_space    = typename DeviceType::memory_space;
216 
217   // NOTE (mfh 03 Nov 2014): Kokkos::rand::max() is supposed to define
218   // an exclusive upper bound on the range of random numbers that
219   // draw() can generate.  However, for the float specialization, some
220   // implementations might violate this upper bound, due to rounding
221   // error.  Just in case, we leave an extra space at the end of each
222   // dimension, in the View type below.
223   using type_1d = Kokkos::View<int[HIST_DIM1D + 1], memory_space>;
224   type_1d density_1d;
225   double mean;
226 
test_histogram1d_functorTest::Impl::test_histogram1d_functor227   test_histogram1d_functor(type_1d d1d, int num_draws)
228       : density_1d(d1d), mean(1.0 * num_draws / HIST_DIM1D * 3) {}
229 
operator ()Test::Impl::test_histogram1d_functor230   KOKKOS_INLINE_FUNCTION void operator()(
231       const typename memory_space::size_type i, RandomProperties& prop) const {
232     using size_type    = typename memory_space::size_type;
233     const double count = density_1d(i);
234     prop.mean += count;
235     prop.variance += 1.0 * (count - mean) * (count - mean);
236     // prop.covariance += 1.0*count*count;
237     prop.min = count < prop.min ? count : prop.min;
238     prop.max = count > prop.max ? count : prop.max;
239     if (i < static_cast<size_type>(HIST_DIM1D - 1)) {
240       prop.covariance += (count - mean) * (density_1d(i + 1) - mean);
241     }
242   }
243 };
244 
245 template <class DeviceType>
246 struct test_histogram3d_functor {
247   using value_type      = RandomProperties;
248   using execution_space = typename DeviceType::execution_space;
249   using memory_space    = typename DeviceType::memory_space;
250 
251   // NOTE (mfh 03 Nov 2014): Kokkos::rand::max() is supposed to define
252   // an exclusive upper bound on the range of random numbers that
253   // draw() can generate.  However, for the float specialization, some
254   // implementations might violate this upper bound, due to rounding
255   // error.  Just in case, we leave an extra space at the end of each
256   // dimension, in the View type below.
257   using type_3d =
258       Kokkos::View<int[HIST_DIM3D + 1][HIST_DIM3D + 1][HIST_DIM3D + 1],
259                    memory_space>;
260   type_3d density_3d;
261   double mean;
262 
test_histogram3d_functorTest::Impl::test_histogram3d_functor263   test_histogram3d_functor(type_3d d3d, int num_draws)
264       : density_3d(d3d), mean(1.0 * num_draws / HIST_DIM1D) {}
265 
operator ()Test::Impl::test_histogram3d_functor266   KOKKOS_INLINE_FUNCTION void operator()(
267       const typename memory_space::size_type i, RandomProperties& prop) const {
268     using size_type    = typename memory_space::size_type;
269     const double count = density_3d(
270         i / (HIST_DIM3D * HIST_DIM3D),
271         (i % (HIST_DIM3D * HIST_DIM3D)) / HIST_DIM3D, i % HIST_DIM3D);
272     prop.mean += count;
273     prop.variance += (count - mean) * (count - mean);
274     if (i < static_cast<size_type>(HIST_DIM1D - 1)) {
275       const double count_next =
276           density_3d((i + 1) / (HIST_DIM3D * HIST_DIM3D),
277                      ((i + 1) % (HIST_DIM3D * HIST_DIM3D)) / HIST_DIM3D,
278                      (i + 1) % HIST_DIM3D);
279       prop.covariance += (count - mean) * (count_next - mean);
280     }
281   }
282 };
283 
284 //
285 // Templated test that uses the above functors.
286 //
287 template <class RandomGenerator, class Scalar>
288 struct test_random_scalar {
289   using rnd_type = typename RandomGenerator::generator_type;
290 
291   int pass_mean, pass_var, pass_covar;
292   int pass_hist1d_mean, pass_hist1d_var, pass_hist1d_covar;
293   int pass_hist3d_mean, pass_hist3d_var, pass_hist3d_covar;
294 
test_random_scalarTest::Impl::test_random_scalar295   test_random_scalar(
296       typename test_random_functor<RandomGenerator, int>::type_1d& density_1d,
297       typename test_random_functor<RandomGenerator, int>::type_3d& density_3d,
298       RandomGenerator& pool, unsigned int num_draws) {
299     using Kokkos::parallel_reduce;
300     using std::cout;
301     using std::endl;
302 
303     {
304       cout << " -- Testing randomness properties" << endl;
305 
306       RandomProperties result;
307       using functor_type = test_random_functor<RandomGenerator, Scalar>;
308       parallel_reduce(num_draws / 1024,
309                       functor_type(pool, density_1d, density_3d), result);
310 
311       // printf("Result: %lf %lf
312       // %lf\n",result.mean/num_draws/3,result.variance/num_draws/3,result.covariance/num_draws/2);
313       double tolerance       = 1.6 * std::sqrt(1.0 / num_draws);
314       double mean_expect     = 0.5 * Kokkos::rand<rnd_type, Scalar>::max();
315       double variance_expect = 1.0 / 3.0 * mean_expect * mean_expect;
316       double mean_eps = mean_expect / (result.mean / num_draws / 3) - 1.0;
317       double variance_eps =
318           variance_expect / (result.variance / num_draws / 3) - 1.0;
319       double covariance_eps =
320           result.covariance / num_draws / 2 / variance_expect;
321       pass_mean = ((-tolerance < mean_eps) && (tolerance > mean_eps)) ? 1 : 0;
322       pass_var  = ((-1.5 * tolerance < variance_eps) &&
323                   (1.5 * tolerance > variance_eps))
324                      ? 1
325                      : 0;
326       pass_covar = ((-2.0 * tolerance < covariance_eps) &&
327                     (2.0 * tolerance > covariance_eps))
328                        ? 1
329                        : 0;
330       cout << "Pass: " << pass_mean << " " << pass_var << " " << mean_eps << " "
331            << variance_eps << " " << covariance_eps << " || " << tolerance
332            << endl;
333     }
334     {
335       cout << " -- Testing 1-D histogram" << endl;
336 
337       RandomProperties result;
338       using functor_type =
339           test_histogram1d_functor<typename RandomGenerator::device_type>;
340       parallel_reduce(HIST_DIM1D, functor_type(density_1d, num_draws), result);
341 
342       double tolerance   = 6 * std::sqrt(1.0 / HIST_DIM1D);
343       double mean_expect = 1.0 * num_draws * 3 / HIST_DIM1D;
344       double variance_expect =
345           1.0 * num_draws * 3 / HIST_DIM1D * (1.0 - 1.0 / HIST_DIM1D);
346       double covariance_expect = -1.0 * num_draws * 3 / HIST_DIM1D / HIST_DIM1D;
347       double mean_eps          = mean_expect / (result.mean / HIST_DIM1D) - 1.0;
348       double variance_eps =
349           variance_expect / (result.variance / HIST_DIM1D) - 1.0;
350       double covariance_eps =
351           (result.covariance / HIST_DIM1D - covariance_expect) / mean_expect;
352       pass_hist1d_mean = ((-0.0001 < mean_eps) && (0.0001 > mean_eps)) ? 1 : 0;
353       pass_hist1d_var =
354           ((-0.07 < variance_eps) && (0.07 > variance_eps)) ? 1 : 0;
355       pass_hist1d_covar =
356           ((-0.06 < covariance_eps) && (0.06 > covariance_eps)) ? 1 : 0;
357 
358       cout << "Density 1D: " << mean_eps << " " << variance_eps << " "
359            << (result.covariance / HIST_DIM1D / HIST_DIM1D) << " || "
360            << tolerance << " " << result.min << " " << result.max << " || "
361            << result.variance / HIST_DIM1D << " "
362            << 1.0 * num_draws * 3 / HIST_DIM1D * (1.0 - 1.0 / HIST_DIM1D)
363            << " || " << result.covariance / HIST_DIM1D << " "
364            << -1.0 * num_draws * 3 / HIST_DIM1D / HIST_DIM1D << endl;
365     }
366     {
367       cout << " -- Testing 3-D histogram" << endl;
368 
369       RandomProperties result;
370       using functor_type =
371           test_histogram3d_functor<typename RandomGenerator::device_type>;
372       parallel_reduce(HIST_DIM1D, functor_type(density_3d, num_draws), result);
373 
374       double tolerance   = 6 * std::sqrt(1.0 / HIST_DIM1D);
375       double mean_expect = 1.0 * num_draws / HIST_DIM1D;
376       double variance_expect =
377           1.0 * num_draws / HIST_DIM1D * (1.0 - 1.0 / HIST_DIM1D);
378       double covariance_expect = -1.0 * num_draws / HIST_DIM1D / HIST_DIM1D;
379       double mean_eps          = mean_expect / (result.mean / HIST_DIM1D) - 1.0;
380       double variance_eps =
381           variance_expect / (result.variance / HIST_DIM1D) - 1.0;
382       double covariance_eps =
383           (result.covariance / HIST_DIM1D - covariance_expect) / mean_expect;
384       pass_hist3d_mean =
385           ((-tolerance < mean_eps) && (tolerance > mean_eps)) ? 1 : 0;
386       pass_hist3d_var = ((-1.2 * tolerance < variance_eps) &&
387                          (1.2 * tolerance > variance_eps))
388                             ? 1
389                             : 0;
390       pass_hist3d_covar =
391           ((-tolerance < covariance_eps) && (tolerance > covariance_eps)) ? 1
392                                                                           : 0;
393 
394       cout << "Density 3D: " << mean_eps << " " << variance_eps << " "
395            << result.covariance / HIST_DIM1D / HIST_DIM1D << " || " << tolerance
396            << " " << result.min << " " << result.max << endl;
397     }
398   }
399 };
400 
401 template <class RandomGenerator>
test_random(unsigned int num_draws)402 void test_random(unsigned int num_draws) {
403   using std::cout;
404   using std::endl;
405   typename test_random_functor<RandomGenerator, int>::type_1d density_1d("D1d");
406   typename test_random_functor<RandomGenerator, int>::type_3d density_3d("D3d");
407 
408   uint64_t ticks =
409       std::chrono::high_resolution_clock::now().time_since_epoch().count();
410   cout << "Test Seed:" << ticks << endl;
411 
412   RandomGenerator pool(ticks);
413 
414   cout << "Test Scalar=int" << endl;
415   test_random_scalar<RandomGenerator, int> test_int(density_1d, density_3d,
416                                                     pool, num_draws);
417   ASSERT_EQ(test_int.pass_mean, 1);
418   ASSERT_EQ(test_int.pass_var, 1);
419   ASSERT_EQ(test_int.pass_covar, 1);
420   ASSERT_EQ(test_int.pass_hist1d_mean, 1);
421   ASSERT_EQ(test_int.pass_hist1d_var, 1);
422   ASSERT_EQ(test_int.pass_hist1d_covar, 1);
423   ASSERT_EQ(test_int.pass_hist3d_mean, 1);
424   ASSERT_EQ(test_int.pass_hist3d_var, 1);
425   ASSERT_EQ(test_int.pass_hist3d_covar, 1);
426   deep_copy(density_1d, 0);
427   deep_copy(density_3d, 0);
428 
429   cout << "Test Scalar=unsigned int" << endl;
430   test_random_scalar<RandomGenerator, unsigned int> test_uint(
431       density_1d, density_3d, pool, num_draws);
432   ASSERT_EQ(test_uint.pass_mean, 1);
433   ASSERT_EQ(test_uint.pass_var, 1);
434   ASSERT_EQ(test_uint.pass_covar, 1);
435   ASSERT_EQ(test_uint.pass_hist1d_mean, 1);
436   ASSERT_EQ(test_uint.pass_hist1d_var, 1);
437   ASSERT_EQ(test_uint.pass_hist1d_covar, 1);
438   ASSERT_EQ(test_uint.pass_hist3d_mean, 1);
439   ASSERT_EQ(test_uint.pass_hist3d_var, 1);
440   ASSERT_EQ(test_uint.pass_hist3d_covar, 1);
441   deep_copy(density_1d, 0);
442   deep_copy(density_3d, 0);
443 
444   cout << "Test Scalar=int64_t" << endl;
445   test_random_scalar<RandomGenerator, int64_t> test_int64(
446       density_1d, density_3d, pool, num_draws);
447   ASSERT_EQ(test_int64.pass_mean, 1);
448   ASSERT_EQ(test_int64.pass_var, 1);
449   ASSERT_EQ(test_int64.pass_covar, 1);
450   ASSERT_EQ(test_int64.pass_hist1d_mean, 1);
451   ASSERT_EQ(test_int64.pass_hist1d_var, 1);
452   ASSERT_EQ(test_int64.pass_hist1d_covar, 1);
453   ASSERT_EQ(test_int64.pass_hist3d_mean, 1);
454   ASSERT_EQ(test_int64.pass_hist3d_var, 1);
455   ASSERT_EQ(test_int64.pass_hist3d_covar, 1);
456   deep_copy(density_1d, 0);
457   deep_copy(density_3d, 0);
458 
459   cout << "Test Scalar=uint64_t" << endl;
460   test_random_scalar<RandomGenerator, uint64_t> test_uint64(
461       density_1d, density_3d, pool, num_draws);
462   ASSERT_EQ(test_uint64.pass_mean, 1);
463   ASSERT_EQ(test_uint64.pass_var, 1);
464   ASSERT_EQ(test_uint64.pass_covar, 1);
465   ASSERT_EQ(test_uint64.pass_hist1d_mean, 1);
466   ASSERT_EQ(test_uint64.pass_hist1d_var, 1);
467   ASSERT_EQ(test_uint64.pass_hist1d_covar, 1);
468   ASSERT_EQ(test_uint64.pass_hist3d_mean, 1);
469   ASSERT_EQ(test_uint64.pass_hist3d_var, 1);
470   ASSERT_EQ(test_uint64.pass_hist3d_covar, 1);
471   deep_copy(density_1d, 0);
472   deep_copy(density_3d, 0);
473 
474   cout << "Test Scalar=float" << endl;
475   test_random_scalar<RandomGenerator, float> test_float(density_1d, density_3d,
476                                                         pool, num_draws);
477   ASSERT_EQ(test_float.pass_mean, 1);
478   ASSERT_EQ(test_float.pass_var, 1);
479   ASSERT_EQ(test_float.pass_covar, 1);
480   ASSERT_EQ(test_float.pass_hist1d_mean, 1);
481   ASSERT_EQ(test_float.pass_hist1d_var, 1);
482   ASSERT_EQ(test_float.pass_hist1d_covar, 1);
483   ASSERT_EQ(test_float.pass_hist3d_mean, 1);
484   ASSERT_EQ(test_float.pass_hist3d_var, 1);
485   ASSERT_EQ(test_float.pass_hist3d_covar, 1);
486   deep_copy(density_1d, 0);
487   deep_copy(density_3d, 0);
488 
489   cout << "Test Scalar=double" << endl;
490   test_random_scalar<RandomGenerator, double> test_double(
491       density_1d, density_3d, pool, num_draws);
492   ASSERT_EQ(test_double.pass_mean, 1);
493   ASSERT_EQ(test_double.pass_var, 1);
494   ASSERT_EQ(test_double.pass_covar, 1);
495   ASSERT_EQ(test_double.pass_hist1d_mean, 1);
496   ASSERT_EQ(test_double.pass_hist1d_var, 1);
497   ASSERT_EQ(test_double.pass_hist1d_covar, 1);
498   ASSERT_EQ(test_double.pass_hist3d_mean, 1);
499   ASSERT_EQ(test_double.pass_hist3d_var, 1);
500   ASSERT_EQ(test_double.pass_hist3d_covar, 1);
501 }
502 }  // namespace Impl
503 
504 template <typename ExecutionSpace>
test_random_xorshift64()505 void test_random_xorshift64() {
506 #if defined(KOKKOS_ENABLE_SYCL) || defined(KOKKOS_ENABLE_CUDA) || \
507     defined(KOKKOS_ENABLE_HIP)
508   const int num_draws = 132141141;
509 #else  // SERIAL, HPX, OPENMP
510   const int num_draws = 10240000;
511 #endif
512   Impl::test_random<Kokkos::Random_XorShift64_Pool<ExecutionSpace>>(num_draws);
513   Impl::test_random<Kokkos::Random_XorShift64_Pool<
514       Kokkos::Device<ExecutionSpace, typename ExecutionSpace::memory_space>>>(
515       num_draws);
516 }
517 
518 template <typename ExecutionSpace>
test_random_xorshift1024()519 void test_random_xorshift1024() {
520 #if defined(KOKKOS_ENABLE_SYCL) || defined(KOKKOS_ENABLE_CUDA) || \
521     defined(KOKKOS_ENABLE_HIP)
522   const int num_draws = 52428813;
523 #else  // SERIAL, HPX, OPENMP
524   const int num_draws = 10130144;
525 #endif
526   Impl::test_random<Kokkos::Random_XorShift1024_Pool<ExecutionSpace>>(
527       num_draws);
528   Impl::test_random<Kokkos::Random_XorShift1024_Pool<
529       Kokkos::Device<ExecutionSpace, typename ExecutionSpace::memory_space>>>(
530       num_draws);
531 }
532 }  // namespace Test
533 
534 #endif  // KOKKOS_TEST_UNORDERED_MAP_HPP
535