Kaydet (Commit) d4daad18 authored tarafından Jan Holesovsky's avatar Jan Holesovsky

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
üst bd8a89f2
...@@ -409,9 +409,6 @@ class SC_DLLPUBLIC ScFullMatrix : public ScMatrix ...@@ -409,9 +409,6 @@ class SC_DLLPUBLIC ScFullMatrix : public ScMatrix
std::unique_ptr<ScMatrixImpl> pImpl; std::unique_ptr<ScMatrixImpl> pImpl;
// only delete via Delete()
virtual ~ScFullMatrix();
ScFullMatrix( const ScFullMatrix& ) = delete; ScFullMatrix( const ScFullMatrix& ) = delete;
ScFullMatrix& operator=( const ScFullMatrix&) = delete; ScFullMatrix& operator=( const ScFullMatrix&) = delete;
...@@ -422,6 +419,8 @@ public: ...@@ -422,6 +419,8 @@ public:
ScFullMatrix( size_t nC, size_t nR, const std::vector<double>& rInitVals ); ScFullMatrix( size_t nC, size_t nR, const std::vector<double>& rInitVals );
virtual ~ScFullMatrix();
/** Clone the matrix. */ /** Clone the matrix. */
virtual ScMatrix* Clone() const override; virtual ScMatrix* Clone() const override;
...@@ -611,19 +610,27 @@ class SC_DLLPUBLIC ScVectorRefMatrix : public ScMatrix ...@@ -611,19 +610,27 @@ class SC_DLLPUBLIC ScVectorRefMatrix : public ScMatrix
const formula::DoubleVectorRefToken* mpToken; const formula::DoubleVectorRefToken* mpToken;
ScInterpreter* mpErrorInterpreter; 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 mnRowStart;
SCSIZE mnRowSize; SCSIZE mnRowSize;
// only delete via Delete()
virtual ~ScVectorRefMatrix();
ScVectorRefMatrix( const ScVectorRefMatrix& ) = delete; ScVectorRefMatrix( const ScVectorRefMatrix& ) = delete;
ScVectorRefMatrix& operator=( 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: public:
ScVectorRefMatrix(const formula::DoubleVectorRefToken* pToken, SCSIZE nRowStart, SCSIZE nRowSize); ScVectorRefMatrix(const formula::DoubleVectorRefToken* pToken, SCSIZE nRowStart, SCSIZE nRowSize);
virtual ~ScVectorRefMatrix();
/** Clone the matrix. */ /** Clone the matrix. */
virtual ScMatrix* Clone() const override; virtual ScMatrix* Clone() const override;
......
...@@ -138,156 +138,6 @@ FormulaGroupContext::~FormulaGroupContext() ...@@ -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() {}
CompiledFormula::~CompiledFormula() {} CompiledFormula::~CompiledFormula() {}
...@@ -374,58 +224,8 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres ...@@ -374,58 +224,8 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
if (!p2->IsEndFixed()) if (!p2->IsEndFixed())
nRowEnd += i; nRowEnd += i;
ScMatrixRef pMat;
if (ScCalcConfig::isSwInterpreterEnabled())
{
assert(nRowStart <= nRowEnd); assert(nRowStart <= nRowEnd);
pMat.reset(new ScVectorRefMatrix(p2, nRowStart, nRowEnd - nRowStart + 1)); ScMatrixRef pMat(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);
}
}
}
if (p2->IsStartFixed() && p2->IsEndFixed()) if (p2->IsStartFixed() && p2->IsEndFixed())
{ {
......
...@@ -2835,6 +2835,197 @@ void ScFullMatrix::Dump() const ...@@ -2835,6 +2835,197 @@ void ScFullMatrix::Dump() const
} }
#endif #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) ScVectorRefMatrix::ScVectorRefMatrix(const formula::DoubleVectorRefToken* pToken, SCSIZE nRowStart, SCSIZE nRowSize)
: ScMatrix() : ScMatrix()
, mpToken(pToken) , mpToken(pToken)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment