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