Skip to content

Commit

Permalink
Update source codes for Unity
Browse files Browse the repository at this point in the history
  • Loading branch information
mayuki committed Jun 15, 2020
1 parent 2147a83 commit 6eb53f6
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 22 deletions.
Expand Up @@ -60,7 +60,6 @@ public static int FindFirstIntKey<T>(T[] array, int key, Func<T, int> selector)
{
if (array.Length == 0) return -1;

var originalHi = hi;
lo = lo - 1;

while (hi - lo > 1)
Expand All @@ -83,14 +82,7 @@ public static int FindFirstIntKey<T>(T[] array, int key, Func<T, int> selector)
}
}

if (selectLower)
{
return (lo < 0) ? 0 : lo;
}
else
{
return (originalHi <= hi) ? originalHi - 1 : hi;
}
return selectLower ? lo : hi;
}

// default lo = 0, hi = array.Count
Expand Down Expand Up @@ -151,5 +143,78 @@ public static int FindFirstIntKey<T>(T[] array, int key, Func<T, int> selector)
? index
: -1;
}


//... want the lowest index of Key <= Value
//... returns 0 if key is <= all values in array
//... returns array.Length if key is > all values in array

public static int LowerBoundClosest<T, TKey>(T[] array, int lo, int hi, TKey key, Func<T, TKey> selector, IComparer<TKey> comparer)
{
while (lo < hi)
{
var mid = lo + ((hi - lo) >> 1);
var found = comparer.Compare(key, selector(array[mid]));

if (found <= 0) //... Key is <= value at mid
{
hi = mid;
}
else
{
lo = mid + 1; //... Notice that lo starts at zero and can only increase
}
}

var index = lo; //... index will always be zero or greater

if ( array.Length <= index)
{
return array.Length;
}

// check final
return (comparer.Compare(key, selector(array[index])) <= 0)
? index
: -1;
}


//... want the highest index of Key >= Value
//... returns -1 if key is < than all values in array
//... returns array.Length - 1 if key is >= than all values in array

public static int UpperBoundClosest<T, TKey>(T[] array, int lo, int hi, TKey key, Func<T, TKey> selector, IComparer<TKey> comparer)
{
while (lo < hi)
{
var mid = lo + ((hi - lo) >> 1);
var found = comparer.Compare(key, selector(array[mid]));

if (found >= 0) //... Key >= value at mid
{
lo = mid + 1; //... Note lo starts at zero and can only increase
}
else
{
hi = mid;
}
}

var index = (lo == 0) ? 0 : lo - 1; //... index will always be zero or greater

if ( index >= array.Length )
{
return array.Length;
}

// check final
return (comparer.Compare(key, selector(array[index])) >= 0)
? index
: -1;
}



}
}
Expand Up @@ -6,7 +6,7 @@ namespace MasterMemory
{
public readonly struct RangeView<T> : IEnumerable<T>, IReadOnlyList<T>, IList<T>
{
public static RangeView<T> Empty => default(RangeView<T>);
public static RangeView<T> Empty => new RangeView<T>( null, -1, -1, false );

readonly T[] orderedData;
readonly int left;
Expand Down Expand Up @@ -46,7 +46,7 @@ namespace MasterMemory

public RangeView(T[] orderedData, int left, int right, bool ascendant)
{
this.hasValue = (orderedData.Length != 0) && (left <= right); // same index is length = 1
this.hasValue = (orderedData != null ) && (orderedData.Length != 0) && (left <= right); // same index is length = 1 this.orderedData = orderedData;
this.orderedData = orderedData;
this.left = left;
this.right = right;
Expand Down
33 changes: 30 additions & 3 deletions src/MasterMemory.Unity/Assets/Scripts/MasterMemory/TableBase.cs
Expand Up @@ -2,6 +2,7 @@
using MasterMemory.Validation;
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace MasterMemory
{
Expand Down Expand Up @@ -133,6 +134,10 @@ static protected RangeView<TElement> FindUniqueRangeCore<TKey>(TElement[] indexA
{
var lo = BinarySearch.FindClosest(indexArray, 0, indexArray.Length, min, keySelector, comparer, false);
var hi = BinarySearch.FindClosest(indexArray, 0, indexArray.Length, max, keySelector, comparer, true);

if ( lo == -1 ) lo = 0;
if ( hi == indexArray.Length ) hi -= 1;

return new RangeView<TElement>(indexArray, lo, hi, ascendant);
}

Expand All @@ -152,15 +157,37 @@ static protected RangeView<TElement> FindManyCore<TKey>(TElement[] indexKeys, Fu
static protected RangeView<TElement> FindManyClosestCore<TKey>(TElement[] indexArray, Func<TElement, TKey> keySelector, IComparer<TKey> comparer, TKey key, bool selectLower)
{
var closest = BinarySearch.FindClosest(indexArray, 0, indexArray.Length, key, keySelector, comparer, selectLower);
if (closest == -1) return RangeView<TElement>.Empty;

if ((closest == -1) || ( closest >= indexArray.Length ))
return RangeView<TElement>.Empty;

return FindManyCore(indexArray, keySelector, comparer, keySelector(indexArray[closest]));
}

static protected RangeView<TElement> FindManyRangeCore<TKey>(TElement[] indexArray, Func<TElement, TKey> keySelector, IComparer<TKey> comparer, TKey min, TKey max, bool ascendant)
{
var lo = FindManyClosestCore(indexArray, keySelector, comparer, min, false).FirstIndex;
var hi = FindManyClosestCore(indexArray, keySelector, comparer, max, true).LastIndex;
//... Empty set when min > max
//... Alternatively, could treat this as between and swap min and max.

if ( Comparer<TKey>.Default.Compare( min, max ) > 0 )
return RangeView<TElement>.Empty;

//... want lo to be the lowest index of the values >= than min.
//... lo should be in the range [0,arraylength]

var lo = BinarySearch.LowerBoundClosest(indexArray, 0, indexArray.Length, min, keySelector, comparer );

//... want hi to be the highest index of the values <= than max
//... hi should be in the range [-1,arraylength-1]

var hi = BinarySearch.UpperBoundClosest(indexArray, 0, indexArray.Length, max, keySelector, comparer );

Debug.Assert( lo >= 0 );
Debug.Assert( hi < indexArray.Length );

if ( hi < lo )
return RangeView<TElement>.Empty;

return new RangeView<TElement>(indexArray, lo, hi, ascendant);
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/MasterMemory.Unity/Assets/Tests/BinarySearchTest.cs
Expand Up @@ -84,7 +84,8 @@ public void Closest()
new { id = 5, bound = 1000 },
};

BinarySearch.FindClosest(source, 0, source.Length, -100, x => x.bound, Comparer<int>.Default, true).Should().Be(0);
BinarySearch.FindClosest(source, 0, source.Length, -100, x => x.bound, Comparer<int>.Default, true).Should().Be(-1);
// BinarySearch.FindClosest(source, 0, source.Length, -100, x => x.bound, Comparer<int>.Default, true).Should().Be(0);
BinarySearch.FindClosest(source, 0, source.Length, 0, x => x.bound, Comparer<int>.Default, true).Should().Be(0);
BinarySearch.FindClosest(source, 0, source.Length, 10, x => x.bound, Comparer<int>.Default, true).Should().Be(0);
BinarySearch.FindClosest(source, 0, source.Length, 50, x => x.bound, Comparer<int>.Default, true).Should().Be(0);
Expand All @@ -98,7 +99,9 @@ public void Closest()
source[BinarySearch.FindClosest(source, 0, source.Length, 1000, x => x.bound, Comparer<int>.Default, true)].id.Should().Be(5);
source[BinarySearch.FindClosest(source, 0, source.Length, 1001, x => x.bound, Comparer<int>.Default, true)].id.Should().Be(5);
source[BinarySearch.FindClosest(source, 0, source.Length, 10000, x => x.bound, Comparer<int>.Default, true)].id.Should().Be(5);
source[BinarySearch.FindClosest(source, 0, source.Length, 10000, x => x.bound, Comparer<int>.Default, false)].id.Should().Be(5);
// source[BinarySearch.FindClosest(source, 0, source.Length, 10000, x => x.bound, Comparer<int>.Default, false)].id.Should().Be(5);

BinarySearch.FindClosest(source, 0, source.Length, 10000, x => x.bound, Comparer<int>.Default, false).Should().Be(6);
}
}
}
15 changes: 15 additions & 0 deletions src/MasterMemory.Unity/Assets/Tests/DatabaseTest.cs
Expand Up @@ -65,6 +65,21 @@ public void All()
db.SampleTable.SortByAge.Select(x => x.Id).OrderBy(x => x).ToArray().Should().BeEquivalentTo(new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
}

[Fact]
public void Ranges()
{
var builder = new DatabaseBuilder();
builder.Append(CreateData());

var bin = builder.Build();
var db = new MemoryDatabase(bin);

db.SampleTable.FindRangeByAge(2,2).Select(x=>x.Id).ToArray().Should().BeEquivalentTo( new int[] {} );
db.SampleTable.FindRangeByAge(30,50).Select(x=>x.Id).ToArray().Should().BeEquivalentTo( new int[] { 7, 8 } );
db.SampleTable.FindRangeByAge(100,100).Select(x=>x.Id).ToArray().Should().BeEquivalentTo( new int[] {} );
}


[Fact]
public void EmptyAll()
{
Expand Down
19 changes: 13 additions & 6 deletions src/MasterMemory.Unity/Assets/Tests/MemoryTest.cs
Expand Up @@ -96,7 +96,8 @@ public void FindClosest()
// first
for (int i = 0; i < 9; i++)
{
table.FindClosestByAge(i, selectLower: true).First.Age.Should().Be(9);
table.FindClosestByAge(i, selectLower: true).Count.Should().Be(0);
// table.FindClosestByAge(i, selectLower: true).First.Age.Should().Be(9);
}

var lastAge = 9;
Expand All @@ -111,9 +112,12 @@ public void FindClosest()
}

// last
for (int i = 99; i < 120; i++)
table.FindClosestByAge(99, selectLower: false).First.Age.Should().Be(99);

for (int i = 100; i < 120; i++)
{
table.FindClosestByAge(i, selectLower: true).First.Age.Should().Be(99);
table.FindClosestByAge(i, selectLower: false).Count.Should().Be(0);
// table.FindClosestByAge(i, selectLower: true).First.Age.Should().Be(99);
}
}
{
Expand All @@ -134,9 +138,11 @@ public void FindClosest()
}

// last
for (int i = 99; i < 120; i++)
table.FindClosestByAge(99, selectLower: false).First.Age.Should().Be(99);

for (int i = 100; i < 120; i++)
{
table.FindClosestByAge(i, selectLower: false).First.Age.Should().Be(99);
table.FindClosestByAge(i, selectLower: false).Count.Should().Be(0);
}
}
}
Expand All @@ -153,7 +159,8 @@ public void FindClosestMultiKey()
//new Sample { Id = 4, Age = 89, FirstName = "aaa", LastName = "tako" },
//new Sample { Id = 9, Age = 99, FirstName = "aaa", LastName = "ika" },

table.FindClosestByFirstNameAndAge(("aaa", 10), true).First.Age.Should().Be(19);
table.FindClosestByFirstNameAndAge(("aaa", 10), true).Count.Should().Be(0);
table.FindClosestByFirstNameAndAge(("aaa", 10), false).First.Age.Should().Be(19);
table.FindClosestByFirstNameAndAge(("aaa", 92), true).First.Age.Should().Be(89);
table.FindClosestByFirstNameAndAge(("aaa", 120), true).First.Age.Should().Be(99);
table.FindClosestByFirstNameAndAge(("aaa", 10), false).First.Age.Should().Be(19);
Expand Down

0 comments on commit 6eb53f6

Please sign in to comment.