xref: /AOO41X/main/sc/source/core/tool/scmatrix.cxx (revision 245212b4a6344def03df5c29631ba99a8d6dbb8e)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 #include <tools/debug.hxx>
28 
29 #include "scmatrix.hxx"
30 #include "global.hxx"
31 #include "address.hxx"
32 #include "formula/errorcodes.hxx"
33 #include "interpre.hxx"
34 #include <svl/zforlist.hxx>
35 #include <tools/stream.hxx>
36 #include <rtl/math.hxx>
37 
38 #include <math.h>
39 
40 //------------------------------------------------------------------------
41 
CreateMatrix(SCSIZE nC,SCSIZE nR)42 void ScMatrix::CreateMatrix(SCSIZE nC, SCSIZE nR)       // nur fuer ctor
43 {
44     pErrorInterpreter = NULL;
45     nColCount = nC;
46     nRowCount = nR;
47     SCSIZE nCount = nColCount * nRowCount;
48     if ( !nCount || nCount > GetElementsMax() )
49     {
50         DBG_ERRORFILE("ScMatrix::CreateMatrix: dimension error");
51         nColCount = nRowCount = 1;
52         pMat = new ScMatrixValue[1];
53         pMat[0].fVal = CreateDoubleError( errStackOverflow);
54     }
55     else
56         pMat = new ScMatrixValue[nCount];
57     mnValType = NULL;
58     mnNonValue = 0;
59 }
60 
Clear()61 void ScMatrix::Clear()
62 {
63     DeleteIsString();
64     delete [] pMat;
65 }
66 
~ScMatrix()67 ScMatrix::~ScMatrix()
68 {
69     Clear();
70 }
71 
Clone() const72 ScMatrix* ScMatrix::Clone() const
73 {
74     ScMatrix* pScMat = new ScMatrix( nColCount, nRowCount);
75     MatCopy(*pScMat);
76     pScMat->SetErrorInterpreter( pErrorInterpreter);    // TODO: really?
77     return pScMat;
78 }
79 
CloneIfConst()80 ScMatrix* ScMatrix::CloneIfConst()
81 {
82     return (mbCloneIfConst || IsEternalRef()) ? Clone() : this;
83 }
84 
Resize(SCSIZE nC,SCSIZE nR)85 void ScMatrix::Resize( SCSIZE nC, SCSIZE nR)
86 {
87     Clear();
88     CreateMatrix(nC, nR);
89 }
90 
CloneAndExtend(SCSIZE nNewCols,SCSIZE nNewRows) const91 ScMatrix* ScMatrix::CloneAndExtend( SCSIZE nNewCols, SCSIZE nNewRows ) const
92 {
93     ScMatrix* pScMat = new ScMatrix( nNewCols, nNewRows);
94     MatCopy(*pScMat);
95     pScMat->SetErrorInterpreter( pErrorInterpreter);
96     return pScMat;
97 }
98 
SetErrorAtInterpreter(sal_uInt16 nError) const99 void ScMatrix::SetErrorAtInterpreter( sal_uInt16 nError ) const
100 {
101     if ( pErrorInterpreter )
102         pErrorInterpreter->SetError( nError);
103 }
104 
105 //
106 //  File format: sal_uInt16 columns, sal_uInt16 rows, (columns*rows) entries:
107 //  sal_uInt8 type ( CELLTYPE_NONE, CELLTYPE_VALUE, CELLTYPE_STRING ); nothing, double or String
108 //
109 
ScMatrix(SvStream &)110 ScMatrix::ScMatrix(SvStream& /* rStream */)
111         : pErrorInterpreter( NULL)
112         , nRefCnt(0)
113 {
114 #if SC_ROWLIMIT_STREAM_ACCESS
115 #error address types changed!
116     sal_uInt16 nC;
117     sal_uInt16 nR;
118 
119     rStream >> nC;
120     rStream >> nR;
121 
122     CreateMatrix(nC, nR);
123     DBG_ASSERT( pMat, "pMat == NULL" );
124 
125     String aMatStr;
126     double fVal;
127     rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
128     SCSIZE nCount = nColCount * nRowCount;
129     SCSIZE nReadCount = (SCSIZE) nC * nR;
130     for (SCSIZE i=0; i<nReadCount; i++)
131     {
132         sal_uInt8 nType;
133         rStream >> nType;
134         if ( nType == CELLTYPE_VALUE )
135         {
136             if ( i < nCount )
137                 rStream >> pMat[i].fVal;
138             else
139                 rStream >> fVal;
140         }
141         else
142         {
143             // For unknown types read and forget string (upwards compatibility)
144 
145             if ( nType != CELLTYPE_NONE )
146                 rStream.ReadByteString( aMatStr, eCharSet );
147 
148             if ( i < nCount )
149             {
150                 if (!mnValType)
151                     ResetIsString();        // init string flags
152                 mnValType[i] = ( nType == CELLTYPE_NONE ? SC_MATVAL_EMPTY : SC_MATVAL_STRING );
153                 mnNonValue++;
154 
155                 if ( nType == CELLTYPE_STRING )
156                     pMat[i].pS = new String(aMatStr);
157                 else
158                     pMat[i].pS = NULL;
159             }
160         }
161     }
162 #else
163     CreateMatrix(0,0);
164 #endif // SC_ROWLIMIT_STREAM_ACCESS
165 }
166 
Store(SvStream &) const167 void ScMatrix::Store(SvStream& /* rStream */) const
168 {
169 #if SC_ROWLIMIT_STREAM_ACCESS
170 #error address types changed!
171     SCSIZE nCount = nColCount * nRowCount;
172     // Don't store matrix with more than sal_uInt16 max elements, old versions
173     // might get confused in loops for(sal_uInt16 i=0; i<nC*nR; i++)
174     if ( !pMat || nCount > ((sal_uInt16)(~0)) )
175     {
176         DBG_ASSERT( pMat, "ScMatrix::Store: pMat == NULL" );
177         // We can't store a 0 dimension because old versions rely on some
178         // matrix being present, e.g. DDE link results, and old versions didn't
179         // create a matrix if dimension was 0. Store an error result.
180         rStream << (sal_uInt16) 1;
181         rStream << (sal_uInt16) 1;
182         rStream << (sal_uInt8) CELLTYPE_VALUE;
183         double fVal;
184         ::rtl::math::setNan( &fVal );
185         rStream << fVal;
186         return;
187     }
188 
189     rStream << (sal_uInt16) nColCount;
190 #if SC_ROWLIMIT_MORE_THAN_32K
191     #error row32k
192 #endif
193     rStream << (sal_uInt16) nRowCount;
194 
195     String aMatStr;
196     rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
197     for (SCSIZE i=0; i<nCount; i++)
198     {
199         sal_uInt8 nType = CELLTYPE_VALUE;
200         if ( mnValType && IsNonValueType( mnValType[i]))
201         {
202             if ( pMat[i].pS )
203                 aMatStr = *pMat[i].pS;
204             else
205                 aMatStr.Erase();
206 
207             if ( mnValType[i] == SC_MATVAL_STRING )
208                 nType = CELLTYPE_STRING;
209             else
210                 nType = CELLTYPE_NONE;
211         }
212         rStream << nType;
213         if ( nType == CELLTYPE_VALUE )
214             rStream << pMat[i].fVal;
215         else if ( nType == CELLTYPE_STRING )
216             rStream.WriteByteString( aMatStr, eCharSet );
217     }
218 #endif // SC_ROWLIMIT_STREAM_ACCESS
219 }
220 
ResetIsString()221 void ScMatrix::ResetIsString()
222 {
223     SCSIZE nCount = nColCount * nRowCount;
224     if (mnValType)
225     {
226         for (SCSIZE i = 0; i < nCount; i++)
227         {
228             if ( IsNonValueType( mnValType[i]))
229                 delete pMat[i].pS;
230         }
231     }
232     else
233         mnValType = new sal_uInt8[nCount];
234     memset( mnValType, 0, nCount * sizeof( sal_uInt8 ) );
235     mnNonValue = 0;
236 }
237 
DeleteIsString()238 void ScMatrix::DeleteIsString()
239 {
240     if ( mnValType )
241     {
242         SCSIZE nCount = nColCount * nRowCount;
243         for ( SCSIZE i = 0; i < nCount; i++ )
244         {
245             if (IsNonValueType( mnValType[i]))
246                 delete pMat[i].pS;
247         }
248         delete [] mnValType;
249         mnValType = NULL;
250         mnNonValue = 0;
251     }
252 }
253 
PutDouble(double fVal,SCSIZE nC,SCSIZE nR)254 void ScMatrix::PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
255 {
256     if (ValidColRow( nC, nR))
257         PutDouble( fVal, CalcOffset( nC, nR) );
258     else
259     {
260         DBG_ERRORFILE("ScMatrix::PutDouble: dimension error");
261     }
262 }
263 
PutString(const String & rStr,SCSIZE nC,SCSIZE nR)264 void ScMatrix::PutString(const String& rStr, SCSIZE nC, SCSIZE nR)
265 {
266     if (ValidColRow( nC, nR))
267         PutString( rStr, CalcOffset( nC, nR) );
268     else
269     {
270         DBG_ERRORFILE("ScMatrix::PutString: dimension error");
271     }
272 }
273 
PutString(const String & rStr,SCSIZE nIndex)274 void ScMatrix::PutString(const String& rStr, SCSIZE nIndex)
275 {
276     if (mnValType == NULL)
277         ResetIsString();
278     if ( IsNonValueType( mnValType[nIndex]) && pMat[nIndex].pS )
279         *(pMat[nIndex].pS) = rStr;
280     else
281     {
282         pMat[nIndex].pS = new String(rStr);
283         mnNonValue++;
284     }
285     mnValType[nIndex] = SC_MATVAL_STRING;
286 }
287 
PutStringEntry(const String * pStr,sal_uInt8 bFlag,SCSIZE nIndex)288 void ScMatrix::PutStringEntry( const String* pStr, sal_uInt8 bFlag, SCSIZE nIndex )
289 {
290     DBG_ASSERT( bFlag, "ScMatrix::PutStringEntry: bFlag == 0" );
291     if (mnValType == NULL)
292         ResetIsString();
293     // Make sure all bytes of the union are initialized to be able to access
294     // the value with if (IsValueOrEmpty()) GetDouble(). Backup pS first.
295     String* pS = pMat[nIndex].pS;
296     pMat[nIndex].fVal = 0.0;
297     // An EMPTY or EMPTYPATH entry must not have a string pointer therefor.
298     DBG_ASSERT( (((bFlag & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY) && !pStr) || sal_True,
299             "ScMatrix::PutStringEntry: pStr passed through EMPTY entry");
300     if ( IsNonValueType( mnValType[nIndex]) && pS )
301     {
302         if ((bFlag & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY)
303             delete pS, pS = NULL;
304         if ( pStr )
305             *pS = *pStr;
306         else if (pS)
307             pS->Erase();
308         pMat[nIndex].pS = pS;
309     }
310     else
311     {
312         pMat[nIndex].pS = (pStr ? new String(*pStr) : NULL);
313         mnNonValue++;
314     }
315     mnValType[nIndex] = bFlag;
316 }
317 
PutEmpty(SCSIZE nC,SCSIZE nR)318 void ScMatrix::PutEmpty(SCSIZE nC, SCSIZE nR)
319 {
320     if (ValidColRow( nC, nR))
321         PutEmpty( CalcOffset( nC, nR) );
322     else
323     {
324         DBG_ERRORFILE("ScMatrix::PutEmpty: dimension error");
325     }
326 }
327 
PutEmpty(SCSIZE nIndex)328 void ScMatrix::PutEmpty(SCSIZE nIndex)
329 {
330     if (mnValType == NULL)
331         ResetIsString();
332     if ( IsNonValueType( mnValType[nIndex]) && pMat[nIndex].pS )
333     {
334         delete pMat[nIndex].pS;
335     }
336     else
337     {
338         mnNonValue++;
339     }
340     mnValType[nIndex] = SC_MATVAL_EMPTY;
341     pMat[nIndex].pS = NULL;
342     pMat[nIndex].fVal = 0.0;
343 }
344 
PutEmptyPath(SCSIZE nC,SCSIZE nR)345 void ScMatrix::PutEmptyPath(SCSIZE nC, SCSIZE nR)
346 {
347     if (ValidColRow( nC, nR))
348         PutEmptyPath( CalcOffset( nC, nR) );
349     else
350     {
351         DBG_ERRORFILE("ScMatrix::PutEmptyPath: dimension error");
352     }
353 }
354 
PutEmptyPath(SCSIZE nIndex)355 void ScMatrix::PutEmptyPath(SCSIZE nIndex)
356 {
357     if (mnValType == NULL)
358         ResetIsString();
359     if ( IsNonValueType( mnValType[nIndex]) && pMat[nIndex].pS )
360     {
361         delete pMat[nIndex].pS;
362     }
363     else
364     {
365         mnNonValue++;
366     }
367     mnValType[nIndex] = SC_MATVAL_EMPTYPATH;
368     pMat[nIndex].pS = NULL;
369     pMat[nIndex].fVal = 0.0;
370 }
371 
PutBoolean(bool bVal,SCSIZE nC,SCSIZE nR)372 void ScMatrix::PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
373 {
374     if (ValidColRow( nC, nR))
375         PutBoolean( bVal, CalcOffset( nC, nR) );
376     else
377     {
378         DBG_ERRORFILE("ScMatrix::PutBoolean: dimension error");
379     }
380 }
381 
PutBoolean(bool bVal,SCSIZE nIndex)382 void ScMatrix::PutBoolean( bool bVal, SCSIZE nIndex)
383 {
384     if (mnValType == NULL)
385         ResetIsString();
386     if ( IsNonValueType( mnValType[nIndex]) && pMat[nIndex].pS )
387     {
388         delete pMat[nIndex].pS;
389         mnNonValue--;
390     }
391 
392     mnValType[nIndex] = SC_MATVAL_BOOLEAN;
393     pMat[nIndex].pS = NULL;
394     pMat[nIndex].fVal = bVal ? 1. : 0.;
395 }
396 
GetError(SCSIZE nC,SCSIZE nR) const397 sal_uInt16 ScMatrix::GetError( SCSIZE nC, SCSIZE nR) const
398 {
399     if (ValidColRowOrReplicated( nC, nR ))
400         return GetError( CalcOffset( nC, nR) );
401     else
402     {
403         DBG_ERRORFILE("ScMatrix::GetError: dimension error");
404         return errNoValue;
405     }
406 }
407 
GetDouble(SCSIZE nC,SCSIZE nR) const408 double ScMatrix::GetDouble(SCSIZE nC, SCSIZE nR) const
409 {
410     if (ValidColRowOrReplicated( nC, nR ))
411         return GetDouble( CalcOffset( nC, nR) );
412     else
413     {
414         DBG_ERRORFILE("ScMatrix::GetDouble: dimension error");
415         return CreateDoubleError( errNoValue);
416     }
417 }
418 
GetString(SCSIZE nC,SCSIZE nR) const419 const String& ScMatrix::GetString(SCSIZE nC, SCSIZE nR) const
420 {
421     if (ValidColRowOrReplicated( nC, nR ))
422     {
423         SCSIZE nIndex = CalcOffset( nC, nR);
424         if ( IsString( nIndex ) )
425             return GetString( nIndex );
426         else
427         {
428             SetErrorAtInterpreter( GetError( nIndex));
429             DBG_ERRORFILE("ScMatrix::GetString: access error, no string");
430         }
431     }
432     else
433     {
434         DBG_ERRORFILE("ScMatrix::GetString: dimension error");
435     }
436     return ScGlobal::GetEmptyString();
437 }
438 
439 
GetString(SvNumberFormatter & rFormatter,SCSIZE nIndex) const440 String ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nIndex) const
441 {
442     if (IsString( nIndex))
443     {
444         if (IsEmptyPath( nIndex))
445         {   // result of empty sal_False jump path
446             sal_uLong nKey = rFormatter.GetStandardFormat( NUMBERFORMAT_LOGICAL,
447                     ScGlobal::eLnge);
448             String aStr;
449             Color* pColor = NULL;
450             rFormatter.GetOutputString( 0.0, nKey, aStr, &pColor);
451             return aStr;
452         }
453         return GetString( nIndex );
454     }
455 
456     sal_uInt16 nError = GetError( nIndex);
457     if (nError)
458     {
459         SetErrorAtInterpreter( nError);
460         return ScGlobal::GetErrorString( nError);
461     }
462 
463     double fVal= GetDouble( nIndex);
464     sal_uLong nKey = rFormatter.GetStandardFormat( NUMBERFORMAT_NUMBER,
465             ScGlobal::eLnge);
466     String aStr;
467     rFormatter.GetInputLineString( fVal, nKey, aStr);
468     return aStr;
469 }
470 
471 
GetString(SvNumberFormatter & rFormatter,SCSIZE nC,SCSIZE nR) const472 String ScMatrix::GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const
473 {
474     if (ValidColRowOrReplicated( nC, nR ))
475     {
476         SCSIZE nIndex = CalcOffset( nC, nR);
477         return GetString( rFormatter, nIndex);
478     }
479     else
480     {
481         DBG_ERRORFILE("ScMatrix::GetString: dimension error");
482     }
483     return String();
484 }
485 
486 
Get(SCSIZE nC,SCSIZE nR,ScMatValType & nType) const487 const ScMatrixValue* ScMatrix::Get(SCSIZE nC, SCSIZE nR, ScMatValType& nType) const
488 {
489     if (ValidColRowOrReplicated( nC, nR ))
490     {
491         SCSIZE nIndex = CalcOffset( nC, nR);
492         if (mnValType)
493             nType = mnValType[nIndex];
494         else
495             nType = SC_MATVAL_VALUE;
496         return &pMat[nIndex];
497     }
498     else
499     {
500         DBG_ERRORFILE("ScMatrix::Get: dimension error");
501     }
502     nType = SC_MATVAL_EMPTY;
503     return NULL;
504 }
505 
MatCopy(ScMatrix & mRes) const506 void ScMatrix::MatCopy(ScMatrix& mRes) const
507 {
508     if (nColCount > mRes.nColCount || nRowCount > mRes.nRowCount)
509     {
510         DBG_ERRORFILE("ScMatrix::MatCopy: dimension error");
511     }
512     else if ( nColCount == mRes.nColCount && nRowCount == mRes.nRowCount )
513     {
514         if (mnValType)
515         {
516             ScMatValType nType;
517             mRes.ResetIsString();
518             for (SCSIZE i = 0; i < nColCount; i++)
519             {
520                 SCSIZE nStart = i * nRowCount;
521                 for (SCSIZE j = 0; j < nRowCount; j++)
522                 {
523                     if (IsNonValueType( (nType = mnValType[nStart+j])))
524                         mRes.PutStringEntry( pMat[nStart+j].pS, nType, nStart+j );
525                     else
526                     {
527                         mRes.pMat[nStart+j].fVal = pMat[nStart+j].fVal;
528                         mRes.mnValType[nStart+j] = nType;
529                     }
530                 }
531             }
532         }
533         else
534         {
535             mRes.DeleteIsString();
536             SCSIZE nCount = nColCount * nRowCount;
537             for (SCSIZE i = 0; i < nCount; i++)
538                 mRes.pMat[i].fVal = pMat[i].fVal;
539         }
540     }
541     else
542     {
543         // Copy this matrix to upper left rectangle of result matrix.
544         if (mnValType)
545         {
546             ScMatValType nType;
547             mRes.ResetIsString();
548             for (SCSIZE i = 0; i < nColCount; i++)
549             {
550                 SCSIZE nStart = i * nRowCount;
551                 SCSIZE nResStart = i * mRes.nRowCount;
552                 for (SCSIZE j = 0; j < nRowCount; j++)
553                 {
554                     if (IsNonValueType( (nType = mnValType[nStart+j])))
555                         mRes.PutStringEntry( pMat[nStart+j].pS, nType, nResStart+j );
556                     else
557                     {
558                         mRes.pMat[nResStart+j].fVal = pMat[nStart+j].fVal;
559                         mRes.mnValType[nResStart+j] = nType;
560                     }
561                 }
562             }
563         }
564         else
565         {
566             mRes.DeleteIsString();
567             for (SCSIZE i = 0; i < nColCount; i++)
568             {
569                 SCSIZE nStart = i * nRowCount;
570                 SCSIZE nResStart = i * mRes.nRowCount;
571                 for (SCSIZE j = 0; j < nRowCount; j++)
572                     mRes.pMat[nResStart+j].fVal = pMat[nStart+j].fVal;
573             }
574         }
575     }
576 }
577 
MatTrans(ScMatrix & mRes) const578 void ScMatrix::MatTrans(ScMatrix& mRes) const
579 {
580     if (nColCount != mRes.nRowCount || nRowCount != mRes.nColCount)
581     {
582         DBG_ERRORFILE("ScMatrix::MatTrans: dimension error");
583     }
584     else
585     {
586         if (mnValType)
587         {
588             ScMatValType nType;
589             mRes.ResetIsString();
590             for ( SCSIZE i = 0; i < nColCount; i++ )
591             {
592                 SCSIZE nStart = i * nRowCount;
593                 for ( SCSIZE j = 0; j < nRowCount; j++ )
594                 {
595                     if (IsNonValueType( (nType = mnValType[nStart+j])))
596                         mRes.PutStringEntry( pMat[nStart+j].pS, nType, j*mRes.nRowCount+i );
597                     else
598                     {
599                         mRes.pMat[j*mRes.nRowCount+i].fVal = pMat[nStart+j].fVal;
600                         mRes.mnValType[j*mRes.nRowCount+i] = nType;
601                     }
602                 }
603             }
604         }
605         else
606         {
607             mRes.DeleteIsString();
608             for ( SCSIZE i = 0; i < nColCount; i++ )
609             {
610                 SCSIZE nStart = i * nRowCount;
611                 for ( SCSIZE j = 0; j < nRowCount; j++ )
612                 {
613                     mRes.pMat[j*mRes.nRowCount+i].fVal = pMat[nStart+j].fVal;
614                 }
615             }
616         }
617     }
618 }
619 
620 //UNUSED2009-05 void ScMatrix::MatCopyUpperLeft(ScMatrix& mRes) const
621 //UNUSED2009-05 {
622 //UNUSED2009-05     if (nColCount < mRes.nColCount || nRowCount < mRes.nRowCount)
623 //UNUSED2009-05     {
624 //UNUSED2009-05         DBG_ERRORFILE("ScMatrix::MatCopyUpperLeft: dimension error");
625 //UNUSED2009-05     }
626 //UNUSED2009-05     else
627 //UNUSED2009-05     {
628 //UNUSED2009-05         if (mnValType)
629 //UNUSED2009-05         {
630 //UNUSED2009-05             ScMatValType nType;
631 //UNUSED2009-05             mRes.ResetIsString();
632 //UNUSED2009-05             for ( SCSIZE i = 0; i < mRes.nColCount; i++ )
633 //UNUSED2009-05             {
634 //UNUSED2009-05                 SCSIZE nStart = i * nRowCount;
635 //UNUSED2009-05                 for ( SCSIZE j = 0; j < mRes.nRowCount; j++ )
636 //UNUSED2009-05                 {
637 //UNUSED2009-05                     if ( IsNonValueType( (nType = mnValType[nStart+j]) ))
638 //UNUSED2009-05                         mRes.PutStringEntry( pMat[nStart+j].pS, nType,
639 //UNUSED2009-05                             i*mRes.nRowCount+j );
640 //UNUSED2009-05                     else
641 //UNUSED2009-05                     {
642 //UNUSED2009-05                         mRes.pMat[i*mRes.nRowCount+j].fVal = pMat[nStart+j].fVal;
643 //UNUSED2009-05                         mRes.mnValType[i*mRes.nRowCount+j] = nType;
644 //UNUSED2009-05                     }
645 //UNUSED2009-05                 }
646 //UNUSED2009-05             }
647 //UNUSED2009-05         }
648 //UNUSED2009-05         else
649 //UNUSED2009-05         {
650 //UNUSED2009-05             mRes.DeleteIsString();
651 //UNUSED2009-05             for ( SCSIZE i = 0; i < mRes.nColCount; i++ )
652 //UNUSED2009-05             {
653 //UNUSED2009-05                 SCSIZE nStart = i * nRowCount;
654 //UNUSED2009-05                 for ( SCSIZE j = 0; j < mRes.nRowCount; j++ )
655 //UNUSED2009-05                 {
656 //UNUSED2009-05                     mRes.pMat[i*mRes.nRowCount+j].fVal = pMat[nStart+j].fVal;
657 //UNUSED2009-05                 }
658 //UNUSED2009-05             }
659 //UNUSED2009-05         }
660 //UNUSED2009-05     }
661 //UNUSED2009-05 }
662 
FillDouble(double fVal,SCSIZE nC1,SCSIZE nR1,SCSIZE nC2,SCSIZE nR2)663 void ScMatrix::FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 )
664 {
665     if (ValidColRow( nC1, nR1) && ValidColRow( nC2, nR2))
666     {
667         if ( nC1 == 0 && nR1 == 0 && nC2 == nColCount-1 && nR2 == nRowCount-1 )
668         {
669             SCSIZE nEnd = nColCount * nRowCount;
670             for ( SCSIZE j=0; j<nEnd; j++ )
671                 pMat[j].fVal = fVal;
672         }
673         else
674         {
675             for ( SCSIZE i=nC1; i<=nC2; i++ )
676             {
677                 SCSIZE nOff1 = i * nRowCount + nR1;
678                 SCSIZE nOff2 = nOff1 + nR2 - nR1;
679                 for ( SCSIZE j=nOff1; j<=nOff2; j++ )
680                     pMat[j].fVal = fVal;
681             }
682         }
683     }
684     else
685     {
686         DBG_ERRORFILE("ScMatrix::FillDouble: dimension error");
687     }
688 }
689 
CompareEqual()690 void ScMatrix::CompareEqual()
691 {
692     SCSIZE n = nColCount * nRowCount;
693     if ( mnValType )
694     {
695         for ( SCSIZE j=0; j<n; j++ )
696             if ( IsValueType( mnValType[j]) )               // else: #WERT!
697                 if ( ::rtl::math::isFinite( pMat[j].fVal))  // else: DoubleError
698                     pMat[j].fVal = (pMat[j].fVal == 0.0);
699     }
700     else
701     {
702         for ( SCSIZE j=0; j<n; j++ )
703             if ( ::rtl::math::isFinite( pMat[j].fVal))  // else: DoubleError
704                 pMat[j].fVal = (pMat[j].fVal == 0.0);
705     }
706 }
707 
CompareNotEqual()708 void ScMatrix::CompareNotEqual()
709 {
710     SCSIZE n = nColCount * nRowCount;
711     if ( mnValType )
712     {
713         for ( SCSIZE j=0; j<n; j++ )
714             if ( IsValueType( mnValType[j]) )               // else: #WERT!
715                 if ( ::rtl::math::isFinite( pMat[j].fVal))  // else: DoubleError
716                     pMat[j].fVal = (pMat[j].fVal != 0.0);
717     }
718     else
719     {
720         for ( SCSIZE j=0; j<n; j++ )
721             if ( ::rtl::math::isFinite( pMat[j].fVal))  // else: DoubleError
722                 pMat[j].fVal = (pMat[j].fVal != 0.0);
723     }
724 }
725 
CompareLess()726 void ScMatrix::CompareLess()
727 {
728     SCSIZE n = nColCount * nRowCount;
729     if ( mnValType )
730     {
731         for ( SCSIZE j=0; j<n; j++ )
732             if ( IsValueType( mnValType[j]) )               // else: #WERT!
733                 if ( ::rtl::math::isFinite( pMat[j].fVal))  // else: DoubleError
734                     pMat[j].fVal = (pMat[j].fVal < 0.0);
735     }
736     else
737     {
738         for ( SCSIZE j=0; j<n; j++ )
739             if ( ::rtl::math::isFinite( pMat[j].fVal))  // else: DoubleError
740                 pMat[j].fVal = (pMat[j].fVal < 0.0);
741     }
742 }
743 
CompareGreater()744 void ScMatrix::CompareGreater()
745 {
746     SCSIZE n = nColCount * nRowCount;
747     if ( mnValType )
748     {
749         for ( SCSIZE j=0; j<n; j++ )
750             if ( IsValueType( mnValType[j]) )               // else: #WERT!
751                 if ( ::rtl::math::isFinite( pMat[j].fVal))  // else: DoubleError
752                     pMat[j].fVal = (pMat[j].fVal > 0.0);
753     }
754     else
755     {
756         for ( SCSIZE j=0; j<n; j++ )
757             if ( ::rtl::math::isFinite( pMat[j].fVal))  // else: DoubleError
758                 pMat[j].fVal = (pMat[j].fVal > 0.0);
759     }
760 }
761 
CompareLessEqual()762 void ScMatrix::CompareLessEqual()
763 {
764     SCSIZE n = nColCount * nRowCount;
765     if ( mnValType )
766     {
767         for ( SCSIZE j=0; j<n; j++ )
768             if ( IsValueType( mnValType[j]) )               // else: #WERT!
769                 if ( ::rtl::math::isFinite( pMat[j].fVal))  // else: DoubleError
770                     pMat[j].fVal = (pMat[j].fVal <= 0.0);
771     }
772     else
773     {
774         for ( SCSIZE j=0; j<n; j++ )
775             if ( ::rtl::math::isFinite( pMat[j].fVal))  // else: DoubleError
776                 pMat[j].fVal = (pMat[j].fVal <= 0.0);
777     }
778 }
779 
CompareGreaterEqual()780 void ScMatrix::CompareGreaterEqual()
781 {
782     SCSIZE n = nColCount * nRowCount;
783     if ( mnValType )
784     {
785         for ( SCSIZE j=0; j<n; j++ )
786             if ( IsValueType( mnValType[j]) )               // else: #WERT!
787                 if ( ::rtl::math::isFinite( pMat[j].fVal))  // else: DoubleError
788                     pMat[j].fVal = (pMat[j].fVal >= 0.0);
789     }
790     else
791     {
792         for ( SCSIZE j=0; j<n; j++ )
793             if ( ::rtl::math::isFinite( pMat[j].fVal))  // else: DoubleError
794                 pMat[j].fVal = (pMat[j].fVal >= 0.0);
795     }
796 }
797 
And()798 double ScMatrix::And()
799 {
800     SCSIZE n = nColCount * nRowCount;
801     bool bAnd = true;
802     if ( mnValType )
803     {
804         for ( SCSIZE j=0; bAnd && j<n; j++ )
805         {
806             if ( !IsValueType( mnValType[j]) )
807             {   // assuming a CompareMat this is an error
808                 return CreateDoubleError( errIllegalArgument );
809             }
810             else if ( ::rtl::math::isFinite( pMat[j].fVal))
811                 bAnd = (pMat[j].fVal != 0.0);
812             else
813                 return pMat[j].fVal;    // DoubleError
814         }
815     }
816     else
817     {
818         for ( SCSIZE j=0; bAnd && j<n; j++ )
819         {
820             if ( ::rtl::math::isFinite( pMat[j].fVal))
821                 bAnd = (pMat[j].fVal != 0.0);
822             else
823                 return pMat[j].fVal;    // DoubleError
824         }
825     }
826     return bAnd;
827 }
828 
Or()829 double ScMatrix::Or()
830 {
831     SCSIZE n = nColCount * nRowCount;
832     bool bOr = false;
833     if ( mnValType )
834     {
835         for ( SCSIZE j=0; !bOr && j<n; j++ )
836             if ( !IsValueType( mnValType[j]) )
837             {   // assuming a CompareMat this is an error
838                 return CreateDoubleError( errIllegalArgument );
839             }
840             else if ( ::rtl::math::isFinite( pMat[j].fVal))
841                 bOr = (pMat[j].fVal != 0.0);
842             else
843                 return pMat[j].fVal;    // DoubleError
844     }
845     else
846     {
847         for ( SCSIZE j=0; !bOr && j<n; j++ )
848             if ( ::rtl::math::isFinite( pMat[j].fVal))
849                 bOr = (pMat[j].fVal != 0.0);
850             else
851                 return pMat[j].fVal;    // DoubleError
852     }
853     return bOr;
854 }
855 
856 // @Author Marina Plakalovic
857 // Computes the logical XOR of elements
Xor()858 double ScMatrix::Xor()
859 {
860     SCSIZE n = nColCount * nRowCount;
861     bool bXor = false;
862     if ( mnValType )
863     {
864         for ( SCSIZE j=0; j<n; j++ )
865             if ( !IsValueType( mnValType[j]) )
866             {   // assuming a CompareMat this is an error
867                 return CreateDoubleError( errIllegalArgument );
868             }
869             else if ( ::rtl::math::isFinite( pMat[j].fVal))
870                 bXor ^= (pMat[j].fVal != 0.0);
871             else
872                 return pMat[j].fVal;    // DoubleError
873     }
874     else
875     {
876         for ( SCSIZE j=0; j<n; j++ )
877             if ( ::rtl::math::isFinite( pMat[j].fVal))
878                 bXor ^= (pMat[j].fVal != 0.0);
879             else
880                 return pMat[j].fVal;    // DoubleError
881     }
882     return bXor;
883 }
884