169 lines
7.3 KiB
C#
169 lines
7.3 KiB
C#
using System;
|
|
|
|
namespace Upsilon.BaseTypes.Number
|
|
{
|
|
public abstract class ScriptNumber : ScriptType
|
|
{
|
|
protected internal abstract bool IsFloat { get; }
|
|
|
|
public override TypeContainer Type => BaseTypes.Type.Number;
|
|
|
|
#region Binary Operators
|
|
|
|
public static ScriptNumber operator + (ScriptNumber a, ScriptNumber b)
|
|
{
|
|
if (!a.IsFloat && !b.IsFloat)
|
|
return new ScriptNumberLong(((ScriptNumberLong) a).Value + ((ScriptNumberLong) b).Value);
|
|
if (a.IsFloat && b.IsFloat)
|
|
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value + ((ScriptNumberDouble) b).Value);
|
|
if (a.IsFloat)
|
|
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value + ((ScriptNumberLong) b).Value);
|
|
return new ScriptNumberDouble(((ScriptNumberLong) a).Value + ((ScriptNumberDouble) b).Value);
|
|
}
|
|
|
|
public static ScriptNumber operator - (ScriptNumber a, ScriptNumber b)
|
|
{
|
|
if (!a.IsFloat && !b.IsFloat)
|
|
return new ScriptNumberLong(((ScriptNumberLong) a).Value - ((ScriptNumberLong) b).Value);
|
|
if (a.IsFloat && b.IsFloat)
|
|
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value - ((ScriptNumberDouble) b).Value);
|
|
if (a.IsFloat)
|
|
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value - ((ScriptNumberLong) b).Value);
|
|
return new ScriptNumberDouble(((ScriptNumberLong) a).Value - ((ScriptNumberDouble) b).Value);
|
|
}
|
|
|
|
public static ScriptNumber operator * (ScriptNumber a, ScriptNumber b)
|
|
{
|
|
if (!a.IsFloat && !b.IsFloat)
|
|
return new ScriptNumberLong(((ScriptNumberLong) a).Value * ((ScriptNumberLong) b).Value);
|
|
if (a.IsFloat && b.IsFloat)
|
|
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value * ((ScriptNumberDouble) b).Value);
|
|
if (a.IsFloat)
|
|
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value * ((ScriptNumberLong) b).Value);
|
|
return new ScriptNumberDouble(((ScriptNumberLong) a).Value * ((ScriptNumberDouble) b).Value);
|
|
}
|
|
|
|
public static ScriptNumber operator % (ScriptNumber a, ScriptNumber b)
|
|
{
|
|
if (!a.IsFloat && !b.IsFloat)
|
|
return new ScriptNumberLong(((ScriptNumberLong) a).Value % ((ScriptNumberLong) b).Value);
|
|
if (a.IsFloat && b.IsFloat)
|
|
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value % ((ScriptNumberDouble) b).Value);
|
|
if (a.IsFloat)
|
|
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value % ((ScriptNumberLong) b).Value);
|
|
return new ScriptNumberDouble(((ScriptNumberLong) a).Value % ((ScriptNumberDouble) b).Value);
|
|
}
|
|
|
|
public static ScriptNumber operator / (ScriptNumber a, ScriptNumber b)
|
|
{
|
|
if (!a.IsFloat && !b.IsFloat)
|
|
return new ScriptNumberDouble(((ScriptNumberLong) a).Value / (double)((ScriptNumberLong) b).Value);
|
|
if (a.IsFloat && b.IsFloat)
|
|
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value / ((ScriptNumberDouble) b).Value);
|
|
if (a.IsFloat)
|
|
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value / ((ScriptNumberLong) b).Value);
|
|
return new ScriptNumberDouble(((ScriptNumberLong) a).Value / ((ScriptNumberDouble) b).Value);
|
|
}
|
|
#endregion
|
|
|
|
public static ScriptNumber operator - (ScriptNumber n)
|
|
{
|
|
if (n.IsFloat)
|
|
return new ScriptNumberDouble(-((ScriptNumberDouble)n).Value);
|
|
return new ScriptNumberLong(-((ScriptNumberLong)n).Value);
|
|
}
|
|
|
|
public static ScriptNumber Exponent(ScriptNumber a, ScriptNumber b)
|
|
{
|
|
if (!a.IsFloat && !b.IsFloat)
|
|
return new ScriptNumberLong((long) Math.Pow(((ScriptNumberLong) a).Value, ((ScriptNumberLong) b).Value));
|
|
if (a.IsFloat && b.IsFloat)
|
|
return new ScriptNumberDouble(Math.Pow(((ScriptNumberDouble) a).Value, ((ScriptNumberDouble) b).Value));
|
|
if (a.IsFloat)
|
|
return new ScriptNumberDouble(Math.Pow(((ScriptNumberDouble) a).Value, ((ScriptNumberLong) b).Value));
|
|
return new ScriptNumberDouble(Math.Pow(((ScriptNumberLong) a).Value, ((ScriptNumberDouble) b).Value));
|
|
}
|
|
|
|
|
|
|
|
#region Equality
|
|
private bool Equals(ScriptNumber other)
|
|
{
|
|
if (!IsFloat && !other.IsFloat)
|
|
return ((ScriptNumberLong) this).Value.Equals(((ScriptNumberLong) other).Value);
|
|
if (IsFloat && other.IsFloat)
|
|
return ((ScriptNumberDouble) this).Value.Equals(((ScriptNumberDouble) other).Value);
|
|
return false;
|
|
}
|
|
|
|
#pragma warning disable 659
|
|
public override bool Equals(object obj)
|
|
#pragma warning restore 659
|
|
{
|
|
if (ReferenceEquals(null, obj)) return false;
|
|
if (ReferenceEquals(this, obj)) return true;
|
|
if (IsFloat && obj is double d)
|
|
{
|
|
return Math.Abs(((ScriptNumberDouble) this).Value - d) < 0.0000001;
|
|
}
|
|
if (!IsFloat && obj is long l)
|
|
{
|
|
return ((ScriptNumberLong) this).Value == l;
|
|
}
|
|
|
|
if (obj.GetType() != this.GetType()) return false;
|
|
return Equals((ScriptNumber) obj);
|
|
}
|
|
|
|
#endregion
|
|
|
|
public static ScriptBoolean operator < (ScriptNumber a, ScriptNumber b)
|
|
{
|
|
if (!a.IsFloat && !b.IsFloat)
|
|
return new ScriptBoolean(((ScriptNumberLong) a).Value < ((ScriptNumberLong) b).Value);
|
|
if (a.IsFloat && b.IsFloat)
|
|
return new ScriptBoolean(((ScriptNumberDouble) a).Value < ((ScriptNumberDouble) b).Value);
|
|
if (a.IsFloat)
|
|
return new ScriptBoolean(((ScriptNumberDouble) a).Value < ((ScriptNumberLong) b).Value);
|
|
return new ScriptBoolean(((ScriptNumberLong) a).Value < ((ScriptNumberDouble) b).Value);
|
|
}
|
|
|
|
public static ScriptBoolean operator > (ScriptNumber a, ScriptNumber b)
|
|
{
|
|
if (!a.IsFloat && !b.IsFloat)
|
|
return new ScriptBoolean(((ScriptNumberLong) a).Value > ((ScriptNumberLong) b).Value);
|
|
if (a.IsFloat && b.IsFloat)
|
|
return new ScriptBoolean(((ScriptNumberDouble) a).Value > ((ScriptNumberDouble) b).Value);
|
|
if (a.IsFloat)
|
|
return new ScriptBoolean(((ScriptNumberDouble) a).Value > ((ScriptNumberLong) b).Value);
|
|
return new ScriptBoolean(((ScriptNumberLong) a).Value > ((ScriptNumberDouble) b).Value);
|
|
}
|
|
|
|
public static ScriptBoolean operator <= (ScriptNumber a, ScriptNumber b)
|
|
{
|
|
return (a < b) || a.Equals(b);
|
|
}
|
|
|
|
public static ScriptBoolean operator >= (ScriptNumber a, ScriptNumber b)
|
|
{
|
|
return !(a < b) || a.Equals(b);
|
|
}
|
|
|
|
|
|
|
|
|
|
public static explicit operator double(ScriptNumber n)
|
|
{
|
|
if (n.IsFloat)
|
|
return ((ScriptNumberDouble) n);
|
|
return ((ScriptNumberLong) n).Value;
|
|
}
|
|
|
|
public static explicit operator long(ScriptNumber n)
|
|
{
|
|
if (n.IsFloat)
|
|
return (long)((ScriptNumberDouble) n).Value;
|
|
return ((ScriptNumberLong) n).Value;
|
|
}
|
|
}
|
|
} |