1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: compressedarray.cxx,v $
10 * $Revision: 1.10.32.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include "compressedarray.hxx"
35 #include "address.hxx"
39 template< typename A
, typename D
>
40 ScCompressedArray
<A
,D
>::ScCompressedArray( A nMaxAccessP
, const D
& rValue
,
44 , nDelta( nDeltaP
> 0 ? nDeltaP
: 1)
45 , pData( new DataEntry
[1])
46 , nMaxAccess( nMaxAccessP
)
48 pData
[0].aValue
= rValue
;
49 pData
[0].nEnd
= nMaxAccess
;
53 template< typename A
, typename D
>
54 ScCompressedArray
<A
,D
>::ScCompressedArray( A nMaxAccessP
, const D
* pDataArray
,
58 , nDelta( nScCompressedArrayDelta
)
59 , pData( new DataEntry
[nDataCount
])
60 , nMaxAccess( nMaxAccessP
)
62 D aValue
= pDataArray
[0];
63 for (size_t j
=0; j
<nDataCount
; ++j
)
65 if (!(aValue
== pDataArray
[j
]))
67 pData
[nCount
].aValue
= aValue
;
68 pData
[nCount
].nEnd
= j
-1;
70 aValue
= pDataArray
[j
];
73 pData
[nCount
].aValue
= aValue
;
74 pData
[nCount
].nEnd
= nMaxAccess
;
80 template< typename A
, typename D
>
81 ScCompressedArray
<A
,D
>::~ScCompressedArray()
87 template< typename A
, typename D
>
88 void ScCompressedArray
<A
,D
>::Resize( size_t nNewLimit
)
90 if ((nCount
<= nNewLimit
&& nNewLimit
< nLimit
) || nLimit
< nNewLimit
)
93 DataEntry
* pNewData
= new DataEntry
[nLimit
];
94 memcpy( pNewData
, pData
, nCount
*sizeof(DataEntry
));
101 template< typename A
, typename D
>
102 size_t ScCompressedArray
<A
,D
>::Search( A nAccess
) const
108 long nHi
= static_cast<long>(nCount
) - 1;
112 bool bFound
= (nCount
== 1);
113 while (!bFound
&& nLo
<= nHi
)
117 nStart
= (long) pData
[i
- 1].nEnd
;
120 nEnd
= (long) pData
[i
].nEnd
;
121 if (nEnd
< (long) nAccess
)
124 if (nStart
>= (long) nAccess
)
129 return (bFound
? static_cast<size_t>(i
) : (nAccess
< 0 ? 0 : nCount
-1));
133 template< typename A
, typename D
>
134 void ScCompressedArray
<A
,D
>::SetValue( A nStart
, A nEnd
, const D
& rValue
)
136 if (0 <= nStart
&& nStart
<= nMaxAccess
&& 0 <= nEnd
&& nEnd
<= nMaxAccess
139 if ((nStart
== 0) && (nEnd
== nMaxAccess
))
143 // Create a temporary copy in case we got a reference passed that
144 // points to a part of the array to be reallocated.
146 size_t nNeeded
= nCount
+ 2;
147 if (nLimit
< nNeeded
)
150 if (nLimit
< nNeeded
)
152 DataEntry
* pNewData
= new DataEntry
[nLimit
];
153 memcpy( pNewData
, pData
, nCount
*sizeof(DataEntry
));
158 size_t ni
; // number of leading entries
159 size_t nInsert
; // insert position (nMaxAccess+1 := no insert)
160 bool bCombined
= false;
165 ni
= Search( nStart
);
167 nInsert
= nMaxAccess
+1;
168 if (!(pData
[ni
].aValue
== aNewVal
))
170 if (ni
== 0 || (pData
[ni
-1].nEnd
< nStart
- 1))
171 { // may be a split or a simple insert or just a shrink,
172 // row adjustment is done further down
173 if (pData
[ni
].nEnd
> nEnd
)
178 else if (ni
> 0 && pData
[ni
-1].nEnd
== nStart
- 1)
181 if (ni
> 0 && pData
[ni
-1].aValue
== aNewVal
)
183 pData
[ni
-1].nEnd
= nEnd
;
184 nInsert
= nMaxAccess
+1;
194 size_t nj
= ni
; // stop position of range to replace
195 while (nj
< nCount
&& pData
[nj
].nEnd
<= nEnd
)
199 if (nj
< nCount
&& pData
[nj
].aValue
== aNewVal
)
203 if (pData
[ni
-1].aValue
== aNewVal
)
204 { // adjacent entries
205 pData
[ni
-1].nEnd
= pData
[nj
].nEnd
;
208 else if (ni
== nInsert
)
209 pData
[ni
-1].nEnd
= nStart
- 1; // shrink
211 nInsert
= nMaxAccess
+1;
214 else if (ni
> 0 && ni
== nInsert
)
215 pData
[ni
-1].nEnd
= nStart
- 1; // shrink
218 { // remove middle entries
220 { // replace one entry
221 pData
[ni
].nEnd
= nEnd
;
222 pData
[ni
].aValue
= aNewVal
;
224 nInsert
= nMaxAccess
+1;
228 memmove( pData
+ ni
, pData
+ nj
,
229 (nCount
- nj
) * sizeof(DataEntry
));
234 if (nInsert
< static_cast<size_t>(nMaxAccess
+1))
235 { // insert or append new entry
236 if (nInsert
<= nCount
)
239 memmove( pData
+ nInsert
+ 1, pData
+ nInsert
,
240 (nCount
- nInsert
) * sizeof(DataEntry
));
243 memmove( pData
+ nInsert
+ 2, pData
+ nInsert
,
244 (nCount
- nInsert
) * sizeof(DataEntry
));
245 pData
[nInsert
+1] = pData
[nInsert
-1];
250 pData
[nInsert
-1].nEnd
= nStart
- 1;
251 pData
[nInsert
].nEnd
= nEnd
;
252 pData
[nInsert
].aValue
= aNewVal
;
260 template< typename A
, typename D
>
261 void ScCompressedArray
<A
,D
>::CopyFrom( const ScCompressedArray
<A
,D
>& rArray
, A nStart
,
262 A nEnd
, long nSourceDy
)
266 for (A j
=nStart
; j
<=nEnd
; ++j
)
268 const D
& rValue
= (j
==nStart
?
269 rArray
.GetValue( j
+nSourceDy
, nIndex
, nRegionEnd
) :
270 rArray
.GetNextValue( nIndex
, nRegionEnd
));
271 nRegionEnd
-= nSourceDy
;
272 if (nRegionEnd
> nEnd
)
274 SetValue( j
, nRegionEnd
, rValue
);
280 template< typename A
, typename D
>
281 const D
& ScCompressedArray
<A
,D
>::Insert( A nStart
, size_t nAccessCount
)
283 size_t nIndex
= Search( nStart
);
284 // No real insertion is needed, simply extend the one entry and adapt all
285 // following. In case nStart points to the start row of an entry, extend
286 // the previous entry (inserting before nStart).
287 if (nIndex
> 0 && pData
[nIndex
-1].nEnd
+1 == nStart
)
289 const D
& rValue
= pData
[nIndex
].aValue
; // the value "copied"
292 pData
[nIndex
].nEnd
+= nAccessCount
;
293 if (pData
[nIndex
].nEnd
>= nMaxAccess
)
295 pData
[nIndex
].nEnd
= nMaxAccess
;
296 nCount
= nIndex
+ 1; // discard trailing entries
298 } while (++nIndex
< nCount
);
303 template< typename A
, typename D
>
304 void ScCompressedArray
<A
,D
>::Remove( A nStart
, size_t nAccessCount
)
306 A nEnd
= nStart
+ nAccessCount
- 1;
307 size_t nIndex
= Search( nStart
);
308 // equalize/combine/remove all entries in between
309 if (nEnd
> pData
[nIndex
].nEnd
)
310 SetValue( nStart
, nEnd
, pData
[nIndex
].aValue
);
311 // remove an exactly matching entry by shifting up all following by one
312 if ((nStart
== 0 || (nIndex
> 0 && nStart
== pData
[nIndex
-1].nEnd
+1)) &&
313 pData
[nIndex
].nEnd
== nEnd
&& nIndex
< nCount
-1)
315 // In case removing an entry results in two adjacent entries with
316 // identical data, combine them into one. This is also necessary to
317 // make the algorithm used in SetValue() work correctly, it relies on
318 // the fact that consecutive values actually differ.
320 if (nIndex
> 0 && pData
[nIndex
-1].aValue
== pData
[nIndex
+1].aValue
)
327 memmove( pData
+ nIndex
, pData
+ nIndex
+ nRemove
, (nCount
- (nIndex
+
328 nRemove
)) * sizeof(DataEntry
));
331 // adjust end rows, nIndex still being valid
334 pData
[nIndex
].nEnd
-= nAccessCount
;
335 } while (++nIndex
< nCount
);
336 pData
[nCount
-1].nEnd
= nMaxAccess
;
340 template< typename A
, typename D
>
341 A ScCompressedArray
<A
,D
>::GetLastUnequalAccess( A nStart
, const D
& rCompare
)
343 A nEnd
= ::std::numeric_limits
<A
>::max();
344 size_t nIndex
= nCount
-1;
347 if (pData
[nIndex
].aValue
!= rCompare
)
349 nEnd
= pData
[nIndex
].nEnd
;
357 if (pData
[nIndex
].nEnd
< nStart
)
368 // === ScSummableCompressedArray =============================================
370 template< typename A
, typename D
>
371 unsigned long ScSummableCompressedArray
<A
,D
>::SumValues( A nStart
, A nEnd
) const
373 size_t nIndex
= Search( nStart
);
374 unsigned long nSum
= SumValuesContinuation( nStart
, nEnd
, nIndex
);
375 if (nEnd
> this->nMaxAccess
)
376 nSum
+= this->pData
[this->nCount
-1].aValue
* (nEnd
- this->nMaxAccess
);
381 template< typename A
, typename D
>
382 unsigned long ScSummableCompressedArray
<A
,D
>::SumValuesContinuation(
383 A nStart
, A nEnd
, size_t& nIndex
) const
385 unsigned long nSum
= 0;
387 while (nIndex
< this->nCount
&& nS
<= nEnd
)
389 A nE
= ::std::min( this->pData
[nIndex
].nEnd
, nEnd
);
390 // FIXME: test for overflow in a single region?
391 unsigned long nNew
= (unsigned long) this->pData
[nIndex
].aValue
* (nE
- nS
+ 1);
394 return ::std::numeric_limits
<unsigned long>::max();
403 template< typename A
, typename D
>
404 unsigned long ScSummableCompressedArray
<A
,D
>::SumScaledValuesContinuation(
405 A nStart
, A nEnd
, size_t& nIndex
, double fScale
) const
407 unsigned long nSum
= 0;
409 while (nIndex
< this->nCount
&& nS
<= nEnd
)
411 A nE
= ::std::min( this->pData
[nIndex
].nEnd
, nEnd
);
412 unsigned long nScaledVal
= (unsigned long) (this->pData
[nIndex
].aValue
* fScale
);
413 // FIXME: test for overflow in a single region?
414 unsigned long nNew
= nScaledVal
* (nE
- nS
+ 1);
417 return ::std::numeric_limits
<unsigned long>::max();
426 // === ScBitMaskCompressedArray ==============================================
428 template< typename A
, typename D
>
429 void ScBitMaskCompressedArray
<A
,D
>::AndValue( A nStart
, A nEnd
,
430 const D
& rValueToAnd
)
435 size_t nIndex
= Search( nStart
);
438 if ((this->pData
[nIndex
].aValue
& rValueToAnd
) != this->pData
[nIndex
].aValue
)
440 A nS
= ::std::max( (nIndex
>0 ? this->pData
[nIndex
-1].nEnd
+1 : 0), nStart
);
441 A nE
= ::std::min( this->pData
[nIndex
].nEnd
, nEnd
);
442 SetValue( nS
, nE
, this->pData
[nIndex
].aValue
& rValueToAnd
);
445 nIndex
= Search( nE
+ 1);
447 else if (this->pData
[nIndex
].nEnd
>= nEnd
)
451 } while (nIndex
< this->nCount
);
455 template< typename A
, typename D
>
456 void ScBitMaskCompressedArray
<A
,D
>::OrValue( A nStart
, A nEnd
,
457 const D
& rValueToOr
)
462 size_t nIndex
= Search( nStart
);
465 if ((this->pData
[nIndex
].aValue
| rValueToOr
) != this->pData
[nIndex
].aValue
)
467 A nS
= ::std::max( (nIndex
>0 ? this->pData
[nIndex
-1].nEnd
+1 : 0), nStart
);
468 A nE
= ::std::min( this->pData
[nIndex
].nEnd
, nEnd
);
469 SetValue( nS
, nE
, this->pData
[nIndex
].aValue
| rValueToOr
);
472 nIndex
= Search( nE
+ 1);
474 else if (this->pData
[nIndex
].nEnd
>= nEnd
)
478 } while (nIndex
< this->nCount
);
482 template< typename A
, typename D
>
483 void ScBitMaskCompressedArray
<A
,D
>::CopyFromAnded(
484 const ScBitMaskCompressedArray
<A
,D
>& rArray
, A nStart
, A nEnd
,
485 const D
& rValueToAnd
, long nSourceDy
)
489 for (A j
=nStart
; j
<=nEnd
; ++j
)
491 const D
& rValue
= (j
==nStart
?
492 rArray
.GetValue( j
+nSourceDy
, nIndex
, nRegionEnd
) :
493 rArray
.GetNextValue( nIndex
, nRegionEnd
));
494 nRegionEnd
-= nSourceDy
;
495 if (nRegionEnd
> nEnd
)
497 SetValue( j
, nRegionEnd
, rValue
& rValueToAnd
);
503 template< typename A
, typename D
>
504 void ScBitMaskCompressedArray
<A
,D
>::CopyFromOred(
505 const ScBitMaskCompressedArray
<A
,D
>& rArray
, A nStart
, A nEnd
,
506 const D
& rValueToOr
, long nSourceDy
)
510 for (A j
=nStart
; j
<=nEnd
; ++j
)
512 const D
& rValue
= (j
==nStart
?
513 rArray
.GetValue( j
+nSourceDy
, nIndex
, nRegionEnd
) :
514 rArray
.GetNextValue( nIndex
, nRegionEnd
));
515 nRegionEnd
-= nSourceDy
;
516 if (nRegionEnd
> nEnd
)
518 SetValue( j
, nRegionEnd
, rValue
| rValueToOr
);
524 template< typename A
, typename D
>
525 A ScBitMaskCompressedArray
<A
,D
>::GetBitStateStart( A nEnd
,
526 const D
& rBitMask
, const D
& rMaskedCompare
) const
528 A nStart
= ::std::numeric_limits
<A
>::max();
529 size_t nIndex
= Search( nEnd
);
530 while ((this->pData
[nIndex
].aValue
& rBitMask
) == rMaskedCompare
)
535 nStart
= this->pData
[nIndex
].nEnd
+ 1;
547 template< typename A
, typename D
>
548 A ScBitMaskCompressedArray
<A
,D
>::GetBitStateEnd( A nStart
,
549 const D
& rBitMask
, const D
& rMaskedCompare
) const
551 A nEnd
= ::std::numeric_limits
<A
>::max();
552 size_t nIndex
= Search( nStart
);
553 while (nIndex
< this->nCount
&& (this->pData
[nIndex
].aValue
& rBitMask
) ==
556 nEnd
= this->pData
[nIndex
].nEnd
;
563 template< typename A
, typename D
>
564 A ScBitMaskCompressedArray
<A
,D
>::GetFirstForCondition( A nStart
, A nEnd
,
565 const D
& rBitMask
, const D
& rMaskedCompare
) const
567 size_t nIndex
= Search( nStart
);
570 if ((this->pData
[nIndex
].aValue
& rBitMask
) == rMaskedCompare
)
572 A nFound
= nIndex
> 0 ? this->pData
[nIndex
-1].nEnd
+ 1 : 0;
573 return ::std::max( nFound
, nStart
);
575 if (this->pData
[nIndex
].nEnd
>= nEnd
)
578 } while (nIndex
< this->nCount
);
579 return ::std::numeric_limits
<A
>::max();
583 template< typename A
, typename D
>
584 A ScBitMaskCompressedArray
<A
,D
>::GetLastForCondition( A nStart
, A nEnd
,
585 const D
& rBitMask
, const D
& rMaskedCompare
) const
587 size_t nIndex
= Search( nEnd
);
590 if ((this->pData
[nIndex
].aValue
& rBitMask
) == rMaskedCompare
)
591 return ::std::min( this->pData
[nIndex
].nEnd
, nEnd
);
596 if (this->pData
[nIndex
].nEnd
< nStart
)
602 return ::std::numeric_limits
<A
>::max();
606 template< typename A
, typename D
>
607 A ScBitMaskCompressedArray
<A
,D
>::CountForCondition( A nStart
, A nEnd
,
608 const D
& rBitMask
, const D
& rMaskedCompare
) const
611 size_t nIndex
= Search( nStart
);
614 if ((this->pData
[nIndex
].aValue
& rBitMask
) == rMaskedCompare
)
616 A nS
= ::std::max( (nIndex
>0 ? this->pData
[nIndex
-1].nEnd
+1 : 0), nStart
);
617 A nE
= ::std::min( this->pData
[nIndex
].nEnd
, nEnd
);
620 if (this->pData
[nIndex
].nEnd
>= nEnd
)
623 } while (nIndex
< this->nCount
);
628 template< typename A
, typename D
>
629 size_t ScBitMaskCompressedArray
<A
,D
>::FillArrayForCondition( A nStart
, A nEnd
,
630 const D
& rBitMask
, const D
& rMaskedCompare
,
631 A
* pArray
, size_t nArraySize
) const
634 size_t nIndex
= Search( nStart
);
635 while (nIndex
< this->nCount
&& nUsed
< nArraySize
)
637 if ((this->pData
[nIndex
].aValue
& rBitMask
) == rMaskedCompare
)
639 A nS
= ::std::max( (nIndex
>0 ? this->pData
[nIndex
-1].nEnd
+1 : 0), nStart
);
640 A nE
= ::std::min( this->pData
[nIndex
].nEnd
, nEnd
);
641 while (nS
<= nE
&& nUsed
< nArraySize
)
642 pArray
[nUsed
++] = nS
++;
644 if (this->pData
[nIndex
].nEnd
>= nEnd
)
652 template< typename A
, typename D
>
653 bool ScBitMaskCompressedArray
<A
,D
>::HasCondition( A nStart
, A nEnd
,
654 const D
& rBitMask
, const D
& rMaskedCompare
) const
656 size_t nIndex
= Search( nStart
);
659 if ((this->pData
[nIndex
].aValue
& rBitMask
) == rMaskedCompare
)
661 if (this->pData
[nIndex
].nEnd
>= nEnd
)
664 } while (nIndex
< this->nCount
);
669 template< typename A
, typename D
>
670 A ScBitMaskCompressedArray
<A
,D
>::CountForAnyBitCondition( A nStart
, A nEnd
,
671 const D
& rBitMask
) const
674 size_t nIndex
= Search( nStart
);
677 if ((this->pData
[nIndex
].aValue
& rBitMask
) != 0)
679 A nS
= ::std::max( (nIndex
>0 ? this->pData
[nIndex
-1].nEnd
+1 : 0), nStart
);
680 A nE
= ::std::min( this->pData
[nIndex
].nEnd
, nEnd
);
683 if (this->pData
[nIndex
].nEnd
>= nEnd
)
686 } while (nIndex
< this->nCount
);
691 template< typename A
, typename D
>
692 A ScBitMaskCompressedArray
<A
,D
>::GetLastAnyBitAccess( A nStart
,
693 const D
& rBitMask
) const
695 A nEnd
= ::std::numeric_limits
<A
>::max();
696 size_t nIndex
= this->nCount
-1;
699 if ((this->pData
[nIndex
].aValue
& rBitMask
) != 0)
701 nEnd
= this->pData
[nIndex
].nEnd
;
709 if (this->pData
[nIndex
].nEnd
< nStart
)
720 template< typename A
, typename D
>
721 template< typename S
>
722 unsigned long ScBitMaskCompressedArray
<A
,D
>::SumCoupledArrayForCondition(
723 A nStart
, A nEnd
, const D
& rBitMask
, const D
& rMaskedCompare
,
724 const ScSummableCompressedArray
<A
,S
>& rArray
) const
726 unsigned long nSum
= 0;
728 size_t nIndex1
= Search( nStart
);
729 size_t nIndex2
= rArray
.Search( nStart
);
732 if ((this->pData
[nIndex1
].aValue
& rBitMask
) == rMaskedCompare
)
734 while (nIndex2
< rArray
.GetEntryCount() &&
735 rArray
.GetDataEntry(nIndex2
).nEnd
< nS
)
737 unsigned long nNew
= rArray
.SumValuesContinuation( nS
,
738 ::std::min( this->pData
[nIndex1
].nEnd
, nEnd
), nIndex2
);
741 return ::std::numeric_limits
<unsigned long>::max();
743 nS
= this->pData
[nIndex1
].nEnd
+ 1;
745 } while (nIndex1
< this->nCount
&& nS
<= nEnd
);
746 if (nEnd
> this->nMaxAccess
&&
747 (this->pData
[this->GetEntryCount()-1].aValue
& rBitMask
) == rMaskedCompare
)
748 nSum
+= rArray
.GetDataEntry(rArray
.GetEntryCount()-1).aValue
* (nEnd
-
754 template< typename A
, typename D
>
755 template< typename S
>
756 unsigned long ScBitMaskCompressedArray
<A
,D
>::SumScaledCoupledArrayForCondition(
757 A nStart
, A nEnd
, const D
& rBitMask
, const D
& rMaskedCompare
,
758 const ScSummableCompressedArray
<A
,S
>& rArray
, double fScale
) const
760 unsigned long nSum
= 0;
762 size_t nIndex1
= Search( nStart
);
763 size_t nIndex2
= rArray
.Search( nStart
);
766 if ((this->pData
[nIndex1
].aValue
& rBitMask
) == rMaskedCompare
)
768 while (nIndex2
< rArray
.GetEntryCount() &&
769 rArray
.GetDataEntry(nIndex2
).nEnd
< nS
)
771 unsigned long nNew
= rArray
.SumScaledValuesContinuation( nS
,
772 ::std::min( this->pData
[nIndex1
].nEnd
, nEnd
), nIndex2
, fScale
);
775 return ::std::numeric_limits
<unsigned long>::max();
777 nS
= this->pData
[nIndex1
].nEnd
+ 1;
779 } while (nIndex1
< this->nCount
&& nS
<= nEnd
);
780 if (nEnd
> this->nMaxAccess
&&
781 (this->pData
[this->GetEntryCount()-1].aValue
& rBitMask
) == rMaskedCompare
)
782 nSum
+= (unsigned long)
783 (rArray
.GetDataEntry(rArray
.GetEntryCount()-1).aValue
* fScale
) *
784 (nEnd
- this->nMaxAccess
);
789 // === ScCompressedArrayIterator =============================================
791 template< typename A
, typename D
>
792 template< typename X
>
793 void ScCompressedArrayIterator
<A
,D
>::Follow(
794 const ScCompressedArrayIterator
<A
,X
>& rIter
)
796 nCurrent
= rIter
.GetPos();
797 if (GetRangeStart() <= nCurrent
&& nCurrent
<= GetRangeEnd())
799 else if (nCurrent
> GetRangeEnd())
801 A nPos
= nCurrent
; // nCurrent gets changed in NextRange()
806 } while (bAdv
&& GetRangeEnd() < nPos
);
810 nIndex
= rArray
.Search( nCurrent
);
814 // === ScCoupledCompressedArrayIterator ======================================
816 template< typename A
, typename D
, typename S
>
817 ScCoupledCompressedArrayIterator
<A
,D
,S
>::ScCoupledCompressedArrayIterator(
818 const ScBitMaskCompressedArray
<A
,D
> & rArray1
, A nStart
, A nEnd
,
819 const D
& rBitMaskP
, const D
& rMaskedCompareP
,
820 const ScCompressedArray
<A
,S
> & rArray2
)
821 : aIter1( rArray1
, nStart
, nEnd
)
822 , aIter2( rArray2
, nStart
, nEnd
)
823 , rBitMask( rBitMaskP
)
824 , rMaskedCompare( rMaskedCompareP
)
830 template< typename A
, typename D
, typename S
>
831 void ScCoupledCompressedArrayIterator
<A
,D
,S
>::InitLimits()
835 while (bFound
&& ((*aIter1
& rBitMask
) != rMaskedCompare
))
837 bFound
= aIter1
.NextRange();
840 if (bMoved
&& bFound
)
841 aIter2
.Follow( aIter1
);
845 template< typename A
, typename D
, typename S
>
846 void ScCoupledCompressedArrayIterator
<A
,D
,S
>::NewLimits( A nStart
, A nEnd
)
848 aIter1
.NewLimits( nStart
, nEnd
);
849 aIter2
.NewLimits( nStart
, nEnd
);
854 template< typename A
, typename D
, typename S
>
855 bool ScCoupledCompressedArrayIterator
<A
,D
,S
>::NextRange()
858 if (aIter1
.GetRangeEnd() <= aIter2
.GetRangeEnd())
860 // Advance bit mask array until condition is met, coupled array
864 bAdv
= aIter1
.NextRange();
865 } while (bAdv
&& ((*aIter1
& rBitMask
) != rMaskedCompare
));
867 aIter2
.Follow( aIter1
);
871 // Make coupled array catch up with bit mask array.
874 bAdv
= aIter2
.NextRange();
875 } while (bAdv
&& aIter2
.GetRangeEnd() < aIter1
.GetRangeStart());
877 aIter1
.Follow( aIter2
); // synchronize aIter1.nCurrent
879 return operator bool();
883 template< typename A
, typename D
, typename S
>
884 void ScCoupledCompressedArrayIterator
<A
,D
,S
>::Resync( A nPos
)
886 aIter1
.Resync( nPos
);
887 aIter2
.Resync( nPos
);
892 // === Force instantiation of specializations ================================
894 template class ScCompressedArray
< SCROW
, USHORT
>; // heights, base class
895 template class ScSummableCompressedArray
< SCROW
, USHORT
>; // heights
896 template class ScCompressedArray
< SCROW
, BYTE
>; // flags, base class
897 template class ScBitMaskCompressedArray
< SCROW
, BYTE
>; // flags
898 template unsigned long ScBitMaskCompressedArray
< SCROW
,
899 BYTE
>::SumCoupledArrayForCondition( SCROW
, SCROW
, const BYTE
&, const BYTE
&,
900 const ScSummableCompressedArray
< SCROW
, USHORT
>&) const;
901 template unsigned long ScBitMaskCompressedArray
< SCROW
,
902 BYTE
>::SumScaledCoupledArrayForCondition( SCROW
, SCROW
, const BYTE
&,
903 const BYTE
&, const ScSummableCompressedArray
< SCROW
, USHORT
>&,
905 template void ScCompressedArrayIterator
< SCROW
, USHORT
>::Follow(
906 const ScCompressedArrayIterator
< SCROW
, BYTE
>&);
907 template class ScCoupledCompressedArrayIterator
< SCROW
, BYTE
, USHORT
>;
909 // === EOF ===================================================================