/// <summary>Finds the location of an element in the array</summary>
        /// <param name="value">Value of the element to search for.</param>
        /// <param name="offset">Receives the offset of the element inside the level if found; otherwise, 0.</param>
        /// <returns>Level that contains the element if found; otherwise, -1.</returns>
        public int Find(T value, out int offset, out T actualValue)
        {
            if ((m_count & 1) != 0)
            {
                // If someone gets the last inserted key, there is a 50% change that it is in the root
                // (if not, it will the the last one of the first non-empty level)
                if (m_comparer.Compare(value, m_root[0]) == 0)
                {
                    offset      = 0;
                    actualValue = m_root[0];
                    return(0);
                }
            }

            var levels = m_levels;

            for (int i = 1; i < levels.Length; i++)
            {
                if (IsFree(i))
                {                 // this segment is not allocated
                    continue;
                }

                int p = ColaStore.BinarySearch <T>(levels[i], 0, 1 << i, value, m_comparer);
                if (p >= 0)
                {
                    offset      = p;
                    actualValue = levels[i][p];
                    return(i);
                }
            }
            offset      = 0;
            actualValue = default(T);
            return(NOT_FOUND);
        }
Exemple #2
0
        /// <summary>Search for the smallest element that is larger than a reference element</summary>
        /// <param name="value">Reference element</param>
        /// <param name="orEqual">If true, return the position of the value itself if it is found. If false, return the position of the closest value that is smaller.</param>
        /// <param name="offset">Receive the offset within the level of the next element, or 0 if not found</param>
        /// <param name="result">Receive the value of the next element, or default(T) if not found</param>
        /// <returns>Level of the next element, or -1 if <param name="result"/> was already the largest</returns>
        public static int FindNext <T>(T[][] levels, int count, T value, bool orEqual, IComparer <T> comparer, out int offset, out T result)
        {
            int level     = NOT_FOUND;
            T   min       = default(T);
            int minOffset = 0;

            // scan each segment for a value that would be larger, keep track of the smallest found
            for (int i = 0; i < levels.Length; i++)
            {
                if (ColaStore.IsFree(i, count))
                {
                    continue;
                }

                var segment = levels[i];
                int pos     = ColaStore.BinarySearch <T>(segment, 0, segment.Length, value, comparer);
                if (pos >= 0)
                {                 // we found an exact match in this segment
                    if (orEqual)
                    {
                        offset = pos;
                        result = segment[pos];
                        return(i);
                    }

                    // the next item in this segment should be larger
                    ++pos;
                }
                else
                {                 // we found where it would be stored in this segment
                    pos = ~pos;
                }

                if (pos < segment.Length)
                {
                    if (level == NOT_FOUND || comparer.Compare(segment[pos], min) < 0)
                    {                     // we found a better candidate
                        min       = segment[pos];
                        level     = i;
                        minOffset = pos;
                    }
                }
            }

            offset = minOffset;
            result = min;
            return(level);
        }
Exemple #3
0
        /// <summary>Search for the largest element that is smaller than a reference element</summary>
        /// <param name="value">Reference element</param>
        /// <param name="orEqual">If true, return the position of the value itself if it is found. If false, return the position of the closest value that is smaller.</param>
        /// <param name="offset">Receive the offset within the level of the previous element, or 0 if not found</param>
        /// <param name="result">Receive the value of the previous element, or default(T) if not found</param>
        /// <returns>Level of the previous element, or -1 if <param name="result"/> was already the smallest</returns>
        public static int FindPrevious <T>(T[][] levels, int count, T value, bool orEqual, IComparer <T> comparer, out int offset, out T result)
        {
            int level     = NOT_FOUND;
            T   max       = default(T);
            int maxOffset = 0;

            // scan each segment for a value that would be smaller, keep track of the smallest found
            for (int i = 0; i < levels.Length; i++)
            {
                if (ColaStore.IsFree(i, count))
                {
                    continue;
                }

                var segment = levels[i];
                int pos     = ColaStore.BinarySearch <T>(segment, 0, segment.Length, value, comparer);
                // the previous item in this segment should be smaller
                if (pos < 0)
                {                 // it is not
                    pos = ~pos;
                }
                else if (orEqual)
                {                 // we found an exact match in this segment
                    offset = pos;
                    result = segment[pos];
                    return(i);
                }

                --pos;

                if (pos >= 0)
                {
                    if (level == NOT_FOUND || comparer.Compare(segment[pos], max) > 0)
                    {                     // we found a better candidate
                        max       = segment[pos];
                        level     = i;
                        maxOffset = pos;
                    }
                }
            }

            offset = maxOffset;
            result = max;
            return(level);
        }
Exemple #4
0
        public static IEnumerable <T> FindBetween <T>(T[][] levels, int count, T begin, bool beginOrEqual, T end, bool endOrEqual, int limit, IComparer <T> comparer)
        {
            if (limit > 0)
            {
                for (int i = 0; i < levels.Length; i++)
                {
                    if (ColaStore.IsFree(i, count))
                    {
                        continue;
                    }

                    var segment = levels[i];

                    int to = ColaStore.BinarySearch <T>(segment, 0, segment.Length, end, comparer);
                    if (to >= 0)
                    {
                        if (!endOrEqual)
                        {
                            to--;
                        }
                    }
                    else
                    {
                        to = ~to;
                    }
                    if (to < 0 || to >= segment.Length)
                    {
                        continue;
                    }

                    int from = ColaStore.BinarySearch <T>(segment, 0, segment.Length, begin, comparer);
                    if (from >= 0)
                    {
                        if (!beginOrEqual)
                        {
                            ++from;
                        }
                    }
                    else
                    {
                        from = ~from;
                    }
                    if (from >= segment.Length)
                    {
                        continue;
                    }

                    if (from > to)
                    {
                        continue;
                    }

                    for (int j = from; j <= to && limit > 0; j++)
                    {
                        yield return(segment[j]);

                        --limit;
                    }
                    if (limit <= 0)
                    {
                        break;
                    }
                }
            }
        }