Skip to content

Commit

Permalink
Fix #362 - Differentiation of x^x returns wrong expression
Browse files Browse the repository at this point in the history
  • Loading branch information
sys27 committed Oct 6, 2020
1 parent fc26c3f commit 02f2b02
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 23 deletions.
38 changes: 20 additions & 18 deletions xFunc.Maths/Analyzers/Differentiator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,27 +240,29 @@ public override IExpression Analyze(Pow exp, DifferentiatorContext context)
{
ValidateArguments(exp, context);

if (Helpers.HasVariable(exp.Left, context.Variable))
{
return new Mul(
exp.Left.Analyze(this, context),
new Mul(
exp.Right,
new Pow(
exp.Left,
new Sub(exp.Right, Number.One))));
}
var hasVariableInLeft = Helpers.HasVariable(exp.Left, context.Variable);
var hasVariableInRight = Helpers.HasVariable(exp.Right, context.Variable);

if (Helpers.HasVariable(exp.Right, context.Variable))
return (hasVariableInLeft, hasVariableInRight) switch
{
return new Mul(
(true, true) =>
new Mul(
new Ln(exp.Left),
exp),
exp.Right.Analyze(this, context));
}

return Number.Zero;
exp,
new Mul(exp.Right, new Ln(context.Variable)).Analyze(this, context)),
(true, _) =>
new Mul(
exp.Left.Analyze(this, context),
new Mul(
exp.Right,
new Pow(
exp.Left,
new Sub(exp.Right, Number.One)))),
(_, true) =>
new Mul(
new Mul(exp, new Ln(exp.Left)),
exp.Right.Analyze(this, context)),
_ => Number.Zero,
};
}

/// <inheritdoc />
Expand Down
55 changes: 50 additions & 5 deletions xFunc.Tests/Analyzers/DifferentiatorTests/DifferentiatorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ public void MulPartialDerivativeTest4()
Assert.Equal(zero, deriv);
}

[Fact]
[Fact(DisplayName = "x ^ 3")]
public void PowDerivativeTest1()
{
var exp = new Pow(Variable.X, new Number(3));
Expand All @@ -592,23 +592,68 @@ public void PowDerivativeTest1()
Assert.Equal(expected, deriv);
}

[Fact]
[Fact(DisplayName = "2 ^ (3x)")]
public void PowDerivativeTest2()
{
// 2 ^ (3x)
var exp = new Pow(Number.Two, new Mul(new Number(3), Variable.X));
var deriv = Differentiate(exp);
var expected = new Mul(
new Mul(
new Ln(Number.Two),
new Pow(Number.Two, new Mul(new Number(3), Variable.X))
new Pow(Number.Two, new Mul(new Number(3), Variable.X)),
new Ln(Number.Two)
),
new Mul(new Number(3), Number.One)
);

Assert.Equal(expected, deriv);
}

[Fact(DisplayName = "x ^ x")]
public void PowXbyX()
{
var exp = new Pow(Variable.X, Variable.X);
var result = Differentiate(exp);
var expected = new Mul(
new Pow(Variable.X, Variable.X),
new Add(
new Mul(Number.One, new Ln(Variable.X)),
new Mul(Variable.X, new Div(Number.One, Variable.X)))
);

Assert.Equal(expected, result);
}

[Fact(DisplayName = "x ^ 2x")]
public void PowXby2X()
{
var exp = new Pow(Variable.X, new Mul(Number.Two, Variable.X));
var result = Differentiate(exp);
var expected = new Mul(
new Pow(Variable.X, new Mul(Number.Two, Variable.X)),
new Add(
new Mul(new Mul(Number.Two, Number.One), new Ln(Variable.X)),
new Mul(new Mul(Number.Two, Variable.X), new Div(Number.One, Variable.X)))
);

Assert.Equal(expected, result);
}

[Fact(DisplayName = "x ^ sin(x)")]
public void PowXbySinX()
{
var exp = new Pow(Variable.X, new Sin(Variable.X));
var result = Differentiate(exp);
var expected = new Mul(
new Pow(Variable.X, new Sin(Variable.X)),
new Add(
new Mul(new Mul(new Cos(Variable.X), Number.One), new Ln(Variable.X)),
new Mul(new Sin(Variable.X), new Div(Number.One, Variable.X))
)
);

Assert.Equal(expected, result);
}

[Fact]
public void PowPartialDerivativeTest1()
{
Expand Down

0 comments on commit 02f2b02

Please sign in to comment.