View | Details | Raw Unified | Return to issue 46681
Collapse All | Expand All

(-)inc/scmatrix.hxx (-37 / +105 lines)
Lines 66-92 union ScMatrixValue Link Here
66
66
67
    @ATTENTION: optimized for speed and double values.
67
    @ATTENTION: optimized for speed and double values.
68
68
69
    Matrix elements are NOT initialized after construction!
69
    <p> Matrix elements are NOT initialized after construction!
70
70
71
    All methods using an SCSIZE nIndex parameter and all Is... methods do NOT
71
    <p> All methods using an SCSIZE nIndex parameter and all Is...() methods do
72
    check the range for validity! However, the Put... and Get... methods using
72
    NOT check the range for validity! However, the Put...() and Get...()
73
    nCol/nRow parameters do check the range. <p>
73
    methods using nCol/nRow parameters do check the range.
74
75
    <p> Methods using nCol/nRow parameters do replicate a single row vector if
76
    nRow &gt; 0 and nCol &lt; nColCount, respectively a column vector if nCol
77
    &gt; 0 and nRow &lt; nRowCount.
74
78
75
    GetString( SCSIZE nIndex ) does not check if there really is a string, do
79
    <p> GetString( SCSIZE nIndex ) does not check if there really is a string,
76
    this with IsString() first. GetString( SCSIZE nC, SCSIZE nR ) does check
80
    do this with IsString() first. GetString( SCSIZE nC, SCSIZE nR ) does check
77
    it and returns and empty string if there is no string. Both GetDouble()
81
    it and returns and empty string if there is no string. Both GetDouble()
78
    methods don't check for a string, do this with IsNumeric() or IsString()
82
    methods don't check for a string, do this with IsNumeric() or IsString() or
79
    or IsValue() first. <p>
83
    IsValue() first.
80
84
81
    The GetString( SvNumberFormatter&, ...) methods return the matrix element's
85
    <p> The GetString( SvNumberFormatter&, ...) methods return the matrix
82
    string if one is present, otherwise the numerical value is formatted as a
86
    element's string if one is present, otherwise the numerical value is
83
    string, or in case of an error the error string is returned.
87
    formatted as a string, or in case of an error the error string is returned.
84
88
85
    PutDouble() does not reset an eventual string! Use
89
    <p> PutDouble() does not reset an eventual string! Use
86
    PutDoubleAndResetString() if that is wanted. Also the FillDouble...()
90
    PutDoubleAndResetString() if that is wanted. Also the FillDouble...()
87
    methods don't reset strings. As a consequence memory leaks may occur if
91
    methods don't reset strings. As a consequence memory leaks may occur if
88
    used wrong.
92
    used wrong.
89
 */
93
 */
94
90
class ScMatrix
95
class ScMatrix
91
{
96
{
92
    ScMatrixValue*  pMat;
97
    ScMatrixValue*  pMat;
Lines 115-121 class ScMatrix Link Here
115
120
116
public:
121
public:
117
122
118
    /// The maximum number of elements a matrix may have at runtime
123
    /// The maximum number of elements a matrix may have at runtime.
119
    inline static size_t GetElementsMax()
124
    inline static size_t GetElementsMax()
120
    {
125
    {
121
        const size_t nMemMax = (((size_t)(~0))-64) / sizeof(ScMatrixValue);
126
        const size_t nMemMax = (((size_t)(~0))-64) / sizeof(ScMatrixValue);
Lines 157-165 public: Link Here
157
        created instead and a double error value (errStackOverflow) is set.
162
        created instead and a double error value (errStackOverflow) is set.
158
        Compare nC and nR with a GetDimensions() call to check. */
163
        Compare nC and nR with a GetDimensions() call to check. */
159
    ScMatrix( SCSIZE nC, SCSIZE nR) : nRefCnt(0) { CreateMatrix( nC, nR); }
164
    ScMatrix( SCSIZE nC, SCSIZE nR) : nRefCnt(0) { CreateMatrix( nC, nR); }
165
166
    /** Clone the matrix. */
160
    ScMatrix* Clone() const;
167
    ScMatrix* Clone() const;
161
168
162
    /// disable refcounting forever, may only be deleted via Delete() afterwards
169
    /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
170
        MUST be at least of the size of the original matrix. */
171
    ScMatrix* CloneAndExtend( SCSIZE nNewCols, SCSIZE nNewRows ) const;
172
173
    /// Disable refcounting forever, may only be deleted via Delete() afterwards.
163
    inline  void    SetEternalRef()         { nRefCnt = ULONG_MAX; }
174
    inline  void    SetEternalRef()         { nRefCnt = ULONG_MAX; }
164
    inline  bool    IsEternalRef() const    { return nRefCnt == ULONG_MAX; }
175
    inline  bool    IsEternalRef() const    { return nRefCnt == ULONG_MAX; }
165
    inline  void    IncRef() const
176
    inline  void    IncRef() const
Lines 196-201 public: Link Here
196
    inline SCSIZE CalcOffset( SCSIZE nC, SCSIZE nR) const
207
    inline SCSIZE CalcOffset( SCSIZE nC, SCSIZE nR) const
197
        { return nC * nRowCount + nR; }
208
        { return nC * nRowCount + nR; }
198
209
210
    /** For a row vector or column vector, if the position does not point into
211
        the vector but is a valid column or row offset it is adapted such that
212
        it points to an element to be replicated, same column row 0 for a row
213
        vector, same row column 0 for a column vector. Else, for a 2D matrix,
214
        returns false.
215
     */
216
    inline bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const
217
    {
218
        if (nColCount == 1 && nRowCount == 1)
219
        {
220
            rC = 0;
221
            rR = 0;
222
            return true;
223
        }
224
        else if (nColCount == 1 && rR < nRowCount)
225
        {
226
            rC = 0;
227
            return true;
228
        }
229
        else if (nRowCount == 1 && rC < nColCount)
230
        {
231
            rR = 0;
232
            return true;
233
        }
234
        return false;
235
    }
236
237
    /** Checks if the matrix position is within the matrix. If it is not, for a
238
        row vector or column vector the position is adapted such that it points
239
        to an element to be replicated, same column row 0 for a row vector,
240
        same row column 0 for a column vector. Else, for a 2D matrix and
241
        position not within matrix, returns false.
242
     */
243
    inline bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const
244
    {
245
        return ValidColRow( rC, rR) || ValidColRowReplicated( rC, rR);
246
    }
247
248
199
    void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
249
    void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
200
    void PutDouble( double fVal, SCSIZE nIndex)
250
    void PutDouble( double fVal, SCSIZE nIndex)
201
        { pMat[nIndex].fVal = fVal; }
251
        { pMat[nIndex].fVal = fVal; }
Lines 262-293 public: Link Here
262
    /// @return <TRUE/> if string or empty
312
    /// @return <TRUE/> if string or empty
263
    BOOL IsString( SCSIZE nIndex ) const
313
    BOOL IsString( SCSIZE nIndex ) const
264
        { return mnValType && IsStringType( mnValType[nIndex]); }
314
        { return mnValType && IsStringType( mnValType[nIndex]); }
315
265
    /// @return <TRUE/> if string or empty
316
    /// @return <TRUE/> if string or empty
266
    BOOL IsString( SCSIZE nC, SCSIZE nR ) const
317
    BOOL IsString( SCSIZE nC, SCSIZE nR ) const
267
        { return mnValType && IsStringType( mnValType[ nC * nRowCount + nR ]); }
318
    { 
319
        ValidColRowReplicated( nC, nR );
320
        return mnValType && IsStringType( mnValType[ nC * nRowCount + nR ]);
321
    }
322
268
    BOOL IsEmpty( SCSIZE nIndex ) const
323
    BOOL IsEmpty( SCSIZE nIndex ) const
269
        { return mnValType && ((mnValType[nIndex] & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
324
        { return mnValType && ((mnValType[nIndex] & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
325
270
    BOOL IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
326
    BOOL IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
271
        { return mnValType && ((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTYPATH) == SC_MATVAL_EMPTYPATH); }
327
    {
328
        ValidColRowReplicated( nC, nR );
329
        return mnValType && ((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTYPATH) == SC_MATVAL_EMPTYPATH);
330
    }
331
272
    BOOL IsEmptyPath( SCSIZE nIndex ) const
332
    BOOL IsEmptyPath( SCSIZE nIndex ) const
273
        { return mnValType && ((mnValType[nIndex] & SC_MATVAL_EMPTYPATH) == SC_MATVAL_EMPTYPATH); }
333
        { return mnValType && ((mnValType[nIndex] & SC_MATVAL_EMPTYPATH) == SC_MATVAL_EMPTYPATH); }
334
274
    BOOL IsEmpty( SCSIZE nC, SCSIZE nR ) const
335
    BOOL IsEmpty( SCSIZE nC, SCSIZE nR ) const
275
        { return mnValType && ((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
336
    {
337
        ValidColRowReplicated( nC, nR );
338
        return mnValType && ((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY);
339
    }
340
276
    BOOL IsValue( SCSIZE nIndex ) const
341
    BOOL IsValue( SCSIZE nIndex ) const
277
        { return !mnValType || IsValueType( mnValType[nIndex]); }
342
        { return !mnValType || IsValueType( mnValType[nIndex]); }
343
278
    BOOL IsValue( SCSIZE nC, SCSIZE nR ) const
344
    BOOL IsValue( SCSIZE nC, SCSIZE nR ) const
279
        { return !mnValType || IsValueType( mnValType[ nC * nRowCount + nR ]); }
345
    {
346
        ValidColRowReplicated( nC, nR );
347
        return !mnValType || IsValueType( mnValType[ nC * nRowCount + nR ]);
348
    }
349
280
    BOOL IsValueOrEmpty( SCSIZE nIndex ) const
350
    BOOL IsValueOrEmpty( SCSIZE nIndex ) const
281
        { return !mnValType || IsValueType( mnValType[nIndex] ) ||
351
        { return !mnValType || IsValueType( mnValType[nIndex] ) ||
282
            ((mnValType[nIndex] & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
352
            ((mnValType[nIndex] & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
353
283
    BOOL IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
354
    BOOL IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
284
        { return !mnValType || IsValueType( mnValType[ nC * nRowCount + nR ]) ||
355
    {
356
        ValidColRowReplicated( nC, nR );
357
        return !mnValType || IsValueType( mnValType[ nC * nRowCount + nR ]) ||
285
            ((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTY) ==
358
            ((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTY) ==
286
             SC_MATVAL_EMPTY); }
359
             SC_MATVAL_EMPTY);
360
    }
361
287
    BOOL IsBoolean( SCSIZE nIndex ) const
362
    BOOL IsBoolean( SCSIZE nIndex ) const
288
        { return mnValType && IsBooleanType( mnValType[nIndex]); }
363
        { return mnValType && IsBooleanType( mnValType[nIndex]); }
364
289
    BOOL IsBoolean( SCSIZE nC, SCSIZE nR ) const
365
    BOOL IsBoolean( SCSIZE nC, SCSIZE nR ) const
290
        { return mnValType && IsBooleanType( mnValType[ nC * nRowCount + nR ]); }
366
    {
367
        ValidColRowReplicated( nC, nR );
368
        return mnValType && IsBooleanType( mnValType[ nC * nRowCount + nR ]);
369
    }
291
370
292
    /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
371
    /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
293
    BOOL IsNumeric() const
372
    BOOL IsNumeric() const
Lines 295-303 public: Link Here
295
374
296
    void MatTrans( ScMatrix& mRes) const;
375
    void MatTrans( ScMatrix& mRes) const;
297
    void MatCopy ( ScMatrix& mRes) const;
376
    void MatCopy ( ScMatrix& mRes) const;
377
298
    /** Copy upper left of this matrix to mRes matrix.
378
    /** Copy upper left of this matrix to mRes matrix.
299
        This matrix's dimensions must be greater than the mRes matrix
379
        This matrix's dimensions must be greater or equal to the mRes matrix
300
        dimensions. */
380
        dimensions.
381
     */
301
    void MatCopyUpperLeft( ScMatrix& mRes) const;
382
    void MatCopyUpperLeft( ScMatrix& mRes) const;
302
383
303
    // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
384
    // Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
Lines 320-336 typedef ScSimpleIntrusiveReference< clas Link Here
320
typedef ScSimpleIntrusiveReference< const class ScMatrix > ScConstMatrixRef;
401
typedef ScSimpleIntrusiveReference< const class ScMatrix > ScConstMatrixRef;
321
402
322
403
323
// Old values as used up to SO52.
404
#endif  // SC_MATRIX_HXX
324
// The overall elements count had to be <= SC_MAX_MAT_DIM * SC_MAX_MAT_DIM.
325
// Don't use except maybe for file format compatibility.
326
// In any other case use ScMatrix::GetElementsMax() instead.
327
#ifdef WIN
328
#define SC_OLD_MAX_MAT_DIM            64
329
#else
330
#define SC_OLD_MAX_MAT_DIM           128
331
#endif
332
#define SC_OLD_MAX_MAT_ELEMENTS     ((SC_OLD_MAX_MAT_DIM) * (SC_OLD_MAX_MAT_DIM))
333
334
335
#endif
336
(-)source/core/inc/jumpmatrix.hxx (-2 / +52 lines)
Lines 73-78 class ScJumpMatrix Link Here
73
            SCSIZE              nRows;
73
            SCSIZE              nRows;
74
            SCSIZE              nCurCol;
74
            SCSIZE              nCurCol;
75
            SCSIZE              nCurRow;
75
            SCSIZE              nCurRow;
76
            SCSIZE              nResMatCols;
77
            SCSIZE              nResMatRows;
76
            bool                bStarted;
78
            bool                bStarted;
77
79
78
                                // not implemented, prevent usage
80
                                // not implemented, prevent usage
Lines 88-93 public: Link Here
88
                                        , nRows( nRowsP )
90
                                        , nRows( nRowsP )
89
                                        , nCurCol( 0 )
91
                                        , nCurCol( 0 )
90
                                        , nCurRow( 0 )
92
                                        , nCurRow( 0 )
93
                                        , nResMatCols( nColsP )
94
                                        , nResMatRows( nRowsP )
91
                                        , bStarted( false )
95
                                        , bStarted( false )
92
                                    {
96
                                    {
93
                                        // Initialize result matrix in case of
97
                                        // Initialize result matrix in case of
Lines 128-133 public: Link Here
128
                                            short& rStart, short& rNext,
132
                                            short& rStart, short& rNext,
129
                                            short& rStop ) const
133
                                            short& rStop ) const
130
                                    {
134
                                    {
135
                                        if (nCols == 1 && nRows == 1)
136
                                        {
137
                                            nCol = 0;
138
                                            nRow = 0;
139
                                        }
140
                                        else if (nCols == 1 && nRow < nRows)
141
                                            nCol = 0;
142
                                        else if (nRows == 1 && nCol < nCols)
143
                                            nRow = 0;
144
                                        else if (nCols <= nCol || nRows <= nRow)
145
                                        {
146
                                            DBG_ERROR("ScJumpMatrix::GetJump: dimension error");
147
                                            nCol = 0;
148
                                            nRow = 0;
149
                                        }
131
                                        pJump[ (ULONG)nCol * nRows + nRow ].
150
                                        pJump[ (ULONG)nCol * nRows + nRow ].
132
                                            GetJump( rBool, rStart, rNext, rStop);
151
                                            GetJump( rBool, rStart, rNext, rStop);
133
                                    }
152
                                    }
Lines 160-173 public: Link Here
160
                                        }
179
                                        }
161
                                        else
180
                                        else
162
                                        {
181
                                        {
163
                                            if ( ++nCurRow >= nRows )
182
                                            if ( ++nCurRow >= nResMatRows )
164
                                            {
183
                                            {
165
                                                nCurRow = 0;
184
                                                nCurRow = 0;
166
                                                ++nCurCol;
185
                                                ++nCurCol;
167
                                            }
186
                                            }
168
                                        }
187
                                        }
169
                                        GetPos( rCol, rRow );
188
                                        GetPos( rCol, rRow );
170
                                        return nCurCol < nCols;
189
                                        return nCurCol < nResMatCols;
190
                                    }
191
            void                GetResMatDimensions( SCSIZE& rCols, SCSIZE& rRows )
192
                                    {
193
                                        rCols = nResMatCols;
194
                                        rRows = nResMatRows;
195
                                    }
196
            void                SetNewResMat( SCSIZE nNewCols, SCSIZE nNewRows )
197
                                    {
198
                                        if ( nNewCols > nResMatCols || nNewRows > nResMatRows )
199
                                        {
200
                                            pMat = pMat->CloneAndExtend( nNewCols, nNewRows );
201
                                            if ( nResMatCols < nNewCols )
202
                                            {
203
                                                pMat->FillDouble( CreateDoubleError(
204
                                                    NOTAVAILABLE), nResMatCols, 0, nNewCols-1,
205
                                                    nResMatRows-1);
206
                                            }
207
                                            if ( nResMatRows < nNewRows )
208
                                            {
209
                                                pMat->FillDouble( CreateDoubleError(
210
                                                    NOTAVAILABLE), 0, nResMatRows, nNewCols-1,
211
                                                    nNewRows-1);
212
                                            }
213
                                            if ( nRows == 1 && nCurCol != 0 )
214
                                            {
215
                                                nCurCol = 0;
216
                                                nCurRow = nResMatRows - 1;
217
                                            }
218
                                            nResMatCols = nNewCols;
219
                                            nResMatRows = nNewRows;
220
                                        }
171
                                    }
221
                                    }
172
};
222
};
173
223
(-)source/core/tool/interpr1.cxx (-33 / +85 lines)
Lines 309-314 void ScInterpreter::ScChoseJump() Link Here
309
}
309
}
310
310
311
311
312
void lcl_AdjustJumpMatrix( ScJumpMatrix* pJumpM, ScMatrixRef& pResMat, SCSIZE nParmCols, SCSIZE nParmRows )
313
{
314
    SCSIZE nJumpCols, nJumpRows;
315
    SCSIZE nResCols, nResRows;
316
    SCSIZE nAdjustCols, nAdjustRows;
317
    pJumpM->GetDimensions( nJumpCols, nJumpRows );
318
    pJumpM->GetResMatDimensions( nResCols, nResRows );
319
    if (( nJumpCols == 1 && nParmCols > nResCols ) || 
320
        ( nJumpRows == 1 && nParmRows > nResRows ))
321
    {
322
        if ( nJumpCols == 1 && nJumpRows == 1 )
323
        {
324
            nAdjustCols = nParmCols > nResCols ? nParmCols : nResCols;
325
            nAdjustRows = nParmRows > nResRows ? nParmRows : nResRows;
326
        }
327
        else if ( nJumpCols == 1 )
328
        {
329
            nAdjustCols = nParmCols;
330
            nAdjustRows = nResRows;
331
        }
332
        else
333
        {
334
            nAdjustCols = nResCols;
335
            nAdjustRows = nParmRows;
336
        }
337
        pJumpM->SetNewResMat( nAdjustCols, nAdjustRows );
338
        pResMat = pJumpM->GetResultMatrix();
339
    }
340
}
341
342
312
bool ScInterpreter::JumpMatrix( short nStackLevel )
343
bool ScInterpreter::JumpMatrix( short nStackLevel )
313
{
344
{
314
    pJumpMatrix = pStack[sp-nStackLevel]->GetJumpMatrix();
345
    pJumpMatrix = pStack[sp-nStackLevel]->GetJumpMatrix();
Lines 404-455 bool ScInterpreter::JumpMatrix( short nS Link Here
404
                    double fVal;
435
                    double fVal;
405
                    ScRange aRange;
436
                    ScRange aRange;
406
                    PopDoubleRef( aRange );
437
                    PopDoubleRef( aRange );
407
                    ScAddress& rAdr = aRange.aStart;
408
                    ULONG nCol = (ULONG)rAdr.Col() + nC;
409
                    ULONG nRow = (ULONG)rAdr.Row() + nR;
410
                    if ( nGlobalError )
438
                    if ( nGlobalError )
411
                    {
439
                    {
412
                        fVal = CreateDoubleError( nGlobalError );
440
                        fVal = CreateDoubleError( nGlobalError );
413
                        nGlobalError = 0;
441
                        nGlobalError = 0;
414
                        pResMat->PutDouble( fVal, nC, nR );
442
                        pResMat->PutDouble( fVal, nC, nR );
415
                    }
443
                    }
416
                    else if ( nCol > static_cast<ULONG>(aRange.aEnd.Col()) ||
417
                            nRow > static_cast<ULONG>(aRange.aEnd.Row()))
418
                    {
419
                        fVal = CreateDoubleError( errNoValue );
420
                        pResMat->PutDouble( fVal, nC, nR );
421
                    }
422
                    else
444
                    else
423
                    {
445
                    {
424
                        rAdr.SetCol( static_cast<SCCOL>(nCol) );
446
                        // Do not modify the original range because we use it
425
                        rAdr.SetRow( static_cast<SCROW>(nRow) );
447
                        // to adjust the size of the result matrix if necessary.
426
                        ScBaseCell* pCell = GetCell( rAdr );
448
                        ScAddress aAdr( aRange.aStart);
427
                        if (HasCellEmptyData( pCell))
449
                        ULONG nCol = (ULONG)aAdr.Col() + nC;
428
                            pResMat->PutEmpty( nC, nR );
450
                        ULONG nRow = (ULONG)aAdr.Row() + nR;
429
                        else if (HasCellValueData( pCell))
451
                        if ((nCol > static_cast<ULONG>(aRange.aEnd.Col()) &&
452
                                    aRange.aEnd.Col() != aRange.aStart.Col())
453
                                || (nRow > static_cast<ULONG>(aRange.aEnd.Row()) &&
454
                                    aRange.aEnd.Row() != aRange.aStart.Row()))
430
                        {
455
                        {
431
                            double fCellVal = GetCellValue( rAdr, pCell);
456
                            fVal = CreateDoubleError( NOTAVAILABLE );
432
                            if ( nGlobalError )
457
                            pResMat->PutDouble( fVal, nC, nR );
433
                            {
434
                                fCellVal = CreateDoubleError(
435
                                        nGlobalError);
436
                                nGlobalError = 0;
437
                            }
438
                            pResMat->PutDouble( fCellVal, nC, nR );
439
                        }
458
                        }
440
                        else
459
                        else
441
                        {
460
                        {
442
                            String aStr;
461
                            // Replicate column and/or row of a vector if it is
443
                            GetCellString( aStr, pCell );
462
                            // one. Note that this could be a range reference
444
                            if ( nGlobalError )
463
                            // that in fact consists of only one cell, e.g. A1:A1
464
                            if (aRange.aEnd.Col() == aRange.aStart.Col())
465
                                nCol = aRange.aStart.Col();
466
                            if (aRange.aEnd.Row() == aRange.aStart.Row())
467
                                nRow = aRange.aStart.Row();
468
                            aAdr.SetCol( static_cast<SCCOL>(nCol) );
469
                            aAdr.SetRow( static_cast<SCROW>(nRow) );
470
                            ScBaseCell* pCell = GetCell( aAdr );
471
                            if (HasCellEmptyData( pCell))
472
                                pResMat->PutEmpty( nC, nR );
473
                            else if (HasCellValueData( pCell))
445
                            {
474
                            {
446
                                pResMat->PutDouble( CreateDoubleError(
475
                                double fCellVal = GetCellValue( aAdr, pCell);
447
                                            nGlobalError), nC, nR);
476
                                if ( nGlobalError )
448
                                nGlobalError = 0;
477
                                {
478
                                    fCellVal = CreateDoubleError(
479
                                            nGlobalError);
480
                                    nGlobalError = 0;
481
                                }
482
                                pResMat->PutDouble( fCellVal, nC, nR );
449
                            }
483
                            }
450
                            else
484
                            else
451
                                pResMat->PutString( aStr, nC, nR );
485
                            {
486
                                String aStr;
487
                                GetCellString( aStr, pCell );
488
                                if ( nGlobalError )
489
                                {
490
                                    pResMat->PutDouble( CreateDoubleError(
491
                                                nGlobalError), nC, nR);
492
                                    nGlobalError = 0;
493
                                }
494
                                else
495
                                    pResMat->PutString( aStr, nC, nR );
496
                            }
452
                        }
497
                        }
498
                        SCSIZE nParmCols = aRange.aEnd.Col() - aRange.aStart.Col() + 1;
499
                        SCSIZE nParmRows = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
500
                        lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nParmCols, nParmRows );
453
                    }
501
                    }
454
                }
502
                }
455
                break;
503
                break;
Lines 472-480 bool ScInterpreter::JumpMatrix( short nS Link Here
472
                    {
520
                    {
473
                        SCSIZE nCols, nRows;
521
                        SCSIZE nCols, nRows;
474
                        pMat->GetDimensions( nCols, nRows );
522
                        pMat->GetDimensions( nCols, nRows );
475
                        if ( nCols <= nC || nRows <= nR )
523
                        if ((nCols <= nC && nCols != 1) ||
524
                            (nRows <= nR && nRows != 1))
476
                        {
525
                        {
477
                            fVal = CreateDoubleError( errNoValue );
526
                            fVal = CreateDoubleError( NOTAVAILABLE );
478
                            pResMat->PutDouble( fVal, nC, nR );
527
                            pResMat->PutDouble( fVal, nC, nR );
479
                        }
528
                        }
480
                        else
529
                        else
Lines 492-497 bool ScInterpreter::JumpMatrix( short nS Link Here
492
                                pResMat->PutString( rStr, nC, nR );
541
                                pResMat->PutString( rStr, nC, nR );
493
                            }
542
                            }
494
                        }
543
                        }
544
                        lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nCols, nRows );
495
                    }
545
                    }
496
                }
546
                }
497
                break;
547
                break;
Lines 775-781 ScMatrixRef ScInterpreter::CompareMat() Link Here
775
            {
825
            {
776
                for ( SCSIZE k=0; k<nR; k++ )
826
                for ( SCSIZE k=0; k<nR; k++ )
777
                {
827
                {
778
                    if ( j < nC0 && j < nC1 && k < nR0 && k < nR1 )
828
                    SCSIZE nCol = j, nRow = k;
829
                    if (    pMat[0]->ValidColRowOrReplicated( nCol, nRow ) &&
830
                            pMat[1]->ValidColRowOrReplicated( nCol, nRow ))
779
                    {
831
                    {
780
                        for ( short i=1; i>=0; i-- )
832
                        for ( short i=1; i>=0; i-- )
781
                        {
833
                        {
(-)source/core/tool/interpr5.cxx (-53 / +34 lines)
Lines 1032-1037 void ScInterpreter::ScMatTrans() Link Here
1032
    }
1032
    }
1033
}
1033
}
1034
1034
1035
1036
/** Minimum extent of one result matrix dimension.
1037
    For a row or column vector to be replicated the larger matrix dimension is
1038
    returned, else the smaller dimension.
1039
 */
1040
inline SCSIZE lcl_GetMinExtent( SCSIZE n1, SCSIZE n2 )
1041
{
1042
    if (n1 == 1)
1043
        return n2;
1044
    else if (n2 == 1)
1045
        return n1;
1046
    else if (n1 < n2)
1047
        return n1;
1048
    else
1049
        return n2;
1050
}
1051
1035
ScMatrixRef ScInterpreter::MatAdd(ScMatrix* pMat1, ScMatrix* pMat2)
1052
ScMatrixRef ScInterpreter::MatAdd(ScMatrix* pMat1, ScMatrix* pMat2)
1036
{
1053
{
1037
    SCSIZE nC1, nC2, nMinC;
1054
    SCSIZE nC1, nC2, nMinC;
Lines 1039-1052 ScMatrixRef ScInterpreter::MatAdd(ScMatr Link Here
1039
    SCSIZE i, j;
1056
    SCSIZE i, j;
1040
    pMat1->GetDimensions(nC1, nR1);
1057
    pMat1->GetDimensions(nC1, nR1);
1041
    pMat2->GetDimensions(nC2, nR2);
1058
    pMat2->GetDimensions(nC2, nR2);
1042
    if (nC1 < nC2)
1059
    nMinC = lcl_GetMinExtent( nC1, nC2);
1043
        nMinC = nC1;
1060
    nMinR = lcl_GetMinExtent( nR1, nR2);
1044
    else
1045
        nMinC = nC2;
1046
    if (nR1 < nR2)
1047
        nMinR = nR1;
1048
    else
1049
        nMinR = nR2;
1050
    ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
1061
    ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
1051
    if (xResMat)
1062
    if (xResMat)
1052
    {
1063
    {
Lines 1074-1087 ScMatrixRef ScInterpreter::MatSub(ScMatr Link Here
1074
    SCSIZE i, j;
1085
    SCSIZE i, j;
1075
    pMat1->GetDimensions(nC1, nR1);
1086
    pMat1->GetDimensions(nC1, nR1);
1076
    pMat2->GetDimensions(nC2, nR2);
1087
    pMat2->GetDimensions(nC2, nR2);
1077
    if (nC1 < nC2)
1088
    nMinC = lcl_GetMinExtent( nC1, nC2);
1078
        nMinC = nC1;
1089
    nMinR = lcl_GetMinExtent( nR1, nR2);
1079
    else
1080
        nMinC = nC2;
1081
    if (nR1 < nR2)
1082
        nMinR = nR1;
1083
    else
1084
        nMinR = nR2;
1085
    ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
1090
    ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
1086
    if (xResMat)
1091
    if (xResMat)
1087
    {
1092
    {
Lines 1109-1122 ScMatrixRef ScInterpreter::MatMul(ScMatr Link Here
1109
    SCSIZE i, j;
1114
    SCSIZE i, j;
1110
    pMat1->GetDimensions(nC1, nR1);
1115
    pMat1->GetDimensions(nC1, nR1);
1111
    pMat2->GetDimensions(nC2, nR2);
1116
    pMat2->GetDimensions(nC2, nR2);
1112
    if (nC1 < nC2)
1117
    nMinC = lcl_GetMinExtent( nC1, nC2);
1113
        nMinC = nC1;
1118
    nMinR = lcl_GetMinExtent( nR1, nR2);
1114
    else
1115
        nMinC = nC2;
1116
    if (nR1 < nR2)
1117
        nMinR = nR1;
1118
    else
1119
        nMinR = nR2;
1120
    ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
1119
    ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
1121
    if (xResMat)
1120
    if (xResMat)
1122
    {
1121
    {
Lines 1144-1157 ScMatrixRef ScInterpreter::MatDiv(ScMatr Link Here
1144
    SCSIZE i, j;
1143
    SCSIZE i, j;
1145
    pMat1->GetDimensions(nC1, nR1);
1144
    pMat1->GetDimensions(nC1, nR1);
1146
    pMat2->GetDimensions(nC2, nR2);
1145
    pMat2->GetDimensions(nC2, nR2);
1147
    if (nC1 < nC2)
1146
    nMinC = lcl_GetMinExtent( nC1, nC2);
1148
        nMinC = nC1;
1147
    nMinR = lcl_GetMinExtent( nR1, nR2);
1149
    else
1150
        nMinC = nC2;
1151
    if (nR1 < nR2)
1152
        nMinR = nR1;
1153
    else
1154
        nMinR = nR2;
1155
    ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
1148
    ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
1156
    if (xResMat)
1149
    if (xResMat)
1157
    {
1150
    {
Lines 1180-1193 ScMatrixRef ScInterpreter::MatPow(ScMatr Link Here
1180
    SCSIZE i, j;
1173
    SCSIZE i, j;
1181
    pMat1->GetDimensions(nC1, nR1);
1174
    pMat1->GetDimensions(nC1, nR1);
1182
    pMat2->GetDimensions(nC2, nR2);
1175
    pMat2->GetDimensions(nC2, nR2);
1183
    if (nC1 < nC2)
1176
    nMinC = lcl_GetMinExtent( nC1, nC2);
1184
        nMinC = nC1;
1177
    nMinR = lcl_GetMinExtent( nR1, nR2);
1185
    else
1186
        nMinC = nC2;
1187
    if (nR1 < nR2)
1188
        nMinR = nR1;
1189
    else
1190
        nMinR = nR2;
1191
    ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
1178
    ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
1192
    if (xResMat)
1179
    if (xResMat)
1193
    {
1180
    {
Lines 1215-1228 ScMatrixRef ScInterpreter::MatConcat(ScM Link Here
1215
    SCSIZE i, j;
1202
    SCSIZE i, j;
1216
    pMat1->GetDimensions(nC1, nR1);
1203
    pMat1->GetDimensions(nC1, nR1);
1217
    pMat2->GetDimensions(nC2, nR2);
1204
    pMat2->GetDimensions(nC2, nR2);
1218
    if (nC1 < nC2)
1205
    nMinC = lcl_GetMinExtent( nC1, nC2);
1219
        nMinC = nC1;
1206
    nMinR = lcl_GetMinExtent( nR1, nR2);
1220
    else
1221
        nMinC = nC2;
1222
    if (nR1 < nR2)
1223
        nMinR = nR1;
1224
    else
1225
        nMinR = nR2;
1226
    ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
1207
    ScMatrixRef xResMat = GetNewMat(nMinC, nMinR);
1227
    if (xResMat)
1208
    if (xResMat)
1228
    {
1209
    {
Lines 3693-3703 void ScInterpreter::ScMatRef() Link Here
3693
        const ScMatrix* pMat = pCell->GetMatrix();
3674
        const ScMatrix* pMat = pCell->GetMatrix();
3694
        if( pMat )
3675
        if( pMat )
3695
        {
3676
        {
3696
            SCSIZE nCl, nRw;
3677
            SCSIZE nCols, nRows;
3697
            pMat->GetDimensions( nCl, nRw );
3678
            pMat->GetDimensions( nCols, nRows );
3698
            SCSIZE nC = static_cast<SCSIZE>(aPos.Col() - aAdr.Col());
3679
            SCSIZE nC = static_cast<SCSIZE>(aPos.Col() - aAdr.Col());
3699
            SCSIZE nR = static_cast<SCSIZE>(aPos.Row() - aAdr.Row());
3680
            SCSIZE nR = static_cast<SCSIZE>(aPos.Row() - aAdr.Row());
3700
            if (nC < nCl && nR < nRw)
3681
            if ((nCols <= nC && nCols != 1) || (nRows <= nR && nRows != 1))
3682
                PushNA();
3683
            else
3701
            {
3684
            {
3702
                ScMatValType nMatValType;
3685
                ScMatValType nMatValType;
3703
                const ScMatrixValue* pMatVal = pMat->Get( nC, nR, nMatValType);
3686
                const ScMatrixValue* pMatVal = pMat->Get( nC, nR, nMatValType);
Lines 3724-3731 void ScInterpreter::ScMatRef() Link Here
3724
                    nFuncFmtIndex = nCurFmtIndex;
3707
                    nFuncFmtIndex = nCurFmtIndex;
3725
                }
3708
                }
3726
            }
3709
            }
3727
            else
3728
                PushNA();
3729
        }
3710
        }
3730
        else
3711
        else
3731
        {
3712
        {
(-)source/core/tool/scmatrix.cxx (-9 / +52 lines)
Lines 78-83 ScMatrix* ScMatrix::Clone() const Link Here
78
	return pScMat;
78
	return pScMat;
79
}
79
}
80
80
81
ScMatrix* ScMatrix::CloneAndExtend( SCSIZE nNewCols, SCSIZE nNewRows ) const
82
{
83
    ScMatrix* pScMat = new ScMatrix( nNewCols, nNewRows);
84
    MatCopy(*pScMat);
85
    pScMat->SetErrorInterpreter( pErrorInterpreter); 
86
    return pScMat;
87
}
88
81
void ScMatrix::SetErrorAtInterpreter( USHORT nError ) const
89
void ScMatrix::SetErrorAtInterpreter( USHORT nError ) const
82
{
90
{
83
    if ( pErrorInterpreter )
91
    if ( pErrorInterpreter )
Lines 399-427 void ScMatrix::PutBoolean( bool bVal, SC Link Here
399
407
400
USHORT ScMatrix::GetError( SCSIZE nC, SCSIZE nR) const
408
USHORT ScMatrix::GetError( SCSIZE nC, SCSIZE nR) const
401
{
409
{
402
    if (ValidColRow( nC, nR))
410
    if (ValidColRowOrReplicated( nC, nR ))
403
        return GetError( CalcOffset( nC, nR) );
411
        return GetError( CalcOffset( nC, nR) );
404
    else
412
    else
405
    {
413
    {
406
        DBG_ERRORFILE("ScMatrix::GetError: dimension error");
414
        DBG_ERRORFILE("ScMatrix::GetError: dimension error");
407
        return 0;   // TODO: do we want an error instead?
415
		return errNoValue;
408
    }
416
    }
409
}
417
}
410
418
411
double ScMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const
419
double ScMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const
412
{
420
{
413
	if (ValidColRow( nC, nR))
421
    if (ValidColRowOrReplicated( nC, nR ))
414
		return GetDouble( CalcOffset( nC, nR) );
422
		return GetDouble( CalcOffset( nC, nR) );
415
	else
423
	else
416
	{
424
	{
417
		DBG_ERRORFILE("ScMatrix::GetDouble: dimension error");
425
		DBG_ERRORFILE("ScMatrix::GetDouble: dimension error");
418
		return 0.0;
426
		return CreateDoubleError( errNoValue);
419
	}
427
	}
420
}
428
}
421
429
422
const String& ScMatrix::GetString(SCSIZE nC, SCSIZE nR) const
430
const String& ScMatrix::GetString(SCSIZE nC, SCSIZE nR) const
423
{
431
{
424
	if (ValidColRow( nC, nR))
432
    if (ValidColRowOrReplicated( nC, nR ))
425
	{
433
	{
426
		SCSIZE nIndex = CalcOffset( nC, nR);
434
		SCSIZE nIndex = CalcOffset( nC, nR);
427
		if ( IsString( nIndex ) )
435
		if ( IsString( nIndex ) )
Lines 474-480 String ScMatrix::GetString( SvNumberForm Link Here
474
482
475
String ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
483
String ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
476
{
484
{
477
    if (ValidColRow( nC, nR))
485
    if (ValidColRowOrReplicated( nC, nR ))
478
    {
486
    {
479
        SCSIZE nIndex = CalcOffset( nC, nR);
487
        SCSIZE nIndex = CalcOffset( nC, nR);
480
        return GetString( rFormatter, nIndex);
488
        return GetString( rFormatter, nIndex);
Lines 489-495 String ScMatrix::GetString( SvNumberForm Link Here
489
497
490
const ScMatrixValue* ScMatrix::Get(SCSIZE nC, SCSIZE nR, ScMatValType& nType) const
498
const ScMatrixValue* ScMatrix::Get(SCSIZE nC, SCSIZE nR, ScMatValType& nType) const
491
{
499
{
492
	if (ValidColRow( nC, nR))
500
    if (ValidColRowOrReplicated( nC, nR ))
493
	{
501
	{
494
		SCSIZE nIndex = CalcOffset( nC, nR);
502
		SCSIZE nIndex = CalcOffset( nC, nR);
495
		if (mnValType)
503
		if (mnValType)
Lines 508-518 const ScMatrixValue* ScMatrix::Get(SCSIZ Link Here
508
516
509
void ScMatrix::MatCopy(ScMatrix& mRes) const
517
void ScMatrix::MatCopy(ScMatrix& mRes) const
510
{
518
{
511
	if (nColCount != mRes.nColCount || nRowCount != mRes.nRowCount)
519
    if (nColCount > mRes.nColCount || nRowCount > mRes.nRowCount)
512
	{
520
	{
513
		DBG_ERRORFILE("ScMatrix::MatCopy: dimension error");
521
		DBG_ERRORFILE("ScMatrix::MatCopy: dimension error");
514
	}
522
	}
515
	else
523
    else if ( nColCount == mRes.nColCount && nRowCount == mRes.nRowCount )
516
	{
524
	{
517
		if (mnValType)
525
		if (mnValType)
518
		{
526
		{
Lines 541-546 void ScMatrix::MatCopy(ScMatrix& mRes) c Link Here
541
				mRes.pMat[i].fVal = pMat[i].fVal;
549
				mRes.pMat[i].fVal = pMat[i].fVal;
542
		}
550
		}
543
	}
551
	}
552
    else
553
    {
554
        // Copy this matrix to upper left rectangle of result matrix.
555
        if (mnValType)
556
        {
557
            ScMatValType nType;
558
            mRes.ResetIsString();
559
            for (SCSIZE i = 0; i < nColCount; i++)
560
            {
561
                SCSIZE nStart = i * nRowCount;
562
                SCSIZE nResStart = i * mRes.nRowCount;
563
                for (SCSIZE j = 0; j < nRowCount; j++)
564
                {
565
                    if (IsStringType( (nType = mnValType[nStart+j])))
566
                        mRes.PutStringEntry( pMat[nStart+j].pS, nType, nResStart+j );
567
                    else
568
                    {
569
                        mRes.pMat[nResStart+j].fVal = pMat[nStart+j].fVal;
570
                        mRes.mnValType[nResStart+j] = nType;
571
                    }
572
                }
573
            }
574
        }
575
        else
576
        {
577
            mRes.DeleteIsString();
578
            for (SCSIZE i = 0; i < nColCount; i++)
579
            {
580
                SCSIZE nStart = i * nRowCount;
581
                SCSIZE nResStart = i * mRes.nRowCount;
582
                for (SCSIZE j = 0; j < nRowCount; j++)
583
                    mRes.pMat[nResStart+j].fVal = pMat[nStart+j].fVal;
584
            }
585
        }
586
    }
544
}
587
}
545
588
546
void ScMatrix::MatTrans(ScMatrix& mRes) const
589
void ScMatrix::MatTrans(ScMatrix& mRes) const

Return to issue 46681