< Summary

Class:Towel.Mathematics.Symbolics
Assembly:Towel
File(s):File 1: /home/runner/work/Towel/Towel/Sources/Towel/Mathematics/Symbolics.cs
Covered lines:490
Uncovered lines:1290
Coverable lines:1780
Total lines:3862
Line coverage:27.5% (490 of 1780)
Covered branches:197
Total branches:891
Branch coverage:22.1% (197 of 891)

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: .ctor(...)37.5%836.36%
File 1: get_Representations()100%1100%
File 1: .ctor(...)100%1100%
File 1: .ctor(...)100%1100%
File 1: .ctor(...)100%1100%
File 1: .ctor(...)100%1100%
File 1: .ctor(...)100%1100%
File 1: Simplify()100%1100%
File 1: Substitute(...)100%10%
File 1: Substitute(...)100%10%
File 1: SubstitutionHack(...)100%10%
File 1: Derive(...)100%10%
File 1: Integrate(...)100%10%
File 1: op_UnaryNegation(...)100%1100%
File 1: op_Addition(...)100%1100%
File 1: op_Subtraction(...)100%1100%
File 1: op_Multiply(...)100%1100%
File 1: op_Division(...)100%1100%
File 1: op_Equality(...)100%10%
File 1: op_Inequality(...)100%10%
File 1: op_LessThan(...)100%10%
File 1: op_GreaterThan(...)100%10%
File 1: op_ExclusiveOr(...)100%10%
File 1: get_Name()100%10%
File 1: .ctor(...)100%10%
File 1: Clone()100%10%
File 1: Substitute(...)0%20%
File 1: ToString()100%10%
File 1: Equals(...)0%20%
File 1: GetHashCode()100%10%
File 1: get_IsKnownConstant()100%1100%
File 1: get_IsZero()100%10%
File 1: get_IsOne()100%10%
File 1: get_IsTwo()100%10%
File 1: get_IsThree()100%10%
File 1: get_IsPi()100%10%
File 1: Simplify(...)100%10%
File 1: .cctor()100%10%
File 1: BuildGeneric(...)0%40%
File 1: get_IsKnownConstant()100%10%
File 1: .ctor()100%1100%
File 1: get_IsPi()100%10%
File 1: get_IsNegative()100%10%
File 1: ApplyType()100%1100%
File 1: Clone()100%10%
File 1: ToString()100%10%
File 1: Equals(...)0%20%
File 1: GetHashCode()100%10%
File 1: .cctor()100%10%
File 1: .ctor()100%10%
File 1: get_IsZero()100%10%
File 1: get_IsNegative()100%10%
File 1: ApplyType()100%10%
File 1: Clone()100%10%
File 1: ToString()100%10%
File 1: Equals(...)0%20%
File 1: .cctor()100%10%
File 1: GetHashCode()100%10%
File 1: .ctor()100%10%
File 1: get_IsOne()100%10%
File 1: get_IsNegative()100%10%
File 1: ApplyType()100%10%
File 1: Clone()100%10%
File 1: ToString()100%10%
File 1: Equals(...)0%20%
File 1: .cctor()100%10%
File 1: GetHashCode()100%10%
File 1: .ctor()100%10%
File 1: get_IsTwo()100%10%
File 1: get_IsNegative()100%10%
File 1: ApplyType()100%10%
File 1: Clone()100%10%
File 1: ToString()100%10%
File 1: Equals(...)0%20%
File 1: .cctor()100%10%
File 1: GetHashCode()100%10%
File 1: .ctor()100%10%
File 1: get_IsThree()100%10%
File 1: get_IsNegative()100%10%
File 1: ApplyType()100%10%
File 1: Clone()100%10%
File 1: ToString()100%10%
File 1: Equals(...)0%20%
File 1: .cctor()100%10%
File 1: GetHashCode()100%10%
File 1: get_IsZero()100%1100%
File 1: get_IsOne()100%10%
File 1: get_IsTwo()100%10%
File 1: get_IsThree()100%10%
File 1: get_IsNegative()100%1100%
File 1: .ctor(...)100%1100%
File 1: Simplify(...)100%1100%
File 1: Clone()100%1100%
File 1: ToString()50%2100%
File 1: Equals(...)50%283.33%
File 1: .cctor()100%10%
File 1: GetHashCode()100%10%
File 1: get_IsKnownConstant()100%10%
File 1: .ctor(...)100%1100%
File 1: .ctor()100%1100%
File 1: get_IsPi()100%10%
File 1: Clone()100%1100%
File 1: ToString()100%10%
File 1: Equals(...)0%20%
File 1: .cctor()100%10%
File 1: GetHashCode()100%10%
File 1: .ctor()100%10%
File 1: get_IsZero()100%10%
File 1: Clone()100%10%
File 1: ToString()100%10%
File 1: Equals(...)0%20%
File 1: .cctor()100%10%
File 1: GetHashCode()100%10%
File 1: .ctor()100%10%
File 1: get_IsOne()100%10%
File 1: Clone()100%10%
File 1: ToString()100%10%
File 1: Equals(...)0%20%
File 1: .cctor()100%10%
File 1: GetHashCode()100%10%
File 1: .ctor()100%10%
File 1: get_IsTwo()100%10%
File 1: Clone()100%10%
File 1: ToString()100%10%
File 1: Equals(...)0%20%
File 1: .cctor()100%10%
File 1: GetHashCode()100%10%
File 1: .ctor()100%10%
File 1: get_IsThree()100%10%
File 1: Clone()100%10%
File 1: ToString()100%10%
File 1: Equals(...)0%20%
File 1: .cctor()100%10%
File 1: GetHashCode()100%10%
File 1: .ctor()100%10%
File 1: Clone()100%10%
File 1: ToString()100%10%
File 1: Equals(...)0%20%
File 1: .cctor()100%10%
File 1: GetHashCode()100%10%
File 1: .ctor()100%10%
File 1: Clone()100%10%
File 1: ToString()100%10%
File 1: Equals(...)0%20%
File 1: .cctor()100%10%
File 1: GetHashCode()100%10%
File 1: Simplify(...)100%10%
File 1: SimplifyHack(...)100%1100%
File 1: get_A()100%1100%
File 1: .ctor(...)100%1100%
File 1: Equals(...)50%483.33%
File 1: .ctor(...)100%10%
File 1: Simplify()100%10%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%20%
File 1: .ctor(...)100%1100%
File 1: Simplify()0%20%
File 1: Simplify(...)0%20%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()37.5%866.66%
File 1: .ctor(...)100%10%
File 1: Simplify()0%20%
File 1: Simplify(...)0%20%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%20%
File 1: .ctor(...)100%10%
File 1: Simplify()0%20%
File 1: Simplify(...)0%20%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%20%
File 1: .ctor(...)100%10%
File 1: Simplify()0%20%
File 1: Simplify(...)0%20%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%20%
File 1: .ctor(...)100%1100%
File 1: Simplify()0%20%
File 1: Simplify(...)0%20%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()50%462.5%
File 1: .ctor(...)100%10%
File 1: Simplify()0%20%
File 1: Simplify(...)0%20%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%20%
File 1: .ctor(...)100%10%
File 1: .ctor(...)100%10%
File 1: Simplify()100%10%
File 1: Simplify(...)100%10%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%20%
File 1: .ctor(...)100%10%
File 1: Simplify()100%10%
File 1: Simplify(...)100%10%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%20%
File 1: .ctor(...)100%10%
File 1: Simplify()100%10%
File 1: Simplify(...)100%10%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%20%
File 1: .ctor(...)100%10%
File 1: Simplify()100%10%
File 1: Simplify(...)100%10%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%20%
File 1: .ctor(...)100%10%
File 1: Simplify()100%10%
File 1: Simplify(...)100%10%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%20%
File 1: .ctor(...)100%10%
File 1: Simplify()100%10%
File 1: Simplify(...)100%10%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%20%
File 1: get_A()100%1100%
File 1: get_B()100%1100%
File 1: .ctor(...)100%1100%
File 1: Equals(...)50%683.33%
File 1: .ctor(...)100%1100%
File 1: .ctor(...)100%1100%
File 1: Simplify()0%600%
File 1: Simplify(...)0%40%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()77.27%2277.27%
File 1: .ctor(...)100%1100%
File 1: Simplify()0%600%
File 1: Simplify(...)0%40%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()100%12100%
File 1: .ctor(...)100%1100%
File 1: .ctor(...)100%1100%
File 1: Simplify()2.27%888.08%
File 1: Simplify(...)50%483.33%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()81.25%1673.33%
File 1: .ctor(...)100%1100%
File 1: Simplify()5.12%7812.35%
File 1: Simplify(...)50%483.33%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()75%4100%
File 1: .ctor(...)100%10%
File 1: Simplify()0%160%
File 1: Simplify(...)0%40%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%80%
File 1: .ctor(...)100%10%
File 1: Simplify()0%40%
File 1: Simplify(...)0%40%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%40%
File 1: .ctor(...)100%10%
File 1: Simplify()0%40%
File 1: Simplify(...)0%40%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%40%
File 1: .ctor(...)100%10%
File 1: Simplify()0%40%
File 1: Simplify(...)0%40%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%40%
File 1: .ctor(...)100%10%
File 1: Simplify()0%40%
File 1: Simplify(...)0%40%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%40%
File 1: .ctor(...)100%10%
File 1: Simplify()0%40%
File 1: Simplify(...)0%40%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%40%
File 1: .ctor(...)100%10%
File 1: Simplify()0%40%
File 1: Simplify(...)0%40%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%40%
File 1: .ctor(...)100%10%
File 1: Simplify()0%40%
File 1: Simplify(...)0%40%
File 1: Clone()100%10%
File 1: Substitute(...)100%10%
File 1: ToString()0%40%
File 1: get_A()100%10%
File 1: get_B()100%10%
File 1: get_C()100%10%
File 1: .ctor(...)100%10%
File 1: Equals(...)0%80%
File 1: get_Operands()100%10%
File 1: .ctor(...)100%10%
File 1: .cctor()100%1100%
File 1: BuildParsableOperationLibrary()51.78%5656.09%
File 1: Parse(...)100%10%
File 1: ParseAndSimplifyToConstant(...)0%40%
File 1: Parse(...)77.77%1876.66%
File 1: TryParseNonNestedOperatorExpression(...)93.47%4696.87%
File 1: TryParseParenthesisExpression(...)60%1057.69%
File 1: TryParseOperationExpression(...)4.54%2213.04%
File 1: SplitOperands(...)0%120%
File 1: TryParseVariablesExpression(...)21.42%1428.2%
File 1: TryParseKnownConstantExpression(...)83.33%678.94%
File 1: TryParseConstantExpression(...)3.33%3011.11%

File(s)

/home/runner/work/Towel/Towel/Sources/Towel/Mathematics/Symbolics.cs

#LineLine coverage
 1using System.Linq.Expressions;
 2using System.Reflection;
 3using System.Text.RegularExpressions;
 4
 5namespace Towel.Mathematics;
 6
 7/// <summary>Contains definitions necessary for the generic Symbolics class.</summary>
 8public static class Symbolics
 9{
 10  #region OperatorPriority Enum
 11
 12  internal enum OperatorPriority
 13  {
 14#pragma warning disable CA1069 // Enums values should not be duplicated
 15#pragma warning disable SA1602 // Enumeration items should be documented
 16    Addition = 1,
 17    Subtraction = 1,
 18    Multiplication = 2,
 19    Division = 2,
 20    Exponents = 3,
 21    Roots = 3,
 22    Logical = 4,
 23    Negation = 5,
 24    Factorial = 6,
 25#pragma warning restore SA1602 // Enumeration items should be documented
 26#pragma warning restore CA1069 // Enums values should not be duplicated
 27  }
 28
 29  #endregion
 30
 31  #region Attributes
 32
 33  [AttributeUsage(AttributeTargets.Class)]
 34  internal abstract class RepresentationAttribute : Attribute
 35  {
 36    internal string[] _representations;
 37
 238    internal RepresentationAttribute(string a, params string[] b)
 239    {
 240      if (string.IsNullOrWhiteSpace(a))
 041      {
 042        throw new ArgumentException(
 043          "There is a BUG in " + nameof(Towel) + ". A " +
 044          nameof(Symbolics) + "." + nameof(RepresentationAttribute) + " representation is invalid.");
 45      }
 646      foreach (string @string in b)
 047      {
 048        if (string.IsNullOrWhiteSpace(@string))
 049        {
 050          throw new ArgumentException(
 051            "There is a BUG in " + nameof(Towel) + ". A " +
 052            nameof(Symbolics) + "." + nameof(RepresentationAttribute) + " representation is invalid.");
 53        }
 054      }
 255      _representations = new string[b.Length + 1];
 256      _representations[0] = a;
 657      for (int i = 1, j = 0; j < b.Length; i++, j++)
 058      {
 059        _representations[i] = b[j];
 060      }
 261    }
 62
 63    internal string[] Representations
 64    {
 65      get
 266      {
 267        return _representations;
 268      }
 69    }
 70  }
 71
 72  [AttributeUsage(AttributeTargets.Class)]
 73  internal class OperationAttribute : RepresentationAttribute
 74  {
 375    internal OperationAttribute(string a, params string[] b) : base(a, b) { }
 76  }
 77
 78  [AttributeUsage(AttributeTargets.Class)]
 79  internal class LeftUnaryOperatorAttribute : Attribute
 80  {
 81    internal readonly string Representation;
 82    internal readonly OperatorPriority Priority;
 83
 184    internal LeftUnaryOperatorAttribute(string representation, OperatorPriority operatorPriority) : base()
 185    {
 186      Representation = representation;
 187      Priority = operatorPriority;
 188    }
 89  }
 90
 91  [AttributeUsage(AttributeTargets.Class)]
 92  internal class RightUnaryOperatorAttribute : Attribute
 93  {
 94    internal readonly string Representation;
 95    internal readonly OperatorPriority Priority;
 96
 197    internal RightUnaryOperatorAttribute(string representation, OperatorPriority operatorPriority) : base()
 198    {
 199      Representation = representation;
 1100      Priority = operatorPriority;
 1101    }
 102  }
 103
 104  [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
 105  internal class BinaryOperatorAttribute : Attribute
 106  {
 107    internal readonly string Representation;
 108    internal readonly OperatorPriority Priority;
 109
 11110    internal BinaryOperatorAttribute(string representation, OperatorPriority operatorPriority) : base()
 11111    {
 11112      Representation = representation;
 11113      Priority = operatorPriority;
 11114    }
 115  }
 116
 117  [AttributeUsage(AttributeTargets.Class)]
 118  internal class KnownConstantAttribute : RepresentationAttribute
 119  {
 3120    internal KnownConstantAttribute(string a, params string[] b) : base(a, b) { }
 121  }
 122
 123  #endregion
 124
 125  #region Expression + Inheriters
 126
 127  #region Expression
 128
 129#pragma warning disable CS0660 // Type defines operator == or operator != but does not override Object.Equals(object o)
 130#pragma warning disable CS0661 // Type defines operator == or operator != but does not override Object.GetHashCode()
 131  /// <summary>Abstract base class for mathematical expressions.</summary>
 132  public abstract class Expression
 133#pragma warning restore CS0661 // Type defines operator == or operator != but does not override Object.GetHashCode()
 134#pragma warning restore CS0660 // Type defines operator == or operator != but does not override Object.Equals(object o)
 135  {
 136    /// <summary>Simplifies the mathematical expression.</summary>
 137    /// <returns>The simplified mathematical expression.</returns>
 140138    public virtual Expression Simplify() => Clone();
 139
 140    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 141    /// <param name="variable">The variable to be substititued.</param>
 142    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 143    /// <returns>The resulting expression of the substitution.</returns>
 0144    public virtual Expression Substitute(string variable, Expression expression) => Clone();
 145
 146    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 147    /// <typeparam name="T">The type of value to substitute in for the variable.</typeparam>
 148    /// <param name="variable">The variable to be substititued.</param>
 149    /// <param name="value">The value to substitute for each occurence of a variable.</param>
 150    /// <returns>The resulting expression of the substitution.</returns>
 0151    public Expression Substitute<T>(string variable, T value) => SubstitutionHack(variable, new Constant<T>(value));
 152
 0153    internal Expression SubstitutionHack(string variable, Expression expression) => Substitute(variable, expression);
 154    /// <summary>Derives this expression.</summary>
 155    /// <param name="variable">The variable to derive in relation to.</param>
 156    /// <returns>The result of the derivation.</returns>
 157#warning TODO
 0158    public virtual Expression Derive(string variable) => throw new NotImplementedException("This feature is still in dev
 159    /// <summary>Integrates this expression.</summary>
 160    /// <param name="variable">The variable to integrate in relation to.</param>
 161    /// <returns>The result of the integration.</returns>
 162#warning TODO
 0163    public virtual Expression Integrate(string variable) => throw new NotImplementedException("This feature is still in 
 164
 165    /// <summary>Creates a copy of the expression.</summary>
 166    /// <returns>A copy of the expression.</returns>
 167    public abstract Expression Clone();
 168
 169    /// <summary>Negates an expression.</summary>
 170    /// <param name="a">The expression to negate.</param>
 171    /// <returns>The result of the negation.</returns>
 4172    public static Expression operator -(Expression a) => new Negate(a);
 173    /// <summary>Adds two expressions.</summary>
 174    /// <param name="a">The first expression of the addition.</param>
 175    /// <param name="b">The second expression of the addition.</param>
 176    /// <returns>The result of the addition.</returns>
 15177    public static Expression operator +(Expression a, Expression b) => new Add(a, b);
 178    /// <summary>Subtracts two expressions.</summary>
 179    /// <param name="a">The first expression of the subtraction.</param>
 180    /// <param name="b">The second expression of the subtraction.</param>
 181    /// <returns>The result of the subtraction.</returns>
 13182    public static Expression operator -(Expression a, Expression b) => new Subtract(a, b);
 183    /// <summary>Multiplies two expressions.</summary>
 184    /// <param name="a">The first expression of the multiplication.</param>
 185    /// <param name="b">The second expression of the multiplication.</param>
 186    /// <returns>The result of the multiplication.</returns>
 21187    public static Expression operator *(Expression a, Expression b) => new Multiply(a, b);
 188    /// <summary>Divides two expressions.</summary>
 189    /// <param name="a">The first expression of the division.</param>
 190    /// <param name="b">The second expression of the division.</param>
 191    /// <returns>The result of the division.</returns>
 11192    public static Expression operator /(Expression a, Expression b) => new Divide(a, b);
 193    /// <summary>Wraps two expressions in an equality check.</summary>
 194    /// <param name="a">The left side of the equality.</param>
 195    /// <param name="b">The right side of the equality.</param>
 196    /// <returns>The expressions wrapped in an equality check.</returns>
 0197    public static Expression operator ==(Expression a, Expression b) => new Equal(a, b);
 198    /// <summary>Wraps two expressions in an inequality check.</summary>
 199    /// <param name="a">The left side of the inequality.</param>
 200    /// <param name="b">The right side of the inequality.</param>
 201    /// <returns>The expressions wrapped in an inequality check.</returns>
 0202    public static Expression operator !=(Expression a, Expression b) => new NotEqual(a, b);
 203    /// <summary>Wraps two expressions in a less than check.</summary>
 204    /// <param name="a">The left side of the less than.</param>
 205    /// <param name="b">The right side of the less than.</param>
 206    /// <returns>The expressions wrapped in an less than check.</returns>
 0207    public static Expression operator <(Expression a, Expression b) => new LessThan(a, b);
 208    /// <summary>Wraps two expressions in a greater than check.</summary>
 209    /// <param name="a">The left side of the greater than.</param>
 210    /// <param name="b">The right side of the greater than.</param>
 211    /// <returns>The expressions wrapped in an greater than check.</returns>
 0212    public static Expression operator >(Expression a, Expression b) => new GreaterThan(a, b);
 213    /// <summary>Takes one expression to the power of another.</summary>
 214    /// <param name="a">The first expression of the power operation.</param>
 215    /// <param name="b">The second expression of the power operation.</param>
 216    /// <returns>The result of the power operation.</returns>
 0217    public static Expression operator ^(Expression a, Expression b) => new Power(a, b);
 218  }
 219
 220  #endregion
 221
 222  #region Variable
 223
 224  /// <summary>A variable in a symbolic mathematics expression.</summary>
 225  public class Variable : Expression
 226  {
 227    /// <summary>The name of the variable.</summary>
 0228    public string Name { get; }
 229
 230    /// <summary>Constructs a new variable.</summary>
 231    /// <param name="name">The name of the vairable.</param>
 0232    public Variable(string name) { Name = name; }
 233
 234    /// <summary>Clones this expression.</summary>
 235    /// <returns>A clone of this expression.</returns>
 0236    public override Expression Clone() => new Variable(Name);
 237
 238    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 239    /// <param name="variable">The variable to be substititued.</param>
 240    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 241    /// <returns>The resulting expression of the substitution.</returns>
 242    public override Expression Substitute(string variable, Expression expression)
 0243    {
 0244      if (Name == variable)
 0245      {
 0246        return expression.Clone();
 247      }
 248      else
 0249      {
 0250        return base.Substitute(variable, expression);
 251      }
 0252    }
 253
 254    /// <summary>Standard conversion to a string representation.</summary>
 255    /// <returns>The string represnetation of this expression.</returns>
 0256    public override string ToString() => "[" + Name + "]";
 257
 258    /// <summary>Standard equality check.</summary>
 259    /// <param name="b">The object to check for equality with.</param>
 260    /// <returns>True if equal. False if not.</returns>
 261    public override bool Equals(object? b)
 0262    {
 0263      if (b is Variable)
 0264      {
 0265        return Name.Equals(b as Variable);
 266      }
 0267      return false;
 0268    }
 269
 270    /// <summary>Standard hash function.</summary>
 271    /// <returns>The computed hash code for this instance.</returns>
 0272    public override int GetHashCode() => Name.GetHashCode();
 273  }
 274
 275  #endregion
 276
 277  #region Constant + Inheriters
 278
 279  #region Constant
 280
 281  /// <summary>Represents a constant numerical value.</summary>
 282  public abstract class Constant : Expression
 283  {
 284    /// <summary>True if this is a known constant value.</summary>
 34285    public virtual bool IsKnownConstant => false;
 286    /// <summary>True if this numeric value is zero (0).</summary>
 0287    public virtual bool IsZero => false;
 288    /// <summary>True if this numeric value is one (1).</summary>
 0289    public virtual bool IsOne => false;
 290    /// <summary>True if this numeric value is two (2).</summary>
 0291    public virtual bool IsTwo => false;
 292    /// <summary>True if this numeric value is three (3).</summary>
 0293    public virtual bool IsThree => false;
 294    /// <summary>True if this numeric value is Ï€ (pi).</summary>
 0295    public virtual bool IsPi => false;
 296
 297    /// <summary>Determines if the constant is negative.</summary>
 298    public abstract bool IsNegative { get; }
 299
 300    internal virtual Expression Simplify(Operation operation, params Expression[] operands)
 0301    {
 0302      return this;
 0303    }
 304
 0305    internal static System.Collections.Generic.Dictionary<Type, Func<object, Expression>> preCompiledConstructors =
 0306      new();
 307
 308    internal static Expression BuildGeneric(object value)
 0309    {
 0310      Type valueType = value.GetType();
 0311      if (preCompiledConstructors.TryGetValue(valueType, out var preCompiledConstructor))
 0312      {
 0313        return preCompiledConstructor(value);
 314      }
 315      else
 0316      {
 0317        Type constantType = typeof(Constant<>).MakeGenericType(valueType);
 0318        ConstructorInfo? constructorInfo = constantType.GetConstructor(Ɐ(valueType));
 0319        if (constructorInfo is null)
 0320        {
 0321          throw new TowelBugException($"Encountered null {nameof(ConstructorInfo)} in {nameof(BuildGeneric)}.");
 322        }
 0323        ParameterExpression A = System.Linq.Expressions.Expression.Parameter(typeof(object));
 0324        NewExpression newExpression = System.Linq.Expressions.Expression.New(constructorInfo, System.Linq.Expressions.Ex
 0325        Func<object, Expression> newFunction = System.Linq.Expressions.Expression.Lambda<Func<object, Expression>>(newEx
 0326        preCompiledConstructors.Add(valueType, newFunction);
 0327        return newFunction(value);
 328      }
 0329    }
 330  }
 331
 332  #endregion
 333
 334  #region KnownConstantOfUnknownType + Inheriters
 335
 336  #region KnownConstantOfUknownType
 337
 338  /// <summary>Abstract base class for known constants of unknown types.</summary>
 339  public abstract class KnownConstantOfUnknownType : Constant
 340  {
 341    /// <summary>True if this numeric value is a known value.</summary>
 0342    public override bool IsKnownConstant => true;
 343
 344    internal abstract Constant<T> ApplyType<T>();
 345  }
 346
 347  #endregion
 348
 349  #region Pi
 350
 351  /// <summary>Represents the Ï€ (pi).</summary>
 352  [KnownConstant("Ï€")]
 353  public class Pi : KnownConstantOfUnknownType
 354  {
 355    /// <summary>Constructs a new instance of pi.</summary>
 54356    public Pi() : base() { }
 357
 358    /// <summary>True if this numeric value is Ï€ (pi).</summary>
 0359    public override bool IsPi => true;
 360
 361    /// <summary>Determines if the constant is negative.</summary>
 0362    public override bool IsNegative => false;
 363
 18364    internal override Constant<T> ApplyType<T>() => new Pi<T>();
 365
 366    /// <summary>Clones this expression.</summary>
 367    /// <returns>A clone of this expression.</returns>
 0368    public override Expression Clone() => new Pi();
 369
 370    /// <summary>Standard conversion to a string representation.</summary>
 371    /// <returns>The string represnetation of this expression.</returns>
 0372    public override string ToString() => "Ï€";
 373
 374    /// <summary>Standard equality check.</summary>
 375    /// <param name="b">The object to check for equality with.</param>
 376    /// <returns>True if equal. False if not.</returns>
 377    public override bool Equals(object? b)
 0378    {
 0379      if (b is Pi)
 0380      {
 0381        return true;
 382      }
 0383      return false;
 0384    }
 385
 386    /// <summary>The default hash code for this instance.</summary>
 387    /// <returns>The computed hash code.</returns>
 0388    public override int GetHashCode() => HashCode;
 0389    internal static readonly int HashCode = nameof(Pi).GetHashCode();
 390  }
 391
 392  #endregion
 393
 394  #region Zero
 395
 396  /// <summary>Represents zero (0).</summary>
 397  public class Zero : KnownConstantOfUnknownType
 398  {
 399    /// <summary>Constructs a new zero (0) value.</summary>
 0400    public Zero() : base() { }
 401
 402    /// <summary>True if this numeric value is zero (0).</summary>
 0403    public override bool IsZero => true;
 404
 405    /// <summary>Determines if the constant is negative.</summary>
 0406    public override bool IsNegative => false;
 407
 0408    internal override Constant<T> ApplyType<T>() => new Zero<T>();
 409
 410    /// <summary>Clones this expression.</summary>
 411    /// <returns>A clone of this expression.</returns>
 0412    public override Expression Clone() => new Zero();
 413
 414    /// <summary>Standard conversion to a string representation.</summary>
 415    /// <returns>The string represnetation of this expression.</returns>
 0416    public override string ToString() => "0";
 417
 418    /// <summary>Standard equality check.</summary>
 419    /// <param name="b">The object to check for equality with.</param>
 420    /// <returns>True if equal. False if not.</returns>
 421    public override bool Equals(object? b)
 0422    {
 0423      if (b is Zero)
 0424      {
 0425        return true;
 426      }
 0427      return false;
 0428    }
 429
 0430    internal static readonly int HashCode = nameof(Zero).GetHashCode();
 431
 432    /// <summary>The default hash code computation.</summary>
 433    /// <returns>The computed hash code for this instance.</returns>
 0434    public override int GetHashCode() => HashCode;
 435  }
 436
 437  #endregion
 438
 439  #region One
 440
 441  /// <summary>Represents the value of one (1).</summary>
 442  public class One : KnownConstantOfUnknownType
 443  {
 444    /// <summary>Constructs a new one (1) constant.</summary>
 0445    public One() : base() { }
 446
 447    /// <summary>True if this numeric value is one (1).</summary>
 0448    public override bool IsOne => true;
 449
 450    /// <summary>Determines if the constant is negative.</summary>
 0451    public override bool IsNegative => false;
 452
 0453    internal override Constant<T> ApplyType<T>() => new One<T>();
 454
 455    /// <summary>Clones this expression.</summary>
 456    /// <returns>A clone of this expression.</returns>
 0457    public override Expression Clone() => new One();
 458
 459    /// <summary>Standard conversion to a string representation.</summary>
 460    /// <returns>The string represnetation of this expression.</returns>
 0461    public override string ToString() => "1";
 462
 463    /// <summary>Standard equality check.</summary>
 464    /// <param name="b">The object to check for equality with.</param>
 465    /// <returns>True if equal. False if not.</returns>
 466    public override bool Equals(object? b)
 0467    {
 0468      if (b is One)
 0469      {
 0470        return true;
 471      }
 0472      return false;
 0473    }
 474
 0475    internal static readonly int HashCode = nameof(One).GetHashCode();
 476
 477    /// <summary>The default hash code computation.</summary>
 478    /// <returns>The computed hash code for this instance.</returns>
 0479    public override int GetHashCode() => HashCode;
 480  }
 481
 482  #endregion
 483
 484  #region Two
 485
 486  /// <summary>Represents the value of two (2).</summary>
 487  public class Two : KnownConstantOfUnknownType
 488  {
 489    /// <summary>Constructs a new value of two (2).</summary>
 0490    public Two() : base() { }
 491
 492    /// <summary>True if this numeric value is two (2).</summary>
 0493    public override bool IsTwo => true;
 494
 495    /// <summary>Determines if the constant is negative.</summary>
 0496    public override bool IsNegative => false;
 497
 0498    internal override Constant<T> ApplyType<T>() => new Two<T>();
 499
 500    /// <summary>Clones this expression.</summary>
 501    /// <returns>A clone of this expression.</returns>
 0502    public override Expression Clone() => new Two();
 503
 504    /// <summary>Standard conversion to a string representation.</summary>
 505    /// <returns>The string represnetation of this expression.</returns>
 0506    public override string ToString() => "2";
 507
 508    /// <summary>Standard equality check.</summary>
 509    /// <param name="b">The object to check for equality with.</param>
 510    /// <returns>True if equal. False if not.</returns>
 511    public override bool Equals(object? b)
 0512    {
 0513      if (b is Two)
 0514      {
 0515        return true;
 516      }
 0517      return false;
 0518    }
 519
 0520    internal static readonly int HashCode = nameof(Two).GetHashCode();
 521
 522    /// <summary>The default hash code computation.</summary>
 523    /// <returns>The computed hash code for this instance.</returns>
 0524    public override int GetHashCode() => HashCode;
 525  }
 526
 527  #endregion
 528
 529  #region Three
 530
 531  /// <summary>Represents the value of three (3).</summary>
 532  public class Three : KnownConstantOfUnknownType
 533  {
 534    /// <summary>Constructs a new value of three (3).</summary>
 0535    public Three() : base() { }
 536
 537    /// <summary>True if this numeric value is three (3).</summary>
 0538    public override bool IsThree => true;
 539
 540    /// <summary>Determines if the constant is negative.</summary>
 0541    public override bool IsNegative => false;
 542
 0543    internal override Constant<T> ApplyType<T>() => new Three<T>();
 544
 545    /// <summary>Clones this expression.</summary>
 546    /// <returns>A clone of this expression.</returns>
 0547    public override Expression Clone() => new Three();
 548
 549    /// <summary>Standard conversion to a string representation.</summary>
 550    /// <returns>The string represnetation of this expression.</returns>
 0551    public override string ToString() => "3";
 552
 553    /// <summary>Standard equality check.</summary>
 554    /// <param name="b">The object to check for equality with.</param>
 555    /// <returns>True if equal. False if not.</returns>
 556    public override bool Equals(object? b)
 0557    {
 0558      if (b is Three)
 0559      {
 0560        return true;
 561      }
 0562      return false;
 0563    }
 564
 0565    internal static readonly int HashCode = nameof(Three).GetHashCode();
 566
 567    /// <summary>The default hash code computation.</summary>
 568    /// <returns>The computed hash code for this instance.</returns>
 0569    public override int GetHashCode() => HashCode;
 570  }
 571
 572  #endregion
 573
 574  #endregion
 575
 576  #region Constant<T> + Inheriters
 577
 578  #region Constant<T>
 579
 580  /// <summary>Represents a numeric constant.</summary>
 581  /// <typeparam name="T">The generic type of the numeric value.</typeparam>
 582  public class Constant<T> : Constant
 583  {
 584    /// <summary>The value of this numeric constant.</summary>
 585    public readonly T Value;
 586
 587    /// <summary>True if this numeric value is zero (0).</summary>
 18588    public override bool IsZero => Equate(Value, Towel.Constant<T>.Zero);
 589    /// <summary>True if this numeric value is one (1).</summary>
 0590    public override bool IsOne => Equate(Value, Towel.Constant<T>.One);
 591    /// <summary>True if this numeric value is two (2).</summary>
 0592    public override bool IsTwo => Equate(Value, Towel.Constant<T>.Two);
 593    /// <summary>True if this numeric value is three (3).</summary>
 0594    public override bool IsThree => Equate(Value, Towel.Constant<T>.Three);
 595
 596    /// <summary>Determines if the constant is negative.</summary>
 18597    public override bool IsNegative => IsNegative(Value);
 598
 599    /// <summary>Constructs a new numeric constant.</summary>
 600    /// <param name="constant">The value of the numeric constant.</param>
 1588601    public Constant(T constant) { Value = constant; }
 602
 603    internal override Expression Simplify(Operation operation, params Expression[] operands)
 24604    {
 24605      return operation.SimplifyHack<T>(operands);
 24606    }
 607
 608    /// <summary>Clones this expression.</summary>
 609    /// <returns>A clone of this expression.</returns>
 122610    public override Expression Clone() => new Constant<T>(Value);
 611
 612    /// <summary>Standard conversion to a string representation.</summary>
 613    /// <returns>The string represnetation of this expression.</returns>
 176614    public override string? ToString() => Value?.ToString();
 615
 616    /// <summary>Standard equality check.</summary>
 617    /// <param name="b">The object to check for equality with.</param>
 618    /// <returns>True if equal. False if not.</returns>
 619    public override bool Equals(object? b)
 92620    {
 92621      if (b is Constant<T> B)
 92622      {
 92623        return Equate(Value, B.Value);
 624      }
 0625      return false;
 92626    }
 627
 0628    internal static readonly int HashCode = nameof(Constant<T>).GetHashCode();
 629
 630    /// <summary>The default hash code computation.</summary>
 631    /// <returns>The computed hash code for this instance.</returns>
 0632    public override int GetHashCode() => HashCode;
 633  }
 634
 635  #endregion
 636
 637  #region KnownConstantOfKnownType<T> + Inheriters
 638
 639  #region KnownConstantOfKnownType<T>
 640
 641  /// <summary>Abstract base class for known constants of unknown types.</summary>
 642  /// <typeparam name="T">The type of the known constant value.</typeparam>
 643  public abstract class KnownConstantOfKnownType<T> : Constant<T>
 644  {
 645    /// <summary>True if this numeric value is a known value.</summary>
 0646    public override bool IsKnownConstant => true;
 647
 648    /// <summary>Constructs a new constant of a known type.</summary>
 649    /// <param name="constant">The value of the known constant.</param>
 108650    public KnownConstantOfKnownType(T constant) : base(constant) { }
 651  }
 652
 653  #endregion
 654
 655  #region Pi<T>
 656
 657  /// <summary>Represents the value of Ï€ (pi).</summary>
 658  /// <typeparam name="T">The generic type of the numeric.</typeparam>
 659  public class Pi<T> : KnownConstantOfKnownType<T>
 660  {
 661    /// <summary>Constructs a new value of Ï€ (pi).</summary>
 108662    public Pi() : base(Towel.Constant<T>.Pi) { }
 663
 664    /// <summary>True if the value is Ï€ (pi).</summary>
 0665    public override bool IsPi => true;
 666
 667    /// <summary>Clones this expression.</summary>
 668    /// <returns>A clone of this expression.</returns>
 18669    public override Expression Clone() => new Pi<T>();
 670
 671    /// <summary>Standard conversion to a string representation.</summary>
 672    /// <returns>The string represnetation of this expression.</returns>
 0673    public override string ToString() => "Ï€";
 674
 675    /// <summary>Standard equality check.</summary>
 676    /// <param name="b">The object to check for equality with.</param>
 677    /// <returns>True if equal. False if not.</returns>
 678    public override bool Equals(object? b)
 0679    {
 0680      if (b is Pi<T>)
 0681      {
 0682        return true;
 683      }
 0684      return false;
 0685    }
 686
 0687    internal static new readonly int HashCode = nameof(Pi<T>).GetHashCode();
 688
 689    /// <summary>The default hash code computation.</summary>
 690    /// <returns>The computed hash code for this instance.</returns>
 0691    public override int GetHashCode() => HashCode;
 692  }
 693
 694  #endregion
 695
 696  #region Zero<T>
 697
 698  /// <summary>Represents the value of zero (0).</summary>
 699  /// <typeparam name="T">The generic type of the numeric value.</typeparam>
 700  public class Zero<T> : KnownConstantOfKnownType<T>
 701  {
 702    /// <summary>Constructs a new zero (0) value.</summary>
 0703    public Zero() : base(Towel.Constant<T>.Zero) { }
 704
 705    /// <summary>True if the value is zero (0).</summary>
 0706    public override bool IsZero => true;
 707
 708    /// <summary>Clones this expression.</summary>
 709    /// <returns>A clone of this expression.</returns>
 0710    public override Expression Clone() => new Zero<T>();
 711
 712    /// <summary>Standard conversion to a string representation.</summary>
 713    /// <returns>The string represnetation of this expression.</returns>
 0714    public override string ToString() => "0";
 715
 716    /// <summary>Standard equality check.</summary>
 717    /// <param name="b">The object to check for equality with.</param>
 718    /// <returns>True if equal. False if not.</returns>
 719    public override bool Equals(object? b)
 0720    {
 0721      if (b is Zero<T>)
 0722      {
 0723        return true;
 724      }
 0725      return false;
 0726    }
 727
 0728    internal static new readonly int HashCode = nameof(Zero<T>).GetHashCode();
 729
 730    /// <summary>The default hash code computation.</summary>
 731    /// <returns>The computed hash code for this instance.</returns>
 0732    public override int GetHashCode() => HashCode;
 733  }
 734
 735  #endregion
 736
 737  #region One<T>
 738
 739  /// <summary>Represents the value of one (1).</summary>
 740  /// <typeparam name="T">The generic type of the numeric value.</typeparam>
 741  public class One<T> : KnownConstantOfKnownType<T>
 742  {
 743    /// <summary>Constructs a new one (1) value.</summary>
 0744    public One() : base(Towel.Constant<T>.One) { }
 745
 746    /// <summary>True if the value is one (1).</summary>
 0747    public override bool IsOne => true;
 748
 749    /// <summary>Clones this expression.</summary>
 750    /// <returns>A clone of this expression.</returns>
 0751    public override Expression Clone() => new One<T>();
 752
 753    /// <summary>Standard conversion to a string representation.</summary>
 754    /// <returns>The string represnetation of this expression.</returns>
 0755    public override string ToString() => "1";
 756
 757    /// <summary>Standard equality check.</summary>
 758    /// <param name="b">The object to check for equality with.</param>
 759    /// <returns>True if equal. False if not.</returns>
 760    public override bool Equals(object? b)
 0761    {
 0762      if (b is One<T>)
 0763      {
 0764        return true;
 765      }
 0766      return false;
 0767    }
 768
 0769    internal static new readonly int HashCode = nameof(One<T>).GetHashCode();
 770
 771    /// <summary>The default hash code computation.</summary>
 772    /// <returns>The computed hash code for this instance.</returns>
 0773    public override int GetHashCode() => HashCode;
 774  }
 775
 776  #endregion
 777
 778  #region Two<T>
 779
 780  /// <summary>Represents the value of two (2).</summary>
 781  /// <typeparam name="T">The generic type of the numeric value.</typeparam>
 782  public class Two<T> : KnownConstantOfKnownType<T>
 783  {
 784    /// <summary>Constructs a new value of two (2).</summary>
 0785    public Two() : base(Towel.Constant<T>.Two) { }
 786
 787    /// <summary>True if the value is two (2).</summary>
 0788    public override bool IsTwo => true;
 789
 790    /// <summary>Clones this expression.</summary>
 791    /// <returns>A clone of this expression.</returns>
 0792    public override Expression Clone() => new Two<T>();
 793
 794    /// <summary>Standard conversion to a string representation.</summary>
 795    /// <returns>The string represnetation of this expression.</returns>
 0796    public override string ToString() => "2";
 797
 798    /// <summary>Standard equality check.</summary>
 799    /// <param name="b">The object to check for equality with.</param>
 800    /// <returns>True if equal. False if not.</returns>
 801    public override bool Equals(object? b)
 0802    {
 0803      if (b is Two<T>)
 0804      {
 0805        return true;
 806      }
 0807      return false;
 0808    }
 809
 0810    internal static new readonly int HashCode = nameof(Two<T>).GetHashCode();
 811
 812    /// <summary>The default hash code computation.</summary>
 813    /// <returns>The computed hash code for this instance.</returns>
 0814    public override int GetHashCode() => HashCode;
 815  }
 816
 817  #endregion
 818
 819  #region Three<T>
 820
 821  /// <summary>Represents the value of three (3).</summary>
 822  /// <typeparam name="T">The generic type of the numeric value.</typeparam>
 823  public class Three<T> : KnownConstantOfKnownType<T>
 824  {
 825    /// <summary>Constructs a new value of three.</summary>
 0826    public Three() : base(Towel.Constant<T>.Three) { }
 827
 828    /// <summary>True if the value is three (3).</summary>
 0829    public override bool IsThree => true;
 830
 831    /// <summary>Clones this expression.</summary>
 832    /// <returns>A clone of this expression.</returns>
 0833    public override Expression Clone() => new Three<T>();
 834
 835    /// <summary>Standard conversion to a string representation.</summary>
 836    /// <returns>The string represnetation of this expression.</returns>
 0837    public override string ToString() => "3";
 838
 839    /// <summary>Standard equality check.</summary>
 840    /// <param name="b">The object to check for equality with.</param>
 841    /// <returns>True if equal. False if not.</returns>
 842    public override bool Equals(object? b)
 0843    {
 0844      if (b is Three<T>)
 0845      {
 0846        return true;
 847      }
 0848      return false;
 0849    }
 850
 0851    internal static new readonly int HashCode = nameof(Three<T>).GetHashCode();
 852
 853    /// <summary>The default hash code computation.</summary>
 854    /// <returns>The computed hash code for this instance.</returns>
 0855    public override int GetHashCode() => HashCode;
 856  }
 857
 858  #endregion
 859
 860  #region True
 861
 862  /// <summary>Represents the value of true.</summary>
 863  public class True : KnownConstantOfKnownType<bool>
 864  {
 865    /// <summary>Constructs a new value of true.</summary>
 0866    public True() : base(true) { }
 867
 868    /// <summary>Clones this expression.</summary>
 869    /// <returns>A clone of this expression.</returns>
 0870    public override Expression Clone() => new True();
 871
 872    /// <summary>Standard conversion to a string representation.</summary>
 873    /// <returns>The string represnetation of this expression.</returns>
 0874    public override string ToString() => true.ToString();
 875
 876    /// <summary>Standard equality check.</summary>
 877    /// <param name="b">The object to check for equality with.</param>
 878    /// <returns>True if equal. False if not.</returns>
 879    public override bool Equals(object? b)
 0880    {
 0881      if (b is True)
 0882      {
 0883        return true;
 884      }
 0885      return false;
 0886    }
 887
 0888    internal static new readonly int HashCode = nameof(True).GetHashCode();
 889
 890    /// <summary>The default hash code computation.</summary>
 891    /// <returns>The computed hash code for this instance.</returns>
 0892    public override int GetHashCode() => HashCode;
 893  }
 894
 895  #endregion
 896
 897  #region False
 898
 899  /// <summary>Represents the value of false.</summary>
 900  public class False : KnownConstantOfKnownType<bool>
 901  {
 902    /// <summary>Constructs a new false value.</summary>
 0903    public False() : base(true) { }
 904
 905    /// <summary>Clones this expression.</summary>
 906    /// <returns>A clone of this expression.</returns>
 0907    public override Expression Clone() => new False();
 908
 909    /// <summary>Standard conversion to a string representation.</summary>
 910    /// <returns>The string represnetation of this expression.</returns>
 0911    public override string ToString() => false.ToString();
 912
 913    /// <summary>Standard equality check.</summary>
 914    /// <param name="b">The object to check for equality with.</param>
 915    /// <returns>True if equal. False if not.</returns>
 916    public override bool Equals(object? b)
 0917    {
 0918      if (b is False)
 0919      {
 0920        return true;
 921      }
 0922      return false;
 0923    }
 924
 0925    internal static new readonly int HashCode = nameof(False).GetHashCode();
 926
 927    /// <summary>The default hash code computation.</summary>
 928    /// <returns>The computed hash code for this instance.</returns>
 0929    public override int GetHashCode() => HashCode;
 930  }
 931
 932  #endregion
 933
 934  #endregion
 935
 936  #endregion
 937
 938  #endregion
 939
 940  #region Operation + Inheriters
 941
 942  #region Operation
 943
 944  /// <summary>Abstract base class for all symbolic mathematics operations.</summary>
 945  public abstract class Operation : Expression
 946  {
 947    /// <summary>Interface for symbolic mathematics operations that involve numeric computation.</summary>
 948    public interface IMathematical { }
 949    /// <summary>Interface for symbolic mathematics operations that involve logical computation.</summary>
 950    public interface ILogical { }
 951
 952    internal virtual Expression Simplify<T>(params Expression[] operands)
 0953    {
 0954      return this;
 0955    }
 956
 957    internal Expression SimplifyHack<T>(params Expression[] operands)
 24958    {
 24959      return Simplify<T>(operands);
 24960    }
 961  }
 962
 963  #endregion
 964
 965  #region Unary + Inheriters
 966
 967  #region Unary
 968
 969#pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode()
 970  /// <summary>Abstract base class for all symbolic mathematics unary operations.</summary>
 971  public abstract class Unary : Operation
 972#pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode()
 973  {
 974    /// <summary>The operand of th unary operation.</summary>
 92975    public Expression A { get; set; }
 976
 977    /// <summary>Constructs a new unary operation.</summary>
 978    /// <param name="a">The operand of the unary operation.</param>
 112979    public Unary(Expression a) : base() { A = a; }
 980
 981    /// <summary>Standard equality check.</summary>
 982    /// <param name="b">The object to check for equality with.</param>
 983    /// <returns>True if equal. False if not.</returns>
 984    public override bool Equals(object? b)
 14985    {
 14986      if (b is not null && GetType() == b.GetType())
 14987      {
 14988        return A.Equals(((Unary)b).A);
 989      }
 0990      return false;
 14991    }
 992  }
 993
 994  #endregion
 995
 996  #region Simplification
 997
 998  /// <summary>Represents a mathematical simplification operation.</summary>
 999  [Operation("Simplify")]
 1000  public class Simplification : Unary
 1001  {
 1002    /// <summary>Constructs a new simplification operation.</summary>
 1003    /// <param name="a">The expression to simplify.</param>
 01004    public Simplification(Expression a) : base(a) { }
 1005
 1006    /// <summary>Simplifies the mathematical expression.</summary>
 1007    /// <returns>The simplified mathematical expression.</returns>
 01008    public override Expression Simplify() => A.Simplify();
 1009
 1010    /// <summary>Clones this expression.</summary>
 1011    /// <returns>A clone of this expression.</returns>
 01012    public override Expression Clone() => new Simplification(A.Clone());
 1013
 1014    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1015    /// <param name="variable">The variable to be substititued.</param>
 1016    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1017    /// <returns>The resulting expression of the substitution.</returns>
 1018    public override Expression Substitute(string variable, Expression expression) =>
 01019      new Simplification(A.Substitute(variable, expression));
 1020
 1021    /// <summary>Standard conversion to a string representation.</summary>
 1022    /// <returns>The string represnetation of this expression.</returns>
 01023    public override string ToString() => "Simplify(" + A + ")";
 1024  }
 1025
 1026  #endregion
 1027
 1028  #region Negate
 1029
 1030  /// <summary>Represents a negation operation.</summary>
 1031  [LeftUnaryOperator("-", OperatorPriority.Negation)]
 1032  public class Negate : Unary, Operation.IMathematical
 1033  {
 1034    /// <summary>Constructs a new negation operation.</summary>
 1035    /// <param name="a">The expression to negate.</param>
 241036    public Negate(Expression a) : base(a) { }
 1037
 1038    /// <summary>Simplifies the mathematical expression.</summary>
 1039    /// <returns>The simplified mathematical expression.</returns>
 1040    public override Expression Simplify()
 01041    {
 01042      Expression OPERAND = A.Simplify();
 1043      #region Computation
 1044      // Rule: [-A] => [B] where A is constant and B is -A
 01045      if (OPERAND is Constant constant)
 01046      {
 01047        return constant.Simplify(this, OPERAND);
 1048      }
 1049      #endregion
 01050      return -OPERAND;
 01051    }
 1052
 1053    internal override Expression Simplify<T>(params Expression[] operands)
 01054    {
 01055      if (operands[0] is Constant<T> a)
 01056      {
 01057        return new Constant<T>(Negation(a.Value));
 1058      }
 01059      return base.Simplify<T>();
 01060    }
 1061
 1062    /// <summary>Clones this expression.</summary>
 1063    /// <returns>A clone of this expression.</returns>
 01064    public override Expression Clone() => new Negate(A.Clone());
 1065
 1066    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1067    /// <param name="variable">The variable to be substititued.</param>
 1068    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1069    /// <returns>The resulting expression of the substitution.</returns>
 1070    public override Expression Substitute(string variable, Expression expression) =>
 01071      new Negate(A.Substitute(variable, expression));
 1072
 1073    /// <summary>Standard conversion to a string representation.</summary>
 1074    /// <returns>The string represnetation of this expression.</returns>
 1075    public override string ToString()
 81076    {
 81077      if (A is not Constant && A is not Variable)
 01078      {
 01079        return "-(" + A + ")";
 1080      }
 81081      return "-" + A;
 81082    }
 1083  }
 1084
 1085  #endregion
 1086
 1087  #region NaturalLog
 1088
 1089  /// <summary>Represents a natural log operation.</summary>
 1090  public class NaturalLog : Unary, Operation.IMathematical
 1091  {
 1092    /// <summary>Constructs a new natural log operation.</summary>
 1093    /// <param name="a">The expression to compute the natrual log of.</param>
 01094    public NaturalLog(Expression a) : base(a) { }
 1095
 1096    /// <summary>Simplifies the mathematical expression.</summary>
 1097    /// <returns>The simplified mathematical expression.</returns>
 1098    public override Expression Simplify()
 01099    {
 01100      Expression OPERAND = A.Simplify();
 1101      #region Computation
 1102      // Rule: [A] => [B] where A is constant and B is ln(A)
 01103      if (OPERAND is Constant constant)
 01104      {
 01105        return constant.Simplify(this, OPERAND);
 1106      }
 1107      #endregion
 01108      return new NaturalLog(OPERAND);
 01109    }
 1110
 1111    internal override Expression Simplify<T>(params Expression[] operands)
 01112    {
 01113      if (operands[0] is Constant<T> a)
 01114      {
 01115        return new Constant<T>(NaturalLogarithm(a.Value));
 1116      }
 01117      return base.Simplify<T>();
 01118    }
 1119
 1120    /// <summary>Clones this expression.</summary>
 1121    /// <returns>A clone of this expression.</returns>
 01122    public override Expression Clone() => new NaturalLog(A.Clone());
 1123
 1124    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1125    /// <param name="variable">The variable to be substititued.</param>
 1126    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1127    /// <returns>The resulting expression of the substitution.</returns>
 1128    public override Expression Substitute(string variable, Expression expression) =>
 01129      new NaturalLog(A.Substitute(variable, expression));
 1130
 1131    /// <summary>Standard conversion to a string representation.</summary>
 1132    /// <returns>The string represnetation of this expression.</returns>
 01133    public override string ToString() => "ln(" + A + ")";
 1134  }
 1135
 1136  #endregion
 1137
 1138  #region SquareRoot
 1139
 1140  /// <summary>Represents a square root operation </summary>
 1141  public class SquareRoot : Unary, Operation.IMathematical
 1142  {
 1143    /// <summary>Constructs a new square root operation.</summary>
 1144    /// <param name="a">The expression to compute the square root of.</param>
 01145    public SquareRoot(Expression a) : base(a) { }
 1146
 1147    /// <summary>Simplifies the mathematical expression.</summary>
 1148    /// <returns>The simplified mathematical expression.</returns>
 1149    public override Expression Simplify()
 01150    {
 01151      Expression OPERAND = A.Simplify();
 1152      #region Computation
 1153      // Rule: [A] => [B] where A is constant and B is sqrt(A)
 01154      if (OPERAND is Constant constant)
 01155      {
 01156        return constant.Simplify(this, OPERAND);
 1157      }
 1158      #endregion
 01159      return new SquareRoot(OPERAND);
 01160    }
 1161
 1162    internal override Expression Simplify<T>(params Expression[] operands)
 01163    {
 01164      if (operands[0] is Constant<T> a)
 01165      {
 01166        return new Constant<T>(SquareRoot(a.Value));
 1167      }
 01168      return base.Simplify<T>();
 01169    }
 1170
 1171    /// <summary>Clones this expression.</summary>
 1172    /// <returns>A clone of this expression.</returns>
 01173    public override Expression Clone() => new SquareRoot(A.Clone());
 1174
 1175    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1176    /// <param name="variable">The variable to be substititued.</param>
 1177    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1178    /// <returns>The resulting expression of the substitution.</returns>
 1179    public override Expression Substitute(string variable, Expression expression) =>
 01180      new SquareRoot(A.Substitute(variable, expression));
 1181
 1182    /// <summary>Standard conversion to a string representation.</summary>
 1183    /// <returns>The string represnetation of this expression.</returns>
 01184    public override string ToString() => "√(" + A + ")";
 1185  }
 1186
 1187  #endregion
 1188
 1189  #region Exponential
 1190
 1191  /// <summary>Represents an exponential operation.</summary>
 1192  public class Exponential : Unary, Operation.IMathematical
 1193  {
 1194    /// <summary>Constructs a new exponential operation.</summary>
 1195    /// <param name="a">The expression to compute the exponetial function of.</param>
 01196    public Exponential(Expression a) : base(a) { }
 1197
 1198    /// <summary>Simplifies the mathematical expression.</summary>
 1199    /// <returns>The simplified mathematical expression.</returns>
 1200    public override Expression Simplify()
 01201    {
 01202      Expression OPERAND = A.Simplify();
 1203      #region Computation
 1204      // Rule: [A] => [B] where A is constant and B is e ^ A
 01205      if (OPERAND is Constant constant)
 01206      {
 01207        return constant.Simplify(this, constant);
 1208      }
 1209      #endregion
 01210      return new Exponential(OPERAND);
 01211    }
 1212
 1213    internal override Expression Simplify<T>(params Expression[] operands)
 01214    {
 01215      if (operands[0] is Constant<T> a)
 01216      {
 01217        return new Constant<T>(Exponential(a.Value));
 1218      }
 01219      return base.Simplify<T>();
 01220    }
 1221
 1222    /// <summary>Clones this expression.</summary>
 1223    /// <returns>A clone of this expression.</returns>
 01224    public override Expression Clone() => new Exponential(A.Clone());
 1225
 1226    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1227    /// <param name="variable">The variable to be substititued.</param>
 1228    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1229    /// <returns>The resulting expression of the substitution.</returns>
 1230    public override Expression Substitute(string variable, Expression expression) =>
 01231      new Exponential(A.Substitute(variable, expression));
 1232
 1233    /// <summary>Standard conversion to a string representation.</summary>
 1234    /// <returns>The string represnetation of this expression.</returns>
 01235    public override string ToString() => "e^(" + A + ")";
 1236  }
 1237
 1238  #endregion
 1239
 1240  #region Factorial
 1241
 1242  /// <summary>Represents a factorial operation.</summary>
 1243  [RightUnaryOperator("!", OperatorPriority.Factorial)]
 1244  public class Factorial : Unary, Operation.IMathematical
 1245  {
 1246    /// <summary>Constructs a new factorial operation.</summary>
 1247    /// <param name="a">The operand of the factorial operation.</param>
 601248    public Factorial(Expression a) : base(a) { }
 1249
 1250    /// <summary>Simplifies the mathematical expression.</summary>
 1251    /// <returns>The simplified mathematical expression.</returns>
 1252    public override Expression Simplify()
 01253    {
 01254      Expression OPERAND = A.Simplify();
 1255      #region Computation
 1256      // Rule: [A!] => [B] where A is constant and B is A!
 01257      if (OPERAND is Constant constant)
 01258      {
 01259        return constant.Simplify(this, constant);
 1260      }
 1261      #endregion
 01262      return new Factorial(OPERAND);
 01263    }
 1264
 1265    internal override Expression Simplify<T>(params Expression[] operands)
 01266    {
 01267      if (operands[0] is Constant<T> a)
 01268      {
 01269        return new Constant<T>(Factorial(a.Value));
 1270      }
 01271      return base.Simplify<T>();
 01272    }
 1273
 1274    /// <summary>Clones this expression.</summary>
 1275    /// <returns>A clone of this expression.</returns>
 01276    public override Expression Clone() => new Factorial(A.Clone());
 1277
 1278    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1279    /// <param name="variable">The variable to be substititued.</param>
 1280    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1281    /// <returns>The resulting expression of the substitution.</returns>
 1282    public override Expression Substitute(string variable, Expression expression) =>
 01283      new Factorial(A.Substitute(variable, expression));
 1284
 1285    /// <summary>Standard conversion to a string representation.</summary>
 1286    /// <returns>The string represnetation of this expression.</returns>
 1287    public override string ToString()
 201288    {
 1289      static bool RequiresParentheses(string expressionString)
 201290      {
 1001291        foreach (char c in expressionString)
 201292        {
 201293          if (!char.IsDigit(c) && c != '.')
 01294          {
 01295            return true;
 1296          }
 201297        }
 201298        return false;
 201299      }
 1300
 201301      string? a = A.ToString();
 201302      if (a is not null && RequiresParentheses(a))
 01303      {
 01304        a = "(" + a + ")";
 01305      }
 201306      return a + "!";
 201307    }
 1308  }
 1309
 1310  #endregion
 1311
 1312  #region Invert
 1313
 1314  /// <summary>Represents a reciprical/invert operation.</summary>
 1315  public class Invert : Unary, Operation.IMathematical
 1316  {
 1317    /// <summary>Constructs a new reciprical/invert operation.</summary>
 1318    /// <param name="a">Teh expression to recipricate/invert.</param>
 01319    public Invert(Expression a) : base(a) { }
 1320
 1321    /// <summary>Simplifies the mathematical expression.</summary>
 1322    /// <returns>The simplified mathematical expression.</returns>
 1323    public override Expression Simplify()
 01324    {
 01325      Expression OPERAND = A.Simplify();
 1326      #region Computation
 1327      // Rule: [A] => [B] where A is constant and B is 1 / A
 01328      if (OPERAND is Constant constant)
 01329      {
 01330        return constant.Simplify(this, OPERAND);
 1331      }
 1332      #endregion
 01333      return new Invert(OPERAND);
 01334    }
 1335
 1336    internal override Expression Simplify<T>(params Expression[] operands)
 01337    {
 01338      if (operands[0] is Constant<T> a)
 01339      {
 01340        return new Constant<T>(Inversion(a.Value));
 1341      }
 01342      return base.Simplify<T>();
 01343    }
 1344
 1345    /// <summary>Clones this expression.</summary>
 1346    /// <returns>A clone of this expression.</returns>
 01347    public override Expression Clone() => new Invert(A.Clone());
 1348
 1349    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1350    /// <param name="variable">The variable to be substititued.</param>
 1351    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1352    /// <returns>The resulting expression of the substitution.</returns>
 1353    public override Expression Substitute(string variable, Expression expression) =>
 01354      new Invert(A.Substitute(variable, expression));
 1355
 1356    /// <summary>Standard conversion to a string representation.</summary>
 1357    /// <returns>The string represnetation of this expression.</returns>
 01358    public override string ToString() => "(1 / " + A + ")";
 1359  }
 1360
 1361  #endregion
 1362
 1363  #region Trigonometry + Inheriters
 1364
 1365  #region Trigonometry
 1366
 1367  /// <summary>Represents one of the trigonometry functions.</summary>
 1368  public abstract class Trigonometry : Unary, Operation.IMathematical
 1369  {
 1370    /// <summary>Constructs a new trigonometry expression.</summary>
 1371    /// <param name="a">The parameter to the trigonometry expression.</param>
 01372    public Trigonometry(Expression a) : base(a) { }
 1373  }
 1374
 1375  #endregion
 1376
 1377  #region Sine
 1378
 1379  /// <summary>Represents the sine trigonometric function.</summary>
 1380  public class Sine : Trigonometry, Operation.IMathematical
 1381  {
 1382    /// <summary>Constructs a new sine expression.</summary>
 1383    /// <param name="a">The parameter to the sine expression.</param>
 01384    public Sine(Expression a) : base(a) { }
 1385
 1386    /// <summary>Simplifies the mathematical expression.</summary>
 1387    /// <returns>The simplified mathematical expression.</returns>
 1388    public override Expression Simplify()
 01389    {
 01390      Expression OPERAND = A.Simplify();
 1391
 01392      return new Sine(OPERAND);
 01393    }
 1394
 1395    internal override Expression Simplify<T>(params Expression[] operands)
 01396    {
 1397#warning TODO
 1398      // if (A is Constant<T> a)
 1399      // {
 1400      //     //return new Constant<T>(Compute.Sine(a.Value));
 1401      // }
 01402      return base.Simplify<T>();
 01403    }
 1404
 1405    /// <summary>Clones this expression.</summary>
 1406    /// <returns>A clone of this expression.</returns>
 01407    public override Expression Clone() => new Sine(A.Clone());
 1408
 1409    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1410    /// <param name="variable">The variable to be substititued.</param>
 1411    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1412    /// <returns>The resulting expression of the substitution.</returns>
 1413    public override Expression Substitute(string variable, Expression expression) =>
 01414      new Sine(A.Substitute(variable, expression));
 1415
 1416    /// <summary>Standard conversion to a string representation.</summary>
 1417    /// <returns>The string represnetation of this expression.</returns>
 01418    public override string ToString() => nameof(Sine) + "(" + A + ")";
 1419  }
 1420
 1421  #endregion
 1422
 1423  #region Cosine
 1424
 1425  /// <summary>Represents the cosine trigonometric function.</summary>
 1426  public class Cosine : Trigonometry, Operation.IMathematical
 1427  {
 1428    /// <summary>Constructs a new cosine expression.</summary>
 1429    /// <param name="a">The parameter to the cosine expression.</param>
 01430    public Cosine(Expression a) : base(a) { }
 1431
 1432    /// <summary>Simplifies the mathematical expression.</summary>
 1433    /// <returns>The simplified mathematical expression.</returns>
 1434    public override Expression Simplify()
 01435    {
 01436      Expression OPERAND = A.Simplify();
 1437
 01438      return new Cosine(OPERAND);
 01439    }
 1440
 1441    internal override Expression Simplify<T>(params Expression[] operands)
 01442    {
 1443#warning TODO
 1444      // if (A is Constant<T> a)
 1445      // {
 1446      //     //return new Constant<T>(Compute.Cosine(a.Value));
 1447      // }
 01448      return base.Simplify<T>();
 01449    }
 1450
 1451    /// <summary>Clones this expression.</summary>
 1452    /// <returns>A clone of this expression.</returns>
 01453    public override Expression Clone() => new Cosine(A.Clone());
 1454
 1455    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1456    /// <param name="variable">The variable to be substititued.</param>
 1457    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1458    /// <returns>The resulting expression of the substitution.</returns>
 1459    public override Expression Substitute(string variable, Expression expression) =>
 01460      new Cosine(A.Substitute(variable, expression));
 1461
 1462    /// <summary>Standard conversion to a string representation.</summary>
 1463    /// <returns>The string represnetation of this expression.</returns>
 01464    public override string ToString() => nameof(Cosine) + "(" + A + ")";
 1465  }
 1466
 1467  #endregion
 1468
 1469  #region Tangent
 1470
 1471  /// <summary>Represents the tanget trigonometric function.</summary>
 1472  public class Tangent : Trigonometry, Operation.IMathematical
 1473  {
 1474    /// <summary>Constructs a new tangent expression.</summary>
 1475    /// <param name="a">The parameter to the tangent expression.</param>
 01476    public Tangent(Expression a) : base(a) { }
 1477
 1478    /// <summary>Simplifies the mathematical expression.</summary>
 1479    /// <returns>The simplified mathematical expression.</returns>
 1480    public override Expression Simplify()
 01481    {
 01482      Expression OPERAND = A.Simplify();
 1483
 01484      return new Tangent(OPERAND);
 01485    }
 1486
 1487    internal override Expression Simplify<T>(params Expression[] operands)
 01488    {
 1489#warning TODO
 1490      // if (A is Constant<T> a)
 1491      // {
 1492      //     //return new Constant<T>(Compute.Tanget(a.Value));
 1493      // }
 01494      return base.Simplify<T>();
 01495    }
 1496
 1497    /// <summary>Clones this expression.</summary>
 1498    /// <returns>A clone of this expression.</returns>
 01499    public override Expression Clone() => new Tangent(A.Clone());
 1500
 1501    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1502    /// <param name="variable">The variable to be substititued.</param>
 1503    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1504    /// <returns>The resulting expression of the substitution.</returns>
 1505    public override Expression Substitute(string variable, Expression expression) =>
 01506      new Tangent(A.Substitute(variable, expression));
 1507
 1508    /// <summary>Standard conversion to a string representation.</summary>
 1509    /// <returns>The string represnetation of this expression.</returns>
 01510    public override string ToString() => nameof(Tangent) + "(" + A + ")";
 1511  }
 1512
 1513  #endregion
 1514
 1515  #region Cosecant
 1516
 1517  /// <summary>Represents the cosecant trigonometric function.</summary>
 1518  public class Cosecant : Trigonometry, Operation.IMathematical
 1519  {
 1520    /// <summary>Constructs a new cosecant expression.</summary>
 1521    /// <param name="a">The parameter to the cosecant expression.</param>
 01522    public Cosecant(Expression a) : base(a) { }
 1523
 1524    /// <summary>Simplifies the mathematical expression.</summary>
 1525    /// <returns>The simplified mathematical expression.</returns>
 1526    public override Expression Simplify()
 01527    {
 01528      Expression OPERAND = A.Simplify();
 1529
 01530      return new Cosecant(OPERAND);
 01531    }
 1532
 1533    internal override Expression Simplify<T>(params Expression[] operands)
 01534    {
 1535#warning TODO
 1536      // if (A is Constant<T> a)
 1537      // {
 1538      //     //return new Constant<T>(Compute.Cosecant(a.Value));
 1539      // }
 01540      return base.Simplify<T>();
 01541    }
 1542
 1543    /// <summary>Clones this expression.</summary>
 1544    /// <returns>A clone of this expression.</returns>
 01545    public override Expression Clone() => new Cosecant(A.Clone());
 1546
 1547    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1548    /// <param name="variable">The variable to be substititued.</param>
 1549    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1550    /// <returns>The resulting expression of the substitution.</returns>
 1551    public override Expression Substitute(string variable, Expression expression) =>
 01552      new Cosecant(A.Substitute(variable, expression));
 1553
 1554    /// <summary>Standard conversion to a string representation.</summary>
 1555    /// <returns>The string represnetation of this expression.</returns>
 01556    public override string ToString() => nameof(Cosecant) + "(" + A + ")";
 1557  }
 1558
 1559  #endregion
 1560
 1561  #region Secant
 1562
 1563  /// <summary>Represents the secant trigonometric function.</summary>
 1564  public class Secant : Trigonometry, Operation.IMathematical
 1565  {
 1566    /// <summary>Constructs a new secant expression.</summary>
 1567    /// <param name="a">The parameter to the secant expression.</param>
 01568    public Secant(Expression a) : base(a) { }
 1569
 1570    /// <summary>Simplifies the mathematical expression.</summary>
 1571    /// <returns>The simplified mathematical expression.</returns>
 1572    public override Expression Simplify()
 01573    {
 01574      Expression OPERAND = A.Simplify();
 1575
 01576      return new Secant(OPERAND);
 01577    }
 1578
 1579    internal override Expression Simplify<T>(params Expression[] operands)
 01580    {
 1581#warning TODO
 1582      // if (A is Constant<T> a)
 1583      // {
 1584      //     //return new Constant<T>(Compute.Secant(a.Value));
 1585      // }
 01586      return base.Simplify<T>();
 01587    }
 1588
 1589    /// <summary>Clones this expression.</summary>
 1590    /// <returns>A clone of this expression.</returns>
 01591    public override Expression Clone() => new Secant(A.Clone());
 1592
 1593    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1594    /// <param name="variable">The variable to be substititued.</param>
 1595    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1596    /// <returns>The resulting expression of the substitution.</returns>
 1597    public override Expression Substitute(string variable, Expression expression) =>
 01598      new Secant(A.Substitute(variable, expression));
 1599
 1600    /// <summary>Standard conversion to a string representation.</summary>
 1601    /// <returns>The string represnetation of this expression.</returns>
 01602    public override string ToString() => nameof(Secant) + "(" + A + ")";
 1603  }
 1604
 1605  #endregion
 1606
 1607  #region Cotangent
 1608
 1609  /// <summary>Represents the cotangent trigonometric function.</summary>
 1610  public class Cotangent : Trigonometry, Operation.IMathematical
 1611  {
 1612    /// <summary>Constructs a new cotangent expression.</summary>
 1613    /// <param name="a">The parameter to the cotangent expression.</param>
 01614    public Cotangent(Expression a) : base(a) { }
 1615
 1616    /// <summary>Simplifies the mathematical expression.</summary>
 1617    /// <returns>The simplified mathematical expression.</returns>
 1618    public override Expression Simplify()
 01619    {
 01620      Expression OPERAND = A.Simplify();
 1621
 01622      return new Cotangent(OPERAND);
 01623    }
 1624
 1625    internal override Expression Simplify<T>(params Expression[] operands)
 01626    {
 1627#warning TODO
 1628      // if (A is Constant<T> a)
 1629      // {
 1630      //     //return new Constant<T>(Compute.Cotangent(a.Value));
 1631      // }
 01632      return base.Simplify<T>();
 01633    }
 1634
 1635    /// <summary>Clones this expression.</summary>
 1636    /// <returns>A clone of this expression.</returns>
 01637    public override Expression Clone() => new Cotangent(A.Clone());
 1638
 1639    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1640    /// <param name="variable">The variable to be substititued.</param>
 1641    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1642    /// <returns>The resulting expression of the substitution.</returns>
 1643    public override Expression Substitute(string variable, Expression expression) =>
 01644      new Cotangent(A.Substitute(variable, expression));
 1645
 1646    /// <summary>Standard conversion to a string representation.</summary>
 1647    /// <returns>The string represnetation of this expression.</returns>
 01648    public override string ToString() => nameof(Cotangent) + "(" + A + ")";
 1649  }
 1650
 1651  #endregion
 1652
 1653  #endregion
 1654
 1655  #endregion
 1656
 1657  #region Binary + Inheriters
 1658
 1659  #region Binary
 1660
 1661#pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode()
 1662  /// <summary>Abstract base class for all symbolic mathematics binary operations.</summary>
 1663  public abstract class Binary : Operation
 1664#pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode()
 1665  {
 1666    /// <summary>The first operand of the binary operation.</summary>
 6061667    public Expression A { get; set; }
 1668    /// <summary>The second operand of the binary operation.</summary>
 6121669    public Expression B { get; set; }
 1670
 1671    /// <summary>Constructs a new binary operation.</summary>
 1672    /// <param name="a">The left operand of the binary operation.</param>
 1673    /// <param name="b">The right operand of the binary operation.</param>
 1321674    public Binary(Expression a, Expression b)
 1321675    {
 1321676      A = a;
 1321677      B = b;
 1321678    }
 1679
 1680    /// <summary>Standard equality check.</summary>
 1681    /// <param name="b">The object to check for equality with.</param>
 1682    /// <returns>True if equal. False if not.</returns>
 1683    public override bool Equals(object? b)
 541684    {
 541685      if (b is not null && GetType() == b.GetType())
 541686      {
 541687        return A.Equals(((Binary)b).A) && B.Equals(((Binary)b).B);
 1688      }
 01689      return false;
 541690    }
 1691  }
 1692
 1693  #endregion
 1694
 1695  #region AddOrSubtract + Inheriters
 1696
 1697  #region AddOrSubtract
 1698
 1699  /// <summary>Represents an addition or a subtraction operation.</summary>
 1700  public abstract class AddOrSubtract : Binary, Operation.IMathematical
 1701  {
 1702    /// <summary>Constructs a new addition or subtraction operation.</summary>
 1703    /// <param name="a">The left operand of the operation.</param>
 1704    /// <param name="b">The right operand of the operation.</param>
 1681705    public AddOrSubtract(Expression a, Expression b) : base(a, b) { }
 1706  }
 1707
 1708  #endregion
 1709
 1710  #region Add
 1711
 1712  /// <summary>Represents an addition operation.</summary>
 1713  [BinaryOperator("+", OperatorPriority.Addition)]
 1714  public class Add : AddOrSubtract
 1715  {
 1716    /// <summary>Constructs a new addition operation.</summary>
 1717    /// <param name="a">The left operand of the addition operation.</param>
 1718    /// <param name="b">The right operand of the addition operation.</param>
 901719    public Add(Expression a, Expression b) : base(a, b) { }
 1720
 1721    /// <summary>Simplifies the mathematical expression.</summary>
 1722    /// <returns>The simplified mathematical expression.</returns>
 1723    public override Expression Simplify()
 01724    {
 01725      Expression LEFT = A.Simplify();
 01726      Expression RIGHT = B.Simplify();
 1727      #region Computation
 01728      {   // Rule: [A + B] => [C] where A is constant, B is constant, and C is A + B
 01729        if (LEFT is Constant A && RIGHT is Constant B)
 01730        {
 01731          return A.Simplify(this, A, B);
 1732        }
 01733      }
 1734      #endregion
 1735      #region Additive Identity Property
 01736      {   // Rule: [X + 0] => [X]
 01737        if (RIGHT is Constant right && right.IsZero)
 01738        {
 01739          return LEFT;
 1740        }
 01741      }
 01742      {   // Rule: [0 + X] => [X]
 01743        if (LEFT is Constant left && left.IsZero)
 01744        {
 01745          return RIGHT;
 1746        }
 01747      }
 1748      #endregion
 1749      #region Commutative/Associative Property
 01750      {   // Rule: ['X + A' + B] => [X + C] where A is constant, B is constant, and C is A + B
 01751        if (LEFT is Add ADD && ADD.B is Constant A && RIGHT is Constant B)
 01752        {
 01753          var C = (A + B).Simplify();
 01754          var X = ADD.A;
 01755          return X + C;
 1756        }
 01757      }
 01758      {   // Rule: ['A + X' + B] => [X + C] where A is constant, B is constant, and C is A + B
 01759        if (LEFT is Add ADD && ADD.A is Constant A && RIGHT is Constant B)
 01760        {
 01761          var C = (A + B).Simplify();
 01762          var X = ADD.B;
 01763          return X + C;
 1764        }
 01765      }
 01766      {   // Rule: [B + 'X + A'] => [X + C] where A is constant, B is constant, and C is A + B
 01767        if (RIGHT is Add ADD && ADD.B is Constant A && LEFT is Constant B)
 01768        {
 01769          var C = (A + B).Simplify();
 01770          var X = ADD.A;
 01771          return X + C;
 1772        }
 01773      }
 01774      {   // Rule: [B + 'A + X'] => [X + C] where A is constant, B is constant, and C is A + B
 01775        if (RIGHT is Add ADD && ADD.A is Constant A && LEFT is Constant B)
 01776        {
 01777          var C = (A + B).Simplify();
 01778          var X = ADD.B;
 01779          return X + C;
 1780        }
 01781      }
 01782      {   // Rule: ['X - A' + B] => [X + C] where A is constant, B is constant, and C is B - A
 01783        if (LEFT is Subtract SUBTRACT && SUBTRACT.B is Constant A && RIGHT is Constant B)
 01784        {
 01785          var C = (B - A).Simplify();
 01786          var X = SUBTRACT.A;
 01787          return X + C;
 1788        }
 01789      }
 01790      {   // Rule: ['A - X' + B] => [C - X] where A is constant, B is constant, and C is A + B
 01791        if (LEFT is Subtract SUBTRACT && SUBTRACT.A is Constant A && RIGHT is Constant B)
 01792        {
 01793          var C = (A + B).Simplify();
 01794          var X = SUBTRACT.B;
 01795          return C - X;
 1796        }
 01797      }
 01798      {   // Rule: [B + 'X - A'] => [X + C] where A is constant, B is constant, and C is B - A
 01799        if (RIGHT is Subtract SUBTRACT && SUBTRACT.B is Constant A && LEFT is Constant B)
 01800        {
 01801          var C = (B - A).Simplify();
 01802          var X = SUBTRACT.A;
 01803          return C + X;
 1804        }
 01805      }
 01806      {   // Rule: [B + 'A - X'] => [C - X] where A is constant, B is constant, and C is A + B
 01807        if (RIGHT is Subtract SUBTRACT && SUBTRACT.A is Constant A && LEFT is Constant B)
 01808        {
 01809          var C = (A + B).Simplify();
 01810          var X = SUBTRACT.B;
 01811          return C - X;
 1812        }
 01813      }
 1814      #endregion
 01815      return LEFT + RIGHT;
 01816    }
 1817
 1818    internal override Expression Simplify<T>(params Expression[] operands)
 01819    {
 01820      if (operands[0] is Constant<T> a && operands[1] is Constant<T> b)
 01821      {
 01822        return new Constant<T>(Addition(a.Value, b.Value));
 1823      }
 01824      return base.Simplify<T>();
 01825    }
 1826
 1827    /// <summary>Clones this expression.</summary>
 1828    /// <returns>A clone of this expression.</returns>
 01829    public override Expression Clone() => new Add(A.Clone(), B.Clone());
 1830
 1831    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1832    /// <param name="variable">The variable to be substititued.</param>
 1833    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1834    /// <returns>The resulting expression of the substitution.</returns>
 1835    public override Expression Substitute(string variable, Expression expression) =>
 01836      new Add(A.Substitute(variable, expression), B.Substitute(variable, expression));
 1837
 1838    /// <summary>Standard conversion to a string representation.</summary>
 1839    /// <returns>The string represnetation of this expression.</returns>
 1840    public override string ToString()
 301841    {
 301842      string? a = A.ToString();
 301843      string? b = B.ToString();
 301844      {
 301845        if ((A is Multiply || A is Divide) && A is Constant CONSTANT && CONSTANT.IsNegative)
 01846        {
 01847          a = "(" + a + ")";
 01848        }
 301849      }
 301850      {
 301851        if (B is Add || B is Subtract || A is Multiply || A is Divide)
 81852        {
 81853          b = "(" + b + ")";
 81854        }
 301855      }
 301856      {
 301857        if (B is Constant CONSTANT && CONSTANT.IsNegative)
 01858        {
 01859          return a + " - " + Negation(B as Constant);
 1860        }
 301861      }
 301862      return a + " + " + b;
 301863    }
 1864  }
 1865
 1866  #endregion
 1867
 1868  #region Subtract
 1869
 1870  /// <summary>Represents a subtraction operation.</summary>
 1871  [BinaryOperator("-", OperatorPriority.Subtraction)]
 1872  public class Subtract : AddOrSubtract
 1873  {
 1874    /// <summary>Constructs a new subtraction operation.</summary>
 1875    /// <param name="a">The left operand of the subtraction operation.</param>
 1876    /// <param name="b">The right operand of the subtraction operation.</param>
 781877    public Subtract(Expression a, Expression b) : base(a, b) { }
 1878
 1879    /// <summary>Simplifies the mathematical expression.</summary>
 1880    /// <returns>The simplified mathematical expression.</returns>
 1881    public override Expression Simplify()
 01882    {
 01883      Expression LEFT = A.Simplify();
 01884      Expression RIGHT = B.Simplify();
 1885      #region Computation
 01886      {   // Rule: [A - B] => [C] where A is constant, B is constant, and C is A - B
 01887        if (LEFT is Constant left && RIGHT is Constant right)
 01888        {
 01889          return left.Simplify(this, left, right);
 1890        }
 01891      }
 1892      #endregion
 1893      #region Identity Property
 01894      {   // Rule: [X - 0] => [X]
 01895        if (RIGHT is Constant right && right.IsZero)
 01896        {
 01897          return LEFT;
 1898        }
 01899      }
 01900      {   // Rule: [0 - X] => [-X]
 01901        if (LEFT is Constant left && left.IsZero)
 01902        {
 01903          return new Negate(RIGHT);
 1904        }
 01905      }
 1906      #endregion
 1907      #region Commutative/Associative Property
 01908      {   // Rule: ['X - A' - B] => [X - C] where A is constant, B is constant, and C is A + B
 01909        if (LEFT is Subtract SUBTRACT && SUBTRACT.B is Constant A && RIGHT is Constant B)
 01910        {
 01911          var C = (A + B).Simplify();
 01912          var X = SUBTRACT.A;
 01913          return X - C;
 1914        }
 01915      }
 01916      {    // Rule: ['A - X' - B] => [C - X] where A is constant, B is constant, and C is A - B
 01917        if (LEFT is Subtract SUBTRACT && SUBTRACT.A is Constant A && RIGHT is Constant B)
 01918        {
 01919          var C = (A - B).Simplify();
 01920          var X = SUBTRACT.B;
 01921          return C - X;
 1922        }
 01923      }
 01924      {   // Rule: [B - 'X - A'] => [C - X] where A is constant, B is constant, and C is B - A
 01925        if (RIGHT is Subtract SUBTRACT && SUBTRACT.B is Constant A && LEFT is Constant B)
 01926        {
 01927          var C = (B - A).Simplify();
 01928          var X = SUBTRACT.A;
 01929          return C - X;
 1930        }
 01931      }
 01932      {   // Rule: [B - 'A - X'] => [C - X] where A is constant, B is constant, and C is B - A
 01933        if (RIGHT is Subtract SUBTRACT && SUBTRACT.A is Constant A && LEFT is Constant B)
 01934        {
 01935          var C = (B - A).Simplify();
 01936          var X = SUBTRACT.A;
 01937          return C - X;
 1938        }
 01939      }
 01940      {   // Rule: ['X + A' - B] => [X + C] where A is constant, B is constant, and C is A - B
 01941        if (LEFT is Add ADD && ADD.B is Constant A && RIGHT is Constant B)
 01942        {
 01943          var C = (A - B).Simplify();
 01944          var X = ADD.A;
 01945          return X + C;
 1946        }
 01947      }
 01948      {   // Rule: ['A + X' - B] => [C + X] where A is constant, B is constant, and C is A - B
 01949        if (LEFT is Add ADD && ADD.A is Constant A && RIGHT is Constant B)
 01950        {
 01951          var C = (A - B).Simplify();
 01952          var X = ADD.B;
 01953          return C + X;
 1954        }
 01955      }
 01956      {   // Rule: [B - 'X + A'] => [C - X] where A is constant, B is constant, and C is A + B
 01957        if (RIGHT is Add ADD && ADD.B is Constant A && LEFT is Constant B)
 01958        {
 01959          var C = (A + B).Simplify();
 01960          var X = ADD.A;
 01961          return C - X;
 1962        }
 01963      }
 01964      {   // Rule: [B - 'A + X'] => [C + X] where A is constant, B is constant, and C is B - A
 01965        if (RIGHT is Add ADD && ADD.A is Constant A && LEFT is Constant B)
 01966        {
 01967          var C = (B - A).Simplify();
 01968          var X = ADD.B;
 01969          return C + X;
 1970        }
 01971      }
 1972      #endregion
 01973      return LEFT - RIGHT;
 01974    }
 1975
 1976    internal override Expression Simplify<T>(params Expression[] operands)
 01977    {
 01978      if (operands[0] is Constant<T> a && operands[1] is Constant<T> b)
 01979      {
 01980        return new Constant<T>(Subtraction(a.Value, b.Value));
 1981      }
 01982      return base.Simplify<T>();
 01983    }
 1984
 1985    /// <summary>Clones this expression.</summary>
 1986    /// <returns>A clone of this expression.</returns>
 01987    public override Expression Clone() => new Subtract(A.Clone(), B.Clone());
 1988
 1989    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 1990    /// <param name="variable">The variable to be substititued.</param>
 1991    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 1992    /// <returns>The resulting expression of the substitution.</returns>
 1993    public override Expression Substitute(string variable, Expression expression) =>
 01994      new Subtract(A.Substitute(variable, expression), B.Substitute(variable, expression));
 1995
 1996    /// <summary>Standard conversion to a string representation.</summary>
 1997    /// <returns>The string represnetation of this expression.</returns>
 1998    public override string ToString()
 261999    {
 262000      string? a = A.ToString();
 262001      if (A is Multiply || A is Divide)
 22002      {
 22003        a = "(" + a + ")";
 22004      }
 262005      string? b = B.ToString();
 262006      if (B is Add || B is Subtract || A is Multiply || A is Divide)
 82007      {
 82008        b = "(" + b + ")";
 82009      }
 262010      return a + " - " + b;
 262011    }
 2012  }
 2013
 2014  #endregion
 2015
 2016  #endregion
 2017
 2018  #region MultiplyOrDivide + Inheriters
 2019
 2020  #region MultiplyOrDivide
 2021
 2022  /// <summary>Abstract base class for multiplication and division operations.</summary>
 2023  public abstract class MultiplyOrDivide : Binary, Operation.IMathematical
 2024  {
 2025    /// <summary>Constructs a new multiplication or division operation.</summary>
 2026    /// <param name="a">The left operand of the operation.</param>
 2027    /// <param name="b">The right operand of the operation.</param>
 2282028    public MultiplyOrDivide(Expression a, Expression b) : base(a, b) { }
 2029  }
 2030
 2031  #endregion
 2032
 2033  #region Multiply
 2034
 2035  /// <summary>Represents a multiplication operation.</summary>
 2036  [BinaryOperator("*", OperatorPriority.Multiplication)]
 2037  public class Multiply : MultiplyOrDivide
 2038  {
 2039    /// <summary>Constructs a new multiplication operation.</summary>
 2040    /// <param name="a">The left operand of the multiplication operation.</param>
 2041    /// <param name="b">The right operand of the multiplication operation.</param>
 1082042    public Multiply(Expression a, Expression b) : base(a, b) { }
 2043
 2044    /// <summary>Simplifies the mathematical expression.</summary>
 2045    /// <returns>The simplified mathematical expression.</returns>
 2046    public override Expression Simplify()
 62047    {
 62048      Expression LEFT = A.Simplify();
 62049      Expression RIGHT = B.Simplify();
 2050      #region Computation
 62051      {   // Rule: [A * B] => [C] where A is constant, B is constant, and C is A * B
 62052        if (LEFT is Constant A && RIGHT is Constant B)
 62053        {
 62054          return A.Simplify(this, A, B);
 2055        }
 02056      }
 2057      #endregion
 2058      #region Zero Property
 02059      {   // Rule: [X * 0] => [0]
 02060        if (RIGHT is Constant CONSTANT && CONSTANT.IsZero)
 02061        {
 02062          return CONSTANT;
 2063        }
 02064      }
 02065      {   // Rule: [0 * X] => [0]
 02066        if (LEFT is Constant CONSTANT && CONSTANT.IsZero)
 02067        {
 02068          return CONSTANT;
 2069        }
 02070      }
 2071      #endregion
 2072      #region Identity Property
 02073      {   // Rule: [X * 1] => [X]
 02074        if (RIGHT is Constant CONSTANT && CONSTANT.IsOne)
 02075        {
 02076          return LEFT;
 2077        }
 02078      }
 02079      {   // Rule: [1 * X] => [X]
 02080        if (LEFT is Constant CONSTANT && CONSTANT.IsOne)
 02081        {
 02082          return RIGHT;
 2083        }
 02084      }
 2085      #endregion
 2086      #region Commutative/Associative Property
 02087      {   // Rule: [(X * A) * B] => [X * C] where A is constant, B is constant, and C is A * B
 02088        if (LEFT is Multiply MULTIPLY && MULTIPLY.B is Constant A && RIGHT is Constant B)
 02089        {
 02090          var C = (A * B).Simplify();
 02091          var X = MULTIPLY.A;
 02092          return X * C;
 2093        }
 02094      }
 02095      {   // Rule: [(A * X) * B] => [X * C] where A is constant, B is constant, and C is A * B
 02096        if (LEFT is Multiply MULTIPLY && MULTIPLY.A is Constant A && RIGHT is Constant B)
 02097        {
 02098          var C = (A * B).Simplify();
 02099          var X = MULTIPLY.B;
 02100          return X * C;
 2101        }
 02102      }
 02103      {   // Rule: [B * (X * A)] => [X * C] where A is constant, B is constant, and C is A * B
 02104        if (RIGHT is Multiply MULTIPLY && MULTIPLY.B is Constant A && LEFT is Constant B)
 02105        {
 02106          var C = (A * B).Simplify();
 02107          var X = MULTIPLY.A;
 02108          return X * C;
 2109        }
 02110      }
 02111      {   // Rule: [B * (A * X)] => [X * C] where A is constant, B is constant, and C is A * B
 02112        if (RIGHT is Multiply MULTIPLY && MULTIPLY.A is Constant A && LEFT is Constant B)
 02113        {
 02114          var C = (A * B).Simplify();
 02115          var X = MULTIPLY.B;
 02116          return X * C;
 2117        }
 02118      }
 02119      {   // Rule: [(X / A) * B] => [X * C] where A is constant, B is constant, and C is B / A
 02120        if (LEFT is Divide DIVIDE && DIVIDE.B is Constant A && RIGHT is Constant B)
 02121        {
 02122          var C = (B / A).Simplify();
 02123          var X = DIVIDE.A;
 02124          return X * C;
 2125        }
 02126      }
 02127      {   // Rule: [(A / X) * B] => [C / X] where A is constant, B is constant, and C is A * B
 02128        if (LEFT is Divide DIVIDE && DIVIDE.A is Constant A && RIGHT is Constant B)
 02129        {
 02130          var C = (A * B).Simplify();
 02131          var X = DIVIDE.B;
 02132          return C / X;
 2133        }
 02134      }
 02135      {   // Rule: [B * (X / A)] => [X * C] where A is constant, B is constant, and C is B / A
 02136        if (RIGHT is Divide DIVIDE && DIVIDE.B is Constant A && LEFT is Constant B)
 02137        {
 02138          var C = (B / A).Simplify();
 02139          var X = DIVIDE.A;
 02140          return X * C;
 2141        }
 02142      }
 02143      {   // Rule: [B * (A / X)] => [C / X] where A is constant, B is constant, and C is A * B
 02144        if (RIGHT is Divide DIVIDE && DIVIDE.A is Constant A && LEFT is Constant B)
 02145        {
 02146          var C = (A * B).Simplify();
 02147          var X = DIVIDE.B;
 02148          return C / X;
 2149        }
 02150      }
 2151      #endregion
 2152      #region Distributive Property
 2153      // {   // Rule: [X * (A +/- B)] => [X * A + X * B] where X is Variable
 2154      //     if ((LEFT is Variable VARIABLE && RIGHT is AddOrSubtract ADDORSUBTRACT))
 2155      //     {
 2156      //         // This might not be necessary
 2157      //     }
 2158      // }
 2159      // {   // Rule: [(A +/- B) * X] => [X * A + X * B] where X is Variable
 2160      //     if ((RIGHT is Variable VARIABLE && LEFT is AddOrSubtract ADDORSUBTRACT))
 2161      //     {
 2162      //         // This might not be necessary
 2163      //     }
 2164      // }
 2165      #endregion
 2166      #region Duplicate Variable Multiplications
 02167      {   // Rule: [X * X] => [X ^ 2] where X is Variable
 02168        if (LEFT is Variable X1 && RIGHT is Variable X2 && X1.Name == X2.Name)
 02169        {
 02170          return X1 ^ new Two();
 2171        }
 02172      }
 2173      #endregion
 2174      #region Multiplication With Powered Variables
 02175      {   // Rule: [(V ^ A) * (V ^ B)] => [V ^ C] where A is constant, B is constant, V is a variable, and C is A + B
 02176        if (LEFT is Power POWER1 && RIGHT is Power POWER2 &&
 02177          POWER1.A is Variable V1 && POWER2.A is Variable V2 && V1.Name == V2.Name &&
 02178          POWER1.B is Constant A && POWER2.B is Constant B)
 02179        {
 02180          var C = (A + B).Simplify();
 02181          return V1 ^ C;
 2182        }
 02183      }
 2184      #endregion
 02185      return LEFT * RIGHT;
 62186    }
 2187
 2188    internal override Expression Simplify<T>(params Expression[] operands)
 62189    {
 62190      if (operands[0] is Constant<T> a && operands[1] is Constant<T> b)
 62191      {
 62192        return new Constant<T>(Multiplication(a.Value, b.Value));
 2193      }
 02194      return base.Simplify<T>();
 62195    }
 2196
 2197    /// <summary>Clones this expression.</summary>
 2198    /// <returns>A clone of this expression.</returns>
 02199    public override Expression Clone() => new Multiply(A.Clone(), B.Clone());
 2200
 2201    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 2202    /// <param name="variable">The variable to be substititued.</param>
 2203    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 2204    /// <returns>The resulting expression of the substitution.</returns>
 2205    public override Expression Substitute(string variable, Expression expression) =>
 02206      new Multiply(A.Substitute(variable, expression), B.Substitute(variable, expression));
 2207
 2208    /// <summary>Standard conversion to a string representation.</summary>
 2209    /// <returns>The string represnetation of this expression.</returns>
 2210    public override string ToString()
 282211    {
 282212      string? a = A.ToString();
 282213      string? b = B.ToString();
 282214      if (B is Multiply || B is Divide)
 62215      {
 62216        b = "(" + b + ")";
 62217      }
 222218      else if (A is Constant a_const && a_const.IsKnownConstant && B is Constant)
 02219      {
 02220        return b + a;
 2221      }
 222222      else if (A is Constant && B is Constant b_const && b_const.IsKnownConstant)
 02223      {
 02224        return a + b;
 2225      }
 282226      return a + " * " + b;
 282227    }
 2228  }
 2229
 2230  #endregion
 2231
 2232  #region Divide
 2233
 2234  /// <summary>Represents a division operation.</summary>
 2235  [BinaryOperator("/", OperatorPriority.Division)]
 2236  public class Divide : MultiplyOrDivide
 2237  {
 2238    /// <summary>Constructs a new division operation.</summary>
 2239    /// <param name="a">The left operand of the division operation.</param>
 2240    /// <param name="b">The right operand of the division operation.</param>
 1202241    public Divide(Expression a, Expression b) : base(a, b) { }
 2242
 2243    /// <summary>Simplifies the mathematical expression.</summary>
 2244    /// <returns>The simplified mathematical expression.</returns>
 2245    public override Expression Simplify()
 182246    {
 182247      Expression LEFT = A.Simplify();
 182248      Expression RIGHT = B.Simplify();
 2249      #region Error Handling
 182250      {   // Rule: [X / 0] => Error
 182251        if (RIGHT is Constant CONSTANT && CONSTANT.IsZero)
 02252        {
 02253          throw new DivideByZeroException();
 2254        }
 182255      }
 2256      #endregion
 2257      #region Computation
 182258      {   // Rule: [A / B] => [C] where A is constant, B is constant, and C is A / B
 182259        if (LEFT is Constant A && RIGHT is Constant B)
 182260        {
 182261          return A.Simplify(this, A, B);
 2262        }
 02263      }
 2264      #endregion
 2265      #region Zero Property
 02266      {   // Rule: [0 / X] => [0]
 02267        if (LEFT is Constant CONSTANT && CONSTANT.IsZero)
 02268        {
 02269          return CONSTANT;
 2270        }
 02271      }
 2272      #endregion
 2273      #region Identity Property
 02274      {   // Rule: [X / 1] => [X]
 02275        if (RIGHT is Constant CONSTANT && CONSTANT.IsOne)
 02276        {
 02277          return LEFT;
 2278        }
 02279      }
 2280      #endregion
 2281      #region Commutative/Associative Property
 02282      {   // Rule: [(X / A) / B] => [X / C] where A is constant, B is constant, and C is A * B
 02283        if (LEFT is Divide DIVIDE && DIVIDE.B is Constant A && RIGHT is Constant B)
 02284        {
 02285          var C = (A * B).Simplify();
 02286          var X = DIVIDE.A;
 02287          return X / C;
 2288        }
 02289      }
 02290      {   // Rule: [(A / X) / B] => [C / X] where A is constant, B is constant, and C is A / B
 02291        if (LEFT is Divide DIVIDE && DIVIDE.A is Constant A && RIGHT is Constant B)
 02292        {
 02293          var C = (A / B).Simplify();
 02294          var X = DIVIDE.B;
 02295          return C / X;
 2296        }
 02297      }
 02298      {   // Rule: [B / (X / A)] => [C / X] where A is constant, B is constant, and C is B / A
 02299        if (RIGHT is Divide DIVIDE && DIVIDE.B is Constant A && LEFT is Constant B)
 02300        {
 02301          var C = (B / A).Simplify();
 02302          var X = DIVIDE.A;
 02303          return C / X;
 2304        }
 02305      }
 02306      {   // Rule: [B / (A / X)] => [C / X] where A is constant, B is constant, and C is B / A
 02307        if (RIGHT is Divide DIVIDE && DIVIDE.A is Constant A && LEFT is Constant B)
 02308        {
 02309          var C = (B / A).Simplify();
 02310          var X = DIVIDE.B;
 02311          return C / X;
 2312        }
 02313      }
 02314      {   // Rule: [(X * A) / B] => [X * C] where A is constant, B is constant, and C is A / B
 02315        if (LEFT is Multiply MULTIPLY && MULTIPLY.B is Constant A && RIGHT is Constant B)
 02316        {
 02317          var C = (A / B).Simplify();
 02318          var X = MULTIPLY.A;
 02319          return X * C;
 2320        }
 02321      }
 02322      {   // Rule: [(A * X) / B] => [X * C] where A is constant, B is constant, and C is A / B
 02323        if (LEFT is Multiply MULTIPLY && MULTIPLY.A is Constant A && RIGHT is Constant B)
 02324        {
 02325          var C = (A / B).Simplify();
 02326          var X = MULTIPLY.B;
 02327          return X * C;
 2328        }
 02329      }
 02330      {   // Rule: [B / (X * A)] => [C / X] where A is constant, B is constant, and C is A * B
 02331        if (RIGHT is Multiply MULTIPLY && MULTIPLY.B is Constant A && LEFT is Constant B)
 02332        {
 02333          var C = (A * B).Simplify();
 02334          var X = MULTIPLY.A;
 02335          return C / X;
 2336        }
 02337      }
 02338      {   // Rule: [B / (A * X)] => [X * C] where A is constant, B is constant, and C is B / A
 02339        if (RIGHT is Multiply MULTIPLY && MULTIPLY.A is Constant A && LEFT is Constant B)
 02340        {
 02341          var C = (B / A).Simplify();
 02342          var X = MULTIPLY.B;
 02343          return X * C;
 2344        }
 02345      }
 2346      #endregion
 2347      #region Distributive Property
 2348      // {   // Rule: [X / (A +/- B)] => [X / A + X / B] where where A is constant, B is constant, and X is Variable
 2349      //     if ((LEFT is Variable VARIABLE && RIGHT is AddOrSubtract ADDORSUBTRACT))
 2350      //     {
 2351      //         // This might not be necessary
 2352      //     }
 2353      // }
 2354      // {   // Rule: [(A +/- B) / X] => [(A / X) + (B / X)] where where A is constant, B is constant, and X is Variable
 2355      //     if ((RIGHT is Variable VARIABLE && LEFT is AddOrSubtract ADDORSUBTRACT))
 2356      //     {
 2357      //         // This might not be necessary
 2358      //     }
 2359      // }
 2360      #endregion
 2361      #region Division With Powered Variables
 02362      {   // Rule: [(V ^ A) / (V ^ B)] => [V ^ C] where A is constant, B is constant, V is a variable, and C is A - B
 02363        if (LEFT is Power POWER1 && RIGHT is Power POWER2 &&
 02364          POWER1.A is Variable V1 && POWER2.A is Variable V2 && V1.Name == V2.Name &&
 02365          POWER1.B is Constant A && POWER2.B is Constant B)
 02366        {
 02367          var C = (A - B).Simplify();
 02368          return V1 ^ C;
 2369        }
 02370      }
 2371      #endregion
 02372      return LEFT / RIGHT;
 182373    }
 2374
 2375    internal override Expression Simplify<T>(params Expression[] operands)
 182376    {
 182377      if (operands[0] is Constant<T> a && operands[1] is Constant<T> b)
 182378      {
 182379        return new Constant<T>(Division(a.Value, b.Value));
 2380      }
 02381      return base.Simplify<T>();
 182382    }
 2383
 2384    /// <summary>Clones this expression.</summary>
 2385    /// <returns>A clone of this expression.</returns>
 02386    public override Expression Clone() => new Divide(A.Clone(), B.Clone());
 2387
 2388    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 2389    /// <param name="variable">The variable to be substititued.</param>
 2390    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 2391    /// <returns>The resulting expression of the substitution.</returns>
 2392    public override Expression Substitute(string variable, Expression expression) =>
 02393      new Divide(A.Substitute(variable, expression), B.Substitute(variable, expression));
 2394
 2395    /// <summary>Standard conversion to a string representation.</summary>
 2396    /// <returns>The string represnetation of this expression.</returns>
 2397    public override string ToString()
 202398    {
 202399      string? a = A.ToString();
 202400      string? b = B.ToString();
 202401      if (B is Multiply || B is Divide)
 62402      {
 62403        b = "(" + b + ")";
 62404      }
 202405      return a + " / " + b;
 202406    }
 2407  }
 2408
 2409  #endregion
 2410
 2411  #endregion
 2412
 2413  #region Power
 2414
 2415  /// <summary>Represents a power operation.</summary>
 2416  [BinaryOperator("^", OperatorPriority.Exponents)]
 2417  public class Power : Binary, Operation.IMathematical
 2418  {
 2419    /// <summary>Constructs a new power operation.</summary>
 2420    /// <param name="a">The left operand of the power operation.</param>
 2421    /// <param name="b">The right operand of the power operation.</param>
 02422    public Power(Expression a, Expression b) : base(a, b) { }
 2423
 2424    /// <summary>Simplifies the mathematical expression.</summary>
 2425    /// <returns>The simplified mathematical expression.</returns>
 2426    public override Expression Simplify()
 02427    {
 02428      Expression LEFT = A.Simplify();
 02429      Expression RIGHT = B.Simplify();
 2430      #region Computation
 02431      {   // Rule: [A ^ B] => [C] where A is constant, B is constant, and C is A ^ B
 02432        if (LEFT is Constant A && RIGHT is Constant B)
 02433        {
 02434          return A.Simplify(this, A, B);
 2435        }
 02436      }
 2437      #endregion
 2438      #region Zero Base
 02439      {   // Rule: [0 ^ X] => [0]
 02440        if (LEFT is Constant CONSTANT && CONSTANT.IsZero)
 02441        {
 02442          return CONSTANT;
 2443        }
 02444      }
 2445      #endregion
 2446      #region One Power
 02447      {   // Rule: [X ^ 1] => [X]
 02448        if (RIGHT is Constant CONSTANT && CONSTANT.IsOne)
 02449        {
 02450          return LEFT;
 2451        }
 02452      }
 2453      #endregion
 2454      #region Zero Power
 02455      {   // Rule: [X ^ 0] => [1]
 02456        if (RIGHT is Constant CONSTANT && CONSTANT.IsZero)
 02457        {
 02458          return new One();
 2459        }
 02460      }
 2461      #endregion
 02462      return LEFT ^ RIGHT;
 02463    }
 2464
 2465    internal override Expression Simplify<T>(params Expression[] operands)
 02466    {
 02467      if (operands[0] is Constant<T> a && operands[1] is Constant<T> b)
 02468      {
 02469        return new Constant<T>(Power(a.Value, b.Value));
 2470      }
 02471      return base.Simplify<T>();
 02472    }
 2473
 2474    /// <summary>Clones this expression.</summary>
 2475    /// <returns>A clone of this expression.</returns>
 02476    public override Expression Clone() => new Power(A.Clone(), B.Clone());
 2477
 2478    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 2479    /// <param name="variable">The variable to be substititued.</param>
 2480    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 2481    /// <returns>The resulting expression of the substitution.</returns>
 2482    public override Expression Substitute(string variable, Expression expression) =>
 02483      new Power(A.Substitute(variable, expression), B.Substitute(variable, expression));
 2484
 2485    /// <summary>Standard conversion to a string representation.</summary>
 2486    /// <returns>The string represnetation of this expression.</returns>
 2487    public override string ToString()
 02488    {
 2489      static bool RequiresParentheses(string expressionString)
 02490      {
 02491        foreach (char c in expressionString)
 02492        {
 02493          if (!char.IsDigit(c) && c != '.')
 02494          {
 02495            return true;
 2496          }
 02497        }
 02498        return false;
 02499      }
 2500
 02501      string? a = A.ToString();
 02502      string? b = B.ToString();
 02503      if (a is not null && RequiresParentheses(a))
 02504      {
 02505        a = "(" + a + ")";
 02506      }
 02507      if (b is not null && RequiresParentheses(b))
 02508      {
 02509        b = "(" + b + ")";
 02510      }
 02511      return a + " ^ " + b;
 02512    }
 2513  }
 2514
 2515  #endregion
 2516
 2517  #region Root
 2518
 2519  /// <summary>Represents a root operation.</summary>
 2520  public class Root : Binary, Operation.IMathematical
 2521  {
 2522    /// <summary>Constructs a new root operation.</summary>
 2523    /// <param name="a">The base of the root operation.</param>
 2524    /// <param name="b">The root (inverted exponent) value of the operation.</param>
 02525    public Root(Expression a, Expression b) : base(a, b) { }
 2526
 2527    /// <summary>Simplifies the mathematical expression.</summary>
 2528    /// <returns>The simplified mathematical expression.</returns>
 2529    public override Expression Simplify()
 02530    {
 02531      Expression LEFT = A.Simplify();
 02532      Expression RIGHT = B.Simplify();
 2533      #region Computation
 02534      {   // Rule: [A ^ (1 / B)] => [C] where A is constant, B is constant, and C is A ^ (1 / B)
 02535        if (LEFT is Constant A && RIGHT is Constant B)
 02536        {
 02537          return A.Simplify(this, A, B);
 2538        }
 02539      }
 2540      #endregion
 02541      return new Root(LEFT, RIGHT);
 02542    }
 2543
 2544    internal override Expression Simplify<T>(params Expression[] operands)
 02545    {
 02546      if (operands[0] is Constant<T> a && operands[1] is Constant<T> b)
 02547      {
 02548        return new Constant<T>(Root(a.Value, b.Value));
 2549      }
 02550      return base.Simplify<T>();
 02551    }
 2552
 2553    /// <summary>Clones this expression.</summary>
 2554    /// <returns>A clone of this expression.</returns>
 02555    public override Expression Clone() => new Root(A.Clone(), B.Clone());
 2556
 2557    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 2558    /// <param name="variable">The variable to be substititued.</param>
 2559    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 2560    /// <returns>The resulting expression of the substitution.</returns>
 2561    public override Expression Substitute(string variable, Expression expression) =>
 02562      new Root(A.Substitute(variable, expression), B.Substitute(variable, expression));
 2563
 2564    /// <summary>Standard conversion to a string representation.</summary>
 2565    /// <returns>The string represnetation of this expression.</returns>
 02566    public override string ToString() => A + " ^ (1 / " + B + ")";
 2567  }
 2568
 2569  #endregion
 2570
 2571  #region Equal
 2572
 2573  /// <summary>Represents an equality operation between two expressions.</summary>
 2574  [BinaryOperator("=", OperatorPriority.Logical)]
 2575  public class Equal : Binary, Operation.ILogical
 2576  {
 2577    /// <summary>Constructs a new equality operation between two expressions.</summary>
 2578    /// <param name="a">The left expression of the equality.</param>
 2579    /// <param name="b">The right expression of the equality.</param>
 02580    public Equal(Expression a, Expression b) : base(a, b) { }
 2581
 2582    /// <summary>Simplifies the mathematical expression.</summary>
 2583    /// <returns>The simplified mathematical expression.</returns>
 2584    public override Expression Simplify()
 02585    {
 02586      Expression LEFT = A.Simplify();
 02587      Expression RIGHT = B.Simplify();
 2588      #region Computation
 02589      {   // Rule: [A == B] => [C] where A is constant, B is constant, and C is A == B
 02590        if (LEFT is Constant A && RIGHT is Constant B)
 02591        {
 02592          return A.Simplify(this, A, B);
 2593        }
 02594      }
 2595      #endregion
 02596      return LEFT == RIGHT;
 02597    }
 2598
 2599    internal override Expression Simplify<T>(params Expression[] operands)
 02600    {
 02601      if (operands[0] is Constant<T> a && operands[1] is Constant<T> b)
 02602      {
 02603        return new Constant<bool>(Equate(a.Value, b.Value));
 2604      }
 02605      return base.Simplify<T>();
 02606    }
 2607
 2608    /// <summary>Clones this expression.</summary>
 2609    /// <returns>A clone of this expression.</returns>
 02610    public override Expression Clone() => new Equal(A.Clone(), B.Clone());
 2611
 2612    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 2613    /// <param name="variable">The variable to be substititued.</param>
 2614    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 2615    /// <returns>The resulting expression of the substitution.</returns>
 2616    public override Expression Substitute(string variable, Expression expression) =>
 02617      new Equal(A.Substitute(variable, expression), B.Substitute(variable, expression));
 2618
 2619    /// <summary>Standard conversion to a string representation.</summary>
 2620    /// <returns>The string represnetation of this expression.</returns>
 02621    public override string ToString() => A + " = " + B;
 2622  }
 2623
 2624  #endregion
 2625
 2626  #region NotEqual
 2627
 2628  /// <summary>Represents an equality operation between two expressions.</summary>
 2629  [BinaryOperator("≠", OperatorPriority.Logical)]
 2630  public class NotEqual : Binary, Operation.ILogical
 2631  {
 2632    /// <summary>Constructs a new inequality operation between two expressions.</summary>
 2633    /// <param name="a">The left expression of the inequality.</param>
 2634    /// <param name="b">The right expression of the inequality.</param>
 02635    public NotEqual(Expression a, Expression b) : base(a, b) { }
 2636
 2637    /// <summary>Simplifies the mathematical expression.</summary>
 2638    /// <returns>The simplified mathematical expression.</returns>
 2639    public override Expression Simplify()
 02640    {
 02641      Expression LEFT = A.Simplify();
 02642      Expression RIGHT = B.Simplify();
 2643      #region Computation
 02644      {   // Rule: [A == B] => [C] where A is constant, B is constant, and C is A != B
 02645        if (LEFT is Constant A && RIGHT is Constant B)
 02646        {
 02647          return A.Simplify(this, A, B);
 2648        }
 02649      }
 2650      #endregion
 02651      return new NotEqual(LEFT, RIGHT);
 02652    }
 2653
 2654    internal override Expression Simplify<T>(params Expression[] operands)
 02655    {
 02656      if (operands[0] is Constant<T> a && operands[1] is Constant<T> b)
 02657      {
 02658        return new Constant<bool>(Inequate(a.Value, b.Value));
 2659      }
 02660      return base.Simplify<T>();
 02661    }
 2662
 2663    /// <summary>Clones this expression.</summary>
 2664    /// <returns>A clone of this expression.</returns>
 02665    public override Expression Clone() => new NotEqual(A.Clone(), B.Clone());
 2666
 2667    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 2668    /// <param name="variable">The variable to be substititued.</param>
 2669    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 2670    /// <returns>The resulting expression of the substitution.</returns>
 2671    public override Expression Substitute(string variable, Expression expression) =>
 02672      new NotEqual(A.Substitute(variable, expression), B.Substitute(variable, expression));
 2673
 2674    /// <summary>Standard conversion to a string representation.</summary>
 2675    /// <returns>The string represnetation of this expression.</returns>
 02676    public override string ToString() => A + " â‰  " + B;
 2677  }
 2678
 2679  #endregion
 2680
 2681  #region LessThan
 2682
 2683  /// <summary>Represents a less than operation.</summary>
 2684  [BinaryOperator("<", OperatorPriority.Logical)]
 2685  public class LessThan : Binary, Operation.ILogical
 2686  {
 2687    /// <summary>Constructs a new less than operation.</summary>
 2688    /// <param name="a">The left expression of the less than operation.</param>
 2689    /// <param name="b">The right expression of the less than operation.</param>
 02690    public LessThan(Expression a, Expression b) : base(a, b) { }
 2691
 2692    /// <summary>Simplifies the mathematical expression.</summary>
 2693    /// <returns>The simplified mathematical expression.</returns>
 2694    public override Expression Simplify()
 02695    {
 02696      Expression LEFT = A.Simplify();
 02697      Expression RIGHT = B.Simplify();
 2698      #region Computation
 02699      {   // Rule: [A == B] => [C] where A is constant, B is constant, and C is A < B
 02700        if (LEFT is Constant A && RIGHT is Constant B)
 02701        {
 02702          return A.Simplify(this, A, B);
 2703        }
 02704      }
 2705      #endregion
 02706      return new LessThan(LEFT, RIGHT);
 02707    }
 2708
 2709    internal override Expression Simplify<T>(params Expression[] operands)
 02710    {
 02711      if (operands[0] is Constant<T> a && operands[1] is Constant<T> b)
 02712      {
 02713        return new Constant<bool>(LessThan(a.Value, b.Value));
 2714      }
 02715      return base.Simplify<T>();
 02716    }
 2717
 2718    /// <summary>Clones this expression.</summary>
 2719    /// <returns>A clone of this expression.</returns>
 02720    public override Expression Clone() => new LessThan(A.Clone(), B.Clone());
 2721
 2722    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 2723    /// <param name="variable">The variable to be substititued.</param>
 2724    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 2725    /// <returns>The resulting expression of the substitution.</returns>
 2726    public override Expression Substitute(string variable, Expression expression) =>
 02727      new LessThan(A.Substitute(variable, expression), B.Substitute(variable, expression));
 2728
 2729    /// <summary>Standard conversion to a string representation.</summary>
 2730    /// <returns>The string represnetation of this expression.</returns>
 02731    public override string ToString() => A + " < " + B;
 2732  }
 2733
 2734  #endregion
 2735
 2736  #region GreaterThan
 2737
 2738  /// <summary>Represents a greater than operation.</summary>
 2739  [BinaryOperator(">", OperatorPriority.Logical)]
 2740  public class GreaterThan : Binary, Operation.ILogical
 2741  {
 2742    /// <summary>Constructs a new greater than operation.</summary>
 2743    /// <param name="a">The left expression of the greater than operation.</param>
 2744    /// <param name="b">The right expression of the greater than operation.</param>
 02745    public GreaterThan(Expression a, Expression b) : base(a, b) { }
 2746
 2747    /// <summary>Simplifies the mathematical expression.</summary>
 2748    /// <returns>The simplified mathematical expression.</returns>
 2749    public override Expression Simplify()
 02750    {
 02751      Expression LEFT = A.Simplify();
 02752      Expression RIGHT = B.Simplify();
 2753      #region Computation
 02754      {   // Rule: [A == B] => [C] where A is constant, B is constant, and C is A > B
 02755        if (LEFT is Constant A && RIGHT is Constant B)
 02756        {
 02757          return A.Simplify(this, A, B);
 2758        }
 02759      }
 2760      #endregion
 02761      return new GreaterThan(LEFT, RIGHT);
 02762    }
 2763
 2764    internal override Expression Simplify<T>(params Expression[] operands)
 02765    {
 02766      if (operands[0] is Constant<T> a && operands[1] is Constant<T> b)
 02767      {
 02768        return new Constant<bool>(GreaterThan(a.Value, b.Value));
 2769      }
 02770      return base.Simplify<T>();
 02771    }
 2772
 2773    /// <summary>Clones this expression.</summary>
 2774    /// <returns>A clone of this expression.</returns>
 02775    public override Expression Clone() => new GreaterThan(A.Clone(), B.Clone());
 2776
 2777    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 2778    /// <param name="variable">The variable to be substititued.</param>
 2779    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 2780    /// <returns>The resulting expression of the substitution.</returns>
 2781    public override Expression Substitute(string variable, Expression expression) =>
 02782      new GreaterThan(A.Substitute(variable, expression), B.Substitute(variable, expression));
 2783
 2784    /// <summary>Standard conversion to a string representation.</summary>
 2785    /// <returns>The string represnetation of this expression.</returns>
 02786    public override string ToString() => A + " < " + B;
 2787  }
 2788
 2789  #endregion
 2790
 2791  #region LessThanOrEqual
 2792
 2793  /// <summary>Represents a less than or equal to operation.</summary>
 2794  [BinaryOperator("<=", OperatorPriority.Logical)]
 2795  public class LessThanOrEqual : Binary, Operation.ILogical
 2796  {
 2797    /// <summary>Constructs a new less than or equal to operation.</summary>
 2798    /// <param name="a">The left expression of the less than or equal to operation.</param>
 2799    /// <param name="b">The right expression of the less than or equal to operation.</param>
 02800    public LessThanOrEqual(Expression a, Expression b) : base(a, b) { }
 2801
 2802    /// <summary>Simplifies the mathematical expression.</summary>
 2803    /// <returns>The simplified mathematical expression.</returns>
 2804    public override Expression Simplify()
 02805    {
 02806      Expression LEFT = A.Simplify();
 02807      Expression RIGHT = B.Simplify();
 2808      #region Computation
 02809      {   // Rule: [A == B] => [C] where A is constant, B is constant, and C is A <= B
 02810        if (LEFT is Constant A && RIGHT is Constant B)
 02811        {
 02812          return A.Simplify(this, A, B);
 2813        }
 02814      }
 2815      #endregion
 02816      return new LessThanOrEqual(LEFT, RIGHT);
 02817    }
 2818
 2819    internal override Expression Simplify<T>(params Expression[] operands)
 02820    {
 02821      if (operands[0] is Constant<T> a && operands[1] is Constant<T> b)
 02822      {
 02823        return new Constant<bool>(LessThanOrEqual(a.Value, b.Value));
 2824      }
 02825      return base.Simplify<T>();
 02826    }
 2827
 2828    /// <summary>Clones this expression.</summary>
 2829    /// <returns>A clone of this expression.</returns>
 02830    public override Expression Clone() => new LessThanOrEqual(A.Clone(), B.Clone());
 2831
 2832    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 2833    /// <param name="variable">The variable to be substititued.</param>
 2834    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 2835    /// <returns>The resulting expression of the substitution.</returns>
 2836    public override Expression Substitute(string variable, Expression expression) =>
 02837      new LessThanOrEqual(A.Substitute(variable, expression), B.Substitute(variable, expression));
 2838
 2839    /// <summary>Standard conversion to a string representation.</summary>
 2840    /// <returns>The string represnetation of this expression.</returns>
 02841    public override string ToString() => A + " < " + B;
 2842  }
 2843
 2844  #endregion
 2845
 2846  #region GreaterThanOrEqual
 2847
 2848  /// <summary>Represents a greater than or equal to operation.</summary>
 2849  [BinaryOperator(">=", OperatorPriority.Logical)]
 2850  public class GreaterThanOrEqual : Binary, Operation.ILogical
 2851  {
 2852    /// <summary>Constructs a new greater than or equal to operation.</summary>
 2853    /// <param name="a">The left expression of the greater than or equal to operation.</param>
 2854    /// <param name="b">The right expression of the greater than or equal to operation.</param>
 02855    public GreaterThanOrEqual(Expression a, Expression b) : base(a, b) { }
 2856
 2857    /// <summary>Simplifies the mathematical expression.</summary>
 2858    /// <returns>The simplified mathematical expression.</returns>
 2859    public override Expression Simplify()
 02860    {
 02861      Expression LEFT = A.Simplify();
 02862      Expression RIGHT = B.Simplify();
 2863      #region Computation
 02864      {   // Rule: [A == B] => [C] where A is constant, B is constant, and C is A >= B
 02865        if (LEFT is Constant A && RIGHT is Constant B)
 02866        {
 02867          return A.Simplify(this, A, B);
 2868        }
 02869      }
 2870      #endregion
 02871      return new GreaterThanOrEqual(LEFT, RIGHT);
 02872    }
 2873
 2874    internal override Expression Simplify<T>(params Expression[] operands)
 02875    {
 02876      if (operands[0] is Constant<T> a && operands[1] is Constant<T> b)
 02877      {
 02878        return new Constant<bool>(GreaterThanOrEqual(a.Value, b.Value));
 2879      }
 02880      return base.Simplify<T>();
 02881    }
 2882
 2883    /// <summary>Clones this expression.</summary>
 2884    /// <returns>A clone of this expression.</returns>
 02885    public override Expression Clone() => new GreaterThanOrEqual(A.Clone(), B.Clone());
 2886
 2887    /// <summary>Substitutes an expression for all occurences of a variable.</summary>
 2888    /// <param name="variable">The variable to be substititued.</param>
 2889    /// <param name="expression">The expression to substitute for each occurence of a variable.</param>
 2890    /// <returns>The resulting expression of the substitution.</returns>
 2891    public override Expression Substitute(string variable, Expression expression) =>
 02892      new GreaterThanOrEqual(A.Substitute(variable, expression), B.Substitute(variable, expression));
 2893
 2894    /// <summary>Standard conversion to a string representation.</summary>
 2895    /// <returns>The string represnetation of this expression.</returns>
 02896    public override string ToString() => A + " < " + B;
 2897  }
 2898
 2899  #endregion
 2900
 2901  #endregion
 2902
 2903  #region Ternary + Inheriters
 2904
 2905  #region Ternary
 2906
 2907#pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode()
 2908  /// <summary>Abstract base class for ternary operations.</summary>
 2909  public abstract class Ternary : Operation
 2910#pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode()
 2911  {
 2912    /// <summary>The first operand of the ternary operation.</summary>
 02913    public Expression A { get; set; }
 2914    /// <summary>The second operand of the ternary operation.</summary>
 02915    public Expression B { get; set; }
 2916    /// <summary>The third operand of the ternary operation.</summary>
 02917    public Expression C { get; set; }
 2918
 2919    /// <summary>Constructs a new ternary operation.</summary>
 2920    /// <param name="a">The first operand of the ternary operation.</param>
 2921    /// <param name="b">The second operand of the ternary operation.</param>
 2922    /// <param name="c">The third operand of the ternary operation.</param>
 02923    public Ternary(Expression a, Expression b, Expression c)
 02924    {
 02925      A = a;
 02926      B = b;
 02927      C = c;
 02928    }
 2929
 2930    /// <summary>Standard equality check.</summary>
 2931    /// <param name="b">The object to check for equality with.</param>
 2932    /// <returns>True if equal. False if not.</returns>
 2933    public override bool Equals(object? b)
 02934    {
 02935      if (b is not null && GetType() == b.GetType())
 02936      {
 02937        return A.Equals(((Ternary)b).A) && B.Equals(((Ternary)b).B) && C.Equals(((Ternary)b).C);
 2938      }
 02939      return false;
 02940    }
 2941  }
 2942
 2943  #endregion
 2944
 2945  #endregion
 2946
 2947  #region Multinary + Inheriters
 2948
 2949  #region Multinary
 2950
 2951  /// <summary>Abstract base class for multinary operations.</summary>
 2952  public abstract class Multinary : Operation
 2953  {
 2954    /// <summary>The operands of the multinary operation.</summary>
 02955    public Expression[] Operands { get; set; }
 2956
 2957    /// <summary>Constructs a new multinary operation.</summary>
 2958    /// <param name="operands">The operands of the multinary operation.</param>
 02959    public Multinary(Expression[] operands)
 02960    {
 02961      Operands = operands;
 02962    }
 2963  }
 2964
 2965  #endregion
 2966
 2967  #endregion
 2968
 2969  #endregion
 2970
 2971  #endregion
 2972
 2973  #region Parsers
 2974
 2975  // Notes:
 2976  // Parsing uses the Expression class hierarchy with the class atributes to build
 2977  // a library of parsing constants via reflection. Once built, the parsing library
 2978  // is used as a reference to contruct the proper Expression type via a contruction
 2979  // delegate.
 2980
 2981  #region Runtime Built Parsing Libary
 2982
 2983  // Library Building Fields
 2984  internal static bool ParseableLibraryBuilt;
 12985  internal static readonly object ParseableLibraryLock = new();
 2986  // Regex Expressions
 2987  internal const string ParenthesisPattern = @"\(.*\)";
 2988  internal static string? ParsableOperationsRegexPattern;
 2989  internal static string? ParsableOperatorsRegexPattern;
 2990  internal static string? ParsableKnownConstantsRegexPattern;
 2991  internal static string? SpecialStringsPattern;
 2992  // Operation Refrences
 2993  internal static System.Collections.Generic.Dictionary<string, Func<Expression, Unary>>? ParsableUnaryOperations;
 2994  internal static System.Collections.Generic.Dictionary<string, Func<Expression, Expression, Binary>>? ParsableBinaryOpe
 2995  internal static System.Collections.Generic.Dictionary<string, Func<Expression, Expression, Expression, Ternary>>? Pars
 2996  internal static System.Collections.Generic.Dictionary<string, Func<Expression[], Multinary>>? ParsableMultinaryOperati
 2997  // Operator References
 2998  internal static System.Collections.Generic.Dictionary<string, (OperatorPriority, Func<Expression, Unary>)>? ParsableLe
 2999  internal static System.Collections.Generic.Dictionary<string, (OperatorPriority, Func<Expression, Unary>)>? ParsableRi
 3000  internal static System.Collections.Generic.Dictionary<string, (OperatorPriority, Func<Expression, Expression, Binary>)
 3001  // Known Constant References
 3002  internal static System.Collections.Generic.Dictionary<string, Func<KnownConstantOfUnknownType>>? ParsableKnownConstant
 3003
 3004  #region Reflection Code (Actually Building the Parsing Library)
 3005
 3006  internal static void BuildParsableOperationLibrary()
 13007  {
 13008    lock (ParseableLibraryLock)
 13009    {
 13010      if (ParseableLibraryBuilt)
 03011      {
 03012        return;
 3013      }
 3014
 3015      // Unary Operations
 13016      ParsableUnaryOperations = new System.Collections.Generic.Dictionary<string, Func<Expression, Unary>>();
 13017      ParsableLeftUnaryOperators = new System.Collections.Generic.Dictionary<string, (OperatorPriority, Func<Expression,
 13018      ParsableRightUnaryOperators = new System.Collections.Generic.Dictionary<string, (OperatorPriority, Func<Expression
 433019      foreach (Type type in Assembly.GetExecutingAssembly().GetDerivedTypes<Unary>().Where(x => !x.IsAbstract))
 133020      {
 133021        ConstructorInfo? constructorInfo = type.GetConstructor(Ɐ(typeof(Expression)));
 133022        if (constructorInfo is null)
 03023        {
 03024          throw new TowelBugException($"Could not find a {nameof(ConstructorInfo)} when building parsing library");
 3025        }
 133026        ParameterExpression A = System.Linq.Expressions.Expression.Parameter(typeof(Expression));
 133027        NewExpression newExpression = System.Linq.Expressions.Expression.New(constructorInfo, A);
 133028        Func<Expression, Unary> newFunction = System.Linq.Expressions.Expression.Lambda<Func<Expression, Unary>>(newExpr
 133029        string operationName = type.Name;
 133030        if (operationName.Contains('+'))
 03031        {
 03032          int index = operationName.LastIndexOf('+');
 03033          operationName = operationName[(index + 1)..];
 03034        }
 133035        ParsableUnaryOperations.Add(operationName.ToLower(), newFunction);
 133036        OperationAttribute? operationAttribute = type.GetCustomAttribute<OperationAttribute>();
 133037        if (operationAttribute is not null)
 13038        {
 53039          foreach (string representation in operationAttribute.Representations)
 13040          {
 13041            ParsableUnaryOperations.Add(representation.ToLower(), newFunction);
 13042          }
 13043        }
 3044
 3045        // Left Unary Operators
 413046        foreach (LeftUnaryOperatorAttribute @operator in type.GetCustomAttributes<LeftUnaryOperatorAttribute>())
 13047        {
 13048          ParsableLeftUnaryOperators.Add(@operator.Representation.ToLower(), (@operator.Priority, newFunction));
 13049        }
 3050
 3051        // Right Unary Operators
 413052        foreach (RightUnaryOperatorAttribute @operator in type.GetCustomAttributes<RightUnaryOperatorAttribute>())
 13053        {
 13054          ParsableRightUnaryOperators.Add(@operator.Representation.ToLower(), (@operator.Priority, newFunction));
 13055        }
 133056      }
 3057
 3058      // Binary Operations
 13059      ParsableBinaryOperations = new System.Collections.Generic.Dictionary<string, Func<Expression, Expression, Binary>>
 13060      ParsableBinaryOperators = new System.Collections.Generic.Dictionary<string, (OperatorPriority, Func<Expression, Ex
 413061      foreach (Type type in Assembly.GetExecutingAssembly().GetDerivedTypes<Binary>().Where(x => !x.IsAbstract))
 123062      {
 123063        ConstructorInfo? constructorInfo = type.GetConstructor(Ɐ(typeof(Expression), typeof(Expression)));
 123064        if (constructorInfo is null)
 03065        {
 03066          throw new TowelBugException($"Could not find a {nameof(ConstructorInfo)} when building parsing library");
 3067        }
 123068        ParameterExpression A = System.Linq.Expressions.Expression.Parameter(typeof(Expression));
 123069        ParameterExpression B = System.Linq.Expressions.Expression.Parameter(typeof(Expression));
 123070        NewExpression newExpression = System.Linq.Expressions.Expression.New(constructorInfo, A, B);
 123071        Func<Expression, Expression, Binary> newFunction = System.Linq.Expressions.Expression.Lambda<Func<Expression, Ex
 123072        string operationName = type.Name;
 123073        if (operationName.Contains('+'))
 03074        {
 03075          int index = operationName.LastIndexOf('+');
 03076          operationName = operationName[(index + 1)..];
 03077        }
 123078        ParsableBinaryOperations.Add(operationName.ToLower(), newFunction);
 123079        OperationAttribute? operationAttribute = type.GetCustomAttribute<OperationAttribute>();
 123080        if (operationAttribute is not null)
 03081        {
 03082          foreach (string representation in operationAttribute.Representations)
 03083          {
 03084            ParsableBinaryOperations.Add(representation.ToLower(), newFunction);
 03085          }
 03086        }
 3087
 3088        // Binary Operators
 583089        foreach (BinaryOperatorAttribute @operator in type.GetCustomAttributes<BinaryOperatorAttribute>())
 113090        {
 113091          ParsableBinaryOperators.Add(@operator.Representation.ToLower(), (@operator.Priority, newFunction));
 113092        }
 123093      }
 3094
 3095      // Ternary Operations
 13096      ParsableTernaryOperations = new System.Collections.Generic.Dictionary<string, Func<Expression, Expression, Express
 33097      foreach (Type type in Assembly.GetExecutingAssembly().GetDerivedTypes<Ternary>().Where(x => !x.IsAbstract))
 03098      {
 03099        ConstructorInfo? constructorInfo = type.GetConstructor(Ɐ(typeof(Expression), typeof(Expression), typeof(Expressi
 03100        if (constructorInfo is null)
 03101        {
 03102          throw new TowelBugException($"Could not find a {nameof(ConstructorInfo)} when building parsing library");
 3103        }
 03104        ParameterExpression A = System.Linq.Expressions.Expression.Parameter(typeof(Expression));
 03105        ParameterExpression B = System.Linq.Expressions.Expression.Parameter(typeof(Expression));
 03106        ParameterExpression C = System.Linq.Expressions.Expression.Parameter(typeof(Expression));
 03107        NewExpression newExpression = System.Linq.Expressions.Expression.New(constructorInfo, A, B, C);
 03108        Func<Expression, Expression, Expression, Ternary> newFunction = System.Linq.Expressions.Expression.Lambda<Func<E
 03109        string operationName = type.Name;
 03110        if (operationName.Contains('+'))
 03111        {
 03112          int index = operationName.LastIndexOf('+');
 03113          operationName = operationName[(index + 1)..];
 03114        }
 03115        ParsableTernaryOperations.Add(operationName.ToLower(), newFunction);
 03116        OperationAttribute? operationAttribute = type.GetCustomAttribute<OperationAttribute>();
 03117        if (operationAttribute is not null)
 03118        {
 03119          foreach (string representation in operationAttribute.Representations)
 03120          {
 03121            ParsableTernaryOperations.Add(representation.ToLower(), newFunction);
 03122          }
 03123        }
 03124      }
 3125
 3126      // Multinary Operations
 13127      ParsableMultinaryOperations = new System.Collections.Generic.Dictionary<string, Func<Expression[], Multinary>>();
 33128      foreach (Type type in Assembly.GetExecutingAssembly().GetDerivedTypes<Multinary>().Where(x => !x.IsAbstract))
 03129      {
 03130        ConstructorInfo? constructorInfo = type.GetConstructor(Ɐ(typeof(Expression[])));
 03131        if (constructorInfo is null)
 03132        {
 03133          throw new TowelBugException($"Could not find a {nameof(ConstructorInfo)} when building parsing library");
 3134        }
 03135        ParameterExpression A = System.Linq.Expressions.Expression.Parameter(typeof(Expression[]));
 03136        NewExpression newExpression = System.Linq.Expressions.Expression.New(constructorInfo, A);
 03137        Func<Expression[], Multinary> newFunction = System.Linq.Expressions.Expression.Lambda<Func<Expression[], Multina
 03138        string operationName = type.Name;
 03139        if (operationName.Contains('+'))
 03140        {
 03141          int index = operationName.LastIndexOf('+');
 03142          operationName = operationName[(index + 1)..];
 03143        }
 03144        ParsableMultinaryOperations.Add(operationName.ToLower(), newFunction);
 03145        OperationAttribute? operationAttribute = type.GetCustomAttribute<OperationAttribute>();
 03146        if (operationAttribute is not null)
 03147        {
 03148          foreach (string representation in operationAttribute.Representations)
 03149          {
 03150            ParsableMultinaryOperations.Add(representation.ToLower(), newFunction);
 03151          }
 03152        }
 03153      }
 3154
 3155      // Known Constants
 13156      ParsableKnownConstants = new System.Collections.Generic.Dictionary<string, Func<KnownConstantOfUnknownType>>();
 183157      foreach (Type type in Assembly.GetExecutingAssembly().GetDerivedTypes<KnownConstantOfUnknownType>().Where(x => !x.
 53158      {
 53159        ConstructorInfo? constructorInfo = type.GetConstructor(Type.EmptyTypes);
 53160        if (constructorInfo is null)
 03161        {
 03162          throw new TowelBugException($"Could not find a {nameof(ConstructorInfo)} when building parsing library");
 3163        }
 53164        NewExpression newExpression = System.Linq.Expressions.Expression.New(constructorInfo);
 53165        Func<KnownConstantOfUnknownType> newFunction = System.Linq.Expressions.Expression.Lambda<Func<KnownConstantOfUnk
 3166        // string knownConstant = type.ConvertToCsharpSource();
 3167        // if (knownConstant.Contains('+'))
 3168        // {
 3169        //     int index = knownConstant.LastIndexOf('+');
 3170        //     knownConstant = knownConstant.Substring(index + 1);
 3171        // }
 3172        // ParsableKnownConstants.Add(knownConstant.ToLower(), newFunction);
 53173        KnownConstantAttribute? knownConstantAttribute = type.GetCustomAttribute<KnownConstantAttribute>();
 53174        if (knownConstantAttribute is not null)
 13175        {
 53176          foreach (string representation in knownConstantAttribute.Representations)
 13177          {
 13178            ParsableKnownConstants.Add(representation.ToLower(), newFunction);
 13179          }
 13180        }
 53181      }
 3182
 3183      // Build a regex to match any operation
 13184      System.Collections.Generic.IEnumerable<string> operations =
 13185        ParsableUnaryOperations.Keys.Concat(
 13186          ParsableBinaryOperations.Keys.Concat(
 13187            ParsableTernaryOperations.Keys.Concat(
 273188              ParsableMultinaryOperations.Keys))).Select(x => Regex.Escape(x));
 13189      ParsableOperationsRegexPattern = string.Join(@"\s*\(.*\)|", operations) + @"\s *\(.*\)";
 3190
 3191      // Build a regex to match any operator
 13192      System.Collections.Generic.IEnumerable<string> operators =
 13193        ParsableLeftUnaryOperators.Keys.Concat(
 13194          ParsableRightUnaryOperators.Keys.Concat(
 273195            ParsableBinaryOperators.Keys)).Select(x => Regex.Escape(x));
 13196      ParsableOperatorsRegexPattern = string.Join("|", operators);
 3197
 13198      System.Collections.Generic.IEnumerable<string> knownConstants =
 23199        ParsableKnownConstants.Keys.Select(x => Regex.Escape(x));
 13200      ParsableKnownConstantsRegexPattern = string.Join("|", knownConstants);
 3201
 13202      SpecialStringsPattern = string.Join("|", operators.Append(Regex.Escape("(")).Append(Regex.Escape(")")));
 3203
 13204      ParseableLibraryBuilt = true;
 13205    }
 13206  }
 3207
 3208  #endregion
 3209
 3210  #endregion
 3211
 3212  #region System.Linq.Expression
 3213
 3214  /// <summary>Parses a mathematical expression from a linq expression.</summary>
 3215  /// <param name="e">The linq expression to parse.</param>
 3216  /// <returns>The parsed symbolic mathematics linq expression.</returns>
 3217  public static Expression Parse(System.Linq.Expressions.Expression e)
 03218  {
 3219    Expression ParseRecursive(System.Linq.Expressions.Expression expression)
 03220    {
 03221      return expression.NodeType switch
 03222      {
 03223        ExpressionType.Lambda => ParseRecursive(((LambdaExpression)expression).Body),
 03224        ExpressionType.Constant => Constant.BuildGeneric(((ConstantExpression)expression).Value ?? throw new ArgumentExc
 03225        ExpressionType.Parameter => new Variable(((ParameterExpression)expression).Name ?? throw new ArgumentException(p
 03226        ExpressionType.Negate => new Negate(ParseRecursive(((UnaryExpression)expression).Operand)),
 03227        ExpressionType.UnaryPlus => ParseRecursive(((UnaryExpression)expression).Operand),
 03228        ExpressionType.Add => new Add(ParseRecursive(((BinaryExpression)expression).Left), ParseRecursive(((BinaryExpres
 03229        ExpressionType.Subtract => new Subtract(ParseRecursive(((BinaryExpression)expression).Left), ParseRecursive(((Bi
 03230        ExpressionType.Multiply => new Multiply(ParseRecursive(((BinaryExpression)expression).Left), ParseRecursive(((Bi
 03231        ExpressionType.Divide => new Divide(ParseRecursive(((BinaryExpression)expression).Left), ParseRecursive(((Binary
 03232        ExpressionType.Power => new Power(ParseRecursive(((BinaryExpression)expression).Left), ParseRecursive(((BinaryEx
 03233        ExpressionType.Call => ParseMethodCall((MethodCallExpression)expression),
 03234        _ => throw new ArgumentException("The expression could not be parsed.", nameof(e)),
 03235      };
 03236    }
 3237
 3238    Expression ParseMethodCall(MethodCallExpression methodCallExpression)
 03239    {
 03240      MethodInfo methodInfo = methodCallExpression.Method;
 03241      if (methodInfo is null)
 03242      {
 03243        throw new ArgumentException("The expression could not be parsed.", nameof(e));
 3244      }
 3245
 03246      Expression[]? arguments = null;
 03247      if (methodCallExpression.Arguments is not null)
 03248      {
 03249        arguments = new Expression[methodCallExpression.Arguments.Count];
 03250        for (int i = 0; i < arguments.Length; i++)
 03251          arguments[i] = ParseRecursive(methodCallExpression.Arguments[i]);
 03252      }
 3253
 03254      if (!ParseableLibraryBuilt)
 03255      {
 03256        BuildParsableOperationLibrary();
 03257      }
 3258
 03259      string operation = methodInfo.Name.ToLower();
 3260
 03261      if (arguments is null)
 03262      {
 03263        throw new TowelBugException("zero parameter operations are not yet implemented");
 3264      }
 3265
 03266      switch (arguments.Length)
 3267      {
 3268        case 1:
 03269          if (ParsableUnaryOperations!.TryGetValue(operation, out var newUnaryFunction))
 03270          {
 03271            return newUnaryFunction(arguments[0]);
 3272          }
 03273          break;
 3274        case 2:
 03275          if (ParsableBinaryOperations!.TryGetValue(operation, out var newBinaryFunction))
 03276          {
 03277            return newBinaryFunction(arguments[0], arguments[1]);
 3278          }
 03279          break;
 3280        case 3:
 03281          if (ParsableTernaryOperations!.TryGetValue(operation, out var newTernaryFunction))
 03282          {
 03283            return newTernaryFunction(arguments[0], arguments[1], arguments[2]);
 3284          }
 03285          break;
 3286      }
 3287
 03288      if (ParsableMultinaryOperations!.TryGetValue(operation, out var newMultinaryFunction))
 03289      {
 03290        return newMultinaryFunction(arguments);
 3291      }
 3292
 03293      throw new ArgumentException("The expression could not be parsed.", nameof(e));
 03294    }
 3295
 3296    try
 03297    {
 03298      return ParseRecursive(e);
 3299    }
 03300    catch (ArithmeticException arithmeticException)
 03301    {
 03302      throw new ArgumentException("The expression could not be parsed.", nameof(e), arithmeticException);
 3303    }
 03304  }
 3305
 3306  #endregion
 3307
 3308  #region string
 3309
 3310  /// <summary>Parses a symbolic methematics expression with the assumption that it will simplify to a constant.</summar
 3311  /// <typeparam name="T">The generic numerical type to recieve as the outputted type.</typeparam>
 3312  /// <param name="string">The string to be parse.</param>
 3313  /// <param name="tryParse">A function for parsing numerical values into the provided generic type.</param>
 3314  /// <returns>The parsed expression simplified down to a constant value.</returns>
 3315  public static T ParseAndSimplifyToConstant<T>(string @string, Func<string, (bool Success, T? Value)>? tryParse = null)
 03316  {
 03317    tryParse ??= Statics.TryParse<T>;
 03318    var simplified = Parse(@string, tryParse).Simplify();
 03319    if (simplified is Constant<T> constant)
 03320    {
 03321      return constant.Value;
 3322    }
 3323    else
 03324    {
 03325      throw new ArgumentException(paramName: nameof(@string), message: $"{nameof(@string)} could not be simplified to a 
 3326    }
 03327  }
 3328
 3329  /// <summary>Parses a string into a Towel.Mathematics.Symbolics expression tree.</summary>
 3330  /// <typeparam name="T">The type to convert any constants into (ex: float, double, etc).</typeparam>
 3331  /// <param name="string">The expression string to parse.</param>
 3332  /// <param name="tryParse">A parsing function for the provided generic type. This is optional, but highly recommended.
 3333  /// <returns>The parsed Towel.Mathematics.Symbolics expression tree.</returns>
 3334  public static Expression Parse<T>(string @string, Func<string, (bool Success, T? Value)>? tryParse = null)
 3303335  {
 3303336    tryParse ??= Statics.TryParse<T>;
 3337    // Build The Parsing Library
 3303338    if (!ParseableLibraryBuilt)
 13339    {
 13340      BuildParsableOperationLibrary();
 13341    }
 3342    // Error Handling
 3303343    if (string.IsNullOrWhiteSpace(@string))
 03344    {
 03345      throw new ArgumentException("The expression could not be parsed. { " + @string + " }", nameof(@string));
 3346    }
 3347    // Trim
 3303348    @string = @string.Trim();
 3349    // Parse The Next Non-Nested Operator If One Exist
 3303350    if (TryParseNonNestedOperatorExpression<T>(@string, tryParse, out Expression? ParsedNonNestedOperatorExpression))
 863351    {
 863352      return ParsedNonNestedOperatorExpression!;
 3353    }
 3354    // Parse The Next Parenthesis If One Exists
 2443355    if (TryParseParenthesisExpression<T>(@string, tryParse, out Expression? ParsedParenthesisExpression))
 123356    {
 123357      return ParsedParenthesisExpression!;
 3358    }
 3359    // Parse The Next Operation If One Exists
 2323360    if (TryParseOperationExpression<T>(@string, tryParse, out Expression? ParsedOperationExpression))
 03361    {
 03362      return ParsedOperationExpression!;
 3363    }
 3364    // Parse The Next Set Of Variables If Any Exist
 2323365    if (TryParseVariablesExpression<T>(@string, tryParse, out Expression? ParsedVeriablesExpression))
 03366    {
 03367      return ParsedVeriablesExpression!;
 3368    }
 3369    // Parse The Next Known Constant Expression If Any Exist
 2323370    if (TryParseKnownConstantExpression<T>(@string, tryParse, out Expression? ParsedKnownConstantExpression))
 183371    {
 183372      return ParsedKnownConstantExpression!;
 3373    }
 3374    // Parse The Next Constant Expression If Any Exist
 2143375    if (TryParseConstantExpression<T>(@string, tryParse, out Expression? ParsedConstantExpression))
 2143376    {
 2143377      return ParsedConstantExpression!;
 3378    }
 3379    // Invalid Or Non-Supported Expression
 03380    throw new ArgumentException("The expression could not be parsed. { " + @string + " }", nameof(@string));
 3303381  }
 3382
 3383  internal static bool TryParseNonNestedOperatorExpression<T>(string @string, Func<string, (bool Success, T? Value)> try
 3303384  {
 3385    // Try to match the operators pattern built at runtime based on the symbolic tree hierarchy
 3303386    MatchCollection operatorMatches = Regex.Matches(@string, ParsableOperatorsRegexPattern!, RegexOptions.RightToLeft);
 3303387    MatchCollection specialStringMatches = Regex.Matches(@string, SpecialStringsPattern!, RegexOptions.RightToLeft);
 3303388    if (operatorMatches.Count > 0)
 983389    {
 3390      // Find the first operator with the highest available priority
 983391      Match? @operator = null;
 983392      OperatorPriority priority = default;
 983393      int currentOperatorMatch = 0;
 983394      int scope = 0;
 983395      bool isUnaryLeftOperator = false;
 983396      bool isUnaryRightOperator = false;
 983397      bool isBinaryOperator = false;
 8943398      for (int i = @string.Length - 1; i >= 0; i--)
 4473399      {
 4473400        switch (@string[i])
 3401        {
 643402          case ')': scope++; break;
 403403          case '(': scope--; break;
 3404        }
 3405
 3406        // Handle Input Errors
 4473407        if (scope < 0)
 03408        {
 03409          throw new ArgumentException("The expression could not be parsed. { " + @string + " }", nameof(@string));
 3410        }
 3411
 4473412        Match currentMatch = operatorMatches[currentOperatorMatch];
 4473413        if (currentMatch.Index == i)
 1363414        {
 1363415          if (scope is 0)
 1043416          {
 1043417            Match? previousMatch = currentOperatorMatch != 0 ? operatorMatches[currentOperatorMatch - 1] : null;
 1043418            Match? nextMatch = currentOperatorMatch != operatorMatches.Count - 1 ? operatorMatches[currentOperatorMatch 
 3419
 3420            // We found an operator in the current scope
 3421            // Now we need to determine if it is a unary-left, unary-right, or binary operator
 3422
 3423            bool IsUnaryLeftOperator()
 1043424            {
 1043425              if (!ParsableLeftUnaryOperators!.ContainsKey(currentMatch.Value))
 843426              {
 843427                return false;
 3428              }
 3429
 203430              int rightIndex = currentMatch.Index - currentMatch.Length + 1;
 203431              if (rightIndex <= 0)
 53432              {
 53433                return true;
 3434              }
 153435              Match? leftSpecialMatch = null;
 1093436              foreach (Match match in specialStringMatches)
 343437              {
 343438                if (match.Index < currentMatch.Index)
 43439                {
 43440                  leftSpecialMatch = match;
 43441                  break;
 3442                }
 303443              }
 153444              if (leftSpecialMatch is null)
 113445              {
 113446                string substring = @string[..rightIndex];
 113447                return string.IsNullOrWhiteSpace(substring);
 3448              }
 43449              else if (ParsableRightUnaryOperators!.ContainsKey(leftSpecialMatch.Value)) // This will need to be fixed i
 13450              {
 13451                return false;
 3452              }
 3453              else
 33454              {
 33455                int leftIndex = leftSpecialMatch.Index + 1;
 33456                string substring = @string[leftIndex..rightIndex];
 33457                return string.IsNullOrWhiteSpace(substring);
 3458              }
 1043459            }
 3460
 3461            bool IsUnaryRightOperator()
 983462            {
 983463              if (!ParsableRightUnaryOperators!.ContainsKey(currentMatch.Value))
 803464              {
 803465                return false;
 3466              }
 3467
 183468              int leftIndex = currentMatch.Index;
 183469              if (leftIndex >= @string.Length - 1)
 143470              {
 143471                return true;
 3472              }
 43473              Match? rightSpecialMatch = null;
 243474              foreach (Match match in specialStringMatches)
 83475              {
 83476                if (match.Index <= currentMatch.Index)
 43477                {
 43478                  break;
 3479                }
 43480                rightSpecialMatch = match;
 43481              }
 43482              if (rightSpecialMatch is null)
 03483              {
 03484                return string.IsNullOrWhiteSpace(@string[(leftIndex + 1)..]);
 3485              }
 3486              else
 43487              {
 43488                int rightIndex = rightSpecialMatch.Index - rightSpecialMatch.Length;
 43489                return string.IsNullOrWhiteSpace(@string[leftIndex..rightIndex]);
 3490              }
 983491            }
 3492
 1043493            if (IsUnaryLeftOperator())
 63494            {
 63495              if (@operator is null || priority > ParsableLeftUnaryOperators![currentMatch.Value].Item1)
 53496              {
 53497                @operator = currentMatch;
 53498                isUnaryLeftOperator = true;
 53499                isUnaryRightOperator = false;
 53500                isBinaryOperator = false;
 53501                priority = ParsableLeftUnaryOperators![currentMatch.Value].Item1;
 53502              }
 63503            }
 983504            else if (IsUnaryRightOperator())
 143505            {
 143506              if (@operator is null || priority > ParsableRightUnaryOperators![currentMatch.Value].Item1)
 143507              {
 143508                @operator = currentMatch;
 143509                isUnaryLeftOperator = false;
 143510                isUnaryRightOperator = true;
 143511                isBinaryOperator = false;
 143512                priority = ParsableRightUnaryOperators![currentMatch.Value].Item1;
 143513              }
 143514            }
 3515            else
 843516            {
 843517              if (ParsableBinaryOperators!.ContainsKey(currentMatch.Value))
 803518              {
 3519                // Binary Operator
 803520                if (@operator is null || priority > ParsableBinaryOperators[currentMatch.Value].Item1)
 743521                {
 743522                  @operator = currentMatch;
 743523                  isUnaryLeftOperator = false;
 743524                  isUnaryRightOperator = false;
 743525                  isBinaryOperator = true;
 743526                  priority = ParsableBinaryOperators[currentMatch.Value].Item1;
 743527                }
 803528              }
 843529            }
 1043530          }
 1363531          currentOperatorMatch++;
 3532
 1363533          if (currentOperatorMatch >= operatorMatches.Count)
 983534          {
 983535            break;
 3536          }
 383537        }
 3493538      }
 3539
 3540      // if an operator was found, parse the expression
 983541      if (@operator is not null)
 863542      {
 863543        if (isUnaryLeftOperator)
 43544        {
 43545          string a = @string[(@operator.Index + @operator.Length)..];
 43546          Expression A = Parse(a, tryParse);
 43547          expression = ParsableLeftUnaryOperators![@operator.Value].Item2(A);
 43548          return true;
 3549        }
 823550        else if (isUnaryRightOperator)
 103551        {
 103552          string a = @string[..@operator.Index];
 103553          Expression A = Parse(a, tryParse);
 103554          expression = ParsableRightUnaryOperators![@operator.Value].Item2(A);
 103555          return true;
 3556        }
 723557        else if (isBinaryOperator)
 723558        {
 723559          string a = @string[..@operator.Index];
 723560          Expression A = Parse(a, tryParse);
 723561          string b = @string[(@operator.Index + @operator.Length)..];
 723562          Expression B = Parse(b, tryParse);
 723563          expression = ParsableBinaryOperators![@operator.Value].Item2(A, B);
 723564          return true;
 3565        }
 03566      }
 123567    }
 3568
 3569    // No non-nested operator patterns found. Fall back.
 2443570    expression = null;
 2443571    return false;
 3303572  }
 3573
 3574  internal static bool TryParseParenthesisExpression<T>(string @string, Func<string, (bool Success, T? Value)> tryParse,
 2443575  {
 3576    // Try to match a parenthesis pattern.
 2443577    Match parenthesisMatch = Regex.Match(@string, ParenthesisPattern);
 2443578    Match operationMatch = Regex.Match(@string, ParsableOperationsRegexPattern!);
 2443579    if (parenthesisMatch.Success)
 123580    {
 123581      if (operationMatch.Success && parenthesisMatch.Index > operationMatch.Index)
 03582      {
 3583        // The next set of parenthesis are part of an operation. Fall back and
 3584        // let the TryParseOperationExpression handle it.
 03585        expression = null;
 03586        return false;
 3587      }
 3588
 3589      // Parse the nested expression
 123590      string nestedExpression = parenthesisMatch.Value.Substring(1, parenthesisMatch.Length - 2);
 123591      expression = Parse(nestedExpression, tryParse);
 3592
 3593      // Check for implicit multiplications to the left of the parenthesis pattern
 123594      if (parenthesisMatch.Index > 0)
 03595      {
 03596        string leftExpression = @string[..parenthesisMatch.Index];
 03597        expression *= Parse(leftExpression, tryParse);
 03598      }
 3599
 3600      // Check for implicit multiplications to the right of the parenthesis pattern
 123601      int right_start = parenthesisMatch.Index + parenthesisMatch.Length;
 123602      if (right_start != @string.Length)
 03603      {
 03604        string rightExpression = @string[right_start..];
 03605        expression *= Parse(rightExpression, tryParse);
 03606      }
 3607
 3608      // Parsing was successful
 123609      return true;
 3610    }
 3611
 3612    // No parenthesis pattern found. Fall back.
 2323613    expression = null;
 2323614    return false;
 2443615  }
 3616
 3617  internal static bool TryParseOperationExpression<T>(string @string, Func<string, (bool Success, T? Value)> tryParse, o
 2323618  {
 2323619    expression = null;
 2323620    Match operationMatch = Regex.Match(@string, ParsableOperationsRegexPattern!);
 3621
 2323622    if (operationMatch.Success)
 03623    {
 03624      string operationMatch_Value = operationMatch.Value;
 03625      string operation = operationMatch_Value[..operationMatch_Value.IndexOf('(')];
 03626      Match parenthesisMatch = Regex.Match(@string, ParenthesisPattern);
 03627      string parenthesisMatch_Value = parenthesisMatch.Value;
 03628      ListArray<string> operandSplits = SplitOperands(parenthesisMatch_Value[1..^1]);
 3629
 03630      switch (operandSplits.Count)
 3631      {
 3632        case 1:
 03633          if (ParsableUnaryOperations!.TryGetValue(operation, out Func<Expression, Unary>? newUnaryFunction))
 03634          {
 03635            expression = newUnaryFunction(Parse<T>(operandSplits[0]));
 03636          }
 03637          break;
 3638        case 2:
 03639          if (ParsableBinaryOperations!.TryGetValue(operation, out Func<Expression, Expression, Binary>? newBinaryFuncti
 03640          {
 03641            expression = newBinaryFunction(Parse<T>(operandSplits[0]), Parse<T>(operandSplits[1]));
 03642          }
 03643          break;
 3644        case 3:
 03645          if (ParsableTernaryOperations!.TryGetValue(operation, out Func<Expression, Expression, Expression, Ternary>? n
 03646          {
 03647            expression = newTernaryFunction(Parse<T>(operandSplits[0]), Parse<T>(operandSplits[2]), Parse<T>(operandSpli
 03648          }
 03649          break;
 3650      }
 03651      if (ParsableMultinaryOperations!.TryGetValue(operation, out Func<Expression[], Multinary>? newMultinaryFunction))
 03652      {
 03653        expression = newMultinaryFunction(operandSplits.Select(x => Parse<T>(x)).ToArray());
 03654      }
 03655      if (expression is null)
 03656      {
 03657        throw new ArgumentException("The expression could not be parsed. { " + @string + " }", nameof(@string));
 3658      }
 3659      // handle implicit multiplications if any exist
 03660      if (operationMatch.Index != 0) // Left
 03661      {
 03662        Expression A = Parse(@string[..operationMatch.Index], tryParse);
 03663        expression *= A;
 03664      }
 03665      if (operationMatch.Length + operationMatch.Index < @string.Length) // Right
 03666      {
 03667        Expression A = Parse(@string[(operationMatch.Length + operationMatch.Index)..], tryParse);
 03668        expression *= A;
 03669      }
 03670      return true;
 3671    }
 3672
 3673    // No operation pattern found. Fall back.
 2323674    return false;
 2323675  }
 3676
 3677  internal static ListArray<string> SplitOperands(string @string)
 03678  {
 03679    ListArray<string> operands = new();
 03680    int scope = 0;
 03681    int operandStart = 0;
 03682    for (int i = 0; i < @string.Length; i++)
 03683    {
 03684      switch (@string[i])
 3685      {
 03686        case '(': scope++; break;
 03687        case ')': scope--; break;
 3688        case ',':
 03689          if (scope is 0)
 03690          {
 03691            operands.Add(@string[operandStart..i]);
 03692          }
 03693          break;
 3694      }
 03695    }
 03696    if (scope != 0)
 03697    {
 03698      throw new ArgumentException("The expression could not be parsed. { " + @string + " }", nameof(@string));
 3699    }
 03700    operands.Add(@string[operandStart..]);
 03701    return operands;
 03702  }
 3703
 3704  internal static bool TryParseVariablesExpression<T>(string @string, Func<string, (bool Success, T? Value)> tryParse, o
 2323705  {
 2323706    string variablePattern = @"\[.*\]";
 3707
 3708    // extract and parse variables
 2323709    System.Collections.Generic.IEnumerable<Expression> variables =
 2323710      Regex.Matches(@string, variablePattern)
 2323711      .Cast<Match>()
 2323712      .Select(x => new Variable(x.Value[1..^1]));
 3713
 3714    // if no variables, fall back
 2323715    if (!variables.Any())
 2323716    {
 2323717      parsedExpression = null;
 2323718      return false;
 3719    }
 3720
 3721    // assume the remaining string splits are constants and try to parse them
 03722    System.Collections.Generic.IEnumerable<Expression?> constants =
 03723      Regex.Split(@string, variablePattern)
 03724      .Where(x => !string.IsNullOrWhiteSpace(x))
 03725      .Select(x =>
 03726      {
 03727        TryParseConstantExpression(x, tryParse, out var exp);
 03728        return exp;
 03729      });
 3730
 3731    // multiply all the expressions together, starting with the constants because
 3732    // it will look better if converted to a string
 03733    bool set = false;
 03734    parsedExpression = null;
 03735    foreach (var constant in constants.Concat(variables))
 03736    {
 03737      if (!set)
 03738      {
 03739        parsedExpression = constant;
 03740        set = true;
 03741      }
 3742      else
 03743      {
 03744        if (parsedExpression is null)
 03745        {
 03746          throw new TowelBugException($"Encountered null {nameof(parsedExpression)} in {nameof(TryParseVariablesExpressi
 3747        }
 03748        if (constant is null)
 03749        {
 03750          throw new TowelBugException($"Encountered null {nameof(constant)} in {nameof(TryParseVariablesExpression)}.");
 3751        }
 03752        parsedExpression *= constant;
 03753      }
 03754    }
 03755    return true;
 2323756  }
 3757
 3758  internal static bool TryParseKnownConstantExpression<T>(string @string, Func<string, (bool Success, T? Value)> tryPars
 2323759  {
 2323760    Match knownConstantMatch = Regex.Match(@string, ParsableKnownConstantsRegexPattern!);
 3761
 2323762    if (knownConstantMatch.Success)
 183763    {
 183764      parsedExpression = ParsableKnownConstants![knownConstantMatch.Value]().ApplyType<T>();
 3765
 3766      // implied multiplications to the left and right
 183767      if (knownConstantMatch.Index != 0)
 63768      {
 63769        Expression A = Parse<T>(@string[..knownConstantMatch.Index], tryParse);
 63770        parsedExpression *= A;
 63771      }
 183772      if (knownConstantMatch.Index < @string.Length - 1)
 03773      {
 03774        Expression B = Parse<T>(@string[(knownConstantMatch.Index + 1)..], tryParse);
 03775        parsedExpression *= B;
 03776      }
 183777      return true;
 3778    }
 3779
 2143780    parsedExpression = null;
 2143781    return false;
 2323782  }
 3783
 3784  internal static bool TryParseConstantExpression<T>(string @string, Func<string, (bool Success, T? Value)> tryParse, ou
 2143785  {
 2143786    var (parseSuccess, parseValue) = tryParse(@string);
 2143787    if (parseSuccess)
 2143788    {
 2143789      parsedExpression = new Constant<T?>(parseValue);
 2143790      return true;
 3791    }
 03792    int decimalIndex = -1;
 03793    for (int i = 0; i < @string.Length; i++)
 03794    {
 03795      char character = @string[i];
 03796      if (character == '.')
 03797      {
 03798        if (decimalIndex >= 0 || i == @string.Length - 1)
 03799        {
 03800          parsedExpression = null;
 03801          return false;
 3802        }
 03803        decimalIndex = i;
 03804      }
 03805      if ('0' > character && character > '9')
 03806      {
 03807        parsedExpression = null;
 03808        return false;
 3809      }
 03810    }
 03811    if (decimalIndex >= 0)
 03812    {
 3813      string wholeNumberString;
 03814      if (decimalIndex is 0)
 03815      {
 03816        wholeNumberString = "0";
 03817      }
 3818      else
 03819      {
 03820        wholeNumberString = @string[..decimalIndex];
 03821      }
 03822      string decimalPlacesString = @string[(decimalIndex + 1)..];
 3823
 03824      int zeroCount = 0;
 03825      while (decimalPlacesString[zeroCount] == '0')
 03826      {
 03827        zeroCount++;
 03828      }
 3829
 03830      if (int.TryParse(wholeNumberString, out int wholeNumberInt) &&
 03831        int.TryParse(decimalPlacesString, out int decimalPlacesInt))
 03832      {
 03833        T wholeNumber = Convert<int, T>(wholeNumberInt);
 03834        T decimalPlaces = Convert<int, T>(decimalPlacesInt);
 03835        while (GreaterThanOrEqual(decimalPlaces, Towel.Constant<T>.One))
 03836        {
 03837          decimalPlaces = Division(decimalPlaces, Towel.Constant<T>.Ten);
 03838        }
 03839        for (; zeroCount > 0; zeroCount--)
 03840        {
 03841          decimalPlaces = Division(decimalPlaces, Towel.Constant<T>.Ten);
 03842        }
 03843        parsedExpression = new Constant<T>(Addition(wholeNumber, decimalPlaces));
 03844        return true;
 3845      }
 03846    }
 3847    else
 03848    {
 03849      if (int.TryParse(@string, out int parsedInt))
 03850      {
 03851        parsedExpression = new Constant<T>(Convert<int, T>(parsedInt));
 03852        return true;
 3853      }
 03854    }
 03855    parsedExpression = null;
 03856    return false;
 2143857  }
 3858
 3859  #endregion
 3860
 3861  #endregion
 3862}

Methods/Properties

.ctor(...)
get_Representations()
.ctor(...)
.ctor(...)
.ctor(...)
.ctor(...)
.ctor(...)
Simplify()
Substitute(...)
Substitute(...)
SubstitutionHack(...)
Derive(...)
Integrate(...)
op_UnaryNegation(...)
op_Addition(...)
op_Subtraction(...)
op_Multiply(...)
op_Division(...)
op_Equality(...)
op_Inequality(...)
op_LessThan(...)
op_GreaterThan(...)
op_ExclusiveOr(...)
get_Name()
.ctor(...)
Clone()
Substitute(...)
ToString()
Equals(...)
GetHashCode()
get_IsKnownConstant()
get_IsZero()
get_IsOne()
get_IsTwo()
get_IsThree()
get_IsPi()
Simplify(...)
.cctor()
BuildGeneric(...)
get_IsKnownConstant()
.ctor()
get_IsPi()
get_IsNegative()
ApplyType()
Clone()
ToString()
Equals(...)
GetHashCode()
.cctor()
.ctor()
get_IsZero()
get_IsNegative()
ApplyType()
Clone()
ToString()
Equals(...)
.cctor()
GetHashCode()
.ctor()
get_IsOne()
get_IsNegative()
ApplyType()
Clone()
ToString()
Equals(...)
.cctor()
GetHashCode()
.ctor()
get_IsTwo()
get_IsNegative()
ApplyType()
Clone()
ToString()
Equals(...)
.cctor()
GetHashCode()
.ctor()
get_IsThree()
get_IsNegative()
ApplyType()
Clone()
ToString()
Equals(...)
.cctor()
GetHashCode()
get_IsZero()
get_IsOne()
get_IsTwo()
get_IsThree()
get_IsNegative()
.ctor(...)
Simplify(...)
Clone()
ToString()
Equals(...)
.cctor()
GetHashCode()
get_IsKnownConstant()
.ctor(...)
.ctor()
get_IsPi()
Clone()
ToString()
Equals(...)
.cctor()
GetHashCode()
.ctor()
get_IsZero()
Clone()
ToString()
Equals(...)
.cctor()
GetHashCode()
.ctor()
get_IsOne()
Clone()
ToString()
Equals(...)
.cctor()
GetHashCode()
.ctor()
get_IsTwo()
Clone()
ToString()
Equals(...)
.cctor()
GetHashCode()
.ctor()
get_IsThree()
Clone()
ToString()
Equals(...)
.cctor()
GetHashCode()
.ctor()
Clone()
ToString()
Equals(...)
.cctor()
GetHashCode()
.ctor()
Clone()
ToString()
Equals(...)
.cctor()
GetHashCode()
Simplify(...)
SimplifyHack(...)
get_A()
.ctor(...)
Equals(...)
.ctor(...)
Simplify()
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
get_A()
get_B()
.ctor(...)
Equals(...)
.ctor(...)
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
.ctor(...)
Simplify()
Simplify(...)
Clone()
Substitute(...)
ToString()
get_A()
get_B()
get_C()
.ctor(...)
Equals(...)
get_Operands()
.ctor(...)
.cctor()
BuildParsableOperationLibrary()
Parse(...)
ParseAndSimplifyToConstant(...)
Parse(...)
TryParseNonNestedOperatorExpression(...)
TryParseParenthesisExpression(...)
TryParseOperationExpression(...)
SplitOperands(...)
TryParseVariablesExpression(...)
TryParseKnownConstantExpression(...)
TryParseConstantExpression(...)