mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-03 03:47:42 +00:00
060649192f
- Remove 'C# Implementation Considerations' sections from 34 indicator .md files - Delete 29 temp PowerShell scripts (_fix_mojibake.ps1, _hex_scan.ps1, etc.) - Move test files into tests/ subdirectories for consistent project structure - Add trader-focused bullet points to indicator documentation
656 lines
19 KiB
C#
656 lines
19 KiB
C#
namespace QuanTAlib.Tests;
|
|
|
|
/// <summary>
|
|
/// Tests for MonotonicDeque — O(1) amortized sliding window min/max data structure.
|
|
/// Covers: constructor validation, PushMax, PushMin, GetExtremum, Reset,
|
|
/// RebuildMax, RebuildMin, FrontIndex, Count, window expiration,
|
|
/// edge cases (equal values, descending/ascending sequences).
|
|
/// </summary>
|
|
public class MonotonicDequeTests
|
|
{
|
|
// ═══════════════════════════════ Constructor ═══════════════════════════════
|
|
|
|
[Fact]
|
|
public void Constructor_ZeroPeriod_Throws()
|
|
{
|
|
Assert.Throws<ArgumentOutOfRangeException>(() => new MonotonicDeque(0));
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_NegativePeriod_Throws()
|
|
{
|
|
Assert.Throws<ArgumentOutOfRangeException>(() => new MonotonicDeque(-1));
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_ValidPeriod_Succeeds()
|
|
{
|
|
var deque = new MonotonicDeque(5);
|
|
Assert.NotNull(deque);
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_PeriodOne_IsValid()
|
|
{
|
|
var deque = new MonotonicDeque(1);
|
|
Assert.Equal(0, deque.Count);
|
|
}
|
|
|
|
// ═══════════════════════════════ Initial State ════════════════════════════
|
|
|
|
[Fact]
|
|
public void Count_InitiallyZero()
|
|
{
|
|
var deque = new MonotonicDeque(5);
|
|
Assert.Equal(0, deque.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void FrontIndex_InitiallyNegativeOne()
|
|
{
|
|
var deque = new MonotonicDeque(5);
|
|
Assert.Equal(-1, deque.FrontIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetExtremum_Empty_ReturnsNaN()
|
|
{
|
|
var deque = new MonotonicDeque(5);
|
|
double[] buffer = new double[5];
|
|
Assert.True(double.IsNaN(deque.GetExtremum(buffer)));
|
|
}
|
|
|
|
// ═══════════════════════════════ PushMax ═══════════════════════════════════
|
|
|
|
[Fact]
|
|
public void PushMax_SingleValue_Tracked()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0] = 100.0;
|
|
deque.PushMax(0, 100.0, buffer);
|
|
|
|
Assert.Equal(1, deque.Count);
|
|
Assert.Equal(100.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMax_AscendingValues_TracksMaximum()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
buffer[i % period] = i * 10.0;
|
|
deque.PushMax(i, i * 10.0, buffer);
|
|
}
|
|
|
|
// Maximum should be 40 (last value in ascending sequence)
|
|
Assert.Equal(40.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMax_DescendingValues_TracksMaximum()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
double val = (4 - i) * 10.0;
|
|
buffer[i % period] = val;
|
|
deque.PushMax(i, val, buffer);
|
|
}
|
|
|
|
// Maximum should be 40 (first value in descending sequence)
|
|
Assert.Equal(40.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMax_EqualValues_TracksCorrectly()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
buffer[i % period] = 50.0;
|
|
deque.PushMax(i, 50.0, buffer);
|
|
}
|
|
|
|
Assert.Equal(50.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMax_WindowExpiration_DropsOldMax()
|
|
{
|
|
int period = 3;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
// Push: 100, 50, 30, then 20 (window slides past 100)
|
|
buffer[0 % period] = 100.0;
|
|
deque.PushMax(0, 100.0, buffer);
|
|
Assert.Equal(100.0, deque.GetExtremum(buffer));
|
|
|
|
buffer[1 % period] = 50.0;
|
|
deque.PushMax(1, 50.0, buffer);
|
|
Assert.Equal(100.0, deque.GetExtremum(buffer));
|
|
|
|
buffer[2 % period] = 30.0;
|
|
deque.PushMax(2, 30.0, buffer);
|
|
Assert.Equal(100.0, deque.GetExtremum(buffer));
|
|
|
|
// Index 3 — window now [1,2,3], so 100 (index 0) expires
|
|
buffer[3 % period] = 20.0;
|
|
deque.PushMax(3, 20.0, buffer);
|
|
Assert.Equal(50.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMax_NewMaxReplacesAll()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0 % period] = 10.0;
|
|
deque.PushMax(0, 10.0, buffer);
|
|
buffer[1 % period] = 20.0;
|
|
deque.PushMax(1, 20.0, buffer);
|
|
buffer[2 % period] = 30.0;
|
|
deque.PushMax(2, 30.0, buffer);
|
|
|
|
// New value 100 should replace all (they're all <=)
|
|
buffer[3 % period] = 100.0;
|
|
deque.PushMax(3, 100.0, buffer);
|
|
Assert.Equal(100.0, deque.GetExtremum(buffer));
|
|
Assert.Equal(1, deque.Count);
|
|
}
|
|
|
|
// ═══════════════════════════════ PushMin ═══════════════════════════════════
|
|
|
|
[Fact]
|
|
public void PushMin_SingleValue_Tracked()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0] = 100.0;
|
|
deque.PushMin(0, 100.0, buffer);
|
|
|
|
Assert.Equal(1, deque.Count);
|
|
Assert.Equal(100.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMin_DescendingValues_TracksMinimum()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
double val = (4 - i) * 10.0;
|
|
buffer[i % period] = val;
|
|
deque.PushMin(i, val, buffer);
|
|
}
|
|
|
|
// Minimum should be 0 (last value in descending sequence)
|
|
Assert.Equal(0.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMin_AscendingValues_TracksMinimum()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
buffer[i % period] = i * 10.0;
|
|
deque.PushMin(i, i * 10.0, buffer);
|
|
}
|
|
|
|
// Minimum should be 0 (first value in ascending sequence)
|
|
Assert.Equal(0.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMin_EqualValues_TracksCorrectly()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
buffer[i % period] = 50.0;
|
|
deque.PushMin(i, 50.0, buffer);
|
|
}
|
|
|
|
Assert.Equal(50.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMin_WindowExpiration_DropsOldMin()
|
|
{
|
|
int period = 3;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
// Push: 10, 50, 80, then 90 (window slides past 10)
|
|
buffer[0 % period] = 10.0;
|
|
deque.PushMin(0, 10.0, buffer);
|
|
Assert.Equal(10.0, deque.GetExtremum(buffer));
|
|
|
|
buffer[1 % period] = 50.0;
|
|
deque.PushMin(1, 50.0, buffer);
|
|
Assert.Equal(10.0, deque.GetExtremum(buffer));
|
|
|
|
buffer[2 % period] = 80.0;
|
|
deque.PushMin(2, 80.0, buffer);
|
|
Assert.Equal(10.0, deque.GetExtremum(buffer));
|
|
|
|
// Index 3 — window now [1,2,3], so 10 (index 0) expires
|
|
buffer[3 % period] = 90.0;
|
|
deque.PushMin(3, 90.0, buffer);
|
|
Assert.Equal(50.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMin_NewMinReplacesAll()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0 % period] = 100.0;
|
|
deque.PushMin(0, 100.0, buffer);
|
|
buffer[1 % period] = 80.0;
|
|
deque.PushMin(1, 80.0, buffer);
|
|
buffer[2 % period] = 60.0;
|
|
deque.PushMin(2, 60.0, buffer);
|
|
|
|
// New value 5 should replace all (they're all >=)
|
|
buffer[3 % period] = 5.0;
|
|
deque.PushMin(3, 5.0, buffer);
|
|
Assert.Equal(5.0, deque.GetExtremum(buffer));
|
|
Assert.Equal(1, deque.Count);
|
|
}
|
|
|
|
// ═══════════════════════════════ FrontIndex ═══════════════════════════════
|
|
|
|
[Fact]
|
|
public void FrontIndex_TracksCurrentExtremumIndex()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0] = 100.0;
|
|
deque.PushMax(0, 100.0, buffer);
|
|
Assert.Equal(0, deque.FrontIndex);
|
|
|
|
buffer[1 % period] = 50.0;
|
|
deque.PushMax(1, 50.0, buffer);
|
|
Assert.Equal(0, deque.FrontIndex); // 100 is still max
|
|
|
|
buffer[2 % period] = 200.0;
|
|
deque.PushMax(2, 200.0, buffer);
|
|
Assert.Equal(2, deque.FrontIndex); // 200 is new max
|
|
}
|
|
|
|
// ═══════════════════════════════ Reset ════════════════════════════════════
|
|
|
|
[Fact]
|
|
public void Reset_ClearsCount()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
buffer[i] = i * 10.0;
|
|
deque.PushMax(i, i * 10.0, buffer);
|
|
}
|
|
Assert.True(deque.Count > 0);
|
|
|
|
deque.Reset();
|
|
Assert.Equal(0, deque.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void Reset_FrontIndexBecomesNegativeOne()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0] = 50.0;
|
|
deque.PushMax(0, 50.0, buffer);
|
|
deque.Reset();
|
|
Assert.Equal(-1, deque.FrontIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Reset_GetExtremumReturnsNaN()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0] = 50.0;
|
|
deque.PushMax(0, 50.0, buffer);
|
|
deque.Reset();
|
|
Assert.True(double.IsNaN(deque.GetExtremum(buffer)));
|
|
}
|
|
|
|
[Fact]
|
|
public void Reset_AllowsReuse()
|
|
{
|
|
int period = 3;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0] = 100.0;
|
|
deque.PushMax(0, 100.0, buffer);
|
|
deque.Reset();
|
|
|
|
buffer[0] = 50.0;
|
|
deque.PushMax(0, 50.0, buffer);
|
|
Assert.Equal(50.0, deque.GetExtremum(buffer));
|
|
Assert.Equal(1, deque.Count);
|
|
}
|
|
|
|
// ═══════════════════════════════ RebuildMax ═══════════════════════════════
|
|
|
|
[Fact]
|
|
public void RebuildMax_EmptyBuffer_NoOp()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
deque.RebuildMax(buffer, 0, 0);
|
|
Assert.Equal(0, deque.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void RebuildMax_RebuildsCorrectly()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
// Fill buffer: [10, 50, 30, 20, 40]
|
|
buffer[0] = 10.0;
|
|
buffer[1] = 50.0;
|
|
buffer[2] = 30.0;
|
|
buffer[3] = 20.0;
|
|
buffer[4] = 40.0;
|
|
|
|
deque.RebuildMax(buffer, 4, 5);
|
|
|
|
// Maximum should be 50 (at index 1)
|
|
Assert.Equal(50.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void RebuildMax_SingleElement()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0] = 42.0;
|
|
deque.RebuildMax(buffer, 0, 1);
|
|
|
|
Assert.Equal(42.0, deque.GetExtremum(buffer));
|
|
Assert.Equal(1, deque.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void RebuildMax_AfterPreviousData_Resets()
|
|
{
|
|
int period = 3;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
// First push some data
|
|
buffer[0] = 100.0;
|
|
deque.PushMax(0, 100.0, buffer);
|
|
buffer[1] = 200.0;
|
|
deque.PushMax(1, 200.0, buffer);
|
|
|
|
// Rebuild with different data
|
|
buffer[0] = 10.0;
|
|
buffer[1] = 20.0;
|
|
buffer[2] = 15.0;
|
|
deque.RebuildMax(buffer, 2, 3);
|
|
|
|
Assert.Equal(20.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
// ═══════════════════════════════ RebuildMin ═══════════════════════════════
|
|
|
|
[Fact]
|
|
public void RebuildMin_EmptyBuffer_NoOp()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
deque.RebuildMin(buffer, 0, 0);
|
|
Assert.Equal(0, deque.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void RebuildMin_RebuildsCorrectly()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
// Fill buffer: [10, 50, 30, 20, 40]
|
|
buffer[0] = 10.0;
|
|
buffer[1] = 50.0;
|
|
buffer[2] = 30.0;
|
|
buffer[3] = 20.0;
|
|
buffer[4] = 40.0;
|
|
|
|
deque.RebuildMin(buffer, 4, 5);
|
|
|
|
// Minimum should be 10 (at index 0)
|
|
Assert.Equal(10.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void RebuildMin_SingleElement()
|
|
{
|
|
int period = 5;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0] = 42.0;
|
|
deque.RebuildMin(buffer, 0, 1);
|
|
|
|
Assert.Equal(42.0, deque.GetExtremum(buffer));
|
|
Assert.Equal(1, deque.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void RebuildMin_AfterPreviousData_Resets()
|
|
{
|
|
int period = 3;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
// First push some data
|
|
buffer[0] = 5.0;
|
|
deque.PushMin(0, 5.0, buffer);
|
|
buffer[1] = 3.0;
|
|
deque.PushMin(1, 3.0, buffer);
|
|
|
|
// Rebuild with different data
|
|
buffer[0] = 100.0;
|
|
buffer[1] = 200.0;
|
|
buffer[2] = 150.0;
|
|
deque.RebuildMin(buffer, 2, 3);
|
|
|
|
Assert.Equal(100.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
// ═══════════════════════════════ Sliding Window Scenarios ═════════════════
|
|
|
|
[Fact]
|
|
public void PushMax_LongSequence_TracksRollingMax()
|
|
{
|
|
int period = 3;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
double[] values = [10, 20, 30, 15, 25, 5, 35, 10, 40, 20];
|
|
double[] expectedMax = [10, 20, 30, 30, 30, 25, 35, 35, 40, 40];
|
|
|
|
for (int i = 0; i < values.Length; i++)
|
|
{
|
|
buffer[i % period] = values[i];
|
|
deque.PushMax(i, values[i], buffer);
|
|
double actual = deque.GetExtremum(buffer);
|
|
Assert.True(actual == expectedMax[i],
|
|
$"Max mismatch at index {i}: expected {expectedMax[i]}, got {actual}");
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMin_LongSequence_TracksRollingMin()
|
|
{
|
|
int period = 3;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
double[] values = [50, 40, 30, 45, 35, 55, 25, 60, 20, 50];
|
|
double[] expectedMin = [50, 40, 30, 30, 30, 35, 25, 25, 20, 20];
|
|
|
|
for (int i = 0; i < values.Length; i++)
|
|
{
|
|
buffer[i % period] = values[i];
|
|
deque.PushMin(i, values[i], buffer);
|
|
double actual = deque.GetExtremum(buffer);
|
|
Assert.True(actual == expectedMin[i],
|
|
$"Min mismatch at index {i}: expected {expectedMin[i]}, got {actual}");
|
|
}
|
|
}
|
|
|
|
// ═══════════════════════════════ Period 1 ═════════════════════════════════
|
|
|
|
[Fact]
|
|
public void PushMax_PeriodOne_AlwaysLatestValue()
|
|
{
|
|
int period = 1;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0] = 100.0;
|
|
deque.PushMax(0, 100.0, buffer);
|
|
Assert.Equal(100.0, deque.GetExtremum(buffer));
|
|
|
|
buffer[0] = 50.0;
|
|
deque.PushMax(1, 50.0, buffer);
|
|
Assert.Equal(50.0, deque.GetExtremum(buffer));
|
|
|
|
buffer[0] = 200.0;
|
|
deque.PushMax(2, 200.0, buffer);
|
|
Assert.Equal(200.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMin_PeriodOne_AlwaysLatestValue()
|
|
{
|
|
int period = 1;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0] = 100.0;
|
|
deque.PushMin(0, 100.0, buffer);
|
|
Assert.Equal(100.0, deque.GetExtremum(buffer));
|
|
|
|
buffer[0] = 50.0;
|
|
deque.PushMin(1, 50.0, buffer);
|
|
Assert.Equal(50.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
// ═══════════════════════════════ Edge Cases ═══════════════════════════════
|
|
|
|
[Fact]
|
|
public void PushMax_NegativeValues_TracksCorrectly()
|
|
{
|
|
int period = 3;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0] = -30.0;
|
|
deque.PushMax(0, -30.0, buffer);
|
|
buffer[1 % period] = -10.0;
|
|
deque.PushMax(1, -10.0, buffer);
|
|
buffer[2 % period] = -20.0;
|
|
deque.PushMax(2, -20.0, buffer);
|
|
|
|
Assert.Equal(-10.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMin_NegativeValues_TracksCorrectly()
|
|
{
|
|
int period = 3;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0] = -10.0;
|
|
deque.PushMin(0, -10.0, buffer);
|
|
buffer[1 % period] = -30.0;
|
|
deque.PushMin(1, -30.0, buffer);
|
|
buffer[2 % period] = -20.0;
|
|
deque.PushMin(2, -20.0, buffer);
|
|
|
|
Assert.Equal(-30.0, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMax_VeryLargeValues_NoOverflow()
|
|
{
|
|
int period = 3;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
buffer[0] = 1e300;
|
|
deque.PushMax(0, 1e300, buffer);
|
|
Assert.Equal(1e300, deque.GetExtremum(buffer));
|
|
}
|
|
|
|
[Fact]
|
|
public void PushMax_ZeroValues_TracksCorrectly()
|
|
{
|
|
int period = 3;
|
|
var deque = new MonotonicDeque(period);
|
|
double[] buffer = new double[period];
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
buffer[i] = 0.0;
|
|
deque.PushMax(i, 0.0, buffer);
|
|
}
|
|
|
|
Assert.Equal(0.0, deque.GetExtremum(buffer));
|
|
}
|
|
}
|