xref: /aoo41x/main/sc/source/core/tool/scmatrix.cxx (revision cdf0e10c)
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