Index: inc/scmatrix.hxx
===================================================================
RCS file: /cvs/sc/sc/inc/scmatrix.hxx,v
retrieving revision 1.11
diff -p -u -r1.11 scmatrix.hxx
--- inc/scmatrix.hxx 10 Apr 2008 18:51:53 -0000 1.11
+++ inc/scmatrix.hxx 27 Aug 2008 11:58:16 -0000
@@ -66,27 +66,32 @@ union ScMatrixValue
@ATTENTION: optimized for speed and double values.
- Matrix elements are NOT initialized after construction!
+
Matrix elements are NOT initialized after construction!
- All methods using an SCSIZE nIndex parameter and all Is... methods do NOT
- check the range for validity! However, the Put... and Get... methods using
- nCol/nRow parameters do check the range.
+
All methods using an SCSIZE nIndex parameter and all Is...() methods do
+ NOT check the range for validity! However, the Put...() and Get...()
+ methods using nCol/nRow parameters do check the range.
+
+
Methods using nCol/nRow parameters do replicate a single row vector if
+ nRow > 0 and nCol < nColCount, respectively a column vector if nCol
+ > 0 and nRow < nRowCount.
- GetString( SCSIZE nIndex ) does not check if there really is a string, do
- this with IsString() first. GetString( SCSIZE nC, SCSIZE nR ) does check
+
GetString( SCSIZE nIndex ) does not check if there really is a string,
+ do this with IsString() first. GetString( SCSIZE nC, SCSIZE nR ) does check
it and returns and empty string if there is no string. Both GetDouble()
- methods don't check for a string, do this with IsNumeric() or IsString()
- or IsValue() first.
+ methods don't check for a string, do this with IsNumeric() or IsString() or
+ IsValue() first.
- The GetString( SvNumberFormatter&, ...) methods return the matrix element's
- string if one is present, otherwise the numerical value is formatted as a
- string, or in case of an error the error string is returned.
+
The GetString( SvNumberFormatter&, ...) methods return the matrix
+ element's string if one is present, otherwise the numerical value is
+ formatted as a string, or in case of an error the error string is returned.
- PutDouble() does not reset an eventual string! Use
+
PutDouble() does not reset an eventual string! Use
PutDoubleAndResetString() if that is wanted. Also the FillDouble...()
methods don't reset strings. As a consequence memory leaks may occur if
used wrong.
*/
+
class ScMatrix
{
ScMatrixValue* pMat;
@@ -115,7 +120,7 @@ class ScMatrix
public:
- /// The maximum number of elements a matrix may have at runtime
+ /// The maximum number of elements a matrix may have at runtime.
inline static size_t GetElementsMax()
{
const size_t nMemMax = (((size_t)(~0))-64) / sizeof(ScMatrixValue);
@@ -157,9 +162,15 @@ public:
created instead and a double error value (errStackOverflow) is set.
Compare nC and nR with a GetDimensions() call to check. */
ScMatrix( SCSIZE nC, SCSIZE nR) : nRefCnt(0) { CreateMatrix( nC, nR); }
+
+ /** Clone the matrix. */
ScMatrix* Clone() const;
- /// disable refcounting forever, may only be deleted via Delete() afterwards
+ /** 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 ) const;
+
+ /// Disable refcounting forever, may only be deleted via Delete() afterwards.
inline void SetEternalRef() { nRefCnt = ULONG_MAX; }
inline bool IsEternalRef() const { return nRefCnt == ULONG_MAX; }
inline void IncRef() const
@@ -196,6 +207,45 @@ public:
inline SCSIZE CalcOffset( SCSIZE nC, SCSIZE nR) const
{ return nC * nRowCount + nR; }
+ /** 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.
+ */
+ inline bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const
+ {
+ if (nColCount == 1 && nRowCount == 1)
+ {
+ rC = 0;
+ rR = 0;
+ return true;
+ }
+ else if (nColCount == 1 && rR < nRowCount)
+ {
+ rC = 0;
+ return true;
+ }
+ else if (nRowCount == 1 && rC < nColCount)
+ {
+ rR = 0;
+ return true;
+ }
+ return false;
+ }
+
+ /** 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.
+ */
+ inline bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const
+ {
+ return ValidColRow( rC, rR) || ValidColRowReplicated( rC, rR);
+ }
+
+
void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
void PutDouble( double fVal, SCSIZE nIndex)
{ pMat[nIndex].fVal = fVal; }
@@ -262,32 +312,61 @@ public:
/// @return if string or empty
BOOL IsString( SCSIZE nIndex ) const
{ return mnValType && IsStringType( mnValType[nIndex]); }
+
/// @return if string or empty
BOOL IsString( SCSIZE nC, SCSIZE nR ) const
- { return mnValType && IsStringType( mnValType[ nC * nRowCount + nR ]); }
+ {
+ ValidColRowReplicated( nC, nR );
+ return mnValType && IsStringType( mnValType[ nC * nRowCount + nR ]);
+ }
+
BOOL IsEmpty( SCSIZE nIndex ) const
{ return mnValType && ((mnValType[nIndex] & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
+
BOOL IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
- { return mnValType && ((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTYPATH) == SC_MATVAL_EMPTYPATH); }
+ {
+ ValidColRowReplicated( nC, nR );
+ return mnValType && ((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTYPATH) == SC_MATVAL_EMPTYPATH);
+ }
+
BOOL IsEmptyPath( SCSIZE nIndex ) const
{ return mnValType && ((mnValType[nIndex] & SC_MATVAL_EMPTYPATH) == SC_MATVAL_EMPTYPATH); }
+
BOOL IsEmpty( SCSIZE nC, SCSIZE nR ) const
- { return mnValType && ((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
+ {
+ ValidColRowReplicated( nC, nR );
+ return mnValType && ((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY);
+ }
+
BOOL IsValue( SCSIZE nIndex ) const
{ return !mnValType || IsValueType( mnValType[nIndex]); }
+
BOOL IsValue( SCSIZE nC, SCSIZE nR ) const
- { return !mnValType || IsValueType( mnValType[ nC * nRowCount + nR ]); }
+ {
+ ValidColRowReplicated( nC, nR );
+ return !mnValType || IsValueType( mnValType[ nC * nRowCount + nR ]);
+ }
+
BOOL IsValueOrEmpty( SCSIZE nIndex ) const
{ return !mnValType || IsValueType( mnValType[nIndex] ) ||
((mnValType[nIndex] & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
+
BOOL IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
- { return !mnValType || IsValueType( mnValType[ nC * nRowCount + nR ]) ||
+ {
+ ValidColRowReplicated( nC, nR );
+ return !mnValType || IsValueType( mnValType[ nC * nRowCount + nR ]) ||
((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTY) ==
- SC_MATVAL_EMPTY); }
+ SC_MATVAL_EMPTY);
+ }
+
BOOL IsBoolean( SCSIZE nIndex ) const
{ return mnValType && IsBooleanType( mnValType[nIndex]); }
+
BOOL IsBoolean( SCSIZE nC, SCSIZE nR ) const
- { return mnValType && IsBooleanType( mnValType[ nC * nRowCount + nR ]); }
+ {
+ ValidColRowReplicated( nC, nR );
+ return mnValType && IsBooleanType( mnValType[ nC * nRowCount + nR ]);
+ }
/// @return if entire matrix is numeric, including booleans, with no strings or empties
BOOL IsNumeric() const
@@ -295,9 +374,11 @@ public:
void MatTrans( ScMatrix& mRes) const;
void MatCopy ( ScMatrix& mRes) const;
+
/** Copy upper left of this matrix to mRes matrix.
- This matrix's dimensions must be greater than the mRes matrix
- dimensions. */
+ This matrix's dimensions must be greater or equal to the mRes matrix
+ dimensions.
+ */
void MatCopyUpperLeft( ScMatrix& mRes) const;
// Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
@@ -320,17 +401,4 @@ typedef ScSimpleIntrusiveReference< clas
typedef ScSimpleIntrusiveReference< const class ScMatrix > ScConstMatrixRef;
-// Old values as used up to SO52.
-// The overall elements count had to be <= SC_MAX_MAT_DIM * SC_MAX_MAT_DIM.
-// Don't use except maybe for file format compatibility.
-// In any other case use ScMatrix::GetElementsMax() instead.
-#ifdef WIN
-#define SC_OLD_MAX_MAT_DIM 64
-#else
-#define SC_OLD_MAX_MAT_DIM 128
-#endif
-#define SC_OLD_MAX_MAT_ELEMENTS ((SC_OLD_MAX_MAT_DIM) * (SC_OLD_MAX_MAT_DIM))
-
-
-#endif
-
+#endif // SC_MATRIX_HXX
Index: source/core/inc/jumpmatrix.hxx
===================================================================
RCS file: /cvs/sc/sc/source/core/inc/jumpmatrix.hxx,v
retrieving revision 1.6
diff -p -u -r1.6 jumpmatrix.hxx
--- source/core/inc/jumpmatrix.hxx 10 Apr 2008 19:40:01 -0000 1.6
+++ source/core/inc/jumpmatrix.hxx 27 Aug 2008 11:58:17 -0000
@@ -73,6 +73,8 @@ class ScJumpMatrix
SCSIZE nRows;
SCSIZE nCurCol;
SCSIZE nCurRow;
+ SCSIZE nResMatCols;
+ SCSIZE nResMatRows;
bool bStarted;
// not implemented, prevent usage
@@ -88,6 +90,8 @@ public:
, nRows( nRowsP )
, nCurCol( 0 )
, nCurRow( 0 )
+ , nResMatCols( nColsP )
+ , nResMatRows( nRowsP )
, bStarted( false )
{
// Initialize result matrix in case of
@@ -128,6 +132,21 @@ public:
short& rStart, short& rNext,
short& rStop ) const
{
+ if (nCols == 1 && nRows == 1)
+ {
+ nCol = 0;
+ nRow = 0;
+ }
+ else if (nCols == 1 && nRow < nRows)
+ nCol = 0;
+ else if (nRows == 1 && nCol < nCols)
+ nRow = 0;
+ else if (nCols <= nCol || nRows <= nRow)
+ {
+ DBG_ERROR("ScJumpMatrix::GetJump: dimension error");
+ nCol = 0;
+ nRow = 0;
+ }
pJump[ (ULONG)nCol * nRows + nRow ].
GetJump( rBool, rStart, rNext, rStop);
}
@@ -160,14 +179,45 @@ public:
}
else
{
- if ( ++nCurRow >= nRows )
+ if ( ++nCurRow >= nResMatRows )
{
nCurRow = 0;
++nCurCol;
}
}
GetPos( rCol, rRow );
- return nCurCol < nCols;
+ return nCurCol < nResMatCols;
+ }
+ void GetResMatDimensions( SCSIZE& rCols, SCSIZE& rRows )
+ {
+ rCols = nResMatCols;
+ rRows = nResMatRows;
+ }
+ void SetNewResMat( SCSIZE nNewCols, SCSIZE nNewRows )
+ {
+ if ( nNewCols > nResMatCols || nNewRows > nResMatRows )
+ {
+ pMat = pMat->CloneAndExtend( nNewCols, nNewRows );
+ if ( nResMatCols < nNewCols )
+ {
+ pMat->FillDouble( CreateDoubleError(
+ NOTAVAILABLE), nResMatCols, 0, nNewCols-1,
+ nResMatRows-1);
+ }
+ if ( nResMatRows < nNewRows )
+ {
+ pMat->FillDouble( CreateDoubleError(
+ NOTAVAILABLE), 0, nResMatRows, nNewCols-1,
+ nNewRows-1);
+ }
+ if ( nRows == 1 && nCurCol != 0 )
+ {
+ nCurCol = 0;
+ nCurRow = nResMatRows - 1;
+ }
+ nResMatCols = nNewCols;
+ nResMatRows = nNewRows;
+ }
}
};
Index: source/core/tool/interpr1.cxx
===================================================================
RCS file: /cvs/sc/sc/source/core/tool/interpr1.cxx,v
retrieving revision 1.60
diff -p -u -r1.60 interpr1.cxx
--- source/core/tool/interpr1.cxx 8 Jul 2008 07:20:44 -0000 1.60
+++ source/core/tool/interpr1.cxx 27 Aug 2008 11:58:18 -0000
@@ -309,6 +309,37 @@ void ScInterpreter::ScChoseJump()
}
+void lcl_AdjustJumpMatrix( ScJumpMatrix* pJumpM, ScMatrixRef& pResMat, SCSIZE nParmCols, SCSIZE nParmRows )
+{
+ SCSIZE nJumpCols, nJumpRows;
+ SCSIZE nResCols, nResRows;
+ SCSIZE nAdjustCols, nAdjustRows;
+ pJumpM->GetDimensions( nJumpCols, nJumpRows );
+ pJumpM->GetResMatDimensions( nResCols, nResRows );
+ if (( nJumpCols == 1 && nParmCols > nResCols ) ||
+ ( nJumpRows == 1 && nParmRows > nResRows ))
+ {
+ if ( nJumpCols == 1 && nJumpRows == 1 )
+ {
+ nAdjustCols = nParmCols > nResCols ? nParmCols : nResCols;
+ nAdjustRows = nParmRows > nResRows ? nParmRows : nResRows;
+ }
+ else if ( nJumpCols == 1 )
+ {
+ nAdjustCols = nParmCols;
+ nAdjustRows = nResRows;
+ }
+ else
+ {
+ nAdjustCols = nResCols;
+ nAdjustRows = nParmRows;
+ }
+ pJumpM->SetNewResMat( nAdjustCols, nAdjustRows );
+ pResMat = pJumpM->GetResultMatrix();
+ }
+}
+
+
bool ScInterpreter::JumpMatrix( short nStackLevel )
{
pJumpMatrix = pStack[sp-nStackLevel]->GetJumpMatrix();
@@ -404,52 +435,69 @@ bool ScInterpreter::JumpMatrix( short nS
double fVal;
ScRange aRange;
PopDoubleRef( aRange );
- ScAddress& rAdr = aRange.aStart;
- ULONG nCol = (ULONG)rAdr.Col() + nC;
- ULONG nRow = (ULONG)rAdr.Row() + nR;
if ( nGlobalError )
{
fVal = CreateDoubleError( nGlobalError );
nGlobalError = 0;
pResMat->PutDouble( fVal, nC, nR );
}
- else if ( nCol > static_cast(aRange.aEnd.Col()) ||
- nRow > static_cast(aRange.aEnd.Row()))
- {
- fVal = CreateDoubleError( errNoValue );
- pResMat->PutDouble( fVal, nC, nR );
- }
else
{
- rAdr.SetCol( static_cast(nCol) );
- rAdr.SetRow( static_cast(nRow) );
- ScBaseCell* pCell = GetCell( rAdr );
- if (HasCellEmptyData( pCell))
- pResMat->PutEmpty( nC, nR );
- else if (HasCellValueData( pCell))
+ // Do not modify the original range because we use it
+ // to adjust the size of the result matrix if necessary.
+ ScAddress aAdr( aRange.aStart);
+ ULONG nCol = (ULONG)aAdr.Col() + nC;
+ ULONG nRow = (ULONG)aAdr.Row() + nR;
+ if ((nCol > static_cast(aRange.aEnd.Col()) &&
+ aRange.aEnd.Col() != aRange.aStart.Col())
+ || (nRow > static_cast(aRange.aEnd.Row()) &&
+ aRange.aEnd.Row() != aRange.aStart.Row()))
{
- double fCellVal = GetCellValue( rAdr, pCell);
- if ( nGlobalError )
- {
- fCellVal = CreateDoubleError(
- nGlobalError);
- nGlobalError = 0;
- }
- pResMat->PutDouble( fCellVal, nC, nR );
+ fVal = CreateDoubleError( NOTAVAILABLE );
+ pResMat->PutDouble( fVal, nC, nR );
}
else
{
- String aStr;
- GetCellString( aStr, pCell );
- if ( nGlobalError )
+ // Replicate column and/or row of a vector if it is
+ // one. Note that this could be a range reference
+ // that in fact consists of only one cell, e.g. A1:A1
+ if (aRange.aEnd.Col() == aRange.aStart.Col())
+ nCol = aRange.aStart.Col();
+ if (aRange.aEnd.Row() == aRange.aStart.Row())
+ nRow = aRange.aStart.Row();
+ aAdr.SetCol( static_cast(nCol) );
+ aAdr.SetRow( static_cast(nRow) );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellEmptyData( pCell))
+ pResMat->PutEmpty( nC, nR );
+ else if (HasCellValueData( pCell))
{
- pResMat->PutDouble( CreateDoubleError(
- nGlobalError), nC, nR);
- nGlobalError = 0;
+ double fCellVal = GetCellValue( aAdr, pCell);
+ if ( nGlobalError )
+ {
+ fCellVal = CreateDoubleError(
+ nGlobalError);
+ nGlobalError = 0;
+ }
+ pResMat->PutDouble( fCellVal, nC, nR );
}
else
- pResMat->PutString( aStr, nC, nR );
+ {
+ String aStr;
+ GetCellString( aStr, pCell );
+ if ( nGlobalError )
+ {
+ pResMat->PutDouble( CreateDoubleError(
+ nGlobalError), nC, nR);
+ nGlobalError = 0;
+ }
+ else
+ pResMat->PutString( aStr, nC, nR );
+ }
}
+ SCSIZE nParmCols = aRange.aEnd.Col() - aRange.aStart.Col() + 1;
+ SCSIZE nParmRows = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
+ lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nParmCols, nParmRows );
}
}
break;
@@ -472,9 +520,10 @@ bool ScInterpreter::JumpMatrix( short nS
{
SCSIZE nCols, nRows;
pMat->GetDimensions( nCols, nRows );
- if ( nCols <= nC || nRows <= nR )
+ if ((nCols <= nC && nCols != 1) ||
+ (nRows <= nR && nRows != 1))
{
- fVal = CreateDoubleError( errNoValue );
+ fVal = CreateDoubleError( NOTAVAILABLE );
pResMat->PutDouble( fVal, nC, nR );
}
else
@@ -492,6 +541,7 @@ bool ScInterpreter::JumpMatrix( short nS
pResMat->PutString( rStr, nC, nR );
}
}
+ lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nCols, nRows );
}
}
break;
@@ -775,7 +825,9 @@ ScMatrixRef ScInterpreter::CompareMat()
{
for ( SCSIZE k=0; kValidColRowOrReplicated( nCol, nRow ) &&
+ pMat[1]->ValidColRowOrReplicated( nCol, nRow ))
{
for ( short i=1; i>=0; i-- )
{
Index: source/core/tool/interpr5.cxx
===================================================================
RCS file: /cvs/sc/sc/source/core/tool/interpr5.cxx,v
retrieving revision 1.33
diff -p -u -r1.33 interpr5.cxx
--- source/core/tool/interpr5.cxx 21 Jul 2008 12:03:30 -0000 1.33
+++ source/core/tool/interpr5.cxx 27 Aug 2008 11:58:18 -0000
@@ -1032,6 +1032,23 @@ void ScInterpreter::ScMatTrans()
}
}
+
+/** Minimum extent of one result matrix dimension.
+ For a row or column vector to be replicated the larger matrix dimension is
+ returned, else the smaller dimension.
+ */
+inline SCSIZE lcl_GetMinExtent( SCSIZE n1, SCSIZE n2 )
+{
+ if (n1 == 1)
+ return n2;
+ else if (n2 == 1)
+ return n1;
+ else if (n1 < n2)
+ return n1;
+ else
+ return n2;
+}
+
ScMatrixRef ScInterpreter::MatAdd(ScMatrix* pMat1, ScMatrix* pMat2)
{
SCSIZE nC1, nC2, nMinC;
@@ -1039,14 +1056,8 @@ ScMatrixRef ScInterpreter::MatAdd(ScMatr
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
+ nMinC = lcl_GetMinExtent( nC1, nC2);
+ nMinR = lcl_GetMinExtent( nR1, nR2);
ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
if (xResMat)
{
@@ -1074,14 +1085,8 @@ ScMatrixRef ScInterpreter::MatSub(ScMatr
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
+ nMinC = lcl_GetMinExtent( nC1, nC2);
+ nMinR = lcl_GetMinExtent( nR1, nR2);
ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
if (xResMat)
{
@@ -1109,14 +1114,8 @@ ScMatrixRef ScInterpreter::MatMul(ScMatr
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
+ nMinC = lcl_GetMinExtent( nC1, nC2);
+ nMinR = lcl_GetMinExtent( nR1, nR2);
ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
if (xResMat)
{
@@ -1144,14 +1143,8 @@ ScMatrixRef ScInterpreter::MatDiv(ScMatr
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
+ nMinC = lcl_GetMinExtent( nC1, nC2);
+ nMinR = lcl_GetMinExtent( nR1, nR2);
ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
if (xResMat)
{
@@ -1180,14 +1173,8 @@ ScMatrixRef ScInterpreter::MatPow(ScMatr
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
+ nMinC = lcl_GetMinExtent( nC1, nC2);
+ nMinR = lcl_GetMinExtent( nR1, nR2);
ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
if (xResMat)
{
@@ -1215,14 +1202,8 @@ ScMatrixRef ScInterpreter::MatConcat(ScM
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
- nMinC = nC1;
- else
- nMinC = nC2;
- if (nR1 < nR2)
- nMinR = nR1;
- else
- nMinR = nR2;
+ nMinC = lcl_GetMinExtent( nC1, nC2);
+ nMinR = lcl_GetMinExtent( nR1, nR2);
ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
if (xResMat)
{
@@ -3693,11 +3674,13 @@ void ScInterpreter::ScMatRef()
const ScMatrix* pMat = pCell->GetMatrix();
if( pMat )
{
- SCSIZE nCl, nRw;
- pMat->GetDimensions( nCl, nRw );
+ SCSIZE nCols, nRows;
+ pMat->GetDimensions( nCols, nRows );
SCSIZE nC = static_cast(aPos.Col() - aAdr.Col());
SCSIZE nR = static_cast(aPos.Row() - aAdr.Row());
- if (nC < nCl && nR < nRw)
+ if ((nCols <= nC && nCols != 1) || (nRows <= nR && nRows != 1))
+ PushNA();
+ else
{
ScMatValType nMatValType;
const ScMatrixValue* pMatVal = pMat->Get( nC, nR, nMatValType);
@@ -3724,8 +3707,6 @@ void ScInterpreter::ScMatRef()
nFuncFmtIndex = nCurFmtIndex;
}
}
- else
- PushNA();
}
else
{
Index: source/core/tool/scmatrix.cxx
===================================================================
RCS file: /cvs/sc/sc/source/core/tool/scmatrix.cxx,v
retrieving revision 1.17
diff -p -u -r1.17 scmatrix.cxx
--- source/core/tool/scmatrix.cxx 10 Apr 2008 20:01:15 -0000 1.17
+++ source/core/tool/scmatrix.cxx 27 Aug 2008 11:58:18 -0000
@@ -78,6 +78,14 @@ ScMatrix* ScMatrix::Clone() const
return pScMat;
}
+ScMatrix* ScMatrix::CloneAndExtend( SCSIZE nNewCols, SCSIZE nNewRows ) const
+{
+ ScMatrix* pScMat = new ScMatrix( nNewCols, nNewRows);
+ MatCopy(*pScMat);
+ pScMat->SetErrorInterpreter( pErrorInterpreter);
+ return pScMat;
+}
+
void ScMatrix::SetErrorAtInterpreter( USHORT nError ) const
{
if ( pErrorInterpreter )
@@ -399,29 +407,29 @@ void ScMatrix::PutBoolean( bool bVal, SC
USHORT ScMatrix::GetError( SCSIZE nC, SCSIZE nR) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRowOrReplicated( nC, nR ))
return GetError( CalcOffset( nC, nR) );
else
{
DBG_ERRORFILE("ScMatrix::GetError: dimension error");
- return 0; // TODO: do we want an error instead?
+ return errNoValue;
}
}
double ScMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRowOrReplicated( nC, nR ))
return GetDouble( CalcOffset( nC, nR) );
else
{
DBG_ERRORFILE("ScMatrix::GetDouble: dimension error");
- return 0.0;
+ return CreateDoubleError( errNoValue);
}
}
const String& ScMatrix::GetString(SCSIZE nC, SCSIZE nR) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRowOrReplicated( nC, nR ))
{
SCSIZE nIndex = CalcOffset( nC, nR);
if ( IsString( nIndex ) )
@@ -474,7 +482,7 @@ String ScMatrix::GetString( SvNumberForm
String ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRowOrReplicated( nC, nR ))
{
SCSIZE nIndex = CalcOffset( nC, nR);
return GetString( rFormatter, nIndex);
@@ -489,7 +497,7 @@ String ScMatrix::GetString( SvNumberForm
const ScMatrixValue* ScMatrix::Get(SCSIZE nC, SCSIZE nR, ScMatValType& nType) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRowOrReplicated( nC, nR ))
{
SCSIZE nIndex = CalcOffset( nC, nR);
if (mnValType)
@@ -508,11 +516,11 @@ const ScMatrixValue* ScMatrix::Get(SCSIZ
void ScMatrix::MatCopy(ScMatrix& mRes) const
{
- if (nColCount != mRes.nColCount || nRowCount != mRes.nRowCount)
+ if (nColCount > mRes.nColCount || nRowCount > mRes.nRowCount)
{
DBG_ERRORFILE("ScMatrix::MatCopy: dimension error");
}
- else
+ else if ( nColCount == mRes.nColCount && nRowCount == mRes.nRowCount )
{
if (mnValType)
{
@@ -541,6 +549,41 @@ void ScMatrix::MatCopy(ScMatrix& mRes) c
mRes.pMat[i].fVal = pMat[i].fVal;
}
}
+ else
+ {
+ // Copy this matrix to upper left rectangle of result matrix.
+ if (mnValType)
+ {
+ ScMatValType nType;
+ mRes.ResetIsString();
+ for (SCSIZE i = 0; i < nColCount; i++)
+ {
+ SCSIZE nStart = i * nRowCount;
+ SCSIZE nResStart = i * mRes.nRowCount;
+ for (SCSIZE j = 0; j < nRowCount; j++)
+ {
+ if (IsStringType( (nType = mnValType[nStart+j])))
+ mRes.PutStringEntry( pMat[nStart+j].pS, nType, nResStart+j );
+ else
+ {
+ mRes.pMat[nResStart+j].fVal = pMat[nStart+j].fVal;
+ mRes.mnValType[nResStart+j] = nType;
+ }
+ }
+ }
+ }
+ else
+ {
+ mRes.DeleteIsString();
+ for (SCSIZE i = 0; i < nColCount; i++)
+ {
+ SCSIZE nStart = i * nRowCount;
+ SCSIZE nResStart = i * mRes.nRowCount;
+ for (SCSIZE j = 0; j < nRowCount; j++)
+ mRes.pMat[nResStart+j].fVal = pMat[nStart+j].fVal;
+ }
+ }
+ }
}
void ScMatrix::MatTrans(ScMatrix& mRes) const