ooo-build r11270 - in trunk: . patches/src680
- From: kyoshida svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r11270 - in trunk: . patches/src680
- Date: Tue, 15 Jan 2008 16:33:33 +0000 (GMT)
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]