summaryrefslogtreecommitdiff
path: root/sc/source
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 17:55:21 +0100
commitdb988063977e8a17f3db4b726cb783ae8d33b62b (patch)
treed1e13bacc28a923c99d0a6a8fb4b493d746b7fa9 /sc/source
parentd4afaa726ccc6dc622d1a7065aa21f710430657d (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
Diffstat (limited to 'sc/source')
-rw-r--r--sc/source/core/tool/formulagroup.cxx204
-rw-r--r--sc/source/core/tool/scmatrix.cxx191
2 files changed, 193 insertions, 202 deletions
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)