namespace Upsilon.BaseTypes.Number { internal abstract class Number : LuaType { protected abstract bool IsFloat { get; } public override Type Type => Type.Number; #region Binary Operators public static Number operator + (Number a, Number b) { if (!a.IsFloat && !b.IsFloat) return new NumberLong(((NumberLong) a).Value + ((NumberLong) b).Value); if (a.IsFloat && b.IsFloat) return new NumberDouble(((NumberDouble) a).Value + ((NumberDouble) b).Value); if (a.IsFloat) return new NumberDouble(((NumberDouble) a).Value + ((NumberLong) b).Value); return new NumberDouble(((NumberLong) a).Value + ((NumberDouble) b).Value); } public static Number operator - (Number a, Number b) { if (!a.IsFloat && !b.IsFloat) return new NumberLong(((NumberLong) a).Value - ((NumberLong) b).Value); if (a.IsFloat && b.IsFloat) return new NumberDouble(((NumberDouble) a).Value - ((NumberDouble) b).Value); if (a.IsFloat) return new NumberDouble(((NumberDouble) a).Value - ((NumberLong) b).Value); return new NumberDouble(((NumberLong) a).Value - ((NumberDouble) b).Value); } public static Number operator * (Number a, Number b) { if (!a.IsFloat && !b.IsFloat) return new NumberLong(((NumberLong) a).Value * ((NumberLong) b).Value); if (a.IsFloat && b.IsFloat) return new NumberDouble(((NumberDouble) a).Value * ((NumberDouble) b).Value); if (a.IsFloat) return new NumberDouble(((NumberDouble) a).Value * ((NumberLong) b).Value); return new NumberDouble(((NumberLong) a).Value * ((NumberDouble) b).Value); } public static Number operator / (Number a, Number b) { if (!a.IsFloat && !b.IsFloat) return new NumberLong(((NumberLong) a).Value / ((NumberLong) b).Value); if (a.IsFloat && b.IsFloat) return new NumberDouble(((NumberDouble) a).Value / ((NumberDouble) b).Value); if (a.IsFloat) return new NumberDouble(((NumberDouble) a).Value / ((NumberLong) b).Value); return new NumberDouble(((NumberLong) a).Value / ((NumberDouble) b).Value); } #endregion public static Number operator - (Number n) { if (n.IsFloat) return new NumberDouble(-((NumberDouble)n).Value); return new NumberLong(-((NumberLong)n).Value); } #region Equality private bool Equals(Number other) { if (!IsFloat && !other.IsFloat) return ((NumberLong) this).Value.Equals(((NumberLong) other).Value); if (IsFloat && other.IsFloat) return ((NumberDouble) this).Value.Equals(((NumberDouble) 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 (obj.GetType() != this.GetType()) return false; return Equals((Number) obj); } #endregion public static explicit operator double(Number n) { if (n.IsFloat) return ((NumberDouble) n); return ((NumberLong) n).Value; } public static explicit operator long(Number n) { if (n.IsFloat) return (long)((NumberDouble) n).Value; return ((NumberLong) n).Value; } } }