-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Derivative.cs
151 lines (130 loc) · 5.03 KB
/
Derivative.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// 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>
/// Represents the 'deriv' function.
/// </summary>
public class Derivative : DifferentParametersExpression
{
/// <summary>
/// Initializes a new instance of the <see cref="Derivative" /> class.
/// </summary>
/// <param name="differentiator">The differentiator.</param>
/// <param name="simplifier">The simplifier.</param>
/// <param name="expression">The expression.</param>
public Derivative(
IDifferentiator differentiator,
ISimplifier simplifier,
IExpression expression)
: this(differentiator, simplifier, ImmutableArray.Create(expression))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Derivative" /> class.
/// </summary>
/// <param name="differentiator">The differentiator.</param>
/// <param name="simplifier">The simplifier.</param>
/// <param name="expression">The expression.</param>
/// <param name="variable">The variable.</param>
public Derivative(
IDifferentiator differentiator,
ISimplifier simplifier,
IExpression expression,
Variable variable)
: this(differentiator, simplifier, ImmutableArray.Create(expression, variable))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Derivative" /> class.
/// </summary>
/// <param name="differentiator">The differentiator.</param>
/// <param name="simplifier">The simplifier.</param>
/// <param name="expression">The expression.</param>
/// <param name="variable">The variable.</param>
/// <param name="point">The point of derivation.</param>
public Derivative(
IDifferentiator differentiator,
ISimplifier simplifier,
IExpression expression,
Variable variable,
Number point)
: this(differentiator, simplifier, ImmutableArray.Create(expression, variable, point))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Derivative" /> class.
/// </summary>
/// <param name="differentiator">The differentiator.</param>
/// <param name="simplifier">The simplifier.</param>
/// <param name="args">The arguments.</param>
/// <exception cref="ArgumentNullException"><paramref name="args"/> is null.</exception>
internal Derivative(
IDifferentiator differentiator,
ISimplifier simplifier,
ImmutableArray<IExpression> args)
: base(args)
{
Differentiator = differentiator ?? throw new ArgumentNullException(nameof(differentiator));
Simplifier = simplifier ?? throw new ArgumentNullException(nameof(simplifier));
}
/// <inheritdoc />
public override object Execute(ExpressionParameters? parameters)
{
var result = Expression.Execute(parameters);
if (result is not Lambda lambda)
throw ExecutionException.For(this);
var variable = Variable;
var context = new DifferentiatorContext(variable);
var derivative = lambda.Body.Analyze(Differentiator, context);
var point = DerivativePoint;
if (point is not null)
{
var nested = ExpressionParameters.CreateScoped(parameters);
nested[variable.Name] = point.Value;
return derivative.Execute(nested);
}
return derivative
.Analyze(Simplifier)
.ToLambda(lambda.Parameters);
}
/// <inheritdoc />
protected override TResult AnalyzeInternal<TResult>(IAnalyzer<TResult> analyzer)
=> analyzer.Analyze(this);
/// <inheritdoc />
protected override TResult AnalyzeInternal<TResult, TContext>(
IAnalyzer<TResult, TContext> analyzer,
TContext context)
=> analyzer.Analyze(this, context);
/// <inheritdoc />
public override IExpression Clone(ImmutableArray<IExpression>? arguments = null)
=> new Derivative(Differentiator, Simplifier, arguments ?? Arguments);
/// <summary>
/// Gets the expression.
/// </summary>
public IExpression Expression => this[0];
/// <summary>
/// Gets the variable.
/// </summary>
public Variable Variable => ParametersCount >= 2 ? (Variable)this[1] : Variable.X;
/// <summary>
/// Gets the derivative point.
/// </summary>
public Number? DerivativePoint => ParametersCount >= 3 ? (Number)this[2] : null;
/// <summary>
/// Gets the simplifier.
/// </summary>
public ISimplifier Simplifier { get; }
/// <summary>
/// Gets the differentiator.
/// </summary>
public IDifferentiator Differentiator { get; }
/// <summary>
/// Gets the minimum count of parameters.
/// </summary>
public override int? MinParametersCount => 1;
/// <summary>
/// Gets the maximum count of parameters. <c>null</c> - Infinity.
/// </summary>
public override int? MaxParametersCount => 3;
}