summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Holesovsky <kendy@collabora.com>2015-11-30 10:28:43 +0100
committerJan Holesovsky <kendy@collabora.com>2015-12-01 16:40:45 +0100
commitd4daad185e9583bedbb5a4eef1fd53e1f22e219b (patch)
tree993de32421d2b74f1375f4a63e3323003613ba0f
parentbd8a89f208c71e51921d5f090179b99b45cc0a5f (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.hxx19
-rw-r--r--sc/source/core/tool/formulagroup.cxx204
-rw-r--r--sc/source/core/tool/scmatrix.cxx191
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)