nss: upgrade to release 3.73
[LibreOffice.git] / sc / inc / scmatrix.hxx
blobe9a71e82b94d2500e408f9e7bda407a89016feee
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 "address.hxx"
24 #include "matrixoperators.hxx"
25 #include "types.hxx"
26 #include <formula/errorcodes.hxx>
27 #include "scdllapi.h"
28 #include <svl/sharedstring.hxx>
29 #include <svl/sharedstringpool.hxx>
31 #include <memory>
32 #include <utility>
33 #include <vector>
35 #define DEBUG_MATRIX 0
37 class ScInterpreter;
38 class SvNumberFormatter;
39 class ScMatrixImpl;
40 enum class FormulaError : sal_uInt16;
42 namespace sc {
44 struct Compare;
45 struct CompareOptions;
49 /**
50 * Try NOT to use this struct. This struct should go away in a hopefully
51 * not so distant future.
53 struct ScMatrixValue
55 double fVal;
56 svl::SharedString aStr;
57 ScMatValType nType;
59 /// Only valid if ScMatrix methods indicate so!
60 const svl::SharedString& GetString() const { return aStr; }
62 /// Only valid if ScMatrix methods indicate that this is no string!
63 FormulaError GetError() const { return GetDoubleErrorValue(fVal); }
65 /// Only valid if ScMatrix methods indicate that this is a boolean
66 bool GetBoolean() const { return fVal != 0.0; }
68 ScMatrixValue() : fVal(0.0), nType(ScMatValType::Empty) {}
70 ScMatrixValue(const ScMatrixValue& r) :
71 fVal(r.fVal), aStr(r.aStr), nType(r.nType) {}
73 bool operator== (const ScMatrixValue& r) const
75 if (nType != r.nType)
76 return false;
78 switch (nType)
80 case ScMatValType::Value:
81 case ScMatValType::Boolean:
82 return fVal == r.fVal;
83 break;
84 default:
88 return aStr == r.aStr;
91 bool operator!= (const ScMatrixValue& r) const
93 return !operator==(r);
96 ScMatrixValue& operator= (const ScMatrixValue& r)
98 if (this == &r)
99 return *this;
101 nType = r.nType;
102 fVal = r.fVal;
103 aStr = r.aStr;
104 return *this;
109 * Matrix data type that can store values of mixed types. Each element can
110 * be one of the following types: numeric, string, boolean, empty, and empty
111 * path.
113 class SC_DLLPUBLIC ScMatrix final
115 friend class ScMatrixImpl;
117 mutable size_t nRefCnt; // reference count
118 mutable bool mbCloneIfConst; // Whether the matrix is cloned with a CloneIfConst() call.
119 std::unique_ptr<ScMatrixImpl> pImpl;
121 ScMatrix( const ScMatrix& ) = delete;
122 ScMatrix& operator=( const ScMatrix&) = delete;
124 public:
125 ScMatrix(SCSIZE nC, SCSIZE nR);
126 ScMatrix(SCSIZE nC, SCSIZE nR, double fInitVal);
127 ScMatrix( size_t nC, size_t nR, const std::vector<double>& rInitVals );
128 ~ScMatrix();
130 typedef std::function<void(size_t, size_t, double)> DoubleOpFunction;
131 typedef std::function<void(size_t, size_t, bool)> BoolOpFunction;
132 typedef std::function<void(size_t, size_t, svl::SharedString)> StringOpFunction;
133 typedef std::function<void(size_t, size_t)> EmptyOpFunction;
136 * When adding all numerical matrix elements for a scalar result such as
137 * summation, the interpreter wants to separate the first non-zero value
138 * with the rest of the summed values. This is necessary for better
139 * numerical stability, unless we sort all by absolute values before
140 * summing (not really an option) or use another algorithm, e.g. Kahan's
141 * summation algorithm,
142 * https://en.wikipedia.org/wiki/Kahan_summation_algorithm
144 struct IterateResult
146 double mfFirst;
147 double mfRest;
148 size_t mnCount;
150 IterateResult(double fFirst, double fRest, size_t nCount) :
151 mfFirst(fFirst), mfRest(fRest), mnCount(nCount) {}
154 /** Checks nC or nR for zero and uses GetElementsMax() whether a matrix of
155 the size of nC*nR could be allocated. A zero size (both nC and nR zero)
156 matrix is allowed for later resize.
158 bool static IsSizeAllocatable( SCSIZE nC, SCSIZE nR );
160 /// Value or boolean.
161 static bool IsValueType( ScMatValType nType )
163 return nType <= ScMatValType::Boolean;
166 /// Boolean.
167 static bool IsBooleanType( ScMatValType nType )
169 return nType == ScMatValType::Boolean;
172 /// String, empty or empty path, but not value nor boolean.
173 static bool IsNonValueType( ScMatValType nType )
175 return bool(nType & ScMatValType::NonvalueMask);
178 /** String, but not empty or empty path or any other type.
179 Not named IsStringType to prevent confusion because previously
180 IsNonValueType was named IsStringType. */
181 static bool IsRealStringType( ScMatValType nType )
183 return (nType & ScMatValType::NonvalueMask) == ScMatValType::String;
186 /// Empty, but not empty path or any other type.
187 static bool IsEmptyType( ScMatValType nType )
189 return (nType & ScMatValType::NonvalueMask) == ScMatValType::Empty;
192 /// Empty path, but not empty or any other type.
193 static bool IsEmptyPathType( ScMatValType nType )
195 return (nType & ScMatValType::NonvalueMask) == ScMatValType::EmptyPath;
198 /** Clone the matrix. */
199 ScMatrix* Clone() const;
201 /** Clone the matrix if mbCloneIfConst (immutable) is set, otherwise
202 return _this_ matrix, to be assigned to a ScMatrixRef. */
203 ScMatrix* CloneIfConst();
205 /** Set the matrix to mutable for CloneIfConst(), only the interpreter
206 should do this and know the consequences. */
207 void SetMutable();
209 /** Set the matrix to immutable for CloneIfConst(), only the interpreter
210 should do this and know the consequences. */
211 void SetImmutable() const;
214 * Resize the matrix to specified new dimension.
216 void Resize(SCSIZE nC, SCSIZE nR);
218 void Resize(SCSIZE nC, SCSIZE nR, double fVal);
220 /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
221 MUST be at least of the size of the original matrix. */
222 ScMatrix* CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const;
224 void IncRef() const;
225 void DecRef() const;
227 void SetErrorInterpreter( ScInterpreter* p);
228 void GetDimensions( SCSIZE& rC, SCSIZE& rR) const;
229 SCSIZE GetElementCount() const;
230 bool ValidColRow( SCSIZE nC, SCSIZE nR) const;
232 /** For a row vector or column vector, if the position does not point into
233 the vector but is a valid column or row offset it is adapted such that
234 it points to an element to be replicated, same column row 0 for a row
235 vector, same row column 0 for a column vector. Else, for a 2D matrix,
236 returns false.
238 bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const;
240 /** Checks if the matrix position is within the matrix. If it is not, for a
241 row vector or column vector the position is adapted such that it points
242 to an element to be replicated, same column row 0 for a row vector,
243 same row column 0 for a column vector. Else, for a 2D matrix and
244 position not within matrix, returns false.
246 bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const;
248 void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
249 void PutDouble( double fVal, SCSIZE nIndex);
250 void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR);
252 void PutString( const svl::SharedString& rStr, SCSIZE nC, SCSIZE nR) ;
253 void PutString( const svl::SharedString& rStr, SCSIZE nIndex) ;
254 void PutString( const svl::SharedString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) ;
256 void PutEmpty( SCSIZE nC, SCSIZE nR);
258 /// Jump sal_False without path
259 void PutEmptyPath( SCSIZE nC, SCSIZE nR) ;
260 void PutError( FormulaError nErrorCode, SCSIZE nC, SCSIZE nR ) ;
261 void PutBoolean( bool bVal, SCSIZE nC, SCSIZE nR) ;
263 void FillDouble( double fVal,
264 SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 ) ;
266 /** Put a column vector of doubles, starting at row nR, must fit into dimensions. */
267 void PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR ) ;
269 /** Put a column vector of strings, starting at row nR, must fit into dimensions. */
270 void PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR ) ;
272 /** Put a column vector of empties, starting at row nR, must fit into dimensions. */
273 void PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) ;
275 /** Put a column vector of empty results, starting at row nR, must fit into dimensions. */
276 void PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) ;
278 /** Put a column vector of empty paths, starting at row nR, must fit into dimensions. */
279 void PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) ;
281 /** May be used before obtaining the double value of an element to avoid
282 passing its NAN around.
283 @ATTENTION: MUST NOT be used if the element is a string!
284 Use GetErrorIfNotString() instead if not sure.
285 @returns 0 if no error, else one of err... constants */
286 FormulaError GetError( SCSIZE nC, SCSIZE nR) const ;
288 /** Use in ScInterpreter to obtain the error code, if any.
289 @returns 0 if no error or string element, else one of err... constants */
290 FormulaError GetErrorIfNotString( SCSIZE nC, SCSIZE nR) const
291 { return IsValue( nC, nR) ? GetError( nC, nR) : FormulaError::NONE; }
293 /// @return 0.0 if empty or empty path, else value or DoubleError.
294 double GetDouble( SCSIZE nC, SCSIZE nR) const ;
295 /// @return 0.0 if empty or empty path, else value or DoubleError.
296 double GetDouble( SCSIZE nIndex) const ;
297 /// @return value or DoubleError or string converted to value.
298 double GetDoubleWithStringConversion( SCSIZE nC, SCSIZE nR ) const ;
300 /// @return empty string if empty or empty path, else string content.
301 svl::SharedString GetString( SCSIZE nC, SCSIZE nR) const ;
302 /// @return empty string if empty or empty path, else string content.
303 svl::SharedString GetString( SCSIZE nIndex) const ;
305 /** @returns the matrix element's string if one is present, otherwise the
306 numerical value formatted as string, or in case of an error the error
307 string is returned; an empty string for empty, a "FALSE" string for
308 empty path. */
309 svl::SharedString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const ;
311 /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
312 /// an empty string!
313 ScMatrixValue Get( SCSIZE nC, SCSIZE nR) const ;
315 /** @return <TRUE/> if string or any empty, empty cell, empty result, empty
316 path, in fact non-value. */
317 bool IsStringOrEmpty( SCSIZE nIndex ) const ;
319 /** @return <TRUE/> if string or any empty, empty cell, empty result, empty
320 path, in fact non-value. */
321 bool IsStringOrEmpty( SCSIZE nC, SCSIZE nR ) const ;
323 /// @return <TRUE/> if empty or empty cell or empty result, not empty path.
324 bool IsEmpty( SCSIZE nC, SCSIZE nR ) const ;
326 /// @return <TRUE/> if empty cell, not empty or empty result or empty path.
327 bool IsEmptyCell( SCSIZE nC, SCSIZE nR ) const ;
329 /// @return <TRUE/> if empty result, not empty or empty cell or empty path.
330 bool IsEmptyResult( SCSIZE nC, SCSIZE nR ) const ;
332 /// @return <TRUE/> if empty path, not empty or empty cell or empty result.
333 bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const ;
335 /// @return <TRUE/> if value or boolean.
336 bool IsValue( SCSIZE nIndex ) const ;
338 /// @return <TRUE/> if value or boolean.
339 bool IsValue( SCSIZE nC, SCSIZE nR ) const ;
341 /// @return <TRUE/> if value or boolean or empty or empty path.
342 bool IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const ;
344 /// @return <TRUE/> if boolean.
345 bool IsBoolean( SCSIZE nC, SCSIZE nR ) const ;
347 /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
348 bool IsNumeric() const ;
350 void MatTrans( const ScMatrix& mRes) const ;
351 void MatCopy ( const ScMatrix& mRes) const ;
353 // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
354 void CompareEqual() ;
355 void CompareNotEqual() ;
356 void CompareLess() ;
357 void CompareGreater() ;
358 void CompareLessEqual() ;
359 void CompareGreaterEqual() ;
361 double And() const ; // logical AND of all matrix values, or NAN
362 double Or() const ; // logical OR of all matrix values, or NAN
363 double Xor() const ; // logical XOR of all matrix values, or NAN
365 IterateResult Sum( bool bTextAsZero, bool bIgnoreErrorValues = false ) const ;
366 IterateResult SumSquare( bool bTextAsZero, bool bIgnoreErrorValues = false ) const ;
367 IterateResult Product( bool bTextAsZero, bool bIgnoreErrorValues = false ) const ;
368 size_t Count(bool bCountStrings, bool bCountErrors, bool bIgnoreEmptyStrings = false) const ;
369 size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const ;
370 size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const ;
372 double GetMaxValue( bool bTextAsZero, bool bIgnoreErrorValues = false ) const ;
373 double GetMinValue( bool bTextAsZero, bool bIgnoreErrorValues = false ) const ;
374 double GetGcd() const ;
375 double GetLcm() const ;
377 ScMatrixRef CompareMatrix(
378 sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) 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 MergeDoubleArrayMultiply( std::vector<double>& rArray ) const ;
391 void NotOp(const ScMatrix& rMat) ;
392 void NegOp(const ScMatrix& rMat) ;
393 void AddOp(double fVal, const ScMatrix& rMat) ;
394 void SubOp(bool bFlag, double fVal, const ScMatrix& rMat) ;
395 void MulOp(double fVal, const ScMatrix& rMat) ;
396 void DivOp(bool bFlag, double fVal, const ScMatrix& rMat) ;
397 void PowOp(bool bFlag, double fVal, const ScMatrix& rMat) ;
399 std::vector<ScMatrix::IterateResult> Collect(const std::vector<sc::op::Op>& aOp) ;
401 void ExecuteOperation(const std::pair<size_t, size_t>& rStartPos, const std::pair<size_t, size_t>& rEndPos,
402 DoubleOpFunction aDoubleFunc, BoolOpFunction aBoolFunc, StringOpFunction aStringFunc,
403 EmptyOpFunction aEmptyFunc) const ;
405 void MatConcat(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatrixRef& xMat1, const ScMatrixRef& xMat2,
406 SvNumberFormatter& rFormatter, svl::SharedStringPool& rPool) ;
408 #if DEBUG_MATRIX
409 void Dump() const;
410 #endif
413 inline void intrusive_ptr_add_ref(const ScMatrix* p)
415 p->IncRef();
418 inline void intrusive_ptr_release(const ScMatrix* p)
420 p->DecRef();
423 #endif // INCLUDED_SC_INC_SCMATRIX_HXX
425 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */