fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / core / tool / scmatrix.cxx
blobc5c42f338ba5a7e5911be506523d36b8eb2a05a3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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"
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>
35 #include <math.h>
37 #include <vector>
38 #include <limits>
40 #include <mdds/multi_type_matrix.hpp>
41 #include <mdds/multi_type_vector_types.hpp>
42 #include <mdds/multi_type_vector_trait.hpp>
44 #if DEBUG_MATRIX
45 #include <iostream>
46 using std::cout;
47 using std::endl;
48 #endif
50 using ::std::pair;
51 using ::std::for_each;
52 using ::std::count_if;
53 using ::std::advance;
54 using ::std::unary_function;
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.
60 struct custom_string_trait
62 typedef svl::SharedString string_type;
63 typedef sc::string_block string_element_block;
65 static const mdds::mtv::element_t string_type_identifier = sc::element_type_string;
67 typedef mdds::mtv::custom_block_func1<sc::string_block> element_block_func;
70 typedef mdds::multi_type_matrix<custom_string_trait> MatrixImplType;
72 namespace {
74 struct ElemEqualZero : public unary_function<double, double>
76 double operator() (double val) const
78 if (!::rtl::math::isFinite(val))
79 return val;
80 return val == 0.0 ? 1.0 : 0.0;
84 struct ElemNotEqualZero : public unary_function<double, double>
86 double operator() (double val) const
88 if (!::rtl::math::isFinite(val))
89 return val;
90 return val != 0.0 ? 1.0 : 0.0;
94 struct ElemGreaterZero : public unary_function<double, double>
96 double operator() (double val) const
98 if (!::rtl::math::isFinite(val))
99 return val;
100 return val > 0.0 ? 1.0 : 0.0;
104 struct ElemLessZero : public unary_function<double, double>
106 double operator() (double val) const
108 if (!::rtl::math::isFinite(val))
109 return val;
110 return val < 0.0 ? 1.0 : 0.0;
114 struct ElemGreaterEqualZero : public unary_function<double, double>
116 double operator() (double val) const
118 if (!::rtl::math::isFinite(val))
119 return val;
120 return val >= 0.0 ? 1.0 : 0.0;
124 struct ElemLessEqualZero : public unary_function<double, double>
126 double operator() (double val) const
128 if (!::rtl::math::isFinite(val))
129 return val;
130 return val <= 0.0 ? 1.0 : 0.0;
134 template<typename _Comp>
135 class CompareMatrixElemFunc : std::unary_function<MatrixImplType::element_block_node_type, void>
137 static _Comp maComp;
139 std::vector<double> maNewMatValues; // double instead of bool to transport error values
140 size_t mnRow;
141 size_t mnCol;
142 public:
143 CompareMatrixElemFunc( size_t nRow, size_t nCol ) : mnRow(nRow), mnCol(nCol)
145 maNewMatValues.reserve(nRow*nCol);
148 void operator() (const MatrixImplType::element_block_node_type& node)
150 switch (node.type)
152 case mdds::mtm::element_numeric:
154 typedef MatrixImplType::numeric_block_type block_type;
156 block_type::const_iterator it = block_type::begin(*node.data);
157 block_type::const_iterator itEnd = block_type::end(*node.data);
158 for (; it != itEnd; ++it)
160 double fVal = *it;
161 maNewMatValues.push_back(maComp(fVal));
164 break;
165 case mdds::mtm::element_boolean:
167 typedef MatrixImplType::boolean_block_type block_type;
169 block_type::const_iterator it = block_type::begin(*node.data);
170 block_type::const_iterator itEnd = block_type::end(*node.data);
171 for (; it != itEnd; ++it)
173 double fVal = *it ? 1.0 : 0.0;
174 maNewMatValues.push_back(maComp(fVal));
177 break;
178 case mdds::mtm::element_string:
179 case mdds::mtm::element_empty:
180 default:
181 // Fill it with false.
182 maNewMatValues.resize(maNewMatValues.size() + node.size, 0.0);
186 void swap( MatrixImplType& rMat )
188 MatrixImplType aNewMat(mnRow, mnCol, maNewMatValues.begin(), maNewMatValues.end());
189 rMat.swap(aNewMat);
193 template<typename _Comp>
194 _Comp CompareMatrixElemFunc<_Comp>::maComp;
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;
205 class ScMatrixImpl: private boost::noncopyable
207 MatrixImplType maMat;
208 MatrixImplType maMatFlag;
209 ScInterpreter* pErrorInterpreter;
210 bool mbCloneIfConst; // Whether the matrix is cloned with a CloneIfConst() call.
212 public:
213 ScMatrixImpl(SCSIZE nC, SCSIZE nR);
214 ScMatrixImpl(SCSIZE nC, SCSIZE nR, double fInitVal);
216 ScMatrixImpl( size_t nC, size_t nR, const std::vector<double>& rInitVals );
218 ~ScMatrixImpl();
220 void Clear();
221 void SetImmutable(bool bVal);
222 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 ScInterpreter* GetErrorInterpreter() const { return pErrorInterpreter; }
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;
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);
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);
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;
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;
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;
291 double GetMaxValue( bool bTextAsZero ) const;
292 double GetMinValue( bool bTextAsZero ) const;
294 ScMatrixRef CompareMatrix( sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const;
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 );
300 template<typename T>
301 void ApplyOperation(T aOp, ScMatrixImpl& rMat);
303 #if DEBUG_MATRIX
304 void Dump() const;
305 #endif
307 private:
308 void CalcPosition(SCSIZE nIndex, SCSIZE& rC, SCSIZE& rR) const;
311 ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR) :
312 maMat(nR, nC), maMatFlag(nR, nC, SC_MATFLAG_EMPTYCELL), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
314 ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR, double fInitVal) :
315 maMat(nR, nC, fInitVal), maMatFlag(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
317 ScMatrixImpl::ScMatrixImpl( size_t nC, size_t nR, const std::vector<double>& rInitVals ) :
318 maMat(nR, nC, rInitVals.begin(), rInitVals.end()), maMatFlag(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
320 ScMatrixImpl::~ScMatrixImpl()
322 Clear();
325 void ScMatrixImpl::Clear()
327 maMat.clear();
328 maMatFlag.clear();
331 void ScMatrixImpl::SetImmutable(bool bVal)
333 mbCloneIfConst = bVal;
336 void ScMatrixImpl::Resize(SCSIZE nC, SCSIZE nR)
338 maMat.resize(nR, nC);
339 maMatFlag.resize(nR, nC);
342 void ScMatrixImpl::Resize(SCSIZE nC, SCSIZE nR, double fVal)
344 maMat.resize(nR, nC, fVal);
345 maMatFlag.resize(nR, nC);
348 void ScMatrixImpl::SetErrorInterpreter( ScInterpreter* p)
350 pErrorInterpreter = p;
353 void ScMatrixImpl::GetDimensions( SCSIZE& rC, SCSIZE& rR) const
355 MatrixImplType::size_pair_type aSize = maMat.size();
356 rR = aSize.row;
357 rC = aSize.column;
360 SCSIZE ScMatrixImpl::GetElementCount() const
362 MatrixImplType::size_pair_type aSize = maMat.size();
363 return aSize.row * aSize.column;
366 bool ScMatrixImpl::ValidColRow( SCSIZE nC, SCSIZE nR) const
368 MatrixImplType::size_pair_type aSize = maMat.size();
369 return nR < aSize.row && nC < aSize.column;
372 bool ScMatrixImpl::ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const
374 MatrixImplType::size_pair_type aSize = maMat.size();
375 if (aSize.column == 1 && aSize.row == 1)
377 rC = 0;
378 rR = 0;
379 return true;
381 else if (aSize.column == 1 && rR < aSize.row)
383 // single column matrix.
384 rC = 0;
385 return true;
387 else if (aSize.row == 1 && rC < aSize.column)
389 // single row matrix.
390 rR = 0;
391 return true;
393 return false;
396 bool ScMatrixImpl::ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const
398 return ValidColRow( rC, rR) || ValidColRowReplicated( rC, rR);
401 void ScMatrixImpl::SetErrorAtInterpreter( sal_uInt16 nError ) const
403 if ( pErrorInterpreter )
404 pErrorInterpreter->SetError( nError);
407 void ScMatrixImpl::PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
409 if (ValidColRow( nC, nR))
410 maMat.set(nR, nC, fVal);
411 else
413 OSL_FAIL("ScMatrixImpl::PutDouble: dimension error");
417 void ScMatrixImpl::PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
419 if (ValidColRow( nC, nR))
420 maMat.set(nR, nC, pArray, pArray + nLen);
421 else
423 OSL_FAIL("ScMatrixImpl::PutDouble: dimension error");
427 void ScMatrixImpl::PutDouble( double fVal, SCSIZE nIndex)
429 SCSIZE nC, nR;
430 CalcPosition(nIndex, nC, nR);
431 PutDouble(fVal, nC, nR);
434 void ScMatrixImpl::PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR)
436 if (ValidColRow( nC, nR))
437 maMat.set(nR, nC, rStr);
438 else
440 OSL_FAIL("ScMatrixImpl::PutString: dimension error");
444 void ScMatrixImpl::PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
446 if (ValidColRow( nC, nR))
447 maMat.set(nR, nC, pArray, pArray + nLen);
448 else
450 OSL_FAIL("ScMatrixImpl::PutString: dimension error");
454 void ScMatrixImpl::PutString(const svl::SharedString& rStr, SCSIZE nIndex)
456 SCSIZE nC, nR;
457 CalcPosition(nIndex, nC, nR);
458 PutString(rStr, nC, nR);
461 void ScMatrixImpl::PutEmpty(SCSIZE nC, SCSIZE nR)
463 if (ValidColRow( nC, nR))
465 maMat.set_empty(nR, nC);
466 maMatFlag.set(nR, nC, SC_MATFLAG_EMPTYCELL);
468 else
470 OSL_FAIL("ScMatrixImpl::PutEmpty: dimension error");
474 void ScMatrixImpl::PutEmptyPath(SCSIZE nC, SCSIZE nR)
476 if (ValidColRow( nC, nR))
478 maMat.set_empty(nR, nC);
479 maMatFlag.set(nR, nC, SC_MATFLAG_EMPTYPATH);
481 else
483 OSL_FAIL("ScMatrixImpl::PutEmptyPath: dimension error");
487 void ScMatrixImpl::PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR )
489 maMat.set(nR, nC, CreateDoubleError(nErrorCode));
492 void ScMatrixImpl::PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
494 if (ValidColRow( nC, nR))
495 maMat.set(nR, nC, bVal);
496 else
498 OSL_FAIL("ScMatrixImpl::PutBoolean: dimension error");
502 sal_uInt16 ScMatrixImpl::GetError( SCSIZE nC, SCSIZE nR) const
504 if (ValidColRowOrReplicated( nC, nR ))
506 double fVal = maMat.get_numeric(nR, nC);
507 return GetDoubleErrorValue(fVal);
509 else
511 OSL_FAIL("ScMatrixImpl::GetError: dimension error");
512 return errNoValue;
516 double ScMatrixImpl::GetDouble(SCSIZE nC, SCSIZE nR) const
518 if (ValidColRowOrReplicated( nC, nR ))
520 double fVal = maMat.get_numeric(nR, nC);
521 if ( pErrorInterpreter )
523 sal_uInt16 nError = GetDoubleErrorValue(fVal);
524 if ( nError )
525 SetErrorAtInterpreter( nError);
527 return fVal;
529 else
531 OSL_FAIL("ScMatrixImpl::GetDouble: dimension error");
532 return CreateDoubleError( errNoValue);
536 double ScMatrixImpl::GetDouble( SCSIZE nIndex) const
538 SCSIZE nC, nR;
539 CalcPosition(nIndex, nC, nR);
540 return GetDouble(nC, nR);
543 svl::SharedString ScMatrixImpl::GetString(SCSIZE nC, SCSIZE nR) const
545 if (ValidColRowOrReplicated( nC, nR ))
547 double fErr = 0.0;
548 MatrixImplType::const_position_type aPos = maMat.position(nR, nC);
549 switch (maMat.get_type(aPos))
551 case mdds::mtm::element_string:
552 return maMat.get_string(aPos);
553 case mdds::mtm::element_empty:
554 return svl::SharedString::getEmptyString();
555 case mdds::mtm::element_numeric:
556 case mdds::mtm::element_boolean:
557 fErr = maMat.get_numeric(aPos);
558 //fallthrough
559 default:
560 OSL_FAIL("ScMatrixImpl::GetString: access error, no string");
562 SetErrorAtInterpreter(GetDoubleErrorValue(fErr));
564 else
566 OSL_FAIL("ScMatrixImpl::GetString: dimension error");
568 return svl::SharedString::getEmptyString();
571 svl::SharedString ScMatrixImpl::GetString( SCSIZE nIndex) const
573 SCSIZE nC, nR;
574 CalcPosition(nIndex, nC, nR);
575 return GetString(nC, nR);
578 svl::SharedString ScMatrixImpl::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
580 if (!ValidColRowOrReplicated( nC, nR ))
582 OSL_FAIL("ScMatrixImpl::GetString: dimension error");
583 return OUString();
586 double fVal = 0.0;
587 MatrixImplType::const_position_type aPos = maMat.position(nR, nC);
588 switch (maMat.get_type(aPos))
590 case mdds::mtm::element_string:
591 return maMat.get_string(aPos).getString();
592 case mdds::mtm::element_empty:
594 if (maMatFlag.get<TMatFlag>(nR, nC) != SC_MATFLAG_EMPTYPATH)
595 // not an empty path.
596 return svl::SharedString::getEmptyString();
598 // result of empty FALSE jump path
599 sal_uLong nKey = rFormatter.GetStandardFormat( css::util::NumberFormat::LOGICAL,
600 ScGlobal::eLnge);
601 OUString aStr;
602 Color* pColor = NULL;
603 rFormatter.GetOutputString( 0.0, nKey, aStr, &pColor);
604 return aStr;
606 case mdds::mtm::element_numeric:
607 case mdds::mtm::element_boolean:
608 fVal = maMat.get_numeric(aPos);
609 break;
610 default:
614 sal_uInt16 nError = GetDoubleErrorValue(fVal);
615 if (nError)
617 SetErrorAtInterpreter( nError);
618 return ScGlobal::GetErrorString( nError);
621 sal_uLong nKey = rFormatter.GetStandardFormat( css::util::NumberFormat::NUMBER,
622 ScGlobal::eLnge);
623 OUString aStr;
624 rFormatter.GetInputLineString( fVal, nKey, aStr);
625 return aStr;
628 ScMatrixValue ScMatrixImpl::Get(SCSIZE nC, SCSIZE nR) const
630 ScMatrixValue aVal;
631 if (ValidColRowOrReplicated(nC, nR))
633 MatrixImplType::const_position_type aPos = maMat.position(nR, nC);
634 mdds::mtm::element_t eType = maMat.get_type(aPos);
635 switch (eType)
637 case mdds::mtm::element_boolean:
638 aVal.nType = SC_MATVAL_BOOLEAN;
639 aVal.fVal = double(maMat.get_boolean(aPos));
640 break;
641 case mdds::mtm::element_numeric:
642 aVal.nType = SC_MATVAL_VALUE;
643 aVal.fVal = maMat.get_numeric(aPos);
644 break;
645 case mdds::mtm::element_string:
646 aVal.nType = SC_MATVAL_STRING;
647 aVal.aStr = maMat.get_string(aPos);
648 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 aVal.nType = maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYPATH ? SC_MATVAL_EMPTYPATH :
653 SC_MATVAL_EMPTY;
654 aVal.fVal = 0.0;
655 default:
659 else
661 OSL_FAIL("ScMatrixImpl::Get: dimension error");
663 return aVal;
666 bool ScMatrixImpl::IsString( SCSIZE nIndex ) const
668 SCSIZE nC, nR;
669 CalcPosition(nIndex, nC, nR);
670 return IsString(nC, nR);
673 bool ScMatrixImpl::IsString( SCSIZE nC, SCSIZE nR ) const
675 ValidColRowReplicated( nC, nR );
676 switch (maMat.get_type(nR, nC))
678 case mdds::mtm::element_empty:
679 case mdds::mtm::element_string:
680 return true;
681 default:
684 return false;
687 bool ScMatrixImpl::IsEmpty( SCSIZE nC, SCSIZE nR ) const
689 // Flag must indicate an 'empty' or 'empty cell' or 'empty result' element,
690 // but not an 'empty path' element.
691 ValidColRowReplicated( nC, nR );
692 return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
693 maMatFlag.get<TMatFlag>(nR, nC) != SC_MATFLAG_EMPTYPATH;
696 bool ScMatrixImpl::IsEmptyCell( SCSIZE nC, SCSIZE nR ) const
698 // Flag must indicate an 'empty cell' element instead of an
699 // 'empty' or 'empty result' or 'empty path' element.
700 ValidColRowReplicated( nC, nR );
701 return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
702 maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYCELL;
705 bool ScMatrixImpl::IsEmptyResult( SCSIZE nC, SCSIZE nR ) const
707 // Flag must indicate an 'empty result' element instead of an
708 // 'empty' or 'empty cell' or 'empty path' element.
709 ValidColRowReplicated( nC, nR );
710 return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
711 maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYRESULT;
714 bool ScMatrixImpl::IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
716 // Flag must indicate an 'empty path' element.
717 if (ValidColRowOrReplicated( nC, nR ))
718 return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
719 maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYPATH;
720 else
721 return true;
724 bool ScMatrixImpl::IsValue( SCSIZE nIndex ) const
726 SCSIZE nC, nR;
727 CalcPosition(nIndex, nC, nR);
728 return IsValue(nC, nR);
731 bool ScMatrixImpl::IsValue( SCSIZE nC, SCSIZE nR ) const
733 ValidColRowReplicated(nC, nR);
734 switch (maMat.get_type(nR, nC))
736 case mdds::mtm::element_boolean:
737 case mdds::mtm::element_numeric:
738 return true;
739 default:
742 return false;
745 bool ScMatrixImpl::IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
747 ValidColRowReplicated(nC, nR);
748 switch (maMat.get_type(nR, nC))
750 case mdds::mtm::element_boolean:
751 case mdds::mtm::element_numeric:
752 case mdds::mtm::element_empty:
753 return true;
754 default:
757 return false;
760 bool ScMatrixImpl::IsBoolean( SCSIZE nC, SCSIZE nR ) const
762 ValidColRowReplicated( nC, nR );
763 return maMat.get_type(nR, nC) == mdds::mtm::element_boolean;
766 bool ScMatrixImpl::IsNumeric() const
768 return maMat.numeric();
771 void ScMatrixImpl::MatCopy(ScMatrixImpl& mRes) const
773 if (maMat.size().row > mRes.maMat.size().row || maMat.size().column > mRes.maMat.size().column)
775 // destination matrix is not large enough.
776 OSL_FAIL("ScMatrixImpl::MatCopy: dimension error");
777 return;
780 mRes.maMat.copy(maMat);
783 void ScMatrixImpl::MatTrans(ScMatrixImpl& mRes) const
785 mRes.maMat = maMat;
786 mRes.maMat.transpose();
789 void ScMatrixImpl::FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 )
791 if (ValidColRow( nC1, nR1) && ValidColRow( nC2, nR2))
793 for (SCSIZE j = nC1; j <= nC2; ++j)
795 // Passing value array is much faster.
796 std::vector<double> aVals(nR2-nR1+1, fVal);
797 maMat.set(nR1, j, aVals.begin(), aVals.end());
800 else
802 OSL_FAIL("ScMatrixImpl::FillDouble: dimension error");
806 void ScMatrixImpl::PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR )
808 if (!rVec.empty() && ValidColRow( nC, nR) && ValidColRow( nC, nR + rVec.size() - 1))
810 maMat.set(nR, nC, rVec.begin(), rVec.end());
812 else
814 OSL_FAIL("ScMatrixImpl::PutDoubleVector: dimension error");
818 void ScMatrixImpl::PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR )
820 if (!rVec.empty() && ValidColRow( nC, nR) && ValidColRow( nC, nR + rVec.size() - 1))
822 maMat.set(nR, nC, rVec.begin(), rVec.end());
824 else
826 OSL_FAIL("ScMatrixImpl::PutStringVector: dimension error");
830 void ScMatrixImpl::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
832 if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1))
834 maMat.set_empty(nR, nC, nCount);
835 // Flag to indicate that this is 'empty', not 'empty result' or 'empty path'.
836 std::vector<TMatFlag> aVals(nCount, SC_MATFLAG_EMPTYCELL);
837 maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
839 else
841 OSL_FAIL("ScMatrixImpl::PutEmptyVector: dimension error");
845 void ScMatrixImpl::PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
847 if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1))
849 maMat.set_empty(nR, nC, nCount);
850 // Flag to indicate that this is 'empty result', not 'empty' or 'empty path'.
851 std::vector<TMatFlag> aVals(nCount, SC_MATFLAG_EMPTYRESULT);
852 maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
854 else
856 OSL_FAIL("ScMatrixImpl::PutEmptyResultVector: dimension error");
860 void ScMatrixImpl::PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
862 if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1))
864 maMat.set_empty(nR, nC, nCount);
865 // Flag to indicate 'empty path'.
866 std::vector<TMatFlag> aVals(nCount, SC_MATFLAG_EMPTYPATH);
867 maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
869 else
871 OSL_FAIL("ScMatrixImpl::PutEmptyPathVector: dimension error");
875 void ScMatrixImpl::CompareEqual()
877 MatrixImplType::size_pair_type aSize = maMat.size();
878 CompareMatrixElemFunc<ElemEqualZero> aFunc(aSize.row, aSize.column);
879 maMat.walk(aFunc);
880 aFunc.swap(maMat);
883 void ScMatrixImpl::CompareNotEqual()
885 MatrixImplType::size_pair_type aSize = maMat.size();
886 CompareMatrixElemFunc<ElemNotEqualZero> aFunc(aSize.row, aSize.column);
887 maMat.walk(aFunc);
888 aFunc.swap(maMat);
891 void ScMatrixImpl::CompareLess()
893 MatrixImplType::size_pair_type aSize = maMat.size();
894 CompareMatrixElemFunc<ElemLessZero> aFunc(aSize.row, aSize.column);
895 maMat.walk(aFunc);
896 aFunc.swap(maMat);
899 void ScMatrixImpl::CompareGreater()
901 MatrixImplType::size_pair_type aSize = maMat.size();
902 CompareMatrixElemFunc<ElemGreaterZero> aFunc(aSize.row, aSize.column);
903 maMat.walk(aFunc);
904 aFunc.swap(maMat);
907 void ScMatrixImpl::CompareLessEqual()
909 MatrixImplType::size_pair_type aSize = maMat.size();
910 CompareMatrixElemFunc<ElemLessEqualZero> aFunc(aSize.row, aSize.column);
911 maMat.walk(aFunc);
912 aFunc.swap(maMat);
915 void ScMatrixImpl::CompareGreaterEqual()
917 MatrixImplType::size_pair_type aSize = maMat.size();
918 CompareMatrixElemFunc<ElemGreaterEqualZero> aFunc(aSize.row, aSize.column);
919 maMat.walk(aFunc);
920 aFunc.swap(maMat);
923 namespace {
925 struct AndEvaluator
927 bool mbResult;
928 void operate(double fVal) { mbResult &= (fVal != 0.0); }
929 bool result() const { return mbResult; }
930 AndEvaluator() : mbResult(true) {}
933 struct OrEvaluator
935 bool mbResult;
936 void operate(double fVal) { mbResult |= (fVal != 0.0); }
937 bool result() const { return mbResult; }
938 OrEvaluator() : mbResult(false) {}
941 struct XorEvaluator
943 bool mbResult;
944 void operate(double fVal) { mbResult ^= (fVal != 0.0); }
945 bool result() const { return mbResult; }
946 XorEvaluator() : mbResult(false) {}
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 double EvalMatrix(const MatrixImplType& rMat)
954 _Evaluator aEval;
955 size_t nRows = rMat.size().row, nCols = rMat.size().column;
956 for (size_t i = 0; i < nRows; ++i)
958 for (size_t j = 0; j < nCols; ++j)
960 MatrixImplType::const_position_type aPos = rMat.position(i, j);
961 mdds::mtm::element_t eType = rMat.get_type(aPos);
962 if (eType != mdds::mtm::element_numeric && eType != mdds::mtm::element_boolean)
963 // assuming a CompareMat this is an error
964 return CreateDoubleError(errIllegalArgument);
966 double fVal = rMat.get_numeric(aPos);
967 if (!::rtl::math::isFinite(fVal))
968 // DoubleError
969 return fVal;
971 aEval.operate(fVal);
974 return aEval.result();
979 double ScMatrixImpl::And() const
981 // All elements must be of value type.
982 // True only if all the elements have non-zero values.
983 return EvalMatrix<AndEvaluator>(maMat);
986 double ScMatrixImpl::Or() const
988 // All elements must be of value type.
989 // True if at least one element has a non-zero value.
990 return EvalMatrix<OrEvaluator>(maMat);
993 double ScMatrixImpl::Xor() const
995 // All elements must be of value type.
996 // True if an odd number of elements have a non-zero value.
997 return EvalMatrix<XorEvaluator>(maMat);
1000 namespace {
1002 struct SumOp
1004 static const double InitVal;
1006 void operator() (double& rAccum, double fVal)
1008 rAccum += fVal;
1012 const double SumOp::InitVal = 0.0;
1014 struct SumSquareOp
1016 static const double InitVal;
1018 void operator() (double& rAccum, double fVal)
1020 rAccum += fVal*fVal;
1024 const double SumSquareOp::InitVal = 0.0;
1026 struct ProductOp
1028 static const double InitVal;
1030 void operator() (double& rAccum, double fVal)
1032 rAccum *= fVal;
1036 const double ProductOp::InitVal = 1.0;
1038 template<typename _Op>
1039 class WalkElementBlocks : std::unary_function<MatrixImplType::element_block_node_type, void>
1041 _Op maOp;
1043 ScMatrix::IterateResult maRes;
1044 bool mbFirst:1;
1045 bool mbTextAsZero:1;
1046 public:
1047 WalkElementBlocks(bool bTextAsZero) : maRes(_Op::InitVal, _Op::InitVal, 0), mbFirst(true), mbTextAsZero(bTextAsZero) {}
1049 const ScMatrix::IterateResult& getResult() const { return maRes; }
1051 void operator() (const MatrixImplType::element_block_node_type& node)
1053 switch (node.type)
1055 case mdds::mtm::element_numeric:
1057 typedef MatrixImplType::numeric_block_type block_type;
1059 block_type::const_iterator it = block_type::begin(*node.data);
1060 block_type::const_iterator itEnd = block_type::end(*node.data);
1061 for (; it != itEnd; ++it)
1063 if (mbFirst)
1065 maOp(maRes.mfFirst, *it);
1066 mbFirst = false;
1068 else
1069 maOp(maRes.mfRest, *it);
1071 maRes.mnCount += node.size;
1073 break;
1074 case mdds::mtm::element_boolean:
1076 typedef MatrixImplType::boolean_block_type block_type;
1078 block_type::const_iterator it = block_type::begin(*node.data);
1079 block_type::const_iterator itEnd = block_type::end(*node.data);
1080 for (; it != itEnd; ++it)
1082 if (mbFirst)
1084 maOp(maRes.mfFirst, *it);
1085 mbFirst = false;
1087 else
1088 maOp(maRes.mfRest, *it);
1090 maRes.mnCount += node.size;
1092 break;
1093 case mdds::mtm::element_string:
1094 if (mbTextAsZero)
1095 maRes.mnCount += node.size;
1096 break;
1097 case mdds::mtm::element_empty:
1098 default:
1104 class CountElements : std::unary_function<MatrixImplType::element_block_node_type, void>
1106 size_t mnCount;
1107 bool mbCountString;
1108 public:
1109 CountElements(bool bCountString) : mnCount(0), mbCountString(bCountString) {}
1111 size_t getCount() const { return mnCount; }
1113 void operator() (const MatrixImplType::element_block_node_type& node)
1115 switch (node.type)
1117 case mdds::mtm::element_numeric:
1118 case mdds::mtm::element_boolean:
1119 mnCount += node.size;
1120 break;
1121 case mdds::mtm::element_string:
1122 if (mbCountString)
1123 mnCount += node.size;
1124 break;
1125 case mdds::mtm::element_empty:
1126 default:
1132 const size_t ResultNotSet = std::numeric_limits<size_t>::max();
1134 template<typename _Type>
1135 class WalkAndMatchElements : std::unary_function<MatrixImplType::element_block_node_type, void>
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;
1144 public:
1145 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 mnIndex(0) {}
1153 size_t getMatching() const { return mnResult; }
1155 size_t compare(const MatrixImplType::element_block_node_type& node) const;
1157 void operator() (const MatrixImplType::element_block_node_type& node)
1159 // early exit if match already found
1160 if (mnResult != ResultNotSet)
1161 return;
1163 // limit lookup to the requested columns
1164 if ((mnCol1 * maSize.row) <= mnIndex && mnIndex < ((mnCol2 + 1) * maSize.row))
1166 mnResult = compare(node);
1169 mnIndex += node.size;
1173 template<>
1174 size_t WalkAndMatchElements<double>::compare(const MatrixImplType::element_block_node_type& node) const
1176 size_t nCount = 0;
1177 switch (node.type)
1179 case mdds::mtm::element_numeric:
1181 typedef MatrixImplType::numeric_block_type block_type;
1183 block_type::const_iterator it = block_type::begin(*node.data);
1184 block_type::const_iterator itEnd = block_type::end(*node.data);
1185 for (; it != itEnd; ++it, nCount++)
1187 if (*it == maMatchValue)
1189 return mnIndex + nCount;
1192 break;
1194 case mdds::mtm::element_boolean:
1196 typedef MatrixImplType::boolean_block_type block_type;
1198 block_type::const_iterator it = block_type::begin(*node.data);
1199 block_type::const_iterator itEnd = block_type::end(*node.data);
1200 for (; it != itEnd; ++it, ++nCount)
1202 if (int(*it) == maMatchValue)
1204 return mnIndex + nCount;
1207 break;
1209 break;
1210 case mdds::mtm::element_string:
1211 case mdds::mtm::element_empty:
1212 default:
1215 return ResultNotSet;
1218 template<>
1219 size_t WalkAndMatchElements<svl::SharedString>::compare(const MatrixImplType::element_block_node_type& node) const
1221 switch (node.type)
1223 case mdds::mtm::element_string:
1225 size_t nCount = 0;
1226 typedef MatrixImplType::string_block_type block_type;
1228 block_type::const_iterator it = block_type::begin(*node.data);
1229 block_type::const_iterator itEnd = block_type::end(*node.data);
1230 for (; it != itEnd; ++it, ++nCount)
1232 if (it->getDataIgnoreCase() == maMatchValue.getDataIgnoreCase())
1234 return mnIndex + nCount;
1237 break;
1239 case mdds::mtm::element_boolean:
1240 case mdds::mtm::element_numeric:
1241 case mdds::mtm::element_empty:
1242 default:
1245 return ResultNotSet;
1248 struct MaxOp
1250 static double init() { return -std::numeric_limits<double>::max(); }
1251 static double compare(double left, double right)
1253 return std::max(left, right);
1256 static double boolValue(
1257 MatrixImplType::boolean_block_type::const_iterator it,
1258 MatrixImplType::boolean_block_type::const_iterator itEnd)
1260 // If the array has at least one true value, the maximum value is 1.
1261 it = std::find(it, itEnd, true);
1262 return it == itEnd ? 0.0 : 1.0;
1266 struct MinOp
1268 static double init() { return std::numeric_limits<double>::max(); }
1269 static double compare(double left, double right)
1271 return std::min(left, right);
1274 static double boolValue(
1275 MatrixImplType::boolean_block_type::const_iterator it,
1276 MatrixImplType::boolean_block_type::const_iterator itEnd)
1278 // If the array has at least one false value, the minimum value is 0.
1279 it = std::find(it, itEnd, false);
1280 return it == itEnd ? 1.0 : 0.0;
1284 template<typename _Op>
1285 class CalcMaxMinValue : std::unary_function<MatrixImplType::element_block_type, void>
1287 double mfVal;
1288 bool mbTextAsZero;
1289 bool mbHasValue;
1290 public:
1291 CalcMaxMinValue( bool bTextAsZero ) :
1292 mfVal(_Op::init()),
1293 mbTextAsZero(bTextAsZero),
1294 mbHasValue(false) {}
1296 double getValue() const { return mbHasValue ? mfVal : 0.0; }
1298 void operator() (const MatrixImplType::element_block_node_type& node)
1301 switch (node.type)
1303 case mdds::mtm::element_numeric:
1305 typedef MatrixImplType::numeric_block_type block_type;
1307 block_type::const_iterator it = block_type::begin(*node.data);
1308 block_type::const_iterator itEnd = block_type::end(*node.data);
1309 for (; it != itEnd; ++it)
1310 mfVal = _Op::compare(mfVal, *it);
1312 mbHasValue = true;
1314 break;
1315 case mdds::mtm::element_boolean:
1317 typedef MatrixImplType::boolean_block_type block_type;
1319 block_type::const_iterator it = block_type::begin(*node.data);
1320 block_type::const_iterator itEnd = block_type::end(*node.data);
1321 double fVal = _Op::boolValue(it, itEnd);
1322 mfVal = _Op::compare(mfVal, fVal);
1323 mbHasValue = true;
1325 break;
1326 case mdds::mtm::element_string:
1327 case mdds::mtm::element_empty:
1329 // empty elements are treated as empty strings.
1330 if (mbTextAsZero)
1332 mfVal = _Op::compare(mfVal, 0.0);
1333 mbHasValue = true;
1336 break;
1337 default:
1343 inline double evaluate( double fVal, ScQueryOp eOp )
1345 if (!rtl::math::isFinite(fVal))
1346 return fVal;
1348 switch (eOp)
1350 case SC_EQUAL:
1351 return fVal == 0.0 ? 1.0 : 0.0;
1352 case SC_LESS:
1353 return fVal < 0.0 ? 1.0 : 0.0;
1354 case SC_GREATER:
1355 return fVal > 0.0 ? 1.0 : 0.0;
1356 break;
1357 case SC_LESS_EQUAL:
1358 return fVal <= 0.0 ? 1.0 : 0.0;
1359 break;
1360 case SC_GREATER_EQUAL:
1361 return fVal >= 0.0 ? 1.0 : 0.0;
1362 break;
1363 case SC_NOT_EQUAL:
1364 return fVal != 0.0 ? 1.0 : 0.0;
1365 break;
1366 default:
1370 OSL_TRACE( "evaluate: unhandled comparison operator: %d", (int)eOp);
1371 return CreateDoubleError( errUnknownState);
1374 class CompareMatrixFunc : std::unary_function<MatrixImplType::element_block_type, void>
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
1381 void compare()
1383 double fVal = sc::CompareFunc( mrComp, mpOptions);
1384 maResValues.push_back(evaluate(fVal, mrComp.meOp));
1387 public:
1388 CompareMatrixFunc( size_t nResSize, sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) :
1389 mrComp(rComp), mnMatPos(nMatPos), mpOptions(pOptions)
1391 maResValues.reserve(nResSize);
1394 void operator() (const MatrixImplType::element_block_node_type& node)
1396 sc::Compare::Cell& rCell = mrComp.maCells[mnMatPos];
1398 switch (node.type)
1400 case mdds::mtm::element_numeric:
1402 typedef MatrixImplType::numeric_block_type block_type;
1404 block_type::const_iterator it = block_type::begin(*node.data);
1405 block_type::const_iterator itEnd = block_type::end(*node.data);
1406 for (; it != itEnd; ++it)
1408 rCell.mbValue = true;
1409 rCell.mbEmpty = false;
1410 rCell.mfValue = *it;
1411 compare();
1414 break;
1415 case mdds::mtm::element_boolean:
1417 typedef MatrixImplType::boolean_block_type block_type;
1419 block_type::const_iterator it = block_type::begin(*node.data);
1420 block_type::const_iterator itEnd = block_type::end(*node.data);
1421 for (; it != itEnd; ++it)
1423 rCell.mbValue = true;
1424 rCell.mbEmpty = false;
1425 rCell.mfValue = double(*it);
1426 compare();
1429 break;
1430 case mdds::mtm::element_string:
1432 typedef MatrixImplType::string_block_type block_type;
1434 block_type::const_iterator it = block_type::begin(*node.data);
1435 block_type::const_iterator itEnd = block_type::end(*node.data);
1436 for (; it != itEnd; ++it)
1438 const svl::SharedString& rStr = *it;
1439 rCell.mbValue = false;
1440 rCell.mbEmpty = false;
1441 rCell.maStr = rStr;
1442 compare();
1445 break;
1446 case mdds::mtm::element_empty:
1448 rCell.mbValue = false;
1449 rCell.mbEmpty = true;
1450 rCell.maStr = svl::SharedString::getEmptyString();
1451 for (size_t i = 0; i < node.size; ++i)
1452 compare();
1454 default:
1459 const std::vector<double>& getValues() const
1461 return maResValues;
1466 * Left-hand side is a matrix while the right-hand side is a numeric value.
1468 class CompareMatrixToNumericFunc : std::unary_function<MatrixImplType::element_block_type, void>
1470 sc::Compare& mrComp;
1471 double mfRightValue;
1472 sc::CompareOptions* mpOptions;
1473 std::vector<double> maResValues; // double instead of bool to transport error values
1475 void compare()
1477 double fVal = sc::CompareFunc(mrComp.maCells[0], mfRightValue, mpOptions);
1478 maResValues.push_back(evaluate(fVal, mrComp.meOp));
1481 void compareLeftNumeric( double fLeftVal )
1483 double fVal = sc::CompareFunc(fLeftVal, mfRightValue);
1484 maResValues.push_back(evaluate(fVal, mrComp.meOp));
1487 void compareLeftEmpty( size_t nSize )
1489 double fVal = sc::CompareEmptyToNumericFunc(mfRightValue);
1490 bool bRes = evaluate(fVal, mrComp.meOp);
1491 maResValues.resize(maResValues.size() + nSize, bRes ? 1.0 : 0.0);
1494 public:
1495 CompareMatrixToNumericFunc( size_t nResSize, sc::Compare& rComp, double fRightValue, sc::CompareOptions* pOptions ) :
1496 mrComp(rComp), mfRightValue(fRightValue), mpOptions(pOptions)
1498 maResValues.reserve(nResSize);
1501 void operator() (const MatrixImplType::element_block_node_type& node)
1503 sc::Compare::Cell& rCell = mrComp.maCells[0];
1505 switch (node.type)
1507 case mdds::mtm::element_numeric:
1509 typedef MatrixImplType::numeric_block_type block_type;
1511 block_type::const_iterator it = block_type::begin(*node.data);
1512 block_type::const_iterator itEnd = block_type::end(*node.data);
1513 for (; it != itEnd; ++it)
1514 compareLeftNumeric(*it);
1516 break;
1517 case mdds::mtm::element_boolean:
1519 typedef MatrixImplType::boolean_block_type block_type;
1521 block_type::const_iterator it = block_type::begin(*node.data);
1522 block_type::const_iterator itEnd = block_type::end(*node.data);
1523 for (; it != itEnd; ++it)
1524 compareLeftNumeric(double(*it));
1526 break;
1527 case mdds::mtm::element_string:
1529 typedef MatrixImplType::string_block_type block_type;
1531 block_type::const_iterator it = block_type::begin(*node.data);
1532 block_type::const_iterator itEnd = block_type::end(*node.data);
1533 for (; it != itEnd; ++it)
1535 const svl::SharedString& rStr = *it;
1536 rCell.mbValue = false;
1537 rCell.mbEmpty = false;
1538 rCell.maStr = rStr;
1539 compare();
1542 break;
1543 case mdds::mtm::element_empty:
1544 compareLeftEmpty(node.size);
1545 break;
1546 default:
1551 const std::vector<double>& getValues() const
1553 return maResValues;
1557 class ToDoubleArray : std::unary_function<MatrixImplType::element_block_type, void>
1559 std::vector<double> maArray;
1560 std::vector<double>::iterator miPos;
1561 double mfNaN;
1562 bool mbEmptyAsZero;
1564 public:
1565 ToDoubleArray( size_t nSize, bool bEmptyAsZero ) :
1566 maArray(nSize, 0.0), miPos(maArray.begin()), mbEmptyAsZero(bEmptyAsZero)
1568 mfNaN = CreateDoubleError( errElementNaN);
1571 void operator() (const MatrixImplType::element_block_node_type& node)
1573 using namespace mdds::mtv;
1575 switch (node.type)
1577 case mdds::mtm::element_numeric:
1579 numeric_element_block::const_iterator it = numeric_element_block::begin(*node.data);
1580 numeric_element_block::const_iterator itEnd = numeric_element_block::end(*node.data);
1581 for (; it != itEnd; ++it, ++miPos)
1582 *miPos = *it;
1584 break;
1585 case mdds::mtm::element_boolean:
1587 boolean_element_block::const_iterator it = boolean_element_block::begin(*node.data);
1588 boolean_element_block::const_iterator itEnd = boolean_element_block::end(*node.data);
1589 for (; it != itEnd; ++it, ++miPos)
1590 *miPos = *it ? 1.0 : 0.0;
1592 break;
1593 case mdds::mtm::element_string:
1595 for (size_t i = 0; i < node.size; ++i, ++miPos)
1596 *miPos = mfNaN;
1598 break;
1599 case mdds::mtm::element_empty:
1601 if (mbEmptyAsZero)
1603 std::advance(miPos, node.size);
1604 return;
1607 for (size_t i = 0; i < node.size; ++i, ++miPos)
1608 *miPos = mfNaN;
1610 break;
1611 default:
1616 void swap(std::vector<double>& rOther)
1618 maArray.swap(rOther);
1622 struct ArrayMul : public std::binary_function<double, double, double>
1624 double operator() (const double& lhs, const double& rhs) const
1626 return lhs * rhs;
1630 template<typename _Op>
1631 class MergeDoubleArrayFunc : std::unary_function<MatrixImplType::element_block_type, void>
1633 std::vector<double>& mrArray;
1634 std::vector<double>::iterator miPos;
1635 double mfNaN;
1636 public:
1637 MergeDoubleArrayFunc(std::vector<double>& rArray) : mrArray(rArray), miPos(mrArray.begin())
1639 mfNaN = CreateDoubleError( errElementNaN);
1642 void operator() (const MatrixImplType::element_block_node_type& node)
1644 using namespace mdds::mtv;
1645 static _Op op;
1647 switch (node.type)
1649 case mdds::mtm::element_numeric:
1651 numeric_element_block::const_iterator it = numeric_element_block::begin(*node.data);
1652 numeric_element_block::const_iterator itEnd = numeric_element_block::end(*node.data);
1653 for (; it != itEnd; ++it, ++miPos)
1655 if (GetDoubleErrorValue(*miPos) == errElementNaN)
1656 continue;
1658 *miPos = op(*miPos, *it);
1661 break;
1662 case mdds::mtm::element_boolean:
1664 boolean_element_block::const_iterator it = boolean_element_block::begin(*node.data);
1665 boolean_element_block::const_iterator itEnd = boolean_element_block::end(*node.data);
1666 for (; it != itEnd; ++it, ++miPos)
1668 if (GetDoubleErrorValue(*miPos) == errElementNaN)
1669 continue;
1671 *miPos = op(*miPos, *it ? 1.0 : 0.0);
1674 break;
1675 case mdds::mtm::element_string:
1677 for (size_t i = 0; i < node.size; ++i, ++miPos)
1678 *miPos = mfNaN;
1680 break;
1681 case mdds::mtm::element_empty:
1683 // Empty element is equivalent of having a numeric value of 0.0.
1684 for (size_t i = 0; i < node.size; ++i, ++miPos)
1686 if (GetDoubleErrorValue(*miPos) == errElementNaN)
1687 continue;
1689 *miPos = op(*miPos, 0.0);
1692 default:
1700 ScMatrix::IterateResult ScMatrixImpl::Sum(bool bTextAsZero) const
1702 WalkElementBlocks<SumOp> aFunc(bTextAsZero);
1703 maMat.walk(aFunc);
1704 return aFunc.getResult();
1707 ScMatrix::IterateResult ScMatrixImpl::SumSquare(bool bTextAsZero) const
1709 WalkElementBlocks<SumSquareOp> aFunc(bTextAsZero);
1710 maMat.walk(aFunc);
1711 return aFunc.getResult();
1714 ScMatrix::IterateResult ScMatrixImpl::Product(bool bTextAsZero) const
1716 WalkElementBlocks<ProductOp> aFunc(bTextAsZero);
1717 maMat.walk(aFunc);
1718 ScMatrix::IterateResult aRes = aFunc.getResult();
1719 return aRes;
1722 size_t ScMatrixImpl::Count(bool bCountStrings) const
1724 CountElements aFunc(bCountStrings);
1725 maMat.walk(aFunc);
1726 return aFunc.getCount();
1729 size_t ScMatrixImpl::MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const
1731 WalkAndMatchElements<double> aFunc(fValue, maMat.size(), nCol1, nCol2);
1732 maMat.walk(aFunc);
1733 return aFunc.getMatching();
1736 size_t ScMatrixImpl::MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const
1738 WalkAndMatchElements<svl::SharedString> aFunc(rStr, maMat.size(), nCol1, nCol2);
1739 maMat.walk(aFunc);
1740 return aFunc.getMatching();
1743 double ScMatrixImpl::GetMaxValue( bool bTextAsZero ) const
1745 CalcMaxMinValue<MaxOp> aFunc(bTextAsZero);
1746 maMat.walk(aFunc);
1747 return aFunc.getValue();
1750 double ScMatrixImpl::GetMinValue( bool bTextAsZero ) const
1752 CalcMaxMinValue<MinOp> aFunc(bTextAsZero);
1753 maMat.walk(aFunc);
1754 return aFunc.getValue();
1757 ScMatrixRef ScMatrixImpl::CompareMatrix(
1758 sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const
1760 MatrixImplType::size_pair_type aSize = maMat.size();
1761 size_t nSize = aSize.column * aSize.row;
1762 if (nMatPos == 0)
1764 if (rComp.maCells[1].mbValue && !rComp.maCells[1].mbEmpty)
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 CompareMatrixToNumericFunc aFunc(nSize, rComp, rComp.maCells[1].mfValue, pOptions);
1770 maMat.walk(aFunc);
1772 // We assume the result matrix has the same dimension as this matrix.
1773 const std::vector<double>& rResVal = aFunc.getValues();
1774 if (nSize != rResVal.size())
1775 ScMatrixRef();
1777 return ScMatrixRef(new ScMatrix(aSize.column, aSize.row, rResVal));
1781 CompareMatrixFunc aFunc(nSize, rComp, nMatPos, pOptions);
1782 maMat.walk(aFunc);
1784 // We assume the result matrix has the same dimension as this matrix.
1785 const std::vector<double>& rResVal = aFunc.getValues();
1786 if (nSize != rResVal.size())
1787 ScMatrixRef();
1789 return ScMatrixRef(new ScMatrix(aSize.column, aSize.row, rResVal));
1792 void ScMatrixImpl::GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const
1794 MatrixImplType::size_pair_type aSize = maMat.size();
1795 ToDoubleArray aFunc(aSize.row*aSize.column, bEmptyAsZero);
1796 maMat.walk(aFunc);
1797 aFunc.swap(rArray);
1800 void ScMatrixImpl::MergeDoubleArray( std::vector<double>& rArray, ScMatrix::Op eOp ) const
1802 MatrixImplType::size_pair_type aSize = maMat.size();
1803 size_t nSize = aSize.row*aSize.column;
1804 if (nSize != rArray.size())
1805 return;
1807 switch (eOp)
1809 case ScMatrix::Mul:
1811 MergeDoubleArrayFunc<ArrayMul> aFunc(rArray);
1812 maMat.walk(aFunc);
1814 break;
1815 default:
1820 void ScMatrixImpl::AddValues( const ScMatrixImpl& rMat )
1822 const MatrixImplType& rOther = rMat.maMat;
1823 MatrixImplType::size_pair_type aSize = maMat.size();
1824 if (aSize != rOther.size())
1825 // Geometry must match.
1826 return;
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.
1834 MatrixImplType::position_type aPos1 = maMat.position(0, 0);
1835 MatrixImplType::const_position_type aPos2 = rOther.position(0, 0);
1836 if (MatrixImplType::to_mtm_type(aPos1.first->type) != mdds::mtm::element_numeric)
1837 return;
1839 if (aPos1.first->size != aPos2.first->size)
1840 return;
1842 if (aPos1.first->size != aSize.row * aSize.column)
1843 return;
1845 MatrixImplType::numeric_block_type::iterator it =
1846 MatrixImplType::numeric_block_type::begin(*aPos1.first->data);
1847 MatrixImplType::numeric_block_type::iterator itEnd =
1848 MatrixImplType::numeric_block_type::end(*aPos1.first->data);
1850 switch (MatrixImplType::to_mtm_type(aPos2.first->type))
1852 case mdds::mtm::element_boolean:
1854 MatrixImplType::boolean_block_type::iterator it2 =
1855 MatrixImplType::boolean_block_type::begin(*aPos2.first->data);
1857 for (; it != itEnd; ++it, ++it2)
1858 *it += *it2;
1860 break;
1861 case mdds::mtm::element_numeric:
1863 MatrixImplType::numeric_block_type::iterator it2 =
1864 MatrixImplType::numeric_block_type::begin(*aPos2.first->data);
1866 for (; it != itEnd; ++it, ++it2)
1867 *it += *it2;
1869 break;
1870 default:
1875 namespace Op {
1877 template<typename T>
1878 struct return_type
1880 typedef T type;
1883 template<>
1884 struct return_type<bool>
1886 typedef double type;
1889 template<>
1890 struct return_type<char>
1892 typedef svl::SharedString type;
1897 template<typename T, typename U, typename return_type>
1898 struct wrapped_iterator
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;
1907 typename T::const_iterator it;
1908 mutable value_type val;
1909 U maOp;
1911 private:
1913 value_type calcVal() const
1915 return maOp(*it);
1918 public:
1920 wrapped_iterator(typename T::const_iterator it_, U aOp):
1921 it(it_),
1922 val(value_type()),
1923 maOp(aOp)
1927 wrapped_iterator(const wrapped_iterator& r):
1928 it(r.it),
1929 val(r.val),
1930 maOp(r.maOp)
1934 wrapped_iterator& operator=(const wrapped_iterator& r)
1936 it = r.it;
1937 return *this;
1940 bool operator==(const wrapped_iterator& r) const
1942 return it == r.it;
1945 bool operator!=(const wrapped_iterator& r) const
1947 return !operator==(r);
1950 wrapped_iterator& operator++()
1952 ++it;
1954 return *this;
1957 wrapped_iterator& operator--()
1959 --it;
1961 return *this;
1964 value_type& operator*() const
1966 val = calcVal();
1967 return val;
1970 pointer operator->() const
1972 val = calcVal();
1973 return &val;
1977 template<typename T, typename U, typename return_type>
1978 struct MatrixIteratorWrapper
1980 private:
1981 typename T::const_iterator m_itBegin;
1982 typename T::const_iterator m_itEnd;
1983 U maOp;
1984 public:
1985 MatrixIteratorWrapper(typename T::const_iterator itBegin, typename T::const_iterator itEnd, U aOp):
1986 m_itBegin(itBegin),
1987 m_itEnd(itEnd),
1988 maOp(aOp)
1992 wrapped_iterator<T, U, return_type> begin()
1994 return wrapped_iterator<T, U, return_type>(m_itBegin, maOp);
1997 wrapped_iterator<T, U, return_type> end()
1999 return wrapped_iterator<T, U, return_type>(m_itEnd, maOp);
2003 namespace {
2005 MatrixImplType::position_type increment_position(const MatrixImplType::position_type& pos, size_t n)
2007 MatrixImplType::position_type ret = pos;
2010 if (ret.second + n < ret.first->size)
2012 ret.second += n;
2013 break;
2015 else
2017 n -= (ret.first->size - ret.second);
2018 ++ret.first;
2019 ret.second = 0;
2022 while (n > 0);
2023 return ret;
2028 template<typename T>
2029 struct MatrixOpWrapper
2031 private:
2032 MatrixImplType& mrMat;
2033 MatrixImplType::position_type pos;
2034 T maOp;
2036 public:
2037 MatrixOpWrapper(MatrixImplType& rMat, T aOp):
2038 mrMat(rMat),
2039 pos(rMat.position(0,0)),
2040 maOp(aOp)
2044 void operator()(const MatrixImplType::element_block_node_type& node)
2046 switch (node.type)
2048 case mdds::mtm::element_numeric:
2050 typedef MatrixImplType::numeric_block_type block_type;
2052 block_type::const_iterator it = block_type::begin(*node.data);
2053 block_type::const_iterator itEnd = block_type::end(*node.data);
2054 MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, maOp);
2055 pos = mrMat.set(pos,aFunc.begin(), aFunc.end());
2057 break;
2058 case mdds::mtm::element_boolean:
2060 typedef MatrixImplType::boolean_block_type block_type;
2062 block_type::const_iterator it = block_type::begin(*node.data);
2063 block_type::const_iterator itEnd = block_type::end(*node.data);
2065 MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, maOp);
2066 pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
2068 break;
2069 case mdds::mtm::element_string:
2071 typedef MatrixImplType::string_block_type block_type;
2073 block_type::const_iterator it = block_type::begin(*node.data);
2074 block_type::const_iterator itEnd = block_type::end(*node.data);
2076 MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, maOp);
2077 pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
2079 break;
2080 case mdds::mtm::element_empty:
2082 if (maOp.useFunctionForEmpty())
2084 std::vector<char> aVec(node.size);
2085 MatrixIteratorWrapper<std::vector<char>, T, typename T::number_value_type>
2086 aFunc(aVec.begin(), aVec.end(), maOp);
2087 pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
2090 break;
2091 default:
2094 pos = increment_position(pos, node.size);
2098 template<typename T>
2099 void ScMatrixImpl::ApplyOperation(T aOp, ScMatrixImpl& rMat)
2101 MatrixOpWrapper<T> aFunc(rMat.maMat, aOp);
2102 maMat.walk(aFunc);
2105 #if DEBUG_MATRIX
2106 void ScMatrixImpl::Dump() const
2108 cout << "-- matrix content" << endl;
2109 SCSIZE nCols, nRows;
2110 GetDimensions(nCols, nRows);
2111 for (SCSIZE nRow = 0; nRow < nRows; ++nRow)
2113 for (SCSIZE nCol = 0; nCol < nCols; ++nCol)
2115 cout << " row=" << nRow << ", col=" << nCol << " : ";
2116 switch (maMat.get_type(nRow, nCol))
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:
2134 cout << endl;
2138 #endif
2140 void ScMatrixImpl::CalcPosition(SCSIZE nIndex, SCSIZE& rC, SCSIZE& rR) const
2142 SCSIZE nRowSize = maMat.size().row;
2143 SAL_WARN_IF( !nRowSize, "sc", "ScMatrixImpl::CalcPosition: 0 rows!");
2144 rC = nRowSize > 1 ? nIndex / nRowSize : nIndex;
2145 rR = nIndex - rC*nRowSize;
2148 void ScMatrix::IncRef() const
2150 ++nRefCnt;
2153 void ScMatrix::DecRef() const
2155 --nRefCnt;
2156 if (nRefCnt == 0)
2157 delete this;
2160 ScMatrix::ScMatrix( SCSIZE nC, SCSIZE nR) :
2161 pImpl(new ScMatrixImpl(nC, nR)), nRefCnt(0)
2163 SAL_WARN_IF( !nC, "sc", "ScMatrix with 0 columns!");
2164 SAL_WARN_IF( !nR, "sc", "ScMatrix with 0 rows!");
2167 ScMatrix::ScMatrix(SCSIZE nC, SCSIZE nR, double fInitVal) :
2168 pImpl(new ScMatrixImpl(nC, nR, fInitVal)), nRefCnt(0)
2170 SAL_WARN_IF( !nC, "sc", "ScMatrix with 0 columns!");
2171 SAL_WARN_IF( !nR, "sc", "ScMatrix with 0 rows!");
2174 ScMatrix::ScMatrix( size_t nC, size_t nR, const std::vector<double>& rInitVals ) :
2175 pImpl(new ScMatrixImpl(nC, nR, rInitVals)), nRefCnt(0)
2177 SAL_WARN_IF( !nC, "sc", "ScMatrix with 0 columns!");
2178 SAL_WARN_IF( !nR, "sc", "ScMatrix with 0 rows!");
2181 ScMatrix::~ScMatrix()
2183 delete pImpl;
2186 ScMatrix* ScMatrix::Clone() const
2188 SCSIZE nC, nR;
2189 pImpl->GetDimensions(nC, nR);
2190 ScMatrix* pScMat = new ScMatrix(nC, nR);
2191 MatCopy(*pScMat);
2192 pScMat->SetErrorInterpreter(pImpl->GetErrorInterpreter()); // TODO: really?
2193 return pScMat;
2196 ScMatrix* ScMatrix::CloneIfConst()
2198 return pImpl->IsImmutable() ? Clone() : this;
2201 void ScMatrix::SetImmutable( bool bVal )
2203 pImpl->SetImmutable(bVal);
2206 void ScMatrix::Resize( SCSIZE nC, SCSIZE nR)
2208 pImpl->Resize(nC, nR);
2211 void ScMatrix::Resize(SCSIZE nC, SCSIZE nR, double fVal)
2213 pImpl->Resize(nC, nR, fVal);
2216 ScMatrix* ScMatrix::CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const
2218 ScMatrix* pScMat = new ScMatrix(nNewCols, nNewRows);
2219 MatCopy(*pScMat);
2220 pScMat->SetErrorInterpreter(pImpl->GetErrorInterpreter());
2221 return pScMat;
2224 void ScMatrix::SetErrorInterpreter( ScInterpreter* p)
2226 pImpl->SetErrorInterpreter(p);
2229 void ScMatrix::GetDimensions( SCSIZE& rC, SCSIZE& rR) const
2231 pImpl->GetDimensions(rC, rR);
2234 SCSIZE ScMatrix::GetElementCount() const
2236 return pImpl->GetElementCount();
2239 bool ScMatrix::ValidColRow( SCSIZE nC, SCSIZE nR) const
2241 return pImpl->ValidColRow(nC, nR);
2244 bool ScMatrix::ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const
2246 return pImpl->ValidColRowReplicated(rC, rR);
2249 bool ScMatrix::ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const
2251 return ValidColRow( rC, rR) || ValidColRowReplicated( rC, rR);
2254 void ScMatrix::PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
2256 pImpl->PutDouble(fVal, nC, nR);
2259 void ScMatrix::PutDouble( double fVal, SCSIZE nIndex)
2261 pImpl->PutDouble(fVal, nIndex);
2264 void ScMatrix::PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
2266 pImpl->PutDouble(pArray, nLen, nC, nR);
2269 void ScMatrix::PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR)
2271 pImpl->PutString(rStr, nC, nR);
2274 void ScMatrix::PutString(const svl::SharedString& rStr, SCSIZE nIndex)
2276 pImpl->PutString(rStr, nIndex);
2279 void ScMatrix::PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
2281 pImpl->PutString(pArray, nLen, nC, nR);
2284 void ScMatrix::PutEmpty(SCSIZE nC, SCSIZE nR)
2286 pImpl->PutEmpty(nC, nR);
2289 void ScMatrix::PutEmptyPath(SCSIZE nC, SCSIZE nR)
2291 pImpl->PutEmptyPath(nC, nR);
2294 void ScMatrix::PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR )
2296 pImpl->PutError(nErrorCode, nC, nR);
2299 void ScMatrix::PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
2301 pImpl->PutBoolean(bVal, nC, nR);
2304 sal_uInt16 ScMatrix::GetError( SCSIZE nC, SCSIZE nR) const
2306 return pImpl->GetError(nC, nR);
2309 double ScMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const
2311 return pImpl->GetDouble(nC, nR);
2314 double ScMatrix::GetDouble( SCSIZE nIndex) const
2316 return pImpl->GetDouble(nIndex);
2319 svl::SharedString ScMatrix::GetString(SCSIZE nC, SCSIZE nR) const
2321 return pImpl->GetString(nC, nR);
2324 svl::SharedString ScMatrix::GetString( SCSIZE nIndex) const
2326 return pImpl->GetString(nIndex);
2329 svl::SharedString ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
2331 return pImpl->GetString(rFormatter, nC, nR);
2334 ScMatrixValue ScMatrix::Get(SCSIZE nC, SCSIZE nR) const
2336 return pImpl->Get(nC, nR);
2339 bool ScMatrix::IsString( SCSIZE nIndex ) const
2341 return pImpl->IsString(nIndex);
2344 bool ScMatrix::IsString( SCSIZE nC, SCSIZE nR ) const
2346 return pImpl->IsString(nC, nR);
2349 bool ScMatrix::IsEmpty( SCSIZE nC, SCSIZE nR ) const
2351 return pImpl->IsEmpty(nC, nR);
2354 bool ScMatrix::IsEmptyCell( SCSIZE nC, SCSIZE nR ) const
2356 return pImpl->IsEmptyCell(nC, nR);
2359 bool ScMatrix::IsEmptyResult( SCSIZE nC, SCSIZE nR ) const
2361 return pImpl->IsEmptyResult(nC, nR);
2364 bool ScMatrix::IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
2366 return pImpl->IsEmptyPath(nC, nR);
2369 bool ScMatrix::IsValue( SCSIZE nIndex ) const
2371 return pImpl->IsValue(nIndex);
2374 bool ScMatrix::IsValue( SCSIZE nC, SCSIZE nR ) const
2376 return pImpl->IsValue(nC, nR);
2379 bool ScMatrix::IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
2381 return pImpl->IsValueOrEmpty(nC, nR);
2384 bool ScMatrix::IsBoolean( SCSIZE nC, SCSIZE nR ) const
2386 return pImpl->IsBoolean(nC, nR);
2389 bool ScMatrix::IsNumeric() const
2391 return pImpl->IsNumeric();
2394 void ScMatrix::MatCopy(ScMatrix& mRes) const
2396 pImpl->MatCopy(*mRes.pImpl);
2399 void ScMatrix::MatTrans(ScMatrix& mRes) const
2401 pImpl->MatTrans(*mRes.pImpl);
2404 void ScMatrix::FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 )
2406 pImpl->FillDouble(fVal, nC1, nR1, nC2, nR2);
2409 void ScMatrix::PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR )
2411 pImpl->PutDoubleVector(rVec, nC, nR);
2414 void ScMatrix::PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR )
2416 pImpl->PutStringVector(rVec, nC, nR);
2419 void ScMatrix::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
2421 pImpl->PutEmptyVector(nCount, nC, nR);
2424 void ScMatrix::PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
2426 pImpl->PutEmptyResultVector(nCount, nC, nR);
2429 void ScMatrix::PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
2431 pImpl->PutEmptyPathVector(nCount, nC, nR);
2434 void ScMatrix::CompareEqual()
2436 pImpl->CompareEqual();
2439 void ScMatrix::CompareNotEqual()
2441 pImpl->CompareNotEqual();
2444 void ScMatrix::CompareLess()
2446 pImpl->CompareLess();
2449 void ScMatrix::CompareGreater()
2451 pImpl->CompareGreater();
2454 void ScMatrix::CompareLessEqual()
2456 pImpl->CompareLessEqual();
2459 void ScMatrix::CompareGreaterEqual()
2461 pImpl->CompareGreaterEqual();
2464 double ScMatrix::And() const
2466 return pImpl->And();
2469 double ScMatrix::Or() const
2471 return pImpl->Or();
2474 double ScMatrix::Xor() const
2476 return pImpl->Xor();
2479 ScMatrix::IterateResult ScMatrix::Sum(bool bTextAsZero) const
2481 return pImpl->Sum(bTextAsZero);
2484 ScMatrix::IterateResult ScMatrix::SumSquare(bool bTextAsZero) const
2486 return pImpl->SumSquare(bTextAsZero);
2489 ScMatrix::IterateResult ScMatrix::Product(bool bTextAsZero) const
2491 return pImpl->Product(bTextAsZero);
2494 size_t ScMatrix::Count(bool bCountStrings) const
2496 return pImpl->Count(bCountStrings);
2499 size_t ScMatrix::MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const
2501 return pImpl->MatchDoubleInColumns(fValue, nCol1, nCol2);
2504 size_t ScMatrix::MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const
2506 return pImpl->MatchStringInColumns(rStr, nCol1, nCol2);
2509 double ScMatrix::GetMaxValue( bool bTextAsZero ) const
2511 return pImpl->GetMaxValue(bTextAsZero);
2514 double ScMatrix::GetMinValue( bool bTextAsZero ) const
2516 return pImpl->GetMinValue(bTextAsZero);
2519 ScMatrixRef ScMatrix::CompareMatrix(
2520 sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const
2522 return pImpl->CompareMatrix(rComp, nMatPos, pOptions);
2525 void ScMatrix::GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const
2527 pImpl->GetDoubleArray(rArray, bEmptyAsZero);
2530 void ScMatrix::MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const
2532 pImpl->MergeDoubleArray(rArray, eOp);
2535 namespace matop {
2538 * COp struct is used in MatOp class to provide (through template specialization)
2539 * different actions for empty entries in a matrix.
2541 template <typename T, typename S>
2542 struct COp {};
2544 template <typename T>
2545 struct COp<T, svl::SharedString>
2547 svl::SharedString operator()(char, T /*aOp*/, double /*a*/, double /*b*/, const svl::SharedString& rString) const
2549 return rString;
2553 template <typename T>
2554 struct COp<T, double>
2556 double operator()(char, T aOp, double a, double b, const svl::SharedString& /*rString*/) const
2558 return aOp( a, b);
2562 /** A template for operations where operands are supposed to be numeric.
2563 A non-numeric (string) operand leads to the configured conversion to number
2564 method being called if in interpreter context and an errNoValue DoubleError
2565 if conversion was not possible, else to an unconditional errNoValue
2566 DoubleError.
2567 An empty operand evaluates to 0.
2568 XXX: semantically TEmptyRes and types other than number_value_type are
2569 unused, but this template could serve as a basis for future enhancements.
2571 template<typename TOp, typename TEmptyRes=double, typename TRet=double>
2572 struct MatOp
2574 private:
2575 TOp maOp;
2576 ScInterpreter* mpErrorInterpreter;
2577 svl::SharedString maString;
2578 double mfVal;
2579 COp<TOp, TEmptyRes> maCOp;
2581 public:
2582 typedef TEmptyRes empty_value_type;
2583 typedef TRet number_value_type;
2584 typedef svl::SharedString string_value_type;
2586 MatOp( TOp aOp, ScInterpreter* pErrorInterpreter,
2587 double fVal = 0.0, const svl::SharedString& rString = svl::SharedString() ):
2588 maOp(aOp),
2589 mpErrorInterpreter(pErrorInterpreter),
2590 maString(rString),
2591 mfVal(fVal)
2594 TRet operator()(double fVal) const
2596 return maOp(fVal, mfVal);
2599 TRet operator()(bool bVal) const
2601 return maOp((double)bVal, mfVal);
2604 double operator()(const svl::SharedString& rStr) const
2606 if (mpErrorInterpreter)
2608 sal_uInt16 nError = 0;
2609 short nCurFmtType = 0;
2610 double fValue = mpErrorInterpreter->ConvertStringToValue( rStr.getString(), nError, nCurFmtType);
2611 if (nError)
2612 return CreateDoubleError( nError);
2613 return fValue;
2615 return CreateDoubleError( errNoValue);
2618 TEmptyRes operator()(char) const
2620 return maCOp(char{}, maOp, 0, mfVal, maString);
2623 static bool useFunctionForEmpty()
2625 return true;
2631 void ScMatrix::NotOp( ScMatrix& rMat)
2633 auto not_ = [](double a, double){return double(a == 0.0);};
2634 matop::MatOp<decltype(not_), double> aOp(not_, pImpl->GetErrorInterpreter());
2635 pImpl->ApplyOperation(aOp, *rMat.pImpl);
2638 void ScMatrix::NegOp( ScMatrix& rMat)
2640 auto neg_ = [](double a, double){return -a;};
2641 matop::MatOp<decltype(neg_), double> aOp(neg_, pImpl->GetErrorInterpreter());
2642 pImpl->ApplyOperation(aOp, *rMat.pImpl);
2645 void ScMatrix::AddOp( double fVal, ScMatrix& rMat)
2647 auto add_ = [](double a, double b){return a + b;};
2648 matop::MatOp<decltype(add_)> aOp(add_, pImpl->GetErrorInterpreter(), fVal);
2649 pImpl->ApplyOperation(aOp, *rMat.pImpl);
2652 void ScMatrix::SubOp( bool bFlag, double fVal, ScMatrix& rMat)
2654 if (bFlag)
2656 auto sub_ = [](double a, double b){return b - a;};
2657 matop::MatOp<decltype(sub_)> aOp(sub_, pImpl->GetErrorInterpreter(), fVal);
2658 pImpl->ApplyOperation(aOp, *rMat.pImpl);
2660 else
2662 auto sub_ = [](double a, double b){return a - b;};
2663 matop::MatOp<decltype(sub_)> aOp(sub_, pImpl->GetErrorInterpreter(), fVal);
2664 pImpl->ApplyOperation(aOp, *rMat.pImpl);
2668 void ScMatrix::MulOp( double fVal, ScMatrix& rMat)
2670 auto mul_ = [](double a, double b){return a * b;};
2671 matop::MatOp<decltype(mul_)> aOp(mul_, pImpl->GetErrorInterpreter(), fVal);
2672 pImpl->ApplyOperation(aOp, *rMat.pImpl);
2675 void ScMatrix::DivOp( bool bFlag, double fVal, ScMatrix& rMat)
2677 if (bFlag)
2679 auto div_ = [](double a, double b){return sc::div(b, a);};
2680 matop::MatOp<decltype(div_)> aOp(div_, pImpl->GetErrorInterpreter(), fVal);
2681 pImpl->ApplyOperation(aOp, *rMat.pImpl);
2683 else
2685 auto div_ = [](double a, double b){return sc::div(a, b);};
2686 matop::MatOp<decltype(div_)> aOp(div_, pImpl->GetErrorInterpreter(), fVal);
2687 pImpl->ApplyOperation(aOp, *rMat.pImpl);
2691 void ScMatrix::PowOp( bool bFlag, double fVal, ScMatrix& rMat)
2693 if (bFlag)
2695 auto pow_ = [](double a, double b){return pow(b, a);};
2696 matop::MatOp<decltype(pow_)> aOp(pow_, pImpl->GetErrorInterpreter(), fVal);
2697 pImpl->ApplyOperation(aOp, *rMat.pImpl);
2699 else
2701 auto pow_ = [](double a, double b){return pow(a, b);};
2702 matop::MatOp<decltype(pow_)> aOp(pow_, pImpl->GetErrorInterpreter(), fVal);
2703 pImpl->ApplyOperation(aOp, *rMat.pImpl);
2707 ScMatrix& ScMatrix::operator+= ( const ScMatrix& r )
2709 pImpl->AddValues(*r.pImpl);
2710 return *this;
2713 #if DEBUG_MATRIX
2714 void ScMatrix::Dump() const
2716 pImpl->Dump();
2718 #endif
2720 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */