style patterns

This commit is contained in:
Miha Kralj
2026-01-25 16:01:45 -08:00
parent 2836f253c4
commit e59665c8f0
399 changed files with 6892 additions and 1323 deletions
+6
View File
@@ -98,10 +98,14 @@ public class RgmaTests
var streamValues = new List<double>(series.Count);
for (int i = 0; i < series.Count; i++)
{
streamValues.Add(rgma.Update(series[i]).Value);
}
for (int i = 0; i < series.Count; i++)
{
Assert.Equal(batch[i].Value, streamValues[i], precision: 10);
}
}
[Fact]
@@ -117,7 +121,9 @@ public class RgmaTests
TSeries batch = Rgma.Batch(series, period, passes);
for (int i = 0; i < values.Length; i++)
{
Assert.Equal(batch[i].Value, output[i], precision: 10);
}
}
private static TSeries BuildSeries(int count, int seed)
@@ -27,12 +27,16 @@ public sealed class RgmaValidationTests : IDisposable
private void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
_disposed = true;
if (disposing)
{
_testData?.Dispose();
}
}
[Fact]
@@ -52,7 +56,9 @@ public sealed class RgmaValidationTests : IDisposable
int startIdx = rgmaResult.Count - compareCount;
for (int i = startIdx; i < rgmaResult.Count; i++)
{
Assert.Equal(emaResult[i].Value, rgmaResult[i].Value, 1e-10);
}
}
_output.WriteLine("RGMA(passes=1) Batch validated successfully against EMA");
@@ -81,7 +87,9 @@ public sealed class RgmaValidationTests : IDisposable
int startIdx = rgmaResults.Count - compareCount;
for (int i = startIdx; i < rgmaResults.Count; i++)
{
Assert.Equal(emaResults[i], rgmaResults[i], 1e-10);
}
}
_output.WriteLine("RGMA(passes=1) Streaming validated successfully against EMA");
@@ -105,7 +113,9 @@ public sealed class RgmaValidationTests : IDisposable
int startIdx = sourceData.Length - compareCount;
for (int i = startIdx; i < sourceData.Length; i++)
{
Assert.Equal(emaOutput[i], rgmaOutput[i], 1e-10);
}
}
_output.WriteLine("RGMA(passes=1) Span validated successfully against EMA");
@@ -131,7 +141,9 @@ public sealed class RgmaValidationTests : IDisposable
var rgmaStream = new Rgma(period, passCount);
var streaming = new double[_testData.Data.Count];
for (int i = 0; i < _testData.Data.Count; i++)
{
streaming[i] = rgmaStream.Update(_testData.Data[i]).Value;
}
// Span
var spanOutput = new double[sourceData.Length];
+58 -8
View File
@@ -111,7 +111,10 @@ public sealed class Rgma : AbstractBase
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
if (source.Length == 0) return;
if (source.Length == 0)
{
return;
}
_state = State.New();
_p_state = State.New();
@@ -172,9 +175,14 @@ public sealed class Rgma : AbstractBase
finally
{
if (filtersRented != null)
{
ArrayPool<double>.Shared.Return(filtersRented);
}
if (rented != null)
{
ArrayPool<double>.Shared.Return(rented);
}
}
}
@@ -189,7 +197,9 @@ public sealed class Rgma : AbstractBase
if (_passes <= 8)
{
for (int i = 0; i < _passes; i++)
{
_p_filters[i] = _filters[i];
}
}
else
{
@@ -203,7 +213,9 @@ public sealed class Rgma : AbstractBase
if (_passes <= 8)
{
for (int i = 0; i < _passes; i++)
{
_filters[i] = _p_filters[i];
}
}
else
{
@@ -222,7 +234,10 @@ public sealed class Rgma : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public override TSeries Update(TSeries source)
{
if (source.Count == 0) return [];
if (source.Count == 0)
{
return [];
}
int len = source.Count;
var t = new List<long>(len);
@@ -263,22 +278,31 @@ public sealed class Rgma : AbstractBase
state.TickCount = 1;
state.E *= decay;
if (state.E <= COVERAGE_THRESHOLD)
{
state.IsHot = true;
}
return input;
}
// Stage 0
filters[0] = Math.FusedMultiplyAdd(alpha, input - filters[0], filters[0]);
for (int i = 1; i < filters.Length; i++)
{
filters[i] = Math.FusedMultiplyAdd(alpha, filters[i - 1] - filters[i], filters[i]);
}
state.TickCount++;
state.E *= decay;
if (!state.IsHot && state.E <= COVERAGE_THRESHOLD)
{
state.IsHot = true;
}
if (state.TickCount >= ResyncInterval)
{
state.TickCount = 0;
}
return filters[^1];
}
@@ -298,9 +322,13 @@ public sealed class Rgma : AbstractBase
{
double x = source[i];
if (double.IsFinite(x))
{
lastValid = x;
}
else
{
x = lastValid;
}
double y;
if (!state.IsInitialized)
@@ -310,22 +338,31 @@ public sealed class Rgma : AbstractBase
state.TickCount = 1;
state.E *= decay;
if (state.E <= COVERAGE_THRESHOLD)
{
state.IsHot = true;
}
y = x;
}
else
{
filters[0] = Math.FusedMultiplyAdd(alpha, x - filters[0], filters[0]);
for (int p = 1; p < filters.Length; p++)
{
filters[p] = Math.FusedMultiplyAdd(alpha, filters[p - 1] - filters[p], filters[p]);
}
state.TickCount++;
state.E *= decay;
if (!state.IsHot && state.E <= COVERAGE_THRESHOLD)
{
state.IsHot = true;
}
if (state.TickCount >= ResyncInterval)
{
state.TickCount = 0;
}
y = filters[^1];
}
@@ -361,13 +398,24 @@ public sealed class Rgma : AbstractBase
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period, int passes = 3)
{
if (period <= 0)
{
throw new ArgumentException("Period must be greater than 0", nameof(period));
if (passes <= 0)
throw new ArgumentException("Passes must be greater than 0", nameof(passes));
if (source.Length != output.Length)
throw new ArgumentException("Source and output must have the same length", nameof(output));
}
if (source.Length == 0) return;
if (passes <= 0)
{
throw new ArgumentException("Passes must be greater than 0", nameof(passes));
}
if (source.Length != output.Length)
{
throw new ArgumentException("Source and output must have the same length", nameof(output));
}
if (source.Length == 0)
{
return;
}
double alpha = 2.0 / (period / Math.Sqrt(passes) + 1.0);
double decay = 1.0 - alpha;
@@ -405,7 +453,9 @@ public sealed class Rgma : AbstractBase
finally
{
if (rented != null)
{
ArrayPool<double>.Shared.Return(rented);
}
}
}
@@ -420,4 +470,4 @@ public sealed class Rgma : AbstractBase
Array.Fill(_p_filters, double.NaN);
Last = default;
}
}
}