diff -upr old/sc/inc/scmatrix.hxx new/sc/inc/scmatrix.hxx --- old/sc/inc/scmatrix.hxx 2008-07-02 13:54:24.000000000 +0800 +++ new/sc/inc/scmatrix.hxx 2008-07-02 14:06:40.000000000 +0800 @@ -158,6 +158,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; } @@ -195,6 +196,27 @@ 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) @@ -264,30 +286,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 ]) || - ((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTY) == - SC_MATVAL_EMPTY); } + { + ValidColRowReplicated( nC, nR ); + return !mnValType || IsValueType( mnValType[ nC * nRowCount + nR ]) || + ((mnValType[ nC * nRowCount + nR ] & 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 2008-07-02 13:55:15.000000000 +0800 +++ new/sc/source/core/inc/jumpmatrix.hxx 2008-07-02 14:55:09.000000000 +0800 @@ -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,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); } @@ -160,14 +178,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; + } } }; diff -upr old/sc/source/core/tool/interpr1.cxx new/sc/source/core/tool/interpr1.cxx --- old/sc/source/core/tool/interpr1.cxx 2008-07-02 13:56:02.000000000 +0800 +++ new/sc/source/core/tool/interpr1.cxx 2008-08-13 10:47:14.000000000 +0800 @@ -308,6 +308,35 @@ void ScInterpreter::ScChoseJump() } +void lcl_AdjustJumpMatrix( ScJumpMatrix* pJumpM, ScMatrixRef& pResMat, 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 ); + pResMat = pJumpM->GetResultMatrix(); + } +} bool ScInterpreter::JumpMatrix( short nStackLevel ) { pJumpMatrix = pStack[sp-nStackLevel]->GetJumpMatrix(); @@ -330,6 +359,7 @@ bool ScInterpreter::JumpMatrix( short nS else { pJumpMatrix->GetPos( nC, nR ); + SCSIZE nParmCols, nParmRows; switch ( GetStackType() ) { case svDouble: @@ -412,14 +442,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 ); @@ -449,6 +489,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, pResMat, nParmCols, nParmRows ); } } break; @@ -471,7 +514,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 <= nR ) || + ( nRows == 1 && nCols <= nC ) ) && + ( nCols != 1 || nRows != 1 ) ) { fVal = CreateDoubleError( errNoValue ); pResMat->PutDouble( fVal, nC, nR ); @@ -491,6 +537,10 @@ bool ScInterpreter::JumpMatrix( short nS pResMat->PutString( rStr, nC, nR ); } } + nParmCols = nCols; + nParmRows = nRows; + lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nParmCols, nParmRows ); + } } break; @@ -774,7 +824,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-07-02 13:56:28.000000000 +0800 +++ new/sc/source/core/tool/interpr5.cxx 2008-07-02 14:17:07.000000000 +0800 @@ -1039,11 +1039,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; @@ -1074,11 +1082,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; @@ -1109,11 +1125,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; @@ -1144,11 +1168,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; @@ -1180,11 +1212,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; @@ -1215,11 +1255,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; @@ -3697,7 +3745,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 2008-07-02 13:56:56.000000000 +0800 +++ new/sc/source/core/tool/scmatrix.cxx 2008-07-02 15:01:28.000000000 +0800 @@ -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,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 { @@ -410,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 { @@ -421,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 ) ) @@ -474,7 +482,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); @@ -489,7 +497,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) @@ -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,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