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