Use System.Half
This commit is contained in:
@@ -1413,7 +1413,7 @@ namespace AssetStudio
|
|||||||
result[i] = BitConverter.ToSingle(inputBytes, i * 4);
|
result[i] = BitConverter.ToSingle(inputBytes, i * 4);
|
||||||
break;
|
break;
|
||||||
case VertexFormat.Float16:
|
case VertexFormat.Float16:
|
||||||
result[i] = Half.ToHalf(inputBytes, i * 2);
|
result[i] = (float)HalfHelper.ToHalf(inputBytes, i * 2);
|
||||||
break;
|
break;
|
||||||
case VertexFormat.UNorm8:
|
case VertexFormat.UNorm8:
|
||||||
result[i] = inputBytes[i] / 255f;
|
result[i] = inputBytes[i] / 255f;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
|
#if NETFRAMEWORK
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -35,27 +36,27 @@ namespace AssetStudio
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the smallest positive System.Half value greater than zero. This field is constant.
|
/// Represents the smallest positive System.Half value greater than zero. This field is constant.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly Half Epsilon = Half.ToHalf(0x0001);
|
public static readonly Half Epsilon = HalfHelper.ToHalf(0x0001);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the largest possible value of System.Half. This field is constant.
|
/// Represents the largest possible value of System.Half. This field is constant.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly Half MaxValue = Half.ToHalf(0x7bff);
|
public static readonly Half MaxValue = HalfHelper.ToHalf(0x7bff);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the smallest possible value of System.Half. This field is constant.
|
/// Represents the smallest possible value of System.Half. This field is constant.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly Half MinValue = Half.ToHalf(0xfbff);
|
public static readonly Half MinValue = HalfHelper.ToHalf(0xfbff);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents not a number (NaN). This field is constant.
|
/// Represents not a number (NaN). This field is constant.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly Half NaN = Half.ToHalf(0xfe00);
|
public static readonly Half NaN = HalfHelper.ToHalf(0xfe00);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents negative infinity. This field is constant.
|
/// Represents negative infinity. This field is constant.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly Half NegativeInfinity = Half.ToHalf(0xfc00);
|
public static readonly Half NegativeInfinity = HalfHelper.ToHalf(0xfc00);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents positive infinity. This field is constant.
|
/// Represents positive infinity. This field is constant.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly Half PositiveInfinity = Half.ToHalf(0x7c00);
|
public static readonly Half PositiveInfinity = HalfHelper.ToHalf(0x7c00);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
@@ -63,7 +64,7 @@ namespace AssetStudio
|
|||||||
/// Initializes a new instance of System.Half to the value of the specified single-precision floating-point number.
|
/// Initializes a new instance of System.Half to the value of the specified single-precision floating-point number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The value to represent as a System.Half.</param>
|
/// <param name="value">The value to represent as a System.Half.</param>
|
||||||
public Half(float value) { this = HalfHelper.SingleToHalf(value); }
|
public Half(float value) { this = HalfHelper.ToHalf(value); }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of System.Half to the value of the specified 32-bit signed integer.
|
/// Initializes a new instance of System.Half to the value of the specified 32-bit signed integer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -314,7 +315,7 @@ namespace AssetStudio
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">A System.Half to convert.</param>
|
/// <param name="value">A System.Half to convert.</param>
|
||||||
/// <returns>A single-precision floating-point number that represents the converted System.Half.</returns>
|
/// <returns>A single-precision floating-point number that represents the converted System.Half.</returns>
|
||||||
public static implicit operator float(Half value) { return (float)HalfHelper.HalfToSingle(value); }
|
public static implicit operator float(Half value) { return value.ToSingle(); }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts a System.Half to a double-precision floating-point number.
|
/// Converts a System.Half to a double-precision floating-point number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -508,32 +509,6 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
return value.value;
|
return value.value;
|
||||||
}
|
}
|
||||||
/// <summary>
|
|
||||||
/// Returns a half-precision floating point number converted from two bytes
|
|
||||||
/// at a specified position in a byte array.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">An array of bytes.</param>
|
|
||||||
/// <param name="startIndex">The starting position within value.</param>
|
|
||||||
/// <returns>A half-precision floating point number formed by two bytes beginning at startIndex.</returns>
|
|
||||||
/// <exception cref="System.ArgumentException">
|
|
||||||
/// startIndex is greater than or equal to the length of value minus 1, and is
|
|
||||||
/// less than or equal to the length of value minus 1.
|
|
||||||
/// </exception>
|
|
||||||
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
|
||||||
/// <exception cref="System.ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception>
|
|
||||||
public static Half ToHalf(byte[] value, int startIndex)
|
|
||||||
{
|
|
||||||
return Half.ToHalf((ushort)BitConverter.ToInt16(value, startIndex));
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a half-precision floating point number converted from its binary representation.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bits">Binary representation of System.Half value</param>
|
|
||||||
/// <returns>A half-precision floating point number formed by its binary representation.</returns>
|
|
||||||
public static Half ToHalf(ushort bits)
|
|
||||||
{
|
|
||||||
return new Half { value = bits };
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a value indicating the sign of a half-precision floating-point number.
|
/// Returns a value indicating the sign of a half-precision floating-point number.
|
||||||
@@ -886,3 +861,4 @@ namespace AssetStudio
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1,18 +1,32 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Buffers.Binary;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
|
#if NET
|
||||||
|
public static class HalfHelper
|
||||||
|
{
|
||||||
|
public static Half ToHalf(ushort bits)
|
||||||
|
{
|
||||||
|
return (Half)bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Half ToHalf(ReadOnlySpan<byte> bytes, int startIndex)
|
||||||
|
{
|
||||||
|
return BinaryPrimitives.ReadHalfLittleEndian(bytes[startIndex..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper class for Half conversions and some low level operations.
|
/// Helper class for Half conversions and some low level operations.
|
||||||
/// This class is internally used in the Half class.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// References:
|
/// References:
|
||||||
/// - Fast Half Float Conversions, Jeroen van der Zijp, link: http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
|
/// - Fast Half Float Conversions, Jeroen van der Zijp, link: http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[ComVisible(false)]
|
[ComVisible(false)]
|
||||||
internal static class HalfHelper
|
public static class HalfHelper
|
||||||
{
|
{
|
||||||
private static uint[] mantissaTable = GenerateMantissaTable();
|
private static uint[] mantissaTable = GenerateMantissaTable();
|
||||||
private static uint[] exponentTable = GenerateExponentTable();
|
private static uint[] exponentTable = GenerateExponentTable();
|
||||||
@@ -169,27 +183,54 @@ namespace AssetStudio
|
|||||||
ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
|
ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
|
||||||
return Half.ToHalf(result);
|
return Half.ToHalf(result);
|
||||||
}*/
|
}*/
|
||||||
public static float HalfToSingle(Half half)
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a half-precision floating point number converted from two bytes
|
||||||
|
/// at a specified position in a byte array.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">An array of bytes.</param>
|
||||||
|
/// <param name="startIndex">The starting position within value.</param>
|
||||||
|
/// <returns>A half-precision floating point number formed by two bytes beginning at startIndex.</returns>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// startIndex is greater than or equal to the length of value minus 1, and is
|
||||||
|
/// less than or equal to the length of value minus 1.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception>
|
||||||
|
public static Half ToHalf(ReadOnlySpan<byte> value, int startIndex)
|
||||||
|
{
|
||||||
|
return ToHalf((ushort)BinaryPrimitives.ReadInt16LittleEndian(value.Slice(startIndex)));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a half-precision floating point number converted from its binary representation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bits">Binary representation of System.Half value</param>
|
||||||
|
/// <returns>A half-precision floating point number formed by its binary representation.</returns>
|
||||||
|
public static Half ToHalf(ushort bits)
|
||||||
|
{
|
||||||
|
return new Half { value = bits };
|
||||||
|
}
|
||||||
|
public static Half ToHalf(float single)
|
||||||
|
{
|
||||||
|
byte[] singleBytes = BitConverter.GetBytes(single);
|
||||||
|
uint value = BitConverter.ToUInt32(singleBytes, 0);
|
||||||
|
ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
|
||||||
|
return ToHalf(result);
|
||||||
|
}
|
||||||
|
public static float ToSingle(this Half half)
|
||||||
{
|
{
|
||||||
uint result = mantissaTable[offsetTable[half.value >> 10] + (half.value & 0x3ff)] + exponentTable[half.value >> 10];
|
uint result = mantissaTable[offsetTable[half.value >> 10] + (half.value & 0x3ff)] + exponentTable[half.value >> 10];
|
||||||
byte[] uintBytes = BitConverter.GetBytes(result);
|
byte[] uintBytes = BitConverter.GetBytes(result);
|
||||||
return BitConverter.ToSingle(uintBytes, 0);
|
return BitConverter.ToSingle(uintBytes, 0);
|
||||||
}
|
}
|
||||||
public static Half SingleToHalf(float single)
|
|
||||||
{
|
|
||||||
byte[] singleBytes = BitConverter.GetBytes(single);
|
|
||||||
uint value = BitConverter.ToUInt32(singleBytes, 0);
|
|
||||||
ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
|
|
||||||
return Half.ToHalf(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Half Negate(Half half)
|
public static Half Negate(Half half)
|
||||||
{
|
{
|
||||||
return Half.ToHalf((ushort)(half.value ^ 0x8000));
|
return ToHalf((ushort)(half.value ^ 0x8000));
|
||||||
}
|
}
|
||||||
public static Half Abs(Half half)
|
public static Half Abs(Half half)
|
||||||
{
|
{
|
||||||
return Half.ToHalf((ushort)(half.value & 0x7fff));
|
return ToHalf((ushort)(half.value & 0x7fff));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsNaN(Half half)
|
public static bool IsNaN(Half half)
|
||||||
@@ -209,4 +250,5 @@ namespace AssetStudio
|
|||||||
return (half.value == 0xfc00);
|
return (half.value == 0xfc00);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -440,7 +440,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
buff[i] = 0;
|
buff[i] = 0;
|
||||||
buff[i + 1] = 0;
|
buff[i + 1] = 0;
|
||||||
buff[i + 2] = (byte)MathF.Round(Half.ToHalf(image_data, i / 2) * 255f);
|
buff[i + 2] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i / 2) * 255f);
|
||||||
buff[i + 3] = 255;
|
buff[i + 3] = 255;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -451,8 +451,8 @@ namespace AssetStudio
|
|||||||
for (var i = 0; i < outPutDataSize; i += 4)
|
for (var i = 0; i < outPutDataSize; i += 4)
|
||||||
{
|
{
|
||||||
buff[i] = 0;
|
buff[i] = 0;
|
||||||
buff[i + 1] = (byte)MathF.Round(Half.ToHalf(image_data, i + 2) * 255f);
|
buff[i + 1] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i + 2) * 255f);
|
||||||
buff[i + 2] = (byte)MathF.Round(Half.ToHalf(image_data, i) * 255f);
|
buff[i + 2] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i) * 255f);
|
||||||
buff[i + 3] = 255;
|
buff[i + 3] = 255;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -462,10 +462,10 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
for (var i = 0; i < outPutDataSize; i += 4)
|
for (var i = 0; i < outPutDataSize; i += 4)
|
||||||
{
|
{
|
||||||
buff[i] = (byte)MathF.Round(Half.ToHalf(image_data, i * 2 + 4) * 255f);
|
buff[i] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i * 2 + 4) * 255f);
|
||||||
buff[i + 1] = (byte)MathF.Round(Half.ToHalf(image_data, i * 2 + 2) * 255f);
|
buff[i + 1] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i * 2 + 2) * 255f);
|
||||||
buff[i + 2] = (byte)MathF.Round(Half.ToHalf(image_data, i * 2) * 255f);
|
buff[i + 2] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i * 2) * 255f);
|
||||||
buff[i + 3] = (byte)MathF.Round(Half.ToHalf(image_data, i * 2 + 6) * 255f);
|
buff[i + 3] = (byte)MathF.Round((float)HalfHelper.ToHalf(image_data, i * 2 + 6) * 255f);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user