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 "compressedarray.hxx" 32 #include "address.hxx" 33 34 #include <algorithm> 35 36 template< typename A, typename D > 37 ScCompressedArray<A,D>::ScCompressedArray( A nMaxAccessP, const D& rValue, 38 size_t nDeltaP ) 39 : nCount(1) 40 , nLimit(1) 41 , nDelta( nDeltaP > 0 ? nDeltaP : 1) 42 , pData( new DataEntry[1]) 43 , nMaxAccess( nMaxAccessP) 44 { 45 pData[0].aValue = rValue; 46 pData[0].nEnd = nMaxAccess; 47 } 48 49 50 template< typename A, typename D > 51 ScCompressedArray<A,D>::ScCompressedArray( A nMaxAccessP, const D* pDataArray, 52 size_t nDataCount ) 53 : nCount(0) 54 , nLimit( nDataCount) 55 , nDelta( nScCompressedArrayDelta) 56 , pData( new DataEntry[nDataCount]) 57 , nMaxAccess( nMaxAccessP) 58 { 59 D aValue = pDataArray[0]; 60 for (size_t j=0; j<nDataCount; ++j) 61 { 62 if (!(aValue == pDataArray[j])) 63 { 64 pData[nCount].aValue = aValue; 65 pData[nCount].nEnd = j-1; 66 ++nCount; 67 aValue = pDataArray[j]; 68 } 69 } 70 pData[nCount].aValue = aValue; 71 pData[nCount].nEnd = nMaxAccess; 72 ++nCount; 73 Resize( nCount); 74 } 75 76 77 template< typename A, typename D > 78 ScCompressedArray<A,D>::~ScCompressedArray() 79 { 80 delete[] pData; 81 } 82 83 84 template< typename A, typename D > 85 void ScCompressedArray<A,D>::Resize( size_t nNewLimit) 86 { 87 if ((nCount <= nNewLimit && nNewLimit < nLimit) || nLimit < nNewLimit) 88 { 89 nLimit = nNewLimit; 90 DataEntry* pNewData = new DataEntry[nLimit]; 91 memcpy( pNewData, pData, nCount*sizeof(DataEntry)); 92 delete[] pData; 93 pData = pNewData; 94 } 95 } 96 97 98 template< typename A, typename D > 99 size_t ScCompressedArray<A,D>::Search( A nAccess ) const 100 { 101 if (nAccess == 0) 102 return 0; 103 104 long nLo = 0; 105 long nHi = static_cast<long>(nCount) - 1; 106 long nStart = 0; 107 long nEnd = 0; 108 long i = 0; 109 bool bFound = (nCount == 1); 110 while (!bFound && nLo <= nHi) 111 { 112 i = (nLo + nHi) / 2; 113 if (i > 0) 114 nStart = (long) pData[i - 1].nEnd; 115 else 116 nStart = -1; 117 nEnd = (long) pData[i].nEnd; 118 if (nEnd < (long) nAccess) 119 nLo = ++i; 120 else 121 if (nStart >= (long) nAccess) 122 nHi = --i; 123 else 124 bFound = true; 125 } 126 return (bFound ? static_cast<size_t>(i) : (nAccess < 0 ? 0 : nCount-1)); 127 } 128 129 130 template< typename A, typename D > 131 void ScCompressedArray<A,D>::SetValue( A nStart, A nEnd, const D& rValue ) 132 { 133 if (0 <= nStart && nStart <= nMaxAccess && 0 <= nEnd && nEnd <= nMaxAccess 134 && nStart <= nEnd) 135 { 136 if ((nStart == 0) && (nEnd == nMaxAccess)) 137 Reset( rValue); 138 else 139 { 140 // Create a temporary copy in case we got a reference passed that 141 // points to a part of the array to be reallocated. 142 D aNewVal( rValue); 143 size_t nNeeded = nCount + 2; 144 if (nLimit < nNeeded) 145 { 146 nLimit += nDelta; 147 if (nLimit < nNeeded) 148 nLimit = nNeeded; 149 DataEntry* pNewData = new DataEntry[nLimit]; 150 memcpy( pNewData, pData, nCount*sizeof(DataEntry)); 151 delete[] pData; 152 pData = pNewData; 153 } 154 155 size_t ni; // number of leading entries 156 size_t nInsert; // insert position (nMaxAccess+1 := no insert) 157 bool bCombined = false; 158 bool bSplit = false; 159 if (nStart > 0) 160 { 161 // skip leading 162 ni = Search( nStart); 163 164 nInsert = nMaxAccess+1; 165 if (!(pData[ni].aValue == aNewVal)) 166 { 167 if (ni == 0 || (pData[ni-1].nEnd < nStart - 1)) 168 { // may be a split or a simple insert or just a shrink, 169 // row adjustment is done further down 170 if (pData[ni].nEnd > nEnd) 171 bSplit = true; 172 ni++; 173 nInsert = ni; 174 } 175 else if (ni > 0 && pData[ni-1].nEnd == nStart - 1) 176 nInsert = ni; 177 } 178 if (ni > 0 && pData[ni-1].aValue == aNewVal) 179 { // combine 180 pData[ni-1].nEnd = nEnd; 181 nInsert = nMaxAccess+1; 182 bCombined = true; 183 } 184 } 185 else 186 { 187 nInsert = 0; 188 ni = 0; 189 } 190 191 size_t nj = ni; // stop position of range to replace 192 while (nj < nCount && pData[nj].nEnd <= nEnd) 193 nj++; 194 if (!bSplit) 195 { 196 if (nj < nCount && pData[nj].aValue == aNewVal) 197 { // combine 198 if (ni > 0) 199 { 200 if (pData[ni-1].aValue == aNewVal) 201 { // adjacent entries 202 pData[ni-1].nEnd = pData[nj].nEnd; 203 nj++; 204 } 205 else if (ni == nInsert) 206 pData[ni-1].nEnd = nStart - 1; // shrink 207 } 208 nInsert = nMaxAccess+1; 209 bCombined = true; 210 } 211 else if (ni > 0 && ni == nInsert) 212 pData[ni-1].nEnd = nStart - 1; // shrink 213 } 214 if (ni < nj) 215 { // remove middle entries 216 if (!bCombined) 217 { // replace one entry 218 pData[ni].nEnd = nEnd; 219 pData[ni].aValue = aNewVal; 220 ni++; 221 nInsert = nMaxAccess+1; 222 } 223 if (ni < nj) 224 { // remove entries 225 memmove( pData + ni, pData + nj, 226 (nCount - nj) * sizeof(DataEntry)); 227 nCount -= nj - ni; 228 } 229 } 230 231 if (nInsert < static_cast<size_t>(nMaxAccess+1)) 232 { // insert or append new entry 233 if (nInsert <= nCount) 234 { 235 if (!bSplit) 236 memmove( pData + nInsert + 1, pData + nInsert, 237 (nCount - nInsert) * sizeof(DataEntry)); 238 else 239 { 240 memmove( pData + nInsert + 2, pData + nInsert, 241 (nCount - nInsert) * sizeof(DataEntry)); 242 pData[nInsert+1] = pData[nInsert-1]; 243 nCount++; 244 } 245 } 246 if (nInsert) 247 pData[nInsert-1].nEnd = nStart - 1; 248 pData[nInsert].nEnd = nEnd; 249 pData[nInsert].aValue = aNewVal; 250 nCount++; 251 } 252 } 253 } 254 } 255 256 257 template< typename A, typename D > 258 void ScCompressedArray<A,D>::CopyFrom( const ScCompressedArray<A,D>& rArray, A nStart, 259 A nEnd, long nSourceDy ) 260 { 261 size_t nIndex; 262 A nRegionEnd; 263 for (A j=nStart; j<=nEnd; ++j) 264 { 265 const D& rValue = (j==nStart ? 266 rArray.GetValue( j+nSourceDy, nIndex, nRegionEnd) : 267 rArray.GetNextValue( nIndex, nRegionEnd)); 268 nRegionEnd -= nSourceDy; 269 if (nRegionEnd > nEnd) 270 nRegionEnd = nEnd; 271 SetValue( j, nRegionEnd, rValue); 272 j = nRegionEnd; 273 } 274 } 275 276 277 template< typename A, typename D > 278 const D& ScCompressedArray<A,D>::Insert( A nStart, size_t nAccessCount ) 279 { 280 size_t nIndex = Search( nStart); 281 // No real insertion is needed, simply extend the one entry and adapt all 282 // following. In case nStart points to the start row of an entry, extend 283 // the previous entry (inserting before nStart). 284 if (nIndex > 0 && pData[nIndex-1].nEnd+1 == nStart) 285 --nIndex; 286 const D& rValue = pData[nIndex].aValue; // the value "copied" 287 do 288 { 289 pData[nIndex].nEnd += nAccessCount; 290 if (pData[nIndex].nEnd >= nMaxAccess) 291 { 292 pData[nIndex].nEnd = nMaxAccess; 293 nCount = nIndex + 1; // discard trailing entries 294 } 295 } while (++nIndex < nCount); 296 return rValue; 297 } 298 299 300 template< typename A, typename D > 301 void ScCompressedArray<A,D>::Remove( A nStart, size_t nAccessCount ) 302 { 303 A nEnd = nStart + nAccessCount - 1; 304 size_t nIndex = Search( nStart); 305 // equalize/combine/remove all entries in between 306 if (nEnd > pData[nIndex].nEnd) 307 SetValue( nStart, nEnd, pData[nIndex].aValue); 308 // remove an exactly matching entry by shifting up all following by one 309 if ((nStart == 0 || (nIndex > 0 && nStart == pData[nIndex-1].nEnd+1)) && 310 pData[nIndex].nEnd == nEnd && nIndex < nCount-1) 311 { 312 // In case removing an entry results in two adjacent entries with 313 // identical data, combine them into one. This is also necessary to 314 // make the algorithm used in SetValue() work correctly, it relies on 315 // the fact that consecutive values actually differ. 316 size_t nRemove; 317 if (nIndex > 0 && pData[nIndex-1].aValue == pData[nIndex+1].aValue) 318 { 319 nRemove = 2; 320 --nIndex; 321 } 322 else 323 nRemove = 1; 324 memmove( pData + nIndex, pData + nIndex + nRemove, (nCount - (nIndex + 325 nRemove)) * sizeof(DataEntry)); 326 nCount -= nRemove; 327 } 328 // adjust end rows, nIndex still being valid 329 do 330 { 331 pData[nIndex].nEnd -= nAccessCount; 332 } while (++nIndex < nCount); 333 pData[nCount-1].nEnd = nMaxAccess; 334 } 335 336 337 template< typename A, typename D > 338 A ScCompressedArray<A,D>::GetLastUnequalAccess( A nStart, const D& rCompare ) 339 { 340 A nEnd = ::std::numeric_limits<A>::max(); 341 size_t nIndex = nCount-1; 342 while (1) 343 { 344 if (pData[nIndex].aValue != rCompare) 345 { 346 nEnd = pData[nIndex].nEnd; 347 break; // while 348 } 349 else 350 { 351 if (nIndex > 0) 352 { 353 --nIndex; 354 if (pData[nIndex].nEnd < nStart) 355 break; // while 356 } 357 else 358 break; // while 359 } 360 } 361 return nEnd; 362 } 363 364 365 // === ScSummableCompressedArray ============================================= 366 367 template< typename A, typename D > 368 unsigned long ScSummableCompressedArray<A,D>::SumValues( A nStart, A nEnd ) const 369 { 370 size_t nIndex = Search( nStart); 371 unsigned long nSum = SumValuesContinuation( nStart, nEnd, nIndex); 372 if (nEnd > this->nMaxAccess) 373 nSum += this->pData[this->nCount-1].aValue * (nEnd - this->nMaxAccess); 374 return nSum; 375 } 376 377 378 template< typename A, typename D > 379 unsigned long ScSummableCompressedArray<A,D>::SumValuesContinuation( 380 A nStart, A nEnd, size_t& nIndex ) const 381 { 382 unsigned long nSum = 0; 383 A nS = nStart; 384 while (nIndex < this->nCount && nS <= nEnd) 385 { 386 A nE = ::std::min( this->pData[nIndex].nEnd, nEnd); 387 // FIXME: test for overflow in a single region? 388 unsigned long nNew = (unsigned long) this->pData[nIndex].aValue * (nE - nS + 1); 389 nSum += nNew; 390 if (nSum < nNew) 391 return ::std::numeric_limits<unsigned long>::max(); 392 nS = nE + 1; 393 if (nS <= nEnd) 394 ++nIndex; 395 } 396 return nSum; 397 } 398 399 400 template< typename A, typename D > 401 unsigned long ScSummableCompressedArray<A,D>::SumScaledValuesContinuation( 402 A nStart, A nEnd, size_t& nIndex, double fScale ) const 403 { 404 unsigned long nSum = 0; 405 A nS = nStart; 406 while (nIndex < this->nCount && nS <= nEnd) 407 { 408 A nE = ::std::min( this->pData[nIndex].nEnd, nEnd); 409 unsigned long nScaledVal = (unsigned long) (this->pData[nIndex].aValue * fScale); 410 // FIXME: test for overflow in a single region? 411 unsigned long nNew = nScaledVal * (nE - nS + 1); 412 nSum += nNew; 413 if (nSum < nNew) 414 return ::std::numeric_limits<unsigned long>::max(); 415 nS = nE + 1; 416 if (nS <= nEnd) 417 ++nIndex; 418 } 419 return nSum; 420 } 421 422 423 // === ScBitMaskCompressedArray ============================================== 424 425 template< typename A, typename D > 426 void ScBitMaskCompressedArray<A,D>::AndValue( A nStart, A nEnd, 427 const D& rValueToAnd ) 428 { 429 if (nStart > nEnd) 430 return; 431 432 size_t nIndex = Search( nStart); 433 do 434 { 435 if ((this->pData[nIndex].aValue & rValueToAnd) != this->pData[nIndex].aValue) 436 { 437 A nS = ::std::max( (nIndex>0 ? this->pData[nIndex-1].nEnd+1 : 0), nStart); 438 A nE = ::std::min( this->pData[nIndex].nEnd, nEnd); 439 SetValue( nS, nE, this->pData[nIndex].aValue & rValueToAnd); 440 if (nE >= nEnd) 441 break; // while 442 nIndex = Search( nE + 1); 443 } 444 else if (this->pData[nIndex].nEnd >= nEnd) 445 break; // while 446 else 447 ++nIndex; 448 } while (nIndex < this->nCount); 449 } 450 451 452 template< typename A, typename D > 453 void ScBitMaskCompressedArray<A,D>::OrValue( A nStart, A nEnd, 454 const D& rValueToOr ) 455 { 456 if (nStart > nEnd) 457 return; 458 459 size_t nIndex = Search( nStart); 460 do 461 { 462 if ((this->pData[nIndex].aValue | rValueToOr) != this->pData[nIndex].aValue) 463 { 464 A nS = ::std::max( (nIndex>0 ? this->pData[nIndex-1].nEnd+1 : 0), nStart); 465 A nE = ::std::min( this->pData[nIndex].nEnd, nEnd); 466 SetValue( nS, nE, this->pData[nIndex].aValue | rValueToOr); 467 if (nE >= nEnd) 468 break; // while 469 nIndex = Search( nE + 1); 470 } 471 else if (this->pData[nIndex].nEnd >= nEnd) 472 break; // while 473 else 474 ++nIndex; 475 } while (nIndex < this->nCount); 476 } 477 478 479 template< typename A, typename D > 480 void ScBitMaskCompressedArray<A,D>::CopyFromAnded( 481 const ScBitMaskCompressedArray<A,D>& rArray, A nStart, A nEnd, 482 const D& rValueToAnd, long nSourceDy ) 483 { 484 size_t nIndex; 485 A nRegionEnd; 486 for (A j=nStart; j<=nEnd; ++j) 487 { 488 const D& rValue = (j==nStart ? 489 rArray.GetValue( j+nSourceDy, nIndex, nRegionEnd) : 490 rArray.GetNextValue( nIndex, nRegionEnd)); 491 nRegionEnd -= nSourceDy; 492 if (nRegionEnd > nEnd) 493 nRegionEnd = nEnd; 494 SetValue( j, nRegionEnd, rValue & rValueToAnd); 495 j = nRegionEnd; 496 } 497 } 498 499 500 template< typename A, typename D > 501 void ScBitMaskCompressedArray<A,D>::CopyFromOred( 502 const ScBitMaskCompressedArray<A,D>& rArray, A nStart, A nEnd, 503 const D& rValueToOr, long nSourceDy ) 504 { 505 size_t nIndex; 506 A nRegionEnd; 507 for (A j=nStart; j<=nEnd; ++j) 508 { 509 const D& rValue = (j==nStart ? 510 rArray.GetValue( j+nSourceDy, nIndex, nRegionEnd) : 511 rArray.GetNextValue( nIndex, nRegionEnd)); 512 nRegionEnd -= nSourceDy; 513 if (nRegionEnd > nEnd) 514 nRegionEnd = nEnd; 515 SetValue( j, nRegionEnd, rValue | rValueToOr); 516 j = nRegionEnd; 517 } 518 } 519 520 521 template< typename A, typename D > 522 A ScBitMaskCompressedArray<A,D>::GetBitStateStart( A nEnd, 523 const D& rBitMask, const D& rMaskedCompare ) const 524 { 525 A nStart = ::std::numeric_limits<A>::max(); 526 size_t nIndex = Search( nEnd); 527 while ((this->pData[nIndex].aValue & rBitMask) == rMaskedCompare) 528 { 529 if (nIndex > 0) 530 { 531 --nIndex; 532 nStart = this->pData[nIndex].nEnd + 1; 533 } 534 else 535 { 536 nStart = 0; 537 break; // while 538 } 539 } 540 return nStart; 541 } 542 543 544 template< typename A, typename D > 545 A ScBitMaskCompressedArray<A,D>::GetBitStateEnd( A nStart, 546 const D& rBitMask, const D& rMaskedCompare ) const 547 { 548 A nEnd = ::std::numeric_limits<A>::max(); 549 size_t nIndex = Search( nStart); 550 while (nIndex < this->nCount && (this->pData[nIndex].aValue & rBitMask) == 551 rMaskedCompare) 552 { 553 nEnd = this->pData[nIndex].nEnd; 554 ++nIndex; 555 } 556 return nEnd; 557 } 558 559 560 template< typename A, typename D > 561 A ScBitMaskCompressedArray<A,D>::GetFirstForCondition( A nStart, A nEnd, 562 const D& rBitMask, const D& rMaskedCompare ) const 563 { 564 size_t nIndex = Search( nStart); 565 do 566 { 567 if ((this->pData[nIndex].aValue & rBitMask) == rMaskedCompare) 568 { 569 A nFound = nIndex > 0 ? this->pData[nIndex-1].nEnd + 1 : 0; 570 return ::std::max( nFound, nStart); 571 } 572 if (this->pData[nIndex].nEnd >= nEnd) 573 break; // while 574 ++nIndex; 575 } while (nIndex < this->nCount); 576 return ::std::numeric_limits<A>::max(); 577 } 578 579 580 template< typename A, typename D > 581 A ScBitMaskCompressedArray<A,D>::GetLastForCondition( A nStart, A nEnd, 582 const D& rBitMask, const D& rMaskedCompare ) const 583 { 584 size_t nIndex = Search( nEnd); 585 while (1) 586 { 587 if ((this->pData[nIndex].aValue & rBitMask) == rMaskedCompare) 588 return ::std::min( this->pData[nIndex].nEnd, nEnd); 589 590 if (nIndex > 0) 591 { 592 --nIndex; 593 if (this->pData[nIndex].nEnd < nStart) 594 break; // while 595 } 596 else 597 break; // while 598 } 599 return ::std::numeric_limits<A>::max(); 600 } 601 602 603 template< typename A, typename D > 604 A ScBitMaskCompressedArray<A,D>::CountForCondition( A nStart, A nEnd, 605 const D& rBitMask, const D& rMaskedCompare ) const 606 { 607 A nRet = 0; 608 size_t nIndex = Search( nStart); 609 do 610 { 611 if ((this->pData[nIndex].aValue & rBitMask) == rMaskedCompare) 612 { 613 A nS = ::std::max( (nIndex>0 ? this->pData[nIndex-1].nEnd+1 : 0), nStart); 614 A nE = ::std::min( this->pData[nIndex].nEnd, nEnd); 615 nRet += nE - nS + 1; 616 } 617 if (this->pData[nIndex].nEnd >= nEnd) 618 break; // while 619 ++nIndex; 620 } while (nIndex < this->nCount); 621 return nRet; 622 } 623 624 625 template< typename A, typename D > 626 size_t ScBitMaskCompressedArray<A,D>::FillArrayForCondition( A nStart, A nEnd, 627 const D& rBitMask, const D& rMaskedCompare, 628 A * pArray, size_t nArraySize ) const 629 { 630 size_t nUsed = 0; 631 size_t nIndex = Search( nStart); 632 while (nIndex < this->nCount && nUsed < nArraySize) 633 { 634 if ((this->pData[nIndex].aValue & rBitMask) == rMaskedCompare) 635 { 636 A nS = ::std::max( (nIndex>0 ? this->pData[nIndex-1].nEnd+1 : 0), nStart); 637 A nE = ::std::min( this->pData[nIndex].nEnd, nEnd); 638 while (nS <= nE && nUsed < nArraySize) 639 pArray[nUsed++] = nS++; 640 } 641 if (this->pData[nIndex].nEnd >= nEnd) 642 break; // while 643 ++nIndex; 644 } 645 return nUsed; 646 } 647 648 649 template< typename A, typename D > 650 bool ScBitMaskCompressedArray<A,D>::HasCondition( A nStart, A nEnd, 651 const D& rBitMask, const D& rMaskedCompare ) const 652 { 653 size_t nIndex = Search( nStart); 654 do 655 { 656 if ((this->pData[nIndex].aValue & rBitMask) == rMaskedCompare) 657 return true; 658 if (this->pData[nIndex].nEnd >= nEnd) 659 break; // while 660 ++nIndex; 661 } while (nIndex < this->nCount); 662 return false; 663 } 664 665 666 template< typename A, typename D > 667 A ScBitMaskCompressedArray<A,D>::CountForAnyBitCondition( A nStart, A nEnd, 668 const D& rBitMask ) const 669 { 670 A nRet = 0; 671 size_t nIndex = Search( nStart); 672 do 673 { 674 if ((this->pData[nIndex].aValue & rBitMask) != 0) 675 { 676 A nS = ::std::max( (nIndex>0 ? this->pData[nIndex-1].nEnd+1 : 0), nStart); 677 A nE = ::std::min( this->pData[nIndex].nEnd, nEnd); 678 nRet += nE - nS + 1; 679 } 680 if (this->pData[nIndex].nEnd >= nEnd) 681 break; // while 682 ++nIndex; 683 } while (nIndex < this->nCount); 684 return nRet; 685 } 686 687 688 template< typename A, typename D > 689 A ScBitMaskCompressedArray<A,D>::GetLastAnyBitAccess( A nStart, 690 const D& rBitMask ) const 691 { 692 A nEnd = ::std::numeric_limits<A>::max(); 693 size_t nIndex = this->nCount-1; 694 while (1) 695 { 696 if ((this->pData[nIndex].aValue & rBitMask) != 0) 697 { 698 nEnd = this->pData[nIndex].nEnd; 699 break; // while 700 } 701 else 702 { 703 if (nIndex > 0) 704 { 705 --nIndex; 706 if (this->pData[nIndex].nEnd < nStart) 707 break; // while 708 } 709 else 710 break; // while 711 } 712 } 713 return nEnd; 714 } 715 716 717 template< typename A, typename D > 718 template< typename S > 719 unsigned long ScBitMaskCompressedArray<A,D>::SumCoupledArrayForCondition( 720 A nStart, A nEnd, const D& rBitMask, const D& rMaskedCompare, 721 const ScSummableCompressedArray<A,S>& rArray ) const 722 { 723 unsigned long nSum = 0; 724 A nS = nStart; 725 size_t nIndex1 = Search( nStart); 726 size_t nIndex2 = rArray.Search( nStart); 727 do 728 { 729 if ((this->pData[nIndex1].aValue & rBitMask) == rMaskedCompare) 730 { 731 while (nIndex2 < rArray.GetEntryCount() && 732 rArray.GetDataEntry(nIndex2).nEnd < nS) 733 ++nIndex2; 734 unsigned long nNew = rArray.SumValuesContinuation( nS, 735 ::std::min( this->pData[nIndex1].nEnd, nEnd), nIndex2); 736 nSum += nNew; 737 if (nSum < nNew) 738 return ::std::numeric_limits<unsigned long>::max(); 739 } 740 nS = this->pData[nIndex1].nEnd + 1; 741 ++nIndex1; 742 } while (nIndex1 < this->nCount && nS <= nEnd); 743 if (nEnd > this->nMaxAccess && 744 (this->pData[this->GetEntryCount()-1].aValue & rBitMask) == rMaskedCompare) 745 nSum += rArray.GetDataEntry(rArray.GetEntryCount()-1).aValue * (nEnd - 746 this->nMaxAccess); 747 return nSum; 748 } 749 750 751 template< typename A, typename D > 752 template< typename S > 753 unsigned long ScBitMaskCompressedArray<A,D>::SumScaledCoupledArrayForCondition( 754 A nStart, A nEnd, const D& rBitMask, const D& rMaskedCompare, 755 const ScSummableCompressedArray<A,S>& rArray, double fScale ) const 756 { 757 unsigned long nSum = 0; 758 A nS = nStart; 759 size_t nIndex1 = Search( nStart); 760 size_t nIndex2 = rArray.Search( nStart); 761 do 762 { 763 if ((this->pData[nIndex1].aValue & rBitMask) == rMaskedCompare) 764 { 765 while (nIndex2 < rArray.GetEntryCount() && 766 rArray.GetDataEntry(nIndex2).nEnd < nS) 767 ++nIndex2; 768 unsigned long nNew = rArray.SumScaledValuesContinuation( nS, 769 ::std::min( this->pData[nIndex1].nEnd, nEnd), nIndex2, fScale); 770 nSum += nNew; 771 if (nSum < nNew) 772 return ::std::numeric_limits<unsigned long>::max(); 773 } 774 nS = this->pData[nIndex1].nEnd + 1; 775 ++nIndex1; 776 } while (nIndex1 < this->nCount && nS <= nEnd); 777 if (nEnd > this->nMaxAccess && 778 (this->pData[this->GetEntryCount()-1].aValue & rBitMask) == rMaskedCompare) 779 nSum += (unsigned long) 780 (rArray.GetDataEntry(rArray.GetEntryCount()-1).aValue * fScale) * 781 (nEnd - this->nMaxAccess); 782 return nSum; 783 } 784 785 786 // === ScCompressedArrayIterator ============================================= 787 788 template< typename A, typename D > 789 template< typename X > 790 void ScCompressedArrayIterator<A,D>::Follow( 791 const ScCompressedArrayIterator<A,X>& rIter ) 792 { 793 nCurrent = rIter.GetPos(); 794 if (GetRangeStart() <= nCurrent && nCurrent <= GetRangeEnd()) 795 ; // nothing 796 else if (nCurrent > GetRangeEnd()) 797 { 798 A nPos = nCurrent; // nCurrent gets changed in NextRange() 799 bool bAdv; 800 do 801 { 802 bAdv = NextRange(); 803 } while (bAdv && GetRangeEnd() < nPos); 804 nCurrent = nPos; 805 } 806 else 807 nIndex = rArray.Search( nCurrent); 808 } 809 810 811 // === ScCoupledCompressedArrayIterator ====================================== 812 813 template< typename A, typename D, typename S > 814 ScCoupledCompressedArrayIterator<A,D,S>::ScCoupledCompressedArrayIterator( 815 const ScBitMaskCompressedArray<A,D> & rArray1, A nStart, A nEnd, 816 const D& rBitMaskP, const D& rMaskedCompareP, 817 const ScCompressedArray<A,S> & rArray2 ) 818 : aIter1( rArray1, nStart, nEnd ) 819 , aIter2( rArray2, nStart, nEnd ) 820 , rBitMask( rBitMaskP ) 821 , rMaskedCompare( rMaskedCompareP ) 822 { 823 InitLimits(); 824 } 825 826 827 template< typename A, typename D, typename S > 828 void ScCoupledCompressedArrayIterator<A,D,S>::InitLimits() 829 { 830 bool bFound = true; 831 bool bMoved = false; 832 while (bFound && ((*aIter1 & rBitMask) != rMaskedCompare)) 833 { 834 bFound = aIter1.NextRange(); 835 bMoved = true; 836 } 837 if (bMoved && bFound) 838 aIter2.Follow( aIter1); 839 } 840 841 842 template< typename A, typename D, typename S > 843 void ScCoupledCompressedArrayIterator<A,D,S>::NewLimits( A nStart, A nEnd ) 844 { 845 aIter1.NewLimits( nStart, nEnd); 846 aIter2.NewLimits( nStart, nEnd); 847 InitLimits(); 848 } 849 850 851 template< typename A, typename D, typename S > 852 bool ScCoupledCompressedArrayIterator<A,D,S>::NextRange() 853 { 854 bool bAdv; 855 if (aIter1.GetRangeEnd() <= aIter2.GetRangeEnd()) 856 { 857 // Advance bit mask array until condition is met, coupled array 858 // follows. 859 do 860 { 861 bAdv = aIter1.NextRange(); 862 } while (bAdv && ((*aIter1 & rBitMask) != rMaskedCompare)); 863 if (bAdv) 864 aIter2.Follow( aIter1); 865 } 866 else 867 { 868 // Make coupled array catch up with bit mask array. 869 do 870 { 871 bAdv = aIter2.NextRange(); 872 } while (bAdv && aIter2.GetRangeEnd() < aIter1.GetRangeStart()); 873 if (bAdv) 874 aIter1.Follow( aIter2); // synchronize aIter1.nCurrent 875 } 876 return operator bool(); 877 } 878 879 880 template< typename A, typename D, typename S > 881 void ScCoupledCompressedArrayIterator<A,D,S>::Resync( A nPos ) 882 { 883 aIter1.Resync( nPos); 884 aIter2.Resync( nPos); 885 InitLimits(); 886 } 887 888 889 // === Force instantiation of specializations ================================ 890 891 template class ScCompressedArray< SCROW, sal_uInt16>; // heights, base class 892 template class ScSummableCompressedArray< SCROW, sal_uInt16>; // heights 893 template class ScCompressedArray< SCROW, sal_uInt8>; // flags, base class 894 template class ScBitMaskCompressedArray< SCROW, sal_uInt8>; // flags 895 template unsigned long ScBitMaskCompressedArray< SCROW, 896 sal_uInt8>::SumCoupledArrayForCondition( SCROW, SCROW, const sal_uInt8&, const sal_uInt8&, 897 const ScSummableCompressedArray< SCROW, sal_uInt16>&) const; 898 template unsigned long ScBitMaskCompressedArray< SCROW, 899 sal_uInt8>::SumScaledCoupledArrayForCondition( SCROW, SCROW, const sal_uInt8&, 900 const sal_uInt8&, const ScSummableCompressedArray< SCROW, sal_uInt16>&, 901 double) const; 902 template void ScCompressedArrayIterator< SCROW, sal_uInt16>::Follow( 903 const ScCompressedArrayIterator< SCROW, sal_uInt8>&); 904 template class ScCoupledCompressedArrayIterator< SCROW, sal_uInt8, sal_uInt16>; 905 906 // === EOF =================================================================== 907