Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / tool / scmatrix.cxx
blob132923decf7e0f275c00f331edbe5d28c7cdc982
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"
28 #include <svl/zforlist.hxx>
29 #include "svl/sharedstring.hxx"
30 #include <tools/stream.hxx>
31 #include <rtl/math.hxx>
33 #include <math.h>
35 #include <vector>
36 #include <limits>
38 #include <mdds/multi_type_matrix.hpp>
39 #include <mdds/multi_type_vector_types.hpp>
40 #include <mdds/multi_type_vector_trait.hpp>
42 #if DEBUG_MATRIX
43 #include <iostream>
44 using std::cout;
45 using std::endl;
46 #endif
48 using ::std::pair;
49 using ::std::for_each;
50 using ::std::count_if;
51 using ::std::advance;
52 using ::std::unary_function;
54 /**
55 * Custom string trait struct to tell mdds::multi_type_matrix about the
56 * custom string type and how to handle blocks storing them.
58 struct custom_string_trait
60 typedef svl::SharedString string_type;
61 typedef sc::string_block string_element_block;
63 static const mdds::mtv::element_t string_type_identifier = sc::element_type_string;
65 typedef mdds::mtv::custom_block_func1<sc::string_block> element_block_func;
68 typedef mdds::multi_type_matrix<custom_string_trait> MatrixImplType;
70 namespace {
72 struct ElemEqualZero : public unary_function<double, bool>
74 bool operator() (double val) const
76 return val == 0.0;
80 struct ElemNotEqualZero : public unary_function<double, bool>
82 bool operator() (double val) const
84 return val != 0.0;
88 struct ElemGreaterZero : public unary_function<double, bool>
90 bool operator() (double val) const
92 return val > 0.0;
96 struct ElemLessZero : public unary_function<double, bool>
98 bool operator() (double val) const
100 return val < 0.0;
104 struct ElemGreaterEqualZero : public unary_function<double, bool>
106 bool operator() (double val) const
108 return val >= 0.0;
112 struct ElemLessEqualZero : public unary_function<double, bool>
114 bool operator() (double val) const
116 return val <= 0.0;
120 template<typename _Comp>
121 class CompareMatrixElemFunc : std::unary_function<MatrixImplType::element_block_node_type, void>
123 static _Comp maComp;
125 std::vector<bool> maNewMatValues;
126 size_t mnRow;
127 size_t mnCol;
128 public:
129 CompareMatrixElemFunc( size_t nRow, size_t nCol ) : mnRow(nRow), mnCol(nCol)
131 maNewMatValues.reserve(nRow*nCol);
134 void operator() (const MatrixImplType::element_block_node_type& node)
136 switch (node.type)
138 case mdds::mtm::element_numeric:
140 typedef MatrixImplType::numeric_block_type block_type;
142 block_type::const_iterator it = block_type::begin(*node.data);
143 block_type::const_iterator itEnd = block_type::end(*node.data);
144 for (; it != itEnd; ++it)
146 double fVal = *it;
147 if (!rtl::math::isFinite(fVal))
149 /* FIXME: this silently skips an error instead of propagating it! */
150 maNewMatValues.push_back(false);
151 continue;
154 maNewMatValues.push_back(maComp(fVal));
157 break;
158 case mdds::mtm::element_boolean:
160 typedef MatrixImplType::boolean_block_type block_type;
162 block_type::const_iterator it = block_type::begin(*node.data);
163 block_type::const_iterator itEnd = block_type::end(*node.data);
164 for (; it != itEnd; ++it)
166 double fVal = *it ? 1.0 : 0.0;
167 maNewMatValues.push_back(maComp(fVal));
170 break;
171 case mdds::mtm::element_string:
172 case mdds::mtm::element_empty:
173 default:
174 // Fill it with false.
175 maNewMatValues.resize(maNewMatValues.size() + node.size, false);
179 void swap( MatrixImplType& rMat )
181 MatrixImplType aNewMat(mnRow, mnCol, maNewMatValues.begin(), maNewMatValues.end());
182 rMat.swap(aNewMat);
186 template<typename _Comp>
187 _Comp CompareMatrixElemFunc<_Comp>::maComp;
191 class ScMatrixImpl
193 MatrixImplType maMat;
194 MatrixImplType maMatFlag;
195 ScInterpreter* pErrorInterpreter;
196 bool mbCloneIfConst; // Whether the matrix is cloned with a CloneIfConst() call.
198 ScMatrixImpl();
199 ScMatrixImpl(const ScMatrixImpl&);
200 public:
201 ScMatrixImpl(SCSIZE nC, SCSIZE nR);
202 ScMatrixImpl(SCSIZE nC, SCSIZE nR, double fInitVal);
204 ScMatrixImpl( size_t nC, size_t nR, const std::vector<bool>& rInitVals );
206 ~ScMatrixImpl();
208 void Clear();
209 void SetImmutable(bool bVal);
210 bool IsImmutable() const;
211 void Resize(SCSIZE nC, SCSIZE nR);
212 void Resize(SCSIZE nC, SCSIZE nR, double fVal);
213 void SetErrorInterpreter( ScInterpreter* p);
214 ScInterpreter* GetErrorInterpreter() const { return pErrorInterpreter; }
216 void GetDimensions( SCSIZE& rC, SCSIZE& rR) const;
217 SCSIZE GetElementCount() const;
218 bool ValidColRow( SCSIZE nC, SCSIZE nR) const;
219 bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const;
220 bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const;
221 void SetErrorAtInterpreter( sal_uInt16 nError ) const;
223 void PutDouble(double fVal, SCSIZE nC, SCSIZE nR);
224 void PutDouble( double fVal, SCSIZE nIndex);
225 void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR);
227 void PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR);
228 void PutString(const svl::SharedString& rStr, SCSIZE nIndex);
229 void PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR);
231 void PutEmpty(SCSIZE nC, SCSIZE nR);
232 void PutEmptyPath(SCSIZE nC, SCSIZE nR);
233 void PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR );
234 void PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR);
235 sal_uInt16 GetError( SCSIZE nC, SCSIZE nR) const;
236 double GetDouble(SCSIZE nC, SCSIZE nR) const;
237 double GetDouble( SCSIZE nIndex) const;
238 svl::SharedString GetString(SCSIZE nC, SCSIZE nR) const;
239 svl::SharedString GetString( SCSIZE nIndex) const;
240 svl::SharedString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const;
241 ScMatrixValue Get(SCSIZE nC, SCSIZE nR) const;
242 bool IsString( SCSIZE nIndex ) const;
243 bool IsString( SCSIZE nC, SCSIZE nR ) const;
244 bool IsEmpty( SCSIZE nC, SCSIZE nR ) const;
245 bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const;
246 bool IsValue( SCSIZE nIndex ) const;
247 bool IsValue( SCSIZE nC, SCSIZE nR ) const;
248 bool IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const;
249 bool IsBoolean( SCSIZE nC, SCSIZE nR ) const;
250 bool IsNumeric() const;
252 void MatCopy(ScMatrixImpl& mRes) const;
253 void MatTrans(ScMatrixImpl& mRes) const;
254 void FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 );
255 void PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR );
256 void PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR );
257 void PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
258 void PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
259 void CompareEqual();
260 void CompareNotEqual();
261 void CompareLess();
262 void CompareGreater();
263 void CompareLessEqual();
264 void CompareGreaterEqual();
265 double And() const;
266 double Or() const;
267 double Xor() const;
269 ScMatrix::IterateResult Sum(bool bTextAsZero) const;
270 ScMatrix::IterateResult SumSquare(bool bTextAsZero) const;
271 ScMatrix::IterateResult Product(bool bTextAsZero) const;
272 size_t Count(bool bCountStrings) const;
273 size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const;
274 size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const;
276 double GetMaxValue( bool bTextAsZero ) const;
277 double GetMinValue( bool bTextAsZero ) const;
279 ScMatrixRef CompareMatrix( sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const;
281 void GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const;
282 void MergeDoubleArray( std::vector<double>& rArray, ScMatrix::Op eOp ) const;
283 void AddValues( const ScMatrixImpl& rMat );
285 #if DEBUG_MATRIX
286 void Dump() const;
287 #endif
289 private:
290 void CalcPosition(SCSIZE nIndex, SCSIZE& rC, SCSIZE& rR) const;
293 ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR) :
294 maMat(nR, nC), maMatFlag(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
296 ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR, double fInitVal) :
297 maMat(nR, nC, fInitVal), maMatFlag(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
299 ScMatrixImpl::ScMatrixImpl( size_t nC, size_t nR, const std::vector<bool>& rInitVals ) :
300 maMat(nR, nC, rInitVals.begin(), rInitVals.end()), maMatFlag(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
302 ScMatrixImpl::~ScMatrixImpl()
304 Clear();
307 void ScMatrixImpl::Clear()
309 maMat.clear();
310 maMatFlag.clear();
313 void ScMatrixImpl::SetImmutable(bool bVal)
315 mbCloneIfConst = bVal;
318 bool ScMatrixImpl::IsImmutable() const
320 return mbCloneIfConst;
323 void ScMatrixImpl::Resize(SCSIZE nC, SCSIZE nR)
325 maMat.resize(nR, nC);
326 maMatFlag.resize(nR, nC);
329 void ScMatrixImpl::Resize(SCSIZE nC, SCSIZE nR, double fVal)
331 maMat.resize(nR, nC, fVal);
332 maMatFlag.resize(nR, nC);
335 void ScMatrixImpl::SetErrorInterpreter( ScInterpreter* p)
337 pErrorInterpreter = p;
340 void ScMatrixImpl::GetDimensions( SCSIZE& rC, SCSIZE& rR) const
342 MatrixImplType::size_pair_type aSize = maMat.size();
343 rR = aSize.row;
344 rC = aSize.column;
347 SCSIZE ScMatrixImpl::GetElementCount() const
349 MatrixImplType::size_pair_type aSize = maMat.size();
350 return aSize.row * aSize.column;
353 bool ScMatrixImpl::ValidColRow( SCSIZE nC, SCSIZE nR) const
355 MatrixImplType::size_pair_type aSize = maMat.size();
356 return nR < aSize.row && nC < aSize.column;
359 bool ScMatrixImpl::ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const
361 MatrixImplType::size_pair_type aSize = maMat.size();
362 if (aSize.column == 1 && aSize.row == 1)
364 rC = 0;
365 rR = 0;
366 return true;
368 else if (aSize.column == 1 && rR < aSize.row)
370 // single column matrix.
371 rC = 0;
372 return true;
374 else if (aSize.row == 1 && rC < aSize.column)
376 // single row matrix.
377 rR = 0;
378 return true;
380 return false;
383 bool ScMatrixImpl::ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const
385 return ValidColRow( rC, rR) || ValidColRowReplicated( rC, rR);
388 void ScMatrixImpl::SetErrorAtInterpreter( sal_uInt16 nError ) const
390 if ( pErrorInterpreter )
391 pErrorInterpreter->SetError( nError);
394 void ScMatrixImpl::PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
396 if (ValidColRow( nC, nR))
397 maMat.set(nR, nC, fVal);
398 else
400 OSL_FAIL("ScMatrixImpl::PutDouble: dimension error");
404 void ScMatrixImpl::PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
406 if (ValidColRow( nC, nR))
407 maMat.set(nR, nC, pArray, pArray + nLen);
408 else
410 OSL_FAIL("ScMatrixImpl::PutDouble: dimension error");
414 void ScMatrixImpl::PutDouble( double fVal, SCSIZE nIndex)
416 SCSIZE nC, nR;
417 CalcPosition(nIndex, nC, nR);
418 PutDouble(fVal, nC, nR);
421 void ScMatrixImpl::PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR)
423 if (ValidColRow( nC, nR))
424 maMat.set(nR, nC, rStr);
425 else
427 OSL_FAIL("ScMatrixImpl::PutString: dimension error");
431 void ScMatrixImpl::PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
433 if (ValidColRow( nC, nR))
434 maMat.set(nR, nC, pArray, pArray + nLen);
435 else
437 OSL_FAIL("ScMatrixImpl::PutString: dimension error");
441 void ScMatrixImpl::PutString(const svl::SharedString& rStr, SCSIZE nIndex)
443 SCSIZE nC, nR;
444 CalcPosition(nIndex, nC, nR);
445 PutString(rStr, nC, nR);
448 void ScMatrixImpl::PutEmpty(SCSIZE nC, SCSIZE nR)
450 if (ValidColRow( nC, nR))
452 maMat.set_empty(nR, nC);
453 maMatFlag.set(nR, nC, false); // zero flag to indicate that this is 'empty', not 'empty path'.
455 else
457 OSL_FAIL("ScMatrixImpl::PutEmpty: dimension error");
461 void ScMatrixImpl::PutEmptyPath(SCSIZE nC, SCSIZE nR)
463 if (ValidColRow( nC, nR))
465 maMat.set_empty(nR, nC);
466 maMatFlag.set(nR, nC, true); // non-zero flag to indicate empty 'path'.
468 else
470 OSL_FAIL("ScMatrixImpl::PutEmptyPath: dimension error");
474 void ScMatrixImpl::PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR )
476 maMat.set(nR, nC, CreateDoubleError(nErrorCode));
479 void ScMatrixImpl::PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
481 if (ValidColRow( nC, nR))
482 maMat.set(nR, nC, bVal);
483 else
485 OSL_FAIL("ScMatrixImpl::PutBoolean: dimension error");
489 sal_uInt16 ScMatrixImpl::GetError( SCSIZE nC, SCSIZE nR) const
491 if (ValidColRowOrReplicated( nC, nR ))
493 double fVal = maMat.get_numeric(nR, nC);
494 return GetDoubleErrorValue(fVal);
496 else
498 OSL_FAIL("ScMatrixImpl::GetError: dimension error");
499 return errNoValue;
503 double ScMatrixImpl::GetDouble(SCSIZE nC, SCSIZE nR) const
505 if (ValidColRowOrReplicated( nC, nR ))
507 double fVal = maMat.get_numeric(nR, nC);
508 if ( pErrorInterpreter )
510 sal_uInt16 nError = GetDoubleErrorValue(fVal);
511 if ( nError )
512 SetErrorAtInterpreter( nError);
514 return fVal;
516 else
518 OSL_FAIL("ScMatrixImpl::GetDouble: dimension error");
519 return CreateDoubleError( errNoValue);
523 double ScMatrixImpl::GetDouble( SCSIZE nIndex) const
525 SCSIZE nC, nR;
526 CalcPosition(nIndex, nC, nR);
527 return GetDouble(nC, nR);
530 svl::SharedString ScMatrixImpl::GetString(SCSIZE nC, SCSIZE nR) const
532 if (ValidColRowOrReplicated( nC, nR ))
534 double fErr = 0.0;
535 MatrixImplType::const_position_type aPos = maMat.position(nR, nC);
536 switch (maMat.get_type(aPos))
538 case mdds::mtm::element_string:
539 return maMat.get_string(aPos);
540 case mdds::mtm::element_empty:
541 return svl::SharedString::getEmptyString();
542 case mdds::mtm::element_numeric:
543 case mdds::mtm::element_boolean:
544 OSL_FAIL("ScMatrixImpl::GetString: access error, no string");
545 fErr = maMat.get_numeric(aPos);
546 default:
547 OSL_FAIL("ScMatrixImpl::GetString: access error, no string");
549 SetErrorAtInterpreter(GetDoubleErrorValue(fErr));
551 else
553 OSL_FAIL("ScMatrixImpl::GetString: dimension error");
555 return svl::SharedString::getEmptyString();
558 svl::SharedString ScMatrixImpl::GetString( SCSIZE nIndex) const
560 SCSIZE nC, nR;
561 CalcPosition(nIndex, nC, nR);
562 return GetString(nC, nR);
565 svl::SharedString ScMatrixImpl::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
567 if (!ValidColRowOrReplicated( nC, nR ))
569 OSL_FAIL("ScMatrixImpl::GetString: dimension error");
570 return OUString();
573 double fVal = 0.0;
574 MatrixImplType::const_position_type aPos = maMat.position(nR, nC);
575 switch (maMat.get_type(aPos))
577 case mdds::mtm::element_string:
578 return maMat.get_string(aPos).getString();
579 case mdds::mtm::element_empty:
581 if (!maMatFlag.get<bool>(nR, nC))
582 // not an empty path.
583 break;
585 // result of empty FALSE jump path
586 sal_uLong nKey = rFormatter.GetStandardFormat( NUMBERFORMAT_LOGICAL,
587 ScGlobal::eLnge);
588 OUString aStr;
589 Color* pColor = NULL;
590 rFormatter.GetOutputString( 0.0, nKey, aStr, &pColor);
591 return aStr;
593 case mdds::mtm::element_numeric:
594 case mdds::mtm::element_boolean:
595 fVal = maMat.get_numeric(aPos);
596 break;
597 default:
601 sal_uInt16 nError = GetDoubleErrorValue(fVal);
602 if (nError)
604 SetErrorAtInterpreter( nError);
605 return ScGlobal::GetErrorString( nError);
608 sal_uLong nKey = rFormatter.GetStandardFormat( NUMBERFORMAT_NUMBER,
609 ScGlobal::eLnge);
610 OUString aStr;
611 rFormatter.GetInputLineString( fVal, nKey, aStr);
612 return aStr;
615 ScMatrixValue ScMatrixImpl::Get(SCSIZE nC, SCSIZE nR) const
617 ScMatrixValue aVal;
618 if (ValidColRowOrReplicated(nC, nR))
620 MatrixImplType::const_position_type aPos = maMat.position(nR, nC);
621 mdds::mtm::element_t eType = maMat.get_type(aPos);
622 switch (eType)
624 case mdds::mtm::element_boolean:
625 aVal.nType = SC_MATVAL_BOOLEAN;
626 aVal.fVal = maMat.get_boolean(aPos);
627 break;
628 case mdds::mtm::element_numeric:
629 aVal.nType = SC_MATVAL_VALUE;
630 aVal.fVal = maMat.get_numeric(aPos);
631 break;
632 case mdds::mtm::element_string:
633 aVal.nType = SC_MATVAL_STRING;
634 aVal.aStr = maMat.get_string(aPos);
635 break;
636 case mdds::mtm::element_empty:
637 // Empty path equals empty plus flag.
638 aVal.nType = maMatFlag.get<bool>(nR, nC) ? SC_MATVAL_EMPTYPATH : SC_MATVAL_EMPTY;
639 aVal.fVal = 0.0;
640 default:
644 else
646 OSL_FAIL("ScMatrixImpl::Get: dimension error");
648 return aVal;
651 bool ScMatrixImpl::IsString( SCSIZE nIndex ) const
653 SCSIZE nC, nR;
654 CalcPosition(nIndex, nC, nR);
655 return IsString(nC, nR);
658 bool ScMatrixImpl::IsString( SCSIZE nC, SCSIZE nR ) const
660 ValidColRowReplicated( nC, nR );
661 switch (maMat.get_type(nR, nC))
663 case mdds::mtm::element_empty:
664 case mdds::mtm::element_string:
665 return true;
666 default:
669 return false;
672 bool ScMatrixImpl::IsEmpty( SCSIZE nC, SCSIZE nR ) const
674 // Flag must be zero for this to be an empty element, instead of being an
675 // empty path element.
676 ValidColRowReplicated( nC, nR );
677 return maMat.get_type(nR, nC) == mdds::mtm::element_empty && !maMatFlag.get<bool>(nR, nC);
680 bool ScMatrixImpl::IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
682 // 'Empty path' is empty plus non-zero flag.
683 if (ValidColRowOrReplicated( nC, nR ))
684 return maMat.get_type(nR, nC) == mdds::mtm::element_empty && maMatFlag.get<bool>(nR, nC);
685 else
686 return true;
689 bool ScMatrixImpl::IsValue( SCSIZE nIndex ) const
691 SCSIZE nC, nR;
692 CalcPosition(nIndex, nC, nR);
693 return IsValue(nC, nR);
696 bool ScMatrixImpl::IsValue( SCSIZE nC, SCSIZE nR ) const
698 ValidColRowReplicated(nC, nR);
699 switch (maMat.get_type(nR, nC))
701 case mdds::mtm::element_boolean:
702 case mdds::mtm::element_numeric:
703 return true;
704 default:
707 return false;
710 bool ScMatrixImpl::IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
712 ValidColRowReplicated(nC, nR);
713 switch (maMat.get_type(nR, nC))
715 case mdds::mtm::element_boolean:
716 case mdds::mtm::element_numeric:
717 case mdds::mtm::element_empty:
718 return true;
719 default:
722 return false;
725 bool ScMatrixImpl::IsBoolean( SCSIZE nC, SCSIZE nR ) const
727 ValidColRowReplicated( nC, nR );
728 return maMat.get_type(nR, nC) == mdds::mtm::element_boolean;
731 bool ScMatrixImpl::IsNumeric() const
733 return maMat.numeric();
736 void ScMatrixImpl::MatCopy(ScMatrixImpl& mRes) const
738 if (maMat.size().row > mRes.maMat.size().row || maMat.size().column > mRes.maMat.size().column)
740 // destination matrix is not large enough.
741 OSL_FAIL("ScMatrixImpl::MatCopy: dimension error");
742 return;
745 mRes.maMat.copy(maMat);
748 void ScMatrixImpl::MatTrans(ScMatrixImpl& mRes) const
750 mRes.maMat = maMat;
751 mRes.maMat.transpose();
754 void ScMatrixImpl::FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 )
756 if (ValidColRow( nC1, nR1) && ValidColRow( nC2, nR2))
758 for (SCSIZE j = nC1; j <= nC2; ++j)
760 // Passing value array is much faster.
761 std::vector<double> aVals(nR2-nR1+1, fVal);
762 maMat.set(nR1, j, aVals.begin(), aVals.end());
765 else
767 OSL_FAIL("ScMatrixImpl::FillDouble: dimension error");
771 void ScMatrixImpl::PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR )
773 if (!rVec.empty() && ValidColRow( nC, nR) && ValidColRow( nC, nR + rVec.size() - 1))
775 maMat.set(nR, nC, rVec.begin(), rVec.end());
777 else
779 OSL_FAIL("ScMatrixImpl::PutDoubleVector: dimension error");
783 void ScMatrixImpl::PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR )
785 if (!rVec.empty() && ValidColRow( nC, nR) && ValidColRow( nC, nR + rVec.size() - 1))
787 maMat.set(nR, nC, rVec.begin(), rVec.end());
789 else
791 OSL_FAIL("ScMatrixImpl::PutStringVector: dimension error");
795 void ScMatrixImpl::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
797 if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1))
799 maMat.set_empty(nR, nC, nCount);
800 // zero flag to indicate that this is 'empty', not 'empty path'.
801 std::vector<bool> aVals(nCount, false);
802 maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
804 else
806 OSL_FAIL("ScMatrixImpl::PutEmptyVector: dimension error");
810 void ScMatrixImpl::PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
812 if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1))
814 maMat.set_empty(nR, nC, nCount);
815 // non-zero flag to indicate empty 'path'.
816 std::vector<bool> aVals(nCount, true);
817 maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
819 else
821 OSL_FAIL("ScMatrixImpl::PutEmptyPathVector: dimension error");
825 void ScMatrixImpl::CompareEqual()
827 MatrixImplType::size_pair_type aSize = maMat.size();
828 CompareMatrixElemFunc<ElemEqualZero> aFunc(aSize.row, aSize.column);
829 maMat.walk(aFunc);
830 aFunc.swap(maMat);
833 void ScMatrixImpl::CompareNotEqual()
835 MatrixImplType::size_pair_type aSize = maMat.size();
836 CompareMatrixElemFunc<ElemNotEqualZero> aFunc(aSize.row, aSize.column);
837 maMat.walk(aFunc);
838 aFunc.swap(maMat);
841 void ScMatrixImpl::CompareLess()
843 MatrixImplType::size_pair_type aSize = maMat.size();
844 CompareMatrixElemFunc<ElemLessZero> aFunc(aSize.row, aSize.column);
845 maMat.walk(aFunc);
846 aFunc.swap(maMat);
849 void ScMatrixImpl::CompareGreater()
851 MatrixImplType::size_pair_type aSize = maMat.size();
852 CompareMatrixElemFunc<ElemGreaterZero> aFunc(aSize.row, aSize.column);
853 maMat.walk(aFunc);
854 aFunc.swap(maMat);
857 void ScMatrixImpl::CompareLessEqual()
859 MatrixImplType::size_pair_type aSize = maMat.size();
860 CompareMatrixElemFunc<ElemLessEqualZero> aFunc(aSize.row, aSize.column);
861 maMat.walk(aFunc);
862 aFunc.swap(maMat);
865 void ScMatrixImpl::CompareGreaterEqual()
867 MatrixImplType::size_pair_type aSize = maMat.size();
868 CompareMatrixElemFunc<ElemGreaterEqualZero> aFunc(aSize.row, aSize.column);
869 maMat.walk(aFunc);
870 aFunc.swap(maMat);
873 namespace {
875 struct AndEvaluator
877 bool mbResult;
878 void operate(double fVal) { mbResult &= (fVal != 0.0); }
879 bool result() const { return mbResult; }
880 AndEvaluator() : mbResult(true) {}
883 struct OrEvaluator
885 bool mbResult;
886 void operate(double fVal) { mbResult |= (fVal != 0.0); }
887 bool result() const { return mbResult; }
888 OrEvaluator() : mbResult(false) {}
891 struct XorEvaluator
893 bool mbResult;
894 void operate(double fVal) { mbResult ^= (fVal != 0.0); }
895 bool result() const { return mbResult; }
896 XorEvaluator() : mbResult(false) {}
899 // Do not short circuit logical operations, in case there are error values
900 // these need to be propagated even if the result was determined earlier.
901 template <typename _Evaluator>
902 double EvalMatrix(const MatrixImplType& rMat)
904 _Evaluator aEval;
905 size_t nRows = rMat.size().row, nCols = rMat.size().column;
906 for (size_t i = 0; i < nRows; ++i)
908 for (size_t j = 0; j < nCols; ++j)
910 MatrixImplType::const_position_type aPos = rMat.position(i, j);
911 mdds::mtm::element_t eType = rMat.get_type(aPos);
912 if (eType != mdds::mtm::element_numeric && eType != mdds::mtm::element_boolean)
913 // assuming a CompareMat this is an error
914 return CreateDoubleError(errIllegalArgument);
916 double fVal = rMat.get_numeric(aPos);
917 if (!::rtl::math::isFinite(fVal))
918 // DoubleError
919 return fVal;
921 aEval.operate(fVal);
924 return aEval.result();
929 double ScMatrixImpl::And() const
931 // All elements must be of value type.
932 // True only if all the elements have non-zero values.
933 return EvalMatrix<AndEvaluator>(maMat);
936 double ScMatrixImpl::Or() const
938 // All elements must be of value type.
939 // True if at least one element has a non-zero value.
940 return EvalMatrix<OrEvaluator>(maMat);
943 double ScMatrixImpl::Xor() const
945 // All elements must be of value type.
946 // True if an odd number of elements have a non-zero value.
947 return EvalMatrix<XorEvaluator>(maMat);
950 namespace {
952 struct SumOp
954 static const int InitVal = 0;
956 void operator() (double& rAccum, double fVal)
958 rAccum += fVal;
962 struct SumSquareOp
964 static const int InitVal = 0;
966 void operator() (double& rAccum, double fVal)
968 rAccum += fVal*fVal;
972 struct ProductOp
974 static const int InitVal = 1;
976 void operator() (double& rAccum, double fVal)
978 rAccum *= fVal;
982 template<typename _Op>
983 class WalkElementBlocks : std::unary_function<MatrixImplType::element_block_node_type, void>
985 _Op maOp;
987 ScMatrix::IterateResult maRes;
988 bool mbFirst:1;
989 bool mbTextAsZero:1;
990 public:
991 WalkElementBlocks(bool bTextAsZero) : maRes(0.0, _Op::InitVal, 0), mbFirst(true), mbTextAsZero(bTextAsZero) {}
993 const ScMatrix::IterateResult& getResult() const { return maRes; }
995 void operator() (const MatrixImplType::element_block_node_type& node)
997 switch (node.type)
999 case mdds::mtm::element_numeric:
1001 typedef MatrixImplType::numeric_block_type block_type;
1003 block_type::const_iterator it = block_type::begin(*node.data);
1004 block_type::const_iterator itEnd = block_type::end(*node.data);
1005 for (; it != itEnd; ++it)
1007 if (mbFirst)
1009 maOp(maRes.mfFirst, *it);
1010 mbFirst = false;
1012 else
1013 maOp(maRes.mfRest, *it);
1015 maRes.mnCount += node.size;
1017 break;
1018 case mdds::mtm::element_boolean:
1020 typedef MatrixImplType::boolean_block_type block_type;
1022 block_type::const_iterator it = block_type::begin(*node.data);
1023 block_type::const_iterator itEnd = block_type::end(*node.data);
1024 for (; it != itEnd; ++it)
1026 if (mbFirst)
1028 maOp(maRes.mfFirst, *it);
1029 mbFirst = false;
1031 else
1032 maOp(maRes.mfRest, *it);
1034 maRes.mnCount += node.size;
1036 break;
1037 case mdds::mtm::element_string:
1038 if (mbTextAsZero)
1039 maRes.mnCount += node.size;
1040 break;
1041 case mdds::mtm::element_empty:
1042 default:
1048 class CountElements : std::unary_function<MatrixImplType::element_block_node_type, void>
1050 size_t mnCount;
1051 bool mbCountString;
1052 public:
1053 CountElements(bool bCountString) : mnCount(0), mbCountString(bCountString) {}
1055 size_t getCount() const { return mnCount; }
1057 void operator() (const MatrixImplType::element_block_node_type& node)
1059 switch (node.type)
1061 case mdds::mtm::element_numeric:
1062 case mdds::mtm::element_boolean:
1063 mnCount += node.size;
1064 break;
1065 case mdds::mtm::element_string:
1066 if (mbCountString)
1067 mnCount += node.size;
1068 break;
1069 case mdds::mtm::element_empty:
1070 default:
1076 const size_t ResultNotSet = std::numeric_limits<size_t>::max();
1078 template<typename _Type>
1079 class WalkAndMatchElements : std::unary_function<MatrixImplType::element_block_node_type, void>
1081 _Type maMatchValue;
1082 MatrixImplType::size_pair_type maSize;
1083 size_t mnCol1;
1084 size_t mnCol2;
1085 size_t mnResult;
1086 size_t mnIndex;
1088 public:
1089 WalkAndMatchElements(_Type aMatchValue, const MatrixImplType::size_pair_type& aSize, size_t nCol1, size_t nCol2) :
1090 maMatchValue(aMatchValue),
1091 maSize(aSize),
1092 mnCol1(nCol1),
1093 mnCol2(nCol2),
1094 mnResult(ResultNotSet),
1095 mnIndex(0) {}
1097 size_t getMatching() const { return mnResult; }
1099 size_t compare(const MatrixImplType::element_block_node_type& node) const;
1101 void operator() (const MatrixImplType::element_block_node_type& node)
1103 // early exit if match aleady found
1104 if (mnResult != ResultNotSet)
1105 return;
1107 // limit lookup to the requested columns
1108 if ((mnCol1 * maSize.row) <= mnIndex && mnIndex < ((mnCol2 + 1) * maSize.row))
1110 mnResult = compare(node);
1113 mnIndex += node.size;
1117 template<>
1118 size_t WalkAndMatchElements<double>::compare(const MatrixImplType::element_block_node_type& node) const
1120 size_t nCount = 0;
1121 switch (node.type)
1123 case mdds::mtm::element_numeric:
1125 typedef MatrixImplType::numeric_block_type block_type;
1127 block_type::const_iterator it = block_type::begin(*node.data);
1128 block_type::const_iterator itEnd = block_type::end(*node.data);
1129 for (; it != itEnd; ++it, nCount++)
1131 if (*it == maMatchValue)
1133 return mnIndex + nCount;
1136 break;
1138 case mdds::mtm::element_boolean:
1140 typedef MatrixImplType::boolean_block_type block_type;
1142 block_type::const_iterator it = block_type::begin(*node.data);
1143 block_type::const_iterator itEnd = block_type::end(*node.data);
1144 for (; it != itEnd; ++it, ++nCount)
1146 if (int(*it) == maMatchValue)
1148 return mnIndex + nCount;
1151 break;
1153 break;
1154 case mdds::mtm::element_string:
1155 case mdds::mtm::element_empty:
1156 default:
1159 return ResultNotSet;
1162 template<>
1163 size_t WalkAndMatchElements<svl::SharedString>::compare(const MatrixImplType::element_block_node_type& node) const
1165 size_t nCount = 0;
1166 switch (node.type)
1168 case mdds::mtm::element_string:
1170 typedef MatrixImplType::string_block_type block_type;
1172 block_type::const_iterator it = block_type::begin(*node.data);
1173 block_type::const_iterator itEnd = block_type::end(*node.data);
1174 for (; it != itEnd; ++it, ++nCount)
1176 if (it->getDataIgnoreCase() == maMatchValue.getDataIgnoreCase())
1178 return mnIndex + nCount;
1181 break;
1183 case mdds::mtm::element_boolean:
1184 case mdds::mtm::element_numeric:
1185 case mdds::mtm::element_empty:
1186 default:
1189 return ResultNotSet;
1192 struct MaxOp
1194 static double init() { return -std::numeric_limits<double>::max(); }
1195 static double compare(double left, double right)
1197 return std::max(left, right);
1200 static double boolValue(
1201 MatrixImplType::boolean_block_type::const_iterator it,
1202 MatrixImplType::boolean_block_type::const_iterator itEnd)
1204 // If the array has at least one true value, the maximum value is 1.
1205 it = std::find(it, itEnd, true);
1206 return it == itEnd ? 0.0 : 1.0;
1210 struct MinOp
1212 static double init() { return std::numeric_limits<double>::max(); }
1213 static double compare(double left, double right)
1215 return std::min(left, right);
1218 static double boolValue(
1219 MatrixImplType::boolean_block_type::const_iterator it,
1220 MatrixImplType::boolean_block_type::const_iterator itEnd)
1222 // If the array has at least one false value, the minimum value is 0.
1223 it = std::find(it, itEnd, false);
1224 return it == itEnd ? 1.0 : 0.0;
1228 template<typename _Op>
1229 class CalcMaxMinValue : std::unary_function<MatrixImplType::element_block_type, void>
1231 double mfVal;
1232 bool mbTextAsZero;
1233 public:
1234 CalcMaxMinValue( bool bTextAsZero ) :
1235 mfVal(_Op::init()),
1236 mbTextAsZero(bTextAsZero) {}
1238 double getValue() const { return mfVal; }
1240 void operator() (const MatrixImplType::element_block_node_type& node)
1243 switch (node.type)
1245 case mdds::mtm::element_numeric:
1247 typedef MatrixImplType::numeric_block_type block_type;
1249 block_type::const_iterator it = block_type::begin(*node.data);
1250 block_type::const_iterator itEnd = block_type::end(*node.data);
1251 for (; it != itEnd; ++it)
1252 mfVal = _Op::compare(mfVal, *it);
1254 break;
1255 case mdds::mtm::element_boolean:
1257 typedef MatrixImplType::boolean_block_type block_type;
1259 block_type::const_iterator it = block_type::begin(*node.data);
1260 block_type::const_iterator itEnd = block_type::end(*node.data);
1261 double fVal = _Op::boolValue(it, itEnd);
1262 mfVal = _Op::compare(mfVal, fVal);
1264 break;
1265 case mdds::mtm::element_string:
1266 case mdds::mtm::element_empty:
1268 // empty elements are treated as empty strings.
1269 if (mbTextAsZero)
1270 mfVal = _Op::compare(mfVal, 0.0);
1272 break;
1273 default:
1279 inline bool evaluate( double fVal, ScQueryOp eOp )
1281 switch (eOp)
1283 case SC_EQUAL:
1284 return fVal == 0.0;
1285 case SC_LESS:
1286 return fVal < 0.0;
1287 case SC_GREATER:
1288 return fVal > 0.0;
1289 break;
1290 case SC_LESS_EQUAL:
1291 return fVal <= 0.0;
1292 break;
1293 case SC_GREATER_EQUAL:
1294 return fVal >= 0.0;
1295 break;
1296 case SC_NOT_EQUAL:
1297 return fVal != 0.0;
1298 break;
1299 default:
1303 OSL_TRACE( "evaluate: unhandled comparison operator: %d", (int)eOp);
1304 return false;
1307 class CompareMatrixFunc : std::unary_function<MatrixImplType::element_block_type, void>
1309 sc::Compare& mrComp;
1310 size_t mnMatPos;
1311 sc::CompareOptions* mpOptions;
1312 std::vector<bool> maResValues;
1314 void compare()
1316 double fVal = sc::CompareFunc(mrComp.maCells[0], mrComp.maCells[1], mrComp.mbIgnoreCase, mpOptions);
1317 maResValues.push_back(evaluate(fVal, mrComp.meOp));
1320 public:
1321 CompareMatrixFunc( size_t nResSize, sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) :
1322 mrComp(rComp), mnMatPos(nMatPos), mpOptions(pOptions)
1324 maResValues.reserve(nResSize);
1327 void operator() (const MatrixImplType::element_block_node_type& node)
1329 sc::Compare::Cell& rCell = mrComp.maCells[mnMatPos];
1331 switch (node.type)
1333 case mdds::mtm::element_numeric:
1335 typedef MatrixImplType::numeric_block_type block_type;
1337 block_type::const_iterator it = block_type::begin(*node.data);
1338 block_type::const_iterator itEnd = block_type::end(*node.data);
1339 for (; it != itEnd; ++it)
1341 rCell.mbValue = true;
1342 rCell.mbEmpty = false;
1343 rCell.mfValue = *it;
1344 compare();
1347 break;
1348 case mdds::mtm::element_boolean:
1350 typedef MatrixImplType::boolean_block_type block_type;
1352 block_type::const_iterator it = block_type::begin(*node.data);
1353 block_type::const_iterator itEnd = block_type::end(*node.data);
1354 for (; it != itEnd; ++it)
1356 rCell.mbValue = true;
1357 rCell.mbEmpty = false;
1358 rCell.mfValue = *it;
1359 compare();
1362 break;
1363 case mdds::mtm::element_string:
1365 typedef MatrixImplType::string_block_type block_type;
1367 block_type::const_iterator it = block_type::begin(*node.data);
1368 block_type::const_iterator itEnd = block_type::end(*node.data);
1369 for (; it != itEnd; ++it)
1371 const svl::SharedString& rStr = *it;
1372 rCell.mbValue = false;
1373 rCell.mbEmpty = false;
1374 rCell.maStr = rStr;
1375 compare();
1378 break;
1379 case mdds::mtm::element_empty:
1381 rCell.mbValue = false;
1382 rCell.mbEmpty = true;
1383 rCell.maStr = svl::SharedString::getEmptyString();
1384 for (size_t i = 0; i < node.size; ++i)
1385 compare();
1387 default:
1392 const std::vector<bool>& getValues() const
1394 return maResValues;
1399 * Left-hand side is a matrix while the right-hand side is a numeric value.
1401 class CompareMatrixToNumericFunc : std::unary_function<MatrixImplType::element_block_type, void>
1403 sc::Compare& mrComp;
1404 double mfRightValue;
1405 sc::CompareOptions* mpOptions;
1406 std::vector<bool> maResValues;
1408 void compare()
1410 double fVal = sc::CompareFunc(mrComp.maCells[0], mfRightValue, mpOptions);
1411 maResValues.push_back(evaluate(fVal, mrComp.meOp));
1414 void compareLeftNumeric( double fLeftVal )
1416 double fVal = sc::CompareFunc(fLeftVal, mfRightValue);
1417 maResValues.push_back(evaluate(fVal, mrComp.meOp));
1420 void compareLeftEmpty( size_t nSize )
1422 double fVal = sc::CompareEmptyToNumericFunc(mfRightValue);
1423 bool bRes = evaluate(fVal, mrComp.meOp);
1424 maResValues.resize(maResValues.size() + nSize, bRes);
1427 public:
1428 CompareMatrixToNumericFunc( size_t nResSize, sc::Compare& rComp, double fRightValue, sc::CompareOptions* pOptions ) :
1429 mrComp(rComp), mfRightValue(fRightValue), mpOptions(pOptions)
1431 maResValues.reserve(nResSize);
1434 void operator() (const MatrixImplType::element_block_node_type& node)
1436 sc::Compare::Cell& rCell = mrComp.maCells[0];
1438 switch (node.type)
1440 case mdds::mtm::element_numeric:
1442 typedef MatrixImplType::numeric_block_type block_type;
1444 block_type::const_iterator it = block_type::begin(*node.data);
1445 block_type::const_iterator itEnd = block_type::end(*node.data);
1446 for (; it != itEnd; ++it)
1447 compareLeftNumeric(*it);
1449 break;
1450 case mdds::mtm::element_boolean:
1452 typedef MatrixImplType::boolean_block_type block_type;
1454 block_type::const_iterator it = block_type::begin(*node.data);
1455 block_type::const_iterator itEnd = block_type::end(*node.data);
1456 for (; it != itEnd; ++it)
1457 compareLeftNumeric(*it);
1459 break;
1460 case mdds::mtm::element_string:
1462 typedef MatrixImplType::string_block_type block_type;
1464 block_type::const_iterator it = block_type::begin(*node.data);
1465 block_type::const_iterator itEnd = block_type::end(*node.data);
1466 for (; it != itEnd; ++it)
1468 const svl::SharedString& rStr = *it;
1469 rCell.mbValue = false;
1470 rCell.mbEmpty = false;
1471 rCell.maStr = rStr;
1472 compare();
1475 break;
1476 case mdds::mtm::element_empty:
1477 compareLeftEmpty(node.size);
1478 break;
1479 default:
1484 const std::vector<bool>& getValues() const
1486 return maResValues;
1490 class ToDoubleArray : std::unary_function<MatrixImplType::element_block_type, void>
1492 std::vector<double> maArray;
1493 std::vector<double>::iterator miPos;
1494 double mfNaN;
1495 bool mbEmptyAsZero;
1497 public:
1498 ToDoubleArray( size_t nSize, bool bEmptyAsZero ) :
1499 maArray(nSize, 0.0), miPos(maArray.begin()), mbEmptyAsZero(bEmptyAsZero)
1501 rtl::math::setNan(&mfNaN);
1504 void operator() (const MatrixImplType::element_block_node_type& node)
1506 using namespace mdds::mtv;
1508 switch (node.type)
1510 case mdds::mtm::element_numeric:
1512 numeric_element_block::const_iterator it = numeric_element_block::begin(*node.data);
1513 numeric_element_block::const_iterator itEnd = numeric_element_block::end(*node.data);
1514 for (; it != itEnd; ++it, ++miPos)
1515 *miPos = *it;
1517 break;
1518 case mdds::mtm::element_boolean:
1520 boolean_element_block::const_iterator it = boolean_element_block::begin(*node.data);
1521 boolean_element_block::const_iterator itEnd = boolean_element_block::end(*node.data);
1522 for (; it != itEnd; ++it, ++miPos)
1523 *miPos = *it ? 1.0 : 0.0;
1525 break;
1526 case mdds::mtm::element_string:
1528 for (size_t i = 0; i < node.size; ++i, ++miPos)
1529 *miPos = mfNaN;
1531 break;
1532 case mdds::mtm::element_empty:
1534 if (mbEmptyAsZero)
1536 std::advance(miPos, node.size);
1537 return;
1540 for (size_t i = 0; i < node.size; ++i, ++miPos)
1541 *miPos = mfNaN;
1543 break;
1544 default:
1549 void swap(std::vector<double>& rOther)
1551 maArray.swap(rOther);
1555 struct ArrayMul : public std::binary_function<double, double, double>
1557 double operator() (const double& lhs, const double& rhs) const
1559 return lhs * rhs;
1563 template<typename _Op>
1564 class MergeDoubleArrayFunc : std::unary_function<MatrixImplType::element_block_type, void>
1566 std::vector<double>& mrArray;
1567 std::vector<double>::iterator miPos;
1568 double mfNaN;
1569 public:
1570 MergeDoubleArrayFunc(std::vector<double>& rArray) : mrArray(rArray), miPos(mrArray.begin())
1572 rtl::math::setNan(&mfNaN);
1575 void operator() (const MatrixImplType::element_block_node_type& node)
1577 using namespace mdds::mtv;
1578 static _Op op;
1580 switch (node.type)
1582 case mdds::mtm::element_numeric:
1584 numeric_element_block::const_iterator it = numeric_element_block::begin(*node.data);
1585 numeric_element_block::const_iterator itEnd = numeric_element_block::end(*node.data);
1586 for (; it != itEnd; ++it, ++miPos)
1588 if (rtl::math::isNan(*miPos))
1589 continue;
1591 *miPos = op(*miPos, *it);
1594 break;
1595 case mdds::mtm::element_boolean:
1597 boolean_element_block::const_iterator it = boolean_element_block::begin(*node.data);
1598 boolean_element_block::const_iterator itEnd = boolean_element_block::end(*node.data);
1599 for (; it != itEnd; ++it, ++miPos)
1601 if (rtl::math::isNan(*miPos))
1602 continue;
1604 *miPos = op(*miPos, *it ? 1.0 : 0.0);
1607 break;
1608 case mdds::mtm::element_string:
1610 for (size_t i = 0; i < node.size; ++i, ++miPos)
1611 *miPos = mfNaN;
1613 break;
1614 case mdds::mtm::element_empty:
1615 std::advance(miPos, node.size);
1616 default:
1624 ScMatrix::IterateResult ScMatrixImpl::Sum(bool bTextAsZero) const
1626 WalkElementBlocks<SumOp> aFunc(bTextAsZero);
1627 maMat.walk(aFunc);
1628 return aFunc.getResult();
1631 ScMatrix::IterateResult ScMatrixImpl::SumSquare(bool bTextAsZero) const
1633 WalkElementBlocks<SumSquareOp> aFunc(bTextAsZero);
1634 maMat.walk(aFunc);
1635 return aFunc.getResult();
1638 ScMatrix::IterateResult ScMatrixImpl::Product(bool bTextAsZero) const
1640 WalkElementBlocks<ProductOp> aFunc(bTextAsZero);
1641 maMat.walk(aFunc);
1642 ScMatrix::IterateResult aRes = aFunc.getResult();
1643 return aRes;
1646 size_t ScMatrixImpl::Count(bool bCountStrings) const
1648 CountElements aFunc(bCountStrings);
1649 maMat.walk(aFunc);
1650 return aFunc.getCount();
1653 size_t ScMatrixImpl::MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const
1655 WalkAndMatchElements<double> aFunc(fValue, maMat.size(), nCol1, nCol2);
1656 maMat.walk(aFunc);
1657 return aFunc.getMatching();
1660 size_t ScMatrixImpl::MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const
1662 WalkAndMatchElements<svl::SharedString> aFunc(rStr, maMat.size(), nCol1, nCol2);
1663 maMat.walk(aFunc);
1664 return aFunc.getMatching();
1667 double ScMatrixImpl::GetMaxValue( bool bTextAsZero ) const
1669 CalcMaxMinValue<MaxOp> aFunc(bTextAsZero);
1670 maMat.walk(aFunc);
1671 return aFunc.getValue();
1674 double ScMatrixImpl::GetMinValue( bool bTextAsZero ) const
1676 CalcMaxMinValue<MinOp> aFunc(bTextAsZero);
1677 maMat.walk(aFunc);
1678 return aFunc.getValue();
1681 ScMatrixRef ScMatrixImpl::CompareMatrix(
1682 sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const
1684 MatrixImplType::size_pair_type aSize = maMat.size();
1685 size_t nSize = aSize.column * aSize.row;
1686 if (nMatPos == 0)
1688 if (rComp.maCells[1].mbValue && !rComp.maCells[1].mbEmpty)
1690 // Matrix on the left, and a numeric value on the right. Use a
1691 // function object that has much less branching for much better
1692 // performance.
1693 CompareMatrixToNumericFunc aFunc(nSize, rComp, rComp.maCells[1].mfValue, pOptions);
1694 maMat.walk(aFunc);
1696 // We assume the result matrix has the same dimension as this matrix.
1697 const std::vector<bool>& rResVal = aFunc.getValues();
1698 if (nSize != rResVal.size())
1699 ScMatrixRef();
1701 return ScMatrixRef(new ScMatrix(aSize.column, aSize.row, rResVal));
1705 CompareMatrixFunc aFunc(nSize, rComp, nMatPos, pOptions);
1706 maMat.walk(aFunc);
1708 // We assume the result matrix has the same dimension as this matrix.
1709 const std::vector<bool>& rResVal = aFunc.getValues();
1710 if (nSize != rResVal.size())
1711 ScMatrixRef();
1713 return ScMatrixRef(new ScMatrix(aSize.column, aSize.row, rResVal));
1716 void ScMatrixImpl::GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const
1718 MatrixImplType::size_pair_type aSize = maMat.size();
1719 ToDoubleArray aFunc(aSize.row*aSize.column, bEmptyAsZero);
1720 maMat.walk(aFunc);
1721 aFunc.swap(rArray);
1724 void ScMatrixImpl::MergeDoubleArray( std::vector<double>& rArray, ScMatrix::Op eOp ) const
1726 MatrixImplType::size_pair_type aSize = maMat.size();
1727 size_t nSize = aSize.row*aSize.column;
1728 if (nSize != rArray.size())
1729 return;
1731 switch (eOp)
1733 case ScMatrix::Mul:
1735 MergeDoubleArrayFunc<ArrayMul> aFunc(rArray);
1736 maMat.walk(aFunc);
1738 break;
1739 default:
1744 void ScMatrixImpl::AddValues( const ScMatrixImpl& rMat )
1746 const MatrixImplType& rOther = rMat.maMat;
1747 MatrixImplType::size_pair_type aSize = maMat.size();
1748 if (aSize != rOther.size())
1749 // Geometry must match.
1750 return;
1752 // For now, we only add two matricies if and only if 1) the receiving
1753 // matrix consists only of one numeric block, and 2) the other matrix
1754 // consists of either one numeric block or one boolean block. In the
1755 // future, we may want to be more flexible support matricies that consist
1756 // of multiple blocks.
1758 MatrixImplType::position_type aPos1 = maMat.position(0, 0);
1759 MatrixImplType::const_position_type aPos2 = rOther.position(0, 0);
1760 if (MatrixImplType::to_mtm_type(aPos1.first->type) != mdds::mtm::element_numeric)
1761 return;
1763 if (aPos1.first->size != aPos2.first->size)
1764 return;
1766 if (aPos1.first->size != aSize.row * aSize.column)
1767 return;
1769 MatrixImplType::numeric_block_type::iterator it =
1770 MatrixImplType::numeric_block_type::begin(*aPos1.first->data);
1771 MatrixImplType::numeric_block_type::iterator itEnd =
1772 MatrixImplType::numeric_block_type::end(*aPos1.first->data);
1774 switch (MatrixImplType::to_mtm_type(aPos2.first->type))
1776 case mdds::mtm::element_boolean:
1778 MatrixImplType::boolean_block_type::iterator it2 =
1779 MatrixImplType::boolean_block_type::begin(*aPos2.first->data);
1781 for (; it != itEnd; ++it, ++it2)
1782 *it += *it2;
1784 break;
1785 case mdds::mtm::element_numeric:
1787 MatrixImplType::numeric_block_type::iterator it2 =
1788 MatrixImplType::numeric_block_type::begin(*aPos2.first->data);
1790 for (; it != itEnd; ++it, ++it2)
1791 *it += *it2;
1793 break;
1794 default:
1799 #if DEBUG_MATRIX
1800 void ScMatrixImpl::Dump() const
1802 cout << "-- matrix content" << endl;
1803 SCSIZE nCols, nRows;
1804 GetDimensions(nCols, nRows);
1805 for (SCSIZE nRow = 0; nRow < nRows; ++nRow)
1807 for (SCSIZE nCol = 0; nCol < nCols; ++nCol)
1809 cout << " row=" << nRow << ", col=" << nCol << " : ";
1810 switch (maMat.get_type(nRow, nCol))
1812 case mdds::mtm::element_string:
1813 cout << "string (" << maMat.get_string(nRow, nCol).getString() << ")";
1814 break;
1815 case mdds::mtm::element_numeric:
1816 cout << "numeric (" << maMat.get_numeric(nRow, nCol) << ")";
1817 break;
1818 case mdds::mtm::element_boolean:
1819 cout << "boolean (" << maMat.get_boolean(nRow, nCol) << ")";
1820 break;
1821 case mdds::mtm::element_empty:
1822 cout << "empty";
1823 break;
1824 default:
1828 cout << endl;
1832 #endif
1834 void ScMatrixImpl::CalcPosition(SCSIZE nIndex, SCSIZE& rC, SCSIZE& rR) const
1836 SCSIZE nRowSize = maMat.size().row;
1837 SAL_WARN_IF( !nRowSize, "sc", "ScMatrixImpl::CalcPosition: 0 rows!");
1838 rC = nRowSize > 1 ? nIndex / nRowSize : nIndex;
1839 rR = nIndex - rC*nRowSize;
1842 void ScMatrix::IncRef() const
1844 ++nRefCnt;
1847 void ScMatrix::DecRef() const
1849 --nRefCnt;
1850 if (nRefCnt == 0)
1851 delete this;
1854 ScMatrix::ScMatrix( SCSIZE nC, SCSIZE nR) :
1855 pImpl(new ScMatrixImpl(nC, nR)), nRefCnt(0)
1857 SAL_WARN_IF( !nC, "sc", "ScMatrix with 0 columns!");
1858 SAL_WARN_IF( !nR, "sc", "ScMatrix with 0 rows!");
1861 ScMatrix::ScMatrix(SCSIZE nC, SCSIZE nR, double fInitVal) :
1862 pImpl(new ScMatrixImpl(nC, nR, fInitVal)), nRefCnt(0)
1864 SAL_WARN_IF( !nC, "sc", "ScMatrix with 0 columns!");
1865 SAL_WARN_IF( !nR, "sc", "ScMatrix with 0 rows!");
1868 ScMatrix::ScMatrix( size_t nC, size_t nR, const std::vector<bool>& rInitVals ) :
1869 pImpl(new ScMatrixImpl(nC, nR, rInitVals)), nRefCnt(0)
1871 SAL_WARN_IF( !nC, "sc", "ScMatrix with 0 columns!");
1872 SAL_WARN_IF( !nR, "sc", "ScMatrix with 0 rows!");
1875 ScMatrix::~ScMatrix()
1877 delete pImpl;
1880 ScMatrix* ScMatrix::Clone() const
1882 SCSIZE nC, nR;
1883 pImpl->GetDimensions(nC, nR);
1884 ScMatrix* pScMat = new ScMatrix(nC, nR);
1885 MatCopy(*pScMat);
1886 pScMat->SetErrorInterpreter(pImpl->GetErrorInterpreter()); // TODO: really?
1887 return pScMat;
1890 ScMatrix* ScMatrix::CloneIfConst()
1892 return pImpl->IsImmutable() ? Clone() : this;
1895 void ScMatrix::SetImmutable( bool bVal )
1897 pImpl->SetImmutable(bVal);
1900 void ScMatrix::Resize( SCSIZE nC, SCSIZE nR)
1902 pImpl->Resize(nC, nR);
1905 void ScMatrix::Resize(SCSIZE nC, SCSIZE nR, double fVal)
1907 pImpl->Resize(nC, nR, fVal);
1910 ScMatrix* ScMatrix::CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const
1912 ScMatrix* pScMat = new ScMatrix(nNewCols, nNewRows);
1913 MatCopy(*pScMat);
1914 pScMat->SetErrorInterpreter(pImpl->GetErrorInterpreter());
1915 return pScMat;
1918 void ScMatrix::SetErrorInterpreter( ScInterpreter* p)
1920 pImpl->SetErrorInterpreter(p);
1923 void ScMatrix::GetDimensions( SCSIZE& rC, SCSIZE& rR) const
1925 pImpl->GetDimensions(rC, rR);
1928 SCSIZE ScMatrix::GetElementCount() const
1930 return pImpl->GetElementCount();
1933 bool ScMatrix::ValidColRow( SCSIZE nC, SCSIZE nR) const
1935 return pImpl->ValidColRow(nC, nR);
1938 bool ScMatrix::ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const
1940 return pImpl->ValidColRowReplicated(rC, rR);
1943 bool ScMatrix::ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const
1945 return ValidColRow( rC, rR) || ValidColRowReplicated( rC, rR);
1948 void ScMatrix::PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
1950 pImpl->PutDouble(fVal, nC, nR);
1953 void ScMatrix::PutDouble( double fVal, SCSIZE nIndex)
1955 pImpl->PutDouble(fVal, nIndex);
1958 void ScMatrix::PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
1960 pImpl->PutDouble(pArray, nLen, nC, nR);
1963 void ScMatrix::PutString(const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR)
1965 pImpl->PutString(rStr, nC, nR);
1968 void ScMatrix::PutString(const svl::SharedString& rStr, SCSIZE nIndex)
1970 pImpl->PutString(rStr, nIndex);
1973 void ScMatrix::PutString(const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR)
1975 pImpl->PutString(pArray, nLen, nC, nR);
1978 void ScMatrix::PutEmpty(SCSIZE nC, SCSIZE nR)
1980 pImpl->PutEmpty(nC, nR);
1983 void ScMatrix::PutEmptyPath(SCSIZE nC, SCSIZE nR)
1985 pImpl->PutEmptyPath(nC, nR);
1988 void ScMatrix::PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR )
1990 pImpl->PutError(nErrorCode, nC, nR);
1993 void ScMatrix::PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
1995 pImpl->PutBoolean(bVal, nC, nR);
1998 sal_uInt16 ScMatrix::GetError( SCSIZE nC, SCSIZE nR) const
2000 return pImpl->GetError(nC, nR);
2003 double ScMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const
2005 return pImpl->GetDouble(nC, nR);
2008 double ScMatrix::GetDouble( SCSIZE nIndex) const
2010 return pImpl->GetDouble(nIndex);
2013 svl::SharedString ScMatrix::GetString(SCSIZE nC, SCSIZE nR) const
2015 return pImpl->GetString(nC, nR);
2018 svl::SharedString ScMatrix::GetString( SCSIZE nIndex) const
2020 return pImpl->GetString(nIndex);
2023 svl::SharedString ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
2025 return pImpl->GetString(rFormatter, nC, nR);
2028 ScMatrixValue ScMatrix::Get(SCSIZE nC, SCSIZE nR) const
2030 return pImpl->Get(nC, nR);
2033 sal_Bool ScMatrix::IsString( SCSIZE nIndex ) const
2035 return pImpl->IsString(nIndex);
2038 sal_Bool ScMatrix::IsString( SCSIZE nC, SCSIZE nR ) const
2040 return pImpl->IsString(nC, nR);
2043 sal_Bool ScMatrix::IsEmpty( SCSIZE nC, SCSIZE nR ) const
2045 return pImpl->IsEmpty(nC, nR);
2048 sal_Bool ScMatrix::IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
2050 return pImpl->IsEmptyPath(nC, nR);
2053 sal_Bool ScMatrix::IsValue( SCSIZE nIndex ) const
2055 return pImpl->IsValue(nIndex);
2058 sal_Bool ScMatrix::IsValue( SCSIZE nC, SCSIZE nR ) const
2060 return pImpl->IsValue(nC, nR);
2063 sal_Bool ScMatrix::IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
2065 return pImpl->IsValueOrEmpty(nC, nR);
2068 sal_Bool ScMatrix::IsBoolean( SCSIZE nC, SCSIZE nR ) const
2070 return pImpl->IsBoolean(nC, nR);
2073 sal_Bool ScMatrix::IsNumeric() const
2075 return pImpl->IsNumeric();
2078 void ScMatrix::MatCopy(ScMatrix& mRes) const
2080 pImpl->MatCopy(*mRes.pImpl);
2083 void ScMatrix::MatTrans(ScMatrix& mRes) const
2085 pImpl->MatTrans(*mRes.pImpl);
2088 void ScMatrix::FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 )
2090 pImpl->FillDouble(fVal, nC1, nR1, nC2, nR2);
2093 void ScMatrix::PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR )
2095 pImpl->PutDoubleVector(rVec, nC, nR);
2098 void ScMatrix::PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR )
2100 pImpl->PutStringVector(rVec, nC, nR);
2103 void ScMatrix::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
2105 pImpl->PutEmptyVector(nCount, nC, nR);
2108 void ScMatrix::PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR )
2110 pImpl->PutEmptyPathVector(nCount, nC, nR);
2113 void ScMatrix::CompareEqual()
2115 pImpl->CompareEqual();
2118 void ScMatrix::CompareNotEqual()
2120 pImpl->CompareNotEqual();
2123 void ScMatrix::CompareLess()
2125 pImpl->CompareLess();
2128 void ScMatrix::CompareGreater()
2130 pImpl->CompareGreater();
2133 void ScMatrix::CompareLessEqual()
2135 pImpl->CompareLessEqual();
2138 void ScMatrix::CompareGreaterEqual()
2140 pImpl->CompareGreaterEqual();
2143 double ScMatrix::And() const
2145 return pImpl->And();
2148 double ScMatrix::Or() const
2150 return pImpl->Or();
2153 double ScMatrix::Xor() const
2155 return pImpl->Xor();
2158 ScMatrix::IterateResult ScMatrix::Sum(bool bTextAsZero) const
2160 return pImpl->Sum(bTextAsZero);
2163 ScMatrix::IterateResult ScMatrix::SumSquare(bool bTextAsZero) const
2165 return pImpl->SumSquare(bTextAsZero);
2168 ScMatrix::IterateResult ScMatrix::Product(bool bTextAsZero) const
2170 return pImpl->Product(bTextAsZero);
2173 size_t ScMatrix::Count(bool bCountStrings) const
2175 return pImpl->Count(bCountStrings);
2178 size_t ScMatrix::MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const
2180 return pImpl->MatchDoubleInColumns(fValue, nCol1, nCol2);
2183 size_t ScMatrix::MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const
2185 return pImpl->MatchStringInColumns(rStr, nCol1, nCol2);
2188 double ScMatrix::GetMaxValue( bool bTextAsZero ) const
2190 return pImpl->GetMaxValue(bTextAsZero);
2193 double ScMatrix::GetMinValue( bool bTextAsZero ) const
2195 return pImpl->GetMinValue(bTextAsZero);
2198 ScMatrixRef ScMatrix::CompareMatrix(
2199 sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const
2201 return pImpl->CompareMatrix(rComp, nMatPos, pOptions);
2204 void ScMatrix::GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero ) const
2206 pImpl->GetDoubleArray(rArray, bEmptyAsZero);
2209 void ScMatrix::MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const
2211 pImpl->MergeDoubleArray(rArray, eOp);
2214 ScMatrix& ScMatrix::operator+= ( const ScMatrix& r )
2216 pImpl->AddValues(*r.pImpl);
2217 return *this;
2220 #if DEBUG_MATRIX
2221 void ScMatrix::Dump() const
2223 pImpl->Dump();
2225 #endif
2227 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */