forked from bit/DotRecastNetSim
Support split special case
This commit is contained in:
parent
c47cc79552
commit
609508c94f
|
@ -191,14 +191,17 @@ namespace DotRecast.Core.Buffers
|
||||||
public T[] ToArray()
|
public T[] ToArray()
|
||||||
{
|
{
|
||||||
T[] newArray = new T[Size];
|
T[] newArray = new T[Size];
|
||||||
|
CopyTo(newArray);
|
||||||
var span1 = ArrayOne();
|
|
||||||
span1.CopyTo(newArray.AsSpan());
|
|
||||||
ArrayTwo().CopyTo(newArray.AsSpan(span1.Length..));
|
|
||||||
|
|
||||||
return 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.")
|
private void ThrowIfEmpty(string message = "Cannot access an empty buffer.")
|
||||||
{
|
{
|
||||||
if (IsEmpty)
|
if (IsEmpty)
|
||||||
|
@ -232,7 +235,7 @@ namespace DotRecast.Core.Buffers
|
||||||
: index - Capacity);
|
: index - Capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Span<T> ArrayOne()
|
internal Span<T> ArrayOne()
|
||||||
{
|
{
|
||||||
if (IsEmpty)
|
if (IsEmpty)
|
||||||
{
|
{
|
||||||
|
@ -247,7 +250,7 @@ namespace DotRecast.Core.Buffers
|
||||||
return new Span<T>(_buffer, _start, _buffer.Length - _start);
|
return new Span<T>(_buffer, _start, _buffer.Length - _start);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Span<T> ArrayTwo()
|
internal Span<T> ArrayTwo()
|
||||||
{
|
{
|
||||||
if (IsEmpty)
|
if (IsEmpty)
|
||||||
{
|
{
|
||||||
|
@ -262,11 +265,6 @@ namespace DotRecast.Core.Buffers
|
||||||
return new Span<T>(_buffer, 0, _end);
|
return new Span<T>(_buffer, 0, _end);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ReadOnlySpan<T> GetBufferSpan()
|
|
||||||
{
|
|
||||||
return _buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Enumerator GetEnumerator() => new Enumerator(this);
|
public Enumerator GetEnumerator() => new Enumerator(this);
|
||||||
|
|
||||||
IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator();
|
IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator();
|
||||||
|
|
|
@ -6,9 +6,9 @@ namespace DotRecast.Core.Buffers
|
||||||
{
|
{
|
||||||
public static class RcCyclicBuffers
|
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;
|
var result = 0L;
|
||||||
if (Vector.IsHardwareAccelerated)
|
if (Vector.IsHardwareAccelerated)
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,7 @@ namespace DotRecast.Core.Buffers
|
||||||
vecSum += vec;
|
vecSum += vec;
|
||||||
|
|
||||||
result = Vector.Dot(vecSum, Vector<long>.One);
|
result = Vector.Dot(vecSum, Vector<long>.One);
|
||||||
var remainder = source.Size % Vector<long>.Count;
|
var remainder = source.Length % Vector<long>.Count;
|
||||||
buffer = buffer[^remainder..];
|
buffer = buffer[^remainder..];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,17 +28,17 @@ namespace DotRecast.Core.Buffers
|
||||||
return result;
|
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 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;
|
var result = long.MaxValue;
|
||||||
|
|
||||||
if (Vector.IsHardwareAccelerated)
|
if (Vector.IsHardwareAccelerated)
|
||||||
|
@ -52,7 +52,7 @@ namespace DotRecast.Core.Buffers
|
||||||
for (int i = 0; i < Vector<long>.Count; i++)
|
for (int i = 0; i < Vector<long>.Count; i++)
|
||||||
result = Math.Min(result, vecMin[i]);
|
result = Math.Min(result, vecMin[i]);
|
||||||
|
|
||||||
var remainder = source.Size % Vector<long>.Count;
|
var remainder = source.Length % Vector<long>.Count;
|
||||||
buffer = buffer[^remainder..];
|
buffer = buffer[^remainder..];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,9 +62,9 @@ namespace DotRecast.Core.Buffers
|
||||||
return result;
|
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;
|
var result = long.MinValue;
|
||||||
|
|
||||||
if (Vector.IsHardwareAccelerated)
|
if (Vector.IsHardwareAccelerated)
|
||||||
|
@ -78,7 +78,7 @@ namespace DotRecast.Core.Buffers
|
||||||
for (int i = 0; i < Vector<long>.Count; i++)
|
for (int i = 0; i < Vector<long>.Count; i++)
|
||||||
result = Math.Max(result, vecMax[i]);
|
result = Math.Max(result, vecMax[i]);
|
||||||
|
|
||||||
var remainder = source.Size % Vector<long>.Count;
|
var remainder = source.Length % Vector<long>.Count;
|
||||||
buffer = buffer[^remainder..];
|
buffer = buffer[^remainder..];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,5 +87,33 @@ namespace DotRecast.Core.Buffers
|
||||||
|
|
||||||
return result;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -394,4 +394,56 @@ public class RcCyclicBufferTests
|
||||||
var buffer = new RcCyclicBuffer<long>(refValues.Length, refValues);
|
var buffer = new RcCyclicBuffer<long>(refValues.Length, refValues);
|
||||||
Assert.That(RcCyclicBuffers.Max(buffer), Is.EqualTo(refValues.Max()));
|
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()));
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue