#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 } }