Support split special case

This commit is contained in:
wreng 2024-02-21 16:39:13 +03:00 committed by Ikpil
parent c47cc79552
commit 609508c94f
3 changed files with 102 additions and 24 deletions

View File

@ -191,14 +191,17 @@ namespace DotRecast.Core.Buffers
public T[] ToArray()
{
T[] newArray = new T[Size];
var span1 = ArrayOne();
span1.CopyTo(newArray.AsSpan());
ArrayTwo().CopyTo(newArray.AsSpan(span1.Length..));
CopyTo(newArray);
return newArray;
}
public void CopyTo(Span<T> destination)
{
var span1 = ArrayOne();
span1.CopyTo(destination);
ArrayTwo().CopyTo(destination[span1.Length..]);
}
private void ThrowIfEmpty(string message = "Cannot access an empty buffer.")
{
if (IsEmpty)
@ -232,7 +235,7 @@ namespace DotRecast.Core.Buffers
: index - Capacity);
}
private Span<T> ArrayOne()
internal Span<T> ArrayOne()
{
if (IsEmpty)
{
@ -247,7 +250,7 @@ namespace DotRecast.Core.Buffers
return new Span<T>(_buffer, _start, _buffer.Length - _start);
}
private Span<T> ArrayTwo()
internal Span<T> ArrayTwo()
{
if (IsEmpty)
{
@ -262,11 +265,6 @@ namespace DotRecast.Core.Buffers
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();

View File

@ -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)
{
@ -18,7 +18,7 @@ namespace DotRecast.Core.Buffers
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..];
}
@ -28,17 +28,17 @@ namespace DotRecast.Core.Buffers
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)
@ -52,7 +52,7 @@ namespace DotRecast.Core.Buffers
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..];
}
@ -62,9 +62,9 @@ namespace DotRecast.Core.Buffers
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)
@ -78,7 +78,7 @@ namespace DotRecast.Core.Buffers
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..];
}
@ -87,5 +87,33 @@ namespace DotRecast.Core.Buffers
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);
}
}
}

View File

@ -394,4 +394,56 @@ public class RcCyclicBufferTests
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()));
}
}