diff options
author | Jan Holesovsky <kendy@collabora.com> | 2015-11-30 10:28:43 +0100 |
---|---|---|
committer | Jan Holesovsky <kendy@collabora.com> | 2015-12-01 16:40:45 +0100 |
commit | d4daad185e9583bedbb5a4eef1fd53e1f22e219b (patch) | |
tree | 993de32421d2b74f1375f4a63e3323003613ba0f | |
parent | bd8a89f208c71e51921d5f090179b99b45cc0a5f (diff) |
sc interpreter: Move the code that can create a ScFullMatrix.
For the operations that we haven't implemented directly in ScVectorRefMatrix
yet, create the ScFullMatrix the same way as we used to do before, and call
the appropriate method of ScFullMatrix.
This commit only moves the code, does not turn the 'throw
std::runtime_exception' into actually using the new ensureFullMatrix().
Change-Id: I336a4ddf07b0b60a5a41036e19c70a44ba575834
-rw-r--r-- | sc/inc/scmatrix.hxx | 19 | ||||
-rw-r--r-- | sc/source/core/tool/formulagroup.cxx | 204 | ||||
-rw-r--r-- | sc/source/core/tool/scmatrix.cxx | 191 |
3 files changed, 206 insertions, 208 deletions
diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx index 7f1392b8cf66..9287f556b41f 100644 --- a/sc/inc/scmatrix.hxx +++ b/sc/inc/scmatrix.hxx @@ -409,9 +409,6 @@ class SC_DLLPUBLIC ScFullMatrix : public ScMatrix std::unique_ptr<ScMatrixImpl> pImpl; - // only delete via Delete() - virtual ~ScFullMatrix(); - ScFullMatrix( const ScFullMatrix& ) = delete; ScFullMatrix& operator=( const ScFullMatrix&) = delete; @@ -422,6 +419,8 @@ public: ScFullMatrix( size_t nC, size_t nR, const std::vector<double>& rInitVals ); + virtual ~ScFullMatrix(); + /** Clone the matrix. */ virtual ScMatrix* Clone() const override; @@ -611,19 +610,27 @@ class SC_DLLPUBLIC ScVectorRefMatrix : public ScMatrix const formula::DoubleVectorRefToken* mpToken; ScInterpreter* mpErrorInterpreter; + /// For the operations that are not fully implemented, create a ScFullMatrix, and operate on it. + std::unique_ptr<ScFullMatrix> mpFullMatrix; + SCSIZE mnRowStart; SCSIZE mnRowSize; - // only delete via Delete() - virtual ~ScVectorRefMatrix(); - ScVectorRefMatrix( const ScVectorRefMatrix& ) = delete; ScVectorRefMatrix& operator=( const ScVectorRefMatrix&) = delete; + /// For the operations that are not fully implemented, create a ScFullMatrix, and operate on it. + /// + /// Note: This is potentially an expensive operation. + /// TODO: Implement as much as possible directly using the DoubleVectorRefToken. + void ensureFullMatrix(); + public: ScVectorRefMatrix(const formula::DoubleVectorRefToken* pToken, SCSIZE nRowStart, SCSIZE nRowSize); + virtual ~ScVectorRefMatrix(); + /** Clone the matrix. */ virtual ScMatrix* Clone() const override; diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index ce5c70a2b5b2..f2f8acf1aa7f 100644 --- a/sc/source/core/tool/formulagroup.cxx +++ b/sc/source/core/tool/formulagroup.cxx @@ -138,156 +138,6 @@ FormulaGroupContext::~FormulaGroupContext() { } -namespace { - -/** - * Input double array consists of segments of NaN's and normal values. - * Insert only the normal values into the matrix while skipping the NaN's. - */ -void fillMatrix( ScMatrix& rMat, size_t nCol, const double* pNums, size_t nLen ) -{ - const double* pNum = pNums; - const double* pNumEnd = pNum + nLen; - const double* pNumHead = nullptr; - for (; pNum != pNumEnd; ++pNum) - { - if (!rtl::math::isNan(*pNum)) - { - if (!pNumHead) - // Store the first non-NaN position. - pNumHead = pNum; - - continue; - } - - if (pNumHead) - { - // Flush this non-NaN segment to the matrix. - rMat.PutDouble(pNumHead, pNum - pNumHead, nCol, pNumHead - pNums); - pNumHead = nullptr; - } - } - - if (pNumHead) - { - // Flush last non-NaN segment to the matrix. - rMat.PutDouble(pNumHead, pNum - pNumHead, nCol, pNumHead - pNums); - } -} - -void flushStrSegment( - ScMatrix& rMat, size_t nCol, rtl_uString** pHead, rtl_uString** pCur, rtl_uString** pTop ) -{ - size_t nOffset = pHead - pTop; - std::vector<svl::SharedString> aStrs; - aStrs.reserve(pCur - pHead); - for (; pHead != pCur; ++pHead) - aStrs.push_back(svl::SharedString(*pHead, *pHead)); - - rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset); -} - -void fillMatrix( ScMatrix& rMat, size_t nCol, rtl_uString** pStrs, size_t nLen ) -{ - rtl_uString** p = pStrs; - rtl_uString** pEnd = p + nLen; - rtl_uString** pHead = nullptr; - for (; p != pEnd; ++p) - { - if (*p) - { - if (!pHead) - // Store the first non-empty string position. - pHead = p; - - continue; - } - - if (pHead) - { - // Flush this non-empty segment to the matrix. - flushStrSegment(rMat, nCol, pHead, p, pStrs); - pHead = nullptr; - } - } - - if (pHead) - { - // Flush last non-empty segment to the matrix. - flushStrSegment(rMat, nCol, pHead, p, pStrs); - } -} - -void fillMatrix( ScMatrix& rMat, size_t nCol, const double* pNums, rtl_uString** pStrs, size_t nLen ) -{ - if (!pStrs) - { - fillMatrix(rMat, nCol, pNums, nLen); - return; - } - - const double* pNum = pNums; - const double* pNumHead = nullptr; - rtl_uString** pStr = pStrs; - rtl_uString** pStrEnd = pStr + nLen; - rtl_uString** pStrHead = nullptr; - - for (; pStr != pStrEnd; ++pStr, ++pNum) - { - if (*pStr) - { - // String cell exists. - - if (pNumHead) - { - // Flush this numeric segment to the matrix. - rMat.PutDouble(pNumHead, pNum - pNumHead, nCol, pNumHead - pNums); - pNumHead = nullptr; - } - - if (!pStrHead) - // Store the first non-empty string position. - pStrHead = pStr; - - continue; - } - - // No string cell. Check the numeric cell value. - - if (pStrHead) - { - // Flush this non-empty string segment to the matrix. - flushStrSegment(rMat, nCol, pStrHead, pStr, pStrs); - pStrHead = nullptr; - } - - if (!rtl::math::isNan(*pNum)) - { - // Numeric cell exists. - if (!pNumHead) - // Store the first non-NaN position. - pNumHead = pNum; - - continue; - } - - // Empty cell. No action required. - } - - if (pStrHead) - { - // Flush the last non-empty segment to the matrix. - flushStrSegment(rMat, nCol, pStrHead, pStr, pStrs); - } - else if (pNumHead) - { - // Flush the last numeric segment to the matrix. - rMat.PutDouble(pNumHead, pNum - pNumHead, nCol, pNumHead - pNums); - } -} - -} - CompiledFormula::CompiledFormula() {} CompiledFormula::~CompiledFormula() {} @@ -374,58 +224,8 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres if (!p2->IsEndFixed()) nRowEnd += i; - ScMatrixRef pMat; - if (ScCalcConfig::isSwInterpreterEnabled()) - { - assert(nRowStart <= nRowEnd); - pMat.reset(new ScVectorRefMatrix(p2, nRowStart, nRowEnd - nRowStart + 1)); - } - else - { - const std::vector<formula::VectorRefArray>& rArrays = p2->GetArrays(); - size_t nColSize = rArrays.size(); - size_t nRowSize = nRowEnd - nRowStart + 1; - pMat.reset(new ScFullMatrix(nColSize, nRowSize)); - - size_t nDataRowEnd = p2->GetArrayLength() - 1; - if (nRowStart > nDataRowEnd) - // Referenced rows are all empty. - nRowSize = 0; - else if (nRowEnd > nDataRowEnd) - // Data array is shorter than the row size of the reference. Truncate it to the data. - nRowSize -= nRowEnd - nDataRowEnd; - - for (size_t nCol = 0; nCol < nColSize; ++nCol) - { - const formula::VectorRefArray& rArray = rArrays[nCol]; - if (rArray.mpStringArray) - { - if (rArray.mpNumericArray) - { - // Mixture of string and numeric values. - const double* pNums = rArray.mpNumericArray; - pNums += nRowStart; - rtl_uString** pStrs = rArray.mpStringArray; - pStrs += nRowStart; - fillMatrix(*pMat, nCol, pNums, pStrs, nRowSize); - } - else - { - // String cells only. - rtl_uString** pStrs = rArray.mpStringArray; - pStrs += nRowStart; - fillMatrix(*pMat, nCol, pStrs, nRowSize); - } - } - else if (rArray.mpNumericArray) - { - // Numeric cells only. - const double* pNums = rArray.mpNumericArray; - pNums += nRowStart; - fillMatrix(*pMat, nCol, pNums, nRowSize); - } - } - } + assert(nRowStart <= nRowEnd); + ScMatrixRef pMat(new ScVectorRefMatrix(p2, nRowStart, nRowEnd - nRowStart + 1)); if (p2->IsStartFixed() && p2->IsEndFixed()) { diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx index 649e86d792db..b973fa5455f9 100644 --- a/sc/source/core/tool/scmatrix.cxx +++ b/sc/source/core/tool/scmatrix.cxx @@ -2835,6 +2835,197 @@ void ScFullMatrix::Dump() const } #endif +namespace { + +/** + * Input double array consists of segments of NaN's and normal values. + * Insert only the normal values into the matrix while skipping the NaN's. + */ +void fillMatrix( ScMatrix& rMat, size_t nCol, const double* pNums, size_t nLen ) +{ + const double* pNum = pNums; + const double* pNumEnd = pNum + nLen; + const double* pNumHead = nullptr; + for (; pNum != pNumEnd; ++pNum) + { + if (!rtl::math::isNan(*pNum)) + { + if (!pNumHead) + // Store the first non-NaN position. + pNumHead = pNum; + + continue; + } + + if (pNumHead) + { + // Flush this non-NaN segment to the matrix. + rMat.PutDouble(pNumHead, pNum - pNumHead, nCol, pNumHead - pNums); + pNumHead = nullptr; + } + } + + if (pNumHead) + { + // Flush last non-NaN segment to the matrix. + rMat.PutDouble(pNumHead, pNum - pNumHead, nCol, pNumHead - pNums); + } +} + +void flushStrSegment( + ScMatrix& rMat, size_t nCol, rtl_uString** pHead, rtl_uString** pCur, rtl_uString** pTop ) +{ + size_t nOffset = pHead - pTop; + std::vector<svl::SharedString> aStrs; + aStrs.reserve(pCur - pHead); + for (; pHead != pCur; ++pHead) + aStrs.push_back(svl::SharedString(*pHead, *pHead)); + + rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset); +} + +void fillMatrix( ScMatrix& rMat, size_t nCol, rtl_uString** pStrs, size_t nLen ) +{ + rtl_uString** p = pStrs; + rtl_uString** pEnd = p + nLen; + rtl_uString** pHead = nullptr; + for (; p != pEnd; ++p) + { + if (*p) + { + if (!pHead) + // Store the first non-empty string position. + pHead = p; + + continue; + } + + if (pHead) + { + // Flush this non-empty segment to the matrix. + flushStrSegment(rMat, nCol, pHead, p, pStrs); + pHead = nullptr; + } + } + + if (pHead) + { + // Flush last non-empty segment to the matrix. + flushStrSegment(rMat, nCol, pHead, p, pStrs); + } +} + +void fillMatrix( ScMatrix& rMat, size_t nCol, const double* pNums, rtl_uString** pStrs, size_t nLen ) +{ + if (!pStrs) + { + fillMatrix(rMat, nCol, pNums, nLen); + return; + } + + const double* pNum = pNums; + const double* pNumHead = nullptr; + rtl_uString** pStr = pStrs; + rtl_uString** pStrEnd = pStr + nLen; + rtl_uString** pStrHead = nullptr; + + for (; pStr != pStrEnd; ++pStr, ++pNum) + { + if (*pStr) + { + // String cell exists. + + if (pNumHead) + { + // Flush this numeric segment to the matrix. + rMat.PutDouble(pNumHead, pNum - pNumHead, nCol, pNumHead - pNums); + pNumHead = nullptr; + } + + if (!pStrHead) + // Store the first non-empty string position. + pStrHead = pStr; + + continue; + } + + // No string cell. Check the numeric cell value. + + if (pStrHead) + { + // Flush this non-empty string segment to the matrix. + flushStrSegment(rMat, nCol, pStrHead, pStr, pStrs); + pStrHead = nullptr; + } + + if (!rtl::math::isNan(*pNum)) + { + // Numeric cell exists. + if (!pNumHead) + // Store the first non-NaN position. + pNumHead = pNum; + + continue; + } + + // Empty cell. No action required. + } + + if (pStrHead) + { + // Flush the last non-empty segment to the matrix. + flushStrSegment(rMat, nCol, pStrHead, pStr, pStrs); + } + else if (pNumHead) + { + // Flush the last numeric segment to the matrix. + rMat.PutDouble(pNumHead, pNum - pNumHead, nCol, pNumHead - pNums); + } +} + +} // anonymous namespace + +void ScVectorRefMatrix::ensureFullMatrix() +{ + if (mpFullMatrix) + return; + + const std::vector<formula::VectorRefArray>& rArrays = mpToken->GetArrays(); + size_t nColSize = rArrays.size(); + mpFullMatrix.reset(new ScFullMatrix(nColSize, mnRowSize)); + + for (size_t nCol = 0; nCol < nColSize; ++nCol) + { + const formula::VectorRefArray& rArray = rArrays[nCol]; + if (rArray.mpStringArray) + { + if (rArray.mpNumericArray) + { + // Mixture of string and numeric values. + const double* pNums = rArray.mpNumericArray; + pNums += mnRowStart; + rtl_uString** pStrs = rArray.mpStringArray; + pStrs += mnRowStart; + fillMatrix(*mpFullMatrix, nCol, pNums, pStrs, mnRowSize); + } + else + { + // String cells only. + rtl_uString** pStrs = rArray.mpStringArray; + pStrs += mnRowStart; + fillMatrix(*mpFullMatrix, nCol, pStrs, mnRowSize); + } + } + else if (rArray.mpNumericArray) + { + // Numeric cells only. + const double* pNums = rArray.mpNumericArray; + pNums += mnRowStart; + fillMatrix(*mpFullMatrix, nCol, pNums, mnRowSize); + } + } +} + ScVectorRefMatrix::ScVectorRefMatrix(const formula::DoubleVectorRefToken* pToken, SCSIZE nRowStart, SCSIZE nRowSize) : ScMatrix() , mpToken(pToken) |