cui/source/options/optopencl.cxx | 19 cui/source/options/optopencl.hxx | 1 cui/uiconfig/ui/optopenclpage.ui | 18 officecfg/registry/schema/org/openoffice/Office/Common.xcs | 7 sc/inc/calcconfig.hxx | 1 sc/inc/scmatrix.hxx | 19 sc/source/core/data/formulacell.cxx | 3 sc/source/core/tool/calcconfig.cxx | 6 sc/source/core/tool/formulagroup.cxx | 223 ----- sc/source/core/tool/scmatrix.cxx | 511 ++++++++----- sc/source/core/tool/token.cxx | 10 11 files changed, 442 insertions(+), 376 deletions(-)
New commits: commit f55d76b8a6d9f5a218f100620da29c7ea4ed00e9 Author: Jan Holesovsky <ke...@collabora.com> Date: Mon Nov 30 12:49:02 2015 +0100 Test commit: S/W Interpreter including the UI changes. Change-Id: Ia23c360a0db1ee2c8f6bfd8b31657405d97fcd9c diff --git a/cui/source/options/optopencl.cxx b/cui/source/options/optopencl.cxx index 71cd281..db1470e 100644 --- a/cui/source/options/optopencl.cxx +++ b/cui/source/options/optopencl.cxx @@ -35,7 +35,8 @@ #include <com/sun/star/util/XChangesBatch.hpp> #include <com/sun/star/setup/UpdateCheckConfig.hpp> -#include "cuires.hrc" +#include <cuires.hrc> +#include <dialmgr.hxx> #include "optopencl.hxx" #include <svtools/treelistentry.hxx> @@ -43,6 +44,7 @@ SvxOpenCLTabPage::SvxOpenCLTabPage(vcl::Window* pParent, const SfxItemSet& rSet) SfxTabPage(pParent, "OptOpenCLPage", "cui/ui/optopenclpage.ui", &rSet), maConfig(OpenCLConfig::get()) { + get(mpUseSwInterpreter, "useswinterpreter"); get(mpUseOpenCL, "useopencl"); get(mpBlackListTable, "blacklist"); get(mpBlackListFrame,"blacklistframe"); @@ -60,6 +62,8 @@ SvxOpenCLTabPage::SvxOpenCLTabPage(vcl::Window* pParent, const SfxItemSet& rSet) get(mpVendor,"vendor"); get(mpDrvVersion,"driverversion"); + mpUseSwInterpreter->Check(officecfg::Office::Common::Misc::UseSwInterpreter::get()); + mpUseOpenCL->Check(maConfig.mbUseOpenCL); mpUseOpenCL->SetClickHdl(LINK(this, SvxOpenCLTabPage, EnableOpenCLHdl)); @@ -116,6 +120,7 @@ void SvxOpenCLTabPage::dispose() mpBlackList.disposeAndClear(); mpWhiteList.disposeAndClear(); + mpUseSwInterpreter.clear(); mpUseOpenCL.clear(); mpBlackListFrame.clear(); mpBlackListTable.clear(); @@ -146,6 +151,15 @@ bool SvxOpenCLTabPage::FillItemSet( SfxItemSet* ) bool bModified = false; std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create()); + if (mpUseSwInterpreter->IsValueChangedFromSaved()) + { + officecfg::Office::Common::Misc::UseSwInterpreter::set(mpUseSwInterpreter->IsChecked(), batch); + bModified = true; + + ScopedVclPtrInstance<MessageDialog> aWarnBox(this, CUI_RES(RID_SVXSTR_OPTIONS_RESTART), VCL_MESSAGE_INFO); + aWarnBox->Execute(); + } + if (mpUseOpenCL->IsValueChangedFromSaved()) maConfig.mbUseOpenCL = mpUseOpenCL->IsChecked(); @@ -195,6 +209,9 @@ void SvxOpenCLTabPage::Reset( const SfxItemSet* ) { maConfig = OpenCLConfig::get(); + mpUseSwInterpreter->Check(officecfg::Office::Common::Misc::UseSwInterpreter::get()); + mpUseSwInterpreter->SaveValue(); + mpUseOpenCL->Check(maConfig.mbUseOpenCL); mpUseOpenCL->SaveValue(); diff --git a/cui/source/options/optopencl.hxx b/cui/source/options/optopencl.hxx index fe91fe1..10dc30b 100644 --- a/cui/source/options/optopencl.hxx +++ b/cui/source/options/optopencl.hxx @@ -31,6 +31,7 @@ class SvxOpenCLTabPage : public SfxTabPage private: OpenCLConfig maConfig; + VclPtr<CheckBox> mpUseSwInterpreter; VclPtr<CheckBox> mpUseOpenCL; VclPtr<VclFrame> mpBlackListFrame; diff --git a/cui/uiconfig/ui/optopenclpage.ui b/cui/uiconfig/ui/optopenclpage.ui index 89ac882..2cad763 100644 --- a/cui/uiconfig/ui/optopenclpage.ui +++ b/cui/uiconfig/ui/optopenclpage.ui @@ -26,6 +26,22 @@ <property name="orientation">vertical</property> <property name="spacing">12</property> <child> + <object class="GtkCheckButton" id="useswinterpreter"> + <property name="label" translatable="yes">Allow use of Software Interpreter (even when OpenCL is not available)</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> <object class="GtkCheckButton" id="useopencl"> <property name="label" translatable="yes">Allow use of OpenCL</property> <property name="visible">True</property> @@ -38,7 +54,7 @@ <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">0</property> + <property name="position">1</property> </packing> </child> <child> diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs index d693fc7..800ac71 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs @@ -5642,6 +5642,13 @@ </info> <value oor:separator=";">Linux//Advanced Micro Devices, Inc\.//1445\.5 \(sse2,avx\);//Advanced Micro Devices, Inc\.//;//Intel\(R\) Corporation//;//NVIDIA Corporation//</value> </prop> + <prop oor:name="UseSwInterpreter" oor:type="xs:boolean" oor:nillable="false"> + <info> + <desc>Determines whether Software Interpreter can be used to speed + up some operations on Calc formulas.</desc> + </info> + <value>true</value> + </prop> <prop oor:name="MacroRecorderMode" oor:type="xs:boolean" oor:nillable="false"> <info> <desc>Determines if the limited, and awkward code producing diff --git a/sc/inc/calcconfig.hxx b/sc/inc/calcconfig.hxx index ec355cf..eaf4f36 100644 --- a/sc/inc/calcconfig.hxx +++ b/sc/inc/calcconfig.hxx @@ -49,6 +49,7 @@ struct SC_DLLPUBLIC ScCalcConfig bool mbHasStringRefSyntax:1; static bool isOpenCLEnabled(); + static bool isSwInterpreterEnabled(); bool mbOpenCLSubsetOnly:1; bool mbOpenCLAutoSelect:1; diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx index a6c6d96..1cea9c9 100644 --- a/sc/inc/scmatrix.hxx +++ b/sc/inc/scmatrix.hxx @@ -409,9 +409,6 @@ class SC_DLLPUBLIC ScFullMatrix : public ScMatrix 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/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 66c0c40..1e3f740 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -3879,6 +3879,9 @@ bool ScFormulaCell::InterpretFormulaGroup() return false; } + if (!ScCalcConfig::isOpenCLEnabled() && !ScCalcConfig::isSwInterpreterEnabled()) + return false; + // TODO : Disable invariant formula group interpretation for now in order // to get implicit intersection to work. if (mxGroup->mbInvariant && false) diff --git a/sc/source/core/tool/calcconfig.cxx b/sc/source/core/tool/calcconfig.cxx index f285e13..96277ce 100644 --- a/sc/source/core/tool/calcconfig.cxx +++ b/sc/source/core/tool/calcconfig.cxx @@ -38,6 +38,12 @@ bool ScCalcConfig::isOpenCLEnabled() return gOpenCLEnabled.get(); } +bool ScCalcConfig::isSwInterpreterEnabled() +{ + static comphelper::ConfigurationListenerProperty<bool> gSwInterpreterEnabled(getMiscListener(), OUString("UseSwInterpreter")); + return gSwInterpreterEnabled.get(); +} + ScCalcConfig::ScCalcConfig() : meStringRefAddressSyntax(formula::FormulaGrammar::CONV_UNSPECIFIED), meStringConversion(StringConversion::LOCALE), // old LibreOffice behavior diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index 4369623..554aa48 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() {} @@ -369,8 +219,6 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres case formula::svDoubleVectorRef: { const formula::DoubleVectorRefToken* p2 = static_cast<const formula::DoubleVectorRefToken*>(p); - //const std::vector<formula::VectorRefArray>& rArrays = p2->GetArrays(); - //size_t nColSize = rArrays.size(); size_t nRowStart = p2->IsStartFixed() ? 0 : i; size_t nRowEnd = p2->GetRefRowSize() - 1; if (!p2->IsEndFixed()) @@ -379,50 +227,6 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres assert(nRowStart <= nRowEnd); ScMatrixRef pMat(new ScVectorRefMatrix(p2, nRowStart, nRowEnd - nRowStart + 1)); - /* - size_t nRowSize = nRowEnd - nRowStart + 1; - ScMatrixRef pMat(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()) { // Cached the converted token for absolute range reference. @@ -477,13 +281,14 @@ FormulaGroupInterpreter *FormulaGroupInterpreter::getStatic() if ( !msInstance ) { #if HAVE_FEATURE_OPENCL - const ScCalcConfig& rConfig = ScInterpreter::GetGlobalConfig(); if (ScCalcConfig::isOpenCLEnabled()) + { + const ScCalcConfig& rConfig = ScInterpreter::GetGlobalConfig(); switchOpenCLDevice(rConfig.maOpenCLDevice, rConfig.mbOpenCLAutoSelect); + } #endif - static bool bAllowSoftwareInterpreter = true; - if ( !msInstance && bAllowSoftwareInterpreter ) // software fallback + if (!msInstance && ScCalcConfig::isSwInterpreterEnabled()) // software interpreter { SAL_INFO("sc.formulagroup", "Create S/W interpreter"); msInstance = new sc::FormulaGroupInterpreterSoftware(); @@ -505,20 +310,26 @@ void FormulaGroupInterpreter::fillOpenCLInfo(std::vector<OpenCLPlatformInfo>& rP bool FormulaGroupInterpreter::switchOpenCLDevice(const OUString& rDeviceId, bool bAutoSelect, bool bForceEvaluation) { bool bOpenCLEnabled = ScCalcConfig::isOpenCLEnabled(); - static bool bAllowSoftwareInterpreter = true; - if (!bOpenCLEnabled || (bAllowSoftwareInterpreter && rDeviceId == OPENCL_SOFTWARE_DEVICE_CONFIG_NAME)) + if (!bOpenCLEnabled || (rDeviceId == OPENCL_SOFTWARE_DEVICE_CONFIG_NAME)) { - if(msInstance) + bool bSwInterpreterEnabled = ScCalcConfig::isSwInterpreterEnabled(); + if (msInstance) { // if we already have a software interpreter don't delete it - if(dynamic_cast<sc::FormulaGroupInterpreterSoftware*>(msInstance)) + if (bSwInterpreterEnabled && dynamic_cast<sc::FormulaGroupInterpreterSoftware*>(msInstance)) return true; delete msInstance; + msInstance = nullptr; } - msInstance = new sc::FormulaGroupInterpreterSoftware(); - return true; + if (bSwInterpreterEnabled) + { + msInstance = new sc::FormulaGroupInterpreterSoftware(); + return true; + } + + return false; } bool bSuccess = ::opencl::switchOpenCLDevice(&rDeviceId, bAutoSelect, bForceEvaluation); if(!bSuccess) @@ -527,7 +338,7 @@ bool FormulaGroupInterpreter::switchOpenCLDevice(const OUString& rDeviceId, bool delete msInstance; msInstance = nullptr; - if (ScCalcConfig::isOpenCLEnabled()) + if (bOpenCLEnabled) { msInstance = new sc::opencl::FormulaGroupInterpreterOpenCL(); return msInstance != nullptr; diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx index aa86383..1d38318 100644 --- a/sc/source/core/tool/scmatrix.cxx +++ b/sc/source/core/tool/scmatrix.cxx @@ -1005,7 +1005,6 @@ class WalkElementBlocks bool mbFirst:1; bool mbTextAsZero:1; public: - // TODO add here also the beginning of the iteration WalkElementBlocks(bool bTextAsZero) : maRes(_Op::InitVal, _Op::InitVal, 0), mbFirst(true), mbTextAsZero(bTextAsZero) {} const ScMatrix::IterateResult& getResult() const { return maRes; } @@ -1018,8 +1017,6 @@ public: { typedef MatrixImplType::numeric_block_type block_type; - // TODO do here the same thing as Michael / Quikee did in - // interpr6.cxx - see NumericCellAccumulator block_type::const_iterator it = block_type::begin(*node.data); block_type::const_iterator itEnd = block_type::end(*node.data); for (; it != itEnd; ++it) @@ -2839,6 +2836,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) @@ -2853,282 +3041,350 @@ ScVectorRefMatrix::~ScVectorRefMatrix() ScMatrix* ScVectorRefMatrix::Clone() const { - throw std::runtime_error("ScVectorRefMatrix::Clone() called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->Clone(); } void ScVectorRefMatrix::Resize(SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::Resize called"); + ensureFullMatrix(); + mpFullMatrix->Resize(nC, nR); } void ScVectorRefMatrix::Resize(SCSIZE nC, SCSIZE nR, double fVal) { - throw std::runtime_error("ScVectorRefMatrix::Resize called"); + ensureFullMatrix(); + mpFullMatrix->Resize(nC, nR, fVal); } ScMatrix* ScVectorRefMatrix::CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const { - throw std::runtime_error("ScVectorRefMatrix::CloneAndExtend called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->CloneAndExtend(nNewCols, nNewRows); } void ScVectorRefMatrix::SetErrorInterpreter(ScInterpreter* p) { + if (mpFullMatrix) + { + mpFullMatrix->SetErrorInterpreter(p); + return; + } + mpErrorInterpreter = p; } void ScVectorRefMatrix::GetDimensions(SCSIZE& rC, SCSIZE& rR) const { + if (mpFullMatrix) + { + mpFullMatrix->GetDimensions(rC, rR); + return; + } + rC = mpToken->GetArrays().size(); rR = mnRowSize; } SCSIZE ScVectorRefMatrix::GetElementCount() const { - throw std::runtime_error("ScVectorRefMatrix::GetElementCount called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->GetElementCount(); } bool ScVectorRefMatrix::ValidColRow(SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::ValidColRow called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->ValidColRow(nC, nR); } bool ScVectorRefMatrix::ValidColRowReplicated(SCSIZE & rC, SCSIZE & rR) const { - throw std::runtime_error("ScVectorRefMatrix::ValidColRowReplicated called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->ValidColRowReplicated(rC, rR); } bool ScVectorRefMatrix::ValidColRowOrReplicated(SCSIZE & rC, SCSIZE & rR) const { - throw std::runtime_error("ScVectorRefMatrix::ValidColRowOrReplicated called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->ValidColRowOrReplicated(rC, rR); } void ScVectorRefMatrix::PutDouble(double fVal, SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::PutDouble called"); + ensureFullMatrix(); + mpFullMatrix->PutDouble(fVal, nC, nR); } void ScVectorRefMatrix::PutDouble(double fVal, SCSIZE nIndex) { - throw std::runtime_error("ScVectorRefMatrix::PutDouble called"); + ensureFullMatrix(); + mpFullMatrix->PutDouble(fVal, nIndex); } void ScVectorRefMatrix::PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::PutDouble called"); + ensureFullMatrix(); + mpFullMatrix->PutDouble(pArray, nLen, nC, nR); } void ScVectorRefMatrix::PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::PutString called"); + ensureFullMatrix(); + mpFullMatrix->PutString(rStr, nC, nR); } void ScVectorRefMatrix::PutString(const svl::SharedString& rStr, SCSIZE nIndex) { - throw std::runtime_error("ScVectorRefMatrix::PutString called"); + ensureFullMatrix(); + mpFullMatrix->PutString(rStr, nIndex); } void ScVectorRefMatrix::PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::PutString called"); + ensureFullMatrix(); + mpFullMatrix->PutString(pArray, nLen, nC, nR); } void ScVectorRefMatrix::PutEmpty(SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::PutEmpty called"); + ensureFullMatrix(); + mpFullMatrix->PutEmpty(nC, nR); } void ScVectorRefMatrix::PutEmptyPath(SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::PutEmptyPath called"); + ensureFullMatrix(); + mpFullMatrix->PutEmptyPath(nC, nR); } void ScVectorRefMatrix::PutError(sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::PutError called"); + ensureFullMatrix(); + mpFullMatrix->PutError(nErrorCode, nC, nR); } void ScVectorRefMatrix::PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::PutBoolean called"); + ensureFullMatrix(); + mpFullMatrix->PutBoolean(bVal, nC, nR); } void ScVectorRefMatrix::FillDouble(double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2) { - throw std::runtime_error("ScVectorRefMatrix::FillDouble called"); + ensureFullMatrix(); + mpFullMatrix->FillDouble(fVal, nC1, nR1, nC2, nR2); } void ScVectorRefMatrix::PutDoubleVector(const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::PutDoubleVector called"); + ensureFullMatrix(); + mpFullMatrix->PutDoubleVector(rVec, nC, nR); } void ScVectorRefMatrix::PutStringVector(const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::PutStringVector called"); + ensureFullMatrix(); + mpFullMatrix->PutStringVector(rVec, nC, nR); } void ScVectorRefMatrix::PutEmptyVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::PutEmptyVector called"); + ensureFullMatrix(); + mpFullMatrix->PutEmptyVector(nCount, nC, nR); } void ScVectorRefMatrix::PutEmptyResultVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::PutEmptyResultVector called"); + ensureFullMatrix(); + mpFullMatrix->PutEmptyResultVector(nCount, nC, nR); } void ScVectorRefMatrix::PutEmptyPathVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR) { - throw std::runtime_error("ScVectorRefMatrix::PutEmptyPathVector called"); + ensureFullMatrix(); + mpFullMatrix->PutEmptyPathVector(nCount, nC, nR); } sal_uInt16 ScVectorRefMatrix::GetError(SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::GetError called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->GetError(nC, nR); } double ScVectorRefMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::GetDouble called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->GetDouble(nC, nR); } double ScVectorRefMatrix::GetDouble(SCSIZE nIndex) const { - throw std::runtime_error("ScVectorRefMatrix::GetDouble called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->GetDouble(nIndex); } svl::SharedString ScVectorRefMatrix::GetString(SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::GetString called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->GetString(nC, nR); } svl::SharedString ScVectorRefMatrix::GetString(SCSIZE nIndex) const { - throw std::runtime_error("ScVectorRefMatrix::GetString called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->GetString(nIndex); } svl::SharedString ScVectorRefMatrix::GetString(SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::GetString called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->GetString(rFormatter, nC, nR); } ScMatrixValue ScVectorRefMatrix::Get(SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::Get called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->Get(nC, nR); } bool ScVectorRefMatrix::IsString(SCSIZE nIndex) const { - throw std::runtime_error("ScVectorRefMatrix::IsString called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->IsString(nIndex); } bool ScVectorRefMatrix::IsString(SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::IsString called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->IsString(nC, nR); } bool ScVectorRefMatrix::IsEmpty(SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::IsEmpty called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->IsEmpty(nC, nR); } bool ScVectorRefMatrix::IsEmptyCell(SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::IsEmptyCell called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->IsEmptyCell(nC, nR); } bool ScVectorRefMatrix::IsEmptyResult(SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::IsEmptyResult called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->IsEmptyResult(nC, nR); } bool ScVectorRefMatrix::IsEmptyPath(SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::IsEmptyPath called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->IsEmptyPath(nC, nR); } bool ScVectorRefMatrix::IsValue(SCSIZE nIndex) const { - throw std::runtime_error("ScVectorRefMatrix::IsValue called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->IsValue(nIndex); } bool ScVectorRefMatrix::IsValue(SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::IsValue called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->IsValue(nC, nR); } bool ScVectorRefMatrix::IsValueOrEmpty(SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::IsValueOrEmpty called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->IsValueOrEmpty(nC, nR); } bool ScVectorRefMatrix::IsBoolean(SCSIZE nC, SCSIZE nR) const { - throw std::runtime_error("ScVectorRefMatrix::IsBoolean called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->IsBoolean(nC, nR); } bool ScVectorRefMatrix::IsNumeric() const { - throw std::runtime_error("ScVectorRefMatrix::IsNumeric called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->IsNumeric(); } void ScVectorRefMatrix::MatTrans(ScMatrix& mRes) const { - throw std::runtime_error("ScVectorRefMatrix::MatTrans called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + mpFullMatrix->MatTrans(mRes); } void ScVectorRefMatrix::MatCopy(ScMatrix& mRes) const { - throw std::runtime_error("ScVectorRefMatrix::MatCopy called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + mpFullMatrix->MatCopy(mRes); } void ScVectorRefMatrix::CompareEqual() { - throw std::runtime_error("ScVectorRefMatrix::CompareEqual called"); + ensureFullMatrix(); + mpFullMatrix->CompareEqual(); } void ScVectorRefMatrix::CompareNotEqual() { - throw std::runtime_error("ScVectorRefMatrix::CompareNotEqual called"); + ensureFullMatrix(); + mpFullMatrix->CompareNotEqual(); } void ScVectorRefMatrix::CompareLess() { - throw std::runtime_error("ScVectorRefMatrix::CompareLess called"); + ensureFullMatrix(); + mpFullMatrix->CompareLess(); } void ScVectorRefMatrix::CompareGreater() { - throw std::runtime_error("ScVectorRefMatrix::CompareGreater called"); + ensureFullMatrix(); + mpFullMatrix->CompareGreater(); } void ScVectorRefMatrix::CompareLessEqual() { - throw std::runtime_error("ScVectorRefMatrix::CompareLessEqual called"); + ensureFullMatrix(); + mpFullMatrix->CompareLessEqual(); } void ScVectorRefMatrix::CompareGreaterEqual() { - throw std::runtime_error("ScVectorRefMatrix::CompareGreaterEqual called"); + ensureFullMatrix(); + mpFullMatrix->CompareGreaterEqual(); } double ScVectorRefMatrix::And() const { - throw std::runtime_error("ScVectorRefMatrix::And called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->And(); } double ScVectorRefMatrix::Or() const { - throw std::runtime_error("ScVectorRefMatrix::Or called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->Or(); } double ScVectorRefMatrix::Xor() const { - throw std::runtime_error("ScVectorRefMatrix::Xor called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->Xor(); } ScMatrix::IterateResult ScVectorRefMatrix::Sum(bool bTextAsZero) const { + if (mpFullMatrix) + return mpFullMatrix->Sum(bTextAsZero); + const std::vector<formula::VectorRefArray>& rArrays = mpToken->GetArrays(); size_t nDataSize = mnRowSize; @@ -3147,7 +3403,9 @@ ScMatrix::IterateResult ScVectorRefMatrix::Sum(bool bTextAsZero) const { if (rArray.mpStringArray) { - throw std::runtime_error("ScVectorRefMatrix::Sum - string array"); + // FIXME operate directly on the array too + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->Sum(bTextAsZero); } else if (rArray.mpNumericArray) { @@ -3182,177 +3440,110 @@ ScMatrix::IterateResult ScVectorRefMatrix::Sum(bool bTextAsZero) const ScMatrix::IterateResult ScVectorRefMatrix::SumSquare(bool bTextAsZero) const { - throw std::runtime_error("ScVectorRefMatrix::SumSquare called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->SumSquare(bTextAsZero); } ScMatrix::IterateResult ScVectorRefMatrix::Product(bool bTextAsZero) const { - throw std::runtime_error("ScVectorRefMatrix::Product called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->Product(bTextAsZero); } size_t ScVectorRefMatrix::Count(bool bCountStrings) const { - throw std::runtime_error("ScVectorRefMatrix::Count called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->Count(bCountStrings); } size_t ScVectorRefMatrix::MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const { - throw std::runtime_error("ScVectorRefMatrix::MatchDoubleInColumns called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->MatchDoubleInColumns(fValue, nCol1, nCol2); } size_t ScVectorRefMatrix::MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const { - throw std::runtime_error("ScVectorRefMatrix::MatchStringInColumns called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->MatchStringInColumns(rStr, nCol1, nCol2); } double ScVectorRefMatrix::GetMaxValue(bool bTextAsZero) const { - throw std::runtime_error("ScVectorRefMatrix::GetMaxValue called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->GetMaxValue(bTextAsZero); } double ScVectorRefMatrix::GetMinValue(bool bTextAsZero) const { - throw std::runtime_error("ScVectorRefMatrix::GetMinValue called"); + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->GetMinValue(bTextAsZero); } ScMatrixRef ScVectorRefMatrix::CompareMatrix(sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions) const { - throw std::runtime_error("ScVectorRefMatrix::CompareMatrix called"); -#if 0 - // TODO FIXME - return ScMatrixRef(new ScFullMatrix(mpToken->GetArrays().size(), mnRowSize)); -#endif + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + return mpFullMatrix->CompareMatrix(rComp, nMatPos, pOptions); } void ScVectorRefMatrix::GetDoubleArray(std::vector<double>& rVector, bool bEmptyAsZero) const { - throw std::runtime_error("ScVectorRefMatrix::GetDoubleArray called"); -#if 0 - const std::vector<formula::VectorRefArray>& rArrays = mpToken->GetArrays(); - size_t nDataSize = mnRowSize; - - if (mnRowStart >= mpToken->GetRefRowSize()) - { - return; - } - else if (nDataSize > mpToken->GetRefRowSize() + mnRowStart) - { - nDataSize = mpToken->GetRefRowSize() - mnRowStart; - } - - rVector.resize(rArrays.size()*nDataSize); - std::vector<double>::iterator it = rVector.begin(); - - for (const formula::VectorRefArray& rArray : rArrays) - { - if (rArray.mpStringArray) - { - // TODO FIXME - std::fill(rVector.begin(), rVector.end(), 0.0); - //throw std::runtime_error("ScVectorRefMatrix::GetDoubleArray - string array"); - } - else if (rArray.mpNumericArray) - { - // Numeric cells only. - const double* p = rArray.mpNumericArray + mnRowStart; - - // append to the array - rVector.insert(rVector.end(), p, p + nDataSize); - } - } -#endif + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + mpFullMatrix->GetDoubleArray(rVector, bEmptyAsZero); } void ScVectorRefMatrix::MergeDoubleArray(std::vector<double>& rVector, Op eOp) const { - throw std::runtime_error("ScVectorRefMatrix::MergeDoubleArray called"); -#if 0 - if (mnRowSize*mpToken->GetArrays().size() != rVector.size()) - return; - - const std::vector<formula::VectorRefArray>& rArrays = mpToken->GetArrays(); - size_t nDataSize = mnRowSize; - - if (mnRowStart >= mpToken->GetRefRowSize()) - { - return; - } - else if (nDataSize > mpToken->GetRefRowSize() + mnRowStart) - { - nDataSize = mpToken->GetRefRowSize() - mnRowStart; - } - - std::vector<double>::iterator it = rVector.begin(); - - switch (eOp) - { - case ScFullMatrix::Mul: - { - for (const formula::VectorRefArray& rArray : rArrays) - { - if (rArray.mpStringArray) - { - throw std::runtime_error("ScVectorRefMatrix::MergeDoubleArray - string array"); - } - else if (rArray.mpNumericArray) - { - // Numeric cells only. - const double* p = rArray.mpNumericArray + mnRowStart; - - for (size_t nSize = nDataSize; nSize > 0; --nSize) - { - *it *= (*p); - ++it; - ++p; - } - } - } - } - break; - default: - ; - } -#endif + const_cast<ScVectorRefMatrix*>(this)->ensureFullMatrix(); + mpFullMatrix->MergeDoubleArray(rVector, eOp); } void ScVectorRefMatrix::NotOp(ScMatrix& rMat) { - throw std::runtime_error("ScVectorRefMatrix::NotOp called"); + ensureFullMatrix(); + mpFullMatrix->NotOp(rMat); } void ScVectorRefMatrix::NegOp(ScMatrix& rMat) { - throw std::runtime_error("ScVectorRefMatrix::NegOp called"); + ensureFullMatrix(); + mpFullMatrix->NegOp(rMat); } void ScVectorRefMatrix::AddOp(double fVal, ScMatrix& rMat) { - throw std::runtime_error("ScVectorRefMatrix::AddOp called"); + ensureFullMatrix(); + mpFullMatrix->AddOp(fVal, rMat); } void ScVectorRefMatrix::SubOp(bool bFlag, double fVal, ScMatrix& rMat) { - throw std::runtime_error("ScVectorRefMatrix::SubOp called"); + ensureFullMatrix(); + mpFullMatrix->SubOp(bFlag, fVal, rMat); } void ScVectorRefMatrix::MulOp(double fVal, ScMatrix& rMat) { - throw std::runtime_error("ScVectorRefMatrix::MulOp called"); + ensureFullMatrix(); + mpFullMatrix->MulOp(fVal, rMat); } void ScVectorRefMatrix::DivOp(bool bFlag, double fVal, ScMatrix& rMat) { - throw std::runtime_error("ScVectorRefMatrix::DivOp called"); + ensureFullMatrix(); + mpFullMatrix->DivOp(bFlag, fVal, rMat); } void ScVectorRefMatrix::PowOp(bool bFlag, double fVal, ScMatrix& rMat) { - throw std::runtime_error("ScVectorRefMatrix::PowOp called"); + ensureFullMatrix(); + mpFullMatrix->PowOp(bFlag, fVal, rMat); } std::vector<ScMatrix::IterateResult> ScVectorRefMatrix::Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp) { - throw std::runtime_error("ScVectorRefMatrix::Collect called"); + ensureFullMatrix(); + return mpFullMatrix->Collect(bTextAsZero, aOp); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index e97ef65..39fd0db 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -32,6 +32,7 @@ #include "compiler.hxx" #include "interpre.hxx" #include <formula/compiler.hrc> +#include <formulagroup.hxx> #include "rechead.hxx" #include "parclass.hxx" #include "jumpmatrix.hxx" @@ -1321,7 +1322,9 @@ void ScTokenArray::CheckToken( const FormulaToken& r ) return; } - if (!ScCalcConfig::isOpenCLEnabled() && ScInterpreter::GetGlobalConfig().mpSwInterpreterSubsetOpCodes->find(eOp) == ScInterpreter::GetGlobalConfig().mpSwInterpreterSubsetOpCodes->end()) + // test for OpenCL interpreter first - the assumption is that S/W + // interpreter blacklist is more strict than the OpenCL one + if (ScCalcConfig::isSwInterpreterEnabled() && (dynamic_cast<sc::FormulaGroupInterpreterSoftware*>(sc::FormulaGroupInterpreter::getStatic()) != nullptr) && ScInterpreter::GetGlobalConfig().mpSwInterpreterSubsetOpCodes->find(eOp) == ScInterpreter::GetGlobalConfig().mpSwInterpreterSubsetOpCodes->end()) { meVectorState = FormulaVectorDisabled; return; @@ -1568,9 +1571,12 @@ void ScTokenArray::CheckToken( const FormulaToken& r ) return; } + // only when openCL interpreter is not enabled - the assumption is that + // the S/W interpreter blacklist is more strict if (eOp >= SC_OPCODE_START_BIN_OP && eOp <= SC_OPCODE_STOP_UN_OP && - !ScCalcConfig::isOpenCLEnabled() && + ScCalcConfig::isSwInterpreterEnabled() && + (dynamic_cast<sc::FormulaGroupInterpreterSoftware*>(sc::FormulaGroupInterpreter::getStatic()) != nullptr) && ScInterpreter::GetGlobalConfig().mpSwInterpreterSubsetOpCodes->find(eOp) == ScInterpreter::GetGlobalConfig().mpSwInterpreterSubsetOpCodes->end()) { meVectorState = FormulaVectorDisabled; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits