示例#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);
            }
        }
示例#2
0
        /**
         * @return zero based index
         */
        private static int FindIndexOfValue(ValueEval lookupValue, ValueVector lookupRange,
                                            bool matchExact, bool FindLargestLessThanOrEqual)
        {
            LookupValueComparer lookupComparer = CreateLookupComparer(lookupValue, matchExact);

            int size = lookupRange.Size;

            if (matchExact)
            {
                for (int i = 0; i < size; i++)
                {
                    if (lookupComparer.CompareTo(lookupRange.GetItem(i)).IsEqual)
                    {
                        return(i);
                    }
                }
                throw new EvaluationException(ErrorEval.NA);
            }

            if (FindLargestLessThanOrEqual)
            {
                // Note - backward iteration
                for (int i = size - 1; i >= 0; i--)
                {
                    CompareResult cmp = lookupComparer.CompareTo(lookupRange.GetItem(i));
                    if (cmp.IsTypeMismatch)
                    {
                        continue;
                    }
                    if (!cmp.IsLessThan)
                    {
                        return(i);
                    }
                }
                throw new EvaluationException(ErrorEval.NA);
            }

            // else - Find smallest greater than or equal to
            // TODO - Is binary search used for (match_type==+1) ?
            for (int i = 0; i < size; i++)
            {
                CompareResult cmp = lookupComparer.CompareTo(lookupRange.GetItem(i));
                if (cmp.IsEqual)
                {
                    return(i);
                }
                if (cmp.IsGreaterThan)
                {
                    if (i < 1)
                    {
                        throw new EvaluationException(ErrorEval.NA);
                    }
                    return(i - 1);
                }
            }

            return(size - 1);
        }
示例#3
0
        public ValueEval Evaluate(ValueEval[] args, int srcCellRow, int srcCellCol)
        {
            ValueEval arg3 = null;

            switch (args.Length)
            {
            case 4:
                arg3 = args[3];     // important: assumed array element Is never null
                break;

            case 3:
                break;

            default:
                // wrong number of arguments
                return(ErrorEval.VALUE_INVALID);
            }
            try
            {
                // Evaluation order:
                // arg0 lookup_value, arg1 table_array, arg3 range_lookup, Find lookup value, arg2 row_index, fetch result
                ValueEval   lookupValue   = OperandResolver.GetSingleValue(args[0], srcCellRow, srcCellCol);
                AreaEval    tableArray    = LookupUtils.ResolveTableArrayArg(args[1]);
                bool        IsRangeLookup = LookupUtils.ResolveRangeLookupArg(arg3, srcCellRow, srcCellCol);
                int         colIndex      = LookupUtils.LookupIndexOfValue(lookupValue, LookupUtils.CreateRowVector(tableArray, 0), IsRangeLookup);
                int         rowIndex      = LookupUtils.ResolveRowOrColIndexArg(args[2], srcCellRow, srcCellCol);
                ValueVector resultCol     = CreateResultColumnVector(tableArray, rowIndex);
                return(resultCol.GetItem(colIndex));
            }
            catch (EvaluationException e)
            {
                return(e.GetErrorEval());
            }
        }
示例#4
0
        /**
         * Finds first (lowest index) exact occurrence of specified value.
         * @param lookupComparer the value to be found in column or row vector
         * @param vector the values to be searched. For VLOOKUP this Is the first column of the
         *  tableArray. For HLOOKUP this Is the first row of the tableArray.
         * @return zero based index into the vector, -1 if value cannot be found
         */
        private static int lookupFirstIndexOfValue(LookupValueComparer lookupComparer, ValueVector vector, MatchMode matchMode)
        {
            // Find first occurrence of lookup value
            int       size          = vector.Size;
            int       bestMatchIdx  = -1;
            ValueEval bestMatchEval = null;

            for (int i = 0; i < size; i++)
            {
                ValueEval     valueEval = vector.GetItem(i);
                CompareResult result    = lookupComparer.CompareTo(valueEval);
                if (result.IsEqual)
                {
                    return(i);
                }
                switch (matchMode)
                {
                case MatchMode.ExactMatchFallbackToLargerValue:
                    if (result.IsLessThan)
                    {
                        if (bestMatchEval == null)
                        {
                            bestMatchIdx  = i;
                            bestMatchEval = valueEval;
                        }
                        else
                        {
                            LookupValueComparer matchComparer = CreateTolerantLookupComparer(valueEval, true, true);
                            if (matchComparer.CompareTo(bestMatchEval).IsLessThan)
                            {
                                bestMatchIdx  = i;
                                bestMatchEval = valueEval;
                            }
                        }
                    }
                    break;

                case MatchMode.ExactMatchFallbackToSmallerValue:
                    if (result.IsGreaterThan)
                    {
                        if (bestMatchEval == null)
                        {
                            bestMatchIdx  = i;
                            bestMatchEval = valueEval;
                        }
                        else
                        {
                            LookupValueComparer matchComparer = CreateTolerantLookupComparer(valueEval, true, true);
                            if (matchComparer.CompareTo(bestMatchEval).IsGreaterThan)
                            {
                                bestMatchIdx  = i;
                                bestMatchEval = valueEval;
                            }
                        }
                    }
                    break;
                }
            }
            return(bestMatchIdx);
        }
示例#5
0
        private double EvaluateInternal(ValueVector x, ValueVector y, int size)
        {
            Accumulator acc = CreateAccumulator();

            // error handling is as if the x is fully evaluated before y
            ErrorEval firstXerr      = null;
            ErrorEval firstYerr      = null;
            bool      accumlatedSome = false;
            double    result         = 0.0;

            for (int i = 0; i < size; i++)
            {
                ValueEval vx = x.GetItem(i);
                ValueEval vy = y.GetItem(i);
                if (vx is ErrorEval)
                {
                    if (firstXerr == null)
                    {
                        firstXerr = (ErrorEval)vx;
                        continue;
                    }
                }
                if (vy is ErrorEval)
                {
                    if (firstYerr == null)
                    {
                        firstYerr = (ErrorEval)vy;
                        continue;
                    }
                }
                // only count pairs if both elements are numbers
                if (vx is NumberEval && vy is NumberEval)
                {
                    accumlatedSome = true;
                    NumberEval nx = (NumberEval)vx;
                    NumberEval ny = (NumberEval)vy;
                    result += acc.Accumulate(nx.NumberValue, ny.NumberValue);
                }
                else
                {
                    // all other combinations of value types are silently ignored
                }
            }
            if (firstXerr != null)
            {
                throw new EvaluationException(firstXerr);
            }
            if (firstYerr != null)
            {
                throw new EvaluationException(firstYerr);
            }
            if (!accumlatedSome)
            {
                throw new EvaluationException(ErrorEval.DIV_ZERO);
            }
            return(result);
        }
示例#6
0
 /**
  * Once the binary search has found a single match, (V/H)LOOKUP steps one by one over subsequent
  * values to choose the last matching item.
  */
 private static int FindLastIndexInRunOfEqualValues(LookupValueComparer lookupComparer, ValueVector vector,
                                                    int firstFoundIndex, int maxIx)
 {
     for (int i = firstFoundIndex + 1; i < maxIx; i++)
     {
         if (!lookupComparer.CompareTo(vector.GetItem(i)).IsEqual)
         {
             return(i - 1);
         }
     }
     return(maxIx - 1);
 }
示例#7
0
        /**
         * Finds first (lowest index) exact occurrence of specified value.
         * @param lookupValue the value to be found in column or row vector
         * @param vector the values to be searched. For VLOOKUP this Is the first column of the
         *  tableArray. For HLOOKUP this Is the first row of the tableArray.
         * @return zero based index into the vector, -1 if value cannot be found
         */
        private static int LookupIndexOfExactValue(LookupValueComparer lookupComparer, ValueVector vector)
        {
            // Find first occurrence of lookup value
            int size = vector.Size;

            for (int i = 0; i < size; i++)
            {
                if (lookupComparer.CompareTo(vector.GetItem(i)).IsEqual)
                {
                    return(i);
                }
            }
            return(-1);
        }
示例#8
0
文件: Vlookup.cs 项目: hiodava/Romero
 public override ValueEval Evaluate(int srcRowIndex, int srcColumnIndex, ValueEval lookup_value, ValueEval table_array,
                                    ValueEval col_index, ValueEval range_lookup)
 {
     try
     {
         // Evaluation order:
         // arg0 lookup_value, arg1 table_array, arg3 range_lookup, find lookup value, arg2 col_index, fetch result
         ValueEval   lookupValue   = OperandResolver.GetSingleValue(lookup_value, srcRowIndex, srcColumnIndex);
         TwoDEval    tableArray    = LookupUtils.ResolveTableArrayArg(table_array);
         bool        isRangeLookup = LookupUtils.ResolveRangeLookupArg(range_lookup, srcRowIndex, srcColumnIndex);
         int         rowIndex      = LookupUtils.LookupIndexOfValue(lookupValue, LookupUtils.CreateColumnVector(tableArray, 0), isRangeLookup);
         int         colIndex      = LookupUtils.ResolveRowOrColIndexArg(col_index, srcRowIndex, srcColumnIndex);
         ValueVector resultCol     = CreateResultColumnVector(tableArray, colIndex);
         return(resultCol.GetItem(rowIndex));
     }
     catch (EvaluationException e)
     {
         return(e.GetErrorEval());
     }
 }
示例#9
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);
            }
        }
示例#10
0
        public ValueEval Evaluate(ValueEval[] args, int srcCellRow, int srcCellCol)
        {
            switch (args.Length)
            {
            case 3:
                break;

            case 2:
                // complex rules to choose lookupVector and resultVector from the single area ref
                throw new Exception("Two arg version of LOOKUP not supported yet");

            default:
                return(ErrorEval.VALUE_INVALID);
            }


            try
            {
                ValueEval lookupValue    = OperandResolver.GetSingleValue(args[0], srcCellRow, srcCellCol);
                AreaEval  aeLookupVector = LookupUtils.ResolveTableArrayArg(args[1]);
                AreaEval  aeResultVector = LookupUtils.ResolveTableArrayArg(args[2]);

                ValueVector lookupVector = CreateVector(aeLookupVector);
                ValueVector resultVector = CreateVector(aeResultVector);
                if (lookupVector.Size > resultVector.Size)
                {
                    // Excel seems to handle this by accessing past the end of the result vector.
                    throw new Exception("Lookup vector and result vector of differing sizes not supported yet");
                }
                int index = LookupUtils.LookupIndexOfValue(lookupValue, lookupVector, true);

                return(resultVector.GetItem(index));
            }
            catch (EvaluationException e)
            {
                return(e.GetErrorEval());
            }
        }
示例#11
0
        private double EvaluateInternal(ValueVector x, ValueVector y, int size)
        {
            // error handling is as if the x is fully Evaluated before y
            ErrorEval firstXerr      = null;
            ErrorEval firstYerr      = null;
            bool      accumlatedSome = false;
            // first pass: read in data, compute xbar and ybar
            double sumx = 0.0, sumy = 0.0;

            for (int i = 0; i < size; i++)
            {
                ValueEval vx = x.GetItem(i);
                ValueEval vy = y.GetItem(i);
                if (vx is ErrorEval)
                {
                    if (firstXerr == null)
                    {
                        firstXerr = (ErrorEval)vx;
                        continue;
                    }
                }
                if (vy is ErrorEval)
                {
                    if (firstYerr == null)
                    {
                        firstYerr = (ErrorEval)vy;
                        continue;
                    }
                }
                // only count pairs if both elements are numbers
                if (vx is NumberEval && vy is NumberEval)
                {
                    accumlatedSome = true;
                    NumberEval nx = (NumberEval)vx;
                    NumberEval ny = (NumberEval)vy;
                    sumx += nx.NumberValue;
                    sumy += ny.NumberValue;
                }
                else
                {
                    // all other combinations of value types are silently ignored
                }
            }
            double xbar = sumx / size;
            double ybar = sumy / size;

            // second pass: compute summary statistics
            double xxbar = 0.0, xybar = 0.0;

            for (int i = 0; i < size; i++)
            {
                ValueEval vx = x.GetItem(i);
                ValueEval vy = y.GetItem(i);

                if (vx is ErrorEval)
                {
                    if (firstXerr == null)
                    {
                        firstXerr = (ErrorEval)vx;
                        continue;
                    }
                }
                if (vy is ErrorEval)
                {
                    if (firstYerr == null)
                    {
                        firstYerr = (ErrorEval)vy;
                        continue;
                    }
                }

                // only count pairs if both elements are numbers
                if (vx is NumberEval && vy is NumberEval)
                {
                    NumberEval nx = (NumberEval)vx;
                    NumberEval ny = (NumberEval)vy;
                    xxbar += (nx.NumberValue - xbar) * (nx.NumberValue - xbar);
                    xybar += (nx.NumberValue - xbar) * (ny.NumberValue - ybar);
                }
                else
                {
                    // all other combinations of value types are silently ignored
                }
            }
            double beta1 = xybar / xxbar;
            double beta0 = ybar - beta1 * xbar;

            if (firstXerr != null)
            {
                throw new EvaluationException(firstXerr);
            }
            if (firstYerr != null)
            {
                throw new EvaluationException(firstYerr);
            }
            if (!accumlatedSome)
            {
                throw new EvaluationException(ErrorEval.DIV_ZERO);
            }

            if (function == FUNCTION.INTERCEPT)
            {
                return(beta0);
            }
            else
            {
                return(beta1);
            }
        }
        private double EvaluateInternal(ValueVector x, ValueVector y, int size)
        {

            // error handling is as if the x is fully Evaluated before y
            ErrorEval firstXerr = null;
            ErrorEval firstYerr = null;
            bool accumlatedSome = false;
            // first pass: read in data, compute xbar and ybar
            double sumx = 0.0, sumy = 0.0;

            for (int i = 0; i < size; i++)
            {
                ValueEval vx = x.GetItem(i);
                ValueEval vy = y.GetItem(i);
                if (vx is ErrorEval)
                {
                    if (firstXerr == null)
                    {
                        firstXerr = (ErrorEval)vx;
                        continue;
                    }
                }
                if (vy is ErrorEval)
                {
                    if (firstYerr == null)
                    {
                        firstYerr = (ErrorEval)vy;
                        continue;
                    }
                }
                // only count pairs if both elements are numbers
                if (vx is NumberEval && vy is NumberEval)
                {
                    accumlatedSome = true;
                    NumberEval nx = (NumberEval)vx;
                    NumberEval ny = (NumberEval)vy;
                    sumx += nx.NumberValue;
                    sumy += ny.NumberValue;
                }
                else
                {
                    // all other combinations of value types are silently ignored
                }
            }
            double xbar = sumx / size;
            double ybar = sumy / size;

            // second pass: compute summary statistics
            double xxbar = 0.0, xybar = 0.0;
            for (int i = 0; i < size; i++)
            {
                ValueEval vx = x.GetItem(i);
                ValueEval vy = y.GetItem(i);

                if (vx is ErrorEval)
                {
                    if (firstXerr == null)
                    {
                        firstXerr = (ErrorEval)vx;
                        continue;
                    }
                }
                if (vy is ErrorEval)
                {
                    if (firstYerr == null)
                    {
                        firstYerr = (ErrorEval)vy;
                        continue;
                    }
                }

                // only count pairs if both elements are numbers
                if (vx is NumberEval && vy is NumberEval)
                {
                    NumberEval nx = (NumberEval)vx;
                    NumberEval ny = (NumberEval)vy;
                    xxbar += (nx.NumberValue - xbar) * (nx.NumberValue - xbar);
                    xybar += (nx.NumberValue - xbar) * (ny.NumberValue - ybar);
                }
                else
                {
                    // all other combinations of value types are silently ignored
                }
            }
            double beta1 = xybar / xxbar;
            double beta0 = ybar - beta1 * xbar;

            if (firstXerr != null)
            {
                throw new EvaluationException(firstXerr);
            }
            if (firstYerr != null)
            {
                throw new EvaluationException(firstYerr);
            }
            if (!accumlatedSome)
            {
                throw new EvaluationException(ErrorEval.DIV_ZERO);
            }

            if (function == FUNCTION.INTERCEPT)
            {
                return beta0;
            }
            else
            {
                return beta1;
            }
        }
示例#13
0
 /**
  * Once the binary search has found a single match, (V/H)LOOKUP steps one by one over subsequent
  * values to choose the last matching item.
  */
 private static int FindLastIndexInRunOfEqualValues(LookupValueComparer lookupComparer, ValueVector vector,
             int firstFoundIndex, int maxIx)
 {
     for (int i = firstFoundIndex + 1; i < maxIx; i++)
     {
         if (!lookupComparer.CompareTo(vector.GetItem(i)).IsEqual)
         {
             return i - 1;
         }
     }
     return maxIx - 1;
 }
示例#14
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;
            }
        }
示例#15
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);
            }
        }
示例#16
0
        /**
         * Finds first (lowest index) exact occurrence of specified value.
         * @param lookupValue the value to be found in column or row vector
         * @param vector the values to be searched. For VLOOKUP this Is the first column of the 
         * 	tableArray. For HLOOKUP this Is the first row of the tableArray. 
         * @return zero based index into the vector, -1 if value cannot be found
         */
        private static int LookupIndexOfExactValue(LookupValueComparer lookupComparer, ValueVector vector)
        {

            // Find first occurrence of lookup value
            int size = vector.Size;
            for (int i = 0; i < size; i++)
            {
                if (lookupComparer.CompareTo(vector.GetItem(i)).IsEqual)
                {
                    return i;
                }
            }
            return -1;
        }
示例#17
0
文件: Match.cs 项目: babywzazy/Server
        /**
         * @return zero based index
         */
        private static int FindIndexOfValue(ValueEval lookupValue, ValueVector lookupRange,
                bool matchExact, bool FindLargestLessThanOrEqual)
        {
            LookupValueComparer lookupComparer = CreateLookupComparer(lookupValue, matchExact);

            if (matchExact)
            {
                for (int i = 0; i < lookupRange.Size; i++)
                {
                    if (lookupComparer.CompareTo(lookupRange.GetItem(i)).IsEqual)
                    {
                        return i;
                    }
                }
                throw new EvaluationException(ErrorEval.NA);
            }

            if (FindLargestLessThanOrEqual)
            {
                // Note - backward iteration
                for (int i = lookupRange.Size - 1; i >= 0; i--)
                {
                    CompareResult cmp = lookupComparer.CompareTo(lookupRange.GetItem(i));
                    if (cmp.IsTypeMismatch)
                    {
                        continue;
                    }
                    if (!cmp.IsLessThan)
                    {
                        return i;
                    }
                }
                throw new EvaluationException(ErrorEval.NA);
            }

            // else - Find smallest greater than or equal to
            // TODO - Is binary search used for (match_type==+1) ?
            for (int i = 0; i < lookupRange.Size; i++)
            {
                CompareResult cmp = lookupComparer.CompareTo(lookupRange.GetItem(i));
                if (cmp.IsEqual)
                {
                    return i;
                }
                if (cmp.IsGreaterThan)
                {
                    if (i < 1)
                    {
                        throw new EvaluationException(ErrorEval.NA);
                    }
                    return i - 1;
                }
            }

            throw new EvaluationException(ErrorEval.NA);
        }
        private double EvaluateInternal(ValueVector x, ValueVector y, int size)
        {
            Accumulator acc = CreateAccumulator();

            // error handling is as if the x is fully evaluated before y
            ErrorEval firstXerr = null;
            ErrorEval firstYerr = null;
            bool accumlatedSome = false;
            double result = 0.0;

            for (int i = 0; i < size; i++)
            {
                ValueEval vx = x.GetItem(i);
                ValueEval vy = y.GetItem(i);
                if (vx is ErrorEval)
                {
                    if (firstXerr == null)
                    {
                        firstXerr = (ErrorEval)vx;
                        continue;
                    }
                }
                if (vy is ErrorEval)
                {
                    if (firstYerr == null)
                    {
                        firstYerr = (ErrorEval)vy;
                        continue;
                    }
                }
                // only count pairs if both elements are numbers
                if (vx is NumberEval && vy is NumberEval)
                {
                    accumlatedSome = true;
                    NumberEval nx = (NumberEval)vx;
                    NumberEval ny = (NumberEval)vy;
                    result += acc.Accumulate(nx.NumberValue, ny.NumberValue);
                }
                else
                {
                    // all other combinations of value types are silently ignored
                }
            }
            if (firstXerr != null)
            {
                throw new EvaluationException(firstXerr);
            }
            if (firstYerr != null)
            {
                throw new EvaluationException(firstYerr);
            }
            if (!accumlatedSome)
            {
                throw new EvaluationException(ErrorEval.DIV_ZERO);
            }
            return result;
        }
示例#19
0
        /**
         * @return zero based index
         */
        private static int FindIndexOfValue(ValueEval lookupValue, ValueVector lookupRange,
                                            bool matchExact, bool FindLargestLessThanOrEqual)
        {
            LookupValueComparer lookupComparer = CreateLookupComparer(lookupValue, matchExact);

            int size = lookupRange.Size;

            if (matchExact)
            {
                for (int i = 0; i < size; i++)
                {
                    if (lookupComparer.CompareTo(lookupRange.GetItem(i)).IsEqual)
                    {
                        return(i);
                    }
                }
                throw new EvaluationException(ErrorEval.NA);
            }

            if (FindLargestLessThanOrEqual)
            {
                //in case the lookupRange area is not sorted, still try to get the right index
                if (lookupValue is NumericValueEval nve)
                {
                    Dictionary <int, double> dicDeltas = new Dictionary <int, double>();
                    for (int i = 0; i < size; i++)
                    {
                        var item = lookupRange.GetItem(i) as NumericValueEval;
                        if (lookupComparer.CompareTo(item).IsEqual)
                        {
                            return(i);
                        }
                        else
                        {
                            dicDeltas.Add(i, item.NumberValue - nve.NumberValue);
                        }
                    }

                    return(dicDeltas.Where(kv => kv.Value < 0).OrderByDescending(kv => kv.Value).First().Key);
                }
                // Note - backward iteration
                for (int i = size - 1; i >= 0; i--)
                {
                    CompareResult cmp = lookupComparer.CompareTo(lookupRange.GetItem(i));
                    if (cmp.IsTypeMismatch)
                    {
                        continue;
                    }
                    if (!cmp.IsLessThan)
                    {
                        return(i);
                    }
                }
                throw new EvaluationException(ErrorEval.NA);
            }

            // else - Find smallest greater than or equal to
            // TODO - Is binary search used for (match_type==+1) ?
            for (int i = 0; i < size; i++)
            {
                CompareResult cmp = lookupComparer.CompareTo(lookupRange.GetItem(i));
                if (cmp.IsEqual)
                {
                    return(i);
                }
                if (cmp.IsGreaterThan)
                {
                    if (i < 1)
                    {
                        throw new EvaluationException(ErrorEval.NA);
                    }
                    return(i - 1);
                }
            }

            return(size - 1);
        }