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