[Libreoffice-commits] core.git: 3 commits - sc/inc sc/qa sc/source

Jan Holesovsky kendy at collabora.com
Tue Nov 24 08:42:12 PST 2015


 sc/inc/calcconfig.hxx                       |    1 
 sc/inc/scmatrix.hxx                         |  587 +++++++++++++++++++----
 sc/qa/unit/ucalc.cxx                        |   16 
 sc/source/core/data/table1.cxx              |    2 
 sc/source/core/data/validat.cxx             |    2 
 sc/source/core/inc/arraysumfunctor.hxx      |    1 
 sc/source/core/tool/addincol.cxx            |    6 
 sc/source/core/tool/calcconfig.cxx          |   11 
 sc/source/core/tool/ddelink.cxx             |    4 
 sc/source/core/tool/formulagroup.cxx        |   80 +--
 sc/source/core/tool/interpr1.cxx            |    6 
 sc/source/core/tool/interpr5.cxx            |   10 
 sc/source/core/tool/jumpmatrix.cxx          |    2 
 sc/source/core/tool/rangeseq.cxx            |    2 
 sc/source/core/tool/scmatrix.cxx            |  695 +++++++++++++++++++++++-----
 sc/source/core/tool/token.cxx               |   18 
 sc/source/filter/excel/tokstack.cxx         |    2 
 sc/source/filter/excel/xihelper.cxx         |    2 
 sc/source/filter/excel/xilink.cxx           |    2 
 sc/source/filter/inc/xihelper.hxx           |    2 
 sc/source/filter/xml/XMLDDELinksContext.cxx |    2 
 sc/source/filter/xml/xmlcelli.cxx           |    2 
 sc/source/ui/docshell/externalrefmgr.cxx    |    6 
 23 files changed, 1180 insertions(+), 281 deletions(-)

New commits:
commit a81de86c47322bd6bc59b462eb2f69e0f1185df4
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Tue Nov 24 17:13:21 2015 +0100

    sc: Implement Software Interpreter subsetting, similarly to openCL one.
    
    And add only the minimum amount of operations we are sure about.
    
    Change-Id: I0dd35968206161e31fcd8bfd0b647329c703e0da

diff --git a/sc/inc/calcconfig.hxx b/sc/inc/calcconfig.hxx
index 4091bda..ec355cf 100644
--- a/sc/inc/calcconfig.hxx
+++ b/sc/inc/calcconfig.hxx
@@ -58,6 +58,7 @@ struct SC_DLLPUBLIC ScCalcConfig
     typedef std::shared_ptr<std::set<OpCode>> OpCodeSet;
 
     OpCodeSet mpOpenCLSubsetOpCodes;
+    OpCodeSet mpSwInterpreterSubsetOpCodes;
 
     ScCalcConfig();
 
diff --git a/sc/source/core/tool/calcconfig.cxx b/sc/source/core/tool/calcconfig.cxx
index 20d5530..f285e13 100644
--- a/sc/source/core/tool/calcconfig.cxx
+++ b/sc/source/core/tool/calcconfig.cxx
@@ -86,6 +86,15 @@ void ScCalcConfig::setOpenCLConfigToDefault()
         ocSlope,
         ocSumIfs}));
 
+    // opcodes that are known to work well with the software interpreter
+    static OpCodeSet pDefaultSwInterpreterSubsetOpCodes(new std::set<OpCode>({
+        ocAdd,
+        ocSub,
+        ocMul,
+        ocDiv,
+        ocSum,
+        ocProduct}));
+
     // Note that these defaults better be kept in sync with those in
     // officecfg/registry/schema/org/openoffice/Office/Calc.xcs.
     // Crazy.
@@ -93,6 +102,7 @@ void ScCalcConfig::setOpenCLConfigToDefault()
     mbOpenCLAutoSelect = true;
     mnOpenCLMinimumFormulaGroupSize = 100;
     mpOpenCLSubsetOpCodes = pDefaultOpenCLSubsetOpCodes;
+    mpSwInterpreterSubsetOpCodes = pDefaultSwInterpreterSubsetOpCodes;
 }
 
 void ScCalcConfig::reset()
@@ -127,6 +137,7 @@ bool ScCalcConfig::operator== (const ScCalcConfig& r) const
            maOpenCLDevice == r.maOpenCLDevice &&
            mnOpenCLMinimumFormulaGroupSize == r.mnOpenCLMinimumFormulaGroupSize &&
            *mpOpenCLSubsetOpCodes == *r.mpOpenCLSubsetOpCodes &&
+           *mpSwInterpreterSubsetOpCodes == *r.mpSwInterpreterSubsetOpCodes &&
            true;
 }
 
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 3f978c4..138e087 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -1319,6 +1319,12 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
             return;
         }
 
+        if (!ScCalcConfig::isOpenCLEnabled() && getenv("SC_ALLOW_SOFTWARE_INTERPRETER") != nullptr && ScInterpreter::GetGlobalConfig().mpSwInterpreterSubsetOpCodes->find(eOp) == ScInterpreter::GetGlobalConfig().mpSwInterpreterSubsetOpCodes->end())
+        {
+            meVectorState = FormulaVectorDisabled;
+            return;
+        }
+
         // We support vectorization for the following opcodes.
         switch (eOp)
         {
@@ -1559,6 +1565,16 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
         meVectorState = FormulaVectorDisabled;
         return;
     }
+
+    if (eOp >= SC_OPCODE_START_BIN_OP &&
+        eOp <= SC_OPCODE_STOP_UN_OP &&
+        !ScCalcConfig::isOpenCLEnabled() &&
+        getenv("SC_ALLOW_SOFTWARE_INTERPRETER") != nullptr &&
+        ScInterpreter::GetGlobalConfig().mpSwInterpreterSubsetOpCodes->find(eOp) == ScInterpreter::GetGlobalConfig().mpSwInterpreterSubsetOpCodes->end())
+    {
+        meVectorState = FormulaVectorDisabled;
+        return;
+    }
 }
 
 bool ScTokenArray::ImplGetReference( ScRange& rRange, const ScAddress& rPos, bool bValidOnly ) const
commit 8e148863d9683b8b73b28818d144330a607fb511
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Tue Nov 24 10:27:03 2015 +0100

    sc: Implement ScVectorRefMatrix.
    
    This is a ScMatrix implementation that operates directly on
    formula::DoubleVectorRefToken, saving tremendous amount of copying data back
    and forth.
    
    Change-Id: I027e6cb668ef40eb474773a0ce8d0eeefc1ab71c

diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index 1f5d438..7f1392b 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -40,6 +40,8 @@ class ScInterpreter;
 class SvNumberFormatter;
 class ScMatrixImpl;
 
+namespace formula { class DoubleVectorRefToken; }
+
 namespace sc {
 
 struct Compare;
@@ -106,7 +108,7 @@ struct ScMatrixValue
     }
 };
 
-/// Abstract base class for ScFullMatrix and ScSubMatrix implementations.
+/// Abstract base class for ScFullMatrix and ScVectorRefMatrix implementations.
 class SC_DLLPUBLIC ScMatrix
 {
     mutable size_t  nRefCnt;    // reference count
@@ -604,6 +606,202 @@ public:
 #endif
 };
 
+class SC_DLLPUBLIC ScVectorRefMatrix : public ScMatrix
+{
+    const formula::DoubleVectorRefToken* mpToken;
+    ScInterpreter* mpErrorInterpreter;
+
+    SCSIZE mnRowStart;
+    SCSIZE mnRowSize;
+
+    // only delete via Delete()
+    virtual ~ScVectorRefMatrix();
+
+    ScVectorRefMatrix( const ScVectorRefMatrix& ) = delete;
+    ScVectorRefMatrix& operator=( const ScVectorRefMatrix&) = delete;
+
+public:
+
+    ScVectorRefMatrix(const formula::DoubleVectorRefToken* pToken, SCSIZE nRowStart, SCSIZE nRowSize);
+
+    /** Clone the matrix. */
+    virtual ScMatrix* Clone() const override;
+
+    /**
+     * Resize the matrix to specified new dimension.
+     */
+    virtual void Resize(SCSIZE nC, SCSIZE nR) override;
+
+    virtual void Resize(SCSIZE nC, SCSIZE nR, double fVal) override;
+
+    /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
+        MUST be at least of the size of the original matrix. */
+    virtual ScMatrix* CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const override;
+
+    virtual void SetErrorInterpreter(ScInterpreter* p) override;
+    virtual void GetDimensions(SCSIZE& rC, SCSIZE& rR) const override;
+    virtual SCSIZE GetElementCount() const override;
+    virtual bool ValidColRow( SCSIZE nC, SCSIZE nR) const override;
+
+    /** For a row vector or column vector, if the position does not point into
+        the vector but is a valid column or row offset it is adapted such that
+        it points to an element to be replicated, same column row 0 for a row
+        vector, same row column 0 for a column vector. Else, for a 2D matrix,
+        returns false.
+     */
+    virtual bool ValidColRowReplicated(SCSIZE & rC, SCSIZE & rR) const override;
+
+    /** Checks if the matrix position is within the matrix. If it is not, for a
+        row vector or column vector the position is adapted such that it points
+        to an element to be replicated, same column row 0 for a row vector,
+        same row column 0 for a column vector. Else, for a 2D matrix and
+        position not within matrix, returns false.
+     */
+    virtual bool ValidColRowOrReplicated(SCSIZE & rC, SCSIZE & rR) const override;
+
+    virtual void PutDouble(double fVal, SCSIZE nC, SCSIZE nR) override;
+    virtual void PutDouble(double fVal, SCSIZE nIndex) override;
+    virtual void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) override;
+
+    virtual void PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR) override;
+    virtual void PutString(const svl::SharedString& rStr, SCSIZE nIndex) override;
+    virtual void PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) override;
+
+    virtual void PutEmpty(SCSIZE nC, SCSIZE nR) override;
+
+    /// Jump sal_False without path
+    virtual void PutEmptyPath(SCSIZE nC, SCSIZE nR) override;
+    virtual void PutError(sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR ) override;
+    virtual void PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR) override;
+
+    virtual void FillDouble(double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2) override;
+
+    /** Put a column vector of doubles, starting at row nR, must fit into dimensions. */
+    virtual void PutDoubleVector(const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR) override;
+
+    /** Put a column vector of strings, starting at row nR, must fit into dimensions. */
+    virtual void PutStringVector(const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR) override;
+
+    /** Put a column vector of empties, starting at row nR, must fit into dimensions. */
+    virtual void PutEmptyVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR) override;
+
+    /** Put a column vector of empty results, starting at row nR, must fit into dimensions. */
+    virtual void PutEmptyResultVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR) override;
+
+    /** Put a column vector of empty paths, starting at row nR, must fit into dimensions. */
+    virtual void PutEmptyPathVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR) override;
+
+    /** May be used before obtaining the double value of an element to avoid
+        passing its NAN around.
+        @ATTENTION: MUST NOT be used if the element is a string!
+                    Use GetErrorIfNotString() instead if not sure.
+        @returns 0 if no error, else one of err... constants */
+    virtual sal_uInt16 GetError(SCSIZE nC, SCSIZE nR) const override;
+
+    /// @return 0.0 if empty or empty path, else value or DoubleError.
+    virtual double GetDouble(SCSIZE nC, SCSIZE nR) const override;
+    /// @return 0.0 if empty or empty path, else value or DoubleError.
+    virtual double GetDouble(SCSIZE nIndex) const override;
+
+    /// @return empty string if empty or empty path, else string content.
+    virtual svl::SharedString GetString(SCSIZE nC, SCSIZE nR) const override;
+    /// @return empty string if empty or empty path, else string content.
+    virtual svl::SharedString GetString(SCSIZE nIndex) const override;
+
+    /** @returns the matrix element's string if one is present, otherwise the
+        numerical value formatted as string, or in case of an error the error
+        string is returned; an empty string for empty, a "FALSE" string for
+        empty path. */
+    virtual svl::SharedString GetString(SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const override;
+
+    /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
+    /// an empty string!
+    virtual ScMatrixValue Get(SCSIZE nC, SCSIZE nR) const override;
+
+    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
+    virtual bool IsString(SCSIZE nIndex) const override;
+
+    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
+    virtual bool IsString(SCSIZE nC, SCSIZE nR) const override;
+
+    /// @return <TRUE/> if empty or empty cell or empty result, not empty path.
+    virtual bool IsEmpty(SCSIZE nC, SCSIZE nR) const override;
+
+    /// @return <TRUE/> if empty cell, not empty or empty result or empty path.
+    virtual bool IsEmptyCell(SCSIZE nC, SCSIZE nR) const override;
+
+    /// @return <TRUE/> if empty result, not empty or empty cell or empty path.
+    virtual bool IsEmptyResult(SCSIZE nC, SCSIZE nR) const override;
+
+    /// @return <TRUE/> if empty path, not empty or empty cell or empty result.
+    virtual bool IsEmptyPath(SCSIZE nC, SCSIZE nR) const override;
+
+    /// @return <TRUE/> if value or boolean.
+    virtual bool IsValue(SCSIZE nIndex) const override;
+
+    /// @return <TRUE/> if value or boolean.
+    virtual bool IsValue(SCSIZE nC, SCSIZE nR) const override;
+
+    /// @return <TRUE/> if value or boolean or empty or empty path.
+    virtual bool IsValueOrEmpty(SCSIZE nC, SCSIZE nR) const override;
+
+    /// @return <TRUE/> if boolean.
+    virtual bool IsBoolean(SCSIZE nC, SCSIZE nR) const override;
+
+    /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
+    virtual bool IsNumeric() const override;
+
+    virtual void MatTrans(ScMatrix& mRes) const override;
+    virtual void MatCopy (ScMatrix& mRes) const override;
+
+    // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
+    virtual void CompareEqual() override;
+    virtual void CompareNotEqual() override;
+    virtual void CompareLess() override;
+    virtual void CompareGreater() override;
+    virtual void CompareLessEqual() override;
+    virtual void CompareGreaterEqual() override;
+
+    virtual double And() const override;       // logical AND of all matrix values, or NAN
+    virtual double Or() const override;        // logical OR of all matrix values, or NAN
+    virtual double Xor() const override;       // logical XOR of all matrix values, or NAN
+
+    virtual IterateResult Sum(bool bTextAsZero) const override;
+    virtual IterateResult SumSquare(bool bTextAsZero) const override;
+    virtual IterateResult Product(bool bTextAsZero) const override;
+    virtual size_t Count(bool bCountStrings) const override;
+    virtual size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const override;
+    virtual size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const override;
+
+    virtual double GetMaxValue(bool bTextAsZero) const override;
+    virtual double GetMinValue(bool bTextAsZero) const override;
+
+    virtual ScMatrixRef CompareMatrix(sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions = nullptr) const override;
+
+    /**
+     * Convert the content of matrix into a linear array of numeric values.
+     * String elements are mapped to NaN's and empty elements are mapped to
+     * either NaN or zero values.
+     *
+     * @param bEmptyAsZero if true empty elements are mapped to zero values,
+     *                     otherwise they become NaN values.
+     */
+    virtual void GetDoubleArray(std::vector<double>& rVector, bool bEmptyAsZero = true) const override;
+    virtual void MergeDoubleArray(std::vector<double>& rVector, Op eOp) const override;
+
+    virtual void NotOp(ScMatrix& rMat) override;
+    virtual void NegOp(ScMatrix& rMat) override;
+    virtual void AddOp(double fVal, ScMatrix& rMat) override;
+    virtual void SubOp(bool bFlag, double fVal, ScMatrix& rMat) override;
+    virtual void MulOp(double fVal, ScMatrix& rMat) override;
+    virtual void DivOp(bool bFlag, double fVal, ScMatrix& rMat) override;
+    virtual void PowOp(bool bFlag, double fVal, ScMatrix& rMat) override;
+
+    virtual std::vector<ScMatrix::IterateResult> Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp) override;
+
+    ScVectorRefMatrix& operator+=(const ScVectorRefMatrix& r);
+};
+
 inline void intrusive_ptr_add_ref(const ScMatrix* p)
 {
     p->IncRef();
diff --git a/sc/source/core/inc/arraysumfunctor.hxx b/sc/source/core/inc/arraysumfunctor.hxx
index e9ef404..200fdc6 100644
--- a/sc/source/core/inc/arraysumfunctor.hxx
+++ b/sc/source/core/inc/arraysumfunctor.hxx
@@ -11,6 +11,7 @@
 #ifndef INCLUDED_SC_SOURCE_CORE_INC_ARRAYSUMFUNCTOR_HXX
 #define INCLUDED_SC_SOURCE_CORE_INC_ARRAYSUMFUNCTOR_HXX
 
+#include <cstdint>
 #include <tools/cpuid.hxx>
 
 #if defined(LO_SSE2_AVAILABLE)
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index a9f8a61..c4abe00 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -369,52 +369,62 @@ 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())
                         nRowEnd += i;
-                    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)
+
+                    ScMatrixRef pMat;
+                    if (getenv("SC_ALLOW_SOFTWARE_INTERPRETER") != nullptr)
                     {
-                        const formula::VectorRefArray& rArray = rArrays[nCol];
-                        if (rArray.mpStringArray)
+                        assert(nRowStart <= nRowEnd);
+                        pMat.reset(new ScVectorRefMatrix(p2, nRowStart, nRowEnd - nRowStart + 1));
+                    }
+                    else
+                    {
+                        const std::vector<formula::VectorRefArray>& rArrays = p2->GetArrays();
+                        size_t nColSize = rArrays.size();
+                        size_t nRowSize = nRowEnd - nRowStart + 1;
+                        pMat.reset(new ScFullMatrix(nColSize, nRowSize));
+
+                        size_t nDataRowEnd = p2->GetArrayLength() - 1;
+                        if (nRowStart > nDataRowEnd)
+                            // Referenced rows are all empty.
+                            nRowSize = 0;
+                        else if (nRowEnd > nDataRowEnd)
+                            // Data array is shorter than the row size of the reference. Truncate it to the data.
+                            nRowSize -= nRowEnd - nDataRowEnd;
+
+                        for (size_t nCol = 0; nCol < nColSize; ++nCol)
                         {
-                            if (rArray.mpNumericArray)
+                            const formula::VectorRefArray& rArray = rArrays[nCol];
+                            if (rArray.mpStringArray)
                             {
-                                // 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);
+                                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
+                            else if (rArray.mpNumericArray)
                             {
-                                // String cells only.
-                                rtl_uString** pStrs = rArray.mpStringArray;
-                                pStrs += nRowStart;
-                                fillMatrix(*pMat, nCol, pStrs, nRowSize);
+                                // Numeric cells only.
+                                const double* pNums = rArray.mpNumericArray;
+                                pNums += nRowStart;
+                                fillMatrix(*pMat, nCol, pNums, 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())
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index e3823bd..cb242ca 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -17,10 +17,12 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <arraysumfunctor.hxx>
 #include "scmatrix.hxx"
 #include "global.hxx"
 #include "address.hxx"
 #include <formula/errorcodes.hxx>
+#include <formula/vectortoken.hxx>
 #include "interpre.hxx"
 #include "mtvelements.hxx"
 #include "compare.hxx"
@@ -279,9 +281,9 @@ public:
     double Or() const;
     double Xor() const;
 
-    ScFullMatrix::IterateResult Sum(bool bTextAsZero) const;
-    ScFullMatrix::IterateResult SumSquare(bool bTextAsZero) const;
-    ScFullMatrix::IterateResult Product(bool bTextAsZero) const;
+    ScMatrix::IterateResult Sum(bool bTextAsZero) const;
+    ScMatrix::IterateResult SumSquare(bool bTextAsZero) const;
+    ScMatrix::IterateResult Product(bool bTextAsZero) const;
     size_t Count(bool bCountStrings) const;
     size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const;
     size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const;
@@ -299,7 +301,7 @@ public:
     void ApplyOperation(T aOp, ScMatrixImpl& rMat);
 
     template<typename T>
-    std::vector<ScFullMatrix::IterateResult> ApplyCollectOperation(bool bTextAsZero, const std::vector<std::unique_ptr<T>>& aOp);
+    std::vector<ScMatrix::IterateResult> ApplyCollectOperation(bool bTextAsZero, const std::vector<std::unique_ptr<T>>& aOp);
 
 #if DEBUG_MATRIX
     void Dump() const;
@@ -999,13 +1001,13 @@ template<typename _Op>
 class WalkElementBlocks
 {
     _Op maOp;
-    ScFullMatrix::IterateResult maRes;
+    ScMatrix::IterateResult maRes;
     bool mbFirst:1;
     bool mbTextAsZero:1;
 public:
     WalkElementBlocks(bool bTextAsZero) : maRes(_Op::InitVal, _Op::InitVal, 0), mbFirst(true), mbTextAsZero(bTextAsZero) {}
 
-    const ScFullMatrix::IterateResult& getResult() const { return maRes; }
+    const ScMatrix::IterateResult& getResult() const { return maRes; }
 
     void operator() (const MatrixImplType::element_block_node_type& node)
     {
@@ -1068,7 +1070,7 @@ template<typename _Op>
 class WalkElementBlocksMultipleValues
 {
     const std::vector<std::unique_ptr<_Op>>& maOp;
-    std::vector<ScFullMatrix::IterateResult> maRes;
+    std::vector<ScMatrix::IterateResult> maRes;
     bool mbFirst:1;
     bool mbTextAsZero:1;
 public:
@@ -1082,7 +1084,7 @@ public:
         maRes.emplace_back(0.0, 0.0, 0); // count
     }
 
-    const std::vector<ScFullMatrix::IterateResult>& getResult() const { return maRes; }
+    const std::vector<ScMatrix::IterateResult>& getResult() const { return maRes; }
 
     void operator() (const MatrixImplType::element_block_node_type& node)
     {
@@ -1752,7 +1754,7 @@ public:
 namespace {
 
 template<typename TOp>
-ScFullMatrix::IterateResult GetValueWithCount(bool bTextAsZero, const MatrixImplType& maMat)
+ScMatrix::IterateResult GetValueWithCount(bool bTextAsZero, const MatrixImplType& maMat)
 {
     WalkElementBlocks<TOp> aFunc(bTextAsZero);
     maMat.walk(aFunc);
@@ -1761,17 +1763,17 @@ ScFullMatrix::IterateResult GetValueWithCount(bool bTextAsZero, const MatrixImpl
 
 }
 
-ScFullMatrix::IterateResult ScMatrixImpl::Sum(bool bTextAsZero) const
+ScMatrix::IterateResult ScMatrixImpl::Sum(bool bTextAsZero) const
 {
     return GetValueWithCount<sc::op::Sum>(bTextAsZero, maMat);
 }
 
-ScFullMatrix::IterateResult ScMatrixImpl::SumSquare(bool bTextAsZero) const
+ScMatrix::IterateResult ScMatrixImpl::SumSquare(bool bTextAsZero) const
 {
     return GetValueWithCount<sc::op::SumSquare>(bTextAsZero, maMat);
 }
 
-ScFullMatrix::IterateResult ScMatrixImpl::Product(bool bTextAsZero) const
+ScMatrix::IterateResult ScMatrixImpl::Product(bool bTextAsZero) const
 {
     return GetValueWithCount<sc::op::Product>(bTextAsZero, maMat);
 }
@@ -2160,7 +2162,7 @@ void ScMatrixImpl::ApplyOperation(T aOp, ScMatrixImpl& rMat)
 }
 
 template<typename T>
-std::vector<ScFullMatrix::IterateResult> ScMatrixImpl::ApplyCollectOperation(bool bTextAsZero, const std::vector<std::unique_ptr<T>>& aOp)
+std::vector<ScMatrix::IterateResult> ScMatrixImpl::ApplyCollectOperation(bool bTextAsZero, const std::vector<std::unique_ptr<T>>& aOp)
 {
     WalkElementBlocksMultipleValues<T> aFunc(bTextAsZero, aOp);
     maMat.walk(aFunc);
@@ -2550,17 +2552,17 @@ double ScFullMatrix::Xor() const
     return pImpl->Xor();
 }
 
-ScFullMatrix::IterateResult ScFullMatrix::Sum(bool bTextAsZero) const
+ScMatrix::IterateResult ScFullMatrix::Sum(bool bTextAsZero) const
 {
     return pImpl->Sum(bTextAsZero);
 }
 
-ScFullMatrix::IterateResult ScFullMatrix::SumSquare(bool bTextAsZero) const
+ScMatrix::IterateResult ScFullMatrix::SumSquare(bool bTextAsZero) const
 {
     return pImpl->SumSquare(bTextAsZero);
 }
 
-ScFullMatrix::IterateResult ScFullMatrix::Product(bool bTextAsZero) const
+ScMatrix::IterateResult ScFullMatrix::Product(bool bTextAsZero) const
 {
     return pImpl->Product(bTextAsZero);
 }
@@ -2815,7 +2817,7 @@ void ScFullMatrix::PowOp( bool bFlag, double fVal, ScMatrix& rMat)
     }
 }
 
-std::vector<ScFullMatrix::IterateResult> ScFullMatrix::Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp)
+std::vector<ScMatrix::IterateResult> ScFullMatrix::Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp)
 {
     return pImpl->ApplyCollectOperation(bTextAsZero, aOp);
 }
@@ -2833,4 +2835,436 @@ void ScFullMatrix::Dump() const
 }
 #endif
 
+ScVectorRefMatrix::ScVectorRefMatrix(const formula::DoubleVectorRefToken* pToken, SCSIZE nRowStart, SCSIZE nRowSize)
+    : ScMatrix()
+    , mpToken(pToken)
+    , mnRowStart(nRowStart)
+    , mnRowSize(nRowSize)
+{
+}
+
+ScVectorRefMatrix::~ScVectorRefMatrix()
+{
+}
+
+ScMatrix* ScVectorRefMatrix::Clone() const
+{
+    throw std::runtime_error("ScVectorRefMatrix::Clone() called");
+}
+
+void ScVectorRefMatrix::Resize(SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::Resize called");
+}
+
+void ScVectorRefMatrix::Resize(SCSIZE nC, SCSIZE nR, double fVal)
+{
+    throw std::runtime_error("ScVectorRefMatrix::Resize called");
+}
+
+ScMatrix* ScVectorRefMatrix::CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::CloneAndExtend called");
+}
+
+void ScVectorRefMatrix::SetErrorInterpreter(ScInterpreter* p)
+{
+    mpErrorInterpreter = p;
+}
+
+void ScVectorRefMatrix::GetDimensions(SCSIZE& rC, SCSIZE& rR) const
+{
+    rC = mpToken->GetArrays().size();
+    rR = mnRowSize;
+}
+
+SCSIZE ScVectorRefMatrix::GetElementCount() const
+{
+    throw std::runtime_error("ScVectorRefMatrix::GetElementCount called");
+}
+
+bool ScVectorRefMatrix::ValidColRow(SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::ValidColRow called");
+}
+
+bool ScVectorRefMatrix::ValidColRowReplicated(SCSIZE & rC, SCSIZE & rR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::ValidColRowReplicated called");
+}
+
+bool ScVectorRefMatrix::ValidColRowOrReplicated(SCSIZE & rC, SCSIZE & rR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::ValidColRowOrReplicated called");
+}
+
+void ScVectorRefMatrix::PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutDouble called");
+}
+
+void ScVectorRefMatrix::PutDouble(double fVal, SCSIZE nIndex)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutDouble called");
+}
+
+void ScVectorRefMatrix::PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutDouble called");
+}
+
+void ScVectorRefMatrix::PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutString called");
+}
+
+void ScVectorRefMatrix::PutString(const svl::SharedString& rStr, SCSIZE nIndex)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutString called");
+}
+
+void ScVectorRefMatrix::PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutString called");
+}
+
+void ScVectorRefMatrix::PutEmpty(SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutEmpty called");
+}
+
+void ScVectorRefMatrix::PutEmptyPath(SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutEmptyPath called");
+}
+
+void ScVectorRefMatrix::PutError(sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutError called");
+}
+
+void ScVectorRefMatrix::PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutBoolean called");
+}
+
+void ScVectorRefMatrix::FillDouble(double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2)
+{
+    throw std::runtime_error("ScVectorRefMatrix::FillDouble called");
+}
+
+void ScVectorRefMatrix::PutDoubleVector(const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutDoubleVector called");
+}
+
+void ScVectorRefMatrix::PutStringVector(const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutStringVector called");
+}
+
+void ScVectorRefMatrix::PutEmptyVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutEmptyVector called");
+}
+
+void ScVectorRefMatrix::PutEmptyResultVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutEmptyResultVector called");
+}
+
+void ScVectorRefMatrix::PutEmptyPathVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PutEmptyPathVector called");
+}
+
+sal_uInt16 ScVectorRefMatrix::GetError(SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::GetError called");
+}
+
+double ScVectorRefMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::GetDouble called");
+}
+
+double ScVectorRefMatrix::GetDouble(SCSIZE nIndex) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::GetDouble called");
+}
+
+svl::SharedString ScVectorRefMatrix::GetString(SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::GetString called");
+}
+
+svl::SharedString ScVectorRefMatrix::GetString(SCSIZE nIndex) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::GetString called");
+}
+
+svl::SharedString ScVectorRefMatrix::GetString(SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::GetString called");
+}
+
+ScMatrixValue ScVectorRefMatrix::Get(SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::Get called");
+}
+
+bool ScVectorRefMatrix::IsString(SCSIZE nIndex) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::IsString called");
+}
+
+bool ScVectorRefMatrix::IsString(SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::IsString called");
+}
+
+bool ScVectorRefMatrix::IsEmpty(SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::IsEmpty called");
+}
+
+bool ScVectorRefMatrix::IsEmptyCell(SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::IsEmptyCell called");
+}
+
+bool ScVectorRefMatrix::IsEmptyResult(SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::IsEmptyResult called");
+}
+
+bool ScVectorRefMatrix::IsEmptyPath(SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::IsEmptyPath called");
+}
+
+bool ScVectorRefMatrix::IsValue(SCSIZE nIndex) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::IsValue called");
+}
+
+bool ScVectorRefMatrix::IsValue(SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::IsValue called");
+}
+
+bool ScVectorRefMatrix::IsValueOrEmpty(SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::IsValueOrEmpty called");
+}
+
+bool ScVectorRefMatrix::IsBoolean(SCSIZE nC, SCSIZE nR) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::IsBoolean called");
+}
+
+bool ScVectorRefMatrix::IsNumeric() const
+{
+    throw std::runtime_error("ScVectorRefMatrix::IsNumeric called");
+}
+
+void ScVectorRefMatrix::MatTrans(ScMatrix& mRes) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::MatTrans called");
+}
+
+void ScVectorRefMatrix::MatCopy(ScMatrix& mRes) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::MatCopy called");
+}
+
+void ScVectorRefMatrix::CompareEqual()
+{
+    throw std::runtime_error("ScVectorRefMatrix::CompareEqual called");
+}
+
+void ScVectorRefMatrix::CompareNotEqual()
+{
+    throw std::runtime_error("ScVectorRefMatrix::CompareNotEqual called");
+}
+
+void ScVectorRefMatrix::CompareLess()
+{
+    throw std::runtime_error("ScVectorRefMatrix::CompareLess called");
+}
+
+void ScVectorRefMatrix::CompareGreater()
+{
+    throw std::runtime_error("ScVectorRefMatrix::CompareGreater called");
+}
+
+void ScVectorRefMatrix::CompareLessEqual()
+{
+    throw std::runtime_error("ScVectorRefMatrix::CompareLessEqual called");
+}
+
+void ScVectorRefMatrix::CompareGreaterEqual()
+{
+    throw std::runtime_error("ScVectorRefMatrix::CompareGreaterEqual called");
+}
+
+double ScVectorRefMatrix::And() const
+{
+    throw std::runtime_error("ScVectorRefMatrix::And called");
+}
+
+double ScVectorRefMatrix::Or() const
+{
+    throw std::runtime_error("ScVectorRefMatrix::Or called");
+}
+
+double ScVectorRefMatrix::Xor() const
+{
+    throw std::runtime_error("ScVectorRefMatrix::Xor called");
+}
+
+ScMatrix::IterateResult ScVectorRefMatrix::Sum(bool bTextAsZero) const
+{
+    const std::vector<formula::VectorRefArray>& rArrays = mpToken->GetArrays();
+    size_t nDataSize = mnRowSize;
+
+    if (mnRowStart >= mpToken->GetRefRowSize())
+    {
+        return ScMatrix::IterateResult(0.0, 0.0, 0);
+    }
+    else if (nDataSize > mpToken->GetRefRowSize() + mnRowStart)
+    {
+        nDataSize = mpToken->GetRefRowSize() - mnRowStart;
+    }
+
+    double mfFirst = 0.0;
+    double mfRest = 0.0;
+    for (const formula::VectorRefArray& rArray : rArrays)
+    {
+        if (rArray.mpStringArray)
+        {
+            // TODO FIXME
+            throw std::runtime_error("ScVectorRefMatrix::Sum - string array");
+        }
+        else if (rArray.mpNumericArray)
+        {
+            // Numeric cells only.
+            const double* p = rArray.mpNumericArray + mnRowStart;
+            size_t i = 0;
+
+            // Store the first non-zero value in mfFirst (for some reason).
+            if (!mfFirst)
+            {
+                for (i = 0; i < nDataSize; ++i)
+                {
+                    if (!mfFirst)
+                        mfFirst = p[i];
+                    else
+                        break;
+                }
+            }
+            p += i;
+            nDataSize -= i;
+            if (nDataSize == 0)
+                continue;
+
+            sc::ArraySumFunctor functor(p, nDataSize);
+
+            mfRest += functor();
+        }
+    }
+
+    return ScMatrix::IterateResult(mfFirst, mfRest, mpToken->GetArrays().size()*nDataSize);
+}
+
+ScMatrix::IterateResult ScVectorRefMatrix::SumSquare(bool bTextAsZero) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::SumSquare called");
+}
+
+ScMatrix::IterateResult ScVectorRefMatrix::Product(bool bTextAsZero) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::Product called");
+}
+
+size_t ScVectorRefMatrix::Count(bool bCountStrings) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::Count called");
+}
+
+size_t ScVectorRefMatrix::MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::MatchDoubleInColumns called");
+}
+
+size_t ScVectorRefMatrix::MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::MatchStringInColumns called");
+}
+
+double ScVectorRefMatrix::GetMaxValue(bool bTextAsZero) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::GetMaxValue called");
+}
+
+double ScVectorRefMatrix::GetMinValue(bool bTextAsZero) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::GetMinValue called");
+}
+
+ScMatrixRef ScVectorRefMatrix::CompareMatrix(sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::CompareMatrix called");
+}
+
+void ScVectorRefMatrix::GetDoubleArray(std::vector<double>& rVector, bool bEmptyAsZero) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::GetDoubleArray called");
+}
+
+void ScVectorRefMatrix::MergeDoubleArray(std::vector<double>& rVector, Op eOp) const
+{
+    throw std::runtime_error("ScVectorRefMatrix::MergeDoubleArray called");
+}
+
+void ScVectorRefMatrix::NotOp(ScMatrix& rMat)
+{
+    throw std::runtime_error("ScVectorRefMatrix::NotOp called");
+}
+
+void ScVectorRefMatrix::NegOp(ScMatrix& rMat)
+{
+    throw std::runtime_error("ScVectorRefMatrix::NegOp called");
+}
+
+void ScVectorRefMatrix::AddOp(double fVal, ScMatrix& rMat)
+{
+    throw std::runtime_error("ScVectorRefMatrix::AddOp called");
+}
+
+void ScVectorRefMatrix::SubOp(bool bFlag, double fVal, ScMatrix& rMat)
+{
+    throw std::runtime_error("ScVectorRefMatrix::SubOp called");
+}
+
+void ScVectorRefMatrix::MulOp(double fVal, ScMatrix& rMat)
+{
+    throw std::runtime_error("ScVectorRefMatrix::MulOp called");
+}
+
+void ScVectorRefMatrix::DivOp(bool bFlag, double fVal, ScMatrix& rMat)
+{
+    throw std::runtime_error("ScVectorRefMatrix::DivOp called");
+}
+
+void ScVectorRefMatrix::PowOp(bool bFlag, double fVal, ScMatrix& rMat)
+{
+    throw std::runtime_error("ScVectorRefMatrix::PowOp called");
+}
+
+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");
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 02226081592e47b0c42489258ed688b9ebb7a939
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Thu Nov 19 12:42:36 2015 +0100

    sc: Introduce Abstract Base Class for ScMatrix, for a future rework.
    
    We want to introduce another type of ScMatrix that will directly contain
    DoubleVectorRefToken and operate on that.  The idea is that it is pointless to
    construct a ScMatrix via lots of copying around, when we already have a nice
    array of doubles.
    
    Change-Id: I3e5d7b9e2e0f9b9bf350336a8582cfd852586b3f

diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index 883550d..1f5d438 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -106,24 +106,18 @@ struct ScMatrixValue
     }
 };
 
-/**
- * Matrix data type that can store values of mixed types.  Each element can
- * be one of the following types: numeric, string, boolean, empty, and empty
- * path.
- */
+/// Abstract base class for ScFullMatrix and ScSubMatrix implementations.
 class SC_DLLPUBLIC ScMatrix
 {
-    friend class ScMatrixImpl;
-
-    std::unique_ptr<ScMatrixImpl> pImpl;
     mutable size_t  nRefCnt;    // reference count
-
-    // only delete via Delete()
-    ~ScMatrix();
+    bool            mbCloneIfConst; // Whether the matrix is cloned with a CloneIfConst() call.
 
     ScMatrix( const ScMatrix& ) = delete;
     ScMatrix& operator=( const ScMatrix&) = delete;
 
+protected:
+    virtual ~ScMatrix() {}
+
 public:
     enum Op { Add, Sub, Mul, Div };
 
@@ -202,13 +196,10 @@ public:
         return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTYPATH;
     }
 
-    ScMatrix(SCSIZE nC, SCSIZE nR);
-    ScMatrix(SCSIZE nC, SCSIZE nR, double fInitVal);
-
-    ScMatrix( size_t nC, size_t nR, const std::vector<double>& rInitVals );
+    ScMatrix() : nRefCnt(0), mbCloneIfConst(true) {}
 
     /** Clone the matrix. */
-    ScMatrix* Clone() const;
+    virtual ScMatrix* Clone() const = 0;
 
     /** Clone the matrix if mbCloneIfConst (immutable) is set, otherwise
         return _this_ matrix, to be assigned to a ScMatrixRef. */
@@ -221,21 +212,21 @@ public:
     /**
      * Resize the matrix to specified new dimension.
      */
-    void Resize( SCSIZE nC, SCSIZE nR);
+    virtual void Resize(SCSIZE nC, SCSIZE nR) = 0;
 
-    void Resize(SCSIZE nC, SCSIZE nR, double fVal);
+    virtual void Resize(SCSIZE nC, SCSIZE nR, double fVal) = 0;
 
     /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
         MUST be at least of the size of the original matrix. */
-    ScMatrix* CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const;
+    virtual ScMatrix* CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const = 0;
 
     void IncRef() const;
     void DecRef() const;
 
-    void SetErrorInterpreter( ScInterpreter* p);
-    void GetDimensions( SCSIZE& rC, SCSIZE& rR) const;
-    SCSIZE GetElementCount() const;
-    bool ValidColRow( SCSIZE nC, SCSIZE nR) const;
+    virtual void SetErrorInterpreter( ScInterpreter* p) = 0;
+    virtual void GetDimensions( SCSIZE& rC, SCSIZE& rR) const = 0;
+    virtual SCSIZE GetElementCount() const = 0;
+    virtual bool ValidColRow( SCSIZE nC, SCSIZE nR) const = 0;
 
     /** For a row vector or column vector, if the position does not point into
         the vector but is a valid column or row offset it is adapted such that
@@ -243,7 +234,7 @@ public:
         vector, same row column 0 for a column vector. Else, for a 2D matrix,
         returns false.
      */
-    bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const;
+    virtual bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const = 0;
 
     /** Checks if the matrix position is within the matrix. If it is not, for a
         row vector or column vector the position is adapted such that it points
@@ -251,47 +242,47 @@ public:
         same row column 0 for a column vector. Else, for a 2D matrix and
         position not within matrix, returns false.
      */
-    bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const;
+    virtual bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const = 0;
 
-    void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
-    void PutDouble( double fVal, SCSIZE nIndex);
-    void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR);
+    virtual void PutDouble( double fVal, SCSIZE nC, SCSIZE nR) = 0;
+    virtual void PutDouble( double fVal, SCSIZE nIndex) = 0;
+    virtual void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) = 0;
 
-    void PutString( const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR);
-    void PutString( const svl::SharedString& rStr, SCSIZE nIndex);
-    void PutString( const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR);
+    virtual void PutString( const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR) = 0;
+    virtual void PutString( const svl::SharedString& rStr, SCSIZE nIndex) = 0;
+    virtual void PutString( const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) = 0;
 
-    void PutEmpty( SCSIZE nC, SCSIZE nR);
+    virtual void PutEmpty( SCSIZE nC, SCSIZE nR) = 0;
 
     /// Jump sal_False without path
-    void PutEmptyPath( SCSIZE nC, SCSIZE nR);
-    void PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR );
-    void PutBoolean( bool bVal, SCSIZE nC, SCSIZE nR);
+    virtual void PutEmptyPath( SCSIZE nC, SCSIZE nR) = 0;
+    virtual void PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR ) = 0;
+    virtual void PutBoolean( bool bVal, SCSIZE nC, SCSIZE nR) = 0;
 
-    void FillDouble( double fVal,
-            SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 );
+    virtual void FillDouble( double fVal,
+            SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 ) = 0;
 
     /** Put a column vector of doubles, starting at row nR, must fit into dimensions. */
-    void PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR );
+    virtual void PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR ) = 0;
 
     /** Put a column vector of strings, starting at row nR, must fit into dimensions. */
-    void PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR );
+    virtual void PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR ) = 0;
 
     /** Put a column vector of empties, starting at row nR, must fit into dimensions. */
-    void PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
+    virtual void PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) = 0;
 
     /** Put a column vector of empty results, starting at row nR, must fit into dimensions. */
-    void PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
+    virtual void PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) = 0;
 
     /** Put a column vector of empty paths, starting at row nR, must fit into dimensions. */
-    void PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
+    virtual void PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) = 0;
 
     /** May be used before obtaining the double value of an element to avoid
         passing its NAN around.
         @ATTENTION: MUST NOT be used if the element is a string!
                     Use GetErrorIfNotString() instead if not sure.
         @returns 0 if no error, else one of err... constants */
-    sal_uInt16 GetError( SCSIZE nC, SCSIZE nR) const;
+    virtual sal_uInt16 GetError( SCSIZE nC, SCSIZE nR) const = 0;
 
     /** Use in ScInterpreter to obtain the error code, if any.
         @returns 0 if no error or string element, else one of err... constants */
@@ -299,85 +290,291 @@ public:
         { return IsValue( nC, nR) ? GetError( nC, nR) : 0; }
 
     /// @return 0.0 if empty or empty path, else value or DoubleError.
-    double GetDouble( SCSIZE nC, SCSIZE nR) const;
+    virtual double GetDouble( SCSIZE nC, SCSIZE nR) const = 0;
+    /// @return 0.0 if empty or empty path, else value or DoubleError.
+    virtual double GetDouble( SCSIZE nIndex) const = 0;
+
+    /// @return empty string if empty or empty path, else string content.
+    virtual svl::SharedString GetString( SCSIZE nC, SCSIZE nR) const = 0;
+    /// @return empty string if empty or empty path, else string content.
+    virtual svl::SharedString GetString( SCSIZE nIndex) const = 0;
+
+    /** @returns the matrix element's string if one is present, otherwise the
+        numerical value formatted as string, or in case of an error the error
+        string is returned; an empty string for empty, a "FALSE" string for
+        empty path. */
+    virtual svl::SharedString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const = 0;
+
+    /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
+    /// an empty string!
+    virtual ScMatrixValue Get( SCSIZE nC, SCSIZE nR) const = 0;
+
+    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
+    virtual bool IsString( SCSIZE nIndex ) const = 0;
+
+    /// @return <TRUE/> if string or empty or empty path, in fact non-value.
+    virtual bool IsString( SCSIZE nC, SCSIZE nR ) const = 0;
+
+    /// @return <TRUE/> if empty or empty cell or empty result, not empty path.
+    virtual bool IsEmpty( SCSIZE nC, SCSIZE nR ) const = 0;
+
+    /// @return <TRUE/> if empty cell, not empty or empty result or empty path.
+    virtual bool IsEmptyCell( SCSIZE nC, SCSIZE nR ) const = 0;
+
+    /// @return <TRUE/> if empty result, not empty or empty cell or empty path.
+    virtual bool IsEmptyResult( SCSIZE nC, SCSIZE nR ) const = 0;
+
+    /// @return <TRUE/> if empty path, not empty or empty cell or empty result.
+    virtual bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const = 0;
+
+    /// @return <TRUE/> if value or boolean.
+    virtual bool IsValue( SCSIZE nIndex ) const = 0;
+
+    /// @return <TRUE/> if value or boolean.
+    virtual bool IsValue( SCSIZE nC, SCSIZE nR ) const = 0;
+
+    /// @return <TRUE/> if value or boolean or empty or empty path.
+    virtual bool IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const = 0;
+
+    /// @return <TRUE/> if boolean.
+    virtual bool IsBoolean( SCSIZE nC, SCSIZE nR ) const = 0;
+
+    /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
+    virtual bool IsNumeric() const = 0;
+
+    virtual void MatTrans( ScMatrix& mRes) const = 0;
+    virtual void MatCopy ( ScMatrix& mRes) const = 0;
+
+    // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
+    virtual void CompareEqual() = 0;
+    virtual void CompareNotEqual() = 0;
+    virtual void CompareLess() = 0;
+    virtual void CompareGreater() = 0;
+    virtual void CompareLessEqual() = 0;
+    virtual void CompareGreaterEqual() = 0;
+
+    virtual double And() const = 0;       // logical AND of all matrix values, or NAN
+    virtual double Or() const = 0;        // logical OR of all matrix values, or NAN
+    virtual double Xor() const = 0;       // logical XOR of all matrix values, or NAN
+
+    virtual IterateResult Sum(bool bTextAsZero) const = 0;
+    virtual IterateResult SumSquare(bool bTextAsZero) const = 0;
+    virtual IterateResult Product(bool bTextAsZero) const = 0;
+    virtual size_t Count(bool bCountStrings) const = 0;
+    virtual size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const = 0;
+    virtual size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const = 0;
+
+    virtual double GetMaxValue( bool bTextAsZero ) const = 0;
+    virtual double GetMinValue( bool bTextAsZero ) const = 0;
+
+    virtual ScMatrixRef CompareMatrix(
+        sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions = nullptr ) const = 0;
+
+    /**
+     * Convert the content of matrix into a linear array of numeric values.
+     * String elements are mapped to NaN's and empty elements are mapped to
+     * either NaN or zero values.
+     *
+     * @param bEmptyAsZero if true empty elements are mapped to zero values,
+     *                     otherwise they become NaN values.
+     */
+    virtual void GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero = true ) const = 0;
+    virtual void MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const = 0;
+
+    virtual void NotOp(ScMatrix& rMat) = 0;
+    virtual void NegOp(ScMatrix& rMat) = 0;
+    virtual void AddOp(double fVal, ScMatrix& rMat) = 0;
+    virtual void SubOp(bool bFlag, double fVal, ScMatrix& rMat) = 0;
+    virtual void MulOp(double fVal, ScMatrix& rMat) = 0;
+    virtual void DivOp(bool bFlag, double fVal, ScMatrix& rMat) = 0;
+    virtual void PowOp(bool bFlag, double fVal, ScMatrix& rMat) = 0;
+
+    virtual std::vector<ScMatrix::IterateResult> Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp) = 0;
+
+#if DEBUG_MATRIX
+    void Dump() const;
+#endif
+};
+
+/**
+ * Matrix data type that can store values of mixed types.  Each element can
+ * be one of the following types: numeric, string, boolean, empty, and empty
+ * path.
+ */
+class SC_DLLPUBLIC ScFullMatrix : public ScMatrix
+{
+    friend class ScMatrixImpl;
+
+    std::unique_ptr<ScMatrixImpl> pImpl;
+
+    // only delete via Delete()
+    virtual ~ScFullMatrix();
+
+    ScFullMatrix( const ScFullMatrix& ) = delete;
+    ScFullMatrix& operator=( const ScFullMatrix&) = delete;
+
+public:
+
+    ScFullMatrix(SCSIZE nC, SCSIZE nR);
+    ScFullMatrix(SCSIZE nC, SCSIZE nR, double fInitVal);
+
+    ScFullMatrix( size_t nC, size_t nR, const std::vector<double>& rInitVals );
+
+    /** Clone the matrix. */
+    virtual ScMatrix* Clone() const override;
+
+    /**
+     * Resize the matrix to specified new dimension.
+     */
+    virtual void Resize( SCSIZE nC, SCSIZE nR) override;
+
+    virtual void Resize(SCSIZE nC, SCSIZE nR, double fVal) override;
+
+    /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
+        MUST be at least of the size of the original matrix. */
+    virtual ScMatrix* CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const override;
+
+    virtual void SetErrorInterpreter( ScInterpreter* p) override;
+    virtual void GetDimensions( SCSIZE& rC, SCSIZE& rR) const override;
+    virtual SCSIZE GetElementCount() const override;
+    virtual bool ValidColRow( SCSIZE nC, SCSIZE nR) const override;
+
+    /** For a row vector or column vector, if the position does not point into
+        the vector but is a valid column or row offset it is adapted such that
+        it points to an element to be replicated, same column row 0 for a row
+        vector, same row column 0 for a column vector. Else, for a 2D matrix,
+        returns false.
+     */
+    virtual bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const override;
+
+    /** Checks if the matrix position is within the matrix. If it is not, for a
+        row vector or column vector the position is adapted such that it points
+        to an element to be replicated, same column row 0 for a row vector,
+        same row column 0 for a column vector. Else, for a 2D matrix and
+        position not within matrix, returns false.
+     */
+    virtual bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const override;
+
+    virtual void PutDouble( double fVal, SCSIZE nC, SCSIZE nR) override;
+    virtual void PutDouble( double fVal, SCSIZE nIndex) override;
+    virtual void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) override;
+
+    virtual void PutString( const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR) override;
+    virtual void PutString( const svl::SharedString& rStr, SCSIZE nIndex) override;
+    virtual void PutString( const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) override;
+
+    virtual void PutEmpty( SCSIZE nC, SCSIZE nR) override;
+
+    /// Jump sal_False without path
+    virtual void PutEmptyPath( SCSIZE nC, SCSIZE nR) override;
+    virtual void PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR ) override;
+    virtual void PutBoolean( bool bVal, SCSIZE nC, SCSIZE nR) override;
+
+    virtual void FillDouble( double fVal,
+            SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 ) override;
+
+    /** Put a column vector of doubles, starting at row nR, must fit into dimensions. */
+    virtual void PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR ) override;
+
+    /** Put a column vector of strings, starting at row nR, must fit into dimensions. */
+    virtual void PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR ) override;
+
+    /** Put a column vector of empties, starting at row nR, must fit into dimensions. */
+    virtual void PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) override;
+
+    /** Put a column vector of empty results, starting at row nR, must fit into dimensions. */
+    virtual void PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) override;
+
+    /** Put a column vector of empty paths, starting at row nR, must fit into dimensions. */
+    virtual void PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) override;
+
+    /** May be used before obtaining the double value of an element to avoid
+        passing its NAN around.
+        @ATTENTION: MUST NOT be used if the element is a string!
+                    Use GetErrorIfNotString() instead if not sure.
+        @returns 0 if no error, else one of err... constants */
+    virtual sal_uInt16 GetError( SCSIZE nC, SCSIZE nR) const override;
+
+    /// @return 0.0 if empty or empty path, else value or DoubleError.
+    virtual double GetDouble( SCSIZE nC, SCSIZE nR) const override;
     /// @return 0.0 if empty or empty path, else value or DoubleError.
-    double GetDouble( SCSIZE nIndex) const;
+    virtual double GetDouble( SCSIZE nIndex) const override;
 
     /// @return empty string if empty or empty path, else string content.
-    svl::SharedString GetString( SCSIZE nC, SCSIZE nR) const;
+    virtual svl::SharedString GetString( SCSIZE nC, SCSIZE nR) const override;
     /// @return empty string if empty or empty path, else string content.
-    svl::SharedString GetString( SCSIZE nIndex) const;
+    virtual svl::SharedString GetString( SCSIZE nIndex) const override;
 
     /** @returns the matrix element's string if one is present, otherwise the
         numerical value formatted as string, or in case of an error the error
         string is returned; an empty string for empty, a "FALSE" string for
         empty path. */
-    svl::SharedString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const;
+    virtual svl::SharedString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const override;
 
     /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
     /// an empty string!
-    ScMatrixValue Get( SCSIZE nC, SCSIZE nR) const;
+    virtual ScMatrixValue Get( SCSIZE nC, SCSIZE nR) const override;
 
     /// @return <TRUE/> if string or empty or empty path, in fact non-value.
-    bool IsString( SCSIZE nIndex ) const;
+    virtual bool IsString( SCSIZE nIndex ) const override;
 
     /// @return <TRUE/> if string or empty or empty path, in fact non-value.
-    bool IsString( SCSIZE nC, SCSIZE nR ) const;
+    virtual bool IsString( SCSIZE nC, SCSIZE nR ) const override;
 
     /// @return <TRUE/> if empty or empty cell or empty result, not empty path.
-    bool IsEmpty( SCSIZE nC, SCSIZE nR ) const;
+    virtual bool IsEmpty( SCSIZE nC, SCSIZE nR ) const override;
 
     /// @return <TRUE/> if empty cell, not empty or empty result or empty path.
-    bool IsEmptyCell( SCSIZE nC, SCSIZE nR ) const;
+    virtual bool IsEmptyCell( SCSIZE nC, SCSIZE nR ) const override;
 
     /// @return <TRUE/> if empty result, not empty or empty cell or empty path.
-    bool IsEmptyResult( SCSIZE nC, SCSIZE nR ) const;
+    virtual bool IsEmptyResult( SCSIZE nC, SCSIZE nR ) const override;
 
     /// @return <TRUE/> if empty path, not empty or empty cell or empty result.
-    bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const;
+    virtual bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const override;
 
     /// @return <TRUE/> if value or boolean.
-    bool IsValue( SCSIZE nIndex ) const;
+    virtual bool IsValue( SCSIZE nIndex ) const override;
 
     /// @return <TRUE/> if value or boolean.
-    bool IsValue( SCSIZE nC, SCSIZE nR ) const;
+    virtual bool IsValue( SCSIZE nC, SCSIZE nR ) const override;
 
     /// @return <TRUE/> if value or boolean or empty or empty path.
-    bool IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const;
+    virtual bool IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const override;
 
     /// @return <TRUE/> if boolean.
-    bool IsBoolean( SCSIZE nC, SCSIZE nR ) const;
+    virtual bool IsBoolean( SCSIZE nC, SCSIZE nR ) const override;
 
     /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
-    bool IsNumeric() const;
+    virtual bool IsNumeric() const override;
 
-    void MatTrans( ScMatrix& mRes) const;
-    void MatCopy ( ScMatrix& mRes) const;
+    virtual void MatTrans( ScMatrix& mRes) const override;
+    virtual void MatCopy ( ScMatrix& mRes) const override;
 
     // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
-    void CompareEqual();
-    void CompareNotEqual();
-    void CompareLess();
-    void CompareGreater();
-    void CompareLessEqual();
-    void CompareGreaterEqual();
-
-    double And() const;       // logical AND of all matrix values, or NAN
-    double Or() const;        // logical OR of all matrix values, or NAN
-    double Xor() const;       // logical XOR of all matrix values, or NAN
-
-    IterateResult Sum(bool bTextAsZero) const;
-    IterateResult SumSquare(bool bTextAsZero) const;
-    IterateResult Product(bool bTextAsZero) const;
-    size_t Count(bool bCountStrings) const;
-    size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const;
-    size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const;
-
-    double GetMaxValue( bool bTextAsZero ) const;
-    double GetMinValue( bool bTextAsZero ) const;
-
-    ScMatrixRef CompareMatrix(
-        sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions = nullptr ) const;
+    virtual void CompareEqual() override;
+    virtual void CompareNotEqual() override;
+    virtual void CompareLess() override;
+    virtual void CompareGreater() override;
+    virtual void CompareLessEqual() override;
+    virtual void CompareGreaterEqual() override;
+
+    virtual double And() const override;       // logical AND of all matrix values, or NAN
+    virtual double Or() const override;        // logical OR of all matrix values, or NAN
+    virtual double Xor() const override;       // logical XOR of all matrix values, or NAN
+
+    virtual IterateResult Sum(bool bTextAsZero) const override;
+    virtual IterateResult SumSquare(bool bTextAsZero) const override;
+    virtual IterateResult Product(bool bTextAsZero) const override;
+    virtual size_t Count(bool bCountStrings) const override;
+    virtual size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const override;
+    virtual size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const override;
+
+    virtual double GetMaxValue( bool bTextAsZero ) const override;
+    virtual double GetMinValue( bool bTextAsZero ) const override;
+
+    virtual ScMatrixRef CompareMatrix(
+        sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions = nullptr ) const override;
 
     /**
      * Convert the content of matrix into a linear array of numeric values.
@@ -387,20 +584,20 @@ public:
      * @param bEmptyAsZero if true empty elements are mapped to zero values,
      *                     otherwise they become NaN values.
      */
-    void GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero = true ) const;
-    void MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const;
+    virtual void GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero = true ) const override;
+    virtual void MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const override;
 
-    void NotOp(ScMatrix& rMat);
-    void NegOp(ScMatrix& rMat);
-    void AddOp(double fVal, ScMatrix& rMat);
-    void SubOp(bool bFlag, double fVal, ScMatrix& rMat);
-    void MulOp(double fVal, ScMatrix& rMat);
-    void DivOp(bool bFlag, double fVal, ScMatrix& rMat);
-    void PowOp(bool bFlag, double fVal, ScMatrix& rMat);
+    virtual void NotOp(ScMatrix& rMat) override;
+    virtual void NegOp(ScMatrix& rMat) override;
+    virtual void AddOp(double fVal, ScMatrix& rMat) override;
+    virtual void SubOp(bool bFlag, double fVal, ScMatrix& rMat) override;
+    virtual void MulOp(double fVal, ScMatrix& rMat) override;
+    virtual void DivOp(bool bFlag, double fVal, ScMatrix& rMat) override;
+    virtual void PowOp(bool bFlag, double fVal, ScMatrix& rMat) override;
 
-    std::vector<ScMatrix::IterateResult> Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp);
+    virtual std::vector<ScMatrix::IterateResult> Collect(bool bTextAsZero, const std::vector<std::unique_ptr<sc::op::Op>>& aOp) override;
 
-    ScMatrix& operator+= ( const ScMatrix& r );
+    ScFullMatrix& operator+= ( const ScFullMatrix& r );
 
 #if DEBUG_MATRIX
     void Dump() const;
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 3fc85a6..bf22802 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -1889,7 +1889,7 @@ void Test::testMatrix()
     ScMatrixRef pMat, pMat2;
 
     // First, test the zero matrix type.
-    pMat = new ScMatrix(0, 0, 0.0);
+    pMat = new ScFullMatrix(0, 0, 0.0);
     SCSIZE nC, nR;
     pMat->GetDimensions(nC, nR);
     CPPUNIT_ASSERT_MESSAGE("matrix is not empty", nC == 0 && nR == 0);
@@ -1912,7 +1912,7 @@ void Test::testMatrix()
                            pMat->And() && pMat->Or());
 
     // Test the AND and OR evaluations.
-    pMat = new ScMatrix(2, 2, 0.0);
+    pMat = new ScFullMatrix(2, 2, 0.0);
 
     // Only some of the elements are non-zero.
     pMat->PutBoolean(true, 0, 0);
@@ -1927,7 +1927,7 @@ void Test::testMatrix()
     CPPUNIT_ASSERT_MESSAGE("incorrect AND result", pMat->And());
 
     // Now test the emtpy matrix type.
-    pMat = new ScMatrix(10, 20);
+    pMat = new ScFullMatrix(10, 20);
     pMat->GetDimensions(nC, nR);
     CPPUNIT_ASSERT_MESSAGE("matrix size is not as expected", nC == 10 && nR == 20);
     checkMatrixElements<AllEmptyMatrix>(*pMat);
@@ -1939,7 +1939,7 @@ void Test::testMatrix()
     checkMatrixElements<PartiallyFilledEmptyMatrix>(*pMat);
 
     // Test resizing.
-    pMat = new ScMatrix(0, 0);
+    pMat = new ScFullMatrix(0, 0);
     pMat->Resize(2, 2, 1.5);
     pMat->PutEmpty(1, 1);
 
@@ -1949,7 +1949,7 @@ void Test::testMatrix()
     CPPUNIT_ASSERT_MESSAGE("PutEmpty() call failed.", pMat->IsEmpty(1, 1));
 
     // Max and min values.
-    pMat = new ScMatrix(2, 2, 0.0);
+    pMat = new ScFullMatrix(2, 2, 0.0);
     pMat->PutDouble(-10, 0, 0);
     pMat->PutDouble(-12, 0, 1);
     pMat->PutDouble(-8, 1, 0);
@@ -1961,7 +1961,7 @@ void Test::testMatrix()
     CPPUNIT_ASSERT_EQUAL(-8.0, pMat->GetMaxValue(false)); // ignore text.
     pMat->PutBoolean(true, 0, 0);
     CPPUNIT_ASSERT_EQUAL(1.0, pMat->GetMaxValue(false));
-    pMat = new ScMatrix(2, 2, 10.0);
+    pMat = new ScFullMatrix(2, 2, 10.0);
     pMat->PutBoolean(false, 0, 0);
     pMat->PutDouble(12.5, 1, 1);
     CPPUNIT_ASSERT_EQUAL(0.0, pMat->GetMinValue(false));
@@ -1969,7 +1969,7 @@ void Test::testMatrix()
 
     // Convert matrix into a linear double array. String elements become NaN
     // and empty elements become 0.
-    pMat = new ScMatrix(3, 3);
+    pMat = new ScFullMatrix(3, 3);
     pMat->PutDouble(2.5, 0, 0);
     pMat->PutDouble(1.2, 0, 1);
     pMat->PutString(rPool.intern("A"), 1, 1);
@@ -1994,7 +1994,7 @@ void Test::testMatrix()
         }
     }
 
-    pMat2 = new ScMatrix(3, 3, 10.0);
+    pMat2 = new ScFullMatrix(3, 3, 10.0);
     pMat2->PutString(rPool.intern("B"), 1, 0);
     pMat2->MergeDoubleArray(aDoubles, ScMatrix::Mul);
 
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 655954e..df05e22 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -2169,7 +2169,7 @@ formula::FormulaTokenRef ScTable::ResolveStaticReference( SCCOL nCol1, SCROW nRo
     if (!ValidCol(nCol1) || !ValidCol(nCol2) || !ValidRow(nRow1) || !ValidRow(nRow2))
         return formula::FormulaTokenRef();
 
-    ScMatrixRef pMat(new ScMatrix(nCol2-nCol1+1, nRow2-nRow1+1, 0.0));
+    ScMatrixRef pMat(new ScFullMatrix(nCol2-nCol1+1, nRow2-nRow1+1, 0.0));
     for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
     {
         if (!aCol[nCol].ResolveStaticReference(*pMat, nCol2-nCol1, nRow1, nRow2))
diff --git a/sc/source/core/data/validat.cxx b/sc/source/core/data/validat.cxx
index 37a1bc9..437434a 100644
--- a/sc/source/core/data/validat.cxx
+++ b/sc/source/core/data/validat.cxx
@@ -643,7 +643,7 @@ bool ScValidationData::GetSelectionFromFormula(
         // is stored as a single value.
 
         // Use an interim matrix to create the TypedStrData below.
-        xMatRef = new ScMatrix(1, 1, 0.0);
+        xMatRef = new ScFullMatrix(1, 1, 0.0);
 
         sal_uInt16 nErrCode = aValidationSrc.GetErrCode();
         if (nErrCode)
diff --git a/sc/source/core/tool/addincol.cxx b/sc/source/core/tool/addincol.cxx
index 2618a51..ff9aaac 100644
--- a/sc/source/core/tool/addincol.cxx
+++ b/sc/source/core/tool/addincol.cxx
@@ -1576,7 +1576,7 @@ void ScUnoAddInCall::SetResult( const uno::Any& rNewRes )
                     }
                     if ( nMaxColCount && nRowCount )
                     {
-                        xMatrix = new ScMatrix(
+                        xMatrix = new ScFullMatrix(
                                 static_cast<SCSIZE>(nMaxColCount),
                                 static_cast<SCSIZE>(nRowCount), 0.0);
                         for (long nRow=0; nRow<nRowCount; nRow++)
@@ -1617,7 +1617,7 @@ void ScUnoAddInCall::SetResult( const uno::Any& rNewRes )
                     }
                     if ( nMaxColCount && nRowCount )
                     {
-                        xMatrix = new ScMatrix(
+                        xMatrix = new ScFullMatrix(
                                 static_cast<SCSIZE>(nMaxColCount),
                                 static_cast<SCSIZE>(nRowCount), 0.0);
                         for (long nRow=0; nRow<nRowCount; nRow++)
@@ -1658,7 +1658,7 @@ void ScUnoAddInCall::SetResult( const uno::Any& rNewRes )
                     }
                     if ( nMaxColCount && nRowCount )
                     {
-                        xMatrix = new ScMatrix(
+                        xMatrix = new ScFullMatrix(
                                 static_cast<SCSIZE>(nMaxColCount),
                                 static_cast<SCSIZE>(nRowCount), 0.0);
                         for (long nRow=0; nRow<nRowCount; nRow++)
diff --git a/sc/source/core/tool/ddelink.cxx b/sc/source/core/tool/ddelink.cxx
index 22f05e4..8a78554 100644
--- a/sc/source/core/tool/ddelink.cxx
+++ b/sc/source/core/tool/ddelink.cxx
@@ -89,7 +89,7 @@ ScDdeLink::ScDdeLink( ScDocument* pD, SvStream& rStream, ScMultipleReadHeader& r
     bool bHasValue;
     rStream.ReadCharAsBool( bHasValue );
     if ( bHasValue )
-        pResult = new ScMatrix(0, 0);
+        pResult = new ScFullMatrix(0, 0);
 
     if (rHdr.BytesLeft())       // neu in 388b und der 364w (RealTime-Client) Version
         rStream.ReadUChar( nMode );
@@ -155,7 +155,7 @@ sfx2::SvBaseLink::UpdateResult ScDdeLink::DataChanged(
     else                                // Daten aufteilen
     {
         //  Matrix immer neu anlegen, damit bIsString nicht durcheinanderkommt
-        pResult = new ScMatrix(nCols, nRows, 0.0);
+        pResult = new ScFullMatrix(nCols, nRows, 0.0);
 
         SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
         svl::SharedStringPool& rPool = pDoc->GetSharedStringPool();
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 085dc0f..a9f8a61 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -376,7 +376,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
                     if (!p2->IsEndFixed())
                         nRowEnd += i;
                     size_t nRowSize = nRowEnd - nRowStart + 1;
-                    ScMatrixRef pMat(new ScMatrix(nColSize, nRowSize));
+                    ScMatrixRef pMat(new ScFullMatrix(nColSize, nRowSize));
 
                     size_t nDataRowEnd = p2->GetArrayLength() - 1;
                     if (nRowStart > nDataRowEnd)
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 5517f48..bf3c0e2 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -4651,7 +4651,7 @@ double ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc )
                 break;
             case svExternalSingleRef:
                 {
-                    pSumExtraMatrix = new ScMatrix(1, 1, 0.0);
+                    pSumExtraMatrix = new ScFullMatrix(1, 1, 0.0);
                     ScExternalRefCache::TokenRef pToken;
                     PopExternalSingleRef(pToken);
                     if (!pToken)
@@ -5903,7 +5903,7 @@ void ScInterpreter::ScLookup()
         ScMatrixRef pDataMat2;
         if (bVertical)
         {
-            ScMatrixRef pTempMat(new ScMatrix(1, nR, 0.0));
+            ScMatrixRef pTempMat(new ScFullMatrix(1, nR, 0.0));
             for (SCSIZE i = 0; i < nR; ++i)
                 if (pDataMat->IsValue(0, i))
                     pTempMat->PutDouble(pDataMat->GetDouble(0, i), 0, i);
@@ -5913,7 +5913,7 @@ void ScInterpreter::ScLookup()
         }
         else
         {
-            ScMatrixRef pTempMat(new ScMatrix(nC, 1, 0.0));
+            ScMatrixRef pTempMat(new ScFullMatrix(nC, 1, 0.0));
             for (SCSIZE i = 0; i < nC; ++i)
                 if (pDataMat->IsValue(i, 0))
                     pTempMat->PutDouble(pDataMat->GetDouble(i, 0), i, 0);
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index eb9852e..a0933c0 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -319,9 +319,9 @@ ScMatrixRef ScInterpreter::GetNewMat(SCSIZE nC, SCSIZE nR, bool bEmpty)
 {
     ScMatrixRef pMat;
     if (bEmpty)
-        pMat = new ScMatrix(nC, nR);
+        pMat = new ScFullMatrix(nC, nR);
     else
-        pMat = new ScMatrix(nC, nR, 0.0);
+        pMat = new ScFullMatrix(nC, nR, 0.0);
 
     pMat->SetErrorInterpreter( this);
     // A temporary matrix is mutable and ScMatrix::CloneIfConst() returns the
@@ -463,17 +463,17 @@ ScMatrixRef ScInterpreter::GetMatrix()
             }
             if (pToken->GetType() == svDouble)
             {
-                pMat = new ScMatrix(1, 1, 0.0);
+                pMat = new ScFullMatrix(1, 1, 0.0);
                 pMat->PutDouble(pToken->GetDouble(), 0, 0);
             }
             else if (pToken->GetType() == svString)
             {
-                pMat = new ScMatrix(1, 1, 0.0);
+                pMat = new ScFullMatrix(1, 1, 0.0);
                 pMat->PutString(pToken->GetString(), 0, 0);
             }
             else
             {
-                pMat = new ScMatrix(1, 1);
+                pMat = new ScFullMatrix(1, 1);
             }
         }
         break;
diff --git a/sc/source/core/tool/jumpmatrix.cxx b/sc/source/core/tool/jumpmatrix.cxx
index ea27b97..f02612c2 100644
--- a/sc/source/core/tool/jumpmatrix.cxx
+++ b/sc/source/core/tool/jumpmatrix.cxx
@@ -29,7 +29,7 @@ const SCSIZE kBufferThreshhold = 128;
 
 ScJumpMatrix::ScJumpMatrix(SCSIZE nColsP, SCSIZE nRowsP)
     : pJump(new ScJumpMatrixEntry[nColsP * nRowsP])
-    , pMat(new ScMatrix(nColsP, nRowsP))
+    , pMat(new ScFullMatrix(nColsP, nRowsP))
     , pParams(nullptr)
     , nCols(nColsP)
     , nRows(nRowsP)
diff --git a/sc/source/core/tool/rangeseq.cxx b/sc/source/core/tool/rangeseq.cxx
index 6ec7e71..20b9419 100644
--- a/sc/source/core/tool/rangeseq.cxx
+++ b/sc/source/core/tool/rangeseq.cxx
@@ -372,7 +372,7 @@ ScMatrixRef ScSequenceToMatrix::CreateMixedMatrix( const css::uno::Any & rAny )
         if ( nMaxColCount && nRowCount )
         {
             OUString aUStr;
-            xMatrix = new ScMatrix(
+            xMatrix = new ScFullMatrix(
                     static_cast<SCSIZE>(nMaxColCount),
                     static_cast<SCSIZE>(nRowCount), 0.0);
             SCSIZE nCols, nRows;
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 2af2df3..e3823bd 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -208,7 +208,6 @@ class ScMatrixImpl: private boost::noncopyable
     MatrixImplType maMat;
     MatrixImplType maMatFlag;
     ScInterpreter* pErrorInterpreter;
-    bool            mbCloneIfConst; // Whether the matrix is cloned with a CloneIfConst() call.
 
 public:
     ScMatrixImpl(SCSIZE nC, SCSIZE nR);
@@ -219,8 +218,6 @@ public:
     ~ScMatrixImpl();
 
     void Clear();
-    void SetImmutable(bool bVal);
-    bool IsImmutable() const { return mbCloneIfConst;}
     void Resize(SCSIZE nC, SCSIZE nR);
     void Resize(SCSIZE nC, SCSIZE nR, double fVal);
     void SetErrorInterpreter( ScInterpreter* p);
@@ -282,9 +279,9 @@ public:
     double Or() const;
     double Xor() const;
 
-    ScMatrix::IterateResult Sum(bool bTextAsZero) const;
-    ScMatrix::IterateResult SumSquare(bool bTextAsZero) const;
-    ScMatrix::IterateResult Product(bool bTextAsZero) const;
+    ScFullMatrix::IterateResult Sum(bool bTextAsZero) const;
+    ScFullMatrix::IterateResult SumSquare(bool bTextAsZero) const;
+    ScFullMatrix::IterateResult Product(bool bTextAsZero) const;
     size_t Count(bool bCountStrings) const;
     size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const;
     size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const;
@@ -295,14 +292,14 @@ public:
     ScMatrixRef CompareMatrix( sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const;
 
     void GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const;
-    void MergeDoubleArray( std::vector<double>& rArray, ScMatrix::Op eOp ) const;
+    void MergeDoubleArray( std::vector<double>& rArray, ScFullMatrix::Op eOp ) const;
     void AddValues( const ScMatrixImpl& rMat );
 
     template<typename T>
     void ApplyOperation(T aOp, ScMatrixImpl& rMat);
 
     template<typename T>
-    std::vector<ScMatrix::IterateResult> ApplyCollectOperation(bool bTextAsZero, const std::vector<std::unique_ptr<T>>& aOp);
+    std::vector<ScFullMatrix::IterateResult> ApplyCollectOperation(bool bTextAsZero, const std::vector<std::unique_ptr<T>>& aOp);
 
 #if DEBUG_MATRIX
     void Dump() const;
@@ -313,13 +310,13 @@ private:
 };
 
 ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR) :
-    maMat(nR, nC), maMatFlag(nR, nC, SC_MATFLAG_EMPTYCELL), pErrorInterpreter(nullptr), mbCloneIfConst(true) {}
+    maMat(nR, nC), maMatFlag(nR, nC, SC_MATFLAG_EMPTYCELL), pErrorInterpreter(nullptr) {}
 
 ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR, double fInitVal) :
-    maMat(nR, nC, fInitVal), maMatFlag(nR, nC), pErrorInterpreter(nullptr), mbCloneIfConst(true) {}
+    maMat(nR, nC, fInitVal), maMatFlag(nR, nC), pErrorInterpreter(nullptr) {}
 
 ScMatrixImpl::ScMatrixImpl( size_t nC, size_t nR, const std::vector<double>& rInitVals ) :
-    maMat(nR, nC, rInitVals.begin(), rInitVals.end()), maMatFlag(nR, nC), pErrorInterpreter(nullptr), mbCloneIfConst(true) {}
+    maMat(nR, nC, rInitVals.begin(), rInitVals.end()), maMatFlag(nR, nC), pErrorInterpreter(nullptr) {}
 
 ScMatrixImpl::~ScMatrixImpl()
 {
@@ -332,11 +329,6 @@ void ScMatrixImpl::Clear()
     maMatFlag.clear();
 }
 
-void ScMatrixImpl::SetImmutable(bool bVal)
-{
-    mbCloneIfConst = bVal;
-}
-
 void ScMatrixImpl::Resize(SCSIZE nC, SCSIZE nR)
 {
     maMat.resize(nR, nC);
@@ -1007,13 +999,13 @@ template<typename _Op>
 class WalkElementBlocks
 {
     _Op maOp;
-    ScMatrix::IterateResult maRes;
+    ScFullMatrix::IterateResult maRes;
     bool mbFirst:1;
     bool mbTextAsZero:1;
 public:
     WalkElementBlocks(bool bTextAsZero) : maRes(_Op::InitVal, _Op::InitVal, 0), mbFirst(true), mbTextAsZero(bTextAsZero) {}
 
-    const ScMatrix::IterateResult& getResult() const { return maRes; }
+    const ScFullMatrix::IterateResult& getResult() const { return maRes; }
 
     void operator() (const MatrixImplType::element_block_node_type& node)
     {
@@ -1076,7 +1068,7 @@ template<typename _Op>
 class WalkElementBlocksMultipleValues
 {
     const std::vector<std::unique_ptr<_Op>>& maOp;
-    std::vector<ScMatrix::IterateResult> maRes;
+    std::vector<ScFullMatrix::IterateResult> maRes;
     bool mbFirst:1;
     bool mbTextAsZero:1;
 public:
@@ -1090,7 +1082,7 @@ public:
         maRes.emplace_back(0.0, 0.0, 0); // count
     }
 
-    const std::vector<ScMatrix::IterateResult>& getResult() const { return maRes; }
+    const std::vector<ScFullMatrix::IterateResult>& getResult() const { return maRes; }
 
     void operator() (const MatrixImplType::element_block_node_type& node)
     {
@@ -1760,7 +1752,7 @@ public:
 namespace {
 
 template<typename TOp>
-ScMatrix::IterateResult GetValueWithCount(bool bTextAsZero, const MatrixImplType& maMat)
+ScFullMatrix::IterateResult GetValueWithCount(bool bTextAsZero, const MatrixImplType& maMat)
 {
     WalkElementBlocks<TOp> aFunc(bTextAsZero);
     maMat.walk(aFunc);
@@ -1769,17 +1761,17 @@ ScMatrix::IterateResult GetValueWithCount(bool bTextAsZero, const MatrixImplType
 
 }
 
-ScMatrix::IterateResult ScMatrixImpl::Sum(bool bTextAsZero) const
+ScFullMatrix::IterateResult ScMatrixImpl::Sum(bool bTextAsZero) const
 {
     return GetValueWithCount<sc::op::Sum>(bTextAsZero, maMat);
 }
 
-ScMatrix::IterateResult ScMatrixImpl::SumSquare(bool bTextAsZero) const
+ScFullMatrix::IterateResult ScMatrixImpl::SumSquare(bool bTextAsZero) const
 {
     return GetValueWithCount<sc::op::SumSquare>(bTextAsZero, maMat);
 }
 
-ScMatrix::IterateResult ScMatrixImpl::Product(bool bTextAsZero) const
+ScFullMatrix::IterateResult ScMatrixImpl::Product(bool bTextAsZero) const
 {
     return GetValueWithCount<sc::op::Product>(bTextAsZero, maMat);
 }
@@ -1839,7 +1831,7 @@ ScMatrixRef ScMatrixImpl::CompareMatrix(
             if (nSize != rResVal.size())
                 ScMatrixRef();
 
-            return ScMatrixRef(new ScMatrix(aSize.column, aSize.row, rResVal));
+            return ScMatrixRef(new ScFullMatrix(aSize.column, aSize.row, rResVal));
         }
     }
 
@@ -1851,7 +1843,7 @@ ScMatrixRef ScMatrixImpl::CompareMatrix(
     if (nSize != rResVal.size())
         ScMatrixRef();
 
-    return ScMatrixRef(new ScMatrix(aSize.column, aSize.row, rResVal));
+    return ScMatrixRef(new ScFullMatrix(aSize.column, aSize.row, rResVal));
 }
 
 void ScMatrixImpl::GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const
@@ -1862,7 +1854,7 @@ void ScMatrixImpl::GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZer
     aFunc.swap(rArray);
 }
 
-void ScMatrixImpl::MergeDoubleArray( std::vector<double>& rArray, ScMatrix::Op eOp ) const
+void ScMatrixImpl::MergeDoubleArray( std::vector<double>& rArray, ScFullMatrix::Op eOp ) const
 {
     MatrixImplType::size_pair_type aSize = maMat.size();
     size_t nSize = aSize.row*aSize.column;
@@ -1871,7 +1863,7 @@ void ScMatrixImpl::MergeDoubleArray( std::vector<double>& rArray, ScMatrix::Op e
 
     switch (eOp)
     {
-        case ScMatrix::Mul:
+        case ScFullMatrix::Mul:
         {
             MergeDoubleArrayFunc<ArrayMul> aFunc(rArray);
             maMat.walk(aFunc);
@@ -2168,7 +2160,7 @@ void ScMatrixImpl::ApplyOperation(T aOp, ScMatrixImpl& rMat)
 }
 
 template<typename T>
-std::vector<ScMatrix::IterateResult> ScMatrixImpl::ApplyCollectOperation(bool bTextAsZero, const std::vector<std::unique_ptr<T>>& aOp)
+std::vector<ScFullMatrix::IterateResult> ScMatrixImpl::ApplyCollectOperation(bool bTextAsZero, const std::vector<std::unique_ptr<T>>& aOp)
 {
     WalkElementBlocksMultipleValues<T> aFunc(bTextAsZero, aOp);
     maMat.walk(aFunc);
@@ -2231,36 +2223,39 @@ void ScMatrix::DecRef() const
         delete this;
 }
 
-ScMatrix::ScMatrix( SCSIZE nC, SCSIZE nR) :
-    pImpl(new ScMatrixImpl(nC, nR)), nRefCnt(0)
+ScFullMatrix::ScFullMatrix( SCSIZE nC, SCSIZE nR) :
+    ScMatrix(),
+    pImpl(new ScMatrixImpl(nC, nR))
 {
     SAL_WARN_IF( !nC, "sc", "ScMatrix with 0 columns!");
     SAL_WARN_IF( !nR, "sc", "ScMatrix with 0 rows!");
 }
 
-ScMatrix::ScMatrix(SCSIZE nC, SCSIZE nR, double fInitVal) :
-    pImpl(new ScMatrixImpl(nC, nR, fInitVal)), nRefCnt(0)
+ScFullMatrix::ScFullMatrix(SCSIZE nC, SCSIZE nR, double fInitVal) :
+    ScMatrix(),
+    pImpl(new ScMatrixImpl(nC, nR, fInitVal))
 {
     SAL_WARN_IF( !nC, "sc", "ScMatrix with 0 columns!");
     SAL_WARN_IF( !nR, "sc", "ScMatrix with 0 rows!");
 }
 
-ScMatrix::ScMatrix( size_t nC, size_t nR, const std::vector<double>& rInitVals ) :
-    pImpl(new ScMatrixImpl(nC, nR, rInitVals)), nRefCnt(0)
+ScFullMatrix::ScFullMatrix( size_t nC, size_t nR, const std::vector<double>& rInitVals ) :
+    ScMatrix(),
+    pImpl(new ScMatrixImpl(nC, nR, rInitVals))
 {
     SAL_WARN_IF( !nC, "sc", "ScMatrix with 0 columns!");
     SAL_WARN_IF( !nR, "sc", "ScMatrix with 0 rows!");
 }
 
-ScMatrix::~ScMatrix()
+ScFullMatrix::~ScFullMatrix()
 {
 }
 
-ScMatrix* ScMatrix::Clone() const
+ScMatrix* ScFullMatrix::Clone() const
 {
     SCSIZE nC, nR;
     pImpl->GetDimensions(nC, nR);
-    ScMatrix* pScMat = new ScMatrix(nC, nR);
+    ScMatrix* pScMat = new ScFullMatrix(nC, nR);
     MatCopy(*pScMat);
     pScMat->SetErrorInterpreter(pImpl->GetErrorInterpreter());    // TODO: really?
     return pScMat;
@@ -2268,339 +2263,345 @@ ScMatrix* ScMatrix::Clone() const
 
 ScMatrix* ScMatrix::CloneIfConst()
 {
-    return pImpl->IsImmutable() ? Clone() : this;
+    return mbCloneIfConst ? Clone() : this;
 }
 
 void ScMatrix::SetImmutable( bool bVal )
 {
-    pImpl->SetImmutable(bVal);
+    mbCloneIfConst = bVal;
 }
 
-void ScMatrix::Resize( SCSIZE nC, SCSIZE nR)
+void ScFullMatrix::Resize( SCSIZE nC, SCSIZE nR)
 {
     pImpl->Resize(nC, nR);
 }
 
-void ScMatrix::Resize(SCSIZE nC, SCSIZE nR, double fVal)
+void ScFullMatrix::Resize(SCSIZE nC, SCSIZE nR, double fVal)
 {
     pImpl->Resize(nC, nR, fVal);
 }
 
-ScMatrix* ScMatrix::CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const
+ScMatrix* ScFullMatrix::CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const
 {
-    ScMatrix* pScMat = new ScMatrix(nNewCols, nNewRows);
+    ScMatrix* pScMat = new ScFullMatrix(nNewCols, nNewRows);
     MatCopy(*pScMat);
     pScMat->SetErrorInterpreter(pImpl->GetErrorInterpreter());
     return pScMat;
 }
 
-void ScMatrix::SetErrorInterpreter( ScInterpreter* p)
+void ScFullMatrix::SetErrorInterpreter( ScInterpreter* p)
 {
     pImpl->SetErrorInterpreter(p);
 }
 
-void ScMatrix::GetDimensions( SCSIZE& rC, SCSIZE& rR) const
+void ScFullMatrix::GetDimensions( SCSIZE& rC, SCSIZE& rR) const
 {
     pImpl->GetDimensions(rC, rR);
 }
 
-SCSIZE ScMatrix::GetElementCount() const
+SCSIZE ScFullMatrix::GetElementCount() const
 {
     return pImpl->GetElementCount();
 }
 
-bool ScMatrix::ValidColRow( SCSIZE nC, SCSIZE nR) const
+bool ScFullMatrix::ValidColRow( SCSIZE nC, SCSIZE nR) const
 {
     return pImpl->ValidColRow(nC, nR);
 }
 
-bool ScMatrix::ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const
+bool ScFullMatrix::ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const
 {
     return pImpl->ValidColRowReplicated(rC, rR);
 }
 
-bool ScMatrix::ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const
+bool ScFullMatrix::ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const
 {
     return ValidColRow( rC, rR) || ValidColRowReplicated( rC, rR);
 }
 
-void ScMatrix::PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
+void ScFullMatrix::PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
 {
     pImpl->PutDouble(fVal, nC, nR);
 }
 
-void ScMatrix::PutDouble( double fVal, SCSIZE nIndex)
+void ScFullMatrix::PutDouble( double fVal, SCSIZE nIndex)
 {
     pImpl->PutDouble(fVal, nIndex);
 }
 
-void ScMatrix::PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
+void ScFullMatrix::PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
 {
     pImpl->PutDouble(pArray, nLen, nC, nR);
 }
 
-void ScMatrix::PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR)
+void ScFullMatrix::PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR)
 {
     pImpl->PutString(rStr, nC, nR);
 }
 
-void ScMatrix::PutString(const svl::SharedString& rStr, SCSIZE nIndex)
+void ScFullMatrix::PutString(const svl::SharedString& rStr, SCSIZE nIndex)
 {
     pImpl->PutString(rStr, nIndex);
 }
 
-void ScMatrix::PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
+void ScFullMatrix::PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
 {
     pImpl->PutString(pArray, nLen, nC, nR);
 }
 
-void ScMatrix::PutEmpty(SCSIZE nC, SCSIZE nR)
+void ScFullMatrix::PutEmpty(SCSIZE nC, SCSIZE nR)
 {
     pImpl->PutEmpty(nC, nR);
 }
 
-void ScMatrix::PutEmptyPath(SCSIZE nC, SCSIZE nR)
+void ScFullMatrix::PutEmptyPath(SCSIZE nC, SCSIZE nR)
 {
     pImpl->PutEmptyPath(nC, nR);
 }
 
-void ScMatrix::PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR )
+void ScFullMatrix::PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR )
 {
     pImpl->PutError(nErrorCode, nC, nR);
 }
 
-void ScMatrix::PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
+void ScFullMatrix::PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
 {
     pImpl->PutBoolean(bVal, nC, nR);
 }
 
-sal_uInt16 ScMatrix::GetError( SCSIZE nC, SCSIZE nR) const
+sal_uInt16 ScFullMatrix::GetError( SCSIZE nC, SCSIZE nR) const
 {
     return pImpl->GetError(nC, nR);
 }
 
-double ScMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const
+double ScFullMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const
 {
     return pImpl->GetDouble(nC, nR);
 }
 
-double ScMatrix::GetDouble( SCSIZE nIndex) const
+double ScFullMatrix::GetDouble( SCSIZE nIndex) const
 {
     return pImpl->GetDouble(nIndex);
 }
 
-svl::SharedString ScMatrix::GetString(SCSIZE nC, SCSIZE nR) const
+svl::SharedString ScFullMatrix::GetString(SCSIZE nC, SCSIZE nR) const
 {
     return pImpl->GetString(nC, nR);
 }
 
-svl::SharedString ScMatrix::GetString( SCSIZE nIndex) const
+svl::SharedString ScFullMatrix::GetString( SCSIZE nIndex) const
 {
     return pImpl->GetString(nIndex);
 }
 
-svl::SharedString ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
+svl::SharedString ScFullMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
 {
     return pImpl->GetString(rFormatter, nC, nR);
 }
 
-ScMatrixValue ScMatrix::Get(SCSIZE nC, SCSIZE nR) const
+ScMatrixValue ScFullMatrix::Get(SCSIZE nC, SCSIZE nR) const
 {
     return pImpl->Get(nC, nR);
 }
 
-bool ScMatrix::IsString( SCSIZE nIndex ) const
+bool ScFullMatrix::IsString( SCSIZE nIndex ) const
 {
     return pImpl->IsString(nIndex);
 }
 
-bool ScMatrix::IsString( SCSIZE nC, SCSIZE nR ) const
+bool ScFullMatrix::IsString( SCSIZE nC, SCSIZE nR ) const
 {
     return pImpl->IsString(nC, nR);
 }
 
-bool ScMatrix::IsEmpty( SCSIZE nC, SCSIZE nR ) const
+bool ScFullMatrix::IsEmpty( SCSIZE nC, SCSIZE nR ) const
 {
     return pImpl->IsEmpty(nC, nR);
 }
 
-bool ScMatrix::IsEmptyCell( SCSIZE nC, SCSIZE nR ) const
+bool ScFullMatrix::IsEmptyCell( SCSIZE nC, SCSIZE nR ) const
 {
     return pImpl->IsEmptyCell(nC, nR);
 }
 
-bool ScMatrix::IsEmptyResult( SCSIZE nC, SCSIZE nR ) const
+bool ScFullMatrix::IsEmptyResult( SCSIZE nC, SCSIZE nR ) const
 {
     return pImpl->IsEmptyResult(nC, nR);
 }
 
-bool ScMatrix::IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
+bool ScFullMatrix::IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
 {
     return pImpl->IsEmptyPath(nC, nR);
 }
 
-bool ScMatrix::IsValue( SCSIZE nIndex ) const
+bool ScFullMatrix::IsValue( SCSIZE nIndex ) const
 {
     return pImpl->IsValue(nIndex);
 }
 
-bool ScMatrix::IsValue( SCSIZE nC, SCSIZE nR ) const
+bool ScFullMatrix::IsValue( SCSIZE nC, SCSIZE nR ) const
 {
     return pImpl->IsValue(nC, nR);
 }
 
-bool ScMatrix::IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
+bool ScFullMatrix::IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
 {
     return pImpl->IsValueOrEmpty(nC, nR);
 }
 
-bool ScMatrix::IsBoolean( SCSIZE nC, SCSIZE nR ) const
+bool ScFullMatrix::IsBoolean( SCSIZE nC, SCSIZE nR ) const
 {
     return pImpl->IsBoolean(nC, nR);
 }
 
-bool ScMatrix::IsNumeric() const
+bool ScFullMatrix::IsNumeric() const
 {
     return pImpl->IsNumeric();
 }
 
-void ScMatrix::MatCopy(ScMatrix& mRes) const
+void ScFullMatrix::MatCopy(ScMatrix& mRes) const
 {
-    pImpl->MatCopy(*mRes.pImpl);
+    // FIXME
+    ScFullMatrix* pMatrix = dynamic_cast<ScFullMatrix*>(&mRes);
+    assert(pMatrix);
+    pImpl->MatCopy(*pMatrix->pImpl);
 }
 
-void ScMatrix::MatTrans(ScMatrix& mRes) const
+void ScFullMatrix::MatTrans(ScMatrix& mRes) const
 {
-    pImpl->MatTrans(*mRes.pImpl);
+    // FIXME
+    ScFullMatrix* pMatrix = dynamic_cast<ScFullMatrix*>(&mRes);
+    assert(pMatrix);
+    pImpl->MatTrans(*pMatrix->pImpl);
 }
 
-void ScMatrix::FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 )
+void ScFullMatrix::FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 )
 {
     pImpl->FillDouble(fVal, nC1, nR1, nC2, nR2);
 }
 
-void ScMatrix::PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR )
+void ScFullMatrix::PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR )
 {
     pImpl->PutDoubleVector(rVec, nC, nR);
 }
 
-void ScMatrix::PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR )
+void ScFullMatrix::PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR )
 {
     pImpl->PutStringVector(rVec, nC, nR);
 }
 
-void ScMatrix::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
+void ScFullMatrix::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
 {
     pImpl->PutEmptyVector(nCount, nC, nR);
 }
 
-void ScMatrix::PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
+void ScFullMatrix::PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
 {
     pImpl->PutEmptyResultVector(nCount, nC, nR);
 }
 
-void ScMatrix::PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
+void ScFullMatrix::PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
 {
     pImpl->PutEmptyPathVector(nCount, nC, nR);
 }
 
-void ScMatrix::CompareEqual()
+void ScFullMatrix::CompareEqual()
 {
     pImpl->CompareEqual();
 }
 
-void ScMatrix::CompareNotEqual()
+void ScFullMatrix::CompareNotEqual()
 {
     pImpl->CompareNotEqual();
 }
 
-void ScMatrix::CompareLess()
+void ScFullMatrix::CompareLess()
 {
     pImpl->CompareLess();
 }
 
-void ScMatrix::CompareGreater()
+void ScFullMatrix::CompareGreater()
 {
     pImpl->CompareGreater();
 }
 
-void ScMatrix::CompareLessEqual()
+void ScFullMatrix::CompareLessEqual()
 {
     pImpl->CompareLessEqual();
 }
 
-void ScMatrix::CompareGreaterEqual()
+void ScFullMatrix::CompareGreaterEqual()
 {
     pImpl->CompareGreaterEqual();
 }
 
-double ScMatrix::And() const
+double ScFullMatrix::And() const
 {
     return pImpl->And();
 }
 
-double ScMatrix::Or() const
+double ScFullMatrix::Or() const
 {
     return pImpl->Or();
 }
 
-double ScMatrix::Xor() const
+double ScFullMatrix::Xor() const
 {
     return pImpl->Xor();
 }
 
-ScMatrix::IterateResult ScMatrix::Sum(bool bTextAsZero) const
+ScFullMatrix::IterateResult ScFullMatrix::Sum(bool bTextAsZero) const
 {
     return pImpl->Sum(bTextAsZero);
 }
 
-ScMatrix::IterateResult ScMatrix::SumSquare(bool bTextAsZero) const
+ScFullMatrix::IterateResult ScFullMatrix::SumSquare(bool bTextAsZero) const
 {
     return pImpl->SumSquare(bTextAsZero);
 }
 
-ScMatrix::IterateResult ScMatrix::Product(bool bTextAsZero) const
+ScFullMatrix::IterateResult ScFullMatrix::Product(bool bTextAsZero) const
 {
     return pImpl->Product(bTextAsZero);
 }
 
-size_t ScMatrix::Count(bool bCountStrings) const
+size_t ScFullMatrix::Count(bool bCountStrings) const
 {
     return pImpl->Count(bCountStrings);
 }
 
-size_t ScMatrix::MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const
+size_t ScFullMatrix::MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const
 {
     return pImpl->MatchDoubleInColumns(fValue, nCol1, nCol2);
 }
 
-size_t ScMatrix::MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const
+size_t ScFullMatrix::MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const
 {
     return pImpl->MatchStringInColumns(rStr, nCol1, nCol2);
 }
 
-double ScMatrix::GetMaxValue( bool bTextAsZero ) const
+double ScFullMatrix::GetMaxValue( bool bTextAsZero ) const
 {
     return pImpl->GetMaxValue(bTextAsZero);
 }
 
-double ScMatrix::GetMinValue( bool bTextAsZero ) const
+double ScFullMatrix::GetMinValue( bool bTextAsZero ) const
 {
     return pImpl->GetMinValue(bTextAsZero);
 }
 
-ScMatrixRef ScMatrix::CompareMatrix(
+ScMatrixRef ScFullMatrix::CompareMatrix(
     sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const
 {
     return pImpl->CompareMatrix(rComp, nMatPos, pOptions);
 }
 
-void ScMatrix::GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const
+void ScFullMatrix::GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const
 {
     pImpl->GetDoubleArray(rArray, bEmptyAsZero);
 }
 
-void ScMatrix::MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const
+void ScFullMatrix::MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const
 {
     pImpl->MergeDoubleArray(rArray, eOp);
 }
@@ -2708,95 +2709,125 @@ public:
 
 }
 
-void ScMatrix::NotOp( ScMatrix& rMat)
+void ScFullMatrix::NotOp( ScMatrix& rMat)
 {
     auto not_ = [](double a, double){return double(a == 0.0);};
     matop::MatOp<decltype(not_), double> aOp(not_, pImpl->GetErrorInterpreter());
-    pImpl->ApplyOperation(aOp, *rMat.pImpl);
+    // FIXME
+    ScFullMatrix* pMatrix = dynamic_cast<ScFullMatrix*>(&rMat);
+    assert(pMatrix);
+    pImpl->ApplyOperation(aOp, *pMatrix->pImpl);
 }
 
-void ScMatrix::NegOp( ScMatrix& rMat)
+void ScFullMatrix::NegOp( ScMatrix& rMat)
 {
     auto neg_ = [](double a, double){return -a;};
     matop::MatOp<decltype(neg_), double> aOp(neg_, pImpl->GetErrorInterpreter());
-    pImpl->ApplyOperation(aOp, *rMat.pImpl);
+    // FIXME
+    ScFullMatrix* pMatrix = dynamic_cast<ScFullMatrix*>(&rMat);
+    assert(pMatrix);
+    pImpl->ApplyOperation(aOp, *pMatrix->pImpl);
 }
 
-void ScMatrix::AddOp( double fVal, ScMatrix& rMat)
+void ScFullMatrix::AddOp( double fVal, ScMatrix& rMat)
 {
     auto add_ = [](double a, double b){return a + b;};
     matop::MatOp<decltype(add_)> aOp(add_, pImpl->GetErrorInterpreter(), fVal);
-    pImpl->ApplyOperation(aOp, *rMat.pImpl);
+    // FIXME
+    ScFullMatrix* pMatrix = dynamic_cast<ScFullMatrix*>(&rMat);
+    assert(pMatrix);
+    pImpl->ApplyOperation(aOp, *pMatrix->pImpl);
 }
 
-void ScMatrix::SubOp( bool bFlag, double fVal, ScMatrix& rMat)
+void ScFullMatrix::SubOp( bool bFlag, double fVal, ScMatrix& rMat)
 {
     if (bFlag)
     {
         auto sub_ = [](double a, double b){return b - a;};
         matop::MatOp<decltype(sub_)> aOp(sub_, pImpl->GetErrorInterpreter(), fVal);
-        pImpl->ApplyOperation(aOp, *rMat.pImpl);
+        // FIXME
+        ScFullMatrix* pMatrix = dynamic_cast<ScFullMatrix*>(&rMat);
+        assert(pMatrix);
+        pImpl->ApplyOperation(aOp, *pMatrix->pImpl);
     }
     else
     {
         auto sub_ = [](double a, double b){return a - b;};
         matop::MatOp<decltype(sub_)> aOp(sub_, pImpl->GetErrorInterpreter(), fVal);
-        pImpl->ApplyOperation(aOp, *rMat.pImpl);
+        // FIXME
+        ScFullMatrix* pMatrix = dynamic_cast<ScFullMatrix*>(&rMat);
+        assert(pMatrix);
+        pImpl->ApplyOperation(aOp, *pMatrix->pImpl);
     }
 }
 
-void ScMatrix::MulOp( double fVal, ScMatrix& rMat)
+void ScFullMatrix::MulOp( double fVal, ScMatrix& rMat)
 {
     auto mul_ = [](double a, double b){return a * b;};
     matop::MatOp<decltype(mul_)> aOp(mul_, pImpl->GetErrorInterpreter(), fVal);
-    pImpl->ApplyOperation(aOp, *rMat.pImpl);
+    // FIXME
+    ScFullMatrix* pMatrix = dynamic_cast<ScFullMatrix*>(&rMat);
+    assert(pMatrix);
+    pImpl->ApplyOperation(aOp, *pMatrix->pImpl);
 }
 
-void ScMatrix::DivOp( bool bFlag, double fVal, ScMatrix& rMat)
+void ScFullMatrix::DivOp( bool bFlag, double fVal, ScMatrix& rMat)
 {
     if (bFlag)
     {
         auto div_ = [](double a, double b){return sc::div(b, a);};

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list