/* //@HEADER // ************************************************************************ // // Kokkos v. 3.0 // Copyright (2020) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. Neither the name of the Corporation nor the names of the // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Questions? Contact Christian R. Trott (crtrott@sandia.gov) // // ************************************************************************ //@HEADER */ #include #include #include #include "Kokkos_NumericTraits.hpp" #include "Kokkos_ExecPolicy.hpp" struct extrema { #define DEFINE_EXTREMA(T, m, M) \ KOKKOS_FUNCTION static T min(T) { return m; } \ KOKKOS_FUNCTION static T max(T) { return M; } DEFINE_EXTREMA(char, CHAR_MIN, CHAR_MAX); DEFINE_EXTREMA(signed char, SCHAR_MIN, SCHAR_MAX); DEFINE_EXTREMA(unsigned char, 0, UCHAR_MAX); DEFINE_EXTREMA(short, SHRT_MIN, SHRT_MAX); DEFINE_EXTREMA(unsigned short, 0, USHRT_MAX); DEFINE_EXTREMA(int, INT_MIN, INT_MAX); DEFINE_EXTREMA(unsigned, 0U, UINT_MAX); DEFINE_EXTREMA(long, LONG_MIN, LONG_MAX); DEFINE_EXTREMA(unsigned long, 0UL, ULONG_MAX); DEFINE_EXTREMA(long long, LLONG_MIN, LLONG_MAX); DEFINE_EXTREMA(unsigned long long, 0ULL, ULLONG_MAX); DEFINE_EXTREMA(float, -FLT_MAX, FLT_MAX); DEFINE_EXTREMA(double, -DBL_MAX, DBL_MAX); DEFINE_EXTREMA(long double, -LDBL_MAX, LDBL_MAX); #undef DEFINE_EXTREMA }; // clang-format off struct Infinity { template using trait = Kokkos::Experimental::infinity; }; struct Epsilon { template using trait = Kokkos::Experimental::epsilon; }; struct FiniteMin { template using trait = Kokkos::Experimental::finite_min; }; struct FiniteMax { template using trait = Kokkos::Experimental::finite_max; }; struct RoundError { template using trait = Kokkos::Experimental::round_error; }; struct NormMin { template using trait = Kokkos::Experimental::norm_min; }; struct Digits { template using trait = Kokkos::Experimental::digits; }; struct Digits10 { template using trait = Kokkos::Experimental::digits10; }; struct MaxDigits10 { template using trait = Kokkos::Experimental::max_digits10; }; struct Radix { template using trait = Kokkos::Experimental::radix; }; struct MinExponent { template using trait = Kokkos::Experimental::min_exponent; }; struct MaxExponent { template using trait = Kokkos::Experimental::max_exponent; }; struct MinExponent10 { template using trait = Kokkos::Experimental::min_exponent10; }; struct MaxExponent10 { template using trait = Kokkos::Experimental::max_exponent10; }; // clang-format on template KOKKOS_FUNCTION T* take_address_of(T& arg) { return &arg; } template KOKKOS_FUNCTION void take_by_value(T) {} template struct TestNumericTraits { template using trait = typename Tag::template trait; Kokkos::View compare; TestNumericTraits() { compare = Kokkos::View("C"); run(); } void run() const { int errors = 0; Kokkos::parallel_reduce(Kokkos::RangePolicy(0, 1), *this, errors); ASSERT_EQ(errors, 0); (void)take_address_of(trait::value); // use on host } KOKKOS_FUNCTION void operator()(Infinity, int, int& e) const { using Kokkos::Experimental::infinity; auto const inf = infinity::value; auto const zero = T(0); e += (int)!(inf + inf == inf); e += (int)!(inf != zero); use_on_device(); } KOKKOS_FUNCTION void operator()(Epsilon, int, int& e) const { using Kokkos::Experimental::epsilon; auto const eps = epsilon::value; auto const one = T(1); // Avoid higher precision intermediate representation compare() = one + eps; e += (int)!(compare() != one); compare() = one + eps / 2; e += (int)!(compare() == one); use_on_device(); } KOKKOS_FUNCTION void operator()(FiniteMin, int, int& e) const { using Kokkos::Experimental::finite_max; using Kokkos::Experimental::finite_min; auto const min = finite_min::value; auto const max = finite_max::value; e += (int)!(min == extrema::min(T{})); e += (int)!(max == extrema::max(T{})); use_on_device(); } // clang-format off KOKKOS_FUNCTION void operator()(FiniteMax, int, int&) const { use_on_device(); } KOKKOS_FUNCTION void operator()(RoundError, int, int&) const { use_on_device(); } KOKKOS_FUNCTION void operator()(NormMin, int, int&) const { use_on_device(); } KOKKOS_FUNCTION void operator()(Digits, int, int&) const { use_on_device(); } KOKKOS_FUNCTION void operator()(Digits10, int, int&) const { use_on_device(); } KOKKOS_FUNCTION void operator()(MaxDigits10, int, int&) const { use_on_device(); } KOKKOS_FUNCTION void operator()(Radix, int, int&) const { use_on_device(); } KOKKOS_FUNCTION void operator()(MinExponent, int, int&) const { use_on_device(); } KOKKOS_FUNCTION void operator()(MaxExponent, int, int&) const { use_on_device(); } KOKKOS_FUNCTION void operator()(MinExponent10, int, int&) const { use_on_device(); } KOKKOS_FUNCTION void operator()(MaxExponent10, int, int&) const { use_on_device(); } // clang-format on KOKKOS_FUNCTION void use_on_device() const { #if defined(KOKKOS_COMPILER_NVCC) || defined(KOKKOS_ENABLE_OPENMPTARGET) take_by_value(trait::value); #else (void)take_address_of(trait::value); #endif } }; #if defined(KOKKOS_COMPILER_NVCC) || defined(KOKKOS_ENABLE_SYCL) || \ defined(KOKKOS_ENABLE_OPENMPTARGET) template struct TestNumericTraits< #if defined(KOKKOS_ENABLE_CUDA) Kokkos::Cuda, #elif defined(KOKKOS_ENABLE_SYCL) Kokkos::Experimental::SYCL, #else Kokkos::Experimental::OpenMPTarget, #endif long double, Tag> { template using trait = typename Tag::template trait; TestNumericTraits() { (void)take_address_of(trait::value); // Do nothing on the device. // According to the doc // https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#constexpr-variables // the traits member constant value cannot be directly used in device code. } }; #endif TEST(TEST_CATEGORY, numeric_traits_infinity) { TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); } TEST(TEST_CATEGORY, numeric_traits_epsilon) { TestNumericTraits(); TestNumericTraits(); #ifndef KOKKOS_COMPILER_IBM // fails with XL 16.1.1 TestNumericTraits(); #endif } TEST(TEST_CATEGORY, numeric_traits_round_error) { TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); } TEST(TEST_CATEGORY, numeric_traits_norm_min) { TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); } TEST(TEST_CATEGORY, numeric_traits_finite_min_max) { TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); } TEST(TEST_CATEGORY, numeric_traits_digits) { TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); } TEST(TEST_CATEGORY, numeric_traits_digits10) { TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); } TEST(TEST_CATEGORY, numeric_traits_max_digits10) { TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); } TEST(TEST_CATEGORY, numeric_traits_radix) { TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); } TEST(TEST_CATEGORY, numeric_traits_min_max_exponent) { TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); } TEST(TEST_CATEGORY, numeric_traits_min_max_exponent10) { TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); TestNumericTraits(); }