using System; using System.Diagnostics; namespace HeuristicLab.Problems.DataAnalysis.Symbolic { // algebraic type wrapper for a double value [DebuggerDisplay("{Value}")] public sealed class AlgebraicDouble : IComparableAlgebraicType { public static implicit operator AlgebraicDouble(double value) { return new AlgebraicDouble(value); } public static implicit operator double(AlgebraicDouble value) { return value.Value; } public double Value; [DebuggerBrowsable(DebuggerBrowsableState.Never)] public AlgebraicDouble Zero => new AlgebraicDouble(0.0); [DebuggerBrowsable(DebuggerBrowsableState.Never)] public AlgebraicDouble One => new AlgebraicDouble(1.0); public bool IsInfinity => IsNegativeInfinity || IsPositiveInfinity; public bool IsNegativeInfinity => double.IsNegativeInfinity(Value); public bool IsPositiveInfinity => double.IsPositiveInfinity(Value); public AlgebraicDouble() { } public AlgebraicDouble(double value) { this.Value = value; } public AlgebraicDouble Assign(AlgebraicDouble a) { Value = a.Value; return this; } public AlgebraicDouble Add(AlgebraicDouble a) { Value += a.Value; return this; } public AlgebraicDouble Sub(AlgebraicDouble a) { Value -= a.Value; return this; } public AlgebraicDouble Mul(AlgebraicDouble a) { Value *= a.Value; return this; } public AlgebraicDouble Div(AlgebraicDouble a) { Value /= a.Value; return this; } public AlgebraicDouble Scale(double s) { Value *= s; return this; } public AlgebraicDouble AssignInv(AlgebraicDouble a) { Value = 1.0 / a.Value; return this; } public AlgebraicDouble AssignNeg(AlgebraicDouble a) { Value = -a.Value; return this; } public AlgebraicDouble AssignSin(AlgebraicDouble a) { Value = Math.Sin(a.Value); return this; } public AlgebraicDouble AssignCos(AlgebraicDouble a) { Value = Math.Cos(a.Value); return this; } public AlgebraicDouble AssignTanh(AlgebraicDouble a) { Value = Math.Tanh(a.Value); return this; } public AlgebraicDouble AssignLog(AlgebraicDouble a) { Value = Math.Log(a.Value); return this; } public AlgebraicDouble AssignExp(AlgebraicDouble a) { Value = Math.Exp(a.Value); return this; } public AlgebraicDouble AssignIntPower(AlgebraicDouble a, int p) { Value = Math.Pow(a.Value, p); return this; } public AlgebraicDouble AssignIntRoot(AlgebraicDouble a, int r) { Value = IntRoot(a.Value, r); return this; } //public AlgebraicDouble AssignMin(AlgebraicDouble other) { Value = Math.Min(Value, other.Value); return this; } //public AlgebraicDouble AssignMax(AlgebraicDouble other) { Value = Math.Max(Value, other.Value); return this; } public AlgebraicDouble AssignAbs(AlgebraicDouble a) { Value = Math.Abs(a.Value); return this; } public AlgebraicDouble AssignSgn(AlgebraicDouble a) { Value = double.IsNaN(a.Value) ? double.NaN : Math.Sign(a.Value); return this; } // helper private static double IntRoot(double value, int r) { if (r % 2 == 0) return Math.Pow(value, 1.0 / r); else return value < 0 ? -Math.Pow(-value, 1.0 / r) : Math.Pow(value, 1.0 / r); } public AlgebraicDouble Clone() { return new AlgebraicDouble(Value); } public override string ToString() { return Value.ToString(); } public int CompareTo(AlgebraicDouble other) { return Value.CompareTo(other.Value); } } }