Create bare godot project
This commit is contained in:
386
FixPoint/FixPoint16Long.cs
Normal file
386
FixPoint/FixPoint16Long.cs
Normal file
@@ -0,0 +1,386 @@
|
||||
#if DEBUG
|
||||
#define RANGE_CHECK
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MagmaEngine.Math;
|
||||
|
||||
public struct FixPoint16Long : IComparable, IComparable<FixPoint16Long>, IEquatable<FixPoint16Long>
|
||||
{
|
||||
public FixPoint16Long(FixPoint16Long other)
|
||||
{
|
||||
m_Value = other.m_Value;
|
||||
}
|
||||
|
||||
public FixPoint16Long(int value)
|
||||
{
|
||||
m_Value = (long)value << c_Shift;
|
||||
}
|
||||
|
||||
public FixPoint16Long(long value)
|
||||
{
|
||||
#if RANGE_CHECK
|
||||
if (value < c_IntegerMin || value > c_IntegerMax)
|
||||
{
|
||||
throw new ArithmeticException($"Long to FixPoint argument out of range: {value}");
|
||||
}
|
||||
#endif
|
||||
m_Value = value << c_Shift;
|
||||
}
|
||||
|
||||
public FixPoint16Long(double value)
|
||||
{
|
||||
#if RANGE_CHECK
|
||||
if (value < c_IntegerMin || value > c_IntegerMax)
|
||||
{
|
||||
throw new ArithmeticException($"Double to FixPoint argument out of range: {value}");
|
||||
}
|
||||
#endif
|
||||
if (value < 0.0)
|
||||
{
|
||||
m_Value = (int)((value * c_Multiplier) - 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Value = (int)((value * c_Multiplier) + 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
public FixPoint16Long(float value)
|
||||
{
|
||||
#if RANGE_CHECK
|
||||
if (value < c_IntegerMin || value > c_IntegerMax)
|
||||
{
|
||||
throw new ArithmeticException($"Single to FixPoint argument out of range: {value}");
|
||||
}
|
||||
#endif
|
||||
if (value < 0.0f)
|
||||
{
|
||||
m_Value = (int)((value * c_MultiplierFloat) - 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Value = (int)((value * c_MultiplierFloat) + 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
public long ToLongFloor()
|
||||
{
|
||||
return m_Value >> c_Shift;
|
||||
}
|
||||
|
||||
public long ToLongCeil()
|
||||
{
|
||||
return (m_Value + c_FractionMask) >> c_Shift;
|
||||
}
|
||||
|
||||
public long ToLongRound()
|
||||
{
|
||||
if (m_Value < 0)
|
||||
{
|
||||
return -((-m_Value + c_Half) >> c_Shift);
|
||||
}
|
||||
|
||||
return (m_Value + c_Half) >> c_Shift;
|
||||
}
|
||||
|
||||
public long ToLong()
|
||||
{
|
||||
if (m_Value < 0)
|
||||
{
|
||||
return -(-m_Value >> c_Shift);
|
||||
}
|
||||
|
||||
return m_Value >> c_Shift;
|
||||
}
|
||||
|
||||
public double ToDouble()
|
||||
{
|
||||
return c_Divisor * m_Value;
|
||||
}
|
||||
|
||||
public float ToFloat()
|
||||
{
|
||||
return c_DivisorFloat * m_Value;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{ToDouble()}[0x{m_Value:x16}]";
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return m_Value.GetHashCode();
|
||||
}
|
||||
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
if (obj is not FixPoint16Long other)
|
||||
return -1;
|
||||
|
||||
return m_Value.CompareTo(other.m_Value);
|
||||
}
|
||||
|
||||
public int CompareTo(FixPoint16Long other)
|
||||
{
|
||||
return m_Value.CompareTo(other.m_Value);
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((FixPoint16Long)obj).m_Value == m_Value;
|
||||
}
|
||||
|
||||
public bool Equals(FixPoint16Long other)
|
||||
{
|
||||
return other.m_Value == m_Value;
|
||||
}
|
||||
|
||||
public bool IsZero()
|
||||
{
|
||||
return m_Value == 0L;
|
||||
}
|
||||
|
||||
public static bool operator ==(FixPoint16Long a, FixPoint16Long b)
|
||||
{
|
||||
return a.m_Value == b.m_Value;
|
||||
}
|
||||
|
||||
public static bool operator !=(FixPoint16Long a, FixPoint16Long b)
|
||||
{
|
||||
return a.m_Value != b.m_Value;
|
||||
}
|
||||
|
||||
public static bool operator <(FixPoint16Long a, FixPoint16Long b)
|
||||
{
|
||||
return a.m_Value < b.m_Value;
|
||||
}
|
||||
|
||||
public static bool operator >(FixPoint16Long a, FixPoint16Long b)
|
||||
{
|
||||
return a.m_Value > b.m_Value;
|
||||
}
|
||||
|
||||
public static bool operator <=(FixPoint16Long a, FixPoint16Long b)
|
||||
{
|
||||
return a.m_Value <= b.m_Value;
|
||||
}
|
||||
|
||||
public static bool operator >=(FixPoint16Long a, FixPoint16Long b)
|
||||
{
|
||||
return a.m_Value >= b.m_Value;
|
||||
}
|
||||
|
||||
public static FixPoint16Long operator <<(FixPoint16Long a, int shift)
|
||||
{
|
||||
return new() { m_Value = a.m_Value << shift };
|
||||
}
|
||||
|
||||
public static FixPoint16Long operator >> (FixPoint16Long a, int shift)
|
||||
{
|
||||
return new() { m_Value = a.m_Value >> shift };
|
||||
}
|
||||
|
||||
public static FixPoint16Long operator +(FixPoint16Long a, FixPoint16Long b)
|
||||
{
|
||||
return new() { m_Value = a.m_Value + b.m_Value };
|
||||
}
|
||||
|
||||
public static FixPoint16Long operator -(FixPoint16Long a, FixPoint16Long b)
|
||||
{
|
||||
return new() { m_Value = a.m_Value - b.m_Value };
|
||||
}
|
||||
|
||||
public static FixPoint16Long operator *(FixPoint16Long a, FixPoint16Long b)
|
||||
{
|
||||
Int128 bigA = a.m_Value;
|
||||
Int128 bigB = b.m_Value;
|
||||
var result = ((bigA * bigB) + c_Half) >> c_Shift;
|
||||
#if RANGE_CHECK
|
||||
if (result < long.MinValue || result > long.MaxValue)
|
||||
{
|
||||
throw new ArithmeticException($"Multiplication result out of range: {result}");
|
||||
}
|
||||
#endif
|
||||
return new() { m_Value = (long)result };
|
||||
}
|
||||
|
||||
public static FixPoint16Long operator /(FixPoint16Long a, FixPoint16Long b)
|
||||
{
|
||||
#if RANGE_CHECK
|
||||
if (b.m_Value == 0)
|
||||
{
|
||||
throw new ArithmeticException("Divison by zero");
|
||||
}
|
||||
#endif
|
||||
Int128 result;
|
||||
|
||||
if (((ulong)a.m_Value & 0x8000000000000000UL) == ((ulong)b.m_Value & 0x8000000000000000UL))
|
||||
{
|
||||
result = (((Int128)a.m_Value << c_Shift) + (b.m_Value / 2)) / b.m_Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (((Int128)a.m_Value << c_Shift) - (b.m_Value / 2)) / b.m_Value;
|
||||
}
|
||||
#if RANGE_CHECK
|
||||
if (result < long.MinValue || result > long.MaxValue)
|
||||
{
|
||||
throw new ArithmeticException($"Division result out of range: {result}");
|
||||
}
|
||||
#endif
|
||||
return new() { m_Value = (long)result };
|
||||
}
|
||||
|
||||
public static FixPoint16Long operator -(FixPoint16Long a)
|
||||
{
|
||||
return new() { m_Value = -a.m_Value };
|
||||
}
|
||||
|
||||
public static FixPoint16Long operator *(FixPoint16Long a, int value)
|
||||
{
|
||||
return new() { m_Value = a.m_Value * value };
|
||||
}
|
||||
|
||||
public static FixPoint16Long operator /(FixPoint16Long a, int value)
|
||||
{
|
||||
#if RANGE_CHECK
|
||||
if (value == 0)
|
||||
{
|
||||
throw new ArithmeticException("Divison by zero");
|
||||
}
|
||||
#endif
|
||||
if (((a.m_Value >> 32) & 0x80000000) == (value & 0x80000000))
|
||||
{
|
||||
return new() { m_Value = (long)(((Int128)a.m_Value + (value / 2)) / value) };
|
||||
}
|
||||
|
||||
return new() { m_Value = (long)(((Int128)a.m_Value - (value / 2)) / value) };
|
||||
}
|
||||
|
||||
public static implicit operator FixPoint16Long(int value)
|
||||
{
|
||||
return new(value);
|
||||
}
|
||||
|
||||
public static implicit operator FixPoint16Long(long value)
|
||||
{
|
||||
return new(value);
|
||||
}
|
||||
|
||||
public static implicit operator FixPoint16Long(FixPoint16 value)
|
||||
{
|
||||
return new() { m_Value = value.m_Value };
|
||||
}
|
||||
|
||||
public static explicit operator FixPoint16Long(double value)
|
||||
{
|
||||
return new(value);
|
||||
}
|
||||
|
||||
public static explicit operator FixPoint16Long(float value)
|
||||
{
|
||||
return new(value);
|
||||
}
|
||||
|
||||
public static explicit operator int(FixPoint16Long value)
|
||||
{
|
||||
return (int)value.ToLong();
|
||||
}
|
||||
|
||||
public static explicit operator long(FixPoint16Long value)
|
||||
{
|
||||
return value.ToLong();
|
||||
}
|
||||
|
||||
public static explicit operator double(FixPoint16Long value)
|
||||
{
|
||||
return value.ToDouble();
|
||||
}
|
||||
|
||||
public static explicit operator float(FixPoint16Long value)
|
||||
{
|
||||
return value.ToFloat();
|
||||
}
|
||||
|
||||
public static FixPoint16Long Floor(FixPoint16Long value)
|
||||
{
|
||||
return value.ToLongFloor();
|
||||
}
|
||||
|
||||
public static FixPoint16Long Ceil(FixPoint16Long value)
|
||||
{
|
||||
return value.ToLongCeil();
|
||||
}
|
||||
|
||||
public static FixPoint16Long Round(FixPoint16Long value)
|
||||
{
|
||||
return value.ToLongRound();
|
||||
}
|
||||
|
||||
public static int Sign(FixPoint16Long value)
|
||||
{
|
||||
return System.Math.Sign(value.m_Value);
|
||||
}
|
||||
|
||||
public static FixPoint16Long Abs(FixPoint16Long value)
|
||||
{
|
||||
return new() { m_Value = System.Math.Abs(value.m_Value) };
|
||||
}
|
||||
|
||||
public static FixPoint16Long Min(FixPoint16Long value1, FixPoint16Long value2)
|
||||
{
|
||||
return new() { m_Value = System.Math.Min(value1.m_Value, value2.m_Value) };
|
||||
}
|
||||
|
||||
public static FixPoint16Long Max(FixPoint16Long value1, FixPoint16Long value2)
|
||||
{
|
||||
return new() { m_Value = System.Math.Max(value1.m_Value, value2.m_Value) };
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static FixPoint16Long Length(FixPoint16Long a, FixPoint16Long b)
|
||||
{
|
||||
var aSquared = a.m_Value * a.m_Value;
|
||||
var bSquared = b.m_Value * b.m_Value;
|
||||
var value = aSquared + bSquared;
|
||||
#if RANGE_CHECK
|
||||
if (value < 0)
|
||||
{
|
||||
throw new ArithmeticException($"Length squared out of range: {value}");
|
||||
}
|
||||
#endif
|
||||
|
||||
return new() { m_Value = IntMath.Sqrt(value) };
|
||||
}
|
||||
|
||||
private const int c_Shift = 16;
|
||||
private const long c_IntegerMin = -140737488355327L;
|
||||
private const long c_IntegerMax = 140737488355327L;
|
||||
private const long c_Half = 32786L;
|
||||
private const long c_FractionMask = 0x000000000000ffffL;
|
||||
private const double c_Multiplier = 65536.0;
|
||||
private const double c_Divisor = 1.0 / 65536.0;
|
||||
private const float c_MultiplierFloat = 65536.0f;
|
||||
private const float c_DivisorFloat = (float)c_Divisor;
|
||||
|
||||
public long m_Value;
|
||||
|
||||
public static readonly FixPoint16Long Zero = new() { m_Value = 0 };
|
||||
public static readonly FixPoint16Long MinValue = new() { m_Value = long.MinValue };
|
||||
public static readonly FixPoint16Long MaxValue = new() { m_Value = long.MaxValue };
|
||||
public static readonly FixPoint16Long Epsilon = new() { m_Value = 1 };
|
||||
public static readonly FixPoint16Long MinusEpsilon = new() { m_Value = -1 };
|
||||
public static readonly FixPoint16Long One = new(1);
|
||||
public static readonly FixPoint16Long MinusOne = new(-1);
|
||||
public static readonly FixPoint16Long Half = new() { m_Value = One.m_Value / 2 };
|
||||
public static readonly FixPoint16Long MinusHalf = -Half;
|
||||
}
|
||||
Reference in New Issue
Block a user