From 6a87d1ac090d9b3eb0b655109f36a118bf0105c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Sun, 17 Dec 2023 18:47:07 +0100 Subject: [PATCH] ScriptCore: Use engine implementation of half to no longer rely on Half-Package --- GlitchyEngine/src/Math/half.bf | 12 +- GlitchyEngine/src/Scripting/ScriptGlue.bf | 28 +++ ScriptCore/Math/Half.cs | 282 ++++++++++++++++++++++ ScriptCore/Math/HalfVectors.cs | 1 - ScriptCore/ScriptCore.csproj | 4 - 5 files changed, 321 insertions(+), 6 deletions(-) create mode 100644 ScriptCore/Math/Half.cs diff --git a/GlitchyEngine/src/Math/half.bf b/GlitchyEngine/src/Math/half.bf index dfad962..7139019 100644 --- a/GlitchyEngine/src/Math/half.bf +++ b/GlitchyEngine/src/Math/half.bf @@ -24,7 +24,7 @@ struct half : IFloating, ISigned, IFormattable, IHashable, IEquatable, ICa public bool IsNegative => (_data & Half_Sign_Mask) > 0; - public bool IsFinity => (_data & ~Half_Sign_Mask) < Half_Exponent_Mask; + public bool IsFinite => (_data & ~Half_Sign_Mask) < Half_Exponent_Mask; public bool IsInfinity => (_data & ~Half_Sign_Mask) == Half_Exponent_Mask; public bool IsPositiveInfinity => _data == PositiveInfinity._data; @@ -299,6 +299,16 @@ struct half : IFloating, ISigned, IFormattable, IHashable, IEquatable, ICa return (half)((float)lhs % (float)rhs); } + public static half operator ++(half value) + { + return (half)((float)value + 1.0f); + } + + public static half operator --(half value) + { + return (half)((float)value - 1.0f); + } + public static bool operator==(half value1, half value2) => value1._data == value2._data; public static bool operator!=(half value1, half value2) => value1._data != value2._data; diff --git a/GlitchyEngine/src/Scripting/ScriptGlue.bf b/GlitchyEngine/src/Scripting/ScriptGlue.bf index 97e7ee2..03d5df0 100644 --- a/GlitchyEngine/src/Scripting/ScriptGlue.bf +++ b/GlitchyEngine/src/Scripting/ScriptGlue.bf @@ -465,6 +465,34 @@ static class ScriptGlue RegisterCall("ScriptGlue::modf_float2", => GlitchyEngine.Math.modf); RegisterCall("ScriptGlue::modf_float3", => GlitchyEngine.Math.modf); RegisterCall("ScriptGlue::modf_float4", => GlitchyEngine.Math.modf); + + RegisterHalfFunctions(); + } + + private static void RegisterHalfFunctions() + { + RegisterCall("Math.MyHalf::FromFloat32", (value, halfValue) => halfValue = GlitchyEngine.Math.half.FromFloat32(value)); + RegisterCall("Math.MyHalf::ToFloat32", (value, floatValue) => floatValue = GlitchyEngine.Math.half.ToFloat32(value)); + + RegisterCall("Math.MyHalf::LessThan_Impl", (left, right, result) => result = left < right); + RegisterCall("Math.MyHalf::LessThanOrEqual_Impl", (left, right, result) => result = left <= right); + RegisterCall("Math.MyHalf::GreaterThan_Impl", (left, right, result) => result = left > right); + RegisterCall("Math.MyHalf::GreaterThanOrEqual_Impl", (left, right, result) => result = left >= right); + + RegisterCall("Math.MyHalf::Add_Impl", (left, right, result) => result = left + right); + RegisterCall("Math.MyHalf::Subtract_Impl", (left, right, result) => result = left - right); + RegisterCall("Math.MyHalf::Multiply_Impl", (left, right, result) => result = left * right); + RegisterCall("Math.MyHalf::Divide_Impl", (left, right, result) => result = left / right); + RegisterCall("Math.MyHalf::Modulo_Impl", (left, right, result) => result = left % right); + RegisterCall("Math.MyHalf::Negate_Impl", (value, result) => result = -value); + RegisterCall("Math.MyHalf::Increment_Impl", (value, result) => result = ++value); + RegisterCall("Math.MyHalf::Decrement_Impl", (value, result) => result = --value); + + RegisterCall("Math.MyHalf::IsNegative_Impl", (value) => value.IsNegative); + RegisterCall("Math.MyHalf::IsFinite_Impl", (value) => value.IsFinite); + RegisterCall("Math.MyHalf::IsInfinity_Impl", (value) => value.IsInfinity); + RegisterCall("Math.MyHalf::IsNan_Impl", (value) => value.IsNaN); + RegisterCall("Math.MyHalf::IsSubnormal_Impl", (value) => value.IsSubnormal); } #endregion diff --git a/ScriptCore/Math/Half.cs b/ScriptCore/Math/Half.cs new file mode 100644 index 0000000..63e77ca --- /dev/null +++ b/ScriptCore/Math/Half.cs @@ -0,0 +1,282 @@ +using System; +using System.Runtime.CompilerServices; + +namespace GlitchyEngine.Math; + +/// +/// Represents a 16-bit floating point number. (IEEE 754 half-precision binary floating-point (binary16)) +/// +/// +/// Even though it is possible, it's not recommended to perform calculations using this type directly, because most operators will simply cast the operands to and cast the result back to . +/// +public struct Half : IComparable , IComparable, IConvertible, IEquatable, IFormattable +{ + public static readonly Half MinValue = new(-65504); // Should be 0xFBFF + public static readonly Half MaxValue = new(65504); // Should be 0x7BFF + + // The numbers for Inifnity, NaN and Zero need to be hardcoded as binaries, + // because the conversion intself relies on them. + + public static readonly Half PositiveInfinity = new(0x7C00); + public static readonly Half NegativeInfinity = new(0xFC00); + public static readonly Half NaN = new(0x7CFF); + + public static readonly Half Zero = new(0x0000); + public static readonly Half NegativeZero = new(0x8000); + + private ushort _data; + + public bool IsNegative => IsNegative_Impl(this); + + public bool IsFinite => IsFinite_Impl(this); + public bool IsInfinity => IsInfinity_Impl(this); + public bool IsPositiveInfinity => _data == PositiveInfinity._data; + public bool IsNegativeInfinity => _data == NegativeInfinity._data; + public bool IsNaN => IsNan_Impl(this); + + public bool IsSubnormal => IsSubnormal_Impl(this); + + public Half(float value) + { + FromFloat32(value, out this); + } + + private Half(ushort data) + { + _data = data; + } + + public static explicit operator float(Half value) + { + ToFloat32(value, out float floatValue); + return floatValue; + } + + public static explicit operator Half(float value) + { + FromFloat32(value, out Half halfValue); + return halfValue; + } + + /// Converts the numeric value of this instance to its equivalent string representation. + /// The string representation of the value of this instance. + public override string ToString() => ((float)this).ToString(); + + public int CompareTo(object obj) + { + if (obj == null) + return 1; + + if (obj is not Half value) + throw new ArgumentException($"Object must be of type {typeof(Half)}"); + + return CompareTo(value); + } + + public int CompareTo(Half other) + { + return ((float)this).CompareTo((float)other); + } + + public TypeCode GetTypeCode() => TypeCode.Object; + + public bool ToBoolean(IFormatProvider provider) => Convert.ToBoolean((float)this, provider); + + public byte ToByte(IFormatProvider provider) => Convert.ToByte((float)this, provider); + + public char ToChar(IFormatProvider provider) => Convert.ToChar((float)this, provider); + + public DateTime ToDateTime(IFormatProvider provider) => Convert.ToDateTime((float)this, provider); + + public decimal ToDecimal(IFormatProvider provider) => Convert.ToDecimal((float)this, provider); + + public double ToDouble(IFormatProvider provider) => Convert.ToDouble((float)this, provider); + + public short ToInt16(IFormatProvider provider) => Convert.ToInt16((float)this, provider); + + public int ToInt32(IFormatProvider provider) => Convert.ToInt32((float)this, provider); + + public long ToInt64(IFormatProvider provider) => Convert.ToInt64((float)this, provider); + + public sbyte ToSByte(IFormatProvider provider) => Convert.ToSByte((float)this, provider); + + public float ToSingle(IFormatProvider provider) => Convert.ToSingle((float)this, provider); + + /// Converts the numeric value of this instance to its equivalent string representation using the specified culture-specific format information. + /// An object that supplies culture-specific formatting information. + /// The string representation of the value of this instance as specified by provider. + public string ToString(IFormatProvider provider) => ((float)this).ToString(provider); + + /// Converts the numeric value of this instance to its equivalent string representation, using the specified format. + /// A numeric format string. + /// The string representation of the value of this instance as specified by format. + /// format is invalid. + public string ToString(string format) => ((float)this).ToString(format); + + /// Converts the numeric value of this instance to its equivalent string representation using the specified format and culture-specific format information. + /// A numeric format string. + /// An object that supplies culture-specific formatting information. + /// The string representation of the value of this instance as specified by format and provider. + public string ToString(string format, IFormatProvider provider) => ((float)this).ToString(format, provider); + + public object ToType(Type conversionType, IFormatProvider provider) => ((IConvertible)(float)this).ToType(conversionType, provider); + + public ushort ToUInt16(IFormatProvider provider) => Convert.ToUInt16((float)this, provider); + + public uint ToUInt32(IFormatProvider provider) => Convert.ToUInt32((float)this, provider); + + public ulong ToUInt64(IFormatProvider provider) => Convert.ToUInt64((float)this, provider); + + public bool Equals(Half other) + { + return _data == other._data; + } + + public override bool Equals(object obj) + { + return obj is Half other && Equals(other); + } + + public override int GetHashCode() + { + return _data.GetHashCode(); + } + + #region Operators + + public static bool operator ==(Half left, Half right) => left._data == right._data; + + public static bool operator !=(Half left, Half right) => left._data != right._data; + + public static bool operator <(Half left, Half right) + { + LessThan_Impl(left, right, out bool result); + return result; + } + + public static bool operator <=(Half left, Half right) + { + LessThanOrEqual_Impl(left, right, out bool result); + return result; + } + public static bool operator >(Half left, Half right) + { + GreaterThan_Impl(left, right, out bool result); + return result; + } + + public static bool operator >=(Half left, Half right) + { + GreaterThanOrEqual_Impl(left, right, out bool result); + return result; + } + + public static Half operator +(Half value) => value; + + public static Half operator -(Half value) + { + Negate_Impl(value, out Half result); + return result; + } + + public static Half operator +(Half left, Half right) + { + Add_Impl(left, right, out Half result); + return result; + } + + public static Half operator -(Half left, Half right) + { + Subtract_Impl(left, right, out Half result); + return result; + } + + public static Half operator *(Half left, Half right) + { + Multiply_Impl(left, right, out Half result); + return result; + } + + public static Half operator /(Half left, Half right) + { + Divide_Impl(left, right, out Half result); + return result; + } + + public static Half operator %(Half left, Half right) + { + Modulo_Impl(left, right, out Half result); + return result; + } + + public static Half operator ++(Half value) + { + Increment_Impl(value, out Half result); + return result; + } + + public static Half operator --(Half value) + { + Decrement_Impl(value, out Half result); + return result; + } + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void LessThan_Impl(Half left, Half right, out bool result); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void LessThanOrEqual_Impl(Half left, Half right, out bool result); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void GreaterThan_Impl(Half left, Half right, out bool result); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void GreaterThanOrEqual_Impl(Half left, Half right, out bool result); + + // Externe Methoden hier als Platzhalter + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void Add_Impl(Half left, Half right, out Half result); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void Subtract_Impl(Half left, Half right, out Half result); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void Multiply_Impl(Half left, Half right, out Half result); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void Divide_Impl(Half left, Half right, out Half result); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void Modulo_Impl(Half left, Half right, out Half result); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void Negate_Impl(Half value, out Half result); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void Increment_Impl(Half value, out Half result); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void Decrement_Impl(Half value, out Half result); + + #endregion + + #region Bindings + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void FromFloat32(float value, out Half halfValue); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void ToFloat32(Half value, out float floatValue); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern bool IsNegative_Impl(Half self); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern bool IsFinite_Impl(Half self); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern bool IsInfinity_Impl(Half self); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern bool IsNan_Impl(Half self); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern bool IsSubnormal_Impl(Half self); + + #endregion +} diff --git a/ScriptCore/Math/HalfVectors.cs b/ScriptCore/Math/HalfVectors.cs index da8ef70..47ca32e 100644 --- a/ScriptCore/Math/HalfVectors.cs +++ b/ScriptCore/Math/HalfVectors.cs @@ -1,5 +1,4 @@ using System; -using GlitchyEngine.Math; using GlitchyEngine.Math.Attributes; namespace GlitchyEngine.Math; diff --git a/ScriptCore/ScriptCore.csproj b/ScriptCore/ScriptCore.csproj index accd727..bd609d5 100644 --- a/ScriptCore/ScriptCore.csproj +++ b/ScriptCore/ScriptCore.csproj @@ -14,10 +14,6 @@ - - - -