RecyclableLongList.Compatibility.List.FindLastIndex() implemented. Tests extended.
This commit is contained in:
1 parent
033a442598
commit
b3c8e49600
2 files changed
+160
-86
No files matched your search
+27
-27
@@ -444,6 +444,32 @@ namespace Recyclable.CollectionsTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexWithRangeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||||
|
public void FindIndexShouldNotAnythingWhenRangeExcludesItem(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in (long ItemIndex, long RangedItemsCount)[] itemRanges)
|
||||||
|
{
|
||||||
|
// Prepare
|
||||||
|
using var list = new RecyclableLongList<long>(testData, initialCapacity: itemsCount);
|
||||||
|
var expectedData = testData.ToList();
|
||||||
|
|
||||||
|
foreach (var (itemIndex, rangedItemsCount) in itemRanges)
|
||||||
|
{
|
||||||
|
TestWith(itemsCount, list, expectedData, itemIndex, rangedItemsCount, expectedData[Math.Max((int)(itemIndex - 1), 0)]);
|
||||||
|
TestWith(itemsCount, list, expectedData, itemIndex, rangedItemsCount, expectedData[Math.Min((int)(itemIndex + rangedItemsCount), itemsCount - 1)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TestWith(int itemsCount, RecyclableLongList<long> list, List<long> expectedData, long itemIndex, long rangedItemsCount, long expectedItem)
|
||||||
|
{
|
||||||
|
var expected = expectedData.FindIndex((int)itemIndex, (int)rangedItemsCount, item => item == expectedItem);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var actual = list.FindIndex((int)itemIndex, (int)rangedItemsCount, item => item == expectedItem);
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
_ = actual.Should().Be(expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||||
public void FindIndexShouldReturnCorrectIndexes(string testCase, IEnumerable<long> testData, int itemsCount, in long[] itemIndexes)
|
public void FindIndexShouldReturnCorrectIndexes(string testCase, IEnumerable<long> testData, int itemsCount, in long[] itemIndexes)
|
||||||
@@ -493,32 +519,6 @@ namespace Recyclable.CollectionsTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexWithRangeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
|
||||||
public void FindIndexShouldNotAnythingWhenRangeExcludesItem(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in (long ItemIndex, long RangedItemsCount)[] itemRanges)
|
|
||||||
{
|
|
||||||
// Prepare
|
|
||||||
using var list = new RecyclableLongList<long>(testData, initialCapacity: itemsCount);
|
|
||||||
var expectedData = testData.ToList();
|
|
||||||
|
|
||||||
foreach (var (itemIndex, rangedItemsCount) in itemRanges)
|
|
||||||
{
|
|
||||||
TestWith(itemsCount, list, expectedData, itemIndex, rangedItemsCount, expectedData[Math.Max((int)(itemIndex - 1), 0)]);
|
|
||||||
TestWith(itemsCount, list, expectedData, itemIndex, rangedItemsCount, expectedData[Math.Min((int)(itemIndex + rangedItemsCount), itemsCount - 1)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestWith(int itemsCount, RecyclableLongList<long> list, List<long> expectedData, long itemIndex, long rangedItemsCount, long expectedItem)
|
|
||||||
{
|
|
||||||
var expected = expectedData.FindIndex((int)itemIndex, (int)rangedItemsCount, item => item == expectedItem);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var actual = list.FindIndex((int)itemIndex, (int)rangedItemsCount, item => item == expectedItem);
|
|
||||||
|
|
||||||
// Validate
|
|
||||||
_ = actual.Should().Be(expected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||||
public void FindIndexShouldReturnCorrectIndexesWhenConstrainedIndex(string testCase, IEnumerable<long> testData, int itemsCount, in long[] itemIndexes)
|
public void FindIndexShouldReturnCorrectIndexesWhenConstrainedIndex(string testCase, IEnumerable<long> testData, int itemsCount, in long[] itemIndexes)
|
||||||
@@ -579,7 +579,7 @@ namespace Recyclable.CollectionsTests
|
|||||||
static void TestWith(int itemsCount, RecyclableLongList<long> list, List<long> expectedData, long itemIndex, long expectedItem)
|
static void TestWith(int itemsCount, RecyclableLongList<long> list, List<long> expectedData, long itemIndex, long expectedItem)
|
||||||
{
|
{
|
||||||
var expected = expectedData.FindLastIndex(itemsCount - 1, itemsCount, x => x == expectedItem);
|
var expected = expectedData.FindLastIndex(itemsCount - 1, itemsCount, x => x == expectedItem);
|
||||||
_ = list.FindLastIndex(itemsCount - 1, itemsCount, x => x == expectedItem).Should().Be((int)itemIndex).And.Be(expected);
|
_ = list.FindLastIndex(itemsCount - 1, itemsCount, x => x == expectedItem).Should().Be(expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+133
-59
@@ -495,84 +495,158 @@ namespace Recyclable.Collections
|
|||||||
|
|
||||||
public static int FindLastIndex<T>(this RecyclableLongList<T> list, int startIndex, int count, Predicate<T> match)
|
public static int FindLastIndex<T>(this RecyclableLongList<T> list, int startIndex, int count, Predicate<T> match)
|
||||||
{
|
{
|
||||||
//if (count == 0)
|
if (count == 0)
|
||||||
//{
|
{
|
||||||
// if (startIndex != -1)
|
if (startIndex != -1)
|
||||||
// {
|
{
|
||||||
// ThrowHelper.ThrowArgumentOutOfRangeException_Index();
|
ThrowHelper.ThrowArgumentOutOfRangeException_Index();
|
||||||
// }
|
}
|
||||||
//}
|
|
||||||
//else if (count < 0 || startIndex - count + 1 < 0)
|
|
||||||
//{
|
|
||||||
// ThrowHelper.ThrowArgumentOutOfRangeException_Count();
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if (startIndex < 0)
|
return RecyclableDefaults.ItemNotFoundIndex;
|
||||||
//{
|
}
|
||||||
// return RecyclableDefaults.ItemNotFoundIndex;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//int sourceItemsCount = count; // startIndex - count + 1 >= 0 ? count : startIndex + 1;
|
if (count < 0 || startIndex - count + 1 < 0)
|
||||||
//if (sourceItemsCount == 0)
|
{
|
||||||
//{
|
ThrowHelper.ThrowArgumentOutOfRangeException_Count();
|
||||||
// return RecyclableDefaults.ItemNotFoundIndex;
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
//int lastItemIndex = startIndex - sourceItemsCount;
|
if (startIndex < 0)
|
||||||
//ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
{
|
||||||
//for (var itemIndex = startIndex; itemIndex > lastItemIndex; itemIndex--)
|
return RecyclableDefaults.ItemNotFoundIndex;
|
||||||
//{
|
}
|
||||||
// if (match(sourceSpan[itemIndex]))
|
|
||||||
// {
|
|
||||||
// return itemIndex;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//return RecyclableDefaults.ItemNotFoundIndex;
|
int blockSizeMinus1 = list._blockSizeMinus1,
|
||||||
|
firstBlockIndex = startIndex >> list._blockSizePow2BitShift,
|
||||||
|
firstItemIndex = startIndex & blockSizeMinus1,
|
||||||
|
blockIndex = (startIndex + count) >> list._blockSizePow2BitShift,
|
||||||
|
itemIndex;
|
||||||
|
|
||||||
throw new NotImplementedException();
|
ReadOnlySpan<T[]> memoryBlocksSpan = new(list._memoryBlocks);
|
||||||
|
ReadOnlySpan<T> sourceSpan = memoryBlocksSpan[blockIndex];
|
||||||
|
for (itemIndex = ((startIndex + count) & blockSizeMinus1) - 1; itemIndex >= 0; itemIndex--)
|
||||||
|
{
|
||||||
|
if (match(sourceSpan[itemIndex]))
|
||||||
|
{
|
||||||
|
return itemIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while(blockIndex > firstBlockIndex)
|
||||||
|
{
|
||||||
|
sourceSpan = memoryBlocksSpan[blockIndex];
|
||||||
|
for (itemIndex = blockSizeMinus1; itemIndex >= 0; itemIndex--)
|
||||||
|
{
|
||||||
|
if (match(sourceSpan[itemIndex]))
|
||||||
|
{
|
||||||
|
return itemIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockIndex--;
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSpan = memoryBlocksSpan[blockIndex];
|
||||||
|
for (itemIndex = blockSizeMinus1; itemIndex >= firstItemIndex; itemIndex--)
|
||||||
|
{
|
||||||
|
if (match(sourceSpan[itemIndex]))
|
||||||
|
{
|
||||||
|
return itemIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RecyclableDefaults.ItemNotFoundIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int FindLastIndex<T>(this RecyclableLongList<T> list, int startIndex, Predicate<T> match)
|
public static int FindLastIndex<T>(this RecyclableLongList<T> list, int startIndex, Predicate<T> match)
|
||||||
{
|
{
|
||||||
//if (list._count == 0 || startIndex < 0)
|
if (list._longCount == 0)
|
||||||
//{
|
{
|
||||||
// return RecyclableDefaults.ItemNotFoundIndex;
|
if (startIndex != -1)
|
||||||
//}
|
{
|
||||||
|
ThrowHelper.ThrowArgumentOutOfRangeException_Index();
|
||||||
|
}
|
||||||
|
|
||||||
//ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
return RecyclableDefaults.ItemNotFoundIndex;
|
||||||
//for (var itemIndex = startIndex; itemIndex >= 0; itemIndex--)
|
}
|
||||||
//{
|
|
||||||
// if (match(sourceSpan[itemIndex]))
|
|
||||||
// {
|
|
||||||
// return itemIndex;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//return RecyclableDefaults.ItemNotFoundIndex;
|
if (startIndex < 0)
|
||||||
|
{
|
||||||
|
return RecyclableDefaults.ItemNotFoundIndex;
|
||||||
|
}
|
||||||
|
|
||||||
throw new NotImplementedException();
|
int blockSizeMinus1 = list._blockSizeMinus1,
|
||||||
|
firstBlockIndex = startIndex >> list._blockSizePow2BitShift,
|
||||||
|
firstItemIndex = startIndex & blockSizeMinus1,
|
||||||
|
blockIndex = (int)(list._longCount >> list._blockSizePow2BitShift),
|
||||||
|
itemIndex;
|
||||||
|
|
||||||
|
ReadOnlySpan<T[]> memoryBlocksSpan = new(list._memoryBlocks);
|
||||||
|
ReadOnlySpan<T> sourceSpan = memoryBlocksSpan[blockIndex];
|
||||||
|
for (itemIndex = list._nextItemIndex > 0 ? list._nextItemIndex - 1 : blockSizeMinus1; itemIndex >= 0; itemIndex--)
|
||||||
|
{
|
||||||
|
if (match(sourceSpan[itemIndex]))
|
||||||
|
{
|
||||||
|
return itemIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; blockIndex > firstBlockIndex; blockIndex--)
|
||||||
|
{
|
||||||
|
sourceSpan = memoryBlocksSpan[blockIndex];
|
||||||
|
for (itemIndex = blockSizeMinus1; itemIndex >= 0; itemIndex--)
|
||||||
|
{
|
||||||
|
if (match(sourceSpan[itemIndex]))
|
||||||
|
{
|
||||||
|
return itemIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSpan = memoryBlocksSpan[blockIndex];
|
||||||
|
for (itemIndex = blockSizeMinus1; itemIndex >= firstItemIndex; itemIndex--)
|
||||||
|
{
|
||||||
|
if (match(sourceSpan[itemIndex]))
|
||||||
|
{
|
||||||
|
return itemIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RecyclableDefaults.ItemNotFoundIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int FindLastIndex<T>(this RecyclableLongList<T> list, Predicate<T> match)
|
public static int FindLastIndex<T>(this RecyclableLongList<T> list, Predicate<T> match)
|
||||||
{
|
{
|
||||||
//if (list._count == 0)
|
if (list._longCount == 0)
|
||||||
//{
|
{
|
||||||
// return RecyclableDefaults.ItemNotFoundIndex;
|
return RecyclableDefaults.ItemNotFoundIndex;
|
||||||
//}
|
}
|
||||||
|
|
||||||
//ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
int blockSizeMinus1 = list._blockSizeMinus1;
|
||||||
//for (var itemIndex = list._count - 1; itemIndex >= 0; itemIndex--)
|
ReadOnlySpan<T[]> memoryBlocksSpan = new(list._memoryBlocks);
|
||||||
//{
|
|
||||||
// if (match(sourceSpan[itemIndex]))
|
|
||||||
// {
|
|
||||||
// return itemIndex;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//return RecyclableDefaults.ItemNotFoundIndex;
|
ReadOnlySpan<T> sourceSpan = memoryBlocksSpan[list._lastBlockWithData];
|
||||||
|
int itemIndex;
|
||||||
|
for (itemIndex = list._nextItemIndex == 0 ? blockSizeMinus1 : list._nextItemIndex - 1; itemIndex >= 0; itemIndex--)
|
||||||
|
{
|
||||||
|
if (match(sourceSpan[itemIndex]))
|
||||||
|
{
|
||||||
|
return itemIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throw new NotImplementedException();
|
for (var blockIndex = list._lastBlockWithData - 1; blockIndex >= 0; blockIndex--)
|
||||||
|
{
|
||||||
|
sourceSpan = memoryBlocksSpan[blockIndex];
|
||||||
|
for (itemIndex = blockSizeMinus1; itemIndex >= 0; itemIndex--)
|
||||||
|
{
|
||||||
|
if (match(sourceSpan[itemIndex]))
|
||||||
|
{
|
||||||
|
return itemIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RecyclableDefaults.ItemNotFoundIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user