flatten 20260225
This commit is contained in:
186
tjp/core/math/Float16.inl
Normal file
186
tjp/core/math/Float16.inl
Normal file
@@ -0,0 +1,186 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
inline
|
||||
Float16::operator float() const
|
||||
{
|
||||
return convert(v);
|
||||
}
|
||||
|
||||
inline
|
||||
Float16::operator double() const
|
||||
{
|
||||
return (float)*this;
|
||||
}
|
||||
|
||||
inline
|
||||
bool operator <(const Float16 &lhs, const Float16 &rhs)
|
||||
{
|
||||
return lhs.ordered() < rhs.ordered();
|
||||
}
|
||||
|
||||
inline
|
||||
bool operator >(const Float16 &lhs, const Float16 &rhs)
|
||||
{
|
||||
return lhs.ordered() > rhs.ordered();
|
||||
}
|
||||
|
||||
inline
|
||||
bool operator ==(const Float16 &lhs, const Float16 &rhs)
|
||||
{
|
||||
return lhs.v == rhs.v;
|
||||
}
|
||||
|
||||
inline
|
||||
bool operator !=(const Float16 &lhs, const Float16 &rhs)
|
||||
{
|
||||
return lhs.v != rhs.v;
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
inline
|
||||
constexpr Float16 Float16::max()
|
||||
{
|
||||
return Float16(Float16::Bits { .v = 0x7BFF });
|
||||
}
|
||||
|
||||
inline
|
||||
constexpr Float16 Float16::negative_max()
|
||||
{
|
||||
return Float16(Float16::Bits { .v = 0xFBFF });
|
||||
}
|
||||
|
||||
inline
|
||||
constexpr Float16 Float16::min__()
|
||||
{
|
||||
return Float16(Float16::Bits { .v = 0x0400 });
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
union Float16_Float32Bits {
|
||||
float f;
|
||||
uint32_t u;
|
||||
};
|
||||
|
||||
inline
|
||||
constexpr float Float16::convert(V v)
|
||||
{
|
||||
uint16_t hv = v;
|
||||
uint16_t sign = (hv >> 15) & 0x1;
|
||||
uint16_t exp = (hv >> 10) & 0x1F;
|
||||
uint16_t frac = hv & 0x3FF;
|
||||
|
||||
uint32_t sign32 = sign << 31;
|
||||
uint32_t exp32 = 0, frac32 = 0;
|
||||
|
||||
if (exp == 0) {
|
||||
if (frac == 0) {
|
||||
// Zero
|
||||
exp32 = 0;
|
||||
frac32 = 0;
|
||||
} else {
|
||||
// Subnormal: normalize
|
||||
int e = -14; // unbiased exponent for half subnormals
|
||||
uint32_t f = frac;
|
||||
while ((f & 0x400) == 0) {
|
||||
f <<= 1;
|
||||
e--;
|
||||
}
|
||||
f &= 0x3FF;
|
||||
exp32 = (e + 127) << 23;
|
||||
frac32 = f << 13;
|
||||
}
|
||||
}
|
||||
else if (exp == 0x1F) {
|
||||
// Inf or NaN
|
||||
exp32 = 0xFF << 23;
|
||||
if (frac == 0) {
|
||||
// Inf
|
||||
frac32 = 0;
|
||||
} else {
|
||||
// NaN – preserve payload, set quiet NaN bit
|
||||
frac32 = (frac << 13) | 0x400000;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Normalized
|
||||
int e = exp - 15 + 127;
|
||||
exp32 = (uint32_t)e << 23;
|
||||
frac32 = (uint32_t)frac << 13;
|
||||
}
|
||||
|
||||
auto u = sign32 | exp32 | frac32;
|
||||
Float16_Float32Bits result { .u = u };
|
||||
return result.f;
|
||||
}
|
||||
|
||||
inline
|
||||
constexpr Float16::V Float16::convert(float rhs)
|
||||
{
|
||||
Float16_Float32Bits result { .f = rhs };
|
||||
uint32_t bits = result.u;
|
||||
|
||||
uint32_t sign = (bits >> 31) & 0x1;
|
||||
int32_t exp = (bits >> 23) & 0xFF;
|
||||
uint32_t frac = bits & 0x7FFFFF;
|
||||
|
||||
uint16_t sign16 = sign << 15;
|
||||
uint16_t exp16 = 0;
|
||||
uint16_t frac16 = 0;
|
||||
|
||||
if (exp == 0) {
|
||||
// Zero or subnormal in float
|
||||
exp16 = 0;
|
||||
frac16 = 0; // Flush subnormals to zero
|
||||
}
|
||||
else if (exp == 0xFF) {
|
||||
// Inf or NaN
|
||||
exp16 = 0x1F;
|
||||
frac16 = frac ? 0x200 : 0; // Preserve a quiet NaN bit
|
||||
}
|
||||
else {
|
||||
// Normalized float
|
||||
int newExp = exp - 127 + 15;
|
||||
if (newExp >= 0x1F) {
|
||||
// Overflow → Inf
|
||||
exp16 = 0x1F;
|
||||
frac16 = 0;
|
||||
}
|
||||
else if (newExp <= 0) {
|
||||
// Underflow → subnormal or zero
|
||||
if (newExp < -10) {
|
||||
exp16 = 0;
|
||||
frac16 = 0;
|
||||
}
|
||||
else {
|
||||
// Subnormal half
|
||||
uint32_t mant = (frac | 0x800000) >> (1 - newExp);
|
||||
frac16 = mant >> 13;
|
||||
exp16 = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
exp16 = newExp;
|
||||
frac16 = frac >> 13;
|
||||
}
|
||||
}
|
||||
|
||||
Float16::V v = sign16 | (exp16 << 10) | frac16;
|
||||
return v;
|
||||
}
|
||||
|
||||
inline
|
||||
Float16& set(Float16 &lhs, float rhs)
|
||||
{
|
||||
lhs.v = Float16::convert(rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user