1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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>
38 #include <mdds/multi_type_matrix.hpp>
39 #include <mdds/multi_type_vector_types.hpp>
40 #include <mdds/multi_type_vector_trait.hpp>
49 using ::std::for_each
;
50 using ::std::count_if
;
52 using ::std::unary_function
;
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
;
72 struct ElemEqualZero
: public unary_function
<double, bool>
74 bool operator() (double val
) const
80 struct ElemNotEqualZero
: public unary_function
<double, bool>
82 bool operator() (double val
) const
88 struct ElemGreaterZero
: public unary_function
<double, bool>
90 bool operator() (double val
) const
96 struct ElemLessZero
: public unary_function
<double, bool>
98 bool operator() (double val
) const
104 struct ElemGreaterEqualZero
: public unary_function
<double, bool>
106 bool operator() (double val
) const
112 struct ElemLessEqualZero
: public unary_function
<double, bool>
114 bool operator() (double val
) const
120 template<typename _Comp
>
121 class CompareMatrixElemFunc
: std::unary_function
<MatrixImplType::element_block_node_type
, void>
125 std::vector
<bool> maNewMatValues
;
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
)
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
)
147 if (!rtl::math::isFinite(fVal
))
149 /* FIXME: this silently skips an error instead of propagating it! */
150 maNewMatValues
.push_back(false);
154 maNewMatValues
.push_back(maComp(fVal
));
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
));
171 case mdds::mtm::element_string
:
172 case mdds::mtm::element_empty
:
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());
186 template<typename _Comp
>
187 _Comp CompareMatrixElemFunc
<_Comp
>::maComp
;
193 MatrixImplType maMat
;
194 MatrixImplType maMatFlag
;
195 ScInterpreter
* pErrorInterpreter
;
196 bool mbCloneIfConst
; // Whether the matrix is cloned with a CloneIfConst() call.
199 ScMatrixImpl(const ScMatrixImpl
&);
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
);
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
);
260 void CompareNotEqual();
262 void CompareGreater();
263 void CompareLessEqual();
264 void CompareGreaterEqual();
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
);
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()
307 void ScMatrixImpl::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();
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)
368 else if (aSize
.column
== 1 && rR
< aSize
.row
)
370 // single column matrix.
374 else if (aSize
.row
== 1 && rC
< aSize
.column
)
376 // single row matrix.
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
);
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
);
410 OSL_FAIL("ScMatrixImpl::PutDouble: dimension error");
414 void ScMatrixImpl::PutDouble( double fVal
, SCSIZE nIndex
)
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
);
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
);
437 OSL_FAIL("ScMatrixImpl::PutString: dimension error");
441 void ScMatrixImpl::PutString(const svl::SharedString
& rStr
, SCSIZE nIndex
)
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'.
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'.
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
);
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
);
498 OSL_FAIL("ScMatrixImpl::GetError: dimension error");
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
);
512 SetErrorAtInterpreter( nError
);
518 OSL_FAIL("ScMatrixImpl::GetDouble: dimension error");
519 return CreateDoubleError( errNoValue
);
523 double ScMatrixImpl::GetDouble( SCSIZE nIndex
) const
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
))
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
);
547 OSL_FAIL("ScMatrixImpl::GetString: access error, no string");
549 SetErrorAtInterpreter(GetDoubleErrorValue(fErr
));
553 OSL_FAIL("ScMatrixImpl::GetString: dimension error");
555 return svl::SharedString::getEmptyString();
558 svl::SharedString
ScMatrixImpl::GetString( SCSIZE nIndex
) const
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");
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.
585 // result of empty FALSE jump path
586 sal_uLong nKey
= rFormatter
.GetStandardFormat( NUMBERFORMAT_LOGICAL
,
589 Color
* pColor
= NULL
;
590 rFormatter
.GetOutputString( 0.0, nKey
, aStr
, &pColor
);
593 case mdds::mtm::element_numeric
:
594 case mdds::mtm::element_boolean
:
595 fVal
= maMat
.get_numeric(aPos
);
601 sal_uInt16 nError
= GetDoubleErrorValue(fVal
);
604 SetErrorAtInterpreter( nError
);
605 return ScGlobal::GetErrorString( nError
);
608 sal_uLong nKey
= rFormatter
.GetStandardFormat( NUMBERFORMAT_NUMBER
,
611 rFormatter
.GetInputLineString( fVal
, nKey
, aStr
);
615 ScMatrixValue
ScMatrixImpl::Get(SCSIZE nC
, SCSIZE nR
) const
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
);
624 case mdds::mtm::element_boolean
:
625 aVal
.nType
= SC_MATVAL_BOOLEAN
;
626 aVal
.fVal
= maMat
.get_boolean(aPos
);
628 case mdds::mtm::element_numeric
:
629 aVal
.nType
= SC_MATVAL_VALUE
;
630 aVal
.fVal
= maMat
.get_numeric(aPos
);
632 case mdds::mtm::element_string
:
633 aVal
.nType
= SC_MATVAL_STRING
;
634 aVal
.aStr
= maMat
.get_string(aPos
);
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
;
646 OSL_FAIL("ScMatrixImpl::Get: dimension error");
651 bool ScMatrixImpl::IsString( SCSIZE nIndex
) const
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
:
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
);
689 bool ScMatrixImpl::IsValue( SCSIZE nIndex
) const
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
:
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
:
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");
745 mRes
.maMat
.copy(maMat
);
748 void ScMatrixImpl::MatTrans(ScMatrixImpl
& mRes
) const
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());
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());
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());
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());
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());
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
);
833 void ScMatrixImpl::CompareNotEqual()
835 MatrixImplType::size_pair_type aSize
= maMat
.size();
836 CompareMatrixElemFunc
<ElemNotEqualZero
> aFunc(aSize
.row
, aSize
.column
);
841 void ScMatrixImpl::CompareLess()
843 MatrixImplType::size_pair_type aSize
= maMat
.size();
844 CompareMatrixElemFunc
<ElemLessZero
> aFunc(aSize
.row
, aSize
.column
);
849 void ScMatrixImpl::CompareGreater()
851 MatrixImplType::size_pair_type aSize
= maMat
.size();
852 CompareMatrixElemFunc
<ElemGreaterZero
> aFunc(aSize
.row
, aSize
.column
);
857 void ScMatrixImpl::CompareLessEqual()
859 MatrixImplType::size_pair_type aSize
= maMat
.size();
860 CompareMatrixElemFunc
<ElemLessEqualZero
> aFunc(aSize
.row
, aSize
.column
);
865 void ScMatrixImpl::CompareGreaterEqual()
867 MatrixImplType::size_pair_type aSize
= maMat
.size();
868 CompareMatrixElemFunc
<ElemGreaterEqualZero
> aFunc(aSize
.row
, aSize
.column
);
878 void operate(double fVal
) { mbResult
&= (fVal
!= 0.0); }
879 bool result() const { return mbResult
; }
880 AndEvaluator() : mbResult(true) {}
886 void operate(double fVal
) { mbResult
|= (fVal
!= 0.0); }
887 bool result() const { return mbResult
; }
888 OrEvaluator() : mbResult(false) {}
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
)
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
))
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
);
954 static const int InitVal
= 0;
956 void operator() (double& rAccum
, double fVal
)
964 static const int InitVal
= 0;
966 void operator() (double& rAccum
, double fVal
)
974 static const int InitVal
= 1;
976 void operator() (double& rAccum
, double fVal
)
982 template<typename _Op
>
983 class WalkElementBlocks
: std::unary_function
<MatrixImplType::element_block_node_type
, void>
987 ScMatrix::IterateResult maRes
;
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
)
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
)
1009 maOp(maRes
.mfFirst
, *it
);
1013 maOp(maRes
.mfRest
, *it
);
1015 maRes
.mnCount
+= node
.size
;
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
)
1028 maOp(maRes
.mfFirst
, *it
);
1032 maOp(maRes
.mfRest
, *it
);
1034 maRes
.mnCount
+= node
.size
;
1037 case mdds::mtm::element_string
:
1039 maRes
.mnCount
+= node
.size
;
1041 case mdds::mtm::element_empty
:
1048 class CountElements
: std::unary_function
<MatrixImplType::element_block_node_type
, void>
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
)
1061 case mdds::mtm::element_numeric
:
1062 case mdds::mtm::element_boolean
:
1063 mnCount
+= node
.size
;
1065 case mdds::mtm::element_string
:
1067 mnCount
+= node
.size
;
1069 case mdds::mtm::element_empty
:
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>
1082 MatrixImplType::size_pair_type maSize
;
1089 WalkAndMatchElements(_Type aMatchValue
, const MatrixImplType::size_pair_type
& aSize
, size_t nCol1
, size_t nCol2
) :
1090 maMatchValue(aMatchValue
),
1094 mnResult(ResultNotSet
),
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
)
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
;
1118 size_t WalkAndMatchElements
<double>::compare(const MatrixImplType::element_block_node_type
& node
) const
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
;
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
;
1154 case mdds::mtm::element_string
:
1155 case mdds::mtm::element_empty
:
1159 return ResultNotSet
;
1163 size_t WalkAndMatchElements
<svl::SharedString
>::compare(const MatrixImplType::element_block_node_type
& node
) const
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
;
1183 case mdds::mtm::element_boolean
:
1184 case mdds::mtm::element_numeric
:
1185 case mdds::mtm::element_empty
:
1189 return ResultNotSet
;
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;
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>
1234 CalcMaxMinValue( bool bTextAsZero
) :
1236 mbTextAsZero(bTextAsZero
) {}
1238 double getValue() const { return mfVal
; }
1240 void operator() (const MatrixImplType::element_block_node_type
& node
)
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
);
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
);
1265 case mdds::mtm::element_string
:
1266 case mdds::mtm::element_empty
:
1268 // empty elements are treated as empty strings.
1270 mfVal
= _Op::compare(mfVal
, 0.0);
1279 inline bool evaluate( double fVal
, ScQueryOp eOp
)
1293 case SC_GREATER_EQUAL
:
1303 OSL_TRACE( "evaluate: unhandled comparison operator: %d", (int)eOp
);
1307 class CompareMatrixFunc
: std::unary_function
<MatrixImplType::element_block_type
, void>
1309 sc::Compare
& mrComp
;
1311 sc::CompareOptions
* mpOptions
;
1312 std::vector
<bool> maResValues
;
1316 double fVal
= sc::CompareFunc(mrComp
.maCells
[0], mrComp
.maCells
[1], mrComp
.mbIgnoreCase
, mpOptions
);
1317 maResValues
.push_back(evaluate(fVal
, mrComp
.meOp
));
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
];
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
;
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
;
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;
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
)
1392 const std::vector
<bool>& getValues() const
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
;
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
);
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];
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
);
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
);
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;
1476 case mdds::mtm::element_empty
:
1477 compareLeftEmpty(node
.size
);
1484 const std::vector
<bool>& getValues() const
1490 class ToDoubleArray
: std::unary_function
<MatrixImplType::element_block_type
, void>
1492 std::vector
<double> maArray
;
1493 std::vector
<double>::iterator miPos
;
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
;
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
)
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;
1526 case mdds::mtm::element_string
:
1528 for (size_t i
= 0; i
< node
.size
; ++i
, ++miPos
)
1532 case mdds::mtm::element_empty
:
1536 std::advance(miPos
, node
.size
);
1540 for (size_t i
= 0; i
< node
.size
; ++i
, ++miPos
)
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
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
;
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
;
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
))
1591 *miPos
= op(*miPos
, *it
);
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
))
1604 *miPos
= op(*miPos
, *it
? 1.0 : 0.0);
1608 case mdds::mtm::element_string
:
1610 for (size_t i
= 0; i
< node
.size
; ++i
, ++miPos
)
1614 case mdds::mtm::element_empty
:
1615 std::advance(miPos
, node
.size
);
1624 ScMatrix::IterateResult
ScMatrixImpl::Sum(bool bTextAsZero
) const
1626 WalkElementBlocks
<SumOp
> aFunc(bTextAsZero
);
1628 return aFunc
.getResult();
1631 ScMatrix::IterateResult
ScMatrixImpl::SumSquare(bool bTextAsZero
) const
1633 WalkElementBlocks
<SumSquareOp
> aFunc(bTextAsZero
);
1635 return aFunc
.getResult();
1638 ScMatrix::IterateResult
ScMatrixImpl::Product(bool bTextAsZero
) const
1640 WalkElementBlocks
<ProductOp
> aFunc(bTextAsZero
);
1642 ScMatrix::IterateResult aRes
= aFunc
.getResult();
1646 size_t ScMatrixImpl::Count(bool bCountStrings
) const
1648 CountElements
aFunc(bCountStrings
);
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
);
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
);
1664 return aFunc
.getMatching();
1667 double ScMatrixImpl::GetMaxValue( bool bTextAsZero
) const
1669 CalcMaxMinValue
<MaxOp
> aFunc(bTextAsZero
);
1671 return aFunc
.getValue();
1674 double ScMatrixImpl::GetMinValue( bool bTextAsZero
) const
1676 CalcMaxMinValue
<MinOp
> aFunc(bTextAsZero
);
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
;
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
1693 CompareMatrixToNumericFunc
aFunc(nSize
, rComp
, rComp
.maCells
[1].mfValue
, pOptions
);
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())
1701 return ScMatrixRef(new ScMatrix(aSize
.column
, aSize
.row
, rResVal
));
1705 CompareMatrixFunc
aFunc(nSize
, rComp
, nMatPos
, pOptions
);
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())
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
);
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())
1735 MergeDoubleArrayFunc
<ArrayMul
> aFunc(rArray
);
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.
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
)
1763 if (aPos1
.first
->size
!= aPos2
.first
->size
)
1766 if (aPos1
.first
->size
!= aSize
.row
* aSize
.column
)
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
)
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
)
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() << ")";
1815 case mdds::mtm::element_numeric
:
1816 cout
<< "numeric (" << maMat
.get_numeric(nRow
, nCol
) << ")";
1818 case mdds::mtm::element_boolean
:
1819 cout
<< "boolean (" << maMat
.get_boolean(nRow
, nCol
) << ")";
1821 case mdds::mtm::element_empty
:
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
1847 void ScMatrix::DecRef() const
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()
1880 ScMatrix
* ScMatrix::Clone() const
1883 pImpl
->GetDimensions(nC
, nR
);
1884 ScMatrix
* pScMat
= new ScMatrix(nC
, nR
);
1886 pScMat
->SetErrorInterpreter(pImpl
->GetErrorInterpreter()); // TODO: really?
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
);
1914 pScMat
->SetErrorInterpreter(pImpl
->GetErrorInterpreter());
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
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
);
2221 void ScMatrix::Dump() const
2227 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */