You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Legacy/CryCommon/CryHalf.inl

203 lines
4.4 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#ifndef CRY_HALF_INL
#define CRY_HALF_INL
#pragma once
typedef uint16 CryHalf;
class ICrySizer;
typedef union floatint_union
{
float f;
uint32 i;
} floatint_union;
__forceinline CryHalf CryConvertFloatToHalf(const float Value)
{
#if defined(LINUX) || defined(MAC)
asm volatile("" ::: "memory");
#endif
unsigned int Result;
unsigned int IValue = ((unsigned int*)(&Value))[0];
unsigned int Sign = (IValue & 0x80000000U) >> 16U;
IValue = IValue & 0x7FFFFFFFU; // Hack off the sign
if (IValue > 0x47FFEFFFU)
{
// The number is too large to be represented as a half. Saturate to infinity.
Result = 0x7FFFU;
}
else
{
if (IValue < 0x38800000U)
{
// The number is too small to be represented as a normalized half.
// Convert it to a denormalized value.
unsigned int Shift = 113U - (IValue >> 23U);
IValue = (0x800000U | (IValue & 0x7FFFFFU)) >> Shift;
}
else
{
// Rebias the exponent to represent the value as a normalized half.
IValue += 0xC8000000U;
}
Result = ((IValue + 0x0FFFU + ((IValue >> 13U) & 1U)) >> 13U) & 0x7FFFU;
}
return (CryHalf)(Result | Sign);
}
__forceinline float CryConvertHalfToFloat(const CryHalf Value)
{
#if defined(LINUX) || defined(MAC)
asm volatile("" ::: "memory");
#endif
unsigned int Mantissa;
unsigned int Exponent;
unsigned int Result;
Mantissa = (unsigned int)(Value & 0x03FF);
if ((Value & 0x7C00) != 0) // The value is normalized
{
Exponent = (unsigned int)((Value >> 10) & 0x1F);
}
else if (Mantissa != 0) // The value is denormalized
{
// Normalize the value in the resulting float
Exponent = 1;
do
{
Exponent--;
Mantissa <<= 1;
} while ((Mantissa & 0x0400) == 0);
Mantissa &= 0x03FF;
}
else // The value is zero
{
Exponent = (unsigned int)-112;
}
Result = ((Value & 0x8000) << 16) | // Sign
((Exponent + 112) << 23) | // Exponent
(Mantissa << 13); // Mantissa
return *(float*)&Result;
}
struct CryHalf2
{
CryHalf x;
CryHalf y;
CryHalf2()
{
}
CryHalf2(CryHalf _x, CryHalf _y)
: x(_x)
, y(_y)
{
}
CryHalf2(const CryHalf* const __restrict pArray)
{
x = pArray[0];
y = pArray[1];
}
CryHalf2(float _x, float _y)
{
x = CryConvertFloatToHalf(_x);
y = CryConvertFloatToHalf(_y);
}
CryHalf2(const float* const __restrict pArray)
{
x = CryConvertFloatToHalf(pArray[0]);
y = CryConvertFloatToHalf(pArray[1]);
}
CryHalf2& operator= (const CryHalf2& Half2)
{
x = Half2.x;
y = Half2.y;
return *this;
}
bool operator !=(const CryHalf2& rhs) const
{
return x != rhs.x || y != rhs.y;
}
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {}
AUTO_STRUCT_INFO
};
struct CryHalf4
{
CryHalf x;
CryHalf y;
CryHalf z;
CryHalf w;
CryHalf4()
{
}
CryHalf4(CryHalf _x, CryHalf _y, CryHalf _z, CryHalf _w)
: x(_x)
, y(_y)
, z(_z)
, w(_w)
{
}
CryHalf4(const CryHalf* const __restrict pArray)
{
x = pArray[0];
y = pArray[1];
z = pArray[2];
w = pArray[3];
}
CryHalf4(float _x, float _y, float _z, float _w)
{
x = CryConvertFloatToHalf(_x);
y = CryConvertFloatToHalf(_y);
z = CryConvertFloatToHalf(_z);
w = CryConvertFloatToHalf(_w);
}
CryHalf4(const float* const __restrict pArray)
{
x = CryConvertFloatToHalf(pArray[0]);
y = CryConvertFloatToHalf(pArray[1]);
z = CryConvertFloatToHalf(pArray[2]);
w = CryConvertFloatToHalf(pArray[3]);
}
CryHalf4& operator= (const CryHalf4& Half4)
{
x = Half4.x;
y = Half4.y;
z = Half4.z;
w = Half4.w;
return *this;
}
bool operator !=(const CryHalf4& rhs) const
{
return x != rhs.x || y != rhs.y || z != rhs.z || w != rhs.w;
}
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {}
AUTO_STRUCT_INFO
};
#endif // #ifndef CRY_HALF_INL