//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. // //===----------------------------------------------------------------------===// // MIT License // // Modifications Copyright (C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // clang-format off #include // clang-format on #include #include #include #include #include #include "test_macros.h" template __host__ __device__ constexpr void test_eq(const T tested, const T expected) { if (cuda::std::isnan(expected)) { assert(cuda::std::isnan(tested)); assert(cuda::std::signbit(tested) == false); return; } // extended floating point types don't support constexpr operator== if constexpr (cuda::std::is_floating_point_v) { assert(tested == expected); } else { assert(cuda::std::__fp_get_storage(tested) == cuda::std::__fp_get_storage(expected)); } } template , int> = 0> __host__ __device__ void constexpr test_fabs_abs(const T pos) { static_assert(cuda::std::is_same_v); static_assert(cuda::std::is_same_v); // 1. Test fabs on positive input test_eq(cuda::std::fabs(pos), pos); // 2. Test abs on positive input test_eq(cuda::std::abs(pos), pos); // 3. Test fabsf and fabsl on positive input if constexpr (cuda::std::is_same_v) { test_eq(cuda::std::fabsf(pos), pos); } #if _CCCL_HAS_LONG_DOUBLE() else if constexpr (cuda::std::is_same_v) { test_eq(cuda::std::fabsl(pos), pos); } #endif // _CCCL_HAS_LONG_DOUBLE() if constexpr (cuda::std::numeric_limits::is_signed) { const T neg = cuda::std::copysign(pos, cuda::std::numeric_limits::lowest()); // 4. Test fabs on negative input test_eq(cuda::std::fabs(neg), pos); // 5. Test abs on negative input test_eq(cuda::std::abs(neg), pos); // 6. Test fabsf and fabsl on negative input if constexpr (cuda::std::is_same_v) { test_eq(cuda::std::fabsf(neg), pos); } #if _CCCL_HAS_LONG_DOUBLE() else if constexpr (cuda::std::is_same_v) { test_eq(cuda::std::fabsl(neg), pos); } #endif // _CCCL_HAS_LONG_DOUBLE() } } template , int> = 0> __host__ __device__ void constexpr test_fabs_abs(const T pos) { static_assert(cuda::std::is_same_v); const double pos_ref = cuda::std::fabs(static_cast(pos)); // 1. Test fabs on positive input test_eq(cuda::std::fabs(pos), pos_ref); if constexpr (cuda::std::numeric_limits::is_signed) { const T neg = (pos == cuda::std::numeric_limits::min()) ? cuda::std::numeric_limits::max() : -pos; const double neg_ref = cuda::std::fabs(static_cast(neg)); // 2. Test fabs on negative input test_eq(cuda::std::fabs(neg), neg_ref); } } template __host__ __device__ constexpr void test_type() { // __nv_fp8_e8m0 cannot represent 0 #if _CCCL_HAS_NVFP8_E8M0() if constexpr (!cuda::std::is_same_v) #endif // _CCCL_HAS_NVFP8_E8M0 { // TODO(HIP/AMD): remove this workaround once we can initialize a half with 0 as a constexpr if constexpr (cuda::std::is_same_v){ test_fabs_abs(__half{__half_raw{.x = 0}}); } else{ test_fabs_abs(T{}); } } test_fabs_abs(cuda::std::numeric_limits::min()); test_fabs_abs(cuda::std::numeric_limits::max()); if constexpr (cuda::std::numeric_limits::has_infinity) { test_fabs_abs(cuda::std::numeric_limits::infinity()); } if constexpr (cuda::std::numeric_limits::has_quiet_NaN) { test_fabs_abs(cuda::std::numeric_limits::quiet_NaN()); } if constexpr (cuda::std::numeric_limits::has_signaling_NaN) { test_fabs_abs(cuda::std::numeric_limits::signaling_NaN()); } } __host__ __device__ constexpr bool test() { test_type(); test_type(); #if _CCCL_HAS_LONG_DOUBLE() test_type(); #endif // _CCCL_HAS_LONG_DOUBLE() #if _LIBCUDACXX_HAS_NVFP16() // NOTE(HIP/AMD): for ROCm 7.10 and earlier constexpression setting of __half values is not possible # if LIBHIPCXX_ROCM_VERSION_GE(7, 11, 0) test_type<__half>(); # endif #endif // _LIBCUDACXX_HAS_NVFP16() #if _LIBCUDACXX_HAS_NVBF16() test_type<__nv_bfloat16>(); #endif // _LIBCUDACXX_HAS_NVBF16() #if _CCCL_HAS_NVFP8_E4M3() test_type<__nv_fp8_e4m3>(); #endif // _CCCL_HAS_NVFP8_E4M3 #if _CCCL_HAS_NVFP8_E5M2() test_type<__nv_fp8_e5m2>(); #endif // _CCCL_HAS_NVFP8_E5M2 #if _CCCL_HAS_NVFP8_E8M0() test_type<__nv_fp8_e8m0>(); #endif // _CCCL_HAS_NVFP8_E8M0 #if _CCCL_HAS_NVFP6_E2M3() test_type<__nv_fp6_e2m3>(); #endif // _CCCL_HAS_NVFP6_E2M3 #if _CCCL_HAS_NVFP6_E3M2() test_type<__nv_fp6_e3m2>(); #endif // _CCCL_HAS_NVFP6_E3M2 #if _CCCL_HAS_NVFP4_E2M1() test_type<__nv_fp4_e2m1>(); #endif // _CCCL_HAS_NVFP4_E2M1 test_type(); test_type(); test_type(); test_type(); test_type(); test_type(); test_type(); test_type(); test_type(); test_type(); #if _CCCL_HAS_INT128() test_type<__int128_t>(); test_type<__uint128_t>(); #endif // _CCCL_HAS_INT128() return true; } __host__ __device__ constexpr bool test_constexpr() { #if _LIBCUDACXX_HAS_NVFP16() // NOTE(HIP/AMD): for ROCm 7.10 and earlier constexpression setting of __half values is not possible # if LIBHIPCXX_ROCM_VERSION_GE(7, 11, 0) test_type<__half>(); # endif #endif // _LIBCUDACXX_HAS_NVFP16() #if _LIBCUDACXX_HAS_NVBF16() test_type<__nv_bfloat16>(); #endif // _LIBCUDACXX_HAS_NVBF16() #if _CCCL_HAS_NVFP8_E4M3() test_type<__nv_fp8_e4m3>(); #endif // _CCCL_HAS_NVFP8_E4M3 #if _CCCL_HAS_NVFP8_E5M2() test_type<__nv_fp8_e5m2>(); #endif // _CCCL_HAS_NVFP8_E5M2 #if _CCCL_HAS_NVFP8_E8M0() test_type<__nv_fp8_e8m0>(); #endif // _CCCL_HAS_NVFP8_E8M0 #if _CCCL_HAS_NVFP6_E2M3() test_type<__nv_fp6_e2m3>(); #endif // _CCCL_HAS_NVFP6_E2M3 #if _CCCL_HAS_NVFP6_E3M2() test_type<__nv_fp6_e3m2>(); #endif // _CCCL_HAS_NVFP6_E3M2 #if _CCCL_HAS_NVFP4_E2M1() test_type<__nv_fp4_e2m1>(); #endif // _CCCL_HAS_NVFP4_E2M1 return true; } int main(int, char**) { test(); static_assert(test_constexpr()); return 0; }