Skip to content

Commit bb3ddb0

Browse files
author
LoneWandererProductions
committed
Final push
1 parent 8702ad8 commit bb3ddb0

4 files changed

Lines changed: 99 additions & 7 deletions

File tree

CommonExtendedObjectsTests/SortedKvStoreTests.cs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@
66
* PROGRAMMER: Peter Geinitz (Wayfarer)
77
*/
88

9-
using System;
109
using System.Buffers;
11-
using System.Collections.Generic;
1210
using System.Diagnostics;
1311
using System.Linq;
14-
using System.Windows.Documents;
1512
using ExtendedSystemObjects;
1613
using Microsoft.VisualStudio.TestTools.UnitTesting;
1714

@@ -209,7 +206,7 @@ public void PerformanceRemoveCompact()
209206
/// Inserts the key1 into empty store should keep arrays in synchronize.
210207
/// </summary>
211208
[TestMethod]
212-
public void InsertKey1IntoEmptyStoreShouldKeepArraysInSync()
209+
public void InsertKeyIntoEmptyStoreShouldKeepArraysInSync()
213210
{
214211
// Arrange
215212
var store = new SortedKvStore();
@@ -494,7 +491,32 @@ public void BinarySearch()
494491
Trace.WriteLine(store.ToString());
495492
var position = store.BinarySearch(9);
496493

497-
Assert.AreEqual(9, position, "Wrong position.");
494+
Assert.AreEqual(-10, position, "Wrong position.");
495+
}
496+
497+
/// <summary>
498+
/// Binaries the search fails due to unsorted placeholder values.
499+
/// </summary>
500+
[TestMethod]
501+
public void BinarySearchFailsDueToUnsortedPlaceholderValues()
502+
{
503+
var store = new SortedKvStore(128);
504+
505+
// Add 10 sorted keys: 1 through 10
506+
for (int i = 1; i <= 10; i++)
507+
{
508+
store.Add(i, i);
509+
}
510+
511+
Trace.WriteLine(store.ToString());
512+
513+
// We now search for 10, which is present
514+
var result = store.BinarySearch(10);
515+
516+
Trace.WriteLine($"BinarySearch(10) returned: {result}");
517+
518+
// Expected index is 9 (0-based index of key = 10)
519+
Assert.AreEqual(9, result, "BinarySearch returned incorrect index due to unsorted placeholder values beyond the valid count.");
498520
}
499521
}
500522
}

CommonExtendedObjectsTests/Utilities.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,5 +361,27 @@ public void CompareCustomVsArrayBinarySearchPerformance()
361361
Assert.IsTrue(swCustom.ElapsedMilliseconds < swArray.ElapsedMilliseconds * 3,
362362
$"Custom BinarySearch is too slow: {swCustom.ElapsedMilliseconds} ms vs {swArray.ElapsedMilliseconds} ms");
363363
}
364+
365+
/// <summary>
366+
/// Binaries the search bug.
367+
/// </summary>
368+
[TestMethod]
369+
public void BinarySearchBug()
370+
{
371+
var sortedKeys = new int[128];
372+
373+
for (var i = 0; i < 10; i++)
374+
{
375+
sortedKeys[i] = i+1;
376+
}
377+
for (var i = 10; i < 128; i++)
378+
{
379+
sortedKeys[i] = 0; ;
380+
}
381+
382+
var idx = Utility.BinarySearch(sortedKeys, 14, 10);
383+
384+
Assert.AreEqual(-15, idx ,"Found the bug.");
385+
}
364386
}
365387
}

ExtendedSystemObjects/SortedKvStore.cs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,56 @@ public void Compact()
394394
/// </returns>
395395
public int BinarySearch(int key)
396396
{
397-
return Utility.BinarySearch(_keys.AsSpan(), Count, key);
397+
int left = 0, right = Count - 1;
398+
var keysSpan = _keys.AsSpan()[..Count];
399+
var occupiedSpan = _occupied.AsSpan()[..Count];
400+
401+
while (left <= right)
402+
{
403+
int mid = left + ((right - left) >> 1);
404+
int midKey = keysSpan[mid];
405+
406+
if (midKey == key)
407+
{
408+
if (occupiedSpan[mid] != 0)
409+
return mid; // found active key
410+
411+
// Found deleted slot, try to probe neighbors near mid for active key with same key
412+
// Usually deletions are rare, so probing few neighbors is cheap
413+
414+
// probe left neighbors
415+
for (int i = mid - 1; i >= left && keysSpan[i] == key; i--)
416+
{
417+
if (occupiedSpan[i] != 0)
418+
return i;
419+
}
420+
// probe right neighbors
421+
for (int i = mid + 1; i <= right && keysSpan[i] == key; i++)
422+
{
423+
if (occupiedSpan[i] != 0)
424+
return i;
425+
}
426+
427+
// no active key found
428+
return ~left;
429+
}
430+
431+
if (midKey < key)
432+
{
433+
left = mid + 1;
434+
}
435+
else
436+
{
437+
right = mid - 1;
438+
}
439+
}
440+
441+
// Key not found; try to move left forward to next occupied slot for insertion index
442+
int insertionIndex = left;
443+
while (insertionIndex < Count && occupiedSpan[insertionIndex] == 0)
444+
insertionIndex++;
445+
446+
return ~insertionIndex;
398447
}
399448

400449
/// <summary>

InterpreteTests/CommandBuilder.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
using System.Collections.Generic;
1010
using System.Diagnostics;
1111
using ExtendedSystemObjects;
12-
using Interpreter;
1312
using Interpreter.ScriptEngine;
1413
using Microsoft.VisualStudio.TestTools.UnitTesting;
1514

0 commit comments

Comments
 (0)