diff --git a/config/ImathConfig.h.in b/config/ImathConfig.h.in index 132f6235..3bdf7043 100644 --- a/config/ImathConfig.h.in +++ b/config/ImathConfig.h.in @@ -107,6 +107,15 @@ # define IMATH_HOSTDEVICE #endif +// +// The namespace of C++ standard library +// +#ifdef __CUDACC__ +# define IMATH_STD_NAMESPACE cuda::std +#else +# define IMATH_STD_NAMESPACE std +#endif + // // Some compilers define a special intrinsic to use in conditionals that can // speed up extremely performance-critical spots if the conditional is diff --git a/src/Imath/ImathMath.h b/src/Imath/ImathMath.h index b3d2845a..12c31ce0 100644 --- a/src/Imath/ImathMath.h +++ b/src/Imath/ImathMath.h @@ -13,8 +13,13 @@ #include "ImathNamespace.h" #include "ImathPlatform.h" -#include -#include +#ifdef __CUDACC__ +# include +# include +#else +# include +# include +#endif IMATH_INTERNAL_NAMESPACE_HEADER_ENTER @@ -38,93 +43,93 @@ template struct Math { IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T acos (T x) { return std::acos (x); } + static T acos (T x) { return IMATH_STD_NAMESPACE::acos (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T asin (T x) { return std::asin (x); } + static T asin (T x) { return IMATH_STD_NAMESPACE::asin (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T atan (T x) { return std::atan (x); } + static T atan (T x) { return IMATH_STD_NAMESPACE::atan (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T atan2 (T x, T y) { return std::atan2 (x, y); } + static T atan2 (T x, T y) { return IMATH_STD_NAMESPACE::atan2 (x, y); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T cos (T x) { return std::cos (x); } + static T cos (T x) { return IMATH_STD_NAMESPACE::cos (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T sin (T x) { return std::sin (x); } + static T sin (T x) { return IMATH_STD_NAMESPACE::sin (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T tan (T x) { return std::tan (x); } + static T tan (T x) { return IMATH_STD_NAMESPACE::tan (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T cosh (T x) { return std::cosh (x); } + static T cosh (T x) { return IMATH_STD_NAMESPACE::cosh (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T sinh (T x) { return std::sinh (x); } + static T sinh (T x) { return IMATH_STD_NAMESPACE::sinh (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T tanh (T x) { return std::tanh (x); } + static T tanh (T x) { return IMATH_STD_NAMESPACE::tanh (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T exp (T x) { return std::exp (x); } + static T exp (T x) { return IMATH_STD_NAMESPACE::exp (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T log (T x) { return std::log (x); } + static T log (T x) { return IMATH_STD_NAMESPACE::log (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T log10 (T x) { return std::log10 (x); } + static T log10 (T x) { return IMATH_STD_NAMESPACE::log10 (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE static T modf (T x, T* iptr) { T ival; - T rval (std::modf (T (x), &ival)); + T rval (IMATH_STD_NAMESPACE::modf (T (x), &ival)); *iptr = ival; return rval; } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T pow (T x, T y) { return std::pow (x, y); } + static T pow (T x, T y) { return IMATH_STD_NAMESPACE::pow (x, y); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T sqrt (T x) { return std::sqrt (x); } + static T sqrt (T x) { return IMATH_STD_NAMESPACE::sqrt (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T ceil (T x) { return std::ceil (x); } + static T ceil (T x) { return IMATH_STD_NAMESPACE::ceil (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T fabs (T x) { return std::fabs (x); } + static T fabs (T x) { return IMATH_STD_NAMESPACE::fabs (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T floor (T x) { return std::floor (x); } + static T floor (T x) { return IMATH_STD_NAMESPACE::floor (x); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T fmod (T x, T y) { return std::fmod (x, y); } + static T fmod (T x, T y) { return IMATH_STD_NAMESPACE::fmod (x, y); } IMATH_DEPRECATED ("use std::math functions") IMATH_HOSTDEVICE - static T hypot (T x, T y) { return std::hypot (x, y); } + static T hypot (T x, T y) { return IMATH_STD_NAMESPACE::hypot (x, y); } }; /// @endcond @@ -134,10 +139,10 @@ template IMATH_HOSTDEVICE inline T sinx_over_x (T x) { - if (x * x < std::numeric_limits::epsilon ()) + if (x * x < IMATH_STD_NAMESPACE::numeric_limits::epsilon ()) return T (1); else - return std::sin (x) / x; + return IMATH_STD_NAMESPACE::sin (x) / x; } /// Compare two numbers and test if they are "approximately equal": diff --git a/src/Imath/ImathTypeTraits.h b/src/Imath/ImathTypeTraits.h index 60c85e1c..0d325c57 100644 --- a/src/Imath/ImathTypeTraits.h +++ b/src/Imath/ImathTypeTraits.h @@ -10,19 +10,23 @@ #ifndef INCLUDED_IMATHTYPETRAITS_H #define INCLUDED_IMATHTYPETRAITS_H -#include +#ifdef __CUDACC__ +# include +#else +# include +#endif #include "ImathPlatform.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER -/// Define Imath::enable_if_t to be std for C++14, equivalent for C++11. +/// Define Imath::enable_if_t to be IMATH_STD_NAMESPACE for C++14, equivalent for C++11. #if (IMATH_CPLUSPLUS_VERSION >= 14) -using std::enable_if_t; // Use C++14 std::enable_if_t +using IMATH_STD_NAMESPACE::enable_if_t; // Use C++14 IMATH_STD_NAMESPACE::enable_if_t #else // Define enable_if_t for C++11 template -using enable_if_t = typename std::enable_if::type; +using enable_if_t = typename IMATH_STD_NAMESPACE::enable_if::type; #endif /// An enable_if helper to be used in template parameters which results in @@ -63,14 +67,14 @@ using enable_if_t = typename std::enable_if::type; /// an Imath::V3f by subscripting: /// /// template<> -/// struct Imath::has_subscript : public std::true_type { }; +/// struct Imath::has_subscript : public IMATH_STD_NAMESPACE::true_type { }; /// /// And similarly, user code may correct a potential false positive (that /// is, a `mytype` looks like it should be convertible to a V3f, but you /// don't want it to ever happen): /// /// template -/// struct Imath::has_subscript : public std::false_type { }; +/// struct Imath::has_subscript : public IMATH_STD_NAMESPACE::false_type { }; /// /// `has_xy::value` will be true if type `T` has member variables @@ -85,8 +89,8 @@ template struct has_xy // Valid only if .x, .y exist and are the right type: return a Yes. template < typename C, - IMATH_ENABLE_IF (std::is_same::value), - IMATH_ENABLE_IF (std::is_same::value)> + IMATH_ENABLE_IF (IMATH_STD_NAMESPACE::is_same::value), + IMATH_ENABLE_IF (IMATH_STD_NAMESPACE::is_same::value)> static Yes& test (int); // Fallback, default to returning a No. @@ -113,9 +117,9 @@ template struct has_xyz // Valid only if .x, .y, .z exist and are the right type: return a Yes. template < typename C, - IMATH_ENABLE_IF (std::is_same::value), - IMATH_ENABLE_IF (std::is_same::value), - IMATH_ENABLE_IF (std::is_same::value)> + IMATH_ENABLE_IF (IMATH_STD_NAMESPACE::is_same::value), + IMATH_ENABLE_IF (IMATH_STD_NAMESPACE::is_same::value), + IMATH_ENABLE_IF (IMATH_STD_NAMESPACE::is_same::value)> static Yes& test (int); // Fallback, default to returning a No. @@ -142,10 +146,10 @@ template struct has_xyzw // Valid only if .x, .y, .z, .w exist and are the right type: return a Yes. template < typename C, - IMATH_ENABLE_IF (std::is_same::value), - IMATH_ENABLE_IF (std::is_same::value), - IMATH_ENABLE_IF (std::is_same::value), - IMATH_ENABLE_IF (std::is_same::value)> + IMATH_ENABLE_IF (IMATH_STD_NAMESPACE::is_same::value), + IMATH_ENABLE_IF (IMATH_STD_NAMESPACE::is_same::value), + IMATH_ENABLE_IF (IMATH_STD_NAMESPACE::is_same::value), + IMATH_ENABLE_IF (IMATH_STD_NAMESPACE::is_same::value)> static Yes& test (int); // Fallback, default to returning a No. @@ -172,8 +176,8 @@ template struct has_subscript // Valid only if T[] is possible and is the right type: return a Yes. template < typename C, - IMATH_ENABLE_IF (std::is_same< - typename std::decay::type, + IMATH_ENABLE_IF (IMATH_STD_NAMESPACE::is_same< + typename IMATH_STD_NAMESPACE::decay::type, Base>::value)> static Yes& test (int); @@ -191,7 +195,7 @@ template struct has_subscript /// C arrays of just the right length also are qualified for has_subscript. template -struct has_subscript : public std::true_type +struct has_subscript : public IMATH_STD_NAMESPACE::true_type {}; /// `has_double_subscript::value` will be true if type `T` @@ -207,8 +211,8 @@ struct has_double_subscript // Valid only if T[][] is possible and is the right type: return a Yes. template < typename C, - IMATH_ENABLE_IF (std::is_same< - typename std::decay::type, + IMATH_ENABLE_IF (IMATH_STD_NAMESPACE::is_same< + typename IMATH_STD_NAMESPACE::decay::type, Base>::value)> static Yes& test (int); @@ -227,7 +231,7 @@ struct has_double_subscript /// C arrays of just the right length also are qualified for has_double_subscript. template struct has_double_subscript - : public std::true_type + : public IMATH_STD_NAMESPACE::true_type {}; /// @} diff --git a/src/Imath/ImathVec.h b/src/Imath/ImathVec.h index 49d69256..6bfe7c71 100644 --- a/src/Imath/ImathVec.h +++ b/src/Imath/ImathVec.h @@ -17,8 +17,6 @@ #include "ImathMath.h" #include -#include -#include #include #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER @@ -27,6 +25,14 @@ # pragma warning(disable : 4290) #endif +#ifdef __CUDACC__ +# include +# include +#else +# include +# include +#endif + IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template class Vec2; @@ -299,25 +305,25 @@ template class IMATH_EXPORT_TEMPLATE_TYPE Vec2 /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest () IMATH_NOEXCEPT { - return std::numeric_limits::lowest (); + return IMATH_STD_NAMESPACE::numeric_limits::lowest (); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax () IMATH_NOEXCEPT { - return std::numeric_limits::max (); + return IMATH_STD_NAMESPACE::numeric_limits::max (); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest () IMATH_NOEXCEPT { - return std::numeric_limits::min (); + return IMATH_STD_NAMESPACE::numeric_limits::min (); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon () IMATH_NOEXCEPT { - return std::numeric_limits::epsilon (); + return IMATH_STD_NAMESPACE::numeric_limits::epsilon (); } /// @} @@ -620,25 +626,25 @@ template class IMATH_EXPORT_TEMPLATE_TYPE Vec3 /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest () IMATH_NOEXCEPT { - return std::numeric_limits::lowest (); + return IMATH_STD_NAMESPACE::numeric_limits::lowest (); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax () IMATH_NOEXCEPT { - return std::numeric_limits::max (); + return IMATH_STD_NAMESPACE::numeric_limits::max (); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest () IMATH_NOEXCEPT { - return std::numeric_limits::min (); + return IMATH_STD_NAMESPACE::numeric_limits::min (); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon () IMATH_NOEXCEPT { - return std::numeric_limits::epsilon (); + return IMATH_STD_NAMESPACE::numeric_limits::epsilon (); } /// @} @@ -896,25 +902,25 @@ template class IMATH_EXPORT_TEMPLATE_TYPE Vec4 /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest () IMATH_NOEXCEPT { - return std::numeric_limits::lowest (); + return IMATH_STD_NAMESPACE::numeric_limits::lowest (); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax () IMATH_NOEXCEPT { - return std::numeric_limits::max (); + return IMATH_STD_NAMESPACE::numeric_limits::max (); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest () IMATH_NOEXCEPT { - return std::numeric_limits::min (); + return IMATH_STD_NAMESPACE::numeric_limits::min (); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon () IMATH_NOEXCEPT { - return std::numeric_limits::epsilon (); + return IMATH_STD_NAMESPACE::numeric_limits::epsilon (); } /// @} @@ -1466,8 +1472,8 @@ template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T Vec2::lengthTiny () const IMATH_NOEXCEPT { - T absX = std::abs (x); - T absY = std::abs (y); + T absX = IMATH_STD_NAMESPACE::abs (x); + T absY = IMATH_STD_NAMESPACE::abs (y); T max = absX; @@ -1484,7 +1490,7 @@ Vec2::lengthTiny () const IMATH_NOEXCEPT absX /= max; absY /= max; - return max * std::sqrt (absX * absX + absY * absY); + return max * IMATH_STD_NAMESPACE::sqrt (absX * absX + absY * absY); } template @@ -1493,10 +1499,10 @@ Vec2::length () const IMATH_NOEXCEPT { T length2 = dot (*this); - if (IMATH_UNLIKELY (length2 < T (2) * std::numeric_limits::min ())) + if (IMATH_UNLIKELY (length2 < T (2) * IMATH_STD_NAMESPACE::numeric_limits::min ())) return lengthTiny (); - return std::sqrt (length2); + return IMATH_STD_NAMESPACE::sqrt (length2); } template @@ -1954,7 +1960,7 @@ Vec3::lengthTiny () const IMATH_NOEXCEPT absY /= max; absZ /= max; - return max * std::sqrt (absX * absX + absY * absY + absZ * absZ); + return max * IMATH_STD_NAMESPACE::sqrt (absX * absX + absY * absY + absZ * absZ); } template @@ -1963,10 +1969,10 @@ Vec3::length () const IMATH_NOEXCEPT { T length2 = dot (*this); - if (IMATH_UNLIKELY (length2 < T (2) * std::numeric_limits::min ())) + if (IMATH_UNLIKELY (length2 < T (2) * IMATH_STD_NAMESPACE::numeric_limits::min ())) return lengthTiny (); - return std::sqrt (length2); + return IMATH_STD_NAMESPACE::sqrt (length2); } template @@ -2339,7 +2345,7 @@ Vec4::lengthTiny () const IMATH_NOEXCEPT absW /= max; return max * - std::sqrt (absX * absX + absY * absY + absZ * absZ + absW * absW); + IMATH_STD_NAMESPACE::sqrt (absX * absX + absY * absY + absZ * absZ + absW * absW); } template @@ -2348,10 +2354,10 @@ Vec4::length () const IMATH_NOEXCEPT { T length2 = dot (*this); - if (IMATH_UNLIKELY (length2 < T (2) * std::numeric_limits::min ())) + if (IMATH_UNLIKELY (length2 < T (2) * IMATH_STD_NAMESPACE::numeric_limits::min ())) return lengthTiny (); - return std::sqrt (length2); + return IMATH_STD_NAMESPACE::sqrt (length2); } template diff --git a/src/ImathTest/CMakeLists.txt b/src/ImathTest/CMakeLists.txt index 58820316..92857ac0 100644 --- a/src/ImathTest/CMakeLists.txt +++ b/src/ImathTest/CMakeLists.txt @@ -11,6 +11,36 @@ if("${CMAKE_PROJECT_NAME}" STREQUAL "") find_package(Imath) endif() +set(EXTRA_LIBS Imath::Imath) + +find_package(CUDAToolkit 12) +if(CUDAToolkit_FOUND) + set(IMATH_CUDA_FOUND ON) + + # TODO investigate minimum CUDA architecture. + set(CMAKE_CUDA_ARCHITECTURES 75) + + enable_language(CUDA) + + add_library(ImathTestVecCuda + testVecCUDA.h + testVecCUDA.cu + ) + + # TODO investigate minimum CUDA C++ std. + target_compile_features(ImathTestVecCuda PRIVATE cuda_std_20) + + target_link_libraries(ImathTestVecCuda PRIVATE CUDA::cudart Imath::Imath) + + set_target_properties(ImathTestVecCuda PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + ) + + list(APPEND EXTRA_LIBS ImathTestVecCuda) +endif() + +configure_file(ImathTestConfig.h.in ImathTestConfig.h) + add_executable(ImathTest main.cpp testBox.cpp @@ -48,10 +78,15 @@ add_executable(ImathTest testNoInterop.cpp ) -target_link_libraries(ImathTest Imath::Imath) +target_include_directories(ImathTest + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) +target_link_libraries(ImathTest ${EXTRA_LIBS}) set_target_properties(ImathTest PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" - ) +) if(NOT "${CMAKE_PROJECT_NAME}" STREQUAL "ImathTest") @@ -84,7 +119,7 @@ function(DEFINE_IMATH_TESTS) endforeach() endfunction() -define_imath_tests( +set(TEST_CASES testToFloat testSize testArithmetic @@ -123,3 +158,8 @@ define_imath_tests( testNoInterop ) +if(CUDAToolkit_FOUND) + list(APPEND TEST_CASES testVecCUDA) +endif() + +define_imath_tests(${TEST_CASES}) diff --git a/src/ImathTest/ImathTestConfig.h.in b/src/ImathTest/ImathTestConfig.h.in new file mode 100644 index 00000000..288ad52f --- /dev/null +++ b/src/ImathTest/ImathTestConfig.h.in @@ -0,0 +1 @@ +#cmakedefine IMATH_CUDA_FOUND \ No newline at end of file diff --git a/src/ImathTest/main.cpp b/src/ImathTest/main.cpp index cc8ab569..c1114968 100644 --- a/src/ImathTest/main.cpp +++ b/src/ImathTest/main.cpp @@ -7,6 +7,8 @@ # undef NDEBUG #endif +#include "ImathTestConfig.h" + #include "testArithmetic.h" #include "testBitPatterns.h" #include "testBox.h" @@ -41,6 +43,10 @@ #include "testToFloat.h" #include "testVec.h" +#ifdef IMATH_CUDA_FOUND +# include "testVecCUDA.h" +#endif + #include #include @@ -88,6 +94,13 @@ main (int argc, char* argv[]) TEST (testFrustumTest); TEST (testInterop); TEST (testNoInterop); + +#ifdef IMATH_CUDA_FOUND + std::cout << "Testing some basic vector operations in CUDA" << std::endl; + TEST (testVecCUDA); + std::cout << "ok\n" << std::endl; +#endif + // NB: If you add a test here, make sure to enumerate it in the // CMakeLists.txt so it runs as part of the test suite diff --git a/src/ImathTest/testVecCUDA.cu b/src/ImathTest/testVecCUDA.cu new file mode 100644 index 00000000..e09eb05a --- /dev/null +++ b/src/ImathTest/testVecCUDA.cu @@ -0,0 +1,265 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// Copyright Contributors to the OpenEXR Project. +// + +#ifdef NDEBUG +# undef NDEBUG +#endif + +#include "testVecCUDA.h" +#include +#include +#include +#include + +// Include ImathForward *after* other headers to validate forward declarations +#include + +using namespace cuda::std; +using namespace IMATH_INTERNAL_NAMESPACE; + +namespace +{ + +template +void +testLength2T () +{ + const T s = sqrt (numeric_limits::min ()); + const T e = 4 * numeric_limits::epsilon (); + + Vec2 v; + + v = Vec2 (0, 0); + assert (v.length () == 0); + assert (v.normalized ().length () == 0); + + v = Vec2 (3, 4); + assert (v.length () == 5); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + v = Vec2 (3000, 4000); + assert (v.length () == 5000); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + T t = s * (1 << 4); + + v = Vec2 (t, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec2 (0, t); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec2 (-t, -t); + assert (IMATH_INTERNAL_NAMESPACE::equal ( + v.length (), t * sqrt (2), t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + t = s / (1 << 4); + + v = Vec2 (t, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec2 (0, t); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec2 (-t, -t); + assert (IMATH_INTERNAL_NAMESPACE::equal ( + v.length (), t * sqrt (2), t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + t = s / (1 << 20); + + v = Vec2 (t, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec2 (0, t); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec2 (-t, -t); + assert (IMATH_INTERNAL_NAMESPACE::equal ( + v.length (), t * sqrt (2), t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); +} + +template +void +testLength3T () +{ + const T s = sqrt (numeric_limits::min ()); + const T e = 4 * numeric_limits::epsilon (); + + Vec3 v; + + v = Vec3 (0, 0, 0); + assert (v.length () == 0); + assert (v.normalized ().length () == 0); + + v = Vec3 (3, 4, 0); + assert (v.length () == 5); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + v = Vec3 (3000, 4000, 0); + assert (v.length () == 5000); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + v = Vec3 (1, -1, 1); + assert ( + IMATH_INTERNAL_NAMESPACE::equal (v.length (), 1 * sqrt (3), e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + v = Vec3 (1000, -1000, 1000); + assert (IMATH_INTERNAL_NAMESPACE::equal ( + v.length (), 1000 * sqrt (3), 1000 * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + T t = s * (1 << 4); + + v = Vec3 (t, 0, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec3 (0, t, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec3 (0, 0, t); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec3 (-t, -t, -t); + assert (IMATH_INTERNAL_NAMESPACE::equal ( + v.length (), t * sqrt (3), t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + t = s / (1 << 4); + + v = Vec3 (t, 0, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec3 (0, t, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec3 (0, 0, t); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec3 (-t, -t, -t); + assert (IMATH_INTERNAL_NAMESPACE::equal ( + v.length (), t * sqrt (3), t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + t = s / (1 << 20); + + v = Vec3 (t, 0, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec3 (0, t, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec3 (0, 0, t); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec3 (-t, -t, -t); + assert (IMATH_INTERNAL_NAMESPACE::equal ( + v.length (), t * sqrt (3), t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); +} + +template +void +testLength4T () +{ + const T s = sqrt (numeric_limits::min ()); + const T e = 4 * numeric_limits::epsilon (); + + Vec4 v; + + v = Vec4 (0, 0, 0, 0); + assert (v.length () == 0); + assert (v.normalized ().length () == 0); + + v = Vec4 (3, 4, 0, 0); + assert (v.length () == 5); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + v = Vec4 (3000, 4000, 0, 0); + assert (v.length () == 5000); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + v = Vec4 (1, -1, 1, 1); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), 2, e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + v = Vec4 (1000, -1000, 1000, 1000); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), 2000, 1000 * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + T t = s * (1 << 4); + + v = Vec4 (t, 0, 0, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec4 (0, t, 0, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec4 (0, 0, t, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec4 (0, 0, 0, t); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec4 (-t, -t, -t, -t); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t * 2, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + t = s / (1 << 4); + + v = Vec4 (t, 0, 0, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec4 (0, t, 0, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec4 (0, 0, t, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec4 (0, 0, 0, t); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec4 (-t, -t, -t, -t); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t * 2, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + + t = s / (1 << 20); + + v = Vec4 (t, 0, 0, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec4 (0, t, 0, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec4 (0, 0, t, 0); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec4 (0, 0, 0, t); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); + v = Vec4 (-t, -t, -t, -t); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.length (), t * 2, t * e)); + assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized ().length (), 1, e)); +} + +} // namespace + +void +testVecCUDA () +{ + testLength2T (); + testLength2T (); + testLength3T (); + testLength3T (); + testLength4T (); + testLength4T (); + + // Test template parameter checks pass an alias of a correct type. + using R = double; + testLength4T (); +} diff --git a/src/ImathTest/testVecCUDA.h b/src/ImathTest/testVecCUDA.h new file mode 100644 index 00000000..4c0c2daa --- /dev/null +++ b/src/ImathTest/testVecCUDA.h @@ -0,0 +1,6 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// Copyright Contributors to the OpenEXR Project. +// + +void testVecCUDA ();