ooo-build r11270 - in trunk: . patches/src680



Author: kyoshida
Date: Tue Jan 15 16:33:33 2008
New Revision: 11270
URL: http://svn.gnome.org/viewvc/ooo-build?rev=11270&view=rev

Log:
2008-01-15  Kohei Yoshida  <kyoshida novell com>

	* patches/src680/sc-openformula-match.diff: enhance the built-in MATCH
	function so that it accepts array as a 2nd parameter.

	* patches/src680/apply: apply the new patch.


Added:
   trunk/patches/src680/sc-openformula-match.diff
Modified:
   trunk/ChangeLog
   trunk/patches/src680/apply

Modified: trunk/patches/src680/apply
==============================================================================
--- trunk/patches/src680/apply	(original)
+++ trunk/patches/src680/apply	Tue Jan 15 16:33:33 2008
@@ -670,6 +670,9 @@
 # Enhance FREQUENCY function to make it behave like Excel (ODFF).
 sc-openformula-frequency.diff, i#8946, kohei
 
+# Enhance MATCH function to accept array as the 2nd parameter (ODFF).
+sc-openformula-match.diff, i#8947, kohei
+
 # Enhance SUMIF function to make Calc's handling of the 3rd parameter identical
 # to Excel's (ODFF).
 sc-openformula-sumif.diff, i#85000, kohei

Added: trunk/patches/src680/sc-openformula-match.diff
==============================================================================
--- (empty file)
+++ trunk/patches/src680/sc-openformula-match.diff	Tue Jan 15 16:33:33 2008
@@ -0,0 +1,176 @@
+Index: sc/source/core/tool/interpr1.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/tool/interpr1.cxx,v
+retrieving revision 1.53
+diff -u -r1.53 interpr1.cxx
+--- sc/source/core/tool/interpr1.cxx	1 Nov 2007 16:23:17 -0000	1.53
++++ sc/source/core/tool/interpr1.cxx	15 Jan 2008 14:26:34 -0000
+@@ -3815,9 +3815,51 @@
+ 	}
+ }
+ 
++/** returns -1 when the matrix value is smaller than the query value, 0 when
++    they are equal, and 1 when the matrix value is larger than the query
++    value. */
++static sal_Int8 lcl_CompareMatrix2Query(SCSIZE i, const ScMatrix& rMat, const ScQueryEntry& rEntry)
++{
++    if (rMat.IsValue(i))
++    {
++        const double nVal1 = rMat.GetDouble(i);
++        const double nVal2 = rEntry.nVal;
++        if (nVal1 == nVal2)
++            return 0;
++
++        return nVal1 < nVal2 ? -1 : 1;
++    }
++
++    if (!rEntry.pStr)
++        // this should not happen!
++        return 1;
++
++    const String& rStr1 = rMat.GetString(i);
++    const String& rStr2 = *rEntry.pStr;
++    if (rStr1 == rStr2)
++        return 0;
++
++    return rStr1 < rStr2 ? -1 : 1;
++}
++
++/** returns the last item with the identical value as the original item
++    value. */
++static void lcl_GetLastMatch(SCSIZE& rIndex, const ScMatrix& rMat, SCSIZE nMatCount,
++                             bool bReverse)
++{
++    double nVal = rMat.GetDouble(rIndex);
++    if (bReverse)
++        while (rIndex > 0 && nVal == rMat.GetDouble(rIndex-1))
++            --rIndex;
++    else
++        while (rIndex < nMatCount-1 && nVal == rMat.GetDouble(rIndex+1))
++            ++rIndex;
++}
+ 
+ void ScInterpreter::ScMatch()
+ {
++    ScMatrixRef pMatSrc = NULL;
++
+ 	BYTE nParamCount = GetByte();
+ 	if ( MustHaveParamCount( nParamCount, 2, 3 ) )
+ 	{
+@@ -3841,6 +3883,15 @@
+ 				return;
+ 			}
+ 		}
++        else if (GetStackType() == svMatrix)
++        {
++            pMatSrc = PopMatrix();
++            if (!pMatSrc)
++            {
++                SetIllegalParameter();
++                return;
++            }
++        }
+ 		else
+ 		{
+ 			SetIllegalParameter();
+@@ -3918,6 +3969,100 @@
+ 			}
+ 			if ( rEntry.bQueryByString )
+                 rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
++
++            if (pMatSrc) // The source data is matrix array.
++            {
++                SCSIZE nC, nR;
++                pMatSrc->GetDimensions(nC, nR);
++                if (nC > 1 && nR > 1)
++                {
++                    // The source matrix must be a vector.
++                    SetIllegalParameter();
++                    return;
++                }
++                SCSIZE nMatCount = (nC == 1) ? nR : nC;
++
++                // simple serial search for equality mode (source data doesn't 
++                // need to be sorted).
++
++                if (rEntry.eOp == SC_EQUAL)
++                {
++                    for (SCSIZE i = 0; i < nMatCount; ++i)
++                    {
++                        if (lcl_CompareMatrix2Query(i, *pMatSrc, rEntry) == 0)
++                        {
++                            PushDouble(i+1); // found !
++                            return;
++                        }
++                    }
++                    SetNA(); // not found
++                    return;
++                }
++
++                // binary search for non-equality mode (the source data is
++                // assumed to be sorted).
++
++                bool bAscOrder = (rEntry.eOp == SC_LESS_EQUAL);
++                SCSIZE nFirst = 0, nLast = nMatCount-1, nHitIndex = 0;
++                for (SCSIZE nLen = nLast-nFirst; nLen > 0; nLen = nLast-nFirst)
++                {
++                    SCSIZE nMid = nFirst + nLen/2;
++                    sal_Int8 nCmp = lcl_CompareMatrix2Query(nMid, *pMatSrc, rEntry);
++                    if (nCmp == 0)
++                    {
++                        // exact match.  find the last item with the same value.
++                        lcl_GetLastMatch(nMid, *pMatSrc, nMatCount, !bAscOrder);
++                        PushDouble(nMid+1);
++                        return;
++                    }
++
++                    if (nLen == 1) // first and last items are next to each other.
++                    {
++                        if (nCmp < 0)
++                            nHitIndex = bAscOrder ? nLast : nFirst;
++                        else
++                            nHitIndex = bAscOrder ? nFirst : nLast;
++                        break;
++                    }
++
++                    if (nCmp < 0)
++                    {
++                        if (bAscOrder)
++                            nFirst = nMid;
++                        else
++                            nLast = nMid;
++                    }
++                    else
++                    {
++                        if (bAscOrder)
++                            nLast = nMid;
++                        else
++                            nFirst = nMid;
++                    }
++                }
++
++                if (nHitIndex == nMatCount-1) // last item
++                {
++                    sal_Int8 nCmp = lcl_CompareMatrix2Query(nHitIndex, *pMatSrc, rEntry);
++                    if ((bAscOrder && nCmp <= 0) || (!bAscOrder && nCmp >= 0))
++                    {
++                        // either the last item is an exact match or the real
++                        // hit is beyond the last item.
++                        PushDouble(nHitIndex+1); 
++                        return;
++                    }
++                }
++
++                if (nHitIndex > 0) // valid hit must be 2nd item or higher
++                {
++                    PushDouble(nHitIndex); // non-exact match
++                    return;
++                }
++
++                SetNA();
++                return;
++            }
++
+ 			SCCOLROW nDelta = 0;
+             if (nCol1 == nCol2)
+             {                                           // search row in column



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]