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