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-03 15:17:40.000000000 +0800 @@ -209,6 +209,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) 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-03 15:22:48.000000000 +0800 @@ -49,6 +49,7 @@ #include #endif #include +#include typedef ::std::vector< ScToken*> ScTokenVec; @@ -86,6 +87,8 @@ class ScJumpMatrix SCSIZE nRows; SCSIZE nCurCol; SCSIZE nCurRow; + SCSIZE nResMatCols; + SCSIZE nResMatRows; bool bStarted; // not implemented, prevent usage @@ -101,6 +104,8 @@ public: , nRows( nRowsP ) , nCurCol( 0 ) , nCurRow( 0 ) + , nResMatCols( nColsP ) + , nResMatRows( nRowsP ) , bStarted( false ) { // Initialize result matrix in case of @@ -141,6 +146,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 +192,58 @@ public: } else { - if ( ++nCurRow >= nRows ) + if ( ++nCurRow >= nResMatRows ) { nCurRow = 0; ++nCurCol; } } GetPos( rCol, rRow ); - return nCurCol < nCols; + return nCurCol < nResMatCols; + } + void GetResMatColRows( SCSIZE& rCols, SCSIZE& rRows ) + { + rCols = nResMatCols; + rRows = nResMatRows; + } + void SetNewResMat( SCSIZE nNewCols, SCSIZE nNewRows ) + { + if ( nNewCols > nResMatCols || nNewRows > nResMatRows ) + { + ScMatrix* pNewMat = new ScMatrix( nNewCols, nNewRows); + pNewMat->FillDouble( CreateDoubleError( + NOTAVAILABLE), 0, 0, nNewCols-1, + nNewRows-1); + for (SCSIZE nC = 0; nC < nResMatCols; nC++) + { + for (SCSIZE nR = 0; nR < nResMatRows; nR++) + { + if ( pMat->IsValue( nC, nR ) ) + { + double fVal; + fVal = pMat->GetDouble( nC, nR ); + pNewMat->PutDouble( fVal, nC, nR ); + } + else if ( pMat->IsEmpty( nC, nR ) ) + pNewMat->PutEmpty( nC, nR ); + else + { + const String& rStr = pMat->GetString( nC, nR ); + pNewMat->PutString( rStr, nC, nR ); + } + } + } + ScMatrix* p = pMat; + pMat = pNewMat; + p->Delete(); + 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-03 15:44:32.000000000 +0800 @@ -314,6 +314,34 @@ void ScInterpreter::ScChoseJump() } +void lcl_AjustJumpMatrix( ScJumpMatrix* pJumpM, SCSIZE nParmCols, SCSIZE nParmRows ) +{ + SCSIZE nJumpCols, nJumpRows; + SCSIZE nResCols, nResRows; + SCSIZE nAjustCols, nAjustRows; + pJumpM->GetDimensions( nJumpCols, nJumpRows ); + pJumpM->GetResMatColRows( 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_AjustJumpMatrix( 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_AjustJumpMatrix( pJumpMatrix, nParmCols, nParmRows ); } } break; 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-03 15:35:48.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,27 @@ ScMatrixRef ScInterpreter::MatSub(ScMatr SCSIZE i, j; pMat1->GetDimensions(nC1, nR1); pMat2->GetDimensions(nC2, nR2); - if (nC1 < nC2) + //if (nC1 < nC2) + // nMinC = nC1; + //else + // nMinC = nC2; + //if (nR1 < nR2) + // nMinR = nR1; + //else + // nMinR = nR2; + 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 +1261,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 +1304,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 +1348,17 @@ 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 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 +1389,17 @@ 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 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; 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-03 15:36:36.000000000 +0800 @@ -400,7 +400,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 +411,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 +422,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 +473,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 +486,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)