sc/inc/scmatrix.hxx | 10 +- sc/source/core/tool/interpr1.cxx | 185 ++++++++++++++++++++++----------------- sc/source/core/tool/scmatrix.cxx | 27 ++++- 3 files changed, 134 insertions(+), 88 deletions(-)
New commits: commit 57b1dedcbde5418b1bae6295cbe730afce47a348 Author: Kohei Yoshida <[email protected]> Date: Fri Oct 18 11:07:38 2013 -0400 Slightly optimize matrix value traversal. Change-Id: Idbcb2348ff7f4a5df32d66761849e3a92b4eb794 diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx index 5e9800e..7d6d911 100644 --- a/sc/inc/scmatrix.hxx +++ b/sc/inc/scmatrix.hxx @@ -404,7 +404,15 @@ public: void CompareMatrix( ScMatrix& rResMat, sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions = NULL ) const; - void GetDoubleArray( std::vector<double>& rArray ) const; + /** + * Convert the content of matrix into a linear array of numeric values. + * String elements are mapped to NaN's and empty elements are mapped to + * either NaN or zero values. + * + * @param bEmptyAsZero if true empty elements are mapped to zero values, + * otherwise they become NaN values. + */ + void GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero = true ) const; void MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const; ScMatrix& operator+= ( const ScMatrix& r ); diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 7515c0c..0d63f54 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -5353,7 +5353,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc ) } if (nGlobalError) - continue; // and bail out, no need to evaluate other arguments + return 0; // and bail out, no need to evaluate other arguments // take range nParam = 1; @@ -5391,6 +5391,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc ) if (!pQueryMatrix) { SetError( errIllegalParameter); + return 0; } nCol1 = 0; nRow1 = 0; @@ -5404,9 +5405,13 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc ) break; default: SetError( errIllegalParameter); + return 0; } if ( nTab1 != nTab2 ) + { SetError( errIllegalArgument); + return 0; + } // All reference ranges must be of same dimension and size. if (!nDimensionCols) @@ -5414,80 +5419,87 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc ) if (!nDimensionRows) nDimensionRows = nRow2 - nRow1 + 1; if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1))) + { SetError ( errIllegalArgument); + return 0; + } // recalculate matrix values - if (nGlobalError == 0) + if (nGlobalError) + return 0; + + // initialize temporary result matrix + if (!pResMat) { - // initialize temporary result matrix + SCSIZE nResC, nResR; + nResC = nCol2 - nCol1 + 1; + nResR = nRow2 - nRow1 + 1; + pResMat = GetNewMat(nResC, nResR, false); if (!pResMat) { - SCSIZE nResC, nResR; - nResC = nCol2 - nCol1 + 1; - nResR = nRow2 - nRow1 + 1; - pResMat = GetNewMat(nResC, nResR, false); - if (!pResMat) - SetError( errIllegalParameter); + SetError( errIllegalParameter); + return 0; } + } - ScQueryParam rParam; - rParam.nRow1 = nRow1; - rParam.nRow2 = nRow2; + ScQueryParam rParam; + rParam.nRow1 = nRow1; + rParam.nRow2 = nRow2; - ScQueryEntry& rEntry = rParam.GetEntry(0); - ScQueryEntry::Item& rItem = rEntry.GetQueryItem(); - rEntry.bDoQuery = true; - if (!bIsString) - { - rItem.meType = ScQueryEntry::ByValue; - rItem.mfVal = fVal; - rEntry.eOp = SC_EQUAL; - } - else + ScQueryEntry& rEntry = rParam.GetEntry(0); + ScQueryEntry::Item& rItem = rEntry.GetQueryItem(); + rEntry.bDoQuery = true; + if (!bIsString) + { + rItem.meType = ScQueryEntry::ByValue; + rItem.mfVal = fVal; + rEntry.eOp = SC_EQUAL; + } + else + { + rParam.FillInExcelSyntax(pDok->GetSharedStringPool(), aString.getString(), 0); + sal_uInt32 nIndex = 0; + bool bNumber = pFormatter->IsNumberFormat( + rItem.maString.getString(), nIndex, rItem.mfVal); + rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString; + if (rItem.meType == ScQueryEntry::ByString) + rParam.bRegExp = MayBeRegExp(rItem.maString.getString(), pDok); + } + ScAddress aAdr; + aAdr.SetTab( nTab1 ); + rParam.nCol1 = nCol1; + rParam.nCol2 = nCol2; + rEntry.nField = nCol1; + SCsCOL nColDiff = -nCol1; + SCsROW nRowDiff = -nRow1; + if (pQueryMatrix) + { + // Never case-sensitive. + sc::CompareOptions aOptions( pDok, rEntry, rParam.bRegExp); + ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions); + if (nGlobalError || !pResultMatrix) { - rParam.FillInExcelSyntax(pDok->GetSharedStringPool(), aString.getString(), 0); - sal_uInt32 nIndex = 0; - bool bNumber = pFormatter->IsNumberFormat( - rItem.maString.getString(), nIndex, rItem.mfVal); - rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString; - if (rItem.meType == ScQueryEntry::ByString) - rParam.bRegExp = MayBeRegExp(rItem.maString.getString(), pDok); + SetError( errIllegalParameter); + return 0; } - ScAddress aAdr; - aAdr.SetTab( nTab1 ); - rParam.nCol1 = nCol1; - rParam.nCol2 = nCol2; - rEntry.nField = nCol1; - SCsCOL nColDiff = -nCol1; - SCsROW nRowDiff = -nRow1; - if (pQueryMatrix) - { - // Never case-sensitive. - sc::CompareOptions aOptions( pDok, rEntry, rParam.bRegExp); - ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions); - if (nGlobalError || !pResultMatrix) - { - SetError( errIllegalParameter); - } - // query and result matrices have same geometry, and the - // result matrix is filled with boolean values. - *pResMat += *pResultMatrix; - } - else + // query and result matrices have same geometry, and the + // result matrix is filled with boolean values. + *pResMat += *pResultMatrix; + } + else + { + ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false); + // Increment Entry.nField in iterator when switching to next column. + aCellIter.SetAdvanceQueryParamEntryField( true ); + if ( aCellIter.GetFirst() ) { - ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false); - // Increment Entry.nField in iterator when switching to next column. - aCellIter.SetAdvanceQueryParamEntryField( true ); - if ( aCellIter.GetFirst() ) + do { - do - { - SCSIZE nC = aCellIter.GetCol() + nColDiff; - SCSIZE nR = aCellIter.GetRow() + nRowDiff; - pResMat->PutDouble(pResMat->GetDouble(nC, nR)+1.0, nC, nR); - } while ( aCellIter.GetNext() ); - } + SCSIZE nC = aCellIter.GetCol() + nColDiff; + SCSIZE nR = aCellIter.GetRow() + nRowDiff; + pResMat->PutDouble(pResMat->GetDouble(nC, nR)+1.0, nC, nR); + } while ( aCellIter.GetNext() ); } } nParamCount -= 2; @@ -5548,13 +5560,20 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc ) break; default: SetError( errIllegalParameter); + return 0; } if ( nMainTab1 != nMainTab2 ) + { SetError( errIllegalArgument); + return 0; + } // All reference ranges must be of same dimension and size. if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1))) + { SetError ( errIllegalArgument); + return 0; + } if (nGlobalError) return 0; // bail out @@ -5564,28 +5583,34 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc ) aAdr.SetTab( nMainTab1 ); if (pMainMatrix) { - SCSIZE nC, nR; - pResMat->GetDimensions(nC, nR); - for (SCSIZE nCol = 0; nCol < nC; ++nCol) + std::vector<double> aResValues, aMainValues; + pResMat->GetDoubleArray(aResValues, true); + pMainMatrix->GetDoubleArray(aMainValues, false); // Map empty values to NaN's. + if (aResValues.size() != aMainValues.size()) { - for (SCSIZE nRow = 0; nRow < nR; ++nRow) + SetError( errIllegalArgument); + return 0; + } + + std::vector<double>::const_iterator itRes = aResValues.begin(), itResEnd = aResValues.end(); + std::vector<double>::const_iterator itMain = aMainValues.begin(); + for (; itRes != itResEnd; ++itRes, ++itMain) + { + if (*itRes != nQueryCount) + continue; + + fVal = *itMain; + if (rtl::math::isNan(fVal)) + continue; + + ++fCount; + if (bNull && fVal != 0.0) { - if (pResMat->GetDouble( nCol, nRow) == nQueryCount) - { - if (pMainMatrix->IsValue( nCol, nRow)) - { - fVal = pMainMatrix->GetDouble( nCol, nRow); - ++fCount; - if ( bNull && fVal != 0.0 ) - { - bNull = false; - fMem = fVal; - } - else - fSum += fVal; - } - } + bNull = false; + fMem = fVal; } + else + fSum += fVal; } } else diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx index 29dcda7..a5487a7 100644 --- a/sc/source/core/tool/scmatrix.cxx +++ b/sc/source/core/tool/scmatrix.cxx @@ -302,7 +302,7 @@ public: void CompareMatrix( ScMatrix& rResMat, sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const; - void GetDoubleArray( std::vector<double>& rArray ) const; + void GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const; void MergeDoubleArray( std::vector<double>& rArray, ScMatrix::Op eOp ) const; void AddValues( const ScMatrixImpl& rMat ); @@ -1482,8 +1482,11 @@ class ToDoubleArray : std::unary_function<MatrixImplType::element_block_type, vo std::vector<double> maArray; std::vector<double>::iterator miPos; double mfNaN; + bool mbEmptyAsZero; + public: - ToDoubleArray(size_t nSize) : maArray(nSize, 0.0), miPos(maArray.begin()) + ToDoubleArray( size_t nSize, bool bEmptyAsZero ) : + maArray(nSize, 0.0), miPos(maArray.begin()), mbEmptyAsZero(bEmptyAsZero) { rtl::math::setNan(&mfNaN); } @@ -1517,7 +1520,17 @@ public: } break; case mdds::mtm::element_empty: - std::advance(miPos, node.size); + { + if (mbEmptyAsZero) + { + std::advance(miPos, node.size); + return; + } + + for (size_t i = 0; i < node.size; ++i, ++miPos) + *miPos = mfNaN; + } + break; default: ; } @@ -1669,10 +1682,10 @@ void ScMatrixImpl::CompareMatrix( rResMat.PutDouble(&rResVal[0], rResVal.size(), 0, 0); } -void ScMatrixImpl::GetDoubleArray( std::vector<double>& rArray ) const +void ScMatrixImpl::GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const { MatrixImplType::size_pair_type aSize = maMat.size(); - ToDoubleArray aFunc(aSize.row*aSize.column); + ToDoubleArray aFunc(aSize.row*aSize.column, bEmptyAsZero); maMat.walk(aFunc); aFunc.swap(rArray); } @@ -2239,9 +2252,9 @@ void ScMatrix::CompareMatrix( ScMatrix& rResMat, sc::Compare& rComp, size_t nMat pImpl->CompareMatrix(rResMat, rComp, nMatPos, pOptions); } -void ScMatrix::GetDoubleArray( std::vector<double>& rArray ) const +void ScMatrix::GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const { - pImpl->GetDoubleArray(rArray); + pImpl->GetDoubleArray(rArray, bEmptyAsZero); } void ScMatrix::MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const _______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
