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