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