diff -upr old/sc/inc/scmatrix.hxx new/sc/inc/scmatrix.hxx
--- old/sc/inc/scmatrix.hxx 2008-01-31 23:34:22.000000000 +0800
+++ new/sc/inc/scmatrix.hxx 2008-06-10 17:04:28.000000000 +0800
@@ -172,6 +172,7 @@ public:
Compare nC and nR with a GetDimensions() call to check. */
ScMatrix( SCSIZE nC, SCSIZE nR) : nRefCnt(0) { CreateMatrix( nC, nR); }
ScMatrix* Clone() const;
+ ScMatrix* CloneAndExtend( SCSIZE nNewCols, SCSIZE nNewRows ) const;
/// disable refcounting forever, may only be deleted via Delete() afterwards
inline void SetEternalRef() { nRefCnt = ULONG_MAX; }
@@ -209,6 +210,26 @@ public:
{ return nC < nColCount && nR < nRowCount; }
inline SCSIZE CalcOffset( SCSIZE nC, SCSIZE nR) const
{ return nC * nRowCount + nR; }
+ inline bool ValidColRowReplicated( SCSIZE& rC, SCSIZE& rR ) const
+ {
+ if ( ( nColCount == 1 && rR < nRowCount ) ||
+ ( nRowCount == 1 && rC < nColCount ) ||
+ ( nColCount == 1 && nRowCount == 1 ) )
+ {
+ if ( nColCount == 1 && nRowCount == 1 )
+ {
+ rC = 0;
+ rR = 0;
+ }
+ else if ( nColCount == 1 )
+ rC = 0;
+ else
+ rR = 0;
+ return true;
+ }
+ else
+ return false;
+ }
void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
void PutDouble( double fVal, SCSIZE nIndex)
@@ -278,30 +299,48 @@ public:
{ 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
diff -upr old/sc/source/core/inc/jumpmatrix.hxx new/sc/source/core/inc/jumpmatrix.hxx
--- old/sc/source/core/inc/jumpmatrix.hxx 2007-07-06 20:34:20.000000000 +0800
+++ new/sc/source/core/inc/jumpmatrix.hxx 2008-06-10 17:20:14.000000000 +0800
@@ -86,6 +86,8 @@ class ScJumpMatrix
SCSIZE nRows;
SCSIZE nCurCol;
SCSIZE nCurRow;
+ SCSIZE nResMatCols;
+ SCSIZE nResMatRows;
bool bStarted;
// not implemented, prevent usage
@@ -101,6 +103,8 @@ public:
, nRows( nRowsP )
, nCurCol( 0 )
, nCurRow( 0 )
+ , nResMatCols( nColsP )
+ , nResMatRows( nRowsP )
, bStarted( false )
{
// Initialize result matrix in case of
@@ -141,6 +145,20 @@ public:
short& rStart, short& rNext,
short& rStop ) const
{
+ if ( ( nCols == 1 && nRow < nRows ) ||
+ ( nRows == 1 && nCol < nCols ) ||
+ ( nCols == 1 && nRows == 1 ) )
+ {
+ if ( nCols == 1 && nRows == 1 )
+ {
+ nCol = 0;
+ nRow = 0;
+ }
+ else if ( nCols == 1 )
+ nCol = 0;
+ else
+ nRow = 0;
+ }
pJump[ (ULONG)nCol * nRows + nRow ].
GetJump( rBool, rStart, rNext, rStop);
}
@@ -173,14 +191,33 @@ 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 ( nRows == 1 && nCurCol != 0 )
+ {
+ nCurCol = 0;
+ nCurRow = nResMatRows - 1;
+ }
+ nResMatCols = nNewCols;
+ nResMatRows = nNewRows;
+ }
}
};
diff -upr old/sc/source/core/tool/interpr1.cxx new/sc/source/core/tool/interpr1.cxx
--- old/sc/source/core/tool/interpr1.cxx 2008-02-25 10:02:14.000000000 +0800
+++ new/sc/source/core/tool/interpr1.cxx 2008-06-10 17:08:00.000000000 +0800
@@ -314,6 +314,34 @@ void ScInterpreter::ScChoseJump()
}
+void lcl_AdjustJumpMatrix( ScJumpMatrix* pJumpM, SCSIZE nParmCols, SCSIZE nParmRows )
+{
+ SCSIZE nJumpCols, nJumpRows;
+ SCSIZE nResCols, nResRows;
+ SCSIZE nAjustCols, nAjustRows;
+ pJumpM->GetDimensions( nJumpCols, nJumpRows );
+ pJumpM->GetResMatDimensions( nResCols, nResRows );
+ if (( nJumpCols == 1 && nParmCols > nResCols ) ||
+ ( nJumpRows == 1 && nParmRows > nResRows ))
+ {
+ if ( nJumpCols == 1 && nJumpRows == 1 )
+ {
+ nAjustCols = nParmCols > nResCols? nParmCols:nResCols;
+ nAjustRows = nParmRows > nResRows? nParmRows:nResRows;
+ }
+ else if ( nJumpCols == 1 )
+ {
+ nAjustCols = nParmCols;
+ nAjustRows = nResRows;
+ }
+ else
+ {
+ nAjustCols = nResCols;
+ nAjustRows = nParmRows;
+ }
+ pJumpM->SetNewResMat( nAjustCols, nAjustRows );
+ }
+}
bool ScInterpreter::JumpMatrix( short nStackLevel )
{
pJumpMatrix = pStack[sp-nStackLevel]->GetJumpMatrix();
@@ -334,6 +362,7 @@ bool ScInterpreter::JumpMatrix( short nS
else
{
pJumpMatrix->GetPos( nC, nR );
+ SCSIZE nParmCols, nParmRows;
switch ( GetStackType() )
{
case svDouble:
@@ -416,14 +445,24 @@ bool ScInterpreter::JumpMatrix( short nS
nGlobalError = 0;
pResMat->PutDouble( fVal, nC, nR );
}
- else if ( nCol > static_cast(aRange.aEnd.Col()) ||
- nRow > static_cast(aRange.aEnd.Row()))
+ else if ( (( nCol > static_cast(aRange.aEnd.Col()) ||
+ nRow > static_cast(aRange.aEnd.Row())) &&
+ aRange.aEnd.Col() != aRange.aStart.Col() &&
+ aRange.aEnd.Row() != aRange.aStart.Row())
+ || ( aRange.aEnd.Col() == aRange.aStart.Col() &&
+ nRow > static_cast(aRange.aEnd.Row()))
+ || ( aRange.aEnd.Row() == aRange.aStart.Row() &&
+ nCol > static_cast(aRange.aEnd.Col())) )
{
fVal = CreateDoubleError( errNoValue );
pResMat->PutDouble( fVal, nC, nR );
}
else
{
+ if (aRange.aEnd.Col() == aRange.aStart.Col())
+ nCol = aRange.aStart.Col();
+ else if (aRange.aEnd.Row() == aRange.aStart.Row())
+ nRow = aRange.aStart.Row();
rAdr.SetCol( static_cast(nCol) );
rAdr.SetRow( static_cast(nRow) );
ScBaseCell* pCell = GetCell( rAdr );
@@ -453,6 +492,9 @@ bool ScInterpreter::JumpMatrix( short nS
else
pResMat->PutString( aStr, nC, nR );
}
+ nParmCols = aRange.aEnd.Col() - aRange.aStart.Col() + 1;
+ nParmRows = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
+ lcl_AdjustJumpMatrix( pJumpMatrix, nParmCols, nParmRows );
}
}
break;
@@ -475,7 +517,10 @@ bool ScInterpreter::JumpMatrix( short nS
{
SCSIZE nCols, nRows;
pMat->GetDimensions( nCols, nRows );
- if ( nCols <= nC || nRows <= nR )
+ if ( (( nCols <= nC || nRows <= nR ) &&
+ ( nCols != 1 && nRows != 1 )) ||
+ ( nCols == 1 && nRows <= nR ) ||
+ ( nRows == 1 && nCols <= nC ) )
{
fVal = CreateDoubleError( errNoValue );
pResMat->PutDouble( fVal, nC, nR );
@@ -495,6 +540,9 @@ bool ScInterpreter::JumpMatrix( short nS
pResMat->PutString( rStr, nC, nR );
}
}
+ nParmCols = nCols;
+ nParmRows = nRows;
+ lcl_AdjustJumpMatrix( pJumpMatrix, nParmCols, nParmRows );
}
}
break;
@@ -778,7 +826,11 @@ ScMatrixRef ScInterpreter::CompareMat()
{
for ( SCSIZE k=0; kValidColRow( nCol, nRow) ||
+ pMat[0]->ValidColRowReplicated( nCol, nRow ))
+ && ( pMat[1]->ValidColRow( nCol, nRow) ||
+ pMat[1]->ValidColRowReplicated( nCol, nRow )) )
{
for ( short i=1; i>=0; i-- )
{
diff -upr old/sc/source/core/tool/interpr5.cxx new/sc/source/core/tool/interpr5.cxx
--- old/sc/source/core/tool/interpr5.cxx 2008-02-25 10:03:26.000000000 +0800
+++ new/sc/source/core/tool/interpr5.cxx 2008-06-10 17:13:22.000000000 +0800
@@ -1167,11 +1167,19 @@ ScMatrixRef ScInterpreter::MatAdd(ScMatr
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
+ if ( nC1 == 1 )
+ nMinC = nC2;
+ else if ( nC2 == 1 )
+ nMinC = nC1;
+ else if (nC1 < nC2)
nMinC = nC1;
else
nMinC = nC2;
- if (nR1 < nR2)
+ if ( nR1 == 1 )
+ nMinR = nR2;
+ else if ( nR2 == 1 )
+ nMinR = nR1;
+ else if (nR1 < nR2)
nMinR = nR1;
else
nMinR = nR2;
@@ -1202,11 +1210,19 @@ ScMatrixRef ScInterpreter::MatSub(ScMatr
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
+ if ( nC1 == 1 )
+ nMinC = nC2;
+ else if ( nC2 == 1 )
+ nMinC = nC1;
+ else if (nC1 < nC2)
nMinC = nC1;
else
nMinC = nC2;
- if (nR1 < nR2)
+ if ( nR1 == 1 )
+ nMinR = nR2;
+ else if ( nR2 == 1 )
+ nMinR = nR1;
+ else if (nR1 < nR2)
nMinR = nR1;
else
nMinR = nR2;
@@ -1237,11 +1253,19 @@ ScMatrixRef ScInterpreter::MatMul(ScMatr
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
+ if ( nC1 == 1 )
+ nMinC = nC2;
+ else if ( nC2 == 1 )
+ nMinC = nC1;
+ else if (nC1 < nC2)
nMinC = nC1;
else
nMinC = nC2;
- if (nR1 < nR2)
+ if ( nR1 == 1 )
+ nMinR = nR2;
+ else if ( nR2 == 1 )
+ nMinR = nR1;
+ else if (nR1 < nR2)
nMinR = nR1;
else
nMinR = nR2;
@@ -1272,11 +1296,19 @@ ScMatrixRef ScInterpreter::MatDiv(ScMatr
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
+ if ( nC1 == 1 )
+ nMinC = nC2;
+ else if ( nC2 == 1 )
+ nMinC = nC1;
+ else if (nC1 < nC2)
nMinC = nC1;
else
nMinC = nC2;
- if (nR1 < nR2)
+ if ( nR1 == 1 )
+ nMinR = nR2;
+ else if ( nR2 == 1 )
+ nMinR = nR1;
+ else if (nR1 < nR2)
nMinR = nR1;
else
nMinR = nR2;
@@ -1308,11 +1340,19 @@ ScMatrixRef ScInterpreter::MatPow(ScMatr
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
+ if ( nC1 == 1 )
+ nMinC = nC2;
+ else if ( nC2 == 1 )
+ nMinC = nC1;
+ else if (nC1 < nC2)
nMinC = nC1;
else
nMinC = nC2;
- if (nR1 < nR2)
+ if ( nR1 == 1 )
+ nMinR = nR2;
+ else if ( nR2 == 1 )
+ nMinR = nR1;
+ else if (nR1 < nR2)
nMinR = nR1;
else
nMinR = nR2;
@@ -1343,11 +1383,19 @@ ScMatrixRef ScInterpreter::MatConcat(ScM
SCSIZE i, j;
pMat1->GetDimensions(nC1, nR1);
pMat2->GetDimensions(nC2, nR2);
- if (nC1 < nC2)
+ if ( nC1 == 1 )
+ nMinC = nC2;
+ else if ( nC2 == 1 )
+ nMinC = nC1;
+ else if (nC1 < nC2)
nMinC = nC1;
else
nMinC = nC2;
- if (nR1 < nR2)
+ if ( nR1 == 1 )
+ nMinR = nR2;
+ else if ( nR2 == 1 )
+ nMinR = nR1;
+ else if (nR1 < nR2)
nMinR = nR1;
else
nMinR = nR2;
@@ -3825,7 +3873,8 @@ void ScInterpreter::ScMatRef()
pMat->GetDimensions( nCl, nRw );
SCSIZE nC = static_cast(aPos.Col() - aAdr.Col());
SCSIZE nR = static_cast(aPos.Row() - aAdr.Row());
- if (nC < nCl && nR < nRw)
+ if ((nC < nCl && nR < nRw) || ( nCl == 1 && nRw == 1 ) ||
+ ( nCl == 1 && nR < nRw ) || ( nRw == 1 && nC < nCl ))
{
ScMatValType nMatValType;
const ScMatrixValue* pMatVal = pMat->Get( nC, nR, nMatValType);
diff -upr old/sc/source/core/tool/scmatrix.cxx new/sc/source/core/tool/scmatrix.cxx
--- old/sc/source/core/tool/scmatrix.cxx 2007-06-13 17:08:20.000000000 +0800
+++ new/sc/source/core/tool/scmatrix.cxx 2008-06-10 17:15:28.000000000 +0800
@@ -91,6 +91,13 @@ 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 )
@@ -400,7 +407,7 @@ void ScMatrix::PutBoolean( bool bVal, SC
USHORT ScMatrix::GetError( SCSIZE nC, SCSIZE nR) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRow( nC, nR) || ValidColRowReplicated( nC, nR ))
return GetError( CalcOffset( nC, nR) );
else
{
@@ -411,7 +418,7 @@ USHORT ScMatrix::GetError( SCSIZE nC, SC
double ScMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRow( nC, nR) || ValidColRowReplicated( nC, nR ))
return GetDouble( CalcOffset( nC, nR) );
else
{
@@ -422,7 +429,7 @@ double ScMatrix::GetDouble(SCSIZE nC, SC
const String& ScMatrix::GetString(SCSIZE nC, SCSIZE nR) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRow( nC, nR) || ValidColRowReplicated( nC, nR ))
{
SCSIZE nIndex = CalcOffset( nC, nR);
if ( IsString( nIndex ) )
@@ -473,7 +480,7 @@ String ScMatrix::GetString( SvNumberForm
String ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRow( nC, nR) || ValidColRowReplicated( nC, nR ))
{
SCSIZE nIndex = CalcOffset( nC, nR);
return GetString( rFormatter, nIndex);
@@ -486,7 +493,7 @@ String ScMatrix::GetString( SvNumberForm
const ScMatrixValue* ScMatrix::Get(SCSIZE nC, SCSIZE nR, ScMatValType& nType) const
{
- if (ValidColRow( nC, nR))
+ if (ValidColRow( nC, nR) || ValidColRowReplicated( nC, nR ))
{
SCSIZE nIndex = CalcOffset( nC, nR);
if (mnValType)
@@ -503,11 +510,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)
{
@@ -536,6 +543,40 @@ void ScMatrix::MatCopy(ScMatrix& mRes) c
mRes.pMat[i].fVal = pMat[i].fVal;
}
}
+ else
+ {
+ 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