Skip to content

Commit 3f4dcdd

Browse files
Added support for Span<double> to SimpleRegression.FitThroughOrigin() as POC for Span support suggested in issue mathnet#1083.
1 parent f196418 commit 3f4dcdd

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

src/Numerics.Tests/FitTests.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
// </copyright>
2929

3030
using System;
31+
using System.Diagnostics;
3132
using System.Linq;
3233

3334
using MathNet.Numerics.LinearRegression;
@@ -98,6 +99,55 @@ public void FitsToBestLineThroughOrigin()
9899
Assert.AreEqual(-0.467791, respSeq, 1e-4);
99100
}
100101

102+
[Test]
103+
public void FitsToBestLineThroughOriginSpanInterface()
104+
{
105+
// Mathematica: Fit[{{1,4.986},{2,2.347},{3,2.061},{4,-2.995},{5,-2.352},{6,-5.782}}, {x}, x]
106+
// -> -0.467791 x
107+
108+
var x = Enumerable.Range(1, 6).Select(Convert.ToDouble).ToArray().AsSpan();
109+
var y = new Span<double> (new[] { 4.986, 2.347, 2.061, -2.995, -2.352, -5.782 });
110+
111+
var resp = SimpleRegression.FitThroughOrigin(x, y);
112+
Assert.AreEqual(-0.467791, resp, 1e-4);
113+
}
114+
115+
[TestCase(10000, 100)]
116+
public void FitsToBestLineThroughOriginBenchmarkSpanVsArray(int dataLength, int windowLength)
117+
{
118+
var xarray = new double[dataLength];
119+
var yarray = new double[dataLength];
120+
121+
var window = windowLength;
122+
123+
var resultArray = new double[dataLength];
124+
var resultSpan = new double[dataLength];
125+
126+
Stopwatch stopwatchArraySlicing = Stopwatch.StartNew();
127+
// Use Array Slicing
128+
for (int i = 0; i < xarray.Length - window; ++i)
129+
{
130+
var xx = xarray.Skip(i).Take(window).ToArray();
131+
var yy = yarray.Skip(i).Take(window).ToArray();
132+
resultArray[i] = SimpleRegression.FitThroughOrigin(xx, yy);
133+
}
134+
stopwatchArraySlicing.Stop();
135+
136+
Stopwatch stopwatchSpanSlicing = Stopwatch.StartNew();
137+
// Use Span Slicing
138+
for (int i = 0; i < xarray.Length - window; ++i)
139+
{
140+
var xx = xarray.AsSpan(i, window);
141+
var yy = yarray.AsSpan(i, window);
142+
resultSpan[i] = SimpleRegression.FitThroughOrigin(xx, yy);
143+
}
144+
stopwatchSpanSlicing.Stop();
145+
146+
Assert.AreEqual(resultArray, resultSpan);
147+
148+
Console.WriteLine($"Array Slicing Timing: {stopwatchArraySlicing.Elapsed.TotalMilliseconds} ms, Span Slicing Timing: {stopwatchSpanSlicing.Elapsed.TotalMilliseconds} ms");
149+
}
150+
101151
[Test]
102152
public void FitsToLineSameAsExcelTrendLine()
103153
{

src/Numerics/LinearRegression/SimpleRegression.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,29 @@ public static double FitThroughOrigin(double[] x, double[] y)
133133
return mxy / mxx;
134134
}
135135

136+
public static double FitThroughOrigin(Span<double> x, Span<double> y)
137+
{
138+
if (x.Length != y.Length)
139+
{
140+
throw new ArgumentException($"All sample vectors must have the same length. However, vectors with disagreeing length {x.Length} and {y.Length} have been provided. A sample with index i is given by the value at index i of each provided vector.");
141+
}
142+
143+
if (x.Length <= 1)
144+
{
145+
throw new ArgumentException($"A regression of the requested order requires at least {2} samples. Only {x.Length} samples have been provided.");
146+
}
147+
148+
double mxy = 0.0;
149+
double mxx = 0.0;
150+
for (int i = 0; i < x.Length; i++)
151+
{
152+
mxx += x[i] * x[i];
153+
mxy += x[i] * y[i];
154+
}
155+
156+
return mxy / mxx;
157+
}
158+
136159

137160
/// <summary>
138161
/// Least-Squares fitting the points (x,y) to a line y : x -> b*x,

src/Numerics/Numerics.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@ many contributions, proper release notes with attributions will follow. thank yo
2929
<PrivateAssets>all</PrivateAssets>
3030
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
3131
</PackageReference>
32+
<PackageReference Include="System.Memory" Version="4.5.5" />
3233
</ItemGroup>
3334
</Project>

0 commit comments

Comments
 (0)