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

Reply via email to