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