1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 12:32:20 +02:00
Beef/BeefLibs/corlib/src/Float.bf
2022-02-15 14:30:11 -03:00

241 lines
5 KiB
Beef

using System.Globalization;
namespace System
{
#unwarn
struct Float : float, IFloating, ISigned, IFormattable, IHashable, IEquatable<float>, ICanBeNaN
{
public const float MinValue = (float)-3.40282346638528859e+38;
public const float Epsilon = (float)1.4e-45;
public const float MaxValue = (float)3.40282346638528859e+38;
public const float PositiveInfinity = 1.0f / 0.0f;
public const float NegativeInfinity = -1.0f / 0.0f;
public const float NaN = 0.0f / 0.0f;
// We use this explicit definition to avoid the confusion between 0.0 and -0.0.
public const float NegativeZero = (float)-0.0;
public static int operator<=>(Float a, Float b)
{
return (float)a <=> (float)b;
}
public static Float operator-(Float value)
{
return (float)value;
}
public static Self operator+(Self lhs, Self rhs)
{
return (SelfBase)lhs + (SelfBase)rhs;
}
public static Self operator-(Self lhs, Self rhs)
{
return (SelfBase)lhs - (SelfBase)rhs;
}
public static Self operator*(Self lhs, Self rhs)
{
return (SelfBase)lhs * (SelfBase)rhs;
}
public static Self operator/(Self lhs, Self rhs)
{
return (SelfBase)lhs / (SelfBase)rhs;
}
/*public bool IsNegative
{
get
{
return this < 0;
}
}*/
public int GetHashCode()
{
var val = (float)this;
return *(int32*)(&val);
}
public bool IsNegative
{
get
{
return this < 0;
}
}
public bool IsFinite
{
get
{
float val = (float)this;
return (*(int32*)(&val) & 0x7FFFFFFF) < 0x7F800000;
}
}
public bool IsInfinity
{
get
{
float val = (float)this;
return (*(int32*)(&val) & 0x7FFFFFFF) == 0x7F800000;
}
}
public bool IsPositiveInfinity
{
get
{
float val = (float)this;
return *(int32*)(&val) == 0x7F800000;
}
}
public bool IsNegativeInfinity
{
get
{
float val = (float)this;
return *(int32*)(&val) == (int32)0xFF800000;
}
}
public bool IsNaN
{
get
{
float val = (float)this;
return (*(int32*)(&val) & 0x7FFFFFFF) > 0x7F800000;
}
}
public bool IsSubnormal
{
get
{
float val = (float)this;
var bits = *(int32*)(&val);
bits &= 0x7FFFFFFF;
return (bits < 0x7F800000) && (bits != 0) && ((bits & 0x7F800000) == 0);
}
}
public bool Equals(float other)
{
return (float)this == other;
}
public int CompareTo(float value)
{
if ((float)this < value) return -1;
if ((float)this > value) return 1;
if ((float)this == value) return 0;
// At least one of the values is NaN.
if (IsNaN)
return (value.IsNaN ? 0 : -1);
else // f is NaN.
return 1;
}
[CallingConvention(.Stdcall), CLink]
static extern int32 ftoa(float val, char8* str);
static extern int32 ToString(float val, char8* str);
public override void ToString(String strBuffer)
{
char8[128] outBuff = ?;
//ftoa((float)this, &outBuff);
int len = ToString((float)this, &outBuff);
strBuffer.Append(&outBuff, len);
}
public void ToString(String outString, String format, IFormatProvider formatProvider)
{
if (format.IsEmpty)
{
ToString(outString);
return;
}
NumberFormatter.NumberToString(format, (float)this, formatProvider, outString);
}
public static Result<float> Parse(StringView val)
{
return Parse(val, NumberFormatInfo.CurrentInfo);
}
public static Result<float> Parse(StringView val, NumberFormatInfo info)
{
if (val.IsEmpty)
return .Err;
bool isNeg = val[0] == '-';
bool isPos = val[0] == '+';
double result = 0;
double decimalMultiplier = 0;
var val;
if (isNeg || isPos)
val.RemoveFromStart(1);
if (@val.Equals(info.NegativeInfinitySymbol, true))
return NegativeInfinity;
else if (val.Equals(info.PositiveInfinitySymbol, true))
return PositiveInfinity;
else if (val.Equals(info.NaNSymbol, true))
return NaN;
//TODO: Use Number.ParseNumber
for (int32 i = 0; i < val.Length; i++)
{
char8 c = val.Ptr[i];
//Exponent prefix used in scientific notation. E.g. 1.2E5
if ((c == 'e') || (c == 'E'))
{
//Error if there are no numbers after the prefix
if(i == val.Length - 1)
return .Err;
var exponent = Try!(int32.Parse(val.Substring(i + 1)));
result *= Math.Pow(10, (double)exponent);
break;
}
if (c == info.NumberDecimalSeparator[0])
{
if (decimalMultiplier != 0)
return .Err;
decimalMultiplier = 0.1;
continue;
}
if (decimalMultiplier != 0)
{
if ((c >= '0') && (c <= '9'))
{
result += (int32)(c - '0') * decimalMultiplier;
decimalMultiplier *= 0.1;
}
else
return .Err;
continue;
}
if ((c >= '0') && (c <= '9'))
{
result *= 10;
result += (int32)(c - '0');
}
else
return .Err;
}
return isNeg ? (float)(-result) : (float)result;
}
}
}