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