Esempio n. 1
0
            private TreeSpan MapSpanDownToChild(TreeSpan span, int childIndex)
            {
                Debug.Assert(childIndex >= 0 && childIndex < _nodeCount, $"Assertion failed: {nameof(childIndex)} >= 0 && {nameof(childIndex)} < {nameof(_nodeCount)}");

                // Offset the input span
                TreeSpan mappedFullSpan = span.Offset(-_offsets[childIndex]);

                // Return the intersection
                return(TreeSpan.Intersect(mappedFullSpan, _nodes[childIndex].Span));
            }
Esempio n. 2
0
            internal override void Sort(TreeSpan span, IComparer <T> comparer)
            {
                Debug.Assert(span.IsSubspanOf(Span), $"Assertion failed: {nameof(span)}.IsSubspanOf({nameof(Span)})");
                Debug.Assert(comparer != null, $"Assertion failed: {nameof(comparer)} != null");

                int firstPage = FindLowerBound(_offsets, _nodeCount, span.Start);
                int lastPage  = firstPage;

                for (int i = firstPage; i < _nodeCount; i++)
                {
                    TreeSpan mappedSpan = MapSpanDownToChild(span, i);
                    if (mappedSpan.IsEmpty)
                    {
                        break;
                    }

                    lastPage = i;
                    _nodes[i].Sort(mappedSpan, comparer);
                }

                if (firstPage != lastPage)
                {
                    // Need to merge the results
                    int pageCount = lastPage - firstPage + 1;
                    for (int mergeSegmentSize = 1; mergeSegmentSize < pageCount; mergeSegmentSize *= 2)
                    {
                        for (int firstSegment = firstPage; firstSegment < lastPage; firstSegment += mergeSegmentSize * 2)
                        {
                            int secondSegment = firstSegment + mergeSegmentSize;
                            if (secondSegment > lastPage)
                            {
                                break;
                            }

                            TreeSpan firstSpan  = GetSegmentSpan(span, firstSegment, mergeSegmentSize);
                            TreeSpan secondSpan = GetSegmentSpan(span, secondSegment, mergeSegmentSize);
                            MergeSegments(firstSpan, secondSpan);
                        }
                    }
                }

                // Local functions
                TreeSpan GetSegmentSpan(TreeSpan bounds, int firstPageOfSegment, int segmentPageCount)
                {
                    int lastPageOfSegment = Math.Min(_nodeCount - 1, firstPageOfSegment + segmentPageCount - 1);
                    int startIndex        = _offsets[firstPageOfSegment];
                    int endIndexExclusive = _offsets[lastPageOfSegment] + _nodes[lastPageOfSegment].Count;

                    return(TreeSpan.Intersect(bounds, TreeSpan.FromBounds(startIndex, endIndexExclusive)));
                }

                void MergeSegments(TreeSpan first, TreeSpan second)
                {
                    Debug.Assert(first.IsSubspanOf(Span), $"Assertion failed: {nameof(first)}.IsSubspanOf({nameof(Span)})");
                    Debug.Assert(second.IsSubspanOf(Span), $"Assertion failed: {nameof(second)}.IsSubspanOf({nameof(Span)})");
                    Debug.Assert(first.EndExclusive == second.Start, $"Assertion failed: first.EndExclusive == second.Start");

                    // Stop immediately if already ordered
                    if (comparer.Compare(this[first.EndInclusive], this[second.Start]) <= 0)
                    {
                        return;
                    }

                    int i = first.Start;
                    int j = second.Start;

                    while (true)
                    {
                        if (i == first.EndExclusive)
                        {
                            break;
                        }

                        Debug.Assert(j < second.EndExclusive, $"Assertion failed: j < second.EndExclusive");

                        int c = comparer.Compare(this[i], this[j]);
                        if (c == 0)
                        {
                            i++;
                        }
                        else if (c < 0)
                        {
                            i++;
                        }
                        else
                        {
                            T temp = this[i];
                            this[i] = this[j];
                            this[j] = temp;
                            i++;
                            while (i < first.EndExclusive && j < second.EndExclusive - 1 && comparer.Compare(temp, this[j + 1]) > 0)
                            {
                                j++;
                                T temp2 = this[i];
                                this[i] = this[j];
                                this[j] = temp2;
                                i++;
                            }

                            if (j > 1 && j + 1 < second.EndExclusive)
                            {
                                MergeSegments(TreeSpan.FromBounds(second.Start, j + 1), TreeSpan.FromBounds(j + 1, second.EndExclusive));
                            }

                            j = second.Start;
                        }
                    }
                }
            }