Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #ifndef SC_MATRIX_HXX
30 : : #define SC_MATRIX_HXX
31 : :
32 : : #include "global.hxx"
33 : : #include "types.hxx"
34 : : #include "formula/errorcodes.hxx"
35 : : #include "scdllapi.h"
36 : : #include <rtl/ustring.hxx>
37 : :
38 : : #include <boost/intrusive_ptr.hpp>
39 : :
40 : : class ScInterpreter;
41 : : class SvNumberFormatter;
42 : : class ScMatrixImpl;
43 : :
44 : : typedef sal_uInt8 ScMatValType;
45 : : const ScMatValType SC_MATVAL_VALUE = 0x00;
46 : : const ScMatValType SC_MATVAL_BOOLEAN = 0x01;
47 : : const ScMatValType SC_MATVAL_STRING = 0x02;
48 : : const ScMatValType SC_MATVAL_EMPTY = SC_MATVAL_STRING | 0x04; // STRING plus flag
49 : : const ScMatValType SC_MATVAL_EMPTYPATH = SC_MATVAL_EMPTY | 0x08; // EMPTY plus flag
50 : : const ScMatValType SC_MATVAL_NONVALUE = SC_MATVAL_EMPTYPATH; // mask of all non-value bits
51 : :
52 : : /**
53 : : * Try NOT to use this struct. This struct should go away in a hopefully
54 : : * not so distant futture.
55 : : */
56 : 1632 : struct ScMatrixValue
57 : : {
58 : : double fVal;
59 : : rtl::OUString aStr;
60 : : ScMatValType nType;
61 : :
62 : : /// Only valid if ScMatrix methods indicate so!
63 : 6 : const ::rtl::OUString& GetString() const { return aStr; }
64 : :
65 : : /// Only valid if ScMatrix methods indicate that this is no string!
66 : 3 : sal_uInt16 GetError() const { return GetDoubleErrorValue( fVal); }
67 : :
68 : : /// Only valid if ScMatrix methods indicate that this is a boolean
69 : 0 : bool GetBoolean() const { return fVal != 0.0; }
70 : :
71 : 1632 : ScMatrixValue() : fVal(0.0), nType(SC_MATVAL_EMPTY) {}
72 : :
73 : : ScMatrixValue(const ScMatrixValue& r) :
74 : : fVal(r.fVal), aStr(r.aStr), nType(r.nType) {}
75 : :
76 : 0 : bool operator== (const ScMatrixValue& r) const
77 : : {
78 [ # # ]: 0 : if (nType != r.nType)
79 : 0 : return false;
80 : :
81 [ # # ]: 0 : switch (nType)
82 : : {
83 : : case SC_MATVAL_VALUE:
84 : : case SC_MATVAL_BOOLEAN:
85 : 0 : return fVal == r.fVal;
86 : : break;
87 : : default:
88 : : ;
89 : : }
90 : :
91 : 0 : return aStr == r.aStr;
92 : : }
93 : :
94 : 0 : bool operator!= (const ScMatrixValue& r) const
95 : : {
96 : 0 : return !operator==(r);
97 : : }
98 : :
99 : 9 : ScMatrixValue& operator= (const ScMatrixValue& r)
100 : : {
101 [ - + ]: 9 : if (this == &r)
102 : 0 : return *this;
103 : :
104 : 9 : nType = r.nType;
105 : 9 : fVal = r.fVal;
106 : 9 : aStr = r.aStr;
107 : 9 : return *this;
108 : : }
109 : : };
110 : :
111 : : /**
112 : : * Matrix data type that can store values of mixed types. Each element can
113 : : * be one of the following types: numeric, string, boolean, empty, and empty
114 : : * path.
115 : : */
116 : : class SC_DLLPUBLIC ScMatrix
117 : : {
118 : : ScMatrixImpl* pImpl;
119 : : mutable size_t nRefCnt; // reference count
120 : :
121 : : // only delete via Delete()
122 : : ~ScMatrix();
123 : :
124 : : // not implemented, prevent usage
125 : : ScMatrix( const ScMatrix& );
126 : : ScMatrix& operator=( const ScMatrix&);
127 : :
128 : : public:
129 : : /**
130 : : * When adding all numerical matrix elements for a scalar result such as
131 : : * summation, the interpreter wants to separate the first non-zero value
132 : : * with the rest of the summed values.
133 : : *
134 : : * TODO: Find out if we still need to do this. If not, we can re-write
135 : : * ScInterpreter::IterateParameters() to make it simpler and remove this
136 : : * struct.
137 : : */
138 : : struct IterateResult
139 : : {
140 : : double mfFirst;
141 : : double mfRest;
142 : : size_t mnCount;
143 : :
144 : 15 : IterateResult(double fFirst, double fRest, size_t nCount) :
145 : 15 : mfFirst(fFirst), mfRest(fRest), mnCount(nCount) {}
146 : :
147 : 15 : IterateResult(const IterateResult& r) :
148 : 15 : mfFirst(r.mfFirst), mfRest(r.mfRest), mnCount(r.mnCount) {}
149 : : };
150 : :
151 : : /// The maximum number of elements a matrix may have at runtime.
152 : 82 : inline static size_t GetElementsMax()
153 : : {
154 : : // TODO: Fix me.
155 : 82 : return 0x08000000;
156 : : #if 0
157 : : // Roughly 125MB in total, divided by 8+1 per element => 14M elements.
158 : : const size_t nMemMax = 0x08000000 / (sizeof(ScMatrixValue) + sizeof(ScMatValType));
159 : : // With MAXROWCOUNT==65536 and 128 columns => 8M elements ~72MB.
160 : : const size_t nArbitraryLimit = (size_t)MAXROWCOUNT * 128;
161 : : // Stuffed with a million rows would limit this to 14 columns.
162 : : return nMemMax < nArbitraryLimit ? nMemMax : nArbitraryLimit;
163 : : #endif
164 : : }
165 : :
166 : : /// Value or boolean.
167 : 18 : inline static bool IsValueType( ScMatValType nType )
168 : : {
169 : 18 : return nType <= SC_MATVAL_BOOLEAN;
170 : : }
171 : :
172 : : /// Boolean.
173 : 0 : inline static bool IsBooleanType( ScMatValType nType )
174 : : {
175 : 0 : return nType == SC_MATVAL_BOOLEAN;
176 : : }
177 : :
178 : : /// String, empty or empty path, but not value nor boolean.
179 : 174 : inline static bool IsNonValueType( ScMatValType nType )
180 : : {
181 : 174 : return (nType & SC_MATVAL_NONVALUE) != 0;
182 : : }
183 : :
184 : : /** String, but not empty or empty path or any other type.
185 : : Not named IsStringType to prevent confusion because previously
186 : : IsNonValueType was named IsStringType. */
187 : 0 : inline static bool IsRealStringType( ScMatValType nType )
188 : : {
189 : 0 : return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_STRING;
190 : : }
191 : :
192 : : /// Empty, but not empty path or any other type.
193 : 3 : inline static bool IsEmptyType( ScMatValType nType )
194 : : {
195 : 3 : return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTY;
196 : : }
197 : :
198 : : /// Empty path, but not empty or any other type.
199 : 3 : inline static bool IsEmptyPathType( ScMatValType nType )
200 : : {
201 : 3 : return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTYPATH;
202 : : }
203 : :
204 : : ScMatrix(SCSIZE nC, SCSIZE nR);
205 : : ScMatrix(SCSIZE nC, SCSIZE nR, double fInitVal);
206 : :
207 : : /** Clone the matrix. */
208 : : ScMatrix* Clone() const;
209 : :
210 : : /** Clone the matrix if mbCloneIfConst (immutable) is set, otherwise
211 : : return _this_ matrix, to be assigned to a ScMatrixRef. */
212 : : ScMatrix* CloneIfConst();
213 : :
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 );
217 : :
218 : : /**
219 : : * Resize the matrix to specified new dimension.
220 : : */
221 : : void Resize( SCSIZE nC, SCSIZE nR);
222 : :
223 : : void Resize(SCSIZE nC, SCSIZE nR, double fVal);
224 : :
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;
228 : :
229 : 1708 : inline void IncRef() const
230 : : {
231 : 1708 : ++nRefCnt;
232 : 1708 : }
233 : 1708 : inline void DecRef() const
234 : : {
235 : 1708 : --nRefCnt;
236 [ + + ]: 1708 : if (nRefCnt == 0)
237 [ + - ]: 275 : delete this;
238 : 1708 : }
239 : :
240 : : void SetErrorInterpreter( ScInterpreter* p);
241 : : void GetDimensions( SCSIZE& rC, SCSIZE& rR) const;
242 : : SCSIZE GetElementCount() const;
243 : : bool ValidColRow( SCSIZE nC, SCSIZE nR) const;
244 : : SCSIZE CalcOffset( SCSIZE nC, SCSIZE nR) const;
245 : :
246 : : /** For a row vector or column vector, if the position does not point into
247 : : the vector but is a valid column or row offset it is adapted such that
248 : : it points to an element to be replicated, same column row 0 for a row
249 : : vector, same row column 0 for a column vector. Else, for a 2D matrix,
250 : : returns false.
251 : : */
252 : : bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const;
253 : :
254 : : /** Checks if the matrix position is within the matrix. If it is not, for a
255 : : row vector or column vector the position is adapted such that it points
256 : : to an element to be replicated, same column row 0 for a row vector,
257 : : same row column 0 for a column vector. Else, for a 2D matrix and
258 : : position not within matrix, returns false.
259 : : */
260 : : bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const;
261 : :
262 : : void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
263 : : void PutDouble( double fVal, SCSIZE nIndex);
264 : : void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR);
265 : :
266 : : void PutString( const ::rtl::OUString& rStr, SCSIZE nC, SCSIZE nR);
267 : : void PutString( const ::rtl::OUString& rStr, SCSIZE nIndex);
268 : : void PutString(const rtl::OUString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR);
269 : :
270 : : void PutEmpty( SCSIZE nC, SCSIZE nR);
271 : :
272 : : /// Jump FALSE without path
273 : : void PutEmptyPath( SCSIZE nC, SCSIZE nR);
274 : : void PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR );
275 : : void PutBoolean( bool bVal, SCSIZE nC, SCSIZE nR);
276 : :
277 : : void FillDouble( double fVal,
278 : : SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 );
279 : :
280 : : /** May be used before obtaining the double value of an element to avoid
281 : : passing its NAN around.
282 : : @ATTENTION: MUST NOT be used if the element is a string!
283 : : Use GetErrorIfNotString() instead if not sure.
284 : : @returns 0 if no error, else one of err... constants */
285 : : sal_uInt16 GetError( SCSIZE nC, SCSIZE nR) const;
286 : :
287 : : /** Use in ScInterpreter to obtain the error code, if any.
288 : : @returns 0 if no error or string element, else one of err... constants */
289 : 0 : sal_uInt16 GetErrorIfNotString( SCSIZE nC, SCSIZE nR) const
290 [ # # ]: 0 : { return IsValue( nC, nR) ? GetError( nC, nR) : 0; }
291 : :
292 : : /// @return 0.0 if empty or empty path, else value or DoubleError.
293 : : double GetDouble( SCSIZE nC, SCSIZE nR) const;
294 : : /// @return 0.0 if empty or empty path, else value or DoubleError.
295 : : double GetDouble( SCSIZE nIndex) const;
296 : :
297 : : /// @return empty string if empty or empty path, else string content.
298 : : rtl::OUString GetString( SCSIZE nC, SCSIZE nR) const;
299 : : /// @return empty string if empty or empty path, else string content.
300 : : rtl::OUString GetString( SCSIZE nIndex) const;
301 : :
302 : : /** @returns the matrix element's string if one is present, otherwise the
303 : : numerical value formatted as string, or in case of an error the error
304 : : string is returned; an empty string for empty, a "FALSE" string for
305 : : empty path. */
306 : : ::rtl::OUString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const;
307 : :
308 : : /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
309 : : /// an empty string!
310 : : ScMatrixValue Get( SCSIZE nC, SCSIZE nR) const;
311 : :
312 : : /// @return <TRUE/> if string or empty or empty path, in fact non-value.
313 : : sal_Bool IsString( SCSIZE nIndex ) const;
314 : :
315 : : /// @return <TRUE/> if string or empty or empty path, in fact non-value.
316 : : sal_Bool IsString( SCSIZE nC, SCSIZE nR ) const;
317 : :
318 : : /// @return <TRUE/> if empty or empty path.
319 : : sal_Bool IsEmpty( SCSIZE nC, SCSIZE nR ) const;
320 : :
321 : : /// @return <TRUE/> if empty path.
322 : : sal_Bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const;
323 : :
324 : : /// @return <TRUE/> if value or boolean.
325 : : sal_Bool IsValue( SCSIZE nIndex ) const;
326 : :
327 : : /// @return <TRUE/> if value or boolean.
328 : : sal_Bool IsValue( SCSIZE nC, SCSIZE nR ) const;
329 : :
330 : : /// @return <TRUE/> if value or boolean or empty or empty path.
331 : : sal_Bool IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const;
332 : :
333 : : /// @return <TRUE/> if boolean.
334 : : sal_Bool IsBoolean( SCSIZE nC, SCSIZE nR ) const;
335 : :
336 : : /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
337 : : sal_Bool IsNumeric() const;
338 : :
339 : : void MatTrans( ScMatrix& mRes) const;
340 : : void MatCopy ( ScMatrix& mRes) const;
341 : :
342 : : // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
343 : : void CompareEqual();
344 : : void CompareNotEqual();
345 : : void CompareLess();
346 : : void CompareGreater();
347 : : void CompareLessEqual();
348 : : void CompareGreaterEqual();
349 : :
350 : : double And() const; // logical AND of all matrix values, or NAN
351 : : double Or() const; // logical OR of all matrix values, or NAN
352 : :
353 : : IterateResult Sum(bool bTextAsZero) const;
354 : : IterateResult SumSquare(bool bTextAsZero) const;
355 : : IterateResult Product(bool bTextAsZero) const;
356 : : size_t Count(bool bCountStrings) const;
357 : :
358 : : // All other matrix functions MatMult, MInv, ... are in ScInterpreter
359 : : // to be numerically safe.
360 : : };
361 : :
362 : 1705 : inline void intrusive_ptr_add_ref(const ScMatrix* p)
363 : : {
364 : 1705 : p->IncRef();
365 : 1705 : }
366 : :
367 : 1705 : inline void intrusive_ptr_release(const ScMatrix* p)
368 : : {
369 : 1705 : p->DecRef();
370 : 1705 : }
371 : :
372 : : #endif // SC_MATRIX_HXX
373 : :
374 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|