/* * Copyright (c) Advanced Micro Devices, Inc., or its affiliates. * * SPDX-License-Identifier: MIT */ #include #include #include constexpr unsigned short kHalfTwo = 0x4000U; // 2.0 constexpr unsigned short kHalfPi = 0x4248U; // ~3.140625 (closest to pi) constexpr unsigned short kHalfInf = 0x7C00U; // +Infinity /** * Constexpr function to create __half from bit pattern. * This pattern is used by libhipcxx for mathematical constants. */ __host__ __device__ constexpr __half makeHalfFromBits(unsigned short bits) { return __half{__half_raw{.x = bits}}; } // Constexpr half-precision constants using the pattern from the bug report constexpr __half kConstTwo = makeHalfFromBits(kHalfTwo); constexpr __half kConstPi = makeHalfFromBits(kHalfPi); /** * Device kernel that uses constexpr __half values. * Tests that constexpr __half can be used in device code. */ __global__ void testConstexprHalfDevice(float* results) { // Verify the constexpr values are usable in device code results[0] = __half2float(kConstTwo); results[1]= __half2float(kConstPi); // Test arithmetic with constexpr values results[2] = __half2float(__hmul(kConstTwo, kConstPi)); // 2 * pi } /** * Test Description * ------------------------ * - Tests constexpr construction of __half from __half_raw{.x = bits} * - This is the pattern used by libhipcxx for mathematical constants * - Verifies fix for union active member issue in constexpr evaluation */ HIP_TEST_CASE(Unit_hipTestHalfConstexpr_HostConstexpr) { // Test that constexpr __half values have correct bit patterns on host SECTION("Two") { constexpr __half two = makeHalfFromBits(kHalfTwo); float f = __half2float(two); REQUIRE(f == 2.0f); REQUIRE(__half_as_ushort(two) == kHalfTwo); } SECTION("Pi approximation") { constexpr __half pi = makeHalfFromBits(kHalfPi); float f = __half2float(pi); // Half precision pi is approximately 3.140625 REQUIRE(f == Catch::Approx(3.14159f).epsilon(0.01)); REQUIRE(__half_as_ushort(pi) == kHalfPi); } SECTION("Infinity") { constexpr __half inf = makeHalfFromBits(kHalfInf); REQUIRE(__hisinf(inf)); REQUIRE(__half_as_ushort(inf) == kHalfInf); } SECTION("File scope constexpr values") { // Test that file-scope constexpr values are correct REQUIRE(__half2float(kConstTwo) == 2.0f); } } /** * Test Description * ------------------------ * - Tests that constexpr __half values can be used in device kernels * - Verifies both file-scope and kernel-local constexpr values work */ HIP_TEST_CASE(Unit_hipTestHalfConstexpr_DeviceConstexpr) { constexpr size_t numResults = 3; float* results_d = nullptr; std::vector results_h(numResults, 0.0f); HIP_CHECK(hipMalloc(&results_d, numResults * sizeof(float))); testConstexprHalfDevice<<<1, 1>>>(results_d); HIP_CHECK(hipDeviceSynchronize()); HIP_CHECK(hipMemcpy(results_h.data(), results_d, numResults * sizeof(float), hipMemcpyDeviceToHost)); // Verify results REQUIRE(results_h[0] == 2.0f); // kConstTwo REQUIRE(results_h[1] == Catch::Approx(3.14159f).epsilon(0.01)); // kConstPi REQUIRE(results_h[2] == Catch::Approx(6.28f).epsilon(0.01)); // 2 * pi HIP_CHECK(hipFree(results_d)); }