Files
TheRock/rocm-libraries/projects/hipsparse/library/include/hipsparse-float16.h
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

278 lines
7.8 KiB
C++

/*! \file */
/* ************************************************************************
* Copyright (C) 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.
*
* ************************************************************************ */
#pragma once
#if __cplusplus < 201103L
// If this is a C or C++ compiler below C++11,
// we only include a minimal definition of hipsparseFloat16
typedef struct hipsparseFloat16
{
uint16_t data;
} hipsparseFloat16;
#else
#include <cmath>
#include <cstdint>
#include <iostream>
#include <ostream>
class hipsparseFloat16
{
public:
uint16_t data;
// Convert IEEE float16 to IEEE float32
static float float16_to_float(hipsparseFloat16 val)
{
uint16_t h = val.data;
// Extract components
uint32_t sign = (h >> 15) & 0x1;
uint32_t exponent = (h >> 10) & 0x1f;
uint32_t mantissa = h & 0x3ff;
uint32_t f;
if(exponent == 0)
{
if(mantissa == 0)
{
// Zero (preserve sign)
f = sign << 31;
}
else
{
// Subnormal float16 -> normalized float32
exponent = 1;
while((mantissa & 0x400) == 0)
{
mantissa <<= 1;
exponent--;
}
mantissa &= 0x3ff;
f = (sign << 31) | ((exponent + 127 - 15) << 23) | (mantissa << 13);
}
}
else if(exponent == 31)
{
// Inf or NaN
f = (sign << 31) | 0x7f800000 | (mantissa << 13);
}
else
{
// Normalized number
f = (sign << 31) | ((exponent + 127 - 15) << 23) | (mantissa << 13);
}
union
{
uint32_t int32;
float fp32;
} u = {f};
return u.fp32;
}
// Convert IEEE float32 to IEEE float16
static uint16_t float_to_float16(float f)
{
union
{
float fp32;
uint32_t int32;
} u = {f};
uint32_t x = u.int32;
// Extract components
uint32_t sign = (x >> 31) & 0x1;
int32_t exponent = ((x >> 23) & 0xff) - 127 + 15;
uint32_t mantissa = x & 0x7fffff;
uint16_t h;
if(exponent <= 0)
{
if(exponent < -10)
{
// Too small, return signed zero
h = static_cast<uint16_t>(sign << 15);
}
else
{
// Subnormal
mantissa |= 0x800000; // Add implicit leading 1
int shift = 14 - exponent;
// Round to nearest, round to even
uint32_t round_bit = 1u << (shift - 1);
uint32_t round_mask = (1u << shift) - 1;
uint32_t m_shifted = mantissa >> shift;
if((mantissa & round_mask) > round_bit
|| ((mantissa & round_mask) == round_bit && (m_shifted & 1)))
{
m_shifted++;
}
h = static_cast<uint16_t>((sign << 15) | m_shifted);
}
}
else if(exponent >= 31)
{
// Overflow to infinity or preserve NaN
if(exponent == 31 && mantissa != 0)
{
// NaN - preserve signaling bit
h = static_cast<uint16_t>((sign << 15) | 0x7c00 | (mantissa >> 13));
if((h & 0x3ff) == 0)
{
h |= 1; // Ensure NaN mantissa is non-zero
}
}
else
{
// Infinity
h = static_cast<uint16_t>((sign << 15) | 0x7c00);
}
}
else
{
// Normalized number - round to nearest, round to even
uint32_t round_bit = 0x1000; // bit 12
uint32_t m = mantissa + round_bit;
if(m & 0x800000)
{
// Mantissa overflow
m = 0;
exponent++;
if(exponent >= 31)
{
// Overflow to infinity
h = static_cast<uint16_t>((sign << 15) | 0x7c00);
return h;
}
}
h = static_cast<uint16_t>((sign << 15) | (exponent << 10) | (m >> 13));
}
return h;
}
hipsparseFloat16() = default;
// Convert float32 to float16
explicit hipsparseFloat16(float f)
: data(float_to_float16(f))
{
}
hipsparseFloat16 operator=(float a)
{
return hipsparseFloat16(a);
}
// Convert float16 to float32
operator float() const
{
return float16_to_float(*this);
}
explicit operator bool() const
{
return data & 0x7fff;
}
};
inline std::ostream& operator<<(std::ostream& os, const hipsparseFloat16& f16)
{
return os << float(f16);
}
typedef struct
{
uint16_t data;
} hipsparseFloat16_public;
static_assert(std::is_standard_layout<hipsparseFloat16>{},
"hipsparseFloat16 is not a standard layout type, and thus is "
"incompatible with C.");
static_assert(std::is_trivial<hipsparseFloat16>{},
"hipsparseFloat16 is not a trivial type, and thus is "
"incompatible with C.");
static_assert(sizeof(hipsparseFloat16) == sizeof(hipsparseFloat16_public)
&& offsetof(hipsparseFloat16, data) == offsetof(hipsparseFloat16_public, data),
"internal hipsparseFloat16 does not match public hipsparseFloat16_public");
inline hipsparseFloat16 operator+=(hipsparseFloat16 a, hipsparseFloat16 b)
{
return a = a + b;
}
inline hipsparseFloat16 operator+=(hipsparseFloat16 a, float b)
{
return a = hipsparseFloat16(float(a) + b);
}
inline float operator+=(float a, hipsparseFloat16 b)
{
return a = a + float(b);
}
inline hipsparseFloat16 operator-=(hipsparseFloat16 a, hipsparseFloat16 b)
{
return a = a - b;
}
inline hipsparseFloat16 operator-=(hipsparseFloat16 a, float b)
{
return a = hipsparseFloat16(float(a) - b);
}
inline float operator-=(float a, hipsparseFloat16 b)
{
return a = a - float(b);
}
inline hipsparseFloat16 operator*=(hipsparseFloat16 a, hipsparseFloat16 b)
{
return a = a * b;
}
inline float operator*=(hipsparseFloat16 a, float b)
{
return a = float(a) * b;
}
inline float operator*=(float a, hipsparseFloat16 b)
{
return a = a * float(b);
}
inline hipsparseFloat16 operator/=(hipsparseFloat16 a, hipsparseFloat16 b)
{
return a = a / b;
}
inline hipsparseFloat16 operator/=(hipsparseFloat16 a, float b)
{
return a = hipsparseFloat16(float(a) / b);
}
inline float operator/=(float a, hipsparseFloat16 b)
{
return a = a / float(b);
}
#endif