MoonWorks/src/Graphics/PackedVector/HalfTypeHelper.cs

140 lines
2.4 KiB
C#

#region License
/* MoonWorks - Game Development Framework
* Copyright 2021 Evan Hemsley
*/
/* Derived from code by Ethan Lee (Copyright 2009-2021).
* Released under the Microsoft Public License.
* See fna.LICENSE for details.
* Derived from code by the Mono.Xna Team (Copyright 2006).
* Released under the MIT License. See monoxna.LICENSE for details.
*/
#endregion
#region Using Statements
using System;
using System.Runtime.InteropServices;
#endregion
namespace MoonWorks.Graphics
{
internal static class HalfTypeHelper
{
#region Private Struct uif
[StructLayout(LayoutKind.Explicit)]
private struct uif
{
[FieldOffset(0)]
public float f;
[FieldOffset(0)]
public int i;
[FieldOffset(0)]
public uint u;
}
#endregion
#region Internal Static Methods
internal static ushort Convert(float f)
{
uif uif = new uif();
uif.f = f;
return Convert(uif.i);
}
internal static ushort Convert(int i)
{
int s = (i >> 16) & 0x00008000;
int e = ((i >> 23) & 0x000000ff) - (127 - 15);
int m = i & 0x007fffff;
if (e <= 0)
{
if (e < -10)
{
return (ushort) s;
}
m = m | 0x00800000;
int t = 14 - e;
int a = (1 << (t - 1)) - 1;
int b = (m >> t) & 1;
m = (m + a + b) >> t;
return (ushort) (s | m);
}
else if (e == 0xff - (127 - 15))
{
if (m == 0)
{
return (ushort) (s | 0x7c00);
}
else
{
m >>= 13;
return (ushort) (s | 0x7c00 | m | ((m == 0) ? 1 : 0));
}
}
else
{
m = m + 0x00000fff + ((m >> 13) & 1);
if ((m & 0x00800000) != 0)
{
m = 0;
e += 1;
}
if (e > 30)
{
return (ushort) (s | 0x7c00);
}
return (ushort) (s | (e << 10) | (m >> 13));
}
}
internal static float Convert(ushort value)
{
uint rst;
uint mantissa = (uint) (value & 1023);
uint exp = 0xfffffff2;
if ((value & -33792) == 0)
{
if (mantissa != 0)
{
while ((mantissa & 1024) == 0)
{
exp--;
mantissa = mantissa << 1;
}
mantissa &= 0xfffffbff;
rst = ((uint) ((((uint) value & 0x8000) << 16) | ((exp + 127) << 23))) | (mantissa << 13);
}
else
{
rst = (uint) ((value & 0x8000) << 16);
}
}
else
{
rst = (uint) (((((uint) value & 0x8000) << 16) | ((((((uint) value >> 10) & 0x1f) - 15) + 127) << 23)) | (mantissa << 13));
}
uif uif = new uif();
uif.u = rst;
return uif.f;
}
#endregion
}
}