mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-16 01:28:05 +00:00
Refactor and expand unit tests for TBarSeries, TSeries, and TValue classes
- Enhanced TBarSeriesTests with additional constructors, methods, and assertions for better coverage. - Improved TSeriesTests to include new constructors, methods, and edge cases. - Expanded TValueTests to cover constructors, implicit conversions, equality checks, and hash codes. - Updated project file to target .NET 10.0 and include internal visibility for tests. - Added Codacy configuration for code quality checks.
This commit is contained in:
@@ -1,249 +1,730 @@
|
||||
using System;
|
||||
using Xunit;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
public class SimdExtensionsTests
|
||||
{
|
||||
[Fact]
|
||||
public void SumSIMD_EmptySpan_ReturnsZero()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
Assert.Equal(0.0, span.SumSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumSIMD_SingleElement_ReturnsElement()
|
||||
{
|
||||
double[] data = [42.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(42.5, span.SumSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumSIMD_MultipleElements_ReturnsCorrectSum()
|
||||
{
|
||||
double[] data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(55.0, span.SumSIMD(), precision: 10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumSIMD_LargeArray_ReturnsCorrectSum()
|
||||
{
|
||||
double[] data = new double[1000];
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
data[i] = i + 1.0;
|
||||
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
double expected = 1000.0 * 1001.0 / 2.0; // Sum of 1..1000
|
||||
Assert.Equal(expected, span.SumSIMD(), precision: 8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinSIMD_EmptySpan_ReturnsNaN()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
Assert.True(double.IsNaN(span.MinSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinSIMD_SingleElement_ReturnsElement()
|
||||
{
|
||||
double[] data = [42.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(42.5, span.MinSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinSIMD_MultipleElements_ReturnsMinimum()
|
||||
{
|
||||
double[] data = [5.0, 2.0, 8.0, 1.0, 9.0, 3.0, 7.0, 4.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(1.0, span.MinSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MaxSIMD_EmptySpan_ReturnsNaN()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
Assert.True(double.IsNaN(span.MaxSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MaxSIMD_SingleElement_ReturnsElement()
|
||||
{
|
||||
double[] data = [42.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(42.5, span.MaxSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MaxSIMD_MultipleElements_ReturnsMaximum()
|
||||
{
|
||||
double[] data = [5.0, 2.0, 8.0, 1.0, 9.0, 3.0, 7.0, 4.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(9.0, span.MaxSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AverageSIMD_EmptySpan_ReturnsNaN()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
Assert.True(double.IsNaN(span.AverageSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AverageSIMD_MultipleElements_ReturnsCorrectAverage()
|
||||
{
|
||||
double[] data = [1.0, 2.0, 3.0, 4.0, 5.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(3.0, span.AverageSIMD(), precision: 10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarianceSIMD_LessThanTwoElements_ReturnsNaN()
|
||||
{
|
||||
double[] data = [42.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(double.IsNaN(span.VarianceSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarianceSIMD_MultipleElements_ReturnsCorrectVariance()
|
||||
{
|
||||
double[] data = [2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
|
||||
// Expected variance: 4.571428... (sample variance)
|
||||
double variance = span.VarianceSIMD();
|
||||
Assert.True(Math.Abs(variance - 4.571428) < 0.0001);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StdDevSIMD_MultipleElements_ReturnsCorrectStdDev()
|
||||
{
|
||||
double[] data = [2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
|
||||
// Expected std dev: sqrt(4.571428) ≈ 2.138
|
||||
double stdDev = span.StdDevSIMD();
|
||||
Assert.True(Math.Abs(stdDev - 2.138) < 0.01);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinMaxSIMD_EmptySpan_ReturnsBothNaN()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
var (min, max) = span.MinMaxSIMD();
|
||||
Assert.True(double.IsNaN(min));
|
||||
Assert.True(double.IsNaN(max));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinMaxSIMD_SingleElement_ReturnsSameValue()
|
||||
{
|
||||
double[] data = [42.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
var (min, max) = span.MinMaxSIMD();
|
||||
Assert.Equal(42.5, min);
|
||||
Assert.Equal(42.5, max);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinMaxSIMD_MultipleElements_ReturnsCorrectMinMax()
|
||||
{
|
||||
double[] data = [5.0, 2.0, 8.0, 1.0, 9.0, 3.0, 7.0, 4.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
var (min, max) = span.MinMaxSIMD();
|
||||
Assert.Equal(1.0, min);
|
||||
Assert.Equal(9.0, max);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SIMD_WorksWithTSeriesValues()
|
||||
{
|
||||
var series = new TSeries(100);
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
series.Add(DateTime.UtcNow.Ticks + i, i + 1.0);
|
||||
}
|
||||
|
||||
var values = series.Values;
|
||||
|
||||
double sum = values.SumSIMD();
|
||||
double avg = values.AverageSIMD();
|
||||
double min = values.MinSIMD();
|
||||
double max = values.MaxSIMD();
|
||||
var (minAlt, maxAlt) = values.MinMaxSIMD();
|
||||
|
||||
Assert.Equal(5050.0, sum, precision: 8); // Sum of 1..100
|
||||
Assert.Equal(50.5, avg, precision: 8);
|
||||
Assert.Equal(1.0, min);
|
||||
Assert.Equal(100.0, max);
|
||||
Assert.Equal(min, minAlt);
|
||||
Assert.Equal(max, maxAlt);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SIMD_WorksWithTBarSeriesClose()
|
||||
{
|
||||
var gbm = new GBM(startPrice: 100.0);
|
||||
long startTime = DateTime.UtcNow.Ticks;
|
||||
var interval = TimeSpan.FromMinutes(1);
|
||||
var bars = gbm.Fetch(1000, startTime, interval);
|
||||
|
||||
var closeValues = bars.Close.Values;
|
||||
|
||||
double sum = closeValues.SumSIMD();
|
||||
double avg = closeValues.AverageSIMD();
|
||||
double min = closeValues.MinSIMD();
|
||||
double max = closeValues.MaxSIMD();
|
||||
|
||||
Assert.True(sum > 0);
|
||||
Assert.True(avg > 0);
|
||||
Assert.True(min > 0);
|
||||
Assert.True(max > min);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SIMD_PerformanceTest_LargeDataset()
|
||||
{
|
||||
// Generate large dataset
|
||||
var gbm = new GBM(startPrice: 100.0);
|
||||
long startTime = DateTime.UtcNow.Ticks;
|
||||
var interval = TimeSpan.FromMinutes(1);
|
||||
var bars = gbm.Fetch(10000, startTime, interval);
|
||||
var closeValues = bars.Close.Values;
|
||||
|
||||
// Warm up
|
||||
_ = closeValues.SumSIMD();
|
||||
|
||||
// Test SIMD operations
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
||||
double sum = closeValues.SumSIMD();
|
||||
double avg = closeValues.AverageSIMD();
|
||||
double min = closeValues.MinSIMD();
|
||||
double max = closeValues.MaxSIMD();
|
||||
var (minAlt, maxAlt) = closeValues.MinMaxSIMD();
|
||||
double variance = closeValues.VarianceSIMD();
|
||||
double stdDev = closeValues.StdDevSIMD();
|
||||
|
||||
sw.Stop();
|
||||
|
||||
// Verify results are valid
|
||||
Assert.True(sum > 0);
|
||||
Assert.True(avg > 0);
|
||||
Assert.True(min > 0);
|
||||
Assert.True(max > min);
|
||||
Assert.True(variance > 0);
|
||||
Assert.True(stdDev > 0);
|
||||
|
||||
// Performance should be sub-millisecond for 10k elements
|
||||
Assert.True(sw.ElapsedMilliseconds < 10,
|
||||
$"SIMD operations took {sw.ElapsedMilliseconds}ms, expected < 10ms");
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using Xunit;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
public class SimdExtensionsTests
|
||||
{
|
||||
// ContainsNonFinite tests
|
||||
[Fact]
|
||||
public void ContainsNonFinite_EmptySpan_ReturnsFalse()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
Assert.False(span.ContainsNonFinite());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsNonFinite_AllFinite_ReturnsFalse()
|
||||
{
|
||||
double[] data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.False(span.ContainsNonFinite());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsNonFinite_ContainsNaN_ReturnsTrue()
|
||||
{
|
||||
double[] data = [1.0, 2.0, double.NaN, 4.0, 5.0, 6.0, 7.0, 8.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(span.ContainsNonFinite());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsNonFinite_ContainsPositiveInfinity_ReturnsTrue()
|
||||
{
|
||||
double[] data = [1.0, 2.0, 3.0, double.PositiveInfinity, 5.0, 6.0, 7.0, 8.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(span.ContainsNonFinite());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsNonFinite_ContainsNegativeInfinity_ReturnsTrue()
|
||||
{
|
||||
double[] data = [1.0, 2.0, 3.0, 4.0, double.NegativeInfinity, 6.0, 7.0, 8.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(span.ContainsNonFinite());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsNonFinite_NonFiniteInRemainder_ReturnsTrue()
|
||||
{
|
||||
double[] data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, double.NaN];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(span.ContainsNonFinite());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsNonFinite_SingleNaN_ReturnsTrue()
|
||||
{
|
||||
double[] data = [double.NaN];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(span.ContainsNonFinite());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsNonFinite_TwoElements_AllFinite_ReturnsFalse()
|
||||
{
|
||||
double[] data = [1.0, 2.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.False(span.ContainsNonFinite());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsNonFinite_TwoElements_OneNaN_ReturnsTrue()
|
||||
{
|
||||
double[] data = [1.0, double.NaN];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(span.ContainsNonFinite());
|
||||
}
|
||||
|
||||
// SumSIMD tests
|
||||
[Fact]
|
||||
public void SumSIMD_EmptySpan_ReturnsZero()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
Assert.Equal(0.0, span.SumSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumSIMD_SingleElement_ReturnsElement()
|
||||
{
|
||||
double[] data = [42.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(42.5, span.SumSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumSIMD_TwoElements_ReturnsSum()
|
||||
{
|
||||
double[] data = [1.5, 2.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(4.0, span.SumSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumSIMD_MultipleElements_ReturnsCorrectSum()
|
||||
{
|
||||
double[] data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(55.0, span.SumSIMD(), precision: 10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumSIMD_LargeArray_ReturnsCorrectSum()
|
||||
{
|
||||
double[] data = new double[1000];
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
data[i] = i + 1.0;
|
||||
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
double expected = 1000.0 * 1001.0 / 2.0;
|
||||
Assert.Equal(expected, span.SumSIMD(), precision: 8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumSIMD_ContainsNaN_ReturnsNaN()
|
||||
{
|
||||
double[] data = [1.0, 2.0, double.NaN, 4.0, 5.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(double.IsNaN(span.SumSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumSIMD_ContainsInfinity_ReturnsNaN()
|
||||
{
|
||||
double[] data = [1.0, 2.0, double.PositiveInfinity, 4.0, 5.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(double.IsNaN(span.SumSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumSIMD_NegativeValues_ReturnsCorrectSum()
|
||||
{
|
||||
double[] data = [-1.0, -2.0, -3.0, -4.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(-10.0, span.SumSIMD());
|
||||
}
|
||||
|
||||
// MinSIMD tests
|
||||
[Fact]
|
||||
public void MinSIMD_EmptySpan_ReturnsNaN()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
Assert.True(double.IsNaN(span.MinSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinSIMD_SingleElement_ReturnsElement()
|
||||
{
|
||||
double[] data = [42.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(42.5, span.MinSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinSIMD_TwoElements_ReturnsMinimum()
|
||||
{
|
||||
double[] data = [5.0, 2.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(2.0, span.MinSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinSIMD_MultipleElements_ReturnsMinimum()
|
||||
{
|
||||
double[] data = [5.0, 2.0, 8.0, 1.0, 9.0, 3.0, 7.0, 4.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(1.0, span.MinSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinSIMD_ContainsNaN_ReturnsNaN()
|
||||
{
|
||||
double[] data = [5.0, 2.0, double.NaN, 1.0, 9.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(double.IsNaN(span.MinSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinSIMD_MinInRemainder_ReturnsCorrectMin()
|
||||
{
|
||||
double[] data = [5.0, 2.0, 8.0, 6.0, 9.0, 3.0, 7.0, 4.0, 0.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(0.5, span.MinSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinSIMD_NegativeValues_ReturnsMinimum()
|
||||
{
|
||||
double[] data = [-5.0, -2.0, -8.0, -1.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(-8.0, span.MinSIMD());
|
||||
}
|
||||
|
||||
// MaxSIMD tests
|
||||
[Fact]
|
||||
public void MaxSIMD_EmptySpan_ReturnsNaN()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
Assert.True(double.IsNaN(span.MaxSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MaxSIMD_SingleElement_ReturnsElement()
|
||||
{
|
||||
double[] data = [42.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(42.5, span.MaxSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MaxSIMD_TwoElements_ReturnsMaximum()
|
||||
{
|
||||
double[] data = [5.0, 9.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(9.0, span.MaxSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MaxSIMD_MultipleElements_ReturnsMaximum()
|
||||
{
|
||||
double[] data = [5.0, 2.0, 8.0, 1.0, 9.0, 3.0, 7.0, 4.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(9.0, span.MaxSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MaxSIMD_ContainsNaN_ReturnsNaN()
|
||||
{
|
||||
double[] data = [5.0, 2.0, double.NaN, 1.0, 9.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(double.IsNaN(span.MaxSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MaxSIMD_MaxInRemainder_ReturnsCorrectMax()
|
||||
{
|
||||
double[] data = [5.0, 2.0, 8.0, 6.0, 4.0, 3.0, 7.0, 1.0, 99.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(99.0, span.MaxSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MaxSIMD_NegativeValues_ReturnsMaximum()
|
||||
{
|
||||
double[] data = [-5.0, -2.0, -8.0, -1.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(-1.0, span.MaxSIMD());
|
||||
}
|
||||
|
||||
// AverageSIMD tests
|
||||
[Fact]
|
||||
public void AverageSIMD_EmptySpan_ReturnsNaN()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
Assert.True(double.IsNaN(span.AverageSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AverageSIMD_TwoElements_ReturnsAverage()
|
||||
{
|
||||
double[] data = [2.0, 4.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(3.0, span.AverageSIMD());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AverageSIMD_MultipleElements_ReturnsCorrectAverage()
|
||||
{
|
||||
double[] data = [1.0, 2.0, 3.0, 4.0, 5.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(3.0, span.AverageSIMD(), precision: 10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AverageSIMD_ContainsNaN_ReturnsNaN()
|
||||
{
|
||||
double[] data = [1.0, double.NaN, 3.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(double.IsNaN(span.AverageSIMD()));
|
||||
}
|
||||
|
||||
// VarianceSIMD tests
|
||||
[Fact]
|
||||
public void VarianceSIMD_LessThanTwoElements_ReturnsNaN()
|
||||
{
|
||||
double[] data = [42.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(double.IsNaN(span.VarianceSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarianceSIMD_EmptySpan_ReturnsNaN()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
Assert.True(double.IsNaN(span.VarianceSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarianceSIMD_TwoElements_ReturnsCorrect()
|
||||
{
|
||||
double[] data = [1.0, 3.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(2.0, span.VarianceSIMD(), precision: 10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarianceSIMD_ThreeElements_ReturnsCorrect()
|
||||
{
|
||||
double[] data = [1.0, 2.0, 3.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(1.0, span.VarianceSIMD(), precision: 10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarianceSIMD_MultipleElements_ReturnsCorrectVariance()
|
||||
{
|
||||
double[] data = [2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
|
||||
double variance = span.VarianceSIMD();
|
||||
Assert.True(Math.Abs(variance - 4.571428) < 0.0001);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarianceSIMD_WithProvidedMean_UsesProvidedMean()
|
||||
{
|
||||
double[] data = [2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
|
||||
double mean = 5.0;
|
||||
double variance = span.VarianceSIMD(mean);
|
||||
|
||||
Assert.True(variance > 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarianceSIMD_ContainsNaN_ReturnsNaN()
|
||||
{
|
||||
double[] data = [2.0, double.NaN, 4.0, 5.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(double.IsNaN(span.VarianceSIMD()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarianceSIMD_WithNaNMean_ReturnsNaN()
|
||||
{
|
||||
double[] data = [2.0, 4.0, 4.0, 5.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(double.IsNaN(span.VarianceSIMD(double.NaN)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarianceSIMD_WithInfinityMean_ReturnsNaN()
|
||||
{
|
||||
double[] data = [2.0, 4.0, 4.0, 5.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(double.IsNaN(span.VarianceSIMD(double.PositiveInfinity)));
|
||||
}
|
||||
|
||||
// StdDevSIMD tests
|
||||
[Fact]
|
||||
public void StdDevSIMD_TwoElements_ReturnsCorrect()
|
||||
{
|
||||
double[] data = [1.0, 3.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(Math.Abs(span.StdDevSIMD() - 1.414) < 0.01);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StdDevSIMD_MultipleElements_ReturnsCorrectStdDev()
|
||||
{
|
||||
double[] data = [2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
|
||||
double stdDev = span.StdDevSIMD();
|
||||
Assert.True(Math.Abs(stdDev - 2.138) < 0.01);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StdDevSIMD_WithProvidedMean_Works()
|
||||
{
|
||||
double[] data = [2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
|
||||
double stdDev = span.StdDevSIMD(5.0);
|
||||
Assert.True(stdDev > 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StdDevSIMD_ContainsNaN_ReturnsNaN()
|
||||
{
|
||||
double[] data = [2.0, double.NaN, 4.0, 5.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(double.IsNaN(span.StdDevSIMD()));
|
||||
}
|
||||
|
||||
// MinMaxSIMD tests
|
||||
[Fact]
|
||||
public void MinMaxSIMD_EmptySpan_ReturnsBothNaN()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
var (min, max) = span.MinMaxSIMD();
|
||||
Assert.True(double.IsNaN(min));
|
||||
Assert.True(double.IsNaN(max));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinMaxSIMD_SingleElement_ReturnsSameValue()
|
||||
{
|
||||
double[] data = [42.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
var (min, max) = span.MinMaxSIMD();
|
||||
Assert.Equal(42.5, min);
|
||||
Assert.Equal(42.5, max);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinMaxSIMD_TwoElements_ReturnsCorrect()
|
||||
{
|
||||
double[] data = [5.0, 2.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
var (min, max) = span.MinMaxSIMD();
|
||||
Assert.Equal(2.0, min);
|
||||
Assert.Equal(5.0, max);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinMaxSIMD_MultipleElements_ReturnsCorrectMinMax()
|
||||
{
|
||||
double[] data = [5.0, 2.0, 8.0, 1.0, 9.0, 3.0, 7.0, 4.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
var (min, max) = span.MinMaxSIMD();
|
||||
Assert.Equal(1.0, min);
|
||||
Assert.Equal(9.0, max);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinMaxSIMD_ContainsNaN_ReturnsBothNaN()
|
||||
{
|
||||
double[] data = [5.0, 2.0, double.NaN, 1.0, 9.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
var (min, max) = span.MinMaxSIMD();
|
||||
Assert.True(double.IsNaN(min));
|
||||
Assert.True(double.IsNaN(max));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinMaxSIMD_MinMaxInRemainder_ReturnsCorrect()
|
||||
{
|
||||
double[] data = [5.0, 2.0, 8.0, 6.0, 4.0, 3.0, 7.0, 5.0, 0.1, 99.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
var (min, max) = span.MinMaxSIMD();
|
||||
Assert.Equal(0.1, min);
|
||||
Assert.Equal(99.0, max);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinMaxSIMD_NegativeValues_ReturnsCorrect()
|
||||
{
|
||||
double[] data = [-5.0, -2.0, -8.0, -1.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
var (min, max) = span.MinMaxSIMD();
|
||||
Assert.Equal(-8.0, min);
|
||||
Assert.Equal(-1.0, max);
|
||||
}
|
||||
|
||||
// Integration tests
|
||||
[Fact]
|
||||
public void SIMD_WorksWithTSeriesValues()
|
||||
{
|
||||
var series = new TSeries(100);
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
series.Add(DateTime.UtcNow.Ticks + i, i + 1.0);
|
||||
}
|
||||
|
||||
var values = series.Values;
|
||||
|
||||
double sum = values.SumSIMD();
|
||||
double avg = values.AverageSIMD();
|
||||
double min = values.MinSIMD();
|
||||
double max = values.MaxSIMD();
|
||||
var (minAlt, maxAlt) = values.MinMaxSIMD();
|
||||
|
||||
Assert.Equal(5050.0, sum, precision: 8);
|
||||
Assert.Equal(50.5, avg, precision: 8);
|
||||
Assert.Equal(1.0, min);
|
||||
Assert.Equal(100.0, max);
|
||||
Assert.Equal(min, minAlt);
|
||||
Assert.Equal(max, maxAlt);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SIMD_WorksWithTBarSeriesClose()
|
||||
{
|
||||
var gbm = new GBM(startPrice: 100.0);
|
||||
long startTime = DateTime.UtcNow.Ticks;
|
||||
var interval = TimeSpan.FromMinutes(1);
|
||||
var bars = gbm.Fetch(1000, startTime, interval);
|
||||
|
||||
var closeValues = bars.Close.Values;
|
||||
|
||||
double sum = closeValues.SumSIMD();
|
||||
double avg = closeValues.AverageSIMD();
|
||||
double min = closeValues.MinSIMD();
|
||||
double max = closeValues.MaxSIMD();
|
||||
|
||||
Assert.True(sum > 0);
|
||||
Assert.True(avg > 0);
|
||||
Assert.True(min > 0);
|
||||
Assert.True(max > min);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SIMD_PerformanceTest_LargeDataset()
|
||||
{
|
||||
var gbm = new GBM(startPrice: 100.0);
|
||||
long startTime = DateTime.UtcNow.Ticks;
|
||||
var interval = TimeSpan.FromMinutes(1);
|
||||
var bars = gbm.Fetch(10000, startTime, interval);
|
||||
var closeValues = bars.Close.Values;
|
||||
|
||||
_ = closeValues.SumSIMD();
|
||||
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
||||
double sum = closeValues.SumSIMD();
|
||||
double avg = closeValues.AverageSIMD();
|
||||
double min = closeValues.MinSIMD();
|
||||
double max = closeValues.MaxSIMD();
|
||||
var (minAlt, maxAlt) = closeValues.MinMaxSIMD();
|
||||
double variance = closeValues.VarianceSIMD();
|
||||
double stdDev = closeValues.StdDevSIMD();
|
||||
|
||||
sw.Stop();
|
||||
|
||||
Assert.True(sum > 0);
|
||||
Assert.True(avg > 0);
|
||||
Assert.True(min > 0);
|
||||
Assert.True(max > min);
|
||||
Assert.True(variance > 0);
|
||||
Assert.True(stdDev > 0);
|
||||
|
||||
Assert.True(sw.ElapsedMilliseconds < 10,
|
||||
$"SIMD operations took {sw.ElapsedMilliseconds}ms, expected < 10ms");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SIMD_ScalarFallback_SmallArray()
|
||||
{
|
||||
double[] data = [1.0, 2.0, 3.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
|
||||
Assert.Equal(6.0, span.SumSIMD());
|
||||
Assert.Equal(1.0, span.MinSIMD());
|
||||
Assert.Equal(3.0, span.MaxSIMD());
|
||||
Assert.Equal(2.0, span.AverageSIMD());
|
||||
|
||||
var (min, max) = span.MinMaxSIMD();
|
||||
Assert.Equal(1.0, min);
|
||||
Assert.Equal(3.0, max);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for internal scalar implementations
|
||||
public class SimdScalarFallbackTests
|
||||
{
|
||||
[Fact]
|
||||
public void ContainsNonFiniteScalar_AllFinite_ReturnsFalse()
|
||||
{
|
||||
double[] data = [1.0, 2.0, 3.0, 4.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.False(SimdExtensions.ContainsNonFiniteScalar(span));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsNonFiniteScalar_ContainsNaN_ReturnsTrue()
|
||||
{
|
||||
double[] data = [1.0, double.NaN, 3.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(SimdExtensions.ContainsNonFiniteScalar(span));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsNonFiniteScalar_ContainsInfinity_ReturnsTrue()
|
||||
{
|
||||
double[] data = [1.0, double.PositiveInfinity, 3.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.True(SimdExtensions.ContainsNonFiniteScalar(span));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsNonFiniteScalar_Empty_ReturnsFalse()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
Assert.False(SimdExtensions.ContainsNonFiniteScalar(span));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumScalar_MultipleElements_ReturnsCorrectSum()
|
||||
{
|
||||
double[] data = [1.0, 2.0, 3.0, 4.0, 5.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(15.0, SimdExtensions.SumScalar(span));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumScalar_NegativeValues_ReturnsCorrectSum()
|
||||
{
|
||||
double[] data = [-1.0, -2.0, 3.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(0.0, SimdExtensions.SumScalar(span));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SumScalar_Empty_ReturnsZero()
|
||||
{
|
||||
var span = ReadOnlySpan<double>.Empty;
|
||||
Assert.Equal(0.0, SimdExtensions.SumScalar(span));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinScalar_MultipleElements_ReturnsMinimum()
|
||||
{
|
||||
double[] data = [5.0, 2.0, 8.0, 1.0, 9.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(1.0, SimdExtensions.MinScalar(span));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinScalar_NegativeValues_ReturnsMinimum()
|
||||
{
|
||||
double[] data = [-5.0, -2.0, -8.0, -1.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(-8.0, SimdExtensions.MinScalar(span));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinScalar_SingleElement_ReturnsElement()
|
||||
{
|
||||
double[] data = [42.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(42.5, SimdExtensions.MinScalar(span));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MaxScalar_MultipleElements_ReturnsMaximum()
|
||||
{
|
||||
double[] data = [5.0, 2.0, 8.0, 1.0, 9.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(9.0, SimdExtensions.MaxScalar(span));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MaxScalar_NegativeValues_ReturnsMaximum()
|
||||
{
|
||||
double[] data = [-5.0, -2.0, -8.0, -1.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(-1.0, SimdExtensions.MaxScalar(span));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MaxScalar_SingleElement_ReturnsElement()
|
||||
{
|
||||
double[] data = [42.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
Assert.Equal(42.5, SimdExtensions.MaxScalar(span));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarianceScalar_MultipleElements_ReturnsCorrectVariance()
|
||||
{
|
||||
double[] data = [2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
double mean = 5.0;
|
||||
double variance = SimdExtensions.VarianceScalar(span, mean);
|
||||
Assert.True(Math.Abs(variance - 4.571428) < 0.0001);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarianceScalar_TwoElements_ReturnsCorrectVariance()
|
||||
{
|
||||
double[] data = [1.0, 3.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
double mean = 2.0;
|
||||
Assert.Equal(2.0, SimdExtensions.VarianceScalar(span, mean), precision: 10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinMaxScalar_MultipleElements_ReturnsCorrectMinMax()
|
||||
{
|
||||
double[] data = [5.0, 2.0, 8.0, 1.0, 9.0, 3.0, 7.0, 4.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
var (min, max) = SimdExtensions.MinMaxScalar(span);
|
||||
Assert.Equal(1.0, min);
|
||||
Assert.Equal(9.0, max);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinMaxScalar_NegativeValues_ReturnsCorrectMinMax()
|
||||
{
|
||||
double[] data = [-5.0, -2.0, -8.0, -1.0];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
var (min, max) = SimdExtensions.MinMaxScalar(span);
|
||||
Assert.Equal(-8.0, min);
|
||||
Assert.Equal(-1.0, max);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MinMaxScalar_SingleElement_ReturnsSameValue()
|
||||
{
|
||||
double[] data = [42.5];
|
||||
var span = new ReadOnlySpan<double>(data);
|
||||
var (min, max) = SimdExtensions.MinMaxScalar(span);
|
||||
Assert.Equal(42.5, min);
|
||||
Assert.Equal(42.5, max);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,76 @@ namespace QuanTAlib;
|
||||
/// </summary>
|
||||
public static class SimdExtensions
|
||||
{
|
||||
// Internal scalar implementations for testability
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static bool ContainsNonFiniteScalar(ReadOnlySpan<double> span)
|
||||
{
|
||||
for (int i = 0; i < span.Length; i++)
|
||||
{
|
||||
if (!double.IsFinite(span[i]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static double SumScalar(ReadOnlySpan<double> span)
|
||||
{
|
||||
double scalar = 0.0;
|
||||
for (int i = 0; i < span.Length; i++)
|
||||
scalar += span[i];
|
||||
return scalar;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static double MinScalar(ReadOnlySpan<double> span)
|
||||
{
|
||||
double min = span[0];
|
||||
for (int i = 1; i < span.Length; i++)
|
||||
{
|
||||
if (span[i] < min)
|
||||
min = span[i];
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static double MaxScalar(ReadOnlySpan<double> span)
|
||||
{
|
||||
double max = span[0];
|
||||
for (int i = 1; i < span.Length; i++)
|
||||
{
|
||||
if (span[i] > max)
|
||||
max = span[i];
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static double VarianceScalar(ReadOnlySpan<double> span, double mean)
|
||||
{
|
||||
double sumSquares = 0.0;
|
||||
for (int i = 0; i < span.Length; i++)
|
||||
{
|
||||
double diff = span[i] - mean;
|
||||
sumSquares += diff * diff;
|
||||
}
|
||||
return sumSquares / (span.Length - 1);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static (double Min, double Max) MinMaxScalar(ReadOnlySpan<double> span)
|
||||
{
|
||||
double scalarMin = span[0];
|
||||
double scalarMax = span[0];
|
||||
for (int i = 1; i < span.Length; i++)
|
||||
{
|
||||
if (span[i] < scalarMin) scalarMin = span[i];
|
||||
if (span[i] > scalarMax) scalarMax = span[i];
|
||||
}
|
||||
return (scalarMin, scalarMax);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if span contains any non-finite values (NaN or Infinity).
|
||||
/// Returns true if any non-finite value is found.
|
||||
@@ -26,8 +96,6 @@ public static class SimdExtensions
|
||||
for (; i <= span.Length - vectorSize; i += vectorSize)
|
||||
{
|
||||
var vector = new Vector<double>(span.Slice(i, vectorSize));
|
||||
// Check for NaN: NaN != NaN is true
|
||||
// Check for Infinity: IsInfinity
|
||||
for (int j = 0; j < vectorSize; j++)
|
||||
{
|
||||
if (!double.IsFinite(vector[j]))
|
||||
@@ -45,13 +113,7 @@ public static class SimdExtensions
|
||||
return false;
|
||||
}
|
||||
|
||||
// Scalar fallback
|
||||
for (int i = 0; i < span.Length; i++)
|
||||
{
|
||||
if (!double.IsFinite(span[i]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return ContainsNonFiniteScalar(span);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -92,11 +154,7 @@ public static class SimdExtensions
|
||||
return result;
|
||||
}
|
||||
|
||||
// Scalar fallback
|
||||
double scalar = 0.0;
|
||||
for (int i = 0; i < span.Length; i++)
|
||||
scalar += span[i];
|
||||
return scalar;
|
||||
return SumScalar(span);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -144,14 +202,7 @@ public static class SimdExtensions
|
||||
return result;
|
||||
}
|
||||
|
||||
// Scalar fallback
|
||||
double min = span[0];
|
||||
for (int i = 1; i < span.Length; i++)
|
||||
{
|
||||
if (span[i] < min)
|
||||
min = span[i];
|
||||
}
|
||||
return min;
|
||||
return MinScalar(span);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -199,14 +250,7 @@ public static class SimdExtensions
|
||||
return result;
|
||||
}
|
||||
|
||||
// Scalar fallback
|
||||
double max = span[0];
|
||||
for (int i = 1; i < span.Length; i++)
|
||||
{
|
||||
if (span[i] > max)
|
||||
max = span[i];
|
||||
}
|
||||
return max;
|
||||
return MaxScalar(span);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -270,14 +314,7 @@ public static class SimdExtensions
|
||||
return result / (span.Length - 1);
|
||||
}
|
||||
|
||||
// Scalar fallback
|
||||
double sumSquares = 0.0;
|
||||
for (int i = 0; i < span.Length; i++)
|
||||
{
|
||||
double diff = span[i] - m;
|
||||
sumSquares += diff * diff;
|
||||
}
|
||||
return sumSquares / (span.Length - 1);
|
||||
return VarianceScalar(span, m);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -339,14 +376,6 @@ public static class SimdExtensions
|
||||
return (min, max);
|
||||
}
|
||||
|
||||
// Scalar fallback
|
||||
double scalarMin = span[0];
|
||||
double scalarMax = span[0];
|
||||
for (int i = 1; i < span.Length; i++)
|
||||
{
|
||||
if (span[i] < scalarMin) scalarMin = span[i];
|
||||
if (span[i] > scalarMax) scalarMax = span[i];
|
||||
}
|
||||
return (scalarMin, scalarMax);
|
||||
return MinMaxScalar(span);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user