summaryrefslogtreecommitdiff
path: root/sc/inc/scmatrix.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/inc/scmatrix.hxx')
-rw-r--r--sc/inc/scmatrix.hxx383
1 files changed, 383 insertions, 0 deletions
diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
new file mode 100644
index 000000000000..8e14c4694d8a
--- /dev/null
+++ b/sc/inc/scmatrix.hxx
@@ -0,0 +1,383 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SC_MATRIX_HXX
+#define SC_MATRIX_HXX
+
+#include "global.hxx"
+#include "types.hxx"
+#include "formula/errorcodes.hxx"
+#include <tools/string.hxx>
+#include "scdllapi.h"
+
+#include <boost/intrusive_ptr.hpp>
+
+class SvStream;
+class ScInterpreter;
+class SvNumberFormatter;
+class ScMatrixImpl;
+
+typedef sal_uInt8 ScMatValType;
+const ScMatValType SC_MATVAL_VALUE = 0x00;
+const ScMatValType SC_MATVAL_BOOLEAN = 0x01;
+const ScMatValType SC_MATVAL_STRING = 0x02;
+const ScMatValType SC_MATVAL_EMPTY = SC_MATVAL_STRING | 0x04; // STRING plus flag
+const ScMatValType SC_MATVAL_EMPTYPATH = SC_MATVAL_EMPTY | 0x08; // EMPTY plus flag
+const ScMatValType SC_MATVAL_NONVALUE = SC_MATVAL_EMPTYPATH; // mask of all non-value bits
+
+struct ScMatrixValue
+{
+ union {
+ double fVal;
+ const String* pS;
+ };
+ ScMatValType nType;
+
+ /// Only valid if ScMatrix methods indicate so!
+ const String& GetString() const { return pS ? *pS : EMPTY_STRING; }
+
+ /// Only valid if ScMatrix methods indicate that this is no string!
+ sal_uInt16 GetError() const { return GetDoubleErrorValue( fVal); }
+
+ /// Only valid if ScMatrix methods indicate that this is a boolean
+ bool GetBoolean() const { return fVal != 0.0; }
+
+ ScMatrixValue() : fVal(0.0), nType(SC_MATVAL_EMPTY) {}
+
+ ScMatrixValue(const ScMatrixValue& r) : fVal(r.fVal), nType(r.nType)
+ {
+ if (nType == SC_MATVAL_STRING)
+ // This is probably not necessary but just in case...
+ pS = r.pS;
+ }
+
+ bool operator== (const ScMatrixValue& r) const
+ {
+ if (nType != r.nType)
+ return false;
+
+ switch (nType)
+ {
+ case SC_MATVAL_VALUE:
+ case SC_MATVAL_BOOLEAN:
+ return fVal == r.fVal;
+ break;
+ default:
+ ;
+ }
+ if (!pS)
+ return r.pS == NULL;
+
+ return GetString().Equals(r.GetString());
+ }
+
+ bool operator!= (const ScMatrixValue& r) const
+ {
+ return !operator==(r);
+ }
+
+ ScMatrixValue& operator= (const ScMatrixValue& r)
+ {
+ nType = r.nType;
+ fVal = r.fVal;
+
+ if (nType == SC_MATVAL_STRING)
+ // This is probably not necessary but just in case...
+ pS = r.pS;
+
+ return *this;
+ }
+};
+
+/**
+ * Matrix data type that can store values of mixed types. Each element can
+ * be one of the following types: numeric, string, boolean, empty, and empty
+ * path.
+ *
+ * This class also supports four different density types: filled zero,
+ * filled empty, sparse zero, and sparse empty. The filled density type
+ * allocates memory for every single element at all times, whereas the
+ * sparse density types allocates memory only for non-default elements.
+ */
+class SC_DLLPUBLIC ScMatrix
+{
+ ScMatrixImpl* pImpl;
+ mutable size_t nRefCnt; // reference count
+
+ // only delete via Delete()
+ ~ScMatrix();
+
+ // not implemented, prevent usage
+ ScMatrix( const ScMatrix& );
+ ScMatrix& operator=( const ScMatrix&);
+
+public:
+ enum DensityType
+ {
+ FILLED_ZERO,
+ FILLED_EMPTY,
+ SPARSE_ZERO,
+ SPARSE_EMPTY
+ };
+
+ /**
+ * When adding all numerical matrix elements for a scalar result such as
+ * summation, the interpreter wants to separate the first non-zero value
+ * with the rest of the summed values.
+ *
+ * TODO: Find out if we still need to do this. If not, we can re-write
+ * ScInterpreter::IterateParameters() to make it simpler and remove this
+ * struct.
+ */
+ struct IterateResult
+ {
+ double mfFirst;
+ double mfRest;
+ size_t mnCount;
+
+ IterateResult(double fFirst, double fRest, size_t nCount) :
+ mfFirst(fFirst), mfRest(fRest), mnCount(nCount) {}
+
+ IterateResult(const IterateResult& r) :
+ mfFirst(r.mfFirst), mfRest(r.mfRest), mnCount(r.mnCount) {}
+ };
+
+ /// The maximum number of elements a matrix may have at runtime.
+ inline static size_t GetElementsMax()
+ {
+ // Roughly 125MB in total, divided by 8+1 per element => 14M elements.
+ const size_t nMemMax = 0x08000000 / (sizeof(ScMatrixValue) + sizeof(ScMatValType));
+ // With MAXROWCOUNT==65536 and 128 columns => 8M elements ~72MB.
+ const size_t nArbitraryLimit = (size_t)MAXROWCOUNT * 128;
+ // Stuffed with a million rows would limit this to 14 columns.
+ return nMemMax < nArbitraryLimit ? nMemMax : nArbitraryLimit;
+ }
+
+ /// Value or boolean.
+ inline static bool IsValueType( ScMatValType nType )
+ {
+ return nType <= SC_MATVAL_BOOLEAN;
+ }
+
+ /// Boolean.
+ inline static bool IsBooleanType( ScMatValType nType )
+ {
+ return nType == SC_MATVAL_BOOLEAN;
+ }
+
+ /// String, empty or empty path, but not value nor boolean.
+ inline static bool IsNonValueType( ScMatValType nType )
+ {
+ return (nType & SC_MATVAL_NONVALUE) != 0;
+ }
+
+ /** String, but not empty or empty path or any other type.
+ Not named IsStringType to prevent confusion because previously
+ IsNonValueType was named IsStringType. */
+ inline static bool IsRealStringType( ScMatValType nType )
+ {
+ return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_STRING;
+ }
+
+ /// Empty, but not empty path or any other type.
+ inline static bool IsEmptyType( ScMatValType nType )
+ {
+ return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTY;
+ }
+
+ /// Empty path, but not empty or any other type.
+ inline static bool IsEmptyPathType( ScMatValType nType )
+ {
+ return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTYPATH;
+ }
+
+ ScMatrix( SCSIZE nC, SCSIZE nR, DensityType eType = FILLED_ZERO);
+
+ /** Clone the matrix. */
+ ScMatrix* Clone() const;
+ ScMatrix* Clone( DensityType eType) const;
+
+ /** Clone the matrix if mbCloneIfConst (immutable) is set, otherwise
+ return _this_ matrix, to be assigned to a ScMatrixRef. */
+ ScMatrix* CloneIfConst();
+
+ /** Set the matrix to (im)mutable for CloneIfConst(), only the interpreter
+ should do this and know the consequences. */
+ void SetImmutable( bool bVal );
+
+ /**
+ * Resize the matrix to specified new dimension.
+ */
+ void Resize( SCSIZE nC, SCSIZE nR);
+
+ /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
+ MUST be at least of the size of the original matrix. */
+ ScMatrix* CloneAndExtend( SCSIZE nNewCols, SCSIZE nNewRows, DensityType eType) const;
+
+ inline void IncRef() const
+ {
+ ++nRefCnt;
+ }
+ inline void DecRef() const
+ {
+ --nRefCnt;
+ if (nRefCnt == 0)
+ delete this;
+ }
+
+ DensityType GetDensityType() const;
+ void SetErrorInterpreter( ScInterpreter* p);
+ void GetDimensions( SCSIZE& rC, SCSIZE& rR) const;
+ SCSIZE GetElementCount() const;
+ bool ValidColRow( SCSIZE nC, SCSIZE nR) const;
+ SCSIZE CalcOffset( SCSIZE nC, SCSIZE nR) const;
+
+ /** For a row vector or column vector, if the position does not point into
+ the vector but is a valid column or row offset it is adapted such that
+ it points to an element to be replicated, same column row 0 for a row
+ vector, same row column 0 for a column vector. Else, for a 2D matrix,
+ returns false.
+ */
+ bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const;
+
+ /** Checks if the matrix position is within the matrix. If it is not, for a
+ row vector or column vector the position is adapted such that it points
+ to an element to be replicated, same column row 0 for a row vector,
+ same row column 0 for a column vector. Else, for a 2D matrix and
+ position not within matrix, returns false.
+ */
+ bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const;
+
+ void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
+ void PutDouble( double fVal, SCSIZE nIndex);
+ void PutString( const String& rStr, SCSIZE nC, SCSIZE nR);
+ void PutString( const String& rStr, SCSIZE nIndex);
+ void PutEmpty( SCSIZE nC, SCSIZE nR);
+ /// Jump FALSE without path
+ void PutEmptyPath( SCSIZE nC, SCSIZE nR);
+ void PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR );
+ void PutBoolean( bool bVal, SCSIZE nC, SCSIZE nR);
+
+ void FillDouble( double fVal,
+ SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 );
+
+ /** May be used before obtaining the double value of an element to avoid
+ passing its NAN around.
+ @ATTENTION: MUST NOT be used if the element is a string!
+ Use GetErrorIfNotString() instead if not sure.
+ @returns 0 if no error, else one of err... constants */
+ sal_uInt16 GetError( SCSIZE nC, SCSIZE nR) const;
+
+ /** Use in ScInterpreter to obtain the error code, if any.
+ @returns 0 if no error or string element, else one of err... constants */
+ sal_uInt16 GetErrorIfNotString( SCSIZE nC, SCSIZE nR) const
+ { return IsValue( nC, nR) ? GetError( nC, nR) : 0; }
+
+ /// @return 0.0 if empty or empty path, else value or DoubleError.
+ double GetDouble( SCSIZE nC, SCSIZE nR) const;
+ /// @return 0.0 if empty or empty path, else value or DoubleError.
+ double GetDouble( SCSIZE nIndex) const;
+
+ /// @return empty string if empty or empty path, else string content.
+ const String& GetString( SCSIZE nC, SCSIZE nR) const;
+ /// @return empty string if empty or empty path, else string content.
+ const String& GetString( SCSIZE nIndex) const;
+
+ /** @returns the matrix element's string if one is present, otherwise the
+ numerical value formatted as string, or in case of an error the error
+ string is returned; an empty string for empty, a "FALSE" string for
+ empty path. */
+ String GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const;
+
+ /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
+ /// an empty string!
+ ScMatrixValue Get( SCSIZE nC, SCSIZE nR) const;
+
+ /// @return <TRUE/> if string or empty or empty path, in fact non-value.
+ sal_Bool IsString( SCSIZE nIndex ) const;
+
+ /// @return <TRUE/> if string or empty or empty path, in fact non-value.
+ sal_Bool IsString( SCSIZE nC, SCSIZE nR ) const;
+
+ /// @return <TRUE/> if empty or empty path.
+ sal_Bool IsEmpty( SCSIZE nC, SCSIZE nR ) const;
+
+ /// @return <TRUE/> if empty path.
+ sal_Bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const;
+
+ /// @return <TRUE/> if value or boolean.
+ sal_Bool IsValue( SCSIZE nIndex ) const;
+
+ /// @return <TRUE/> if value or boolean.
+ sal_Bool IsValue( SCSIZE nC, SCSIZE nR ) const;
+
+ /// @return <TRUE/> if value or boolean or empty or empty path.
+ sal_Bool IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const;
+
+ /// @return <TRUE/> if boolean.
+ sal_Bool IsBoolean( SCSIZE nC, SCSIZE nR ) const;
+
+ /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
+ sal_Bool IsNumeric() const;
+
+ void MatTrans( ScMatrix& mRes) const;
+ void MatCopy ( ScMatrix& mRes) const;
+
+ // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
+ void CompareEqual();
+ void CompareNotEqual();
+ void CompareLess();
+ void CompareGreater();
+ void CompareLessEqual();
+ void CompareGreaterEqual();
+
+ double And() const; // logical AND of all matrix values, or NAN
+ double Or() const; // logical OR of all matrix values, or NAN
+
+ IterateResult Sum(bool bTextAsZero) const;
+ IterateResult SumSquare(bool bTextAsZero) const;
+ IterateResult Product(bool bTextAsZero) const;
+ size_t Count(bool bCountStrings) const;
+
+ // All other matrix functions MatMult, MInv, ... are in ScInterpreter
+ // to be numerically safe.
+};
+
+inline void intrusive_ptr_add_ref(const ScMatrix* p)
+{
+ p->IncRef();
+}
+
+inline void intrusive_ptr_release(const ScMatrix* p)
+{
+ p->DecRef();
+}
+
+#endif // SC_MATRIX_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */