Skip to content

Commit

Permalink
Support split special case
Browse files Browse the repository at this point in the history
  • Loading branch information
wrenge authored and ikpil committed Feb 21, 2024
1 parent c47cc79 commit 609508c
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 23 deletions.
20 changes: 9 additions & 11 deletions src/DotRecast.Core/Buffers/RcCyclicBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,15 @@ public void Clear()
public T[] ToArray()
{
T[] newArray = new T[Size];
CopyTo(newArray);
return newArray;
}

public void CopyTo(Span<T> destination)
{
var span1 = ArrayOne();
span1.CopyTo(newArray.AsSpan());
ArrayTwo().CopyTo(newArray.AsSpan(span1.Length..));

return newArray;
span1.CopyTo(destination);
ArrayTwo().CopyTo(destination[span1.Length..]);
}

private void ThrowIfEmpty(string message = "Cannot access an empty buffer.")
Expand Down Expand Up @@ -232,7 +235,7 @@ private int InternalIndex(int index)
: index - Capacity);
}

private Span<T> ArrayOne()
internal Span<T> ArrayOne()
{
if (IsEmpty)
{
Expand All @@ -247,7 +250,7 @@ private Span<T> ArrayOne()
return new Span<T>(_buffer, _start, _buffer.Length - _start);
}

private Span<T> ArrayTwo()
internal Span<T> ArrayTwo()
{
if (IsEmpty)
{
Expand All @@ -262,11 +265,6 @@ private Span<T> ArrayTwo()
return new Span<T>(_buffer, 0, _end);
}

internal ReadOnlySpan<T> GetBufferSpan()
{
return _buffer;
}

public Enumerator GetEnumerator() => new Enumerator(this);

IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator();
Expand Down
52 changes: 40 additions & 12 deletions src/DotRecast.Core/Buffers/RcCyclicBuffers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ namespace DotRecast.Core.Buffers
{
public static class RcCyclicBuffers
{
public static long Sum(this RcCyclicBuffer<long> source)
public static long Sum(this ReadOnlySpan<long> source)
{
var buffer = source.GetBufferSpan();
var buffer = source;
var result = 0L;
if (Vector.IsHardwareAccelerated)
{
Expand All @@ -18,7 +18,7 @@ public static long Sum(this RcCyclicBuffer<long> source)
vecSum += vec;

result = Vector.Dot(vecSum, Vector<long>.One);
var remainder = source.Size % Vector<long>.Count;
var remainder = source.Length % Vector<long>.Count;
buffer = buffer[^remainder..];
}

Expand All @@ -28,17 +28,17 @@ public static long Sum(this RcCyclicBuffer<long> source)
return result;
}

public static double Average(this RcCyclicBuffer<long> source)
public static double Average(this ReadOnlySpan<long> source)
{
if (0 >= source.Size)
if (0 >= source.Length)
return 0;

return source.Sum() / (double)source.Size;
return source.Sum() / (double)source.Length;
}

public static long Min(this RcCyclicBuffer<long> source)
private static long Min(this ReadOnlySpan<long> source)
{
var buffer = source.GetBufferSpan();
var buffer = source;
var result = long.MaxValue;

if (Vector.IsHardwareAccelerated)
Expand All @@ -52,7 +52,7 @@ public static long Min(this RcCyclicBuffer<long> source)
for (int i = 0; i < Vector<long>.Count; i++)
result = Math.Min(result, vecMin[i]);

var remainder = source.Size % Vector<long>.Count;
var remainder = source.Length % Vector<long>.Count;
buffer = buffer[^remainder..];
}

Expand All @@ -62,9 +62,9 @@ public static long Min(this RcCyclicBuffer<long> source)
return result;
}

public static long Max(this RcCyclicBuffer<long> source)
private static long Max(this ReadOnlySpan<long> source)
{
var buffer = source.GetBufferSpan();
var buffer = source;
var result = long.MinValue;

if (Vector.IsHardwareAccelerated)
Expand All @@ -78,7 +78,7 @@ public static long Max(this RcCyclicBuffer<long> source)
for (int i = 0; i < Vector<long>.Count; i++)
result = Math.Max(result, vecMax[i]);

var remainder = source.Size % Vector<long>.Count;
var remainder = source.Length % Vector<long>.Count;
buffer = buffer[^remainder..];
}

Expand All @@ -87,5 +87,33 @@ public static long Max(this RcCyclicBuffer<long> source)

return result;
}

public static long Sum(this RcCyclicBuffer<long> source)
{
return Sum(source.ArrayOne()) + Sum(source.ArrayTwo());
}

public static double Average(this RcCyclicBuffer<long> source)
{
return Sum(source) / (double)source.Size;
}

public static long Min(this RcCyclicBuffer<long> source)
{
var firstHalf = source.ArrayOne();
var secondHalf = source.ArrayTwo();
var a = firstHalf.Length > 0 ? Min(firstHalf) : long.MaxValue;
var b = secondHalf.Length > 0 ? Min(secondHalf) : long.MaxValue;
return Math.Min(a, b);
}

public static long Max(this RcCyclicBuffer<long> source)
{
var firstHalf = source.ArrayOne();
var secondHalf = source.ArrayTwo();
var a = firstHalf.Length > 0 ? Max(firstHalf) : long.MinValue;
var b = secondHalf.Length > 0 ? Max(secondHalf) : long.MinValue;
return Math.Max(a, b);
}
}
}
52 changes: 52 additions & 0 deletions test/DotRecast.Core.Test/RcCyclicBufferTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -394,4 +394,56 @@ public void RcCyclicBuffers_MaxUnaligned()
var buffer = new RcCyclicBuffer<long>(refValues.Length, refValues);
Assert.That(RcCyclicBuffers.Max(buffer), Is.EqualTo(refValues.Max()));
}

[Test]
public void RcCyclicBuffers_SumDeleted()
{
var initialValues = Enumerable.Range(-100, 211).Select(x => (long)x).ToArray();
var refValues = initialValues.Skip(1).SkipLast(1).ToArray();
var buffer = new RcCyclicBuffer<long>(initialValues.Length, initialValues);
buffer.PopBack();
buffer.PopFront();

Assert.That(RcCyclicBuffers.Sum(buffer), Is.EqualTo(refValues.Sum()));
}

[Test]
public void RcCyclicBuffers_SumSplit()
{
var refValues = Enumerable.Range(-100, 211).Select(x => (long)x).ToArray();
var buffer = new RcCyclicBuffer<long>(refValues.Length, refValues);
buffer.PopFront();
buffer.PushBack(refValues[0]);
Assert.That(RcCyclicBuffers.Sum(buffer), Is.EqualTo(refValues.Sum()));
}

[Test]
public void RcCyclicBuffers_AverageSplit()
{
var refValues = Enumerable.Range(-100, 211).Select(x => (long)x).ToArray();
var buffer = new RcCyclicBuffer<long>(refValues.Length, refValues);
buffer.PopFront();
buffer.PushBack(refValues[0]);
Assert.That(RcCyclicBuffers.Average(buffer), Is.EqualTo(refValues.Average()));
}

[Test]
public void RcCyclicBuffers_MinSplit()
{
var refValues = Enumerable.Range(-100, 211).Select(x => (long)x).ToArray();
var buffer = new RcCyclicBuffer<long>(refValues.Length, refValues);
buffer.PopFront();
buffer.PushBack(refValues[0]);
Assert.That(RcCyclicBuffers.Min(buffer), Is.EqualTo(refValues.Min()));
}

[Test]
public void RcCyclicBuffers_MaxSplit()
{
var refValues = Enumerable.Range(-100, 211).Select(x => (long)x).ToArray();
var buffer = new RcCyclicBuffer<long>(refValues.Length, refValues);
buffer.PopFront();
buffer.PushBack(refValues[0]);
Assert.That(RcCyclicBuffers.Max(buffer), Is.EqualTo(refValues.Max()));
}
}

0 comments on commit 609508c

Please sign in to comment.