Bump version to 4.3-4
[LibreOffice.git] / sc / inc / scmatrix.hxx
blobaebe0e79a83c39c893dc8510f89817a0c70b0553
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_SC_INC_SCMATRIX_HXX
21 #define INCLUDED_SC_INC_SCMATRIX_HXX
23 #include "global.hxx"
24 #include "types.hxx"
25 #include <formula/errorcodes.hxx>
26 #include "scdllapi.h"
27 #include <rtl/ustring.hxx>
28 #include <svl/sharedstring.hxx>
30 #include <boost/intrusive_ptr.hpp>
31 #include <boost/interprocess/smart_ptr/unique_ptr.hpp>
33 #define DEBUG_MATRIX 0
35 class ScInterpreter;
36 class SvNumberFormatter;
37 class ScMatrixImpl;
39 namespace sc {
41 struct Compare;
42 struct CompareOptions;
46 /**
47 * Try NOT to use this struct. This struct should go away in a hopefully
48 * not so distant futture.
50 struct ScMatrixValue
52 double fVal;
53 svl::SharedString aStr;
54 ScMatValType nType;
56 /// Only valid if ScMatrix methods indicate so!
57 svl::SharedString GetString() const { return aStr; }
59 /// Only valid if ScMatrix methods indicate that this is no string!
60 sal_uInt16 GetError() const { return GetDoubleErrorValue( fVal); }
62 /// Only valid if ScMatrix methods indicate that this is a boolean
63 bool GetBoolean() const { return fVal != 0.0; }
65 ScMatrixValue() : fVal(0.0), nType(SC_MATVAL_EMPTY) {}
67 ScMatrixValue(const ScMatrixValue& r) :
68 fVal(r.fVal), aStr(r.aStr), nType(r.nType) {}
70 bool operator== (const ScMatrixValue& r) const
72 if (nType != r.nType)
73 return false;
75 switch (nType)
77 case SC_MATVAL_VALUE:
78 case SC_MATVAL_BOOLEAN:
79 return fVal == r.fVal;
80 break;
81 default:
85 return aStr == r.aStr;
88 bool operator!= (const ScMatrixValue& r) const
90 return !operator==(r);
93 ScMatrixValue& operator= (const ScMatrixValue& r)
95 if (this == &r)
96 return *this;
98 nType = r.nType;
99 fVal = r.fVal;
100 aStr = r.aStr;
101 return *this;
106 * Matrix data type that can store values of mixed types. Each element can
107 * be one of the following types: numeric, string, boolean, empty, and empty
108 * path.
110 class SC_DLLPUBLIC ScMatrix
112 friend class ScMatrixImpl;
114 ScMatrixImpl* pImpl;
115 mutable size_t nRefCnt; // reference count
117 // only delete via Delete()
118 ~ScMatrix();
120 // not implemented, prevent usage
121 ScMatrix( const ScMatrix& );
122 ScMatrix& operator=( const ScMatrix&);
124 public:
125 enum Op { Add, Sub, Mul, Div };
128 * When adding all numerical matrix elements for a scalar result such as
129 * summation, the interpreter wants to separate the first non-zero value
130 * with the rest of the summed values.
132 * TODO: Find out if we still need to do this. If not, we can re-write
133 * ScInterpreter::IterateParameters() to make it simpler and remove this
134 * struct.
136 struct IterateResult
138 double mfFirst;
139 double mfRest;
140 size_t mnCount;
142 IterateResult(double fFirst, double fRest, size_t nCount) :
143 mfFirst(fFirst), mfRest(fRest), mnCount(nCount) {}
145 IterateResult(const IterateResult& r) :
146 mfFirst(r.mfFirst), mfRest(r.mfRest), mnCount(r.mnCount) {}
149 /// The maximum number of elements a matrix may have at runtime.
150 inline static size_t GetElementsMax()
152 // TODO: Fix me.
153 return 0x08000000;
154 #if 0
155 // Roughly 125MB in total, divided by 8+1 per element => 14M elements.
156 const size_t nMemMax = 0x08000000 / (sizeof(ScMatrixValue) + sizeof(ScMatValType));
157 // With MAXROWCOUNT==65536 and 128 columns => 8M elements ~72MB.
158 const size_t nArbitraryLimit = (size_t)MAXROWCOUNT * 128;
159 // Stuffed with a million rows would limit this to 14 columns.
160 return nMemMax < nArbitraryLimit ? nMemMax : nArbitraryLimit;
161 #endif
164 /// Value or boolean.
165 inline static bool IsValueType( ScMatValType nType )
167 return nType <= SC_MATVAL_BOOLEAN;
170 /// Boolean.
171 inline static bool IsBooleanType( ScMatValType nType )
173 return nType == SC_MATVAL_BOOLEAN;
176 /// String, empty or empty path, but not value nor boolean.
177 inline static bool IsNonValueType( ScMatValType nType )
179 return (nType & SC_MATVAL_NONVALUE) != 0;
182 /** String, but not empty or empty path or any other type.
183 Not named IsStringType to prevent confusion because previously
184 IsNonValueType was named IsStringType. */
185 inline static bool IsRealStringType( ScMatValType nType )
187 return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_STRING;
190 /// Empty, but not empty path or any other type.
191 inline static bool IsEmptyType( ScMatValType nType )
193 return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTY;
196 /// Empty path, but not empty or any other type.
197 inline static bool IsEmptyPathType( ScMatValType nType )
199 return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTYPATH;
202 ScMatrix(SCSIZE nC, SCSIZE nR);
203 ScMatrix(SCSIZE nC, SCSIZE nR, double fInitVal);
205 ScMatrix( size_t nC, size_t nR, const std::vector<double>& rInitVals );
207 /** Clone the matrix. */
208 ScMatrix* Clone() const;
210 /** Clone the matrix if mbCloneIfConst (immutable) is set, otherwise
211 return _this_ matrix, to be assigned to a ScMatrixRef. */
212 ScMatrix* CloneIfConst();
214 /** Set the matrix to (im)mutable for CloneIfConst(), only the interpreter
215 should do this and know the consequences. */
216 void SetImmutable( bool bVal );
219 * Resize the matrix to specified new dimension.
221 void Resize( SCSIZE nC, SCSIZE nR);
223 void Resize(SCSIZE nC, SCSIZE nR, double fVal);
225 /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
226 MUST be at least of the size of the original matrix. */
227 ScMatrix* CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const;
229 void IncRef() const;
230 void DecRef() const;
232 void SetErrorInterpreter( ScInterpreter* p);
233 void GetDimensions( SCSIZE& rC, SCSIZE& rR) const;
234 SCSIZE GetElementCount() const;
235 bool ValidColRow( SCSIZE nC, SCSIZE nR) const;
236 SCSIZE CalcOffset( SCSIZE nC, SCSIZE nR) const;
238 /** For a row vector or column vector, if the position does not point into
239 the vector but is a valid column or row offset it is adapted such that
240 it points to an element to be replicated, same column row 0 for a row
241 vector, same row column 0 for a column vector. Else, for a 2D matrix,
242 returns false.
244 bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const;
246 /** Checks if the matrix position is within the matrix. If it is not, for a
247 row vector or column vector the position is adapted such that it points
248 to an element to be replicated, same column row 0 for a row vector,
249 same row column 0 for a column vector. Else, for a 2D matrix and
250 position not within matrix, returns false.
252 bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const;
254 void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
255 void PutDouble( double fVal, SCSIZE nIndex);
256 void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR);
258 void PutString( const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR);
259 void PutString( const svl::SharedString& rStr, SCSIZE nIndex);
260 void PutString( const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR);
262 void PutEmpty( SCSIZE nC, SCSIZE nR);
264 /// Jump sal_False without path
265 void PutEmptyPath( SCSIZE nC, SCSIZE nR);
266 void PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR );
267 void PutBoolean( bool bVal, SCSIZE nC, SCSIZE nR);
269 void FillDouble( double fVal,
270 SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 );
272 /** Put a column vector of doubles, starting at row nR, must fit into dimensions. */
273 void PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR );
275 /** Put a column vector of strings, starting at row nR, must fit into dimensions. */
276 void PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR );
278 /** Put a column vector of empties, starting at row nR, must fit into dimensions. */
279 void PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
281 /** Put a column vector of empty results, starting at row nR, must fit into dimensions. */
282 void PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
284 /** Put a column vector of empty paths, starting at row nR, must fit into dimensions. */
285 void PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR );
287 /** May be used before obtaining the double value of an element to avoid
288 passing its NAN around.
289 @ATTENTION: MUST NOT be used if the element is a string!
290 Use GetErrorIfNotString() instead if not sure.
291 @returns 0 if no error, else one of err... constants */
292 sal_uInt16 GetError( SCSIZE nC, SCSIZE nR) const;
294 /** Use in ScInterpreter to obtain the error code, if any.
295 @returns 0 if no error or string element, else one of err... constants */
296 sal_uInt16 GetErrorIfNotString( SCSIZE nC, SCSIZE nR) const
297 { return IsValue( nC, nR) ? GetError( nC, nR) : 0; }
299 /// @return 0.0 if empty or empty path, else value or DoubleError.
300 double GetDouble( SCSIZE nC, SCSIZE nR) const;
301 /// @return 0.0 if empty or empty path, else value or DoubleError.
302 double GetDouble( SCSIZE nIndex) const;
304 /// @return empty string if empty or empty path, else string content.
305 svl::SharedString GetString( SCSIZE nC, SCSIZE nR) const;
306 /// @return empty string if empty or empty path, else string content.
307 svl::SharedString GetString( SCSIZE nIndex) const;
309 /** @returns the matrix element's string if one is present, otherwise the
310 numerical value formatted as string, or in case of an error the error
311 string is returned; an empty string for empty, a "FALSE" string for
312 empty path. */
313 svl::SharedString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const;
315 /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
316 /// an empty string!
317 ScMatrixValue Get( SCSIZE nC, SCSIZE nR) const;
319 /// @return <TRUE/> if string or empty or empty path, in fact non-value.
320 bool IsString( SCSIZE nIndex ) const;
322 /// @return <TRUE/> if string or empty or empty path, in fact non-value.
323 bool IsString( SCSIZE nC, SCSIZE nR ) const;
325 /// @return <TRUE/> if empty or empty cell or empty result, not empty path.
326 bool IsEmpty( SCSIZE nC, SCSIZE nR ) const;
328 /// @return <TRUE/> if empty cell, not empty or empty result or empty path.
329 bool IsEmptyCell( SCSIZE nC, SCSIZE nR ) const;
331 /// @return <TRUE/> if empty result, not empty or empty cell or empty path.
332 bool IsEmptyResult( SCSIZE nC, SCSIZE nR ) const;
334 /// @return <TRUE/> if empty path, not empty or empty cell or empty result.
335 bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const;
337 /// @return <TRUE/> if value or boolean.
338 bool IsValue( SCSIZE nIndex ) const;
340 /// @return <TRUE/> if value or boolean.
341 bool IsValue( SCSIZE nC, SCSIZE nR ) const;
343 /// @return <TRUE/> if value or boolean or empty or empty path.
344 bool IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const;
346 /// @return <TRUE/> if boolean.
347 bool IsBoolean( SCSIZE nC, SCSIZE nR ) const;
349 /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
350 bool IsNumeric() const;
352 void MatTrans( ScMatrix& mRes) const;
353 void MatCopy ( ScMatrix& mRes) const;
355 // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
356 void CompareEqual();
357 void CompareNotEqual();
358 void CompareLess();
359 void CompareGreater();
360 void CompareLessEqual();
361 void CompareGreaterEqual();
363 double And() const; // logical AND of all matrix values, or NAN
364 double Or() const; // logical OR of all matrix values, or NAN
365 double Xor() const; // logical XOR of all matrix values, or NAN
367 IterateResult Sum(bool bTextAsZero) const;
368 IterateResult SumSquare(bool bTextAsZero) const;
369 IterateResult Product(bool bTextAsZero) const;
370 size_t Count(bool bCountStrings) const;
371 size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const;
372 size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const;
374 double GetMaxValue( bool bTextAsZero ) const;
375 double GetMinValue( bool bTextAsZero ) const;
377 ScMatrixRef CompareMatrix(
378 sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions = NULL ) const;
381 * Convert the content of matrix into a linear array of numeric values.
382 * String elements are mapped to NaN's and empty elements are mapped to
383 * either NaN or zero values.
385 * @param bEmptyAsZero if true empty elements are mapped to zero values,
386 * otherwise they become NaN values.
388 void GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero = true ) const;
389 void MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const;
391 ScMatrix& operator+= ( const ScMatrix& r );
393 #if DEBUG_MATRIX
394 void Dump() const;
395 #endif
398 inline void intrusive_ptr_add_ref(const ScMatrix* p)
400 p->IncRef();
403 inline void intrusive_ptr_release(const ScMatrix* p)
405 p->DecRef();
408 #endif // INCLUDED_SC_INC_SCMATRIX_HXX
410 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */