LCOV - code coverage report
Current view: top level - sc/source/core/tool - scmatrix.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 666 1072 62.1 %
Date: 2015-06-13 12:38:46 Functions: 251 918 27.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "scmatrix.hxx"
      21             : #include "global.hxx"
      22             : #include "address.hxx"
      23             : #include <formula/errorcodes.hxx>
      24             : #include "interpre.hxx"
      25             : #include "mtvelements.hxx"
      26             : #include "compare.hxx"
      27             : #include "math.hxx"
      28             : 
      29             : #include <boost/noncopyable.hpp>
      30             : #include <svl/zforlist.hxx>
      31             : #include <svl/sharedstring.hxx>
      32             : #include <tools/stream.hxx>
      33             : #include <rtl/math.hxx>
      34             : 
      35             : #include <math.h>
      36             : 
      37             : #include <vector>
      38             : #include <limits>
      39             : 
      40             : #include <mdds/multi_type_matrix.hpp>
      41             : #include <mdds/multi_type_vector_types.hpp>
      42             : #include <mdds/multi_type_vector_trait.hpp>
      43             : 
      44             : #if DEBUG_MATRIX
      45             : #include <iostream>
      46             : using std::cout;
      47             : using std::endl;
      48             : #endif
      49             : 
      50             : using ::std::pair;
      51             : using ::std::for_each;
      52             : using ::std::count_if;
      53             : using ::std::advance;
      54             : using ::std::unary_function;
      55             : 
      56             : /**
      57             :  * Custom string trait struct to tell mdds::multi_type_matrix about the
      58             :  * custom string type and how to handle blocks storing them.
      59             :  */
      60             : struct custom_string_trait
      61             : {
      62             :     typedef svl::SharedString string_type;
      63             :     typedef sc::string_block string_element_block;
      64             : 
      65             :     static const mdds::mtv::element_t string_type_identifier = sc::element_type_string;
      66             : 
      67             :     typedef mdds::mtv::custom_block_func1<sc::string_block> element_block_func;
      68             : };
      69             : 
      70             : typedef mdds::multi_type_matrix<custom_string_trait> MatrixImplType;
      71             : 
      72             : namespace {
      73             : 
      74             : struct ElemEqualZero : public unary_function<double, double>
      75             : {
      76           0 :     double operator() (double val) const
      77             :     {
      78           0 :         if (!::rtl::math::isFinite(val))
      79           0 :             return val;
      80           0 :         return val == 0.0 ? 1.0 : 0.0;
      81             :     }
      82             : };
      83             : 
      84             : struct ElemNotEqualZero : public unary_function<double, double>
      85             : {
      86           0 :     double operator() (double val) const
      87             :     {
      88           0 :         if (!::rtl::math::isFinite(val))
      89           0 :             return val;
      90           0 :         return val != 0.0 ? 1.0 : 0.0;
      91             :     }
      92             : };
      93             : 
      94             : struct ElemGreaterZero : public unary_function<double, double>
      95             : {
      96           0 :     double operator() (double val) const
      97             :     {
      98           0 :         if (!::rtl::math::isFinite(val))
      99           0 :             return val;
     100           0 :         return val > 0.0 ? 1.0 : 0.0;
     101             :     }
     102             : };
     103             : 
     104             : struct ElemLessZero : public unary_function<double, double>
     105             : {
     106           0 :     double operator() (double val) const
     107             :     {
     108           0 :         if (!::rtl::math::isFinite(val))
     109           0 :             return val;
     110           0 :         return val < 0.0 ? 1.0 : 0.0;
     111             :     }
     112             : };
     113             : 
     114             : struct ElemGreaterEqualZero : public unary_function<double, double>
     115             : {
     116           0 :     double operator() (double val) const
     117             :     {
     118           0 :         if (!::rtl::math::isFinite(val))
     119           0 :             return val;
     120           0 :         return val >= 0.0 ? 1.0 : 0.0;
     121             :     }
     122             : };
     123             : 
     124             : struct ElemLessEqualZero : public unary_function<double, double>
     125             : {
     126           0 :     double operator() (double val) const
     127             :     {
     128           0 :         if (!::rtl::math::isFinite(val))
     129           0 :             return val;
     130           0 :         return val <= 0.0 ? 1.0 : 0.0;
     131             :     }
     132             : };
     133             : 
     134             : template<typename _Comp>
     135           0 : class CompareMatrixElemFunc : std::unary_function<MatrixImplType::element_block_node_type, void>
     136             : {
     137             :     static _Comp maComp;
     138             : 
     139             :     std::vector<double> maNewMatValues;     // double instead of bool to transport error values
     140             :     size_t mnRow;
     141             :     size_t mnCol;
     142             : public:
     143           0 :     CompareMatrixElemFunc( size_t nRow, size_t nCol ) : mnRow(nRow), mnCol(nCol)
     144             :     {
     145           0 :         maNewMatValues.reserve(nRow*nCol);
     146           0 :     }
     147             : 
     148           0 :     void operator() (const MatrixImplType::element_block_node_type& node)
     149             :     {
     150           0 :         switch (node.type)
     151             :         {
     152             :             case mdds::mtm::element_numeric:
     153             :             {
     154             :                 typedef MatrixImplType::numeric_block_type block_type;
     155             : 
     156           0 :                 block_type::const_iterator it = block_type::begin(*node.data);
     157           0 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
     158           0 :                 for (; it != itEnd; ++it)
     159             :                 {
     160           0 :                     double fVal = *it;
     161           0 :                     maNewMatValues.push_back(maComp(fVal));
     162             :                 }
     163             :             }
     164           0 :             break;
     165             :             case mdds::mtm::element_boolean:
     166             :             {
     167             :                 typedef MatrixImplType::boolean_block_type block_type;
     168             : 
     169           0 :                 block_type::const_iterator it = block_type::begin(*node.data);
     170           0 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
     171           0 :                 for (; it != itEnd; ++it)
     172             :                 {
     173           0 :                     double fVal = *it ? 1.0 : 0.0;
     174           0 :                     maNewMatValues.push_back(maComp(fVal));
     175             :                 }
     176             :             }
     177           0 :             break;
     178             :             case mdds::mtm::element_string:
     179             :             case mdds::mtm::element_empty:
     180             :             default:
     181             :                 // Fill it with false.
     182           0 :                 maNewMatValues.resize(maNewMatValues.size() + node.size, 0.0);
     183             :         }
     184           0 :     }
     185             : 
     186           0 :     void swap( MatrixImplType& rMat )
     187             :     {
     188           0 :         MatrixImplType aNewMat(mnRow, mnCol, maNewMatValues.begin(), maNewMatValues.end());
     189           0 :         rMat.swap(aNewMat);
     190           0 :     }
     191             : };
     192             : 
     193             : template<typename _Comp>
     194             : _Comp CompareMatrixElemFunc<_Comp>::maComp;
     195             : 
     196             : }
     197             : 
     198             : /* TODO: it would be good if mdds had get/set<sal_uInt8> additionally to
     199             :  * get/set<bool>, we're abusing double here. */
     200             : typedef double TMatFlag;
     201             : const TMatFlag SC_MATFLAG_EMPTYCELL   = 0.0;
     202             : const TMatFlag SC_MATFLAG_EMPTYRESULT = 1.0;
     203             : const TMatFlag SC_MATFLAG_EMPTYPATH   = 2.0;
     204             : 
     205             : class ScMatrixImpl: private boost::noncopyable
     206             : {
     207             :     MatrixImplType maMat;
     208             :     MatrixImplType maMatFlag;
     209             :     ScInterpreter* pErrorInterpreter;
     210             :     bool            mbCloneIfConst; // Whether the matrix is cloned with a CloneIfConst() call.
     211             : 
     212             : public:
     213             :     ScMatrixImpl(SCSIZE nC, SCSIZE nR);
     214             :     ScMatrixImpl(SCSIZE nC, SCSIZE nR, double fInitVal);
     215             : 
     216             :     ScMatrixImpl( size_t nC, size_t nR, const std::vector<double>& rInitVals );
     217             : 
     218             :     ~ScMatrixImpl();
     219             : 
     220             :     void Clear();
     221             :     void SetImmutable(bool bVal);
     222           0 :     bool IsImmutable() const { return mbCloneIfConst;}
     223             :     void Resize(SCSIZE nC, SCSIZE nR);
     224             :     void Resize(SCSIZE nC, SCSIZE nR, double fVal);
     225             :     void SetErrorInterpreter( ScInterpreter* p);
     226           0 :     ScInterpreter* GetErrorInterpreter() const { return pErrorInterpreter; }
     227             : 
     228             :     void GetDimensions( SCSIZE& rC, SCSIZE& rR) const;
     229             :     SCSIZE GetElementCount() const;
     230             :     bool ValidColRow( SCSIZE nC, SCSIZE nR) const;
     231             :     bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const;
     232             :     bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const;
     233             :     void SetErrorAtInterpreter( sal_uInt16 nError ) const;
     234             : 
     235             :     void PutDouble(double fVal, SCSIZE nC, SCSIZE nR);
     236             :     void PutDouble( double fVal, SCSIZE nIndex);
     237             :     void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR);
     238             : 
     239             :     void PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR);
     240             :     void PutString(const svl::SharedString& rStr, SCSIZE nIndex);
     241             :     void PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR);
     242             : 
     243             :     void PutEmpty(SCSIZE nC, SCSIZE nR);
     244             :     void PutEmptyPath(SCSIZE nC, SCSIZE nR);
     245             :     void PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR );
     246             :     void PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR);
     247             :     sal_uInt16 GetError( SCSIZE nC, SCSIZE nR) const;
     248             :     double GetDouble(SCSIZE nC, SCSIZE nR) const;
     249             :     double GetDouble( SCSIZE nIndex) const;
     250             :     svl::SharedString GetString(SCSIZE nC, SCSIZE nR) const;
     251             :     svl::SharedString GetString( SCSIZE nIndex) const;
     252             :     svl::SharedString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const;
     253             :     ScMatrixValue Get(SCSIZE nC, SCSIZE nR) const;
     254             :     bool IsString( SCSIZE nIndex ) const;
     255             :     bool IsString( SCSIZE nC, SCSIZE nR ) const;
     256             :     bool IsEmpty( SCSIZE nC, SCSIZE nR ) const;
     257             :     bool IsEmptyCell( SCSIZE nC, SCSIZE nR ) const;
     258             :     bool IsEmptyResult( SCSIZE nC, SCSIZE nR ) const;
     259             :     bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const;
     260             :     bool IsValue( SCSIZE nIndex ) const;
     261             :     bool IsValue( SCSIZE nC, SCSIZE nR ) const;
     262             :     bool IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const;
     263             :     bool IsBoolean( SCSIZE nC, SCSIZE nR ) const;
     264             :     bool IsNumeric() const;
     265             : 
     266             :     void MatCopy(ScMatrixImpl& mRes) const;
     267             :     void MatTrans(ScMatrixImpl& mRes) const;
     268             :     void FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 );
     269             :     void PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR );
     270             :     void PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR );
     271             :     void PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
     272             :     void PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
     273             :     void PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
     274             :     void CompareEqual();
     275             :     void CompareNotEqual();
     276             :     void CompareLess();
     277             :     void CompareGreater();
     278             :     void CompareLessEqual();
     279             :     void CompareGreaterEqual();
     280             :     double And() const;
     281             :     double Or() const;
     282             :     double Xor() const;
     283             : 
     284             :     ScMatrix::IterateResult Sum(bool bTextAsZero) const;
     285             :     ScMatrix::IterateResult SumSquare(bool bTextAsZero) const;
     286             :     ScMatrix::IterateResult Product(bool bTextAsZero) const;
     287             :     size_t Count(bool bCountStrings) const;
     288             :     size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const;
     289             :     size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const;
     290             : 
     291             :     double GetMaxValue( bool bTextAsZero ) const;
     292             :     double GetMinValue( bool bTextAsZero ) const;
     293             : 
     294             :     ScMatrixRef CompareMatrix( sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const;
     295             : 
     296             :     void GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const;
     297             :     void MergeDoubleArray( std::vector<double>& rArray, ScMatrix::Op eOp ) const;
     298             :     void AddValues( const ScMatrixImpl& rMat );
     299             : 
     300             :     template<typename T>
     301             :     void ApplyOperation(T aOp, ScMatrixImpl& rMat);
     302             : 
     303             : #if DEBUG_MATRIX
     304             :     void Dump() const;
     305             : #endif
     306             : 
     307             : private:
     308             :     void CalcPosition(SCSIZE nIndex, SCSIZE& rC, SCSIZE& rR) const;
     309             : };
     310             : 
     311         322 : ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR) :
     312         322 :     maMat(nR, nC), maMatFlag(nR, nC, SC_MATFLAG_EMPTYCELL), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
     313             : 
     314         133 : ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR, double fInitVal) :
     315         133 :     maMat(nR, nC, fInitVal), maMatFlag(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
     316             : 
     317          49 : ScMatrixImpl::ScMatrixImpl( size_t nC, size_t nR, const std::vector<double>& rInitVals ) :
     318          49 :     maMat(nR, nC, rInitVals.begin(), rInitVals.end()), maMatFlag(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
     319             : 
     320         984 : ScMatrixImpl::~ScMatrixImpl()
     321             : {
     322         492 :     Clear();
     323         492 : }
     324             : 
     325         492 : void ScMatrixImpl::Clear()
     326             : {
     327         492 :     maMat.clear();
     328         492 :     maMatFlag.clear();
     329         492 : }
     330             : 
     331         284 : void ScMatrixImpl::SetImmutable(bool bVal)
     332             : {
     333         284 :     mbCloneIfConst = bVal;
     334         284 : }
     335             : 
     336           7 : void ScMatrixImpl::Resize(SCSIZE nC, SCSIZE nR)
     337             : {
     338           7 :     maMat.resize(nR, nC);
     339           7 :     maMatFlag.resize(nR, nC);
     340           7 : }
     341             : 
     342           2 : void ScMatrixImpl::Resize(SCSIZE nC, SCSIZE nR, double fVal)
     343             : {
     344           2 :     maMat.resize(nR, nC, fVal);
     345           2 :     maMatFlag.resize(nR, nC);
     346           2 : }
     347             : 
     348         867 : void ScMatrixImpl::SetErrorInterpreter( ScInterpreter* p)
     349             : {
     350         867 :     pErrorInterpreter = p;
     351         867 : }
     352             : 
     353         962 : void ScMatrixImpl::GetDimensions( SCSIZE& rC, SCSIZE& rR) const
     354             : {
     355         962 :     MatrixImplType::size_pair_type aSize = maMat.size();
     356         962 :     rR = aSize.row;
     357         962 :     rC = aSize.column;
     358         962 : }
     359             : 
     360          32 : SCSIZE ScMatrixImpl::GetElementCount() const
     361             : {
     362          32 :     MatrixImplType::size_pair_type aSize = maMat.size();
     363          32 :     return aSize.row * aSize.column;
     364             : }
     365             : 
     366        3887 : bool ScMatrixImpl::ValidColRow( SCSIZE nC, SCSIZE nR) const
     367             : {
     368        3887 :     MatrixImplType::size_pair_type aSize = maMat.size();
     369        3887 :     return nR < aSize.row && nC < aSize.column;
     370             : }
     371             : 
     372        1955 : bool ScMatrixImpl::ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const
     373             : {
     374        1955 :     MatrixImplType::size_pair_type aSize = maMat.size();
     375        1955 :     if (aSize.column == 1 && aSize.row == 1)
     376             :     {
     377           0 :         rC = 0;
     378           0 :         rR = 0;
     379           0 :         return true;
     380             :     }
     381        1955 :     else if (aSize.column == 1 && rR < aSize.row)
     382             :     {
     383             :         // single column matrix.
     384        1840 :         rC = 0;
     385        1840 :         return true;
     386             :     }
     387         115 :     else if (aSize.row == 1 && rC < aSize.column)
     388             :     {
     389             :         // single row matrix.
     390          87 :         rR = 0;
     391          87 :         return true;
     392             :     }
     393          28 :     return false;
     394             : }
     395             : 
     396        2742 : bool ScMatrixImpl::ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const
     397             : {
     398        2742 :     return ValidColRow( rC, rR) || ValidColRowReplicated( rC, rR);
     399             : }
     400             : 
     401           0 : void ScMatrixImpl::SetErrorAtInterpreter( sal_uInt16 nError ) const
     402             : {
     403           0 :     if ( pErrorInterpreter )
     404           0 :         pErrorInterpreter->SetError( nError);
     405           0 : }
     406             : 
     407         367 : void ScMatrixImpl::PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
     408             : {
     409         367 :     if (ValidColRow( nC, nR))
     410         367 :         maMat.set(nR, nC, fVal);
     411             :     else
     412             :     {
     413             :         OSL_FAIL("ScMatrixImpl::PutDouble: dimension error");
     414             :     }
     415         367 : }
     416             : 
     417         307 : void ScMatrixImpl::PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
     418             : {
     419         307 :     if (ValidColRow( nC, nR))
     420         307 :         maMat.set(nR, nC, pArray, pArray + nLen);
     421             :     else
     422             :     {
     423             :         OSL_FAIL("ScMatrixImpl::PutDouble: dimension error");
     424             :     }
     425         307 : }
     426             : 
     427          33 : void ScMatrixImpl::PutDouble( double fVal, SCSIZE nIndex)
     428             : {
     429             :     SCSIZE nC, nR;
     430          33 :     CalcPosition(nIndex, nC, nR);
     431          33 :     PutDouble(fVal, nC, nR);
     432          33 : }
     433             : 
     434         408 : void ScMatrixImpl::PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR)
     435             : {
     436         408 :     if (ValidColRow( nC, nR))
     437         408 :         maMat.set(nR, nC, rStr);
     438             :     else
     439             :     {
     440             :         OSL_FAIL("ScMatrixImpl::PutString: dimension error");
     441             :     }
     442         408 : }
     443             : 
     444          18 : void ScMatrixImpl::PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
     445             : {
     446          18 :     if (ValidColRow( nC, nR))
     447          18 :         maMat.set(nR, nC, pArray, pArray + nLen);
     448             :     else
     449             :     {
     450             :         OSL_FAIL("ScMatrixImpl::PutString: dimension error");
     451             :     }
     452          18 : }
     453             : 
     454          12 : void ScMatrixImpl::PutString(const svl::SharedString& rStr, SCSIZE nIndex)
     455             : {
     456             :     SCSIZE nC, nR;
     457          12 :     CalcPosition(nIndex, nC, nR);
     458          12 :     PutString(rStr, nC, nR);
     459          12 : }
     460             : 
     461           1 : void ScMatrixImpl::PutEmpty(SCSIZE nC, SCSIZE nR)
     462             : {
     463           1 :     if (ValidColRow( nC, nR))
     464             :     {
     465           1 :         maMat.set_empty(nR, nC);
     466           1 :         maMatFlag.set(nR, nC, SC_MATFLAG_EMPTYCELL);
     467             :     }
     468             :     else
     469             :     {
     470             :         OSL_FAIL("ScMatrixImpl::PutEmpty: dimension error");
     471             :     }
     472           1 : }
     473             : 
     474           3 : void ScMatrixImpl::PutEmptyPath(SCSIZE nC, SCSIZE nR)
     475             : {
     476           3 :     if (ValidColRow( nC, nR))
     477             :     {
     478           3 :         maMat.set_empty(nR, nC);
     479           3 :         maMatFlag.set(nR, nC, SC_MATFLAG_EMPTYPATH);
     480             :     }
     481             :     else
     482             :     {
     483             :         OSL_FAIL("ScMatrixImpl::PutEmptyPath: dimension error");
     484             :     }
     485           3 : }
     486             : 
     487           0 : void ScMatrixImpl::PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR )
     488             : {
     489           0 :     maMat.set(nR, nC, CreateDoubleError(nErrorCode));
     490           0 : }
     491             : 
     492           5 : void ScMatrixImpl::PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
     493             : {
     494           5 :     if (ValidColRow( nC, nR))
     495           5 :         maMat.set(nR, nC, bVal);
     496             :     else
     497             :     {
     498             :         OSL_FAIL("ScMatrixImpl::PutBoolean: dimension error");
     499             :     }
     500           5 : }
     501             : 
     502          15 : sal_uInt16 ScMatrixImpl::GetError( SCSIZE nC, SCSIZE nR) const
     503             : {
     504          15 :     if (ValidColRowOrReplicated( nC, nR ))
     505             :     {
     506          15 :         double fVal = maMat.get_numeric(nR, nC);
     507          15 :         return GetDoubleErrorValue(fVal);
     508             :     }
     509             :     else
     510             :     {
     511             :         OSL_FAIL("ScMatrixImpl::GetError: dimension error");
     512           0 :         return errNoValue;
     513             :     }
     514             : }
     515             : 
     516        2006 : double ScMatrixImpl::GetDouble(SCSIZE nC, SCSIZE nR) const
     517             : {
     518        2006 :     if (ValidColRowOrReplicated( nC, nR ))
     519             :     {
     520        2006 :         double fVal = maMat.get_numeric(nR, nC);
     521        2006 :         if ( pErrorInterpreter )
     522             :         {
     523        1866 :             sal_uInt16 nError = GetDoubleErrorValue(fVal);
     524        1866 :             if ( nError )
     525           0 :                 SetErrorAtInterpreter( nError);
     526             :         }
     527        2006 :         return fVal;
     528             :     }
     529             :     else
     530             :     {
     531             :         OSL_FAIL("ScMatrixImpl::GetDouble: dimension error");
     532           0 :         return CreateDoubleError( errNoValue);
     533             :     }
     534             : }
     535             : 
     536         208 : double ScMatrixImpl::GetDouble( SCSIZE nIndex) const
     537             : {
     538             :     SCSIZE nC, nR;
     539         208 :     CalcPosition(nIndex, nC, nR);
     540         208 :     return GetDouble(nC, nR);
     541             : }
     542             : 
     543          13 : svl::SharedString ScMatrixImpl::GetString(SCSIZE nC, SCSIZE nR) const
     544             : {
     545          13 :     if (ValidColRowOrReplicated( nC, nR ))
     546             :     {
     547          13 :         double fErr = 0.0;
     548          13 :         MatrixImplType::const_position_type aPos = maMat.position(nR, nC);
     549          13 :         switch (maMat.get_type(aPos))
     550             :         {
     551             :             case mdds::mtm::element_string:
     552          26 :                 return maMat.get_string(aPos);
     553             :             case mdds::mtm::element_empty:
     554           0 :                 return svl::SharedString::getEmptyString();
     555             :             case mdds::mtm::element_numeric:
     556             :             case mdds::mtm::element_boolean:
     557           0 :                 fErr = maMat.get_numeric(aPos);
     558             :                 //fallthrough
     559             :             default:
     560             :                 OSL_FAIL("ScMatrixImpl::GetString: access error, no string");
     561             :         }
     562           0 :         SetErrorAtInterpreter(GetDoubleErrorValue(fErr));
     563             :     }
     564             :     else
     565             :     {
     566             :         OSL_FAIL("ScMatrixImpl::GetString: dimension error");
     567             :     }
     568           0 :     return svl::SharedString::getEmptyString();
     569             : }
     570             : 
     571           0 : svl::SharedString ScMatrixImpl::GetString( SCSIZE nIndex) const
     572             : {
     573             :     SCSIZE nC, nR;
     574           0 :     CalcPosition(nIndex, nC, nR);
     575           0 :     return GetString(nC, nR);
     576             : }
     577             : 
     578           3 : svl::SharedString ScMatrixImpl::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
     579             : {
     580           3 :     if (!ValidColRowOrReplicated( nC, nR ))
     581             :     {
     582             :         OSL_FAIL("ScMatrixImpl::GetString: dimension error");
     583           0 :         return OUString();
     584             :     }
     585             : 
     586           3 :     double fVal = 0.0;
     587           3 :     MatrixImplType::const_position_type aPos = maMat.position(nR, nC);
     588           3 :     switch (maMat.get_type(aPos))
     589             :     {
     590             :         case mdds::mtm::element_string:
     591           0 :             return maMat.get_string(aPos).getString();
     592             :         case mdds::mtm::element_empty:
     593             :         {
     594           3 :             if (maMatFlag.get<TMatFlag>(nR, nC) != SC_MATFLAG_EMPTYPATH)
     595             :                 // not an empty path.
     596           3 :                 return svl::SharedString::getEmptyString();
     597             : 
     598             :             // result of empty FALSE jump path
     599             :             sal_uLong nKey = rFormatter.GetStandardFormat( css::util::NumberFormat::LOGICAL,
     600           0 :                     ScGlobal::eLnge);
     601           0 :             OUString aStr;
     602           0 :             Color* pColor = NULL;
     603           0 :             rFormatter.GetOutputString( 0.0, nKey, aStr, &pColor);
     604           0 :             return aStr;
     605             :         }
     606             :         case mdds::mtm::element_numeric:
     607             :         case mdds::mtm::element_boolean:
     608           0 :             fVal = maMat.get_numeric(aPos);
     609           0 :         break;
     610             :         default:
     611             :             ;
     612             :     }
     613             : 
     614           0 :     sal_uInt16 nError = GetDoubleErrorValue(fVal);
     615           0 :     if (nError)
     616             :     {
     617           0 :         SetErrorAtInterpreter( nError);
     618           0 :         return ScGlobal::GetErrorString( nError);
     619             :     }
     620             : 
     621             :     sal_uLong nKey = rFormatter.GetStandardFormat( css::util::NumberFormat::NUMBER,
     622           0 :             ScGlobal::eLnge);
     623           0 :     OUString aStr;
     624           0 :     rFormatter.GetInputLineString( fVal, nKey, aStr);
     625           0 :     return aStr;
     626             : }
     627             : 
     628         698 : ScMatrixValue ScMatrixImpl::Get(SCSIZE nC, SCSIZE nR) const
     629             : {
     630         698 :     ScMatrixValue aVal;
     631         698 :     if (ValidColRowOrReplicated(nC, nR))
     632             :     {
     633         698 :         MatrixImplType::const_position_type aPos = maMat.position(nR, nC);
     634         698 :         mdds::mtm::element_t eType = maMat.get_type(aPos);
     635         698 :         switch (eType)
     636             :         {
     637             :             case mdds::mtm::element_boolean:
     638           1 :                 aVal.nType = SC_MATVAL_BOOLEAN;
     639           1 :                 aVal.fVal = double(maMat.get_boolean(aPos));
     640           1 :             break;
     641             :             case mdds::mtm::element_numeric:
     642         257 :                 aVal.nType = SC_MATVAL_VALUE;
     643         257 :                 aVal.fVal = maMat.get_numeric(aPos);
     644         257 :             break;
     645             :             case mdds::mtm::element_string:
     646          36 :                 aVal.nType = SC_MATVAL_STRING;
     647          36 :                 aVal.aStr = maMat.get_string(aPos);
     648          36 :             break;
     649             :             case mdds::mtm::element_empty:
     650             :                 /* TODO: do we need to pass the differentiation of 'empty' and
     651             :                  * 'empty result' to the outer world anywhere? */
     652         404 :                 aVal.nType = maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYPATH ? SC_MATVAL_EMPTYPATH :
     653         404 :                     SC_MATVAL_EMPTY;
     654         404 :                 aVal.fVal = 0.0;
     655             :             default:
     656             :                 ;
     657             :         }
     658             :     }
     659             :     else
     660             :     {
     661             :         OSL_FAIL("ScMatrixImpl::Get: dimension error");
     662             :     }
     663         698 :     return aVal;
     664             : }
     665             : 
     666           0 : bool ScMatrixImpl::IsString( SCSIZE nIndex ) const
     667             : {
     668             :     SCSIZE nC, nR;
     669           0 :     CalcPosition(nIndex, nC, nR);
     670           0 :     return IsString(nC, nR);
     671             : }
     672             : 
     673        1687 : bool ScMatrixImpl::IsString( SCSIZE nC, SCSIZE nR ) const
     674             : {
     675        1687 :     ValidColRowReplicated( nC, nR );
     676        1687 :     switch (maMat.get_type(nR, nC))
     677             :     {
     678             :         case mdds::mtm::element_empty:
     679             :         case mdds::mtm::element_string:
     680          49 :             return true;
     681             :         default:
     682             :             ;
     683             :     }
     684        1638 :     return false;
     685             : }
     686             : 
     687           8 : bool ScMatrixImpl::IsEmpty( SCSIZE nC, SCSIZE nR ) const
     688             : {
     689             :     // Flag must indicate an 'empty' or 'empty cell' or 'empty result' element,
     690             :     // but not an 'empty path' element.
     691           8 :     ValidColRowReplicated( nC, nR );
     692           9 :     return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
     693           9 :         maMatFlag.get<TMatFlag>(nR, nC) != SC_MATFLAG_EMPTYPATH;
     694             : }
     695             : 
     696          21 : bool ScMatrixImpl::IsEmptyCell( SCSIZE nC, SCSIZE nR ) const
     697             : {
     698             :     // Flag must indicate an 'empty cell' element instead of an
     699             :     // 'empty' or 'empty result' or 'empty path' element.
     700          21 :     ValidColRowReplicated( nC, nR );
     701          33 :     return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
     702          33 :         maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYCELL;
     703             : }
     704             : 
     705           7 : bool ScMatrixImpl::IsEmptyResult( SCSIZE nC, SCSIZE nR ) const
     706             : {
     707             :     // Flag must indicate an 'empty result' element instead of an
     708             :     // 'empty' or 'empty cell' or 'empty path' element.
     709           7 :     ValidColRowReplicated( nC, nR );
     710           7 :     return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
     711           7 :         maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYRESULT;
     712             : }
     713             : 
     714           7 : bool ScMatrixImpl::IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
     715             : {
     716             :     // Flag must indicate an 'empty path' element.
     717           7 :     if (ValidColRowOrReplicated( nC, nR ))
     718           7 :         return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
     719           7 :             maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYPATH;
     720             :     else
     721           0 :         return true;
     722             : }
     723             : 
     724          57 : bool ScMatrixImpl::IsValue( SCSIZE nIndex ) const
     725             : {
     726             :     SCSIZE nC, nR;
     727          57 :     CalcPosition(nIndex, nC, nR);
     728          57 :     return IsValue(nC, nR);
     729             : }
     730             : 
     731         148 : bool ScMatrixImpl::IsValue( SCSIZE nC, SCSIZE nR ) const
     732             : {
     733         148 :     ValidColRowReplicated(nC, nR);
     734         148 :     switch (maMat.get_type(nR, nC))
     735             :     {
     736             :         case mdds::mtm::element_boolean:
     737             :         case mdds::mtm::element_numeric:
     738         148 :             return true;
     739             :         default:
     740             :             ;
     741             :     }
     742           0 :     return false;
     743             : }
     744             : 
     745          66 : bool ScMatrixImpl::IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
     746             : {
     747          66 :     ValidColRowReplicated(nC, nR);
     748          66 :     switch (maMat.get_type(nR, nC))
     749             :     {
     750             :         case mdds::mtm::element_boolean:
     751             :         case mdds::mtm::element_numeric:
     752             :         case mdds::mtm::element_empty:
     753          66 :             return true;
     754             :         default:
     755             :             ;
     756             :     }
     757           0 :     return false;
     758             : }
     759             : 
     760          18 : bool ScMatrixImpl::IsBoolean( SCSIZE nC, SCSIZE nR ) const
     761             : {
     762          18 :     ValidColRowReplicated( nC, nR );
     763          18 :     return maMat.get_type(nR, nC) == mdds::mtm::element_boolean;
     764             : }
     765             : 
     766          14 : bool ScMatrixImpl::IsNumeric() const
     767             : {
     768          14 :     return maMat.numeric();
     769             : }
     770             : 
     771          12 : void ScMatrixImpl::MatCopy(ScMatrixImpl& mRes) const
     772             : {
     773          12 :     if (maMat.size().row > mRes.maMat.size().row || maMat.size().column > mRes.maMat.size().column)
     774             :     {
     775             :         // destination matrix is not large enough.
     776             :         OSL_FAIL("ScMatrixImpl::MatCopy: dimension error");
     777          12 :         return;
     778             :     }
     779             : 
     780          12 :     mRes.maMat.copy(maMat);
     781             : }
     782             : 
     783           1 : void ScMatrixImpl::MatTrans(ScMatrixImpl& mRes) const
     784             : {
     785           1 :     mRes.maMat = maMat;
     786           1 :     mRes.maMat.transpose();
     787           1 : }
     788             : 
     789          12 : void ScMatrixImpl::FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 )
     790             : {
     791          12 :     if (ValidColRow( nC1, nR1) && ValidColRow( nC2, nR2))
     792             :     {
     793          42 :         for (SCSIZE j = nC1; j <= nC2; ++j)
     794             :         {
     795             :             // Passing value array is much faster.
     796          30 :             std::vector<double> aVals(nR2-nR1+1, fVal);
     797          30 :             maMat.set(nR1, j, aVals.begin(), aVals.end());
     798          30 :         }
     799             :     }
     800             :     else
     801             :     {
     802             :         OSL_FAIL("ScMatrixImpl::FillDouble: dimension error");
     803             :     }
     804          12 : }
     805             : 
     806           6 : void ScMatrixImpl::PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR )
     807             : {
     808           6 :     if (!rVec.empty() && ValidColRow( nC, nR) && ValidColRow( nC, nR + rVec.size() - 1))
     809             :     {
     810           6 :         maMat.set(nR, nC, rVec.begin(), rVec.end());
     811             :     }
     812             :     else
     813             :     {
     814             :         OSL_FAIL("ScMatrixImpl::PutDoubleVector: dimension error");
     815             :     }
     816           6 : }
     817             : 
     818           0 : void ScMatrixImpl::PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR )
     819             : {
     820           0 :     if (!rVec.empty() && ValidColRow( nC, nR) && ValidColRow( nC, nR + rVec.size() - 1))
     821             :     {
     822           0 :         maMat.set(nR, nC, rVec.begin(), rVec.end());
     823             :     }
     824             :     else
     825             :     {
     826             :         OSL_FAIL("ScMatrixImpl::PutStringVector: dimension error");
     827             :     }
     828           0 : }
     829             : 
     830           0 : void ScMatrixImpl::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
     831             : {
     832           0 :     if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1))
     833             :     {
     834           0 :         maMat.set_empty(nR, nC, nCount);
     835             :         // Flag to indicate that this is 'empty', not 'empty result' or 'empty path'.
     836           0 :         std::vector<TMatFlag> aVals(nCount, SC_MATFLAG_EMPTYCELL);
     837           0 :         maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
     838             :     }
     839             :     else
     840             :     {
     841             :         OSL_FAIL("ScMatrixImpl::PutEmptyVector: dimension error");
     842             :     }
     843           0 : }
     844             : 
     845           0 : void ScMatrixImpl::PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
     846             : {
     847           0 :     if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1))
     848             :     {
     849           0 :         maMat.set_empty(nR, nC, nCount);
     850             :         // Flag to indicate that this is 'empty result', not 'empty' or 'empty path'.
     851           0 :         std::vector<TMatFlag> aVals(nCount, SC_MATFLAG_EMPTYRESULT);
     852           0 :         maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
     853             :     }
     854             :     else
     855             :     {
     856             :         OSL_FAIL("ScMatrixImpl::PutEmptyResultVector: dimension error");
     857             :     }
     858           0 : }
     859             : 
     860           0 : void ScMatrixImpl::PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
     861             : {
     862           0 :     if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1))
     863             :     {
     864           0 :         maMat.set_empty(nR, nC, nCount);
     865             :         // Flag to indicate 'empty path'.
     866           0 :         std::vector<TMatFlag> aVals(nCount, SC_MATFLAG_EMPTYPATH);
     867           0 :         maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
     868             :     }
     869             :     else
     870             :     {
     871             :         OSL_FAIL("ScMatrixImpl::PutEmptyPathVector: dimension error");
     872             :     }
     873           0 : }
     874             : 
     875           0 : void ScMatrixImpl::CompareEqual()
     876             : {
     877           0 :     MatrixImplType::size_pair_type aSize = maMat.size();
     878           0 :     CompareMatrixElemFunc<ElemEqualZero> aFunc(aSize.row, aSize.column);
     879           0 :     maMat.walk(aFunc);
     880           0 :     aFunc.swap(maMat);
     881           0 : }
     882             : 
     883           0 : void ScMatrixImpl::CompareNotEqual()
     884             : {
     885           0 :     MatrixImplType::size_pair_type aSize = maMat.size();
     886           0 :     CompareMatrixElemFunc<ElemNotEqualZero> aFunc(aSize.row, aSize.column);
     887           0 :     maMat.walk(aFunc);
     888           0 :     aFunc.swap(maMat);
     889           0 : }
     890             : 
     891           0 : void ScMatrixImpl::CompareLess()
     892             : {
     893           0 :     MatrixImplType::size_pair_type aSize = maMat.size();
     894           0 :     CompareMatrixElemFunc<ElemLessZero> aFunc(aSize.row, aSize.column);
     895           0 :     maMat.walk(aFunc);
     896           0 :     aFunc.swap(maMat);
     897           0 : }
     898             : 
     899           0 : void ScMatrixImpl::CompareGreater()
     900             : {
     901           0 :     MatrixImplType::size_pair_type aSize = maMat.size();
     902           0 :     CompareMatrixElemFunc<ElemGreaterZero> aFunc(aSize.row, aSize.column);
     903           0 :     maMat.walk(aFunc);
     904           0 :     aFunc.swap(maMat);
     905           0 : }
     906             : 
     907           0 : void ScMatrixImpl::CompareLessEqual()
     908             : {
     909           0 :     MatrixImplType::size_pair_type aSize = maMat.size();
     910           0 :     CompareMatrixElemFunc<ElemLessEqualZero> aFunc(aSize.row, aSize.column);
     911           0 :     maMat.walk(aFunc);
     912           0 :     aFunc.swap(maMat);
     913           0 : }
     914             : 
     915           0 : void ScMatrixImpl::CompareGreaterEqual()
     916             : {
     917           0 :     MatrixImplType::size_pair_type aSize = maMat.size();
     918           0 :     CompareMatrixElemFunc<ElemGreaterEqualZero> aFunc(aSize.row, aSize.column);
     919           0 :     maMat.walk(aFunc);
     920           0 :     aFunc.swap(maMat);
     921           0 : }
     922             : 
     923             : namespace {
     924             : 
     925             : struct AndEvaluator
     926             : {
     927             :     bool mbResult;
     928         136 :     void operate(double fVal) { mbResult &= (fVal != 0.0); }
     929           9 :     bool result() const { return mbResult; }
     930           9 :     AndEvaluator() : mbResult(true) {}
     931             : };
     932             : 
     933             : struct OrEvaluator
     934             : {
     935             :     bool mbResult;
     936         152 :     void operate(double fVal) { mbResult |= (fVal != 0.0); }
     937          13 :     bool result() const { return mbResult; }
     938          13 :     OrEvaluator() : mbResult(false) {}
     939             : };
     940             : 
     941             : struct XorEvaluator
     942             : {
     943             :     bool mbResult;
     944           0 :     void operate(double fVal) { mbResult ^= (fVal != 0.0); }
     945           0 :     bool result() const { return mbResult; }
     946           0 :     XorEvaluator() : mbResult(false) {}
     947             : };
     948             : 
     949             : // Do not short circuit logical operations, in case there are error values
     950             : // these need to be propagated even if the result was determined earlier.
     951             : template <typename _Evaluator>
     952          22 : double EvalMatrix(const MatrixImplType& rMat)
     953             : {
     954          22 :     _Evaluator aEval;
     955          22 :     size_t nRows = rMat.size().row, nCols = rMat.size().column;
     956         122 :     for (size_t i = 0; i < nRows; ++i)
     957             :     {
     958         776 :         for (size_t j = 0; j < nCols; ++j)
     959             :         {
     960         288 :             MatrixImplType::const_position_type aPos = rMat.position(i, j);
     961         288 :             mdds::mtm::element_t eType = rMat.get_type(aPos);
     962         288 :             if (eType != mdds::mtm::element_numeric && eType != mdds::mtm::element_boolean)
     963             :                 // assuming a CompareMat this is an error
     964           0 :                 return CreateDoubleError(errIllegalArgument);
     965             : 
     966         288 :             double fVal = rMat.get_numeric(aPos);
     967         288 :             if (!::rtl::math::isFinite(fVal))
     968             :                 // DoubleError
     969           0 :                 return fVal;
     970             : 
     971         288 :             aEval.operate(fVal);
     972             :         }
     973             :     }
     974          22 :     return aEval.result();
     975             : }
     976             : 
     977             : }
     978             : 
     979           9 : double ScMatrixImpl::And() const
     980             : {
     981             :     // All elements must be of value type.
     982             :     // True only if all the elements have non-zero values.
     983           9 :     return EvalMatrix<AndEvaluator>(maMat);
     984             : }
     985             : 
     986          13 : double ScMatrixImpl::Or() const
     987             : {
     988             :     // All elements must be of value type.
     989             :     // True if at least one element has a non-zero value.
     990          13 :     return EvalMatrix<OrEvaluator>(maMat);
     991             : }
     992             : 
     993           0 : double ScMatrixImpl::Xor() const
     994             : {
     995             :     // All elements must be of value type.
     996             :     // True if an odd number of elements have a non-zero value.
     997           0 :     return EvalMatrix<XorEvaluator>(maMat);
     998             : }
     999             : 
    1000             : namespace {
    1001             : 
    1002             : struct SumOp
    1003             : {
    1004             :     static const double InitVal;
    1005             : 
    1006          35 :     void operator() (double& rAccum, double fVal)
    1007             :     {
    1008          35 :         rAccum += fVal;
    1009          35 :     }
    1010             : };
    1011             : 
    1012             : const double SumOp::InitVal = 0.0;
    1013             : 
    1014             : struct SumSquareOp
    1015             : {
    1016             :     static const double InitVal;
    1017             : 
    1018           0 :     void operator() (double& rAccum, double fVal)
    1019             :     {
    1020           0 :         rAccum += fVal*fVal;
    1021           0 :     }
    1022             : };
    1023             : 
    1024             : const double SumSquareOp::InitVal = 0.0;
    1025             : 
    1026             : struct ProductOp
    1027             : {
    1028             :     static const double InitVal;
    1029             : 
    1030          24 :     void operator() (double& rAccum, double fVal)
    1031             :     {
    1032          24 :         rAccum *= fVal;
    1033          24 :     }
    1034             : };
    1035             : 
    1036             : const double ProductOp::InitVal = 1.0;
    1037             : 
    1038             : template<typename _Op>
    1039             : class WalkElementBlocks : std::unary_function<MatrixImplType::element_block_node_type, void>
    1040             : {
    1041             :     _Op maOp;
    1042             : 
    1043             :     ScMatrix::IterateResult maRes;
    1044             :     bool mbFirst:1;
    1045             :     bool mbTextAsZero:1;
    1046             : public:
    1047          14 :     WalkElementBlocks(bool bTextAsZero) : maRes(_Op::InitVal, _Op::InitVal, 0), mbFirst(true), mbTextAsZero(bTextAsZero) {}
    1048             : 
    1049          14 :     const ScMatrix::IterateResult& getResult() const { return maRes; }
    1050             : 
    1051          16 :     void operator() (const MatrixImplType::element_block_node_type& node)
    1052             :     {
    1053          16 :         switch (node.type)
    1054             :         {
    1055             :             case mdds::mtm::element_numeric:
    1056             :             {
    1057             :                 typedef MatrixImplType::numeric_block_type block_type;
    1058             : 
    1059          14 :                 block_type::const_iterator it = block_type::begin(*node.data);
    1060          14 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
    1061          73 :                 for (; it != itEnd; ++it)
    1062             :                 {
    1063          59 :                     if (mbFirst)
    1064             :                     {
    1065          14 :                         maOp(maRes.mfFirst, *it);
    1066          14 :                         mbFirst = false;
    1067             :                     }
    1068             :                     else
    1069          45 :                         maOp(maRes.mfRest, *it);
    1070             :                 }
    1071          14 :                 maRes.mnCount += node.size;
    1072             :             }
    1073          14 :             break;
    1074             :             case mdds::mtm::element_boolean:
    1075             :             {
    1076             :                 typedef MatrixImplType::boolean_block_type block_type;
    1077             : 
    1078           0 :                 block_type::const_iterator it = block_type::begin(*node.data);
    1079           0 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
    1080           0 :                 for (; it != itEnd; ++it)
    1081             :                 {
    1082           0 :                     if (mbFirst)
    1083             :                     {
    1084           0 :                         maOp(maRes.mfFirst, *it);
    1085           0 :                         mbFirst = false;
    1086             :                     }
    1087             :                     else
    1088           0 :                         maOp(maRes.mfRest, *it);
    1089             :                 }
    1090           0 :                 maRes.mnCount += node.size;
    1091             :             }
    1092           0 :             break;
    1093             :             case mdds::mtm::element_string:
    1094           0 :                 if (mbTextAsZero)
    1095           0 :                     maRes.mnCount += node.size;
    1096           0 :             break;
    1097             :             case mdds::mtm::element_empty:
    1098             :             default:
    1099             :                 ;
    1100             :         }
    1101          16 :     }
    1102             : };
    1103             : 
    1104             : class CountElements : std::unary_function<MatrixImplType::element_block_node_type, void>
    1105             : {
    1106             :     size_t mnCount;
    1107             :     bool mbCountString;
    1108             : public:
    1109           3 :     CountElements(bool bCountString) : mnCount(0), mbCountString(bCountString) {}
    1110             : 
    1111           3 :     size_t getCount() const { return mnCount; }
    1112             : 
    1113           4 :     void operator() (const MatrixImplType::element_block_node_type& node)
    1114             :     {
    1115           4 :         switch (node.type)
    1116             :         {
    1117             :             case mdds::mtm::element_numeric:
    1118             :             case mdds::mtm::element_boolean:
    1119           2 :                 mnCount += node.size;
    1120           2 :             break;
    1121             :             case mdds::mtm::element_string:
    1122           1 :                 if (mbCountString)
    1123           1 :                     mnCount += node.size;
    1124           1 :             break;
    1125             :             case mdds::mtm::element_empty:
    1126             :             default:
    1127             :                 ;
    1128             :         }
    1129           4 :     }
    1130             : };
    1131             : 
    1132             : const size_t ResultNotSet = std::numeric_limits<size_t>::max();
    1133             : 
    1134             : template<typename _Type>
    1135           2 : class WalkAndMatchElements : std::unary_function<MatrixImplType::element_block_node_type, void>
    1136             : {
    1137             :     _Type maMatchValue;
    1138             :     MatrixImplType::size_pair_type maSize;
    1139             :     size_t mnCol1;
    1140             :     size_t mnCol2;
    1141             :     size_t mnResult;
    1142             :     size_t mnIndex;
    1143             : 
    1144             : public:
    1145           2 :     WalkAndMatchElements(_Type aMatchValue, const MatrixImplType::size_pair_type& aSize, size_t nCol1, size_t nCol2) :
    1146             :         maMatchValue(aMatchValue),
    1147             :         maSize(aSize),
    1148             :         mnCol1(nCol1),
    1149             :         mnCol2(nCol2),
    1150             :         mnResult(ResultNotSet),
    1151           2 :         mnIndex(0) {}
    1152             : 
    1153           2 :     size_t getMatching() const { return mnResult; }
    1154             : 
    1155             :     size_t compare(const MatrixImplType::element_block_node_type& node) const;
    1156             : 
    1157           3 :     void operator() (const MatrixImplType::element_block_node_type& node)
    1158             :     {
    1159             :         // early exit if match already found
    1160           3 :         if (mnResult != ResultNotSet)
    1161           4 :             return;
    1162             : 
    1163             :         // limit lookup to the requested columns
    1164           2 :         if ((mnCol1 * maSize.row) <= mnIndex && mnIndex < ((mnCol2 + 1) * maSize.row))
    1165             :         {
    1166           2 :             mnResult = compare(node);
    1167             :         }
    1168             : 
    1169           2 :         mnIndex += node.size;
    1170             :     }
    1171             : };
    1172             : 
    1173             : template<>
    1174           0 : size_t WalkAndMatchElements<double>::compare(const MatrixImplType::element_block_node_type& node) const
    1175             : {
    1176           0 :     size_t nCount = 0;
    1177           0 :     switch (node.type)
    1178             :     {
    1179             :         case mdds::mtm::element_numeric:
    1180             :         {
    1181             :             typedef MatrixImplType::numeric_block_type block_type;
    1182             : 
    1183           0 :             block_type::const_iterator it = block_type::begin(*node.data);
    1184           0 :             block_type::const_iterator itEnd = block_type::end(*node.data);
    1185           0 :             for (; it != itEnd; ++it, nCount++)
    1186             :             {
    1187           0 :                 if (*it == maMatchValue)
    1188             :                 {
    1189           0 :                     return mnIndex + nCount;
    1190             :                 }
    1191             :             }
    1192           0 :             break;
    1193             :         }
    1194             :         case mdds::mtm::element_boolean:
    1195             :         {
    1196             :             typedef MatrixImplType::boolean_block_type block_type;
    1197             : 
    1198           0 :             block_type::const_iterator it = block_type::begin(*node.data);
    1199           0 :             block_type::const_iterator itEnd = block_type::end(*node.data);
    1200           0 :             for (; it != itEnd; ++it, ++nCount)
    1201             :             {
    1202           0 :                 if (int(*it) == maMatchValue)
    1203             :                 {
    1204           0 :                     return mnIndex + nCount;
    1205             :                 }
    1206             :             }
    1207           0 :             break;
    1208             :         }
    1209             :         break;
    1210             :         case mdds::mtm::element_string:
    1211             :         case mdds::mtm::element_empty:
    1212             :         default:
    1213             :             ;
    1214             :     }
    1215           0 :     return ResultNotSet;
    1216             : }
    1217             : 
    1218             : template<>
    1219           2 : size_t WalkAndMatchElements<svl::SharedString>::compare(const MatrixImplType::element_block_node_type& node) const
    1220             : {
    1221           2 :     switch (node.type)
    1222             :     {
    1223             :         case mdds::mtm::element_string:
    1224             :         {
    1225           2 :             size_t nCount = 0;
    1226             :             typedef MatrixImplType::string_block_type block_type;
    1227             : 
    1228           2 :             block_type::const_iterator it = block_type::begin(*node.data);
    1229           2 :             block_type::const_iterator itEnd = block_type::end(*node.data);
    1230           6 :             for (; it != itEnd; ++it, ++nCount)
    1231             :             {
    1232           6 :                 if (it->getDataIgnoreCase() == maMatchValue.getDataIgnoreCase())
    1233             :                 {
    1234           2 :                     return mnIndex + nCount;
    1235             :                 }
    1236             :             }
    1237           0 :             break;
    1238             :         }
    1239             :         case mdds::mtm::element_boolean:
    1240             :         case mdds::mtm::element_numeric:
    1241             :         case mdds::mtm::element_empty:
    1242             :         default:
    1243             :             ;
    1244             :     }
    1245           0 :     return ResultNotSet;
    1246             : }
    1247             : 
    1248             : struct MaxOp
    1249             : {
    1250           5 :     static double init() { return -std::numeric_limits<double>::max(); }
    1251          19 :     static double compare(double left, double right)
    1252             :     {
    1253          19 :         return std::max(left, right);
    1254             :     }
    1255             : 
    1256           2 :     static double boolValue(
    1257             :         MatrixImplType::boolean_block_type::const_iterator it,
    1258             :         MatrixImplType::boolean_block_type::const_iterator itEnd)
    1259             :     {
    1260             :         // If the array has at least one true value, the maximum value is 1.
    1261           2 :         it = std::find(it, itEnd, true);
    1262           2 :         return it == itEnd ? 0.0 : 1.0;
    1263             :     }
    1264             : };
    1265             : 
    1266             : struct MinOp
    1267             : {
    1268           4 :     static double init() { return std::numeric_limits<double>::max(); }
    1269          11 :     static double compare(double left, double right)
    1270             :     {
    1271          11 :         return std::min(left, right);
    1272             :     }
    1273             : 
    1274           1 :     static double boolValue(
    1275             :         MatrixImplType::boolean_block_type::const_iterator it,
    1276             :         MatrixImplType::boolean_block_type::const_iterator itEnd)
    1277             :     {
    1278             :         // If the array has at least one false value, the minimum value is 0.
    1279           1 :         it = std::find(it, itEnd, false);
    1280           1 :         return it == itEnd ? 1.0 : 0.0;
    1281             :     }
    1282             : };
    1283             : 
    1284             : template<typename _Op>
    1285             : class CalcMaxMinValue : std::unary_function<MatrixImplType::element_block_type, void>
    1286             : {
    1287             :     double mfVal;
    1288             :     bool mbTextAsZero;
    1289             :     bool mbHasValue;
    1290             : public:
    1291           9 :     CalcMaxMinValue( bool bTextAsZero ) :
    1292           9 :         mfVal(_Op::init()),
    1293             :         mbTextAsZero(bTextAsZero),
    1294          18 :         mbHasValue(false) {}
    1295             : 
    1296           9 :     double getValue() const { return mbHasValue ? mfVal : 0.0; }
    1297             : 
    1298          14 :     void operator() (const MatrixImplType::element_block_node_type& node)
    1299             :     {
    1300             : 
    1301          14 :         switch (node.type)
    1302             :         {
    1303             :             case mdds::mtm::element_numeric:
    1304             :             {
    1305             :                 typedef MatrixImplType::numeric_block_type block_type;
    1306             : 
    1307           8 :                 block_type::const_iterator it = block_type::begin(*node.data);
    1308           8 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
    1309          34 :                 for (; it != itEnd; ++it)
    1310          26 :                     mfVal = _Op::compare(mfVal, *it);
    1311             : 
    1312           8 :                 mbHasValue = true;
    1313             :             }
    1314           8 :             break;
    1315             :             case mdds::mtm::element_boolean:
    1316             :             {
    1317             :                 typedef MatrixImplType::boolean_block_type block_type;
    1318             : 
    1319           3 :                 block_type::const_iterator it = block_type::begin(*node.data);
    1320           3 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
    1321           3 :                 double fVal = _Op::boolValue(it, itEnd);
    1322           3 :                 mfVal = _Op::compare(mfVal, fVal);
    1323           3 :                 mbHasValue = true;
    1324             :             }
    1325           3 :             break;
    1326             :             case mdds::mtm::element_string:
    1327             :             case mdds::mtm::element_empty:
    1328             :             {
    1329             :                 // empty elements are treated as empty strings.
    1330           3 :                 if (mbTextAsZero)
    1331             :                 {
    1332           1 :                     mfVal = _Op::compare(mfVal, 0.0);
    1333           1 :                     mbHasValue = true;
    1334             :                 }
    1335             :             }
    1336           3 :             break;
    1337             :             default:
    1338             :                 ;
    1339             :         }
    1340          14 :     }
    1341             : };
    1342             : 
    1343         157 : inline double evaluate( double fVal, ScQueryOp eOp )
    1344             : {
    1345         157 :     if (!rtl::math::isFinite(fVal))
    1346           1 :         return fVal;
    1347             : 
    1348         156 :     switch (eOp)
    1349             :     {
    1350             :         case SC_EQUAL:
    1351         127 :             return fVal == 0.0 ? 1.0 : 0.0;
    1352             :         case SC_LESS:
    1353          28 :             return fVal < 0.0 ? 1.0 : 0.0;
    1354             :         case SC_GREATER:
    1355           1 :             return fVal > 0.0 ? 1.0 : 0.0;
    1356             :         break;
    1357             :         case SC_LESS_EQUAL:
    1358           0 :             return fVal <= 0.0 ? 1.0 : 0.0;
    1359             :         break;
    1360             :         case SC_GREATER_EQUAL:
    1361           0 :             return fVal >= 0.0 ? 1.0 : 0.0;
    1362             :         break;
    1363             :         case SC_NOT_EQUAL:
    1364           0 :             return fVal != 0.0 ? 1.0 : 0.0;
    1365             :         break;
    1366             :         default:
    1367             :             ;
    1368             :     }
    1369             : 
    1370             :     OSL_TRACE( "evaluate: unhandled comparison operator: %d", (int)eOp);
    1371           0 :     return CreateDoubleError( errUnknownState);
    1372             : }
    1373             : 
    1374          25 : class CompareMatrixFunc : std::unary_function<MatrixImplType::element_block_type, void>
    1375             : {
    1376             :     sc::Compare& mrComp;
    1377             :     size_t mnMatPos;
    1378             :     sc::CompareOptions* mpOptions;
    1379             :     std::vector<double> maResValues;    // double instead of bool to transport error values
    1380             : 
    1381          70 :     void compare()
    1382             :     {
    1383          70 :         double fVal = sc::CompareFunc(mrComp.maCells[0], mrComp.maCells[1], mrComp.mbIgnoreCase, mpOptions);
    1384          70 :         maResValues.push_back(evaluate(fVal, mrComp.meOp));
    1385          70 :     }
    1386             : 
    1387             : public:
    1388          25 :     CompareMatrixFunc( size_t nResSize, sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) :
    1389          25 :         mrComp(rComp), mnMatPos(nMatPos), mpOptions(pOptions)
    1390             :     {
    1391          25 :         maResValues.reserve(nResSize);
    1392          25 :     }
    1393             : 
    1394          25 :     void operator() (const MatrixImplType::element_block_node_type& node)
    1395             :     {
    1396          25 :         sc::Compare::Cell& rCell = mrComp.maCells[mnMatPos];
    1397             : 
    1398          25 :         switch (node.type)
    1399             :         {
    1400             :             case mdds::mtm::element_numeric:
    1401             :             {
    1402             :                 typedef MatrixImplType::numeric_block_type block_type;
    1403             : 
    1404           6 :                 block_type::const_iterator it = block_type::begin(*node.data);
    1405           6 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
    1406          22 :                 for (; it != itEnd; ++it)
    1407             :                 {
    1408          16 :                     rCell.mbValue = true;
    1409          16 :                     rCell.mbEmpty = false;
    1410          16 :                     rCell.mfValue = *it;
    1411          16 :                     compare();
    1412             :                 }
    1413             :             }
    1414           6 :             break;
    1415             :             case mdds::mtm::element_boolean:
    1416             :             {
    1417             :                 typedef MatrixImplType::boolean_block_type block_type;
    1418             : 
    1419           0 :                 block_type::const_iterator it = block_type::begin(*node.data);
    1420           0 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
    1421           0 :                 for (; it != itEnd; ++it)
    1422             :                 {
    1423           0 :                     rCell.mbValue = true;
    1424           0 :                     rCell.mbEmpty = false;
    1425           0 :                     rCell.mfValue = double(*it);
    1426           0 :                     compare();
    1427             :                 }
    1428             :             }
    1429           0 :             break;
    1430             :             case mdds::mtm::element_string:
    1431             :             {
    1432             :                 typedef MatrixImplType::string_block_type block_type;
    1433             : 
    1434          19 :                 block_type::const_iterator it = block_type::begin(*node.data);
    1435          19 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
    1436          73 :                 for (; it != itEnd; ++it)
    1437             :                 {
    1438          54 :                     const svl::SharedString& rStr = *it;
    1439          54 :                     rCell.mbValue = false;
    1440          54 :                     rCell.mbEmpty = false;
    1441          54 :                     rCell.maStr = rStr;
    1442          54 :                     compare();
    1443             :                 }
    1444             :             }
    1445          19 :             break;
    1446             :             case mdds::mtm::element_empty:
    1447             :             {
    1448           0 :                 rCell.mbValue = false;
    1449           0 :                 rCell.mbEmpty = true;
    1450           0 :                 rCell.maStr = svl::SharedString::getEmptyString();
    1451           0 :                 for (size_t i = 0; i < node.size; ++i)
    1452           0 :                     compare();
    1453             :             }
    1454             :             default:
    1455             :                 ;
    1456             :         }
    1457          25 :     }
    1458             : 
    1459          25 :     const std::vector<double>& getValues() const
    1460             :     {
    1461          25 :         return maResValues;
    1462             :     }
    1463             : };
    1464             : 
    1465             : /**
    1466             :  * Left-hand side is a matrix while the right-hand side is a numeric value.
    1467             :  */
    1468          24 : class CompareMatrixToNumericFunc : std::unary_function<MatrixImplType::element_block_type, void>
    1469             : {
    1470             :     sc::Compare& mrComp;
    1471             :     double mfRightValue;
    1472             :     sc::CompareOptions* mpOptions;
    1473             :     std::vector<double> maResValues;    // double instead of bool to transport error values
    1474             : 
    1475           0 :     void compare()
    1476             :     {
    1477           0 :         double fVal = sc::CompareFunc(mrComp.maCells[0], mfRightValue, mpOptions);
    1478           0 :         maResValues.push_back(evaluate(fVal, mrComp.meOp));
    1479           0 :     }
    1480             : 
    1481          87 :     void compareLeftNumeric( double fLeftVal )
    1482             :     {
    1483          87 :         double fVal = sc::CompareFunc(fLeftVal, mfRightValue);
    1484          87 :         maResValues.push_back(evaluate(fVal, mrComp.meOp));
    1485          87 :     }
    1486             : 
    1487           0 :     void compareLeftEmpty( size_t nSize )
    1488             :     {
    1489           0 :         double fVal = sc::CompareEmptyToNumericFunc(mfRightValue);
    1490           0 :         bool bRes = evaluate(fVal, mrComp.meOp);
    1491           0 :         maResValues.resize(maResValues.size() + nSize, bRes ? 1.0 : 0.0);
    1492           0 :     }
    1493             : 
    1494             : public:
    1495          24 :     CompareMatrixToNumericFunc( size_t nResSize, sc::Compare& rComp, double fRightValue, sc::CompareOptions* pOptions ) :
    1496          24 :         mrComp(rComp), mfRightValue(fRightValue), mpOptions(pOptions)
    1497             :     {
    1498          24 :         maResValues.reserve(nResSize);
    1499          24 :     }
    1500             : 
    1501          24 :     void operator() (const MatrixImplType::element_block_node_type& node)
    1502             :     {
    1503          24 :         sc::Compare::Cell& rCell = mrComp.maCells[0];
    1504             : 
    1505          24 :         switch (node.type)
    1506             :         {
    1507             :             case mdds::mtm::element_numeric:
    1508             :             {
    1509             :                 typedef MatrixImplType::numeric_block_type block_type;
    1510             : 
    1511          24 :                 block_type::const_iterator it = block_type::begin(*node.data);
    1512          24 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
    1513         111 :                 for (; it != itEnd; ++it)
    1514          87 :                     compareLeftNumeric(*it);
    1515             :             }
    1516          24 :             break;
    1517             :             case mdds::mtm::element_boolean:
    1518             :             {
    1519             :                 typedef MatrixImplType::boolean_block_type block_type;
    1520             : 
    1521           0 :                 block_type::const_iterator it = block_type::begin(*node.data);
    1522           0 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
    1523           0 :                 for (; it != itEnd; ++it)
    1524           0 :                     compareLeftNumeric(double(*it));
    1525             :             }
    1526           0 :             break;
    1527             :             case mdds::mtm::element_string:
    1528             :             {
    1529             :                 typedef MatrixImplType::string_block_type block_type;
    1530             : 
    1531           0 :                 block_type::const_iterator it = block_type::begin(*node.data);
    1532           0 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
    1533           0 :                 for (; it != itEnd; ++it)
    1534             :                 {
    1535           0 :                     const svl::SharedString& rStr = *it;
    1536           0 :                     rCell.mbValue = false;
    1537           0 :                     rCell.mbEmpty = false;
    1538           0 :                     rCell.maStr = rStr;
    1539           0 :                     compare();
    1540             :                 }
    1541             :             }
    1542           0 :             break;
    1543             :             case mdds::mtm::element_empty:
    1544           0 :                 compareLeftEmpty(node.size);
    1545           0 :             break;
    1546             :             default:
    1547             :                 ;
    1548             :         }
    1549          24 :     }
    1550             : 
    1551          24 :     const std::vector<double>& getValues() const
    1552             :     {
    1553          24 :         return maResValues;
    1554             :     }
    1555             : };
    1556             : 
    1557          20 : class ToDoubleArray : std::unary_function<MatrixImplType::element_block_type, void>
    1558             : {
    1559             :     std::vector<double> maArray;
    1560             :     std::vector<double>::iterator miPos;
    1561             :     double mfNaN;
    1562             :     bool mbEmptyAsZero;
    1563             : 
    1564             : public:
    1565          20 :     ToDoubleArray( size_t nSize, bool bEmptyAsZero ) :
    1566          20 :         maArray(nSize, 0.0), miPos(maArray.begin()), mbEmptyAsZero(bEmptyAsZero)
    1567             :     {
    1568          20 :         mfNaN = CreateDoubleError( errElementNaN);
    1569          20 :     }
    1570             : 
    1571          28 :     void operator() (const MatrixImplType::element_block_node_type& node)
    1572             :     {
    1573             :         using namespace mdds::mtv;
    1574             : 
    1575          28 :         switch (node.type)
    1576             :         {
    1577             :             case mdds::mtm::element_numeric:
    1578             :             {
    1579          20 :                 numeric_element_block::const_iterator it = numeric_element_block::begin(*node.data);
    1580          20 :                 numeric_element_block::const_iterator itEnd = numeric_element_block::end(*node.data);
    1581          77 :                 for (; it != itEnd; ++it, ++miPos)
    1582          57 :                     *miPos = *it;
    1583             :             }
    1584          20 :             break;
    1585             :             case mdds::mtm::element_boolean:
    1586             :             {
    1587           0 :                 boolean_element_block::const_iterator it = boolean_element_block::begin(*node.data);
    1588           0 :                 boolean_element_block::const_iterator itEnd = boolean_element_block::end(*node.data);
    1589           0 :                 for (; it != itEnd; ++it, ++miPos)
    1590           0 :                     *miPos = *it ? 1.0 : 0.0;
    1591             :             }
    1592           0 :             break;
    1593             :             case mdds::mtm::element_string:
    1594             :             {
    1595           2 :                 for (size_t i = 0; i < node.size; ++i, ++miPos)
    1596           1 :                     *miPos = mfNaN;
    1597             :             }
    1598           1 :             break;
    1599             :             case mdds::mtm::element_empty:
    1600             :             {
    1601           7 :                 if (mbEmptyAsZero)
    1602             :                 {
    1603           7 :                     std::advance(miPos, node.size);
    1604          35 :                     return;
    1605             :                 }
    1606             : 
    1607           0 :                 for (size_t i = 0; i < node.size; ++i, ++miPos)
    1608           0 :                     *miPos = mfNaN;
    1609             :             }
    1610           0 :             break;
    1611             :             default:
    1612             :                 ;
    1613             :         }
    1614             :     }
    1615             : 
    1616          20 :     void swap(std::vector<double>& rOther)
    1617             :     {
    1618          20 :         maArray.swap(rOther);
    1619          20 :     }
    1620             : };
    1621             : 
    1622             : struct ArrayMul : public std::binary_function<double, double, double>
    1623             : {
    1624          38 :     double operator() (const double& lhs, const double& rhs) const
    1625             :     {
    1626          38 :         return lhs * rhs;
    1627             :     }
    1628             : };
    1629             : 
    1630             : template<typename _Op>
    1631             : class MergeDoubleArrayFunc : std::unary_function<MatrixImplType::element_block_type, void>
    1632             : {
    1633             :     std::vector<double>& mrArray;
    1634             :     std::vector<double>::iterator miPos;
    1635             :     double mfNaN;
    1636             : public:
    1637          10 :     MergeDoubleArrayFunc(std::vector<double>& rArray) : mrArray(rArray), miPos(mrArray.begin())
    1638             :     {
    1639          10 :         mfNaN = CreateDoubleError( errElementNaN);
    1640          10 :     }
    1641             : 
    1642          16 :     void operator() (const MatrixImplType::element_block_node_type& node)
    1643             :     {
    1644             :         using namespace mdds::mtv;
    1645             :         static _Op op;
    1646             : 
    1647          16 :         switch (node.type)
    1648             :         {
    1649             :             case mdds::mtm::element_numeric:
    1650             :             {
    1651           9 :                 numeric_element_block::const_iterator it = numeric_element_block::begin(*node.data);
    1652           9 :                 numeric_element_block::const_iterator itEnd = numeric_element_block::end(*node.data);
    1653          37 :                 for (; it != itEnd; ++it, ++miPos)
    1654             :                 {
    1655          28 :                     if (GetDoubleErrorValue(*miPos) == errElementNaN)
    1656           1 :                         continue;
    1657             : 
    1658          27 :                     *miPos = op(*miPos, *it);
    1659             :                 }
    1660             :             }
    1661           9 :             break;
    1662             :             case mdds::mtm::element_boolean:
    1663             :             {
    1664           0 :                 boolean_element_block::const_iterator it = boolean_element_block::begin(*node.data);
    1665           0 :                 boolean_element_block::const_iterator itEnd = boolean_element_block::end(*node.data);
    1666           0 :                 for (; it != itEnd; ++it, ++miPos)
    1667             :                 {
    1668           0 :                     if (GetDoubleErrorValue(*miPos) == errElementNaN)
    1669           0 :                         continue;
    1670             : 
    1671           0 :                     *miPos = op(*miPos, *it ? 1.0 : 0.0);
    1672             :                 }
    1673             :             }
    1674           0 :             break;
    1675             :             case mdds::mtm::element_string:
    1676             :             {
    1677           2 :                 for (size_t i = 0; i < node.size; ++i, ++miPos)
    1678           1 :                     *miPos = mfNaN;
    1679             :             }
    1680           1 :             break;
    1681             :             case mdds::mtm::element_empty:
    1682             :             {
    1683             :                 // Empty element is equivalent of having a numeric value of 0.0.
    1684          17 :                 for (size_t i = 0; i < node.size; ++i, ++miPos)
    1685             :                 {
    1686          11 :                     if (GetDoubleErrorValue(*miPos) == errElementNaN)
    1687           0 :                         continue;
    1688             : 
    1689          11 :                     *miPos = op(*miPos, 0.0);
    1690             :                 }
    1691             :             }
    1692             :             default:
    1693             :                 ;
    1694             :         }
    1695          16 :     }
    1696             : };
    1697             : 
    1698             : }
    1699             : 
    1700           7 : ScMatrix::IterateResult ScMatrixImpl::Sum(bool bTextAsZero) const
    1701             : {
    1702           7 :     WalkElementBlocks<SumOp> aFunc(bTextAsZero);
    1703           7 :     maMat.walk(aFunc);
    1704           7 :     return aFunc.getResult();
    1705             : }
    1706             : 
    1707           0 : ScMatrix::IterateResult ScMatrixImpl::SumSquare(bool bTextAsZero) const
    1708             : {
    1709           0 :     WalkElementBlocks<SumSquareOp> aFunc(bTextAsZero);
    1710           0 :     maMat.walk(aFunc);
    1711           0 :     return aFunc.getResult();
    1712             : }
    1713             : 
    1714           7 : ScMatrix::IterateResult ScMatrixImpl::Product(bool bTextAsZero) const
    1715             : {
    1716           7 :     WalkElementBlocks<ProductOp> aFunc(bTextAsZero);
    1717           7 :     maMat.walk(aFunc);
    1718           7 :     ScMatrix::IterateResult aRes = aFunc.getResult();
    1719           7 :     return aRes;
    1720             : }
    1721             : 
    1722           3 : size_t ScMatrixImpl::Count(bool bCountStrings) const
    1723             : {
    1724           3 :     CountElements aFunc(bCountStrings);
    1725           3 :     maMat.walk(aFunc);
    1726           3 :     return aFunc.getCount();
    1727             : }
    1728             : 
    1729           0 : size_t ScMatrixImpl::MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const
    1730             : {
    1731           0 :     WalkAndMatchElements<double> aFunc(fValue, maMat.size(), nCol1, nCol2);
    1732           0 :     maMat.walk(aFunc);
    1733           0 :     return aFunc.getMatching();
    1734             : }
    1735             : 
    1736           2 : size_t ScMatrixImpl::MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const
    1737             : {
    1738           2 :     WalkAndMatchElements<svl::SharedString> aFunc(rStr, maMat.size(), nCol1, nCol2);
    1739           2 :     maMat.walk(aFunc);
    1740           2 :     return aFunc.getMatching();
    1741             : }
    1742             : 
    1743           5 : double ScMatrixImpl::GetMaxValue( bool bTextAsZero ) const
    1744             : {
    1745           5 :     CalcMaxMinValue<MaxOp> aFunc(bTextAsZero);
    1746           5 :     maMat.walk(aFunc);
    1747           5 :     return aFunc.getValue();
    1748             : }
    1749             : 
    1750           4 : double ScMatrixImpl::GetMinValue( bool bTextAsZero ) const
    1751             : {
    1752           4 :     CalcMaxMinValue<MinOp> aFunc(bTextAsZero);
    1753           4 :     maMat.walk(aFunc);
    1754           4 :     return aFunc.getValue();
    1755             : }
    1756             : 
    1757          49 : ScMatrixRef ScMatrixImpl::CompareMatrix(
    1758             :     sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const
    1759             : {
    1760          49 :     MatrixImplType::size_pair_type aSize = maMat.size();
    1761          49 :     size_t nSize = aSize.column * aSize.row;
    1762          49 :     if (nMatPos == 0)
    1763             :     {
    1764          37 :         if (rComp.maCells[1].mbValue && !rComp.maCells[1].mbEmpty)
    1765             :         {
    1766             :             // Matrix on the left, and a numeric value on the right.  Use a
    1767             :             // function object that has much less branching for much better
    1768             :             // performance.
    1769          24 :             CompareMatrixToNumericFunc aFunc(nSize, rComp, rComp.maCells[1].mfValue, pOptions);
    1770          24 :             maMat.walk(aFunc);
    1771             : 
    1772             :             // We assume the result matrix has the same dimension as this matrix.
    1773          24 :             const std::vector<double>& rResVal = aFunc.getValues();
    1774          24 :             if (nSize != rResVal.size())
    1775           0 :                 ScMatrixRef();
    1776             : 
    1777          24 :             return ScMatrixRef(new ScMatrix(aSize.column, aSize.row, rResVal));
    1778             :         }
    1779             :     }
    1780             : 
    1781          25 :     CompareMatrixFunc aFunc(nSize, rComp, nMatPos, pOptions);
    1782          25 :     maMat.walk(aFunc);
    1783             : 
    1784             :     // We assume the result matrix has the same dimension as this matrix.
    1785          25 :     const std::vector<double>& rResVal = aFunc.getValues();
    1786          25 :     if (nSize != rResVal.size())
    1787           0 :         ScMatrixRef();
    1788             : 
    1789          25 :     return ScMatrixRef(new ScMatrix(aSize.column, aSize.row, rResVal));
    1790             : }
    1791             : 
    1792          20 : void ScMatrixImpl::GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const
    1793             : {
    1794          20 :     MatrixImplType::size_pair_type aSize = maMat.size();
    1795          20 :     ToDoubleArray aFunc(aSize.row*aSize.column, bEmptyAsZero);
    1796          20 :     maMat.walk(aFunc);
    1797          20 :     aFunc.swap(rArray);
    1798          20 : }
    1799             : 
    1800          10 : void ScMatrixImpl::MergeDoubleArray( std::vector<double>& rArray, ScMatrix::Op eOp ) const
    1801             : {
    1802          10 :     MatrixImplType::size_pair_type aSize = maMat.size();
    1803          10 :     size_t nSize = aSize.row*aSize.column;
    1804          10 :     if (nSize != rArray.size())
    1805          10 :         return;
    1806             : 
    1807          10 :     switch (eOp)
    1808             :     {
    1809             :         case ScMatrix::Mul:
    1810             :         {
    1811          10 :             MergeDoubleArrayFunc<ArrayMul> aFunc(rArray);
    1812          10 :             maMat.walk(aFunc);
    1813             :         }
    1814          10 :         break;
    1815             :         default:
    1816             :             ;
    1817             :     }
    1818             : }
    1819             : 
    1820           0 : void ScMatrixImpl::AddValues( const ScMatrixImpl& rMat )
    1821             : {
    1822           0 :     const MatrixImplType& rOther = rMat.maMat;
    1823           0 :     MatrixImplType::size_pair_type aSize = maMat.size();
    1824           0 :     if (aSize != rOther.size())
    1825             :         // Geometry must match.
    1826           0 :         return;
    1827             : 
    1828             :     // For now, we only add two matricies if and only if 1) the receiving
    1829             :     // matrix consists only of one numeric block, and 2) the other matrix
    1830             :     // consists of either one numeric block or one boolean block.  In the
    1831             :     // future, we may want to be more flexible support matricies that consist
    1832             :     // of multiple blocks.
    1833             : 
    1834           0 :     MatrixImplType::position_type aPos1 = maMat.position(0, 0);
    1835           0 :     MatrixImplType::const_position_type aPos2 = rOther.position(0, 0);
    1836           0 :     if (MatrixImplType::to_mtm_type(aPos1.first->type) != mdds::mtm::element_numeric)
    1837           0 :         return;
    1838             : 
    1839           0 :     if (aPos1.first->size != aPos2.first->size)
    1840           0 :         return;
    1841             : 
    1842           0 :     if (aPos1.first->size != aSize.row * aSize.column)
    1843           0 :         return;
    1844             : 
    1845             :     MatrixImplType::numeric_block_type::iterator it =
    1846           0 :         MatrixImplType::numeric_block_type::begin(*aPos1.first->data);
    1847             :     MatrixImplType::numeric_block_type::iterator itEnd =
    1848           0 :         MatrixImplType::numeric_block_type::end(*aPos1.first->data);
    1849             : 
    1850           0 :     switch (MatrixImplType::to_mtm_type(aPos2.first->type))
    1851             :     {
    1852             :         case mdds::mtm::element_boolean:
    1853             :         {
    1854             :             MatrixImplType::boolean_block_type::iterator it2 =
    1855           0 :                 MatrixImplType::boolean_block_type::begin(*aPos2.first->data);
    1856             : 
    1857           0 :             for (; it != itEnd; ++it, ++it2)
    1858           0 :                 *it += *it2;
    1859             :         }
    1860           0 :         break;
    1861             :         case mdds::mtm::element_numeric:
    1862             :         {
    1863             :             MatrixImplType::numeric_block_type::iterator it2 =
    1864           0 :                 MatrixImplType::numeric_block_type::begin(*aPos2.first->data);
    1865             : 
    1866           0 :             for (; it != itEnd; ++it, ++it2)
    1867           0 :                 *it += *it2;
    1868             :         }
    1869           0 :         break;
    1870             :         default:
    1871             :             ;
    1872             :     }
    1873             : }
    1874             : 
    1875             : namespace Op {
    1876             : 
    1877             : template<typename T>
    1878             : struct return_type
    1879             : {
    1880             :     typedef T type;
    1881             : };
    1882             : 
    1883             : template<>
    1884             : struct return_type<bool>
    1885             : {
    1886             :     typedef double type;
    1887             : };
    1888             : 
    1889             : template<>
    1890             : struct return_type<char>
    1891             : {
    1892             :     typedef svl::SharedString type;
    1893             : };
    1894             : 
    1895             : }
    1896             : 
    1897             : template<typename T, typename U, typename return_type>
    1898         504 : struct wrapped_iterator
    1899             : {
    1900             :     typedef ::std::bidirectional_iterator_tag iterator_category;
    1901             :     typedef typename T::const_iterator::value_type old_value_type;
    1902             :     typedef return_type value_type;
    1903             :     typedef value_type* pointer;
    1904             :     typedef value_type& reference;
    1905             :     typedef typename T::const_iterator::difference_type difference_type;
    1906             : 
    1907             :     typename T::const_iterator it;
    1908             :     mutable value_type val;
    1909             :     U maOp;
    1910             : 
    1911             : private:
    1912             : 
    1913          66 :     value_type calcVal() const
    1914             :     {
    1915          66 :         return maOp(*it);
    1916             :     }
    1917             : 
    1918             : public:
    1919             : 
    1920          24 :     wrapped_iterator(typename T::const_iterator it_, U aOp):
    1921             :         it(it_),
    1922             :         val(value_type()),
    1923          24 :         maOp(aOp)
    1924             :     {
    1925          24 :     }
    1926             : 
    1927         480 :     wrapped_iterator(const wrapped_iterator& r):
    1928             :         it(r.it),
    1929             :         val(r.val),
    1930         480 :         maOp(r.maOp)
    1931             :     {
    1932         480 :     }
    1933             : 
    1934             :     wrapped_iterator& operator=(const wrapped_iterator& r)
    1935             :     {
    1936             :         it = r.it;
    1937             :         return *this;
    1938             :     }
    1939             : 
    1940         216 :     bool operator==(const wrapped_iterator& r) const
    1941             :     {
    1942         216 :         return it == r.it;
    1943             :     }
    1944             : 
    1945         216 :     bool operator!=(const wrapped_iterator& r) const
    1946             :     {
    1947         216 :         return !operator==(r);
    1948             :     }
    1949             : 
    1950         168 :     wrapped_iterator& operator++()
    1951             :     {
    1952         168 :         ++it;
    1953             : 
    1954         168 :         return *this;
    1955             :     }
    1956             : 
    1957           0 :     wrapped_iterator& operator--()
    1958             :     {
    1959           0 :         --it;
    1960             : 
    1961           0 :         return *this;
    1962             :     }
    1963             : 
    1964          66 :     value_type& operator*() const
    1965             :     {
    1966          66 :         val = calcVal();
    1967          66 :         return val;
    1968             :     }
    1969             : 
    1970             :     pointer operator->() const
    1971             :     {
    1972             :         val = calcVal();
    1973             :         return &val;
    1974             :     }
    1975             : };
    1976             : 
    1977             : template<typename T, typename U, typename return_type>
    1978          12 : struct MatrixIteratorWrapper
    1979             : {
    1980             : private:
    1981             :     typename T::const_iterator m_itBegin;
    1982             :     typename T::const_iterator m_itEnd;
    1983             :     U maOp;
    1984             : public:
    1985          12 :     MatrixIteratorWrapper(typename T::const_iterator itBegin, typename T::const_iterator itEnd, U aOp):
    1986             :         m_itBegin(itBegin),
    1987             :         m_itEnd(itEnd),
    1988          12 :         maOp(aOp)
    1989             :     {
    1990          12 :     }
    1991             : 
    1992          12 :     wrapped_iterator<T, U, return_type> begin()
    1993             :     {
    1994          12 :         return wrapped_iterator<T, U, return_type>(m_itBegin, maOp);
    1995             :     }
    1996             : 
    1997          12 :     wrapped_iterator<T, U, return_type> end()
    1998             :     {
    1999          12 :         return wrapped_iterator<T, U, return_type>(m_itEnd, maOp);
    2000             :     }
    2001             : };
    2002             : 
    2003             : namespace {
    2004             : 
    2005          12 : MatrixImplType::position_type increment_position(const MatrixImplType::position_type& pos, size_t n)
    2006             : {
    2007          12 :     MatrixImplType::position_type ret = pos;
    2008          12 :     do
    2009             :     {
    2010          12 :         if (ret.second + n < ret.first->size)
    2011             :         {
    2012           0 :             ret.second += n;
    2013           0 :             break;
    2014             :         }
    2015             :         else
    2016             :         {
    2017          12 :             n -= (ret.first->size - ret.second);
    2018          12 :             ++ret.first;
    2019          12 :             ret.second = 0;
    2020             :         }
    2021             :     }
    2022             :     while (n > 0);
    2023          12 :     return ret;
    2024             : }
    2025             : 
    2026             : }
    2027             : 
    2028             : template<typename T>
    2029          12 : struct MatrixOpWrapper
    2030             : {
    2031             : private:
    2032             :     MatrixImplType& mrMat;
    2033             :     MatrixImplType::position_type pos;
    2034             :     T maOp;
    2035             : 
    2036             : public:
    2037          12 :     MatrixOpWrapper(MatrixImplType& rMat, T aOp):
    2038             :         mrMat(rMat),
    2039             :         pos(rMat.position(0,0)),
    2040          12 :         maOp(aOp)
    2041             :     {
    2042          12 :     }
    2043             : 
    2044          12 :     void operator()(const MatrixImplType::element_block_node_type& node)
    2045             :     {
    2046          12 :         switch (node.type)
    2047             :         {
    2048             :             case mdds::mtm::element_numeric:
    2049             :             {
    2050             :                 typedef MatrixImplType::numeric_block_type block_type;
    2051             : 
    2052          12 :                 block_type::const_iterator it = block_type::begin(*node.data);
    2053          12 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
    2054          12 :                 MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, maOp);
    2055          12 :                 pos = mrMat.set(pos,aFunc.begin(), aFunc.end());
    2056             :             }
    2057          12 :             break;
    2058             :             case mdds::mtm::element_boolean:
    2059             :             {
    2060             :                 typedef MatrixImplType::boolean_block_type block_type;
    2061             : 
    2062           0 :                 block_type::const_iterator it = block_type::begin(*node.data);
    2063           0 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
    2064             : 
    2065           0 :                 MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, maOp);
    2066           0 :                 pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
    2067             :             }
    2068           0 :             break;
    2069             :             case mdds::mtm::element_string:
    2070             :             {
    2071             :                 typedef MatrixImplType::string_block_type block_type;
    2072             : 
    2073           0 :                 block_type::const_iterator it = block_type::begin(*node.data);
    2074           0 :                 block_type::const_iterator itEnd = block_type::end(*node.data);
    2075             : 
    2076           0 :                 MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, maOp);
    2077           0 :                 pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
    2078             :             }
    2079           0 :             break;
    2080             :             case mdds::mtm::element_empty:
    2081             :             {
    2082           0 :                 if (maOp.useFunctionForEmpty())
    2083             :                 {
    2084           0 :                     std::vector<char> aVec(node.size);
    2085             :                     MatrixIteratorWrapper<std::vector<char>, T, typename T::number_value_type>
    2086           0 :                         aFunc(aVec.begin(), aVec.end(), maOp);
    2087           0 :                     pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
    2088             :                 }
    2089             :             }
    2090           0 :             break;
    2091             :             default:
    2092             :                 ;
    2093             :         }
    2094          12 :         pos = increment_position(pos, node.size);
    2095          12 :     }
    2096             : };
    2097             : 
    2098             : template<typename T>
    2099          12 : void ScMatrixImpl::ApplyOperation(T aOp, ScMatrixImpl& rMat)
    2100             : {
    2101          12 :     MatrixOpWrapper<T> aFunc(rMat.maMat, aOp);
    2102          12 :     maMat.walk(aFunc);
    2103          12 : }
    2104             : 
    2105             : #if DEBUG_MATRIX
    2106             : void ScMatrixImpl::Dump() const
    2107             : {
    2108             :     cout << "-- matrix content" << endl;
    2109             :     SCSIZE nCols, nRows;
    2110             :     GetDimensions(nCols, nRows);
    2111             :     for (SCSIZE nRow = 0; nRow < nRows; ++nRow)
    2112             :     {
    2113             :         for (SCSIZE nCol = 0; nCol < nCols; ++nCol)
    2114             :         {
    2115             :             cout << "  row=" << nRow << ", col=" << nCol << " : ";
    2116             :             switch (maMat.get_type(nRow, nCol))
    2117             :             {
    2118             :                 case mdds::mtm::element_string:
    2119             :                     cout << "string (" << maMat.get_string(nRow, nCol).getString() << ")";
    2120             :                 break;
    2121             :                 case mdds::mtm::element_numeric:
    2122             :                     cout << "numeric (" << maMat.get_numeric(nRow, nCol) << ")";
    2123             :                 break;
    2124             :                 case mdds::mtm::element_boolean:
    2125             :                     cout << "boolean (" << maMat.get_boolean(nRow, nCol) << ")";
    2126             :                 break;
    2127             :                 case mdds::mtm::element_empty:
    2128             :                     cout << "empty";
    2129             :                 break;
    2130             :                 default:
    2131             :                     ;
    2132             :             }
    2133             : 
    2134             :             cout << endl;
    2135             :         }
    2136             :     }
    2137             : }
    2138             : #endif
    2139             : 
    2140         310 : void ScMatrixImpl::CalcPosition(SCSIZE nIndex, SCSIZE& rC, SCSIZE& rR) const
    2141             : {
    2142         310 :     SCSIZE nRowSize = maMat.size().row;
    2143             :     SAL_WARN_IF( !nRowSize, "sc", "ScMatrixImpl::CalcPosition: 0 rows!");
    2144         310 :     rC = nRowSize > 1 ? nIndex / nRowSize : nIndex;
    2145         310 :     rR = nIndex - rC*nRowSize;
    2146         310 : }
    2147             : 
    2148        1985 : void ScMatrix::IncRef() const
    2149             : {
    2150        1985 :     ++nRefCnt;
    2151        1985 : }
    2152             : 
    2153        1973 : void ScMatrix::DecRef() const
    2154             : {
    2155        1973 :     --nRefCnt;
    2156        1973 :     if (nRefCnt == 0)
    2157         492 :         delete this;
    2158        1973 : }
    2159             : 
    2160         322 : ScMatrix::ScMatrix( SCSIZE nC, SCSIZE nR) :
    2161         322 :     pImpl(new ScMatrixImpl(nC, nR)), nRefCnt(0)
    2162             : {
    2163             :     SAL_WARN_IF( !nC, "sc", "ScMatrix with 0 columns!");
    2164             :     SAL_WARN_IF( !nR, "sc", "ScMatrix with 0 rows!");
    2165         322 : }
    2166             : 
    2167         133 : ScMatrix::ScMatrix(SCSIZE nC, SCSIZE nR, double fInitVal) :
    2168         133 :     pImpl(new ScMatrixImpl(nC, nR, fInitVal)), nRefCnt(0)
    2169             : {
    2170             :     SAL_WARN_IF( !nC, "sc", "ScMatrix with 0 columns!");
    2171             :     SAL_WARN_IF( !nR, "sc", "ScMatrix with 0 rows!");
    2172         133 : }
    2173             : 
    2174          49 : ScMatrix::ScMatrix( size_t nC, size_t nR, const std::vector<double>& rInitVals ) :
    2175          49 :     pImpl(new ScMatrixImpl(nC, nR, rInitVals)), nRefCnt(0)
    2176             : {
    2177             :     SAL_WARN_IF( !nC, "sc", "ScMatrix with 0 columns!");
    2178             :     SAL_WARN_IF( !nR, "sc", "ScMatrix with 0 rows!");
    2179          49 : }
    2180             : 
    2181         492 : ScMatrix::~ScMatrix()
    2182             : {
    2183         492 :     delete pImpl;
    2184         492 : }
    2185             : 
    2186           0 : ScMatrix* ScMatrix::Clone() const
    2187             : {
    2188             :     SCSIZE nC, nR;
    2189           0 :     pImpl->GetDimensions(nC, nR);
    2190           0 :     ScMatrix* pScMat = new ScMatrix(nC, nR);
    2191           0 :     MatCopy(*pScMat);
    2192           0 :     pScMat->SetErrorInterpreter(pImpl->GetErrorInterpreter());    // TODO: really?
    2193           0 :     return pScMat;
    2194             : }
    2195             : 
    2196           0 : ScMatrix* ScMatrix::CloneIfConst()
    2197             : {
    2198           0 :     return pImpl->IsImmutable() ? Clone() : this;
    2199             : }
    2200             : 
    2201         284 : void ScMatrix::SetImmutable( bool bVal )
    2202             : {
    2203         284 :     pImpl->SetImmutable(bVal);
    2204         284 : }
    2205             : 
    2206           7 : void ScMatrix::Resize( SCSIZE nC, SCSIZE nR)
    2207             : {
    2208           7 :     pImpl->Resize(nC, nR);
    2209           7 : }
    2210             : 
    2211           2 : void ScMatrix::Resize(SCSIZE nC, SCSIZE nR, double fVal)
    2212             : {
    2213           2 :     pImpl->Resize(nC, nR, fVal);
    2214           2 : }
    2215             : 
    2216           0 : ScMatrix* ScMatrix::CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const
    2217             : {
    2218           0 :     ScMatrix* pScMat = new ScMatrix(nNewCols, nNewRows);
    2219           0 :     MatCopy(*pScMat);
    2220           0 :     pScMat->SetErrorInterpreter(pImpl->GetErrorInterpreter());
    2221           0 :     return pScMat;
    2222             : }
    2223             : 
    2224         867 : void ScMatrix::SetErrorInterpreter( ScInterpreter* p)
    2225             : {
    2226         867 :     pImpl->SetErrorInterpreter(p);
    2227         867 : }
    2228             : 
    2229         962 : void ScMatrix::GetDimensions( SCSIZE& rC, SCSIZE& rR) const
    2230             : {
    2231         962 :     pImpl->GetDimensions(rC, rR);
    2232         962 : }
    2233             : 
    2234          32 : SCSIZE ScMatrix::GetElementCount() const
    2235             : {
    2236          32 :     return pImpl->GetElementCount();
    2237             : }
    2238             : 
    2239           0 : bool ScMatrix::ValidColRow( SCSIZE nC, SCSIZE nR) const
    2240             : {
    2241           0 :     return pImpl->ValidColRow(nC, nR);
    2242             : }
    2243             : 
    2244           0 : bool ScMatrix::ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const
    2245             : {
    2246           0 :     return pImpl->ValidColRowReplicated(rC, rR);
    2247             : }
    2248             : 
    2249           0 : bool ScMatrix::ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const
    2250             : {
    2251           0 :     return ValidColRow( rC, rR) || ValidColRowReplicated( rC, rR);
    2252             : }
    2253             : 
    2254         334 : void ScMatrix::PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
    2255             : {
    2256         334 :     pImpl->PutDouble(fVal, nC, nR);
    2257         334 : }
    2258             : 
    2259          33 : void ScMatrix::PutDouble( double fVal, SCSIZE nIndex)
    2260             : {
    2261          33 :     pImpl->PutDouble(fVal, nIndex);
    2262          33 : }
    2263             : 
    2264         307 : void ScMatrix::PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
    2265             : {
    2266         307 :     pImpl->PutDouble(pArray, nLen, nC, nR);
    2267         307 : }
    2268             : 
    2269         396 : void ScMatrix::PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR)
    2270             : {
    2271         396 :     pImpl->PutString(rStr, nC, nR);
    2272         396 : }
    2273             : 
    2274          12 : void ScMatrix::PutString(const svl::SharedString& rStr, SCSIZE nIndex)
    2275             : {
    2276          12 :     pImpl->PutString(rStr, nIndex);
    2277          12 : }
    2278             : 
    2279          18 : void ScMatrix::PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
    2280             : {
    2281          18 :     pImpl->PutString(pArray, nLen, nC, nR);
    2282          18 : }
    2283             : 
    2284           1 : void ScMatrix::PutEmpty(SCSIZE nC, SCSIZE nR)
    2285             : {
    2286           1 :     pImpl->PutEmpty(nC, nR);
    2287           1 : }
    2288             : 
    2289           3 : void ScMatrix::PutEmptyPath(SCSIZE nC, SCSIZE nR)
    2290             : {
    2291           3 :     pImpl->PutEmptyPath(nC, nR);
    2292           3 : }
    2293             : 
    2294           0 : void ScMatrix::PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR )
    2295             : {
    2296           0 :     pImpl->PutError(nErrorCode, nC, nR);
    2297           0 : }
    2298             : 
    2299           5 : void ScMatrix::PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
    2300             : {
    2301           5 :     pImpl->PutBoolean(bVal, nC, nR);
    2302           5 : }
    2303             : 
    2304          15 : sal_uInt16 ScMatrix::GetError( SCSIZE nC, SCSIZE nR) const
    2305             : {
    2306          15 :     return pImpl->GetError(nC, nR);
    2307             : }
    2308             : 
    2309        1798 : double ScMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const
    2310             : {
    2311        1798 :     return pImpl->GetDouble(nC, nR);
    2312             : }
    2313             : 
    2314         208 : double ScMatrix::GetDouble( SCSIZE nIndex) const
    2315             : {
    2316         208 :     return pImpl->GetDouble(nIndex);
    2317             : }
    2318             : 
    2319          13 : svl::SharedString ScMatrix::GetString(SCSIZE nC, SCSIZE nR) const
    2320             : {
    2321          13 :     return pImpl->GetString(nC, nR);
    2322             : }
    2323             : 
    2324           0 : svl::SharedString ScMatrix::GetString( SCSIZE nIndex) const
    2325             : {
    2326           0 :     return pImpl->GetString(nIndex);
    2327             : }
    2328             : 
    2329           3 : svl::SharedString ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
    2330             : {
    2331           3 :     return pImpl->GetString(rFormatter, nC, nR);
    2332             : }
    2333             : 
    2334         698 : ScMatrixValue ScMatrix::Get(SCSIZE nC, SCSIZE nR) const
    2335             : {
    2336         698 :     return pImpl->Get(nC, nR);
    2337             : }
    2338             : 
    2339           0 : bool ScMatrix::IsString( SCSIZE nIndex ) const
    2340             : {
    2341           0 :     return pImpl->IsString(nIndex);
    2342             : }
    2343             : 
    2344        1687 : bool ScMatrix::IsString( SCSIZE nC, SCSIZE nR ) const
    2345             : {
    2346        1687 :     return pImpl->IsString(nC, nR);
    2347             : }
    2348             : 
    2349           8 : bool ScMatrix::IsEmpty( SCSIZE nC, SCSIZE nR ) const
    2350             : {
    2351           8 :     return pImpl->IsEmpty(nC, nR);
    2352             : }
    2353             : 
    2354          21 : bool ScMatrix::IsEmptyCell( SCSIZE nC, SCSIZE nR ) const
    2355             : {
    2356          21 :     return pImpl->IsEmptyCell(nC, nR);
    2357             : }
    2358             : 
    2359           7 : bool ScMatrix::IsEmptyResult( SCSIZE nC, SCSIZE nR ) const
    2360             : {
    2361           7 :     return pImpl->IsEmptyResult(nC, nR);
    2362             : }
    2363             : 
    2364           7 : bool ScMatrix::IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
    2365             : {
    2366           7 :     return pImpl->IsEmptyPath(nC, nR);
    2367             : }
    2368             : 
    2369          57 : bool ScMatrix::IsValue( SCSIZE nIndex ) const
    2370             : {
    2371          57 :     return pImpl->IsValue(nIndex);
    2372             : }
    2373             : 
    2374          91 : bool ScMatrix::IsValue( SCSIZE nC, SCSIZE nR ) const
    2375             : {
    2376          91 :     return pImpl->IsValue(nC, nR);
    2377             : }
    2378             : 
    2379          66 : bool ScMatrix::IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
    2380             : {
    2381          66 :     return pImpl->IsValueOrEmpty(nC, nR);
    2382             : }
    2383             : 
    2384          18 : bool ScMatrix::IsBoolean( SCSIZE nC, SCSIZE nR ) const
    2385             : {
    2386          18 :     return pImpl->IsBoolean(nC, nR);
    2387             : }
    2388             : 
    2389          14 : bool ScMatrix::IsNumeric() const
    2390             : {
    2391          14 :     return pImpl->IsNumeric();
    2392             : }
    2393             : 
    2394          12 : void ScMatrix::MatCopy(ScMatrix& mRes) const
    2395             : {
    2396          12 :     pImpl->MatCopy(*mRes.pImpl);
    2397          12 : }
    2398             : 
    2399           1 : void ScMatrix::MatTrans(ScMatrix& mRes) const
    2400             : {
    2401           1 :     pImpl->MatTrans(*mRes.pImpl);
    2402           1 : }
    2403             : 
    2404          12 : void ScMatrix::FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 )
    2405             : {
    2406          12 :     pImpl->FillDouble(fVal, nC1, nR1, nC2, nR2);
    2407          12 : }
    2408             : 
    2409           6 : void ScMatrix::PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR )
    2410             : {
    2411           6 :     pImpl->PutDoubleVector(rVec, nC, nR);
    2412           6 : }
    2413             : 
    2414           0 : void ScMatrix::PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR )
    2415             : {
    2416           0 :     pImpl->PutStringVector(rVec, nC, nR);
    2417           0 : }
    2418             : 
    2419           0 : void ScMatrix::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
    2420             : {
    2421           0 :     pImpl->PutEmptyVector(nCount, nC, nR);
    2422           0 : }
    2423             : 
    2424           0 : void ScMatrix::PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
    2425             : {
    2426           0 :     pImpl->PutEmptyResultVector(nCount, nC, nR);
    2427           0 : }
    2428             : 
    2429           0 : void ScMatrix::PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
    2430             : {
    2431           0 :     pImpl->PutEmptyPathVector(nCount, nC, nR);
    2432           0 : }
    2433             : 
    2434           0 : void ScMatrix::CompareEqual()
    2435             : {
    2436           0 :     pImpl->CompareEqual();
    2437           0 : }
    2438             : 
    2439           0 : void ScMatrix::CompareNotEqual()
    2440             : {
    2441           0 :     pImpl->CompareNotEqual();
    2442           0 : }
    2443             : 
    2444           0 : void ScMatrix::CompareLess()
    2445             : {
    2446           0 :     pImpl->CompareLess();
    2447           0 : }
    2448             : 
    2449           0 : void ScMatrix::CompareGreater()
    2450             : {
    2451           0 :     pImpl->CompareGreater();
    2452           0 : }
    2453             : 
    2454           0 : void ScMatrix::CompareLessEqual()
    2455             : {
    2456           0 :     pImpl->CompareLessEqual();
    2457           0 : }
    2458             : 
    2459           0 : void ScMatrix::CompareGreaterEqual()
    2460             : {
    2461           0 :     pImpl->CompareGreaterEqual();
    2462           0 : }
    2463             : 
    2464           9 : double ScMatrix::And() const
    2465             : {
    2466           9 :     return pImpl->And();
    2467             : }
    2468             : 
    2469          13 : double ScMatrix::Or() const
    2470             : {
    2471          13 :     return pImpl->Or();
    2472             : }
    2473             : 
    2474           0 : double ScMatrix::Xor() const
    2475             : {
    2476           0 :     return pImpl->Xor();
    2477             : }
    2478             : 
    2479           7 : ScMatrix::IterateResult ScMatrix::Sum(bool bTextAsZero) const
    2480             : {
    2481           7 :     return pImpl->Sum(bTextAsZero);
    2482             : }
    2483             : 
    2484           0 : ScMatrix::IterateResult ScMatrix::SumSquare(bool bTextAsZero) const
    2485             : {
    2486           0 :     return pImpl->SumSquare(bTextAsZero);
    2487             : }
    2488             : 
    2489           7 : ScMatrix::IterateResult ScMatrix::Product(bool bTextAsZero) const
    2490             : {
    2491           7 :     return pImpl->Product(bTextAsZero);
    2492             : }
    2493             : 
    2494           3 : size_t ScMatrix::Count(bool bCountStrings) const
    2495             : {
    2496           3 :     return pImpl->Count(bCountStrings);
    2497             : }
    2498             : 
    2499           0 : size_t ScMatrix::MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const
    2500             : {
    2501           0 :     return pImpl->MatchDoubleInColumns(fValue, nCol1, nCol2);
    2502             : }
    2503             : 
    2504           2 : size_t ScMatrix::MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const
    2505             : {
    2506           2 :     return pImpl->MatchStringInColumns(rStr, nCol1, nCol2);
    2507             : }
    2508             : 
    2509           5 : double ScMatrix::GetMaxValue( bool bTextAsZero ) const
    2510             : {
    2511           5 :     return pImpl->GetMaxValue(bTextAsZero);
    2512             : }
    2513             : 
    2514           4 : double ScMatrix::GetMinValue( bool bTextAsZero ) const
    2515             : {
    2516           4 :     return pImpl->GetMinValue(bTextAsZero);
    2517             : }
    2518             : 
    2519          49 : ScMatrixRef ScMatrix::CompareMatrix(
    2520             :     sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const
    2521             : {
    2522          49 :     return pImpl->CompareMatrix(rComp, nMatPos, pOptions);
    2523             : }
    2524             : 
    2525          20 : void ScMatrix::GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const
    2526             : {
    2527          20 :     pImpl->GetDoubleArray(rArray, bEmptyAsZero);
    2528          20 : }
    2529             : 
    2530          10 : void ScMatrix::MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const
    2531             : {
    2532          10 :     pImpl->MergeDoubleArray(rArray, eOp);
    2533          10 : }
    2534             : 
    2535             : namespace matop {
    2536             : 
    2537             : /**
    2538             :  * COp struct is used in MatOp class to provide (through template specialization)
    2539             :  * different actions for empty entries in a matrix.
    2540             :  */
    2541             : template <typename T, typename S>
    2542             : struct COp {};
    2543             : 
    2544             : template <typename T>
    2545             : struct COp<T, svl::SharedString>
    2546             : {
    2547             :     svl::SharedString operator()(char, T /*aOp*/, double /*a*/, double /*b*/, const svl::SharedString& rString) const
    2548             :     {
    2549             :         return rString;
    2550             :     }
    2551             : };
    2552             : 
    2553             : template <typename T>
    2554             : struct COp<T, double>
    2555             : {
    2556           0 :     double operator()(char, T aOp, double a, double b, const svl::SharedString& /*rString*/) const
    2557             :     {
    2558           0 :         return aOp( a, b);
    2559             :     }
    2560             : };
    2561             : 
    2562             : /** A template for operations where operands are supposed to be numeric.
    2563             :     A non-numeric (string) operand leads to an errNoValue DoubleError.
    2564             :     An empty operand evaluates to 0.
    2565             :     XXX: semantically TEmptyRes and types other than number_value_type are
    2566             :     unused, but this template could serve as a basis for future enhancements.
    2567             :  */
    2568             : template<typename TOp, typename TEmptyRes=double, typename TRet=double>
    2569        1188 : struct MatOp
    2570             : {
    2571             : private:
    2572             :     TOp maOp;
    2573             :     svl::SharedString maString;
    2574             :     double mfVal;
    2575             :     COp<TOp, TEmptyRes> maCOp;
    2576             : 
    2577             : public:
    2578             :     typedef TEmptyRes empty_value_type;
    2579             :     typedef TRet number_value_type;
    2580             :     typedef svl::SharedString string_value_type;
    2581             : 
    2582          12 :     MatOp( TOp aOp, double fVal = 0.0, const svl::SharedString& rString = svl::SharedString() ):
    2583             :         maOp(aOp),
    2584             :         maString(rString),
    2585          12 :         mfVal(fVal)
    2586          12 :     { }
    2587             : 
    2588          66 :     TRet operator()(double fVal) const
    2589             :     {
    2590          66 :         return maOp(fVal, mfVal);
    2591             :     }
    2592             : 
    2593           0 :     TRet operator()(bool bVal) const
    2594             :     {
    2595           0 :         return maOp((double)bVal, mfVal);
    2596             :     }
    2597             : 
    2598           0 :     double operator()(const svl::SharedString&) const
    2599             :     {
    2600           0 :         return CreateDoubleError( errNoValue);
    2601             :     }
    2602             : 
    2603           0 :     TEmptyRes operator()(char) const
    2604             :     {
    2605           0 :         return maCOp(char{}, maOp, 0, mfVal, maString);
    2606             :     }
    2607             : 
    2608           0 :     static bool useFunctionForEmpty()
    2609             :     {
    2610           0 :         return true;
    2611             :     }
    2612             : };
    2613             : 
    2614             : }
    2615             : 
    2616           0 : void ScMatrix::NotOp( ScMatrix& rMat)
    2617             : {
    2618           0 :     auto not_ = [](double a, double){return double(a == 0.0);};
    2619           0 :     matop::MatOp<decltype(not_), double> aOp(not_);
    2620           0 :     pImpl->ApplyOperation(aOp, *rMat.pImpl);
    2621           0 : }
    2622             : 
    2623           0 : void ScMatrix::NegOp( ScMatrix& rMat)
    2624             : {
    2625           0 :     auto neg_ = [](double a, double){return -a;};
    2626           0 :     matop::MatOp<decltype(neg_), double> aOp(neg_);
    2627           0 :     pImpl->ApplyOperation(aOp, *rMat.pImpl);
    2628           0 : }
    2629             : 
    2630           6 : void ScMatrix::AddOp( double fVal, ScMatrix& rMat)
    2631             : {
    2632          34 :     auto add_ = [](double a, double b){return a + b;};
    2633           6 :     matop::MatOp<decltype(add_)> aOp(add_, fVal);
    2634           6 :     pImpl->ApplyOperation(aOp, *rMat.pImpl);
    2635           6 : }
    2636             : 
    2637           3 : void ScMatrix::SubOp( bool bFlag, double fVal, ScMatrix& rMat)
    2638             : {
    2639           3 :     if (bFlag)
    2640             :     {
    2641           5 :         auto sub_ = [](double a, double b){return b - a;};
    2642           1 :         matop::MatOp<decltype(sub_)> aOp(sub_, fVal);
    2643           1 :         pImpl->ApplyOperation(aOp, *rMat.pImpl);
    2644             :     }
    2645             :     else
    2646             :     {
    2647          11 :         auto sub_ = [](double a, double b){return a - b;};
    2648           2 :         matop::MatOp<decltype(sub_)> aOp(sub_, fVal);
    2649           2 :         pImpl->ApplyOperation(aOp, *rMat.pImpl);
    2650             :     }
    2651           3 : }
    2652             : 
    2653           3 : void ScMatrix::MulOp( double fVal, ScMatrix& rMat)
    2654             : {
    2655          16 :     auto mul_ = [](double a, double b){return a * b;};
    2656           3 :     matop::MatOp<decltype(mul_)> aOp(mul_, fVal);
    2657           3 :     pImpl->ApplyOperation(aOp, *rMat.pImpl);
    2658           3 : }
    2659             : 
    2660           0 : void ScMatrix::DivOp( bool bFlag, double fVal, ScMatrix& rMat)
    2661             : {
    2662           0 :     if (bFlag)
    2663             :     {
    2664           0 :         auto div_ = [](double a, double b){return sc::div(b, a);};
    2665           0 :         matop::MatOp<decltype(div_)> aOp(div_, fVal);
    2666           0 :         pImpl->ApplyOperation(aOp, *rMat.pImpl);
    2667             :     }
    2668             :     else
    2669             :     {
    2670           0 :         auto div_ = [](double a, double b){return sc::div(a, b);};
    2671           0 :         matop::MatOp<decltype(div_)> aOp(div_, fVal);
    2672           0 :         pImpl->ApplyOperation(aOp, *rMat.pImpl);
    2673             :     }
    2674           0 : }
    2675             : 
    2676           0 : void ScMatrix::PowOp( bool bFlag, double fVal, ScMatrix& rMat)
    2677             : {
    2678           0 :     if (bFlag)
    2679             :     {
    2680           0 :         auto pow_ = [](double a, double b){return pow(b, a);};
    2681           0 :         matop::MatOp<decltype(pow_)> aOp(pow_, fVal);
    2682           0 :         pImpl->ApplyOperation(aOp, *rMat.pImpl);
    2683             :     }
    2684             :     else
    2685             :     {
    2686           0 :         auto pow_ = [](double a, double b){return pow(a, b);};
    2687           0 :         matop::MatOp<decltype(pow_)> aOp(pow_, fVal);
    2688           0 :         pImpl->ApplyOperation(aOp, *rMat.pImpl);
    2689             :     }
    2690           0 : }
    2691             : 
    2692           0 : ScMatrix& ScMatrix::operator+= ( const ScMatrix& r )
    2693             : {
    2694           0 :     pImpl->AddValues(*r.pImpl);
    2695           0 :     return *this;
    2696         156 : }
    2697             : 
    2698             : #if DEBUG_MATRIX
    2699             : void ScMatrix::Dump() const
    2700             : {
    2701             :     pImpl->Dump();
    2702             : }
    2703             : #endif
    2704             : 
    2705             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11