Browse Source

Use System.Half

pull/2233/head
James Jackson-South 4 years ago
parent
commit
17cb0f7099
  1. 122
      src/ImageSharp/PixelFormats/HalfTypeHelper.cs

122
src/ImageSharp/PixelFormats/HalfTypeHelper.cs

@ -1,8 +1,7 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.PixelFormats;
@ -19,64 +18,8 @@ internal static class HalfTypeHelper
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static ushort Pack(float value)
{
var uif = new Uif { F = value };
return Pack(uif.I);
}
/// <summary>
/// Packs an <see cref="int"/> into a <see cref="ushort"/>
/// </summary>
/// <param name="value">The integer to pack.</param>
/// <returns>The <see cref="ushort"/></returns>
internal static ushort Pack(int value)
{
int s = (value >> 16) & 0x00008000;
int e = ((value >> 23) & 0x000000ff) - (127 - 15);
int m = value & 0x007fffff;
if (e <= 0)
{
if (e < -10)
{
return (ushort)s;
}
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);
}
if (e == 0xff - (127 - 15))
{
if (m == 0)
{
return (ushort)(s | 0x7c00);
}
m >>= 13;
return (ushort)(s | 0x7c00 | m | ((m == 0) ? 1 : 0));
}
m = m + 0x00000fff + ((m >> 13) & 1);
if ((m & 0x00800000) != 0)
{
m = 0;
e++;
}
if (e > 30)
{
return (ushort)(s | 0x7c00);
}
return (ushort)(s | (e << 10) | (m >> 13));
Half h = (Half)value;
return Unsafe.As<Half, ushort>(ref h);
}
/// <summary>
@ -84,61 +27,6 @@ internal static class HalfTypeHelper
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The <see cref="float"/>.</returns>
internal static float Unpack(ushort value)
{
uint result;
uint mantissa = (uint)(value & 1023);
uint exponent = 0xfffffff2;
if ((value & -33792) == 0)
{
if (mantissa != 0)
{
while ((mantissa & 1024) == 0)
{
exponent--;
mantissa <<= 1;
}
mantissa &= 0xfffffbff;
result = (((uint)value & 0x8000) << 16) | ((exponent + 127) << 23) | (mantissa << 13);
}
else
{
result = (uint)((value & 0x8000) << 16);
}
}
else
{
result = (((uint)value & 0x8000) << 16) | ((((((uint)value >> 10) & 0x1f) - 15) + 127) << 23) | (mantissa << 13);
}
var uif = new Uif { U = result };
return uif.F;
}
/// <summary>
/// Maps the position of number types in memory
/// </summary>
[StructLayout(LayoutKind.Explicit)]
private struct Uif
{
/// <summary>
/// The float.
/// </summary>
[FieldOffset(0)]
public float F;
/// <summary>
/// The integer.
/// </summary>
[FieldOffset(0)]
public int I;
/// <summary>
/// The unsigned integer.
/// </summary>
[FieldOffset(0)]
public uint U;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static float Unpack(ushort value) => (float)Unsafe.As<ushort, Half>(ref value);
}

Loading…
Cancel
Save