Skip to content

Commit

Permalink
#131 - Support aliases for simplify, deriv and etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
sys27 committed Jul 13, 2023
1 parent bb1ec81 commit 0306815
Show file tree
Hide file tree
Showing 22 changed files with 255 additions and 179 deletions.
10 changes: 4 additions & 6 deletions xFunc Grammar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ leftUnary = ('~' / '-')* exponentiation
exponentiation = rightUnary ('^' exponentiation)*
rightUnary = incDec
/ factorial
/ operand
/ callExp

incDec = variable ('++' / '--')
factorial = (number '!')

callExp = operand parameters*

operand = complexnumber /
if /
def /
Expand All @@ -42,7 +44,6 @@ operand = complexnumber /
variable /
boolean /
bracketExp /
callExp /
lambda /
matrix /
vector
Expand All @@ -66,7 +67,4 @@ parameters = (statement (',' statement)*)*
vector = ('{' / '(') parameters ('}' / ')')
matrix = ('{' / '(') vector (',' vector) ('}' / ')')

functionDeclaration = id '(' (variable (',' variable)* / '') ')'

lambda = '(' (id (',' id) / '') ')' '=>' exp
callExp = '(' lambda ')' '(' parameters ')'
lambda = '(' (id (',' id) / '') ')' '=>' exp
7 changes: 1 addition & 6 deletions xFunc.Maths/Analyzers/TypeAnalyzers/ResultTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public enum ResultTypes
/// <summary>
/// The expression returns other expression.
/// </summary>
Expression = 1 << 6,
Function = 1 << 6,

/// <summary>
/// The expression returns an angle.
Expand Down Expand Up @@ -95,9 +95,4 @@ public enum ResultTypes
/// The expression returns a volume number.
/// </summary>
VolumeNumber = 1 << 15,

/// <summary>
/// The expression return a function.
/// </summary>
Function = 1 << 16,
}
8 changes: 4 additions & 4 deletions xFunc.Maths/Analyzers/TypeAnalyzers/TypeAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ public virtual ResultTypes Analyze(Assign exp)

/// <inheritdoc />
public virtual ResultTypes Analyze(Del exp)
=> CheckArgument(exp, ResultTypes.Expression);
=> CheckArgument(exp, ResultTypes.Function);

/// <inheritdoc />
public virtual ResultTypes Analyze(Derivative exp)
Expand All @@ -575,10 +575,10 @@ public virtual ResultTypes Analyze(Derivative exp)
ArgNull(ExceptionArgument.exp);

if (exp.ParametersCount == 1)
return ResultTypes.Expression;
return ResultTypes.Function;

if (exp.ParametersCount == 2 && exp[1] is Variable)
return ResultTypes.Expression;
return ResultTypes.Function;

if (exp.ParametersCount == 3 && exp[1] is Variable && exp[2] is Number)
return ResultTypes.Number;
Expand Down Expand Up @@ -1170,7 +1170,7 @@ public virtual ResultTypes Analyze(Round exp)

/// <inheritdoc />
public virtual ResultTypes Analyze(Simplify exp)
=> CheckArgument(exp, ResultTypes.Undefined);
=> CheckArgument(exp, ResultTypes.Function);

/// <inheritdoc />
public virtual ResultTypes Analyze(Sqrt exp)
Expand Down
24 changes: 19 additions & 5 deletions xFunc.Maths/Expressions/Del.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using static xFunc.Maths.ThrowHelpers;

namespace xFunc.Maths.Expressions;
Expand Down Expand Up @@ -54,21 +55,34 @@ internal Del(
/// <inheritdoc />
public override object Execute(ExpressionParameters? parameters)
{
var result = Argument.Execute(parameters);
if (result is not Lambda lambda)
throw new ResultIsNotSupportedException(this, result);

var context = new DifferentiatorContext(parameters);
var body = lambda.Body;
var variables = Helpers.GetAllVariables(body);
if (!variables.TryGetNonEnumeratedCount(out var variablesCount))
variablesCount = variables.Count();

var variables = Helpers.GetAllVariables(Argument).ToList();
var vector = ImmutableArray.CreateBuilder<IExpression>(variables.Count);
var vectorItems = new IExpression[variablesCount];
var i = 0;

foreach (var variable in variables)
{
context.Variable = variable;

vector.Add(Argument
vectorItems[i] = body
.Analyze(differentiator, context)
.Analyze(simplifier));
.Analyze(simplifier);

i++;
}

return new Vector(vector.ToImmutableArray());
var resultLambda = new Vector(Unsafe.As<IExpression[], ImmutableArray<IExpression>>(ref vectorItems))
.ToLambda(lambda.Parameters);

return resultLambda;
}

/// <inheritdoc />
Expand Down
12 changes: 9 additions & 3 deletions xFunc.Maths/Expressions/Derivative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,20 +84,26 @@ internal Derivative(
/// <inheritdoc />
public override object Execute(ExpressionParameters? parameters)
{
var result = Expression.Execute(parameters);
if (result is not Lambda lambda)
throw new ResultIsNotSupportedException(this, result);

var variable = Variable;
var context = new DifferentiatorContext(parameters, variable);
var diff = Analyze(Differentiator, context);
var derivative = lambda.Body.Analyze(Differentiator, context);

var point = DerivativePoint;
if (point is not null)
{
parameters ??= new ExpressionParameters();
parameters[variable.Name] = point.Value;

return diff.Execute(parameters);
return derivative.Execute(parameters);
}

return diff.Analyze(Simplifier);
return derivative
.Analyze(Simplifier)
.ToLambda(lambda.Parameters);
}

/// <inheritdoc />
Expand Down
9 changes: 9 additions & 0 deletions xFunc.Maths/Expressions/Lambda.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ namespace xFunc.Maths.Expressions;
/// </summary>
public readonly struct Lambda : IEquatable<Lambda>
{
/// <summary>
/// Initializes a new instance of the <see cref="Lambda"/> struct.
/// </summary>
/// <param name="body">The body of the function.</param>
public Lambda(IExpression body)
: this(ImmutableArray.Create<string>(), body)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="Lambda"/> struct.
/// </summary>
Expand Down
55 changes: 55 additions & 0 deletions xFunc.Maths/Expressions/LambdaExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (c) Dmytro Kyshchenko. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Immutable;

namespace xFunc.Maths.Expressions;

/// <summary>
/// Extension methods for <see cref="Lambda"/> and <see cref="LambdaExpression"/>.
/// </summary>
public static class LambdaExtensions
{
/// <summary>
/// Converts <paramref name="exp"/> to <see cref="Lambda"/> without parameters.
/// </summary>
/// <param name="exp">The expression to convert.</param>
/// <returns>The lambda.</returns>
public static Lambda ToLambda(this IExpression exp)
=> new Lambda(exp);

/// <summary>
/// Converts <paramref name="exp"/> to <see cref="Lambda"/> without parameters.
/// </summary>
/// <param name="exp">The expression to convert.</param>
/// <param name="variables">The list of lambda parameters.</param>
/// <returns>The lambda.</returns>
public static Lambda ToLambda(this IExpression exp, params string[] variables)
=> new Lambda(variables, exp);

/// <summary>
/// Converts <paramref name="exp"/> to <see cref="Lambda"/> without parameters.
/// </summary>
/// <param name="exp">The expression to convert.</param>
/// <param name="variables">The list of lambda parameters.</param>
/// <returns>The lambda.</returns>
public static Lambda ToLambda(this IExpression exp, ImmutableArray<string> variables)
=> new Lambda(variables, exp);

/// <summary>
/// Converts <paramref name="exp"/> to <see cref="LambdaExpression"/> without parameters.
/// </summary>
/// <param name="exp">The expression to convert.</param>
/// <returns>The lambda expression.</returns>
public static LambdaExpression ToLambdaExpression(this IExpression exp)
=> ToLambda(exp).AsExpression();

/// <summary>
/// Converts <paramref name="exp"/> to <see cref="LambdaExpression"/> without parameters.
/// </summary>
/// <param name="exp">The expression to convert.</param>
/// <param name="variables">The list of lambda parameters.</param>
/// <returns>The lambda expression.</returns>
public static LambdaExpression ToLambdaExpression(this IExpression exp, params string[] variables)
=> ToLambda(exp, variables).AsExpression();
}
12 changes: 11 additions & 1 deletion xFunc.Maths/Expressions/Simplify.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,17 @@ internal Simplify(ISimplifier simplifier, ImmutableArray<IExpression> arguments)
/// <exception cref="ArgumentNullException">Simplifier is null.</exception>
/// <seealso cref="ExpressionParameters" />
public override object Execute(ExpressionParameters? parameters)
=> Analyze(simplifier);
{
var result = Argument.Execute(parameters);
if (result is not Lambda lambda)
throw new ResultIsNotSupportedException(this, result);

var simplifiedExpression = lambda.Body
.Analyze(simplifier)
.ToLambda(lambda.Parameters);

return simplifiedExpression;
}

/// <inheritdoc />
protected override TResult AnalyzeInternal<TResult>(IAnalyzer<TResult> analyzer)
Expand Down
41 changes: 18 additions & 23 deletions xFunc.Maths/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ public IExpression Parse(string expression)
private IExpression? ParseRightUnary(ref TokenReader tokenReader)
=> ParseFactorial(ref tokenReader) ??
ParseIncDec(ref tokenReader) ??
ParseOperand(ref tokenReader);
ParseCallExpression(ref tokenReader);

private IExpression? ParseFactorial(ref TokenReader tokenReader)
=> tokenReader.Scoped(this, static (Parser parser, ref TokenReader reader) =>
Expand Down Expand Up @@ -485,6 +485,22 @@ public IExpression Parse(string expression)
return null;
});

private IExpression? ParseCallExpression(ref TokenReader tokenReader)
{
var operand = ParseOperand(ref tokenReader);
if (operand is null)
return null;

while (true)
{
var parameters = ParseParameterList(ref tokenReader);
if (parameters is null)
return operand;

operand = new CallExpression(operand, parameters.Value);
}
}

private IExpression? ParseOperand(ref TokenReader tokenReader)
=> ParsePolarComplexNumber(ref tokenReader) ??
ParseNumberAndUnit(ref tokenReader) ??
Expand All @@ -493,7 +509,7 @@ public IExpression Parse(string expression)
ParseUnassignFunction(ref tokenReader) ??
ParseFunctionOrVariable(ref tokenReader) ??
ParseBoolean(ref tokenReader) ??
ParseParenthesesOrCallExpression(ref tokenReader) ??
ParseParenthesesExpression(ref tokenReader) ??
ParseLambda(ref tokenReader) ??
ParseMatrix(ref tokenReader) ??
ParseVector(ref tokenReader) ??
Expand Down Expand Up @@ -573,16 +589,6 @@ public IExpression Parse(string expression)
return new Unassign(key);
}

private IExpression? ParseParenthesesOrCallExpression(ref TokenReader tokenReader)
=> tokenReader.Scoped(this, static (Parser parser, ref TokenReader reader) =>
{
var exp = parser.ParseParenthesesExpression(ref reader);
if (exp is null)
return null;

return parser.ParseCallExpression(exp, ref reader);
});

private IExpression? ParseParenthesesExpression(ref TokenReader tokenReader)
=> tokenReader.Scoped(this, static (Parser parser, ref TokenReader reader) =>
{
Expand All @@ -605,17 +611,6 @@ public IExpression Parse(string expression)
return exp;
});

private IExpression ParseCallExpression(IExpression expression, ref TokenReader tokenReader)
{
var parameters = ParseParameterList(ref tokenReader);
if (parameters is null)
return expression;

var callExpression = new CallExpression(expression, parameters.Value);

return callExpression;
}

private IExpression? ParseLambda(ref TokenReader tokenReader)
{
if (!tokenReader.Check(OpenParenthesisSymbol))
Expand Down
6 changes: 0 additions & 6 deletions xFunc.Maths/Processor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,6 @@ bool boolean
string str
=> new StringResult(str),

IExpression expression when simplify
=> new ExpressionResult(Simplify(expression)),

IExpression expression
=> new ExpressionResult(expression),

Lambda lambda
=> new LambdaResult(lambda),

Expand Down
26 changes: 0 additions & 26 deletions xFunc.Maths/Results/ExpressionResult.cs

This file was deleted.

4 changes: 2 additions & 2 deletions xFunc.Tests/Analyzers/DifferentiatorTests/NullArgumentTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public void VariableContextArgumentTest()
public void CallExpressionContextNullArgument()
{
var exp = new CallExpression(
new Lambda(new[] { "x" }, Variable.X).AsExpression(),
Variable.X.ToLambdaExpression(Variable.X.Name),
new IExpression[] { Variable.X }.ToImmutableArray());

Assert.Throws<NotSupportedException>(() => exp.Analyze(differentiator, null));
Expand All @@ -188,7 +188,7 @@ public void CallExpressionContextNullArgument()
[Fact]
public void LambdaExpressionContextNullArgument()
{
var exp = new Lambda(new[] { "x" }, Variable.X).AsExpression();
var exp = Variable.X.ToLambdaExpression(Variable.X.Name);

Assert.Throws<NotSupportedException>(() => exp.Analyze(differentiator, null));
}
Expand Down
Loading

0 comments on commit 0306815

Please sign in to comment.