Skip to content

Commit

Permalink
Use in-modifiers
Browse files Browse the repository at this point in the history
- Update tests and benchmarks.
  • Loading branch information
HamletTanyavong committed Aug 27, 2024
1 parent 003daf4 commit 1b445ee
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 30 deletions.
8 changes: 4 additions & 4 deletions src/Mathematics.NET/AutoDiff/GradientTape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ public Variable<T> Divide(Variable<T> x, T c)
return new(_nodes.Count, x.Value * u);
}

public Variable<Real> Modulo(Variable<Real> x, Variable<Real> y)
public Variable<Real> Modulo(in Variable<Real> x, in Variable<Real> y)
{
if (_isTracking)
{
Expand All @@ -253,7 +253,7 @@ public Variable<Real> Modulo(Variable<Real> x, Variable<Real> y)
return new(_nodes.Count, x.Value % y.Value);
}

public Variable<Real> Modulo(Real c, Variable<Real> x)
public Variable<Real> Modulo(Real c, in Variable<Real> x)
{
if (_isTracking)
{
Expand All @@ -263,7 +263,7 @@ public Variable<Real> Modulo(Real c, Variable<Real> x)
return new(_nodes.Count, c % x.Value);
}

public Variable<Real> Modulo(Variable<Real> x, Real c)
public Variable<Real> Modulo(in Variable<Real> x, Real c)
{
if (_isTracking)
{
Expand Down Expand Up @@ -590,7 +590,7 @@ public Variable<T> Atan(Variable<T> x)
return new(_nodes.Count, T.Atan(x.Value));
}

public Variable<Real> Atan2(Variable<Real> y, Variable<Real> x)
public Variable<Real> Atan2(in Variable<Real> y, in Variable<Real> x)
{
if (_isTracking)
{
Expand Down
8 changes: 4 additions & 4 deletions src/Mathematics.NET/AutoDiff/HessianTape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ public Variable<T> Divide(Variable<T> x, T c)
return new(_nodes.Count, x.Value * u);
}

public Variable<Real> Modulo(Variable<Real> x, Variable<Real> y)
public Variable<Real> Modulo(in Variable<Real> x, in Variable<Real> y)
{
if (_isTracking)
{
Expand All @@ -370,7 +370,7 @@ public Variable<Real> Modulo(Variable<Real> x, Variable<Real> y)
return new(_nodes.Count, x.Value % y.Value);
}

public Variable<Real> Modulo(Real c, Variable<Real> x)
public Variable<Real> Modulo(Real c, in Variable<Real> x)
{
if (_isTracking)
{
Expand All @@ -380,7 +380,7 @@ public Variable<Real> Modulo(Real c, Variable<Real> x)
return new(_nodes.Count, c % x.Value);
}

public Variable<Real> Modulo(Variable<Real> x, Real c)
public Variable<Real> Modulo(in Variable<Real> x, Real c)
{
if (_isTracking)
{
Expand Down Expand Up @@ -765,7 +765,7 @@ public Variable<T> Atan(Variable<T> x)
return new(_nodes.Count, T.Atan(x.Value));
}

public Variable<Real> Atan2(Variable<Real> y, Variable<Real> x)
public Variable<Real> Atan2(in Variable<Real> y, in Variable<Real> x)
{
if (_isTracking)
{
Expand Down
8 changes: 4 additions & 4 deletions src/Mathematics.NET/AutoDiff/ITape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,19 +109,19 @@ public interface ITape<T>
/// <param name="x">A dividend.</param>
/// <param name="y">A divisor.</param>
/// <returns><paramref name="x"/> mod <paramref name="y"/>.</returns>
public Variable<Real> Modulo(Variable<Real> x, Variable<Real> y);
public Variable<Real> Modulo(in Variable<Real> x, in Variable<Real> y);

/// <summary>Compute the modulo of a real value given a divisor.</summary>
/// <param name="c">A real dividend.</param>
/// <param name="x">A variable divisor.</param>
/// <returns><paramref name="c"/> mod <paramref name="x"/>.</returns>
public Variable<Real> Modulo(Real c, Variable<Real> x);
public Variable<Real> Modulo(Real c, in Variable<Real> x);

/// <summary>Compute the modulo of a variable given a divisor.</summary>
/// <param name="x">A variable dividend.</param>
/// <param name="c">A real divisor.</param>
/// <returns><paramref name="x"/> mod <paramref name="c"/>.</returns>
public Variable<Real> Modulo(Variable<Real> x, Real c);
public Variable<Real> Modulo(in Variable<Real> x, Real c);

/// <summary>Multiply two variables.</summary>
/// <param name="x">The first variable.</param>
Expand Down Expand Up @@ -247,7 +247,7 @@ public interface ITape<T>
public Variable<T> Atan(Variable<T> x);

/// <inheritdoc cref="IReal{T}.Atan2(T, T)"/>
public Variable<Real> Atan2(Variable<Real> y, Variable<Real> x);
public Variable<Real> Atan2(in Variable<Real> y, in Variable<Real> x);

/// <inheritdoc cref="IDifferentiableFunctions{T}.Cos(T)"/>
public Variable<T> Cos(Variable<T> x);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ public Variable<T> Divide(Variable<T> x, T c)
return new(_nodes.Count, x.Value * u);
}

public Variable<Real> Modulo(Variable<Real> x, Variable<Real> y)
public Variable<Real> Modulo(in Variable<Real> x, in Variable<Real> y)
{
if (_isTracking)
{
Expand All @@ -176,7 +176,7 @@ public Variable<Real> Modulo(Variable<Real> x, Variable<Real> y)
return new(_nodes.Count, x.Value % y.Value);
}

public Variable<Real> Modulo(Real c, Variable<Real> x)
public Variable<Real> Modulo(Real c, in Variable<Real> x)
{
if (_isTracking)
{
Expand All @@ -186,7 +186,7 @@ public Variable<Real> Modulo(Real c, Variable<Real> x)
return new(_nodes.Count, c % x.Value);
}

public Variable<Real> Modulo(Variable<Real> x, Real c)
public Variable<Real> Modulo(in Variable<Real> x, Real c)
{
if (_isTracking)
{
Expand Down Expand Up @@ -513,7 +513,7 @@ public Variable<T> Atan(Variable<T> x)
return new(_nodes.Count, T.Atan(x.Value));
}

public Variable<Real> Atan2(Variable<Real> y, Variable<Real> x)
public Variable<Real> Atan2(in Variable<Real> y, in Variable<Real> x)
{
if (_isTracking)
{
Expand Down
25 changes: 20 additions & 5 deletions tests/Mathematics.NET.Tests/AutoDiff/GradientTapeOfRealTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,13 @@ public void Atan_Variable_ReturnsValue(double input, double expected)
[DataRow(1.23, 2.34, 0.334835801674179, -0.1760034342133505)]
public void Atan2_TwoVariables_ReturnsGradient(double left, double right, double expectedLeft, double expectedRight)
{
var y = _tape.CreateVariable(left);
var x = _tape.CreateVariable(right);
_ = _tape.Atan2(y, x);

Real[] expected = [expectedLeft, expectedRight];

var actual = ComputeGradient(_tape.Atan2, left, right);
_tape.ReverseAccumulate(out var actual);

Assert<Real>.AreApproximatelyEqual(expected, actual, 1e-15);
}
Expand All @@ -218,7 +222,10 @@ public void Atan2_TwoVariables_ReturnsGradient(double left, double right, double
[DataRow(1.23, 2.34, 0.4839493878600246)]
public void Atan2_TwoVariables_ReturnsValue(double left, double right, double expected)
{
var actual = ComputeValue(_tape.Atan2, left, right);
var y = _tape.CreateVariable(left);
var x = _tape.CreateVariable(right);

var actual = _tape.Atan2(y, x).Value;

Assert<Real>.AreApproximatelyEqual(expected, actual, 1e-15);
}
Expand Down Expand Up @@ -328,10 +335,11 @@ public void CustomOperation_Binary_ReturnsGradient(double left, double right, do
var x = _tape.CreateVariable(right);
var u = Real.One / (x.Value * x.Value + y.Value * y.Value);
_ = _tape.CustomOperation(y, x, Real.Atan2, (y, x) => x * u, (y, x) => -y * u);
_tape.ReverseAccumulate(out var actual);

Real[] expected = [expectedLeft, expectedRight];

_tape.ReverseAccumulate(out var actual);

Assert<Real>.AreApproximatelyEqual(expected, actual, 1e-15);
}

Expand Down Expand Up @@ -572,9 +580,13 @@ public void Log10_Variable_ReturnsValue(double input, double expected)
[DataRow(1.23, 2.34, 1, 0)]
public void Modulo_TwoVariables_ReturnsGradient(double left, double right, double expectedLeft, double expectedRight)
{
var x = _tape.CreateVariable(left);
var y = _tape.CreateVariable(right);
_ = _tape.Modulo(x, y);

Real[] expected = [expectedLeft, expectedRight];

var actual = ComputeGradient(_tape.Modulo, left, right);
_tape.ReverseAccumulate(out var actual);

Assert<Real>.AreApproximatelyEqual(expected, actual, Real.Zero);
}
Expand All @@ -583,7 +595,10 @@ public void Modulo_TwoVariables_ReturnsGradient(double left, double right, doubl
[DataRow(3.14, 2.34, 0.8)]
public void Modulo_TwoVariables_ReturnsValue(double left, double right, double expected)
{
var actual = ComputeValue(_tape.Modulo, left, right);
var x = _tape.CreateVariable(left);
var y = _tape.CreateVariable(right);

var actual = _tape.Modulo(x, y).Value;

Assert<Real>.AreApproximatelyEqual(expected, actual, 1e-15);
}
Expand Down
38 changes: 29 additions & 9 deletions tests/Mathematics.NET.Tests/AutoDiff/HessianTapeOfRealTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,13 @@ public void Atan_Variable_ReturnsValue(double input, double expected)
[DataRow(1.23, 2.34, 0.334835801674179, -0.1760034342133505)]
public void Atan2_TwoVariables_ReturnsGradient(double left, double right, double expectedLeft, double expectedRight)
{
var y = _tape.CreateVariable(left);
var x = _tape.CreateVariable(right);
_ = _tape.Atan2(y, x);

Real[] expected = [expectedLeft, expectedRight];

var actual = ComputeGradient(_tape.Atan2, left, right);
_tape.ReverseAccumulate(out ReadOnlySpan<Real> actual);

Assert<Real>.AreApproximatelyEqual(expected, actual, 1e-15);
}
Expand All @@ -300,9 +304,13 @@ public void Atan2_TwoVariables_ReturnsGradient(double left, double right, double
[DataRow(1.23, 2.34, -0.1178645019844717, -0.081137805227897, 0.1178645019844717)]
public void Atan2_TwoVariables_ReturnsHessian(double left, double right, double expectedXX, double expectedXY, double expectedYY)
{
var y = _tape.CreateVariable(left);
var x = _tape.CreateVariable(right);
_ = _tape.Atan2(y, x);

Real[,] expected = new Real[2, 2] { { expectedXX, expectedXY }, { expectedXY, expectedYY } };

var actual = ComputeHessian(_tape.Atan2, left, right);
_tape.ReverseAccumulate(out ReadOnlySpan2D<Real> actual);

Assert<Real>.AreApproximatelyEqual(expected, actual, 1e-14);
}
Expand All @@ -311,7 +319,10 @@ public void Atan2_TwoVariables_ReturnsHessian(double left, double right, double
[DataRow(1.23, 2.34, 0.4839493878600246)]
public void Atan2_TwoVariables_ReturnsValue(double left, double right, double expected)
{
var actual = ComputeValue(_tape.Atan2, left, right);
var y = _tape.CreateVariable(left);
var x = _tape.CreateVariable(right);

var actual = _tape.Atan2(y, x).Value;

Assert<Real>.AreApproximatelyEqual(expected, actual, 1e-15);
}
Expand Down Expand Up @@ -499,9 +510,7 @@ public void CustomOperation_Binary_ReturnsHessian(double left, double right, dou

Real[,] expected = new Real[2, 2] { { expectedXX, expectedXY }, { expectedXY, expectedYY } };

_tape.ReverseAccumulate(out ReadOnlySpan2D<Real> hessian);

var actual = hessian.ToArray();
_tape.ReverseAccumulate(out ReadOnlySpan2D<Real> actual);

Assert<Real>.AreApproximatelyEqual(expected, actual, 1e-14);
}
Expand Down Expand Up @@ -875,9 +884,13 @@ public void Log10_Variable_ReturnsValue(double input, double expected)
[DataRow(1.23, 2.34, 1, 0)]
public void Modulo_TwoVariables_ReturnsGradient(double left, double right, double expectedLeft, double expectedRight)
{
var x = _tape.CreateVariable(left);
var y = _tape.CreateVariable(right);
_ = _tape.Modulo(x, y);

Real[] expected = [expectedLeft, expectedRight];

var actual = ComputeGradient(_tape.Modulo, left, right);
_tape.ReverseAccumulate(out ReadOnlySpan<Real> actual);

Assert<Real>.AreApproximatelyEqual(expected, actual, Real.Zero);
}
Expand All @@ -886,9 +899,13 @@ public void Modulo_TwoVariables_ReturnsGradient(double left, double right, doubl
[DataRow(1.23, 2.34, 0, 0, 0)]
public void Modulo_TwoVariables_ReturnsHessian(double left, double right, double expectedXX, double expectedXY, double expectedYY)
{
var x = _tape.CreateVariable(left);
var y = _tape.CreateVariable(right);
_ = _tape.Modulo(x, y);

Real[,] expected = new Real[2, 2] { { expectedXX, expectedXY }, { expectedXY, expectedYY } };

var actual = ComputeHessian(_tape.Modulo, left, right);
_tape.ReverseAccumulate(out ReadOnlySpan2D<Real> actual);

Assert<Real>.AreApproximatelyEqual(expected, actual, Real.Zero);
}
Expand All @@ -897,7 +914,10 @@ public void Modulo_TwoVariables_ReturnsHessian(double left, double right, double
[DataRow(3.14, 2.34, 0.8)]
public void Modulo_TwoVariables_ReturnsValue(double left, double right, double expected)
{
var actual = ComputeValue(_tape.Modulo, left, right);
var x = _tape.CreateVariable(left);
var y = _tape.CreateVariable(right);

var actual = _tape.Modulo(x, y).Value;

Assert<Real>.AreApproximatelyEqual(expected, actual, 1e-15);
}
Expand Down

0 comments on commit 1b445ee

Please sign in to comment.