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"
29 #include <boost/noncopyable.hpp>
30 #include <svl/zforlist.hxx>
31 #include <svl/sharedstring.hxx>
32 #include <tools/stream.hxx>
33 #include <rtl/math.hxx>
40 #include <mdds/multi_type_matrix.hpp>
41 #include <mdds/multi_type_vector_types.hpp>
42 #include <mdds/multi_type_vector_trait.hpp>
51 using ::std::for_each
;
52 using ::std::count_if
;
54 using ::std::unary_function
;
57 * Custom string trait struct to tell mdds::multi_type_matrix about the
58 * custom string type and how to handle blocks storing them.
60 struct custom_string_trait
62 typedef svl::SharedString string_type
;
63 typedef sc::string_block string_element_block
;
65 static const mdds::mtv::element_t string_type_identifier
= sc::element_type_string
;
67 typedef mdds::mtv::custom_block_func1
<sc::string_block
> element_block_func
;
70 typedef mdds::multi_type_matrix
<custom_string_trait
> MatrixImplType
;
74 struct ElemEqualZero
: public unary_function
<double, double>
76 double operator() (double val
) const
78 if (!::rtl::math::isFinite(val
))
80 return val
== 0.0 ? 1.0 : 0.0;
84 struct ElemNotEqualZero
: public unary_function
<double, double>
86 double operator() (double val
) const
88 if (!::rtl::math::isFinite(val
))
90 return val
!= 0.0 ? 1.0 : 0.0;
94 struct ElemGreaterZero
: public unary_function
<double, double>
96 double operator() (double val
) const
98 if (!::rtl::math::isFinite(val
))
100 return val
> 0.0 ? 1.0 : 0.0;
104 struct ElemLessZero
: public unary_function
<double, double>
106 double operator() (double val
) const
108 if (!::rtl::math::isFinite(val
))
110 return val
< 0.0 ? 1.0 : 0.0;
114 struct ElemGreaterEqualZero
: public unary_function
<double, double>
116 double operator() (double val
) const
118 if (!::rtl::math::isFinite(val
))
120 return val
>= 0.0 ? 1.0 : 0.0;
124 struct ElemLessEqualZero
: public unary_function
<double, double>
126 double operator() (double val
) const
128 if (!::rtl::math::isFinite(val
))
130 return val
<= 0.0 ? 1.0 : 0.0;
134 template<typename _Comp
>
135 class CompareMatrixElemFunc
: std::unary_function
<MatrixImplType::element_block_node_type
, void>
139 std::vector
<double> maNewMatValues
; // double instead of bool to transport error values
143 CompareMatrixElemFunc( size_t nRow
, size_t nCol
) : mnRow(nRow
), mnCol(nCol
)
145 maNewMatValues
.reserve(nRow
*nCol
);
148 void operator() (const MatrixImplType::element_block_node_type
& node
)
152 case mdds::mtm::element_numeric
:
154 typedef MatrixImplType::numeric_block_type block_type
;
156 block_type::const_iterator it
= block_type::begin(*node
.data
);
157 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
158 for (; it
!= itEnd
; ++it
)
161 maNewMatValues
.push_back(maComp(fVal
));
165 case mdds::mtm::element_boolean
:
167 typedef MatrixImplType::boolean_block_type block_type
;
169 block_type::const_iterator it
= block_type::begin(*node
.data
);
170 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
171 for (; it
!= itEnd
; ++it
)
173 double fVal
= *it
? 1.0 : 0.0;
174 maNewMatValues
.push_back(maComp(fVal
));
178 case mdds::mtm::element_string
:
179 case mdds::mtm::element_empty
:
181 // Fill it with false.
182 maNewMatValues
.resize(maNewMatValues
.size() + node
.size
, 0.0);
186 void swap( MatrixImplType
& rMat
)
188 MatrixImplType
aNewMat(mnRow
, mnCol
, maNewMatValues
.begin(), maNewMatValues
.end());
193 template<typename _Comp
>
194 _Comp CompareMatrixElemFunc
<_Comp
>::maComp
;
198 /* TODO: it would be good if mdds had get/set<sal_uInt8> additionally to
199 * get/set<bool>, we're abusing double here. */
200 typedef double TMatFlag
;
201 const TMatFlag SC_MATFLAG_EMPTYCELL
= 0.0;
202 const TMatFlag SC_MATFLAG_EMPTYRESULT
= 1.0;
203 const TMatFlag SC_MATFLAG_EMPTYPATH
= 2.0;
205 class ScMatrixImpl
: private boost::noncopyable
207 MatrixImplType maMat
;
208 MatrixImplType maMatFlag
;
209 ScInterpreter
* pErrorInterpreter
;
210 bool mbCloneIfConst
; // Whether the matrix is cloned with a CloneIfConst() call.
213 ScMatrixImpl(SCSIZE nC
, SCSIZE nR
);
214 ScMatrixImpl(SCSIZE nC
, SCSIZE nR
, double fInitVal
);
216 ScMatrixImpl( size_t nC
, size_t nR
, const std::vector
<double>& rInitVals
);
221 void SetImmutable(bool bVal
);
222 bool IsImmutable() const { return mbCloneIfConst
;}
223 void Resize(SCSIZE nC
, SCSIZE nR
);
224 void Resize(SCSIZE nC
, SCSIZE nR
, double fVal
);
225 void SetErrorInterpreter( ScInterpreter
* p
);
226 ScInterpreter
* GetErrorInterpreter() const { return pErrorInterpreter
; }
228 void GetDimensions( SCSIZE
& rC
, SCSIZE
& rR
) const;
229 SCSIZE
GetElementCount() const;
230 bool ValidColRow( SCSIZE nC
, SCSIZE nR
) const;
231 bool ValidColRowReplicated( SCSIZE
& rC
, SCSIZE
& rR
) const;
232 bool ValidColRowOrReplicated( SCSIZE
& rC
, SCSIZE
& rR
) const;
233 void SetErrorAtInterpreter( sal_uInt16 nError
) const;
235 void PutDouble(double fVal
, SCSIZE nC
, SCSIZE nR
);
236 void PutDouble( double fVal
, SCSIZE nIndex
);
237 void PutDouble(const double* pArray
, size_t nLen
, SCSIZE nC
, SCSIZE nR
);
239 void PutString(const svl::SharedString
& rStr
, SCSIZE nC
, SCSIZE nR
);
240 void PutString(const svl::SharedString
& rStr
, SCSIZE nIndex
);
241 void PutString(const svl::SharedString
* pArray
, size_t nLen
, SCSIZE nC
, SCSIZE nR
);
243 void PutEmpty(SCSIZE nC
, SCSIZE nR
);
244 void PutEmptyPath(SCSIZE nC
, SCSIZE nR
);
245 void PutError( sal_uInt16 nErrorCode
, SCSIZE nC
, SCSIZE nR
);
246 void PutBoolean(bool bVal
, SCSIZE nC
, SCSIZE nR
);
247 sal_uInt16
GetError( SCSIZE nC
, SCSIZE nR
) const;
248 double GetDouble(SCSIZE nC
, SCSIZE nR
) const;
249 double GetDouble( SCSIZE nIndex
) const;
250 svl::SharedString
GetString(SCSIZE nC
, SCSIZE nR
) const;
251 svl::SharedString
GetString( SCSIZE nIndex
) const;
252 svl::SharedString
GetString( SvNumberFormatter
& rFormatter
, SCSIZE nC
, SCSIZE nR
) const;
253 ScMatrixValue
Get(SCSIZE nC
, SCSIZE nR
) const;
254 bool IsString( SCSIZE nIndex
) const;
255 bool IsString( SCSIZE nC
, SCSIZE nR
) const;
256 bool IsEmpty( SCSIZE nC
, SCSIZE nR
) const;
257 bool IsEmptyCell( SCSIZE nC
, SCSIZE nR
) const;
258 bool IsEmptyResult( SCSIZE nC
, SCSIZE nR
) const;
259 bool IsEmptyPath( SCSIZE nC
, SCSIZE nR
) const;
260 bool IsValue( SCSIZE nIndex
) const;
261 bool IsValue( SCSIZE nC
, SCSIZE nR
) const;
262 bool IsValueOrEmpty( SCSIZE nC
, SCSIZE nR
) const;
263 bool IsBoolean( SCSIZE nC
, SCSIZE nR
) const;
264 bool IsNumeric() const;
266 void MatCopy(ScMatrixImpl
& mRes
) const;
267 void MatTrans(ScMatrixImpl
& mRes
) const;
268 void FillDouble( double fVal
, SCSIZE nC1
, SCSIZE nR1
, SCSIZE nC2
, SCSIZE nR2
);
269 void PutDoubleVector( const ::std::vector
< double > & rVec
, SCSIZE nC
, SCSIZE nR
);
270 void PutStringVector( const ::std::vector
< svl::SharedString
> & rVec
, SCSIZE nC
, SCSIZE nR
);
271 void PutEmptyVector( SCSIZE nCount
, SCSIZE nC
, SCSIZE nR
);
272 void PutEmptyResultVector( SCSIZE nCount
, SCSIZE nC
, SCSIZE nR
);
273 void PutEmptyPathVector( SCSIZE nCount
, SCSIZE nC
, SCSIZE nR
);
275 void CompareNotEqual();
277 void CompareGreater();
278 void CompareLessEqual();
279 void CompareGreaterEqual();
284 ScMatrix::IterateResult
Sum(bool bTextAsZero
) const;
285 ScMatrix::IterateResult
SumSquare(bool bTextAsZero
) const;
286 ScMatrix::IterateResult
Product(bool bTextAsZero
) const;
287 size_t Count(bool bCountStrings
) const;
288 size_t MatchDoubleInColumns(double fValue
, size_t nCol1
, size_t nCol2
) const;
289 size_t MatchStringInColumns(const svl::SharedString
& rStr
, size_t nCol1
, size_t nCol2
) const;
291 double GetMaxValue( bool bTextAsZero
) const;
292 double GetMinValue( bool bTextAsZero
) const;
294 ScMatrixRef
CompareMatrix( sc::Compare
& rComp
, size_t nMatPos
, sc::CompareOptions
* pOptions
) const;
296 void GetDoubleArray( std::vector
<double>& rArray
, bool bEmptyAsZero
) const;
297 void MergeDoubleArray( std::vector
<double>& rArray
, ScMatrix::Op eOp
) const;
298 void AddValues( const ScMatrixImpl
& rMat
);
301 void ApplyOperation(T aOp
, ScMatrixImpl
& rMat
);
308 void CalcPosition(SCSIZE nIndex
, SCSIZE
& rC
, SCSIZE
& rR
) const;
311 ScMatrixImpl::ScMatrixImpl(SCSIZE nC
, SCSIZE nR
) :
312 maMat(nR
, nC
), maMatFlag(nR
, nC
, SC_MATFLAG_EMPTYCELL
), pErrorInterpreter(NULL
), mbCloneIfConst(true) {}
314 ScMatrixImpl::ScMatrixImpl(SCSIZE nC
, SCSIZE nR
, double fInitVal
) :
315 maMat(nR
, nC
, fInitVal
), maMatFlag(nR
, nC
), pErrorInterpreter(NULL
), mbCloneIfConst(true) {}
317 ScMatrixImpl::ScMatrixImpl( size_t nC
, size_t nR
, const std::vector
<double>& rInitVals
) :
318 maMat(nR
, nC
, rInitVals
.begin(), rInitVals
.end()), maMatFlag(nR
, nC
), pErrorInterpreter(NULL
), mbCloneIfConst(true) {}
320 ScMatrixImpl::~ScMatrixImpl()
325 void ScMatrixImpl::Clear()
331 void ScMatrixImpl::SetImmutable(bool bVal
)
333 mbCloneIfConst
= bVal
;
336 void ScMatrixImpl::Resize(SCSIZE nC
, SCSIZE nR
)
338 maMat
.resize(nR
, nC
);
339 maMatFlag
.resize(nR
, nC
);
342 void ScMatrixImpl::Resize(SCSIZE nC
, SCSIZE nR
, double fVal
)
344 maMat
.resize(nR
, nC
, fVal
);
345 maMatFlag
.resize(nR
, nC
);
348 void ScMatrixImpl::SetErrorInterpreter( ScInterpreter
* p
)
350 pErrorInterpreter
= p
;
353 void ScMatrixImpl::GetDimensions( SCSIZE
& rC
, SCSIZE
& rR
) const
355 MatrixImplType::size_pair_type aSize
= maMat
.size();
360 SCSIZE
ScMatrixImpl::GetElementCount() const
362 MatrixImplType::size_pair_type aSize
= maMat
.size();
363 return aSize
.row
* aSize
.column
;
366 bool ScMatrixImpl::ValidColRow( SCSIZE nC
, SCSIZE nR
) const
368 MatrixImplType::size_pair_type aSize
= maMat
.size();
369 return nR
< aSize
.row
&& nC
< aSize
.column
;
372 bool ScMatrixImpl::ValidColRowReplicated( SCSIZE
& rC
, SCSIZE
& rR
) const
374 MatrixImplType::size_pair_type aSize
= maMat
.size();
375 if (aSize
.column
== 1 && aSize
.row
== 1)
381 else if (aSize
.column
== 1 && rR
< aSize
.row
)
383 // single column matrix.
387 else if (aSize
.row
== 1 && rC
< aSize
.column
)
389 // single row matrix.
396 bool ScMatrixImpl::ValidColRowOrReplicated( SCSIZE
& rC
, SCSIZE
& rR
) const
398 return ValidColRow( rC
, rR
) || ValidColRowReplicated( rC
, rR
);
401 void ScMatrixImpl::SetErrorAtInterpreter( sal_uInt16 nError
) const
403 if ( pErrorInterpreter
)
404 pErrorInterpreter
->SetError( nError
);
407 void ScMatrixImpl::PutDouble(double fVal
, SCSIZE nC
, SCSIZE nR
)
409 if (ValidColRow( nC
, nR
))
410 maMat
.set(nR
, nC
, fVal
);
413 OSL_FAIL("ScMatrixImpl::PutDouble: dimension error");
417 void ScMatrixImpl::PutDouble(const double* pArray
, size_t nLen
, SCSIZE nC
, SCSIZE nR
)
419 if (ValidColRow( nC
, nR
))
420 maMat
.set(nR
, nC
, pArray
, pArray
+ nLen
);
423 OSL_FAIL("ScMatrixImpl::PutDouble: dimension error");
427 void ScMatrixImpl::PutDouble( double fVal
, SCSIZE nIndex
)
430 CalcPosition(nIndex
, nC
, nR
);
431 PutDouble(fVal
, nC
, nR
);
434 void ScMatrixImpl::PutString(const svl::SharedString
& rStr
, SCSIZE nC
, SCSIZE nR
)
436 if (ValidColRow( nC
, nR
))
437 maMat
.set(nR
, nC
, rStr
);
440 OSL_FAIL("ScMatrixImpl::PutString: dimension error");
444 void ScMatrixImpl::PutString(const svl::SharedString
* pArray
, size_t nLen
, SCSIZE nC
, SCSIZE nR
)
446 if (ValidColRow( nC
, nR
))
447 maMat
.set(nR
, nC
, pArray
, pArray
+ nLen
);
450 OSL_FAIL("ScMatrixImpl::PutString: dimension error");
454 void ScMatrixImpl::PutString(const svl::SharedString
& rStr
, SCSIZE nIndex
)
457 CalcPosition(nIndex
, nC
, nR
);
458 PutString(rStr
, nC
, nR
);
461 void ScMatrixImpl::PutEmpty(SCSIZE nC
, SCSIZE nR
)
463 if (ValidColRow( nC
, nR
))
465 maMat
.set_empty(nR
, nC
);
466 maMatFlag
.set(nR
, nC
, SC_MATFLAG_EMPTYCELL
);
470 OSL_FAIL("ScMatrixImpl::PutEmpty: dimension error");
474 void ScMatrixImpl::PutEmptyPath(SCSIZE nC
, SCSIZE nR
)
476 if (ValidColRow( nC
, nR
))
478 maMat
.set_empty(nR
, nC
);
479 maMatFlag
.set(nR
, nC
, SC_MATFLAG_EMPTYPATH
);
483 OSL_FAIL("ScMatrixImpl::PutEmptyPath: dimension error");
487 void ScMatrixImpl::PutError( sal_uInt16 nErrorCode
, SCSIZE nC
, SCSIZE nR
)
489 maMat
.set(nR
, nC
, CreateDoubleError(nErrorCode
));
492 void ScMatrixImpl::PutBoolean(bool bVal
, SCSIZE nC
, SCSIZE nR
)
494 if (ValidColRow( nC
, nR
))
495 maMat
.set(nR
, nC
, bVal
);
498 OSL_FAIL("ScMatrixImpl::PutBoolean: dimension error");
502 sal_uInt16
ScMatrixImpl::GetError( SCSIZE nC
, SCSIZE nR
) const
504 if (ValidColRowOrReplicated( nC
, nR
))
506 double fVal
= maMat
.get_numeric(nR
, nC
);
507 return GetDoubleErrorValue(fVal
);
511 OSL_FAIL("ScMatrixImpl::GetError: dimension error");
516 double ScMatrixImpl::GetDouble(SCSIZE nC
, SCSIZE nR
) const
518 if (ValidColRowOrReplicated( nC
, nR
))
520 double fVal
= maMat
.get_numeric(nR
, nC
);
521 if ( pErrorInterpreter
)
523 sal_uInt16 nError
= GetDoubleErrorValue(fVal
);
525 SetErrorAtInterpreter( nError
);
531 OSL_FAIL("ScMatrixImpl::GetDouble: dimension error");
532 return CreateDoubleError( errNoValue
);
536 double ScMatrixImpl::GetDouble( SCSIZE nIndex
) const
539 CalcPosition(nIndex
, nC
, nR
);
540 return GetDouble(nC
, nR
);
543 svl::SharedString
ScMatrixImpl::GetString(SCSIZE nC
, SCSIZE nR
) const
545 if (ValidColRowOrReplicated( nC
, nR
))
548 MatrixImplType::const_position_type aPos
= maMat
.position(nR
, nC
);
549 switch (maMat
.get_type(aPos
))
551 case mdds::mtm::element_string
:
552 return maMat
.get_string(aPos
);
553 case mdds::mtm::element_empty
:
554 return svl::SharedString::getEmptyString();
555 case mdds::mtm::element_numeric
:
556 case mdds::mtm::element_boolean
:
557 fErr
= maMat
.get_numeric(aPos
);
560 OSL_FAIL("ScMatrixImpl::GetString: access error, no string");
562 SetErrorAtInterpreter(GetDoubleErrorValue(fErr
));
566 OSL_FAIL("ScMatrixImpl::GetString: dimension error");
568 return svl::SharedString::getEmptyString();
571 svl::SharedString
ScMatrixImpl::GetString( SCSIZE nIndex
) const
574 CalcPosition(nIndex
, nC
, nR
);
575 return GetString(nC
, nR
);
578 svl::SharedString
ScMatrixImpl::GetString( SvNumberFormatter
& rFormatter
, SCSIZE nC
, SCSIZE nR
) const
580 if (!ValidColRowOrReplicated( nC
, nR
))
582 OSL_FAIL("ScMatrixImpl::GetString: dimension error");
587 MatrixImplType::const_position_type aPos
= maMat
.position(nR
, nC
);
588 switch (maMat
.get_type(aPos
))
590 case mdds::mtm::element_string
:
591 return maMat
.get_string(aPos
).getString();
592 case mdds::mtm::element_empty
:
594 if (maMatFlag
.get
<TMatFlag
>(nR
, nC
) != SC_MATFLAG_EMPTYPATH
)
595 // not an empty path.
596 return svl::SharedString::getEmptyString();
598 // result of empty FALSE jump path
599 sal_uLong nKey
= rFormatter
.GetStandardFormat( css::util::NumberFormat::LOGICAL
,
602 Color
* pColor
= NULL
;
603 rFormatter
.GetOutputString( 0.0, nKey
, aStr
, &pColor
);
606 case mdds::mtm::element_numeric
:
607 case mdds::mtm::element_boolean
:
608 fVal
= maMat
.get_numeric(aPos
);
614 sal_uInt16 nError
= GetDoubleErrorValue(fVal
);
617 SetErrorAtInterpreter( nError
);
618 return ScGlobal::GetErrorString( nError
);
621 sal_uLong nKey
= rFormatter
.GetStandardFormat( css::util::NumberFormat::NUMBER
,
624 rFormatter
.GetInputLineString( fVal
, nKey
, aStr
);
628 ScMatrixValue
ScMatrixImpl::Get(SCSIZE nC
, SCSIZE nR
) const
631 if (ValidColRowOrReplicated(nC
, nR
))
633 MatrixImplType::const_position_type aPos
= maMat
.position(nR
, nC
);
634 mdds::mtm::element_t eType
= maMat
.get_type(aPos
);
637 case mdds::mtm::element_boolean
:
638 aVal
.nType
= SC_MATVAL_BOOLEAN
;
639 aVal
.fVal
= double(maMat
.get_boolean(aPos
));
641 case mdds::mtm::element_numeric
:
642 aVal
.nType
= SC_MATVAL_VALUE
;
643 aVal
.fVal
= maMat
.get_numeric(aPos
);
645 case mdds::mtm::element_string
:
646 aVal
.nType
= SC_MATVAL_STRING
;
647 aVal
.aStr
= maMat
.get_string(aPos
);
649 case mdds::mtm::element_empty
:
650 /* TODO: do we need to pass the differentiation of 'empty' and
651 * 'empty result' to the outer world anywhere? */
652 aVal
.nType
= maMatFlag
.get
<TMatFlag
>(nR
, nC
) == SC_MATFLAG_EMPTYPATH
? SC_MATVAL_EMPTYPATH
:
661 OSL_FAIL("ScMatrixImpl::Get: dimension error");
666 bool ScMatrixImpl::IsString( SCSIZE nIndex
) const
669 CalcPosition(nIndex
, nC
, nR
);
670 return IsString(nC
, nR
);
673 bool ScMatrixImpl::IsString( SCSIZE nC
, SCSIZE nR
) const
675 ValidColRowReplicated( nC
, nR
);
676 switch (maMat
.get_type(nR
, nC
))
678 case mdds::mtm::element_empty
:
679 case mdds::mtm::element_string
:
687 bool ScMatrixImpl::IsEmpty( SCSIZE nC
, SCSIZE nR
) const
689 // Flag must indicate an 'empty' or 'empty cell' or 'empty result' element,
690 // but not an 'empty path' element.
691 ValidColRowReplicated( nC
, nR
);
692 return maMat
.get_type(nR
, nC
) == mdds::mtm::element_empty
&&
693 maMatFlag
.get
<TMatFlag
>(nR
, nC
) != SC_MATFLAG_EMPTYPATH
;
696 bool ScMatrixImpl::IsEmptyCell( SCSIZE nC
, SCSIZE nR
) const
698 // Flag must indicate an 'empty cell' element instead of an
699 // 'empty' or 'empty result' or 'empty path' element.
700 ValidColRowReplicated( nC
, nR
);
701 return maMat
.get_type(nR
, nC
) == mdds::mtm::element_empty
&&
702 maMatFlag
.get
<TMatFlag
>(nR
, nC
) == SC_MATFLAG_EMPTYCELL
;
705 bool ScMatrixImpl::IsEmptyResult( SCSIZE nC
, SCSIZE nR
) const
707 // Flag must indicate an 'empty result' element instead of an
708 // 'empty' or 'empty cell' or 'empty path' element.
709 ValidColRowReplicated( nC
, nR
);
710 return maMat
.get_type(nR
, nC
) == mdds::mtm::element_empty
&&
711 maMatFlag
.get
<TMatFlag
>(nR
, nC
) == SC_MATFLAG_EMPTYRESULT
;
714 bool ScMatrixImpl::IsEmptyPath( SCSIZE nC
, SCSIZE nR
) const
716 // Flag must indicate an 'empty path' element.
717 if (ValidColRowOrReplicated( nC
, nR
))
718 return maMat
.get_type(nR
, nC
) == mdds::mtm::element_empty
&&
719 maMatFlag
.get
<TMatFlag
>(nR
, nC
) == SC_MATFLAG_EMPTYPATH
;
724 bool ScMatrixImpl::IsValue( SCSIZE nIndex
) const
727 CalcPosition(nIndex
, nC
, nR
);
728 return IsValue(nC
, nR
);
731 bool ScMatrixImpl::IsValue( SCSIZE nC
, SCSIZE nR
) const
733 ValidColRowReplicated(nC
, nR
);
734 switch (maMat
.get_type(nR
, nC
))
736 case mdds::mtm::element_boolean
:
737 case mdds::mtm::element_numeric
:
745 bool ScMatrixImpl::IsValueOrEmpty( SCSIZE nC
, SCSIZE nR
) const
747 ValidColRowReplicated(nC
, nR
);
748 switch (maMat
.get_type(nR
, nC
))
750 case mdds::mtm::element_boolean
:
751 case mdds::mtm::element_numeric
:
752 case mdds::mtm::element_empty
:
760 bool ScMatrixImpl::IsBoolean( SCSIZE nC
, SCSIZE nR
) const
762 ValidColRowReplicated( nC
, nR
);
763 return maMat
.get_type(nR
, nC
) == mdds::mtm::element_boolean
;
766 bool ScMatrixImpl::IsNumeric() const
768 return maMat
.numeric();
771 void ScMatrixImpl::MatCopy(ScMatrixImpl
& mRes
) const
773 if (maMat
.size().row
> mRes
.maMat
.size().row
|| maMat
.size().column
> mRes
.maMat
.size().column
)
775 // destination matrix is not large enough.
776 OSL_FAIL("ScMatrixImpl::MatCopy: dimension error");
780 mRes
.maMat
.copy(maMat
);
783 void ScMatrixImpl::MatTrans(ScMatrixImpl
& mRes
) const
786 mRes
.maMat
.transpose();
789 void ScMatrixImpl::FillDouble( double fVal
, SCSIZE nC1
, SCSIZE nR1
, SCSIZE nC2
, SCSIZE nR2
)
791 if (ValidColRow( nC1
, nR1
) && ValidColRow( nC2
, nR2
))
793 for (SCSIZE j
= nC1
; j
<= nC2
; ++j
)
795 // Passing value array is much faster.
796 std::vector
<double> aVals(nR2
-nR1
+1, fVal
);
797 maMat
.set(nR1
, j
, aVals
.begin(), aVals
.end());
802 OSL_FAIL("ScMatrixImpl::FillDouble: dimension error");
806 void ScMatrixImpl::PutDoubleVector( const ::std::vector
< double > & rVec
, SCSIZE nC
, SCSIZE nR
)
808 if (!rVec
.empty() && ValidColRow( nC
, nR
) && ValidColRow( nC
, nR
+ rVec
.size() - 1))
810 maMat
.set(nR
, nC
, rVec
.begin(), rVec
.end());
814 OSL_FAIL("ScMatrixImpl::PutDoubleVector: dimension error");
818 void ScMatrixImpl::PutStringVector( const ::std::vector
< svl::SharedString
> & rVec
, SCSIZE nC
, SCSIZE nR
)
820 if (!rVec
.empty() && ValidColRow( nC
, nR
) && ValidColRow( nC
, nR
+ rVec
.size() - 1))
822 maMat
.set(nR
, nC
, rVec
.begin(), rVec
.end());
826 OSL_FAIL("ScMatrixImpl::PutStringVector: dimension error");
830 void ScMatrixImpl::PutEmptyVector( SCSIZE nCount
, SCSIZE nC
, SCSIZE nR
)
832 if (nCount
&& ValidColRow( nC
, nR
) && ValidColRow( nC
, nR
+ nCount
- 1))
834 maMat
.set_empty(nR
, nC
, nCount
);
835 // Flag to indicate that this is 'empty', not 'empty result' or 'empty path'.
836 std::vector
<TMatFlag
> aVals(nCount
, SC_MATFLAG_EMPTYCELL
);
837 maMatFlag
.set(nR
, nC
, aVals
.begin(), aVals
.end());
841 OSL_FAIL("ScMatrixImpl::PutEmptyVector: dimension error");
845 void ScMatrixImpl::PutEmptyResultVector( SCSIZE nCount
, SCSIZE nC
, SCSIZE nR
)
847 if (nCount
&& ValidColRow( nC
, nR
) && ValidColRow( nC
, nR
+ nCount
- 1))
849 maMat
.set_empty(nR
, nC
, nCount
);
850 // Flag to indicate that this is 'empty result', not 'empty' or 'empty path'.
851 std::vector
<TMatFlag
> aVals(nCount
, SC_MATFLAG_EMPTYRESULT
);
852 maMatFlag
.set(nR
, nC
, aVals
.begin(), aVals
.end());
856 OSL_FAIL("ScMatrixImpl::PutEmptyResultVector: dimension error");
860 void ScMatrixImpl::PutEmptyPathVector( SCSIZE nCount
, SCSIZE nC
, SCSIZE nR
)
862 if (nCount
&& ValidColRow( nC
, nR
) && ValidColRow( nC
, nR
+ nCount
- 1))
864 maMat
.set_empty(nR
, nC
, nCount
);
865 // Flag to indicate 'empty path'.
866 std::vector
<TMatFlag
> aVals(nCount
, SC_MATFLAG_EMPTYPATH
);
867 maMatFlag
.set(nR
, nC
, aVals
.begin(), aVals
.end());
871 OSL_FAIL("ScMatrixImpl::PutEmptyPathVector: dimension error");
875 void ScMatrixImpl::CompareEqual()
877 MatrixImplType::size_pair_type aSize
= maMat
.size();
878 CompareMatrixElemFunc
<ElemEqualZero
> aFunc(aSize
.row
, aSize
.column
);
883 void ScMatrixImpl::CompareNotEqual()
885 MatrixImplType::size_pair_type aSize
= maMat
.size();
886 CompareMatrixElemFunc
<ElemNotEqualZero
> aFunc(aSize
.row
, aSize
.column
);
891 void ScMatrixImpl::CompareLess()
893 MatrixImplType::size_pair_type aSize
= maMat
.size();
894 CompareMatrixElemFunc
<ElemLessZero
> aFunc(aSize
.row
, aSize
.column
);
899 void ScMatrixImpl::CompareGreater()
901 MatrixImplType::size_pair_type aSize
= maMat
.size();
902 CompareMatrixElemFunc
<ElemGreaterZero
> aFunc(aSize
.row
, aSize
.column
);
907 void ScMatrixImpl::CompareLessEqual()
909 MatrixImplType::size_pair_type aSize
= maMat
.size();
910 CompareMatrixElemFunc
<ElemLessEqualZero
> aFunc(aSize
.row
, aSize
.column
);
915 void ScMatrixImpl::CompareGreaterEqual()
917 MatrixImplType::size_pair_type aSize
= maMat
.size();
918 CompareMatrixElemFunc
<ElemGreaterEqualZero
> aFunc(aSize
.row
, aSize
.column
);
928 void operate(double fVal
) { mbResult
&= (fVal
!= 0.0); }
929 bool result() const { return mbResult
; }
930 AndEvaluator() : mbResult(true) {}
936 void operate(double fVal
) { mbResult
|= (fVal
!= 0.0); }
937 bool result() const { return mbResult
; }
938 OrEvaluator() : mbResult(false) {}
944 void operate(double fVal
) { mbResult
^= (fVal
!= 0.0); }
945 bool result() const { return mbResult
; }
946 XorEvaluator() : mbResult(false) {}
949 // Do not short circuit logical operations, in case there are error values
950 // these need to be propagated even if the result was determined earlier.
951 template <typename _Evaluator
>
952 double EvalMatrix(const MatrixImplType
& rMat
)
955 size_t nRows
= rMat
.size().row
, nCols
= rMat
.size().column
;
956 for (size_t i
= 0; i
< nRows
; ++i
)
958 for (size_t j
= 0; j
< nCols
; ++j
)
960 MatrixImplType::const_position_type aPos
= rMat
.position(i
, j
);
961 mdds::mtm::element_t eType
= rMat
.get_type(aPos
);
962 if (eType
!= mdds::mtm::element_numeric
&& eType
!= mdds::mtm::element_boolean
)
963 // assuming a CompareMat this is an error
964 return CreateDoubleError(errIllegalArgument
);
966 double fVal
= rMat
.get_numeric(aPos
);
967 if (!::rtl::math::isFinite(fVal
))
974 return aEval
.result();
979 double ScMatrixImpl::And() const
981 // All elements must be of value type.
982 // True only if all the elements have non-zero values.
983 return EvalMatrix
<AndEvaluator
>(maMat
);
986 double ScMatrixImpl::Or() const
988 // All elements must be of value type.
989 // True if at least one element has a non-zero value.
990 return EvalMatrix
<OrEvaluator
>(maMat
);
993 double ScMatrixImpl::Xor() const
995 // All elements must be of value type.
996 // True if an odd number of elements have a non-zero value.
997 return EvalMatrix
<XorEvaluator
>(maMat
);
1004 static const double InitVal
;
1006 void operator() (double& rAccum
, double fVal
)
1012 const double SumOp::InitVal
= 0.0;
1016 static const double InitVal
;
1018 void operator() (double& rAccum
, double fVal
)
1020 rAccum
+= fVal
*fVal
;
1024 const double SumSquareOp::InitVal
= 0.0;
1028 static const double InitVal
;
1030 void operator() (double& rAccum
, double fVal
)
1036 const double ProductOp::InitVal
= 1.0;
1038 template<typename _Op
>
1039 class WalkElementBlocks
: std::unary_function
<MatrixImplType::element_block_node_type
, void>
1043 ScMatrix::IterateResult maRes
;
1045 bool mbTextAsZero
:1;
1047 WalkElementBlocks(bool bTextAsZero
) : maRes(_Op::InitVal
, _Op::InitVal
, 0), mbFirst(true), mbTextAsZero(bTextAsZero
) {}
1049 const ScMatrix::IterateResult
& getResult() const { return maRes
; }
1051 void operator() (const MatrixImplType::element_block_node_type
& node
)
1055 case mdds::mtm::element_numeric
:
1057 typedef MatrixImplType::numeric_block_type block_type
;
1059 block_type::const_iterator it
= block_type::begin(*node
.data
);
1060 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
1061 for (; it
!= itEnd
; ++it
)
1065 maOp(maRes
.mfFirst
, *it
);
1069 maOp(maRes
.mfRest
, *it
);
1071 maRes
.mnCount
+= node
.size
;
1074 case mdds::mtm::element_boolean
:
1076 typedef MatrixImplType::boolean_block_type block_type
;
1078 block_type::const_iterator it
= block_type::begin(*node
.data
);
1079 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
1080 for (; it
!= itEnd
; ++it
)
1084 maOp(maRes
.mfFirst
, *it
);
1088 maOp(maRes
.mfRest
, *it
);
1090 maRes
.mnCount
+= node
.size
;
1093 case mdds::mtm::element_string
:
1095 maRes
.mnCount
+= node
.size
;
1097 case mdds::mtm::element_empty
:
1104 class CountElements
: std::unary_function
<MatrixImplType::element_block_node_type
, void>
1109 CountElements(bool bCountString
) : mnCount(0), mbCountString(bCountString
) {}
1111 size_t getCount() const { return mnCount
; }
1113 void operator() (const MatrixImplType::element_block_node_type
& node
)
1117 case mdds::mtm::element_numeric
:
1118 case mdds::mtm::element_boolean
:
1119 mnCount
+= node
.size
;
1121 case mdds::mtm::element_string
:
1123 mnCount
+= node
.size
;
1125 case mdds::mtm::element_empty
:
1132 const size_t ResultNotSet
= std::numeric_limits
<size_t>::max();
1134 template<typename _Type
>
1135 class WalkAndMatchElements
: std::unary_function
<MatrixImplType::element_block_node_type
, void>
1138 MatrixImplType::size_pair_type maSize
;
1145 WalkAndMatchElements(_Type aMatchValue
, const MatrixImplType::size_pair_type
& aSize
, size_t nCol1
, size_t nCol2
) :
1146 maMatchValue(aMatchValue
),
1150 mnResult(ResultNotSet
),
1153 size_t getMatching() const { return mnResult
; }
1155 size_t compare(const MatrixImplType::element_block_node_type
& node
) const;
1157 void operator() (const MatrixImplType::element_block_node_type
& node
)
1159 // early exit if match already found
1160 if (mnResult
!= ResultNotSet
)
1163 // limit lookup to the requested columns
1164 if ((mnCol1
* maSize
.row
) <= mnIndex
&& mnIndex
< ((mnCol2
+ 1) * maSize
.row
))
1166 mnResult
= compare(node
);
1169 mnIndex
+= node
.size
;
1174 size_t WalkAndMatchElements
<double>::compare(const MatrixImplType::element_block_node_type
& node
) const
1179 case mdds::mtm::element_numeric
:
1181 typedef MatrixImplType::numeric_block_type block_type
;
1183 block_type::const_iterator it
= block_type::begin(*node
.data
);
1184 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
1185 for (; it
!= itEnd
; ++it
, nCount
++)
1187 if (*it
== maMatchValue
)
1189 return mnIndex
+ nCount
;
1194 case mdds::mtm::element_boolean
:
1196 typedef MatrixImplType::boolean_block_type block_type
;
1198 block_type::const_iterator it
= block_type::begin(*node
.data
);
1199 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
1200 for (; it
!= itEnd
; ++it
, ++nCount
)
1202 if (int(*it
) == maMatchValue
)
1204 return mnIndex
+ nCount
;
1210 case mdds::mtm::element_string
:
1211 case mdds::mtm::element_empty
:
1215 return ResultNotSet
;
1219 size_t WalkAndMatchElements
<svl::SharedString
>::compare(const MatrixImplType::element_block_node_type
& node
) const
1223 case mdds::mtm::element_string
:
1226 typedef MatrixImplType::string_block_type block_type
;
1228 block_type::const_iterator it
= block_type::begin(*node
.data
);
1229 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
1230 for (; it
!= itEnd
; ++it
, ++nCount
)
1232 if (it
->getDataIgnoreCase() == maMatchValue
.getDataIgnoreCase())
1234 return mnIndex
+ nCount
;
1239 case mdds::mtm::element_boolean
:
1240 case mdds::mtm::element_numeric
:
1241 case mdds::mtm::element_empty
:
1245 return ResultNotSet
;
1250 static double init() { return -std::numeric_limits
<double>::max(); }
1251 static double compare(double left
, double right
)
1253 return std::max(left
, right
);
1256 static double boolValue(
1257 MatrixImplType::boolean_block_type::const_iterator it
,
1258 MatrixImplType::boolean_block_type::const_iterator itEnd
)
1260 // If the array has at least one true value, the maximum value is 1.
1261 it
= std::find(it
, itEnd
, true);
1262 return it
== itEnd
? 0.0 : 1.0;
1268 static double init() { return std::numeric_limits
<double>::max(); }
1269 static double compare(double left
, double right
)
1271 return std::min(left
, right
);
1274 static double boolValue(
1275 MatrixImplType::boolean_block_type::const_iterator it
,
1276 MatrixImplType::boolean_block_type::const_iterator itEnd
)
1278 // If the array has at least one false value, the minimum value is 0.
1279 it
= std::find(it
, itEnd
, false);
1280 return it
== itEnd
? 1.0 : 0.0;
1284 template<typename _Op
>
1285 class CalcMaxMinValue
: std::unary_function
<MatrixImplType::element_block_type
, void>
1291 CalcMaxMinValue( bool bTextAsZero
) :
1293 mbTextAsZero(bTextAsZero
),
1294 mbHasValue(false) {}
1296 double getValue() const { return mbHasValue
? mfVal
: 0.0; }
1298 void operator() (const MatrixImplType::element_block_node_type
& node
)
1303 case mdds::mtm::element_numeric
:
1305 typedef MatrixImplType::numeric_block_type block_type
;
1307 block_type::const_iterator it
= block_type::begin(*node
.data
);
1308 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
1309 for (; it
!= itEnd
; ++it
)
1310 mfVal
= _Op::compare(mfVal
, *it
);
1315 case mdds::mtm::element_boolean
:
1317 typedef MatrixImplType::boolean_block_type block_type
;
1319 block_type::const_iterator it
= block_type::begin(*node
.data
);
1320 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
1321 double fVal
= _Op::boolValue(it
, itEnd
);
1322 mfVal
= _Op::compare(mfVal
, fVal
);
1326 case mdds::mtm::element_string
:
1327 case mdds::mtm::element_empty
:
1329 // empty elements are treated as empty strings.
1332 mfVal
= _Op::compare(mfVal
, 0.0);
1343 inline double evaluate( double fVal
, ScQueryOp eOp
)
1345 if (!rtl::math::isFinite(fVal
))
1351 return fVal
== 0.0 ? 1.0 : 0.0;
1353 return fVal
< 0.0 ? 1.0 : 0.0;
1355 return fVal
> 0.0 ? 1.0 : 0.0;
1358 return fVal
<= 0.0 ? 1.0 : 0.0;
1360 case SC_GREATER_EQUAL
:
1361 return fVal
>= 0.0 ? 1.0 : 0.0;
1364 return fVal
!= 0.0 ? 1.0 : 0.0;
1370 OSL_TRACE( "evaluate: unhandled comparison operator: %d", (int)eOp
);
1371 return CreateDoubleError( errUnknownState
);
1374 class CompareMatrixFunc
: std::unary_function
<MatrixImplType::element_block_type
, void>
1376 sc::Compare
& mrComp
;
1378 sc::CompareOptions
* mpOptions
;
1379 std::vector
<double> maResValues
; // double instead of bool to transport error values
1383 double fVal
= sc::CompareFunc( mrComp
, mpOptions
);
1384 maResValues
.push_back(evaluate(fVal
, mrComp
.meOp
));
1388 CompareMatrixFunc( size_t nResSize
, sc::Compare
& rComp
, size_t nMatPos
, sc::CompareOptions
* pOptions
) :
1389 mrComp(rComp
), mnMatPos(nMatPos
), mpOptions(pOptions
)
1391 maResValues
.reserve(nResSize
);
1394 void operator() (const MatrixImplType::element_block_node_type
& node
)
1396 sc::Compare::Cell
& rCell
= mrComp
.maCells
[mnMatPos
];
1400 case mdds::mtm::element_numeric
:
1402 typedef MatrixImplType::numeric_block_type block_type
;
1404 block_type::const_iterator it
= block_type::begin(*node
.data
);
1405 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
1406 for (; it
!= itEnd
; ++it
)
1408 rCell
.mbValue
= true;
1409 rCell
.mbEmpty
= false;
1410 rCell
.mfValue
= *it
;
1415 case mdds::mtm::element_boolean
:
1417 typedef MatrixImplType::boolean_block_type block_type
;
1419 block_type::const_iterator it
= block_type::begin(*node
.data
);
1420 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
1421 for (; it
!= itEnd
; ++it
)
1423 rCell
.mbValue
= true;
1424 rCell
.mbEmpty
= false;
1425 rCell
.mfValue
= double(*it
);
1430 case mdds::mtm::element_string
:
1432 typedef MatrixImplType::string_block_type block_type
;
1434 block_type::const_iterator it
= block_type::begin(*node
.data
);
1435 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
1436 for (; it
!= itEnd
; ++it
)
1438 const svl::SharedString
& rStr
= *it
;
1439 rCell
.mbValue
= false;
1440 rCell
.mbEmpty
= false;
1446 case mdds::mtm::element_empty
:
1448 rCell
.mbValue
= false;
1449 rCell
.mbEmpty
= true;
1450 rCell
.maStr
= svl::SharedString::getEmptyString();
1451 for (size_t i
= 0; i
< node
.size
; ++i
)
1459 const std::vector
<double>& getValues() const
1466 * Left-hand side is a matrix while the right-hand side is a numeric value.
1468 class CompareMatrixToNumericFunc
: std::unary_function
<MatrixImplType::element_block_type
, void>
1470 sc::Compare
& mrComp
;
1471 double mfRightValue
;
1472 sc::CompareOptions
* mpOptions
;
1473 std::vector
<double> maResValues
; // double instead of bool to transport error values
1477 double fVal
= sc::CompareFunc(mrComp
.maCells
[0], mfRightValue
, mpOptions
);
1478 maResValues
.push_back(evaluate(fVal
, mrComp
.meOp
));
1481 void compareLeftNumeric( double fLeftVal
)
1483 double fVal
= sc::CompareFunc(fLeftVal
, mfRightValue
);
1484 maResValues
.push_back(evaluate(fVal
, mrComp
.meOp
));
1487 void compareLeftEmpty( size_t nSize
)
1489 double fVal
= sc::CompareEmptyToNumericFunc(mfRightValue
);
1490 bool bRes
= evaluate(fVal
, mrComp
.meOp
);
1491 maResValues
.resize(maResValues
.size() + nSize
, bRes
? 1.0 : 0.0);
1495 CompareMatrixToNumericFunc( size_t nResSize
, sc::Compare
& rComp
, double fRightValue
, sc::CompareOptions
* pOptions
) :
1496 mrComp(rComp
), mfRightValue(fRightValue
), mpOptions(pOptions
)
1498 maResValues
.reserve(nResSize
);
1501 void operator() (const MatrixImplType::element_block_node_type
& node
)
1503 sc::Compare::Cell
& rCell
= mrComp
.maCells
[0];
1507 case mdds::mtm::element_numeric
:
1509 typedef MatrixImplType::numeric_block_type block_type
;
1511 block_type::const_iterator it
= block_type::begin(*node
.data
);
1512 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
1513 for (; it
!= itEnd
; ++it
)
1514 compareLeftNumeric(*it
);
1517 case mdds::mtm::element_boolean
:
1519 typedef MatrixImplType::boolean_block_type block_type
;
1521 block_type::const_iterator it
= block_type::begin(*node
.data
);
1522 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
1523 for (; it
!= itEnd
; ++it
)
1524 compareLeftNumeric(double(*it
));
1527 case mdds::mtm::element_string
:
1529 typedef MatrixImplType::string_block_type block_type
;
1531 block_type::const_iterator it
= block_type::begin(*node
.data
);
1532 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
1533 for (; it
!= itEnd
; ++it
)
1535 const svl::SharedString
& rStr
= *it
;
1536 rCell
.mbValue
= false;
1537 rCell
.mbEmpty
= false;
1543 case mdds::mtm::element_empty
:
1544 compareLeftEmpty(node
.size
);
1551 const std::vector
<double>& getValues() const
1557 class ToDoubleArray
: std::unary_function
<MatrixImplType::element_block_type
, void>
1559 std::vector
<double> maArray
;
1560 std::vector
<double>::iterator miPos
;
1565 ToDoubleArray( size_t nSize
, bool bEmptyAsZero
) :
1566 maArray(nSize
, 0.0), miPos(maArray
.begin()), mbEmptyAsZero(bEmptyAsZero
)
1568 mfNaN
= CreateDoubleError( errElementNaN
);
1571 void operator() (const MatrixImplType::element_block_node_type
& node
)
1573 using namespace mdds::mtv
;
1577 case mdds::mtm::element_numeric
:
1579 numeric_element_block::const_iterator it
= numeric_element_block::begin(*node
.data
);
1580 numeric_element_block::const_iterator itEnd
= numeric_element_block::end(*node
.data
);
1581 for (; it
!= itEnd
; ++it
, ++miPos
)
1585 case mdds::mtm::element_boolean
:
1587 boolean_element_block::const_iterator it
= boolean_element_block::begin(*node
.data
);
1588 boolean_element_block::const_iterator itEnd
= boolean_element_block::end(*node
.data
);
1589 for (; it
!= itEnd
; ++it
, ++miPos
)
1590 *miPos
= *it
? 1.0 : 0.0;
1593 case mdds::mtm::element_string
:
1595 for (size_t i
= 0; i
< node
.size
; ++i
, ++miPos
)
1599 case mdds::mtm::element_empty
:
1603 std::advance(miPos
, node
.size
);
1607 for (size_t i
= 0; i
< node
.size
; ++i
, ++miPos
)
1616 void swap(std::vector
<double>& rOther
)
1618 maArray
.swap(rOther
);
1622 struct ArrayMul
: public std::binary_function
<double, double, double>
1624 double operator() (const double& lhs
, const double& rhs
) const
1630 template<typename _Op
>
1631 class MergeDoubleArrayFunc
: std::unary_function
<MatrixImplType::element_block_type
, void>
1633 std::vector
<double>& mrArray
;
1634 std::vector
<double>::iterator miPos
;
1637 MergeDoubleArrayFunc(std::vector
<double>& rArray
) : mrArray(rArray
), miPos(mrArray
.begin())
1639 mfNaN
= CreateDoubleError( errElementNaN
);
1642 void operator() (const MatrixImplType::element_block_node_type
& node
)
1644 using namespace mdds::mtv
;
1649 case mdds::mtm::element_numeric
:
1651 numeric_element_block::const_iterator it
= numeric_element_block::begin(*node
.data
);
1652 numeric_element_block::const_iterator itEnd
= numeric_element_block::end(*node
.data
);
1653 for (; it
!= itEnd
; ++it
, ++miPos
)
1655 if (GetDoubleErrorValue(*miPos
) == errElementNaN
)
1658 *miPos
= op(*miPos
, *it
);
1662 case mdds::mtm::element_boolean
:
1664 boolean_element_block::const_iterator it
= boolean_element_block::begin(*node
.data
);
1665 boolean_element_block::const_iterator itEnd
= boolean_element_block::end(*node
.data
);
1666 for (; it
!= itEnd
; ++it
, ++miPos
)
1668 if (GetDoubleErrorValue(*miPos
) == errElementNaN
)
1671 *miPos
= op(*miPos
, *it
? 1.0 : 0.0);
1675 case mdds::mtm::element_string
:
1677 for (size_t i
= 0; i
< node
.size
; ++i
, ++miPos
)
1681 case mdds::mtm::element_empty
:
1683 // Empty element is equivalent of having a numeric value of 0.0.
1684 for (size_t i
= 0; i
< node
.size
; ++i
, ++miPos
)
1686 if (GetDoubleErrorValue(*miPos
) == errElementNaN
)
1689 *miPos
= op(*miPos
, 0.0);
1700 ScMatrix::IterateResult
ScMatrixImpl::Sum(bool bTextAsZero
) const
1702 WalkElementBlocks
<SumOp
> aFunc(bTextAsZero
);
1704 return aFunc
.getResult();
1707 ScMatrix::IterateResult
ScMatrixImpl::SumSquare(bool bTextAsZero
) const
1709 WalkElementBlocks
<SumSquareOp
> aFunc(bTextAsZero
);
1711 return aFunc
.getResult();
1714 ScMatrix::IterateResult
ScMatrixImpl::Product(bool bTextAsZero
) const
1716 WalkElementBlocks
<ProductOp
> aFunc(bTextAsZero
);
1718 ScMatrix::IterateResult aRes
= aFunc
.getResult();
1722 size_t ScMatrixImpl::Count(bool bCountStrings
) const
1724 CountElements
aFunc(bCountStrings
);
1726 return aFunc
.getCount();
1729 size_t ScMatrixImpl::MatchDoubleInColumns(double fValue
, size_t nCol1
, size_t nCol2
) const
1731 WalkAndMatchElements
<double> aFunc(fValue
, maMat
.size(), nCol1
, nCol2
);
1733 return aFunc
.getMatching();
1736 size_t ScMatrixImpl::MatchStringInColumns(const svl::SharedString
& rStr
, size_t nCol1
, size_t nCol2
) const
1738 WalkAndMatchElements
<svl::SharedString
> aFunc(rStr
, maMat
.size(), nCol1
, nCol2
);
1740 return aFunc
.getMatching();
1743 double ScMatrixImpl::GetMaxValue( bool bTextAsZero
) const
1745 CalcMaxMinValue
<MaxOp
> aFunc(bTextAsZero
);
1747 return aFunc
.getValue();
1750 double ScMatrixImpl::GetMinValue( bool bTextAsZero
) const
1752 CalcMaxMinValue
<MinOp
> aFunc(bTextAsZero
);
1754 return aFunc
.getValue();
1757 ScMatrixRef
ScMatrixImpl::CompareMatrix(
1758 sc::Compare
& rComp
, size_t nMatPos
, sc::CompareOptions
* pOptions
) const
1760 MatrixImplType::size_pair_type aSize
= maMat
.size();
1761 size_t nSize
= aSize
.column
* aSize
.row
;
1764 if (rComp
.maCells
[1].mbValue
&& !rComp
.maCells
[1].mbEmpty
)
1766 // Matrix on the left, and a numeric value on the right. Use a
1767 // function object that has much less branching for much better
1769 CompareMatrixToNumericFunc
aFunc(nSize
, rComp
, rComp
.maCells
[1].mfValue
, pOptions
);
1772 // We assume the result matrix has the same dimension as this matrix.
1773 const std::vector
<double>& rResVal
= aFunc
.getValues();
1774 if (nSize
!= rResVal
.size())
1777 return ScMatrixRef(new ScMatrix(aSize
.column
, aSize
.row
, rResVal
));
1781 CompareMatrixFunc
aFunc(nSize
, rComp
, nMatPos
, pOptions
);
1784 // We assume the result matrix has the same dimension as this matrix.
1785 const std::vector
<double>& rResVal
= aFunc
.getValues();
1786 if (nSize
!= rResVal
.size())
1789 return ScMatrixRef(new ScMatrix(aSize
.column
, aSize
.row
, rResVal
));
1792 void ScMatrixImpl::GetDoubleArray( std::vector
<double>& rArray
, bool bEmptyAsZero
) const
1794 MatrixImplType::size_pair_type aSize
= maMat
.size();
1795 ToDoubleArray
aFunc(aSize
.row
*aSize
.column
, bEmptyAsZero
);
1800 void ScMatrixImpl::MergeDoubleArray( std::vector
<double>& rArray
, ScMatrix::Op eOp
) const
1802 MatrixImplType::size_pair_type aSize
= maMat
.size();
1803 size_t nSize
= aSize
.row
*aSize
.column
;
1804 if (nSize
!= rArray
.size())
1811 MergeDoubleArrayFunc
<ArrayMul
> aFunc(rArray
);
1820 void ScMatrixImpl::AddValues( const ScMatrixImpl
& rMat
)
1822 const MatrixImplType
& rOther
= rMat
.maMat
;
1823 MatrixImplType::size_pair_type aSize
= maMat
.size();
1824 if (aSize
!= rOther
.size())
1825 // Geometry must match.
1828 // For now, we only add two matricies if and only if 1) the receiving
1829 // matrix consists only of one numeric block, and 2) the other matrix
1830 // consists of either one numeric block or one boolean block. In the
1831 // future, we may want to be more flexible support matricies that consist
1832 // of multiple blocks.
1834 MatrixImplType::position_type aPos1
= maMat
.position(0, 0);
1835 MatrixImplType::const_position_type aPos2
= rOther
.position(0, 0);
1836 if (MatrixImplType::to_mtm_type(aPos1
.first
->type
) != mdds::mtm::element_numeric
)
1839 if (aPos1
.first
->size
!= aPos2
.first
->size
)
1842 if (aPos1
.first
->size
!= aSize
.row
* aSize
.column
)
1845 MatrixImplType::numeric_block_type::iterator it
=
1846 MatrixImplType::numeric_block_type::begin(*aPos1
.first
->data
);
1847 MatrixImplType::numeric_block_type::iterator itEnd
=
1848 MatrixImplType::numeric_block_type::end(*aPos1
.first
->data
);
1850 switch (MatrixImplType::to_mtm_type(aPos2
.first
->type
))
1852 case mdds::mtm::element_boolean
:
1854 MatrixImplType::boolean_block_type::iterator it2
=
1855 MatrixImplType::boolean_block_type::begin(*aPos2
.first
->data
);
1857 for (; it
!= itEnd
; ++it
, ++it2
)
1861 case mdds::mtm::element_numeric
:
1863 MatrixImplType::numeric_block_type::iterator it2
=
1864 MatrixImplType::numeric_block_type::begin(*aPos2
.first
->data
);
1866 for (; it
!= itEnd
; ++it
, ++it2
)
1877 template<typename T
>
1884 struct return_type
<bool>
1886 typedef double type
;
1890 struct return_type
<char>
1892 typedef svl::SharedString type
;
1897 template<typename T
, typename U
, typename return_type
>
1898 struct wrapped_iterator
1900 typedef ::std::bidirectional_iterator_tag iterator_category
;
1901 typedef typename
T::const_iterator::value_type old_value_type
;
1902 typedef return_type value_type
;
1903 typedef value_type
* pointer
;
1904 typedef value_type
& reference
;
1905 typedef typename
T::const_iterator::difference_type difference_type
;
1907 typename
T::const_iterator it
;
1908 mutable value_type val
;
1913 value_type
calcVal() const
1920 wrapped_iterator(typename
T::const_iterator it_
, U aOp
):
1927 wrapped_iterator(const wrapped_iterator
& r
):
1934 wrapped_iterator
& operator=(const wrapped_iterator
& r
)
1940 bool operator==(const wrapped_iterator
& r
) const
1945 bool operator!=(const wrapped_iterator
& r
) const
1947 return !operator==(r
);
1950 wrapped_iterator
& operator++()
1957 wrapped_iterator
& operator--()
1964 value_type
& operator*() const
1970 pointer
operator->() const
1977 template<typename T
, typename U
, typename return_type
>
1978 struct MatrixIteratorWrapper
1981 typename
T::const_iterator m_itBegin
;
1982 typename
T::const_iterator m_itEnd
;
1985 MatrixIteratorWrapper(typename
T::const_iterator itBegin
, typename
T::const_iterator itEnd
, U aOp
):
1992 wrapped_iterator
<T
, U
, return_type
> begin()
1994 return wrapped_iterator
<T
, U
, return_type
>(m_itBegin
, maOp
);
1997 wrapped_iterator
<T
, U
, return_type
> end()
1999 return wrapped_iterator
<T
, U
, return_type
>(m_itEnd
, maOp
);
2005 MatrixImplType::position_type
increment_position(const MatrixImplType::position_type
& pos
, size_t n
)
2007 MatrixImplType::position_type ret
= pos
;
2010 if (ret
.second
+ n
< ret
.first
->size
)
2017 n
-= (ret
.first
->size
- ret
.second
);
2028 template<typename T
>
2029 struct MatrixOpWrapper
2032 MatrixImplType
& mrMat
;
2033 MatrixImplType::position_type pos
;
2037 MatrixOpWrapper(MatrixImplType
& rMat
, T aOp
):
2039 pos(rMat
.position(0,0)),
2044 void operator()(const MatrixImplType::element_block_node_type
& node
)
2048 case mdds::mtm::element_numeric
:
2050 typedef MatrixImplType::numeric_block_type block_type
;
2052 block_type::const_iterator it
= block_type::begin(*node
.data
);
2053 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
2054 MatrixIteratorWrapper
<block_type
, T
, typename
T::number_value_type
> aFunc(it
, itEnd
, maOp
);
2055 pos
= mrMat
.set(pos
,aFunc
.begin(), aFunc
.end());
2058 case mdds::mtm::element_boolean
:
2060 typedef MatrixImplType::boolean_block_type block_type
;
2062 block_type::const_iterator it
= block_type::begin(*node
.data
);
2063 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
2065 MatrixIteratorWrapper
<block_type
, T
, typename
T::number_value_type
> aFunc(it
, itEnd
, maOp
);
2066 pos
= mrMat
.set(pos
, aFunc
.begin(), aFunc
.end());
2069 case mdds::mtm::element_string
:
2071 typedef MatrixImplType::string_block_type block_type
;
2073 block_type::const_iterator it
= block_type::begin(*node
.data
);
2074 block_type::const_iterator itEnd
= block_type::end(*node
.data
);
2076 MatrixIteratorWrapper
<block_type
, T
, typename
T::number_value_type
> aFunc(it
, itEnd
, maOp
);
2077 pos
= mrMat
.set(pos
, aFunc
.begin(), aFunc
.end());
2080 case mdds::mtm::element_empty
:
2082 if (maOp
.useFunctionForEmpty())
2084 std::vector
<char> aVec(node
.size
);
2085 MatrixIteratorWrapper
<std::vector
<char>, T
, typename
T::number_value_type
>
2086 aFunc(aVec
.begin(), aVec
.end(), maOp
);
2087 pos
= mrMat
.set(pos
, aFunc
.begin(), aFunc
.end());
2094 pos
= increment_position(pos
, node
.size
);
2098 template<typename T
>
2099 void ScMatrixImpl::ApplyOperation(T aOp
, ScMatrixImpl
& rMat
)
2101 MatrixOpWrapper
<T
> aFunc(rMat
.maMat
, aOp
);
2106 void ScMatrixImpl::Dump() const
2108 cout
<< "-- matrix content" << endl
;
2109 SCSIZE nCols
, nRows
;
2110 GetDimensions(nCols
, nRows
);
2111 for (SCSIZE nRow
= 0; nRow
< nRows
; ++nRow
)
2113 for (SCSIZE nCol
= 0; nCol
< nCols
; ++nCol
)
2115 cout
<< " row=" << nRow
<< ", col=" << nCol
<< " : ";
2116 switch (maMat
.get_type(nRow
, nCol
))
2118 case mdds::mtm::element_string
:
2119 cout
<< "string (" << maMat
.get_string(nRow
, nCol
).getString() << ")";
2121 case mdds::mtm::element_numeric
:
2122 cout
<< "numeric (" << maMat
.get_numeric(nRow
, nCol
) << ")";
2124 case mdds::mtm::element_boolean
:
2125 cout
<< "boolean (" << maMat
.get_boolean(nRow
, nCol
) << ")";
2127 case mdds::mtm::element_empty
:
2140 void ScMatrixImpl::CalcPosition(SCSIZE nIndex
, SCSIZE
& rC
, SCSIZE
& rR
) const
2142 SCSIZE nRowSize
= maMat
.size().row
;
2143 SAL_WARN_IF( !nRowSize
, "sc", "ScMatrixImpl::CalcPosition: 0 rows!");
2144 rC
= nRowSize
> 1 ? nIndex
/ nRowSize
: nIndex
;
2145 rR
= nIndex
- rC
*nRowSize
;
2148 void ScMatrix::IncRef() const
2153 void ScMatrix::DecRef() const
2160 ScMatrix::ScMatrix( SCSIZE nC
, SCSIZE nR
) :
2161 pImpl(new ScMatrixImpl(nC
, nR
)), nRefCnt(0)
2163 SAL_WARN_IF( !nC
, "sc", "ScMatrix with 0 columns!");
2164 SAL_WARN_IF( !nR
, "sc", "ScMatrix with 0 rows!");
2167 ScMatrix::ScMatrix(SCSIZE nC
, SCSIZE nR
, double fInitVal
) :
2168 pImpl(new ScMatrixImpl(nC
, nR
, fInitVal
)), nRefCnt(0)
2170 SAL_WARN_IF( !nC
, "sc", "ScMatrix with 0 columns!");
2171 SAL_WARN_IF( !nR
, "sc", "ScMatrix with 0 rows!");
2174 ScMatrix::ScMatrix( size_t nC
, size_t nR
, const std::vector
<double>& rInitVals
) :
2175 pImpl(new ScMatrixImpl(nC
, nR
, rInitVals
)), nRefCnt(0)
2177 SAL_WARN_IF( !nC
, "sc", "ScMatrix with 0 columns!");
2178 SAL_WARN_IF( !nR
, "sc", "ScMatrix with 0 rows!");
2181 ScMatrix::~ScMatrix()
2186 ScMatrix
* ScMatrix::Clone() const
2189 pImpl
->GetDimensions(nC
, nR
);
2190 ScMatrix
* pScMat
= new ScMatrix(nC
, nR
);
2192 pScMat
->SetErrorInterpreter(pImpl
->GetErrorInterpreter()); // TODO: really?
2196 ScMatrix
* ScMatrix::CloneIfConst()
2198 return pImpl
->IsImmutable() ? Clone() : this;
2201 void ScMatrix::SetImmutable( bool bVal
)
2203 pImpl
->SetImmutable(bVal
);
2206 void ScMatrix::Resize( SCSIZE nC
, SCSIZE nR
)
2208 pImpl
->Resize(nC
, nR
);
2211 void ScMatrix::Resize(SCSIZE nC
, SCSIZE nR
, double fVal
)
2213 pImpl
->Resize(nC
, nR
, fVal
);
2216 ScMatrix
* ScMatrix::CloneAndExtend(SCSIZE nNewCols
, SCSIZE nNewRows
) const
2218 ScMatrix
* pScMat
= new ScMatrix(nNewCols
, nNewRows
);
2220 pScMat
->SetErrorInterpreter(pImpl
->GetErrorInterpreter());
2224 void ScMatrix::SetErrorInterpreter( ScInterpreter
* p
)
2226 pImpl
->SetErrorInterpreter(p
);
2229 void ScMatrix::GetDimensions( SCSIZE
& rC
, SCSIZE
& rR
) const
2231 pImpl
->GetDimensions(rC
, rR
);
2234 SCSIZE
ScMatrix::GetElementCount() const
2236 return pImpl
->GetElementCount();
2239 bool ScMatrix::ValidColRow( SCSIZE nC
, SCSIZE nR
) const
2241 return pImpl
->ValidColRow(nC
, nR
);
2244 bool ScMatrix::ValidColRowReplicated( SCSIZE
& rC
, SCSIZE
& rR
) const
2246 return pImpl
->ValidColRowReplicated(rC
, rR
);
2249 bool ScMatrix::ValidColRowOrReplicated( SCSIZE
& rC
, SCSIZE
& rR
) const
2251 return ValidColRow( rC
, rR
) || ValidColRowReplicated( rC
, rR
);
2254 void ScMatrix::PutDouble(double fVal
, SCSIZE nC
, SCSIZE nR
)
2256 pImpl
->PutDouble(fVal
, nC
, nR
);
2259 void ScMatrix::PutDouble( double fVal
, SCSIZE nIndex
)
2261 pImpl
->PutDouble(fVal
, nIndex
);
2264 void ScMatrix::PutDouble(const double* pArray
, size_t nLen
, SCSIZE nC
, SCSIZE nR
)
2266 pImpl
->PutDouble(pArray
, nLen
, nC
, nR
);
2269 void ScMatrix::PutString(const svl::SharedString
& rStr
, SCSIZE nC
, SCSIZE nR
)
2271 pImpl
->PutString(rStr
, nC
, nR
);
2274 void ScMatrix::PutString(const svl::SharedString
& rStr
, SCSIZE nIndex
)
2276 pImpl
->PutString(rStr
, nIndex
);
2279 void ScMatrix::PutString(const svl::SharedString
* pArray
, size_t nLen
, SCSIZE nC
, SCSIZE nR
)
2281 pImpl
->PutString(pArray
, nLen
, nC
, nR
);
2284 void ScMatrix::PutEmpty(SCSIZE nC
, SCSIZE nR
)
2286 pImpl
->PutEmpty(nC
, nR
);
2289 void ScMatrix::PutEmptyPath(SCSIZE nC
, SCSIZE nR
)
2291 pImpl
->PutEmptyPath(nC
, nR
);
2294 void ScMatrix::PutError( sal_uInt16 nErrorCode
, SCSIZE nC
, SCSIZE nR
)
2296 pImpl
->PutError(nErrorCode
, nC
, nR
);
2299 void ScMatrix::PutBoolean(bool bVal
, SCSIZE nC
, SCSIZE nR
)
2301 pImpl
->PutBoolean(bVal
, nC
, nR
);
2304 sal_uInt16
ScMatrix::GetError( SCSIZE nC
, SCSIZE nR
) const
2306 return pImpl
->GetError(nC
, nR
);
2309 double ScMatrix::GetDouble(SCSIZE nC
, SCSIZE nR
) const
2311 return pImpl
->GetDouble(nC
, nR
);
2314 double ScMatrix::GetDouble( SCSIZE nIndex
) const
2316 return pImpl
->GetDouble(nIndex
);
2319 svl::SharedString
ScMatrix::GetString(SCSIZE nC
, SCSIZE nR
) const
2321 return pImpl
->GetString(nC
, nR
);
2324 svl::SharedString
ScMatrix::GetString( SCSIZE nIndex
) const
2326 return pImpl
->GetString(nIndex
);
2329 svl::SharedString
ScMatrix::GetString( SvNumberFormatter
& rFormatter
, SCSIZE nC
, SCSIZE nR
) const
2331 return pImpl
->GetString(rFormatter
, nC
, nR
);
2334 ScMatrixValue
ScMatrix::Get(SCSIZE nC
, SCSIZE nR
) const
2336 return pImpl
->Get(nC
, nR
);
2339 bool ScMatrix::IsString( SCSIZE nIndex
) const
2341 return pImpl
->IsString(nIndex
);
2344 bool ScMatrix::IsString( SCSIZE nC
, SCSIZE nR
) const
2346 return pImpl
->IsString(nC
, nR
);
2349 bool ScMatrix::IsEmpty( SCSIZE nC
, SCSIZE nR
) const
2351 return pImpl
->IsEmpty(nC
, nR
);
2354 bool ScMatrix::IsEmptyCell( SCSIZE nC
, SCSIZE nR
) const
2356 return pImpl
->IsEmptyCell(nC
, nR
);
2359 bool ScMatrix::IsEmptyResult( SCSIZE nC
, SCSIZE nR
) const
2361 return pImpl
->IsEmptyResult(nC
, nR
);
2364 bool ScMatrix::IsEmptyPath( SCSIZE nC
, SCSIZE nR
) const
2366 return pImpl
->IsEmptyPath(nC
, nR
);
2369 bool ScMatrix::IsValue( SCSIZE nIndex
) const
2371 return pImpl
->IsValue(nIndex
);
2374 bool ScMatrix::IsValue( SCSIZE nC
, SCSIZE nR
) const
2376 return pImpl
->IsValue(nC
, nR
);
2379 bool ScMatrix::IsValueOrEmpty( SCSIZE nC
, SCSIZE nR
) const
2381 return pImpl
->IsValueOrEmpty(nC
, nR
);
2384 bool ScMatrix::IsBoolean( SCSIZE nC
, SCSIZE nR
) const
2386 return pImpl
->IsBoolean(nC
, nR
);
2389 bool ScMatrix::IsNumeric() const
2391 return pImpl
->IsNumeric();
2394 void ScMatrix::MatCopy(ScMatrix
& mRes
) const
2396 pImpl
->MatCopy(*mRes
.pImpl
);
2399 void ScMatrix::MatTrans(ScMatrix
& mRes
) const
2401 pImpl
->MatTrans(*mRes
.pImpl
);
2404 void ScMatrix::FillDouble( double fVal
, SCSIZE nC1
, SCSIZE nR1
, SCSIZE nC2
, SCSIZE nR2
)
2406 pImpl
->FillDouble(fVal
, nC1
, nR1
, nC2
, nR2
);
2409 void ScMatrix::PutDoubleVector( const ::std::vector
< double > & rVec
, SCSIZE nC
, SCSIZE nR
)
2411 pImpl
->PutDoubleVector(rVec
, nC
, nR
);
2414 void ScMatrix::PutStringVector( const ::std::vector
< svl::SharedString
> & rVec
, SCSIZE nC
, SCSIZE nR
)
2416 pImpl
->PutStringVector(rVec
, nC
, nR
);
2419 void ScMatrix::PutEmptyVector( SCSIZE nCount
, SCSIZE nC
, SCSIZE nR
)
2421 pImpl
->PutEmptyVector(nCount
, nC
, nR
);
2424 void ScMatrix::PutEmptyResultVector( SCSIZE nCount
, SCSIZE nC
, SCSIZE nR
)
2426 pImpl
->PutEmptyResultVector(nCount
, nC
, nR
);
2429 void ScMatrix::PutEmptyPathVector( SCSIZE nCount
, SCSIZE nC
, SCSIZE nR
)
2431 pImpl
->PutEmptyPathVector(nCount
, nC
, nR
);
2434 void ScMatrix::CompareEqual()
2436 pImpl
->CompareEqual();
2439 void ScMatrix::CompareNotEqual()
2441 pImpl
->CompareNotEqual();
2444 void ScMatrix::CompareLess()
2446 pImpl
->CompareLess();
2449 void ScMatrix::CompareGreater()
2451 pImpl
->CompareGreater();
2454 void ScMatrix::CompareLessEqual()
2456 pImpl
->CompareLessEqual();
2459 void ScMatrix::CompareGreaterEqual()
2461 pImpl
->CompareGreaterEqual();
2464 double ScMatrix::And() const
2466 return pImpl
->And();
2469 double ScMatrix::Or() const
2474 double ScMatrix::Xor() const
2476 return pImpl
->Xor();
2479 ScMatrix::IterateResult
ScMatrix::Sum(bool bTextAsZero
) const
2481 return pImpl
->Sum(bTextAsZero
);
2484 ScMatrix::IterateResult
ScMatrix::SumSquare(bool bTextAsZero
) const
2486 return pImpl
->SumSquare(bTextAsZero
);
2489 ScMatrix::IterateResult
ScMatrix::Product(bool bTextAsZero
) const
2491 return pImpl
->Product(bTextAsZero
);
2494 size_t ScMatrix::Count(bool bCountStrings
) const
2496 return pImpl
->Count(bCountStrings
);
2499 size_t ScMatrix::MatchDoubleInColumns(double fValue
, size_t nCol1
, size_t nCol2
) const
2501 return pImpl
->MatchDoubleInColumns(fValue
, nCol1
, nCol2
);
2504 size_t ScMatrix::MatchStringInColumns(const svl::SharedString
& rStr
, size_t nCol1
, size_t nCol2
) const
2506 return pImpl
->MatchStringInColumns(rStr
, nCol1
, nCol2
);
2509 double ScMatrix::GetMaxValue( bool bTextAsZero
) const
2511 return pImpl
->GetMaxValue(bTextAsZero
);
2514 double ScMatrix::GetMinValue( bool bTextAsZero
) const
2516 return pImpl
->GetMinValue(bTextAsZero
);
2519 ScMatrixRef
ScMatrix::CompareMatrix(
2520 sc::Compare
& rComp
, size_t nMatPos
, sc::CompareOptions
* pOptions
) const
2522 return pImpl
->CompareMatrix(rComp
, nMatPos
, pOptions
);
2525 void ScMatrix::GetDoubleArray( std::vector
<double>& rArray
, bool bEmptyAsZero
) const
2527 pImpl
->GetDoubleArray(rArray
, bEmptyAsZero
);
2530 void ScMatrix::MergeDoubleArray( std::vector
<double>& rArray
, Op eOp
) const
2532 pImpl
->MergeDoubleArray(rArray
, eOp
);
2538 * COp struct is used in MatOp class to provide (through template specialization)
2539 * different actions for empty entries in a matrix.
2541 template <typename T
, typename S
>
2544 template <typename T
>
2545 struct COp
<T
, svl::SharedString
>
2547 svl::SharedString
operator()(char, T
/*aOp*/, double /*a*/, double /*b*/, const svl::SharedString
& rString
) const
2553 template <typename T
>
2554 struct COp
<T
, double>
2556 double operator()(char, T aOp
, double a
, double b
, const svl::SharedString
& /*rString*/) const
2562 /** A template for operations where operands are supposed to be numeric.
2563 A non-numeric (string) operand leads to the configured conversion to number
2564 method being called if in interpreter context and an errNoValue DoubleError
2565 if conversion was not possible, else to an unconditional errNoValue
2567 An empty operand evaluates to 0.
2568 XXX: semantically TEmptyRes and types other than number_value_type are
2569 unused, but this template could serve as a basis for future enhancements.
2571 template<typename TOp
, typename TEmptyRes
=double, typename TRet
=double>
2576 ScInterpreter
* mpErrorInterpreter
;
2577 svl::SharedString maString
;
2579 COp
<TOp
, TEmptyRes
> maCOp
;
2582 typedef TEmptyRes empty_value_type
;
2583 typedef TRet number_value_type
;
2584 typedef svl::SharedString string_value_type
;
2586 MatOp( TOp aOp
, ScInterpreter
* pErrorInterpreter
,
2587 double fVal
= 0.0, const svl::SharedString
& rString
= svl::SharedString() ):
2589 mpErrorInterpreter(pErrorInterpreter
),
2594 TRet
operator()(double fVal
) const
2596 return maOp(fVal
, mfVal
);
2599 TRet
operator()(bool bVal
) const
2601 return maOp((double)bVal
, mfVal
);
2604 double operator()(const svl::SharedString
& rStr
) const
2606 if (mpErrorInterpreter
)
2608 sal_uInt16 nError
= 0;
2609 short nCurFmtType
= 0;
2610 double fValue
= mpErrorInterpreter
->ConvertStringToValue( rStr
.getString(), nError
, nCurFmtType
);
2612 return CreateDoubleError( nError
);
2615 return CreateDoubleError( errNoValue
);
2618 TEmptyRes
operator()(char) const
2620 return maCOp(char{}, maOp
, 0, mfVal
, maString
);
2623 static bool useFunctionForEmpty()
2631 void ScMatrix::NotOp( ScMatrix
& rMat
)
2633 auto not_
= [](double a
, double){return double(a
== 0.0);};
2634 matop::MatOp
<decltype(not_
), double> aOp(not_
, pImpl
->GetErrorInterpreter());
2635 pImpl
->ApplyOperation(aOp
, *rMat
.pImpl
);
2638 void ScMatrix::NegOp( ScMatrix
& rMat
)
2640 auto neg_
= [](double a
, double){return -a
;};
2641 matop::MatOp
<decltype(neg_
), double> aOp(neg_
, pImpl
->GetErrorInterpreter());
2642 pImpl
->ApplyOperation(aOp
, *rMat
.pImpl
);
2645 void ScMatrix::AddOp( double fVal
, ScMatrix
& rMat
)
2647 auto add_
= [](double a
, double b
){return a
+ b
;};
2648 matop::MatOp
<decltype(add_
)> aOp(add_
, pImpl
->GetErrorInterpreter(), fVal
);
2649 pImpl
->ApplyOperation(aOp
, *rMat
.pImpl
);
2652 void ScMatrix::SubOp( bool bFlag
, double fVal
, ScMatrix
& rMat
)
2656 auto sub_
= [](double a
, double b
){return b
- a
;};
2657 matop::MatOp
<decltype(sub_
)> aOp(sub_
, pImpl
->GetErrorInterpreter(), fVal
);
2658 pImpl
->ApplyOperation(aOp
, *rMat
.pImpl
);
2662 auto sub_
= [](double a
, double b
){return a
- b
;};
2663 matop::MatOp
<decltype(sub_
)> aOp(sub_
, pImpl
->GetErrorInterpreter(), fVal
);
2664 pImpl
->ApplyOperation(aOp
, *rMat
.pImpl
);
2668 void ScMatrix::MulOp( double fVal
, ScMatrix
& rMat
)
2670 auto mul_
= [](double a
, double b
){return a
* b
;};
2671 matop::MatOp
<decltype(mul_
)> aOp(mul_
, pImpl
->GetErrorInterpreter(), fVal
);
2672 pImpl
->ApplyOperation(aOp
, *rMat
.pImpl
);
2675 void ScMatrix::DivOp( bool bFlag
, double fVal
, ScMatrix
& rMat
)
2679 auto div_
= [](double a
, double b
){return sc::div(b
, a
);};
2680 matop::MatOp
<decltype(div_
)> aOp(div_
, pImpl
->GetErrorInterpreter(), fVal
);
2681 pImpl
->ApplyOperation(aOp
, *rMat
.pImpl
);
2685 auto div_
= [](double a
, double b
){return sc::div(a
, b
);};
2686 matop::MatOp
<decltype(div_
)> aOp(div_
, pImpl
->GetErrorInterpreter(), fVal
);
2687 pImpl
->ApplyOperation(aOp
, *rMat
.pImpl
);
2691 void ScMatrix::PowOp( bool bFlag
, double fVal
, ScMatrix
& rMat
)
2695 auto pow_
= [](double a
, double b
){return pow(b
, a
);};
2696 matop::MatOp
<decltype(pow_
)> aOp(pow_
, pImpl
->GetErrorInterpreter(), fVal
);
2697 pImpl
->ApplyOperation(aOp
, *rMat
.pImpl
);
2701 auto pow_
= [](double a
, double b
){return pow(a
, b
);};
2702 matop::MatOp
<decltype(pow_
)> aOp(pow_
, pImpl
->GetErrorInterpreter(), fVal
);
2703 pImpl
->ApplyOperation(aOp
, *rMat
.pImpl
);
2707 ScMatrix
& ScMatrix::operator+= ( const ScMatrix
& r
)
2709 pImpl
->AddValues(*r
.pImpl
);
2714 void ScMatrix::Dump() const
2720 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */