Ejemplo n.º 1
0
        /**
         * Excel has funny behaviour when the some elements in the search vector are the wrong type.
         *
         */
        private static int PerformBinarySearch(ValueVector vector, LookupValueComparer lookupComparer)
        {
            // both low and high indexes point to values assumed too low and too high.
            BinarySearchIndexes bsi = new BinarySearchIndexes(vector.Size);

            while (true)
            {
                int midIx = bsi.GetMidIx();

                if (midIx < 0)
                {
                    return(bsi.GetLowIx());
                }
                CompareResult cr = lookupComparer.CompareTo(vector.GetItem(midIx));
                if (cr.IsTypeMismatch)
                {
                    int newMidIx = HandleMidValueTypeMismatch(lookupComparer, vector, bsi, midIx);
                    if (newMidIx < 0)
                    {
                        continue;
                    }
                    midIx = newMidIx;
                    cr    = lookupComparer.CompareTo(vector.GetItem(midIx));
                }
                if (cr.IsEqual)
                {
                    return(FindLastIndexInRunOfEqualValues(lookupComparer, vector, midIx, bsi.GetHighIx()));
                }
                bsi.narrowSearch(midIx, cr.IsLessThan);
            }
        }
Ejemplo n.º 2
0
        /**
         * Excel seems to handle mismatched types initially by just stepping 'mid' ix forward to the
         * first compatible value.
         * @param midIx 'mid' index (value which has the wrong type)
         * @return usually -1, signifying that the BinarySearchIndex has been narrowed to the new mid
         * index.  Zero or greater signifies that an exact match for the lookup value was found
         */
        private static int HandleMidValueTypeMismatch(LookupValueComparer lookupComparer, ValueVector vector,
                                                      BinarySearchIndexes bsi, int midIx)
        {
            int newMid = midIx;
            int highIx = bsi.GetHighIx();

            while (true)
            {
                newMid++;
                if (newMid == highIx)
                {
                    // every element from midIx to highIx was the wrong type
                    // move highIx down to the low end of the mid values
                    bsi.narrowSearch(midIx, true);
                    return(-1);
                }
                CompareResult cr = lookupComparer.CompareTo(vector.GetItem(newMid));
                if (cr.IsLessThan && newMid == highIx - 1)
                {
                    // move highIx down to the low end of the mid values
                    bsi.narrowSearch(midIx, true);
                    return(-1);
                    // but only when "newMid == highIx-1"? slightly weird.
                    // It would seem more efficient to always do this.
                }
                if (cr.IsTypeMismatch)
                {
                    // keep stepping over values Until the right type Is found
                    continue;
                }
                if (cr.IsEqual)
                {
                    return(newMid);
                }
                // Note - if moving highIx down (due to lookup<vector[newMid]),
                // this execution path only moves highIx it down as far as newMid, not midIx,
                // which would be more efficient.
                bsi.narrowSearch(newMid, cr.IsLessThan);
                return(-1);
            }
        }