mirror of
https://github.com/0xJ1M/MathsEngine.git
synced 2026-06-05 01:10:08 +00:00
Merge branch 'main' into feature/AddFunctionEvaluationSupport
This commit is contained in:
@@ -78,10 +78,8 @@ namespace EngineTests.Parser_Tests.Nodes
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestNodeFactoryNumericNodesOnDefinedTypes()
|
public void TestNodeFactoryNumericNodesOnDefinedTypes()
|
||||||
{
|
{
|
||||||
Token test_token1 = new("100", Token.Type.Numeric, Token.NumericType.Integer, 0);
|
|
||||||
Token test_token2 = new("100.5", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
Token test_token2 = new("100.5", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||||
|
|
||||||
BaseNode testNode1 = NodeFactory.CreateNumericNode(test_token1);
|
|
||||||
BaseNode testNode2 = NodeFactory.CreateNumericNode(test_token2);
|
BaseNode testNode2 = NodeFactory.CreateNumericNode(test_token2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Remove="Parser\Nodes\NumericIntegerNode.cs" />
|
||||||
<Compile Remove="Parser\Nodes\TreeNode.cs" />
|
<Compile Remove="Parser\Nodes\TreeNode.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -105,6 +105,28 @@ namespace MathEngine.Parser.Parser
|
|||||||
return lhs.Divide(rhs);
|
return lhs.Divide(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Base method for exponentiating two nodes, returning another BaseNode object
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="otherNode">The node which will be the power to raise the current instance to</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="InvalidOperationException"></exception>
|
||||||
|
protected virtual BaseNode Exponentiate(BaseNode otherNode)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Attempted to call BaseNode _exponentiate, which is invalid!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Base operator for exponentiating two Base Nodes
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">The left BaseNode</param>
|
||||||
|
/// <param name="rhs">The right BaseNode</param>
|
||||||
|
/// <returns>The exponentiating of the two BaseNodes, as defined by the calling type</returns>
|
||||||
|
public static BaseNode operator ^(BaseNode lhs, BaseNode rhs)
|
||||||
|
{
|
||||||
|
return lhs.Exponentiate(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Abstract Base method that evaluates the current Node
|
/// Abstract Base method that evaluates the current Node
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace MathEngine.Parser.Parser
|
|||||||
case Token.Type.Division:
|
case Token.Type.Division:
|
||||||
return new BinaryNode(LeftBranch, RightBranch, (a, b) => a / b);
|
return new BinaryNode(LeftBranch, RightBranch, (a, b) => a / b);
|
||||||
case Token.Type.Exponentiation:
|
case Token.Type.Exponentiation:
|
||||||
throw new NotImplementedException("Exponentiation is not implemented at this time");
|
return new BinaryNode(LeftBranch, RightBranch, (a, b) => a ^ b);
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException("Attempted to create a BinaryNode with an invalid operation!");
|
throw new NotImplementedException("Attempted to create a BinaryNode with an invalid operation!");
|
||||||
}
|
}
|
||||||
@@ -72,9 +72,9 @@ namespace MathEngine.Parser.Parser
|
|||||||
switch (CurrentToken.NumericalType)
|
switch (CurrentToken.NumericalType)
|
||||||
{
|
{
|
||||||
case Token.NumericType.Integer:
|
case Token.NumericType.Integer:
|
||||||
return new NumericNode<Int64>(Int64.Parse(CurrentToken.TokenValue));
|
throw new NotImplementedException("Integer Numbers are not implemented at this time");
|
||||||
case Token.NumericType.Decimal:
|
case Token.NumericType.Decimal:
|
||||||
return new NumericNode<Decimal>(Decimal.Parse(CurrentToken.TokenValue));
|
return new NumericNode<decimal>(Decimal.Parse(CurrentToken.TokenValue));
|
||||||
case Token.NumericType.Complex:
|
case Token.NumericType.Complex:
|
||||||
throw new NotImplementedException("Complex Numbers are not implemented at this time");
|
throw new NotImplementedException("Complex Numbers are not implemented at this time");
|
||||||
default:
|
default:
|
||||||
|
|||||||
90
MathEngine/MathEngine/Parser/Nodes/NumericIntegerNode.cs
Normal file
90
MathEngine/MathEngine/Parser/Nodes/NumericIntegerNode.cs
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
using MathEngine.Parser.Parser;
|
||||||
|
using MathEngine.Parser.Parser.Nodes;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MathEngine.Parser.Nodes
|
||||||
|
{
|
||||||
|
internal class NumericIntegerNode: BaseNode
|
||||||
|
{
|
||||||
|
private readonly decimal Value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialises a new instance of a NumericNode with a given Token
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The token for the nodes value</param>
|
||||||
|
public NumericIntegerNode(decimal value)
|
||||||
|
{
|
||||||
|
this.Children = null;
|
||||||
|
this.Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override BaseNode Add(BaseNode otherNode)
|
||||||
|
{
|
||||||
|
if (otherNode is NumericIntegerNode)
|
||||||
|
{
|
||||||
|
NumericIntegerNode rhs = (NumericIntegerNode)otherNode;
|
||||||
|
return new NumericIntegerNode(Value + rhs.Value);
|
||||||
|
}
|
||||||
|
throw new InvalidOperationException("Attempted Invalid operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override BaseNode Subtract(BaseNode otherNode)
|
||||||
|
{
|
||||||
|
if (otherNode is NumericIntegerNode)
|
||||||
|
{
|
||||||
|
NumericIntegerNode rhs = (NumericIntegerNode)otherNode;
|
||||||
|
return new NumericIntegerNode(Value - rhs.Value);
|
||||||
|
}
|
||||||
|
throw new InvalidOperationException("Attempted Invalid operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override BaseNode Multiply(BaseNode otherNode)
|
||||||
|
{
|
||||||
|
if (otherNode is NumericIntegerNode)
|
||||||
|
{
|
||||||
|
NumericIntegerNode rhs = (NumericIntegerNode)otherNode;
|
||||||
|
return new NumericIntegerNode(Value * rhs.Value);
|
||||||
|
}
|
||||||
|
throw new InvalidOperationException("Attempted Invalid operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override BaseNode Divide(BaseNode otherNode)
|
||||||
|
{
|
||||||
|
if (otherNode is NumericIntegerNode)
|
||||||
|
{
|
||||||
|
NumericIntegerNode rhs = (NumericIntegerNode)otherNode;
|
||||||
|
return new NumericIntegerNode(Value / rhs.Value);
|
||||||
|
}
|
||||||
|
throw new InvalidOperationException("Attempted Invalid operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override BaseNode Exponentiate(BaseNode otherNode)
|
||||||
|
{
|
||||||
|
if (otherNode is NumericIntegerNode)
|
||||||
|
{
|
||||||
|
NumericIntegerNode rhs = (NumericIntegerNode)otherNode;
|
||||||
|
return new NumericIntegerNode((Int64)(Math.Pow((double)(Value), (double)rhs.Value)));
|
||||||
|
}
|
||||||
|
throw new InvalidOperationException("Attempted Invalid operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Evaluates the Numeric Node by simply returning the current instance
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override BaseNode Evaluate()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Value.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,13 +7,13 @@ namespace MathEngine.Parser.Parser.Nodes
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class NumericNode<T> : BaseNode where T: INumber<T>
|
internal class NumericNode<T> : BaseNode where T: INumber<T>
|
||||||
{
|
{
|
||||||
private readonly T Value;
|
private readonly decimal Value;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initialises a new instance of a NumericNode with a given Token
|
/// Initialises a new instance of a NumericNode with a given Token
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The token for the nodes value</param>
|
/// <param name="value">The token for the nodes value</param>
|
||||||
public NumericNode(T value)
|
public NumericNode(decimal value)
|
||||||
{
|
{
|
||||||
this.Children = null;
|
this.Children = null;
|
||||||
this.Value = value;
|
this.Value = value;
|
||||||
@@ -21,40 +21,50 @@ namespace MathEngine.Parser.Parser.Nodes
|
|||||||
|
|
||||||
protected override BaseNode Add(BaseNode otherNode)
|
protected override BaseNode Add(BaseNode otherNode)
|
||||||
{
|
{
|
||||||
if (otherNode is NumericNode<T>)
|
if (otherNode is NumericNode<decimal>)
|
||||||
{
|
{
|
||||||
NumericNode<T> rhs = (NumericNode<T>)otherNode;
|
NumericNode<decimal> rhs = (NumericNode<decimal>)otherNode;
|
||||||
return new NumericNode<T>(Value + rhs.Value);
|
return new NumericNode<decimal>(Value + rhs.Value);
|
||||||
}
|
}
|
||||||
throw new InvalidOperationException("Attempted Invalid operation");
|
throw new InvalidOperationException("Attempted Invalid operation");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override BaseNode Subtract(BaseNode otherNode)
|
protected override BaseNode Subtract(BaseNode otherNode)
|
||||||
{
|
{
|
||||||
if (otherNode is NumericNode<T>)
|
if (otherNode is NumericNode<decimal>)
|
||||||
{
|
{
|
||||||
NumericNode<T> rhs = (NumericNode<T>)otherNode;
|
NumericNode<decimal> rhs = (NumericNode<decimal>)otherNode;
|
||||||
return new NumericNode<T>(Value - rhs.Value);
|
return new NumericNode<decimal>(Value - rhs.Value);
|
||||||
}
|
}
|
||||||
throw new InvalidOperationException("Attempted Invalid operation");
|
throw new InvalidOperationException("Attempted Invalid operation");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override BaseNode Multiply(BaseNode otherNode)
|
protected override BaseNode Multiply(BaseNode otherNode)
|
||||||
{
|
{
|
||||||
if (otherNode is NumericNode<T>)
|
if (otherNode is NumericNode<decimal>)
|
||||||
{
|
{
|
||||||
NumericNode<T> rhs = (NumericNode<T>)otherNode;
|
NumericNode<decimal> rhs = (NumericNode<decimal>)otherNode;
|
||||||
return new NumericNode<T>(Value * rhs.Value);
|
return new NumericNode<decimal>(Value * rhs.Value);
|
||||||
}
|
}
|
||||||
throw new InvalidOperationException("Attempted Invalid operation");
|
throw new InvalidOperationException("Attempted Invalid operation");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override BaseNode Divide(BaseNode otherNode)
|
protected override BaseNode Divide(BaseNode otherNode)
|
||||||
{
|
{
|
||||||
if (otherNode is NumericNode<T>)
|
if (otherNode is NumericNode<decimal>)
|
||||||
{
|
{
|
||||||
NumericNode<T> rhs = (NumericNode<T>)otherNode;
|
NumericNode<decimal> rhs = (NumericNode<decimal>)otherNode;
|
||||||
return new NumericNode<T>(Value / rhs.Value);
|
return new NumericNode<decimal>(Value / rhs.Value);
|
||||||
|
}
|
||||||
|
throw new InvalidOperationException("Attempted Invalid operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override BaseNode Exponentiate(BaseNode otherNode)
|
||||||
|
{
|
||||||
|
if (otherNode is NumericNode<decimal>)
|
||||||
|
{
|
||||||
|
NumericNode<decimal> rhs = (NumericNode<decimal>)otherNode;
|
||||||
|
return new NumericNode<decimal>((decimal)(Math.Pow((double)Value, (double)(rhs.Value))));
|
||||||
}
|
}
|
||||||
throw new InvalidOperationException("Attempted Invalid operation");
|
throw new InvalidOperationException("Attempted Invalid operation");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ namespace MathEngine.Parser.Parser
|
|||||||
case Token.Type.Subtraction:
|
case Token.Type.Subtraction:
|
||||||
case Token.Type.Multiplication:
|
case Token.Type.Multiplication:
|
||||||
case Token.Type.Division:
|
case Token.Type.Division:
|
||||||
|
case Token.Type.Exponentiation:
|
||||||
while ((OperatorStack.Count != 0 && ((((OperatorStack.Peek().Token_Type == Token.Type.Function) | (OperatorPrecedence(OperatorStack.Peek()) > OperatorPrecedence(CurrentToken)) | ((OperatorPrecedence(OperatorStack.Peek()) == OperatorPrecedence(CurrentToken)) & (IsLeftAssociatve(CurrentToken)))) && !(OperatorStack.Peek().Token_Type == Token.Type.LeftParenthesis)))))
|
while ((OperatorStack.Count != 0 && ((((OperatorStack.Peek().Token_Type == Token.Type.Function) | (OperatorPrecedence(OperatorStack.Peek()) > OperatorPrecedence(CurrentToken)) | ((OperatorPrecedence(OperatorStack.Peek()) == OperatorPrecedence(CurrentToken)) & (IsLeftAssociatve(CurrentToken)))) && !(OperatorStack.Peek().Token_Type == Token.Type.LeftParenthesis)))))
|
||||||
{
|
{
|
||||||
OutputStack.Push(OperatorStack.Pop());
|
OutputStack.Push(OperatorStack.Pop());
|
||||||
|
|||||||
@@ -36,6 +36,11 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static Token RightParenthesis = new Token(")", Token.Type.RightParenthesis, Token.NumericType.NaN, 0);
|
public readonly static Token RightParenthesis = new Token(")", Token.Type.RightParenthesis, Token.NumericType.NaN, 0);
|
||||||
|
|
||||||
|
/// Represents the token for ^
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Token Exponentiation = new("^", Type.Exponentiation, NumericType.NaN, 0);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enum representing the token type
|
/// Enum representing the token type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
'-' => Token.Minus,
|
'-' => Token.Minus,
|
||||||
'*' => Token.Multiply,
|
'*' => Token.Multiply,
|
||||||
'/' => Token.Divide,
|
'/' => Token.Divide,
|
||||||
|
'^' => Token.Exponentiation,
|
||||||
_ => throw new Exception(String.Format("Character {0} is not a defined operator", curChar)),
|
_ => throw new Exception(String.Format("Character {0} is not a defined operator", curChar)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user