Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix calculation for slot containing offset #736

Merged
merged 2 commits into from Feb 23, 2015
Merged

Conversation

mattwar
Copy link
Contributor

@mattwar mattwar commented Feb 20, 2015

Fixes issue #605

Add logic to not return zero-length nodes, since they never contain their offset.

Fixes issue dotnet#605

Add logic to not return zero-length nodes, since they never contain
their offset.
@mattwar
Copy link
Contributor Author

mattwar commented Feb 20, 2015

@pharring might want to comment.

@pharring
Copy link
Contributor

We need the same fix for VB.

@@ -53,7 +53,19 @@ public override int FindSlotIndexContainingOffset(int offset)
{
Debug.Assert(offset >= 0 && offset < FullWidth);
int idx = _childOffsets.BinarySearch(offset);
return idx >= 0 ? idx : (~idx - 1);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I wondered about this case when I wrote it. I originally had a hand-coded binary search that avoided this problem, but I was 'encouraged' to change it to Array.BinarySearch in review.

What we really need is an "upper_bound" equivalent (Array.BinarySearch gives the lower bound).

Note that this BinarySearch is already an extension method over int[]. We could introduce a "UpperBoundBinarySearch" method. That would be nice to avoid code duplication (both C# and VB need the same fix).

@pharring
Copy link
Contributor

Here is an "upper_bound" binary search algorithm. The difference from Array.BinarySearch and the existing BinarySearch extension method is subtle, but significant: We don't check for equality in the middle. We keep halving the search space until there's only a single value. Note that, since it's an upper bound, it can return a value equal to array.Length (i.e. off the end of the array).

/// <summary>
/// Search a sorted integer array for the target value in O(log N) time.
/// </summary>
/// <param name="array">The array of integers which must be sorted in ascending order.</param>
/// <param name="value">The target value.</param>
/// <returns>An index in the array pointing to the position where <paramref name="value"/> should be
/// inserted in order to maintain the sorted order. All values to the right of this position will be
/// strictly greater than <paramref name="value"/>. Note that this may return a position off the end
/// of the array if all elements are less than or equal to <paramref name="value"/>.</returns>
static int BinarySearchUpperBound(this int[] array, int value)
{
    int low = 0;
    int high = array.Length - 1;

    while (low <= high)
    {
        int middle = low + ((high - low) >> 1);
        if (array[middle] > value)
        {
            high = middle - 1;
        }
        else
        {
            low = middle + 1;
        }
    }

    return low;
}

With this, I believe FindSlotIndexContainingOffset can be implemented like this:

return _childOffsets.BinarySearchUpperBound(offset) - 1;

@pharring
Copy link
Contributor

@mattwar Let me know if you want me to take care of this for you. (I feel bad since I introduced the bug in the first place)

@mattwar
Copy link
Contributor Author

mattwar commented Feb 23, 2015

@pharring please review the newest changes

@pharring
Copy link
Contributor

👍 please merge at your earliest convenience.

mattwar added a commit that referenced this pull request Feb 23, 2015
Fix calculation for slot containing offset
@mattwar mattwar merged commit 63e58ee into dotnet:master Feb 23, 2015
@mattwar mattwar deleted the Bug605 branch August 29, 2016 19:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants