1 /* $Id: SeqTable_sparse_index.cpp 616043 2020-09-09 15:14:11Z ucko $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Eugene Vasilchenko
27 *
28 * File Description:
29 * Support for SeqTable-sparse-index ASN.1 type
30 * API to work with different representations of sparse index
31 *
32 * Remark:
33 * This code was originally generated by application DATATOOL
34 * using the following specifications:
35 * 'seqtable.asn'.
36 */
37
38 // standard includes
39 #include <ncbi_pch.hpp>
40
41 // generated includes
42 #include <objects/seqtable/SeqTable_sparse_index.hpp>
43
44 #include <objects/seqtable/seq_table_exception.hpp>
45 #include <util/bitset/bmfunc.h>
46 #include <util/bitset/bmserial.h>
47
48 #include <objects/seqtable/impl/delta_cache.hpp>
49
50 // generated classes
51
52 BEGIN_NCBI_SCOPE
53
54 BEGIN_objects_SCOPE // namespace ncbi::objects::
55
56 // destructor
~CSeqTable_sparse_index(void)57 CSeqTable_sparse_index::~CSeqTable_sparse_index(void)
58 {
59 }
60
61
62 #ifdef NCBI_COMPILER_GCC
63 const size_t CSeqTable_sparse_index::kInvalidRow;
64 const size_t CSeqTable_sparse_index::kSkipped;
65 #endif
66
67 DEFINE_STATIC_MUTEX(sx_PrepareMutex_sparse_index);
68
69
sx_CalcByteBitCount(Uint4 word)70 static inline size_t sx_CalcByteBitCount(Uint4 word)
71 {
72 return bm::word_bitcount(word);
73 }
74
75
sx_CalcByteBitCount(Uint1 byte)76 static inline size_t sx_CalcByteBitCount(Uint1 byte)
77 {
78 return bm::bit_count_table<true>::_count[byte];
79 }
80
81
sx_CalcBlockBitCount(const char * block,size_t size)82 static inline size_t sx_CalcBlockBitCount(const char* block, size_t size)
83 {
84 const bm::word_t* word_block = reinterpret_cast<const bm::word_t*>(block);
85 const bm::word_t* word_block_end = word_block + size/sizeof(bm::word_t);
86 size_t ret = bm::bit_count_min_unroll(word_block, word_block_end);
87
88 const char* tail_ptr = reinterpret_cast<const char*>(word_block_end);
89 const char* block_end = block + size;
90 for ( ; tail_ptr != block_end; ++tail_ptr ) {
91 ret += sx_CalcByteBitCount(Uint1(*tail_ptr));
92 }
93
94 return ret;
95 }
96
97
98 // return number of the first set bit in a byte
99 // bit 0x80 - 0
100 // bit 0x40 - 1
101 // ...
102 // bit 0x01 - 7
103 // if there are no set bits return kInvalidRow
sx_FindFirstNonZeroBit(Uint1 b)104 static inline size_t sx_FindFirstNonZeroBit(Uint1 b)
105 {
106 for ( size_t i = 0; i < 8; ++i, b <<= 1 ) {
107 if ( b&0x80 ) {
108 return i;
109 }
110 }
111 return CSeqTable_sparse_index::kInvalidRow;
112 }
113
114
115 // return number of the next set bit in a byte starting with bit prev_i
116 // bit 0x80 - 0
117 // bit 0x40 - 1
118 // ...
119 // bit 0x01 - 7
120 // if there are no more set bits return kInvalidRow
sx_FindNextNonZeroBit(Uint1 b,size_t prev_i)121 static inline size_t sx_FindNextNonZeroBit(Uint1 b, size_t prev_i)
122 {
123 b <<= prev_i+1;
124 for ( size_t i = prev_i+1; i < 8; ++i, b <<= 1 ) {
125 if ( b&0x80 ) {
126 return i;
127 }
128 }
129 return CSeqTable_sparse_index::kInvalidRow;
130 }
131
132
133 // return number of the first non-zero byte in a range
134 // if there are no non-zero bytes return kInvalidRow
sx_FindFirstNonZeroByte(const char * beg,const char * end)135 static inline size_t sx_FindFirstNonZeroByte(const char* beg,
136 const char* end)
137 {
138 typedef Uint8 TBig; // faster scan using bigger type than char
139 const char* ptr = beg;
140 // align to bigger type
141 for ( ; ptr != end && reinterpret_cast<size_t>(ptr)%sizeof(TBig); ++ptr ) {
142 if ( *ptr ) {
143 return ptr - beg;
144 }
145 }
146 // scan using bigger type
147 for ( ; ptr+sizeof(TBig) <= end; ptr += sizeof(TBig) ) {
148 if ( *reinterpret_cast<const TBig*>(ptr) != 0 ) {
149 break;
150 }
151 }
152 // scan for exact char position
153 for ( ; ptr != end; ++ptr ) {
154 if ( *ptr ) {
155 return ptr - beg;
156 }
157 }
158 return CSeqTable_sparse_index::kInvalidRow;
159 }
160
161
162 // return number of the first non-zero byte in a vector, starting with index
163 // if there are no more non-zero bytes return kInvalidRow
sx_FindFirstNonZeroByte(const vector<char> & bytes,size_t index)164 static inline size_t sx_FindFirstNonZeroByte(const vector<char>& bytes,
165 size_t index)
166 {
167 size_t size = bytes.size();
168 const char* ptr = &bytes[0];
169 size_t offset = sx_FindFirstNonZeroByte(ptr+index, ptr+size);
170 if ( offset == CSeqTable_sparse_index::kInvalidRow ) {
171 return CSeqTable_sparse_index::kInvalidRow;
172 }
173 return index + offset;
174 }
175
176
177 const size_t CSeqTable_sparse_index::SBitsInfo::kBlockSize = 256;
178
179
x_GetBitSetCache(size_t byte_count) const180 size_t CSeqTable_sparse_index::x_GetBitSetCache(size_t byte_count) const
181 {
182 const TBit_set& bytes = GetBit_set();
183 size_t size = bytes.size();
184 CMutexGuard guard(sx_PrepareMutex_sparse_index);
185 if ( !m_Cache ) {
186 m_Cache.Reset(new SBitsInfo);
187 }
188 SBitsInfo& info= dynamic_cast<SBitsInfo&>(*m_Cache);
189 static const size_t kBlockSize = SBitsInfo::kBlockSize;
190 size_t block_index = byte_count / kBlockSize;
191 size_t block_offset = byte_count % kBlockSize;
192 for ( ; block_index > info.m_BlocksFilled; ) {
193 if ( !info.m_Blocks ) {
194 size_t block_count = size / kBlockSize;
195 info.m_Blocks.reset(new size_t[block_count]);
196 }
197 size_t next_index = info.m_BlocksFilled;
198 size_t count = sx_CalcBlockBitCount(&bytes[next_index*kBlockSize],
199 kBlockSize);
200 if ( next_index > 0 ) {
201 count += info.m_Blocks[next_index-1];
202 }
203 info.m_Blocks[next_index] = count;
204 info.m_BlocksFilled = next_index+1;
205 }
206 size_t ret = block_index? info.m_Blocks[block_index-1]: 0;
207 if ( block_offset ) {
208 if ( block_index != info.m_CacheBlockIndex ) {
209 if ( !info.m_CacheBlockInfo ) {
210 info.m_CacheBlockInfo.reset(new size_t[kBlockSize]);
211 }
212 size_t count = 0;
213 size_t block_pos = block_index*kBlockSize;
214 size_t block_size = min(kBlockSize, size-block_pos);
215 const char* block = &bytes[block_pos];
216 for ( size_t i = 0; i < block_size; ++i ) {
217 count += sx_CalcByteBitCount(Uint1(block[i]));
218 info.m_CacheBlockInfo[i] = count;
219 }
220 info.m_CacheBlockIndex = block_index;
221 }
222 ret += info.m_CacheBlockInfo[block_offset-1];
223 }
224 return ret;
225 }
226
227
228 /////////////////////////////////////////////////////////////////////////////
229 // CIndexDeltaSumCache
230 /////////////////////////////////////////////////////////////////////////////
231
232 //#define USE_DELTA_CACHE
233 const size_t CIndexDeltaSumCache::kBlockSize = 128;
234 const size_t CIndexDeltaSumCache::kInvalidRow = CSeqTable_sparse_index::kInvalidRow;
235 const size_t CIndexDeltaSumCache::kBlockTooLow = CIndexDeltaSumCache::kInvalidRow-1;
236
237
CIndexDeltaSumCache(size_t size)238 CIndexDeltaSumCache::CIndexDeltaSumCache(size_t size)
239 : m_Blocks(new TValue[(size+kBlockSize-1)/kBlockSize]),
240 m_BlocksFilled(0),
241 #ifdef USE_DELTA_CACHE
242 m_CacheBlockInfo(new TValue[kBlockSize]),
243 #endif
244 m_CacheBlockIndex(size_t(0)-1)
245 {
246 }
247
248
~CIndexDeltaSumCache(void)249 CIndexDeltaSumCache::~CIndexDeltaSumCache(void)
250 {
251 }
252
253
254 inline
255 CIndexDeltaSumCache::TValue
x_GetDeltaSum2(const TDeltas & deltas,size_t block_index,size_t block_offset)256 CIndexDeltaSumCache::x_GetDeltaSum2(const TDeltas& deltas,
257 size_t block_index,
258 size_t block_offset)
259 {
260 #ifdef USE_DELTA_CACHE
261 _ASSERT(block_index <= m_BlocksFilled);
262 if ( block_index != m_CacheBlockIndex ) {
263 size_t size = deltas.size();
264 size_t block_pos = block_index*kBlockSize;
265 _ASSERT(block_pos < size);
266 size_t block_size = min(kBlockSize, size-block_pos);
267 _ASSERT(block_offset < block_size);
268 TValue sum = block_index == 0? 0: m_Blocks[block_index-1];
269 const TDeltas::value_type* block = &deltas[block_pos];
270 for ( size_t i = 0; i < block_size; ++i ) {
271 sum += block[i];
272 m_CacheBlockInfo[i] = sum;
273 }
274 m_CacheBlockIndex = block_index;
275 if ( block_index == m_BlocksFilled ) {
276 m_Blocks[block_index] = sum;
277 m_BlocksFilled = block_index+1;
278 }
279 }
280 return m_CacheBlockInfo[block_offset];
281 #else
282 size_t size = deltas.size();
283 size_t block_pos = block_index*kBlockSize;
284 _ASSERT(block_pos < size);
285 size_t block_size = min(kBlockSize, size-block_pos);
286 _ASSERT(block_offset < block_size);
287 TValue sum = block_index == 0? 0: m_Blocks[block_index-1];
288 const TDeltas::value_type* block = &deltas[block_pos];
289 for ( size_t i = 0; i <= block_offset; ++i ) {
290 sum += block[i];
291 }
292 if ( block_index == m_BlocksFilled ) {
293 TValue sum2 = sum;
294 for ( size_t i = block_offset+1; i < block_size; ++i ) {
295 sum2 += block[i];
296 }
297 m_Blocks[block_index] = sum2;
298 m_BlocksFilled = block_index+1;
299 }
300 return sum;
301 #endif
302 }
303
304
305 inline
x_FindDeltaSum2(const TDeltas & deltas,size_t block_index,TValue find_sum)306 size_t CIndexDeltaSumCache::x_FindDeltaSum2(const TDeltas& deltas,
307 size_t block_index,
308 TValue find_sum)
309 {
310 _ASSERT(block_index<=m_BlocksFilled);
311 _ASSERT(block_index==m_BlocksFilled || find_sum<=m_Blocks[block_index]);
312 _ASSERT(block_index==0 || find_sum>m_Blocks[block_index-1]);
313 size_t size = deltas.size();
314 size_t block_pos = block_index*kBlockSize;
315 _ASSERT(block_pos < size);
316 size_t block_size = min(kBlockSize, size-block_pos);
317 #ifdef USE_DELTA_CACHE
318 if ( block_index < m_BlocksFilled && find_sum > m_Blocks[block_index] ) {
319 return kBlockTooLow;
320 }
321 x_GetDeltaSum2(deltas, block_index, 0);
322 _ASSERT(block_index < m_BlocksFilled);
323 if ( find_sum > m_Blocks[block_index] ) {
324 return kBlockTooLow;
325 }
326 _ASSERT(find_sum <= m_Blocks[block_index]);
327 size_t value_index = lower_bound(&m_CacheBlockInfo[0],
328 &m_CacheBlockInfo[block_size],
329 find_sum) - &m_CacheBlockInfo[0];
330 _ASSERT(value_index < block_size);
331 _ASSERT(find_sum <= m_CacheBlockInfo[value_index]);
332 _ASSERT(value_index==0 || find_sum > m_CacheBlockInfo[value_index-1]);
333 if ( find_sum != m_CacheBlockInfo[value_index] ) {
334 return kInvalidRow;
335 }
336 return block_pos + value_index;
337 #else
338 TValue sum = block_index == 0? 0: m_Blocks[block_index-1];
339 const TDeltas::value_type* block = &deltas[block_pos];
340 for ( size_t i = 0; i < block_size; ++i ) {
341 sum += block[i];
342 if ( sum >= find_sum ) {
343 if ( block_index == m_BlocksFilled ) {
344 TValue sum2 = sum;
345 for ( size_t j = i+1; j < block_size; ++j ) {
346 sum2 += block[j];
347 }
348 m_Blocks[block_index] = sum2;
349 m_BlocksFilled = block_index+1;
350 }
351 return sum > find_sum? kInvalidRow: block_pos+i;
352 }
353 }
354 if ( block_index == m_BlocksFilled ) {
355 m_Blocks[block_index] = sum;
356 m_BlocksFilled = block_index+1;
357 }
358 return kBlockTooLow;
359 #endif
360 }
361
362
363 CIndexDeltaSumCache::TValue
GetDeltaSum(const TDeltas & deltas,size_t index)364 CIndexDeltaSumCache::GetDeltaSum(const TDeltas& deltas,
365 size_t index)
366 {
367 _ASSERT(index < deltas.size());
368 size_t block_index = index / kBlockSize;
369 size_t block_offset = index % kBlockSize;
370 while ( block_index >= m_BlocksFilled ) {
371 x_GetDeltaSum2(deltas, m_BlocksFilled, 0);
372 }
373 return x_GetDeltaSum2(deltas, block_index, block_offset);
374 }
375
376
FindDeltaSum(const TDeltas & deltas,TValue find_sum)377 size_t CIndexDeltaSumCache::FindDeltaSum(const TDeltas& deltas,
378 TValue find_sum)
379 {
380 size_t size = deltas.size();
381 size_t block_index;
382 if ( m_BlocksFilled > 0 && find_sum <= m_Blocks[m_BlocksFilled-1] ) {
383 // sum is within already preprocessed block, locate the block
384 block_index = lower_bound(&m_Blocks[0],
385 &m_Blocks[m_BlocksFilled],
386 find_sum) - &m_Blocks[0];
387 size_t row = x_FindDeltaSum2(deltas, block_index, find_sum);
388 _ASSERT(row != kBlockTooLow);
389 return row;
390 }
391 else {
392 // preprocess blocks sequentially until row will be within block range
393 for ( ;; ) {
394 block_index = m_BlocksFilled;
395 if ( block_index*kBlockSize >= size ) {
396 // last block is processed but the required sum is still bigger
397 return kInvalidRow;
398 }
399 size_t row = x_FindDeltaSum2(deltas, block_index, find_sum);
400 if ( row != kBlockTooLow ) {
401 return row;
402 }
403 }
404 }
405 }
406
407 /////////////////////////////////////////////////////////////////////////////
408
409
x_GetDeltaCache(void) const410 CIndexDeltaSumCache& CSeqTable_sparse_index::x_GetDeltaCache(void) const
411 {
412 CIndexDeltaSumCache* info =
413 dynamic_cast<CIndexDeltaSumCache*>(m_Cache.GetNCPointerOrNull());
414 if ( !info ) {
415 m_Cache = info = new CIndexDeltaSumCache(GetIndexes_delta().size());
416 }
417 return *info;
418 }
419
420
421 inline
x_GetDeltaSum(size_t index) const422 size_t CSeqTable_sparse_index::x_GetDeltaSum(size_t index) const
423 {
424 CMutexGuard guard(sx_PrepareMutex_sparse_index);
425 return x_GetDeltaCache().GetDeltaSum(GetIndexes_delta(), index);
426 }
427
428
429 inline
x_FindDeltaSum(size_t sum) const430 size_t CSeqTable_sparse_index::x_FindDeltaSum(size_t sum) const
431 {
432 CMutexGuard guard(sx_PrepareMutex_sparse_index);
433 return x_GetDeltaCache().FindDeltaSum(GetIndexes_delta(), sum);
434 }
435
436
GetSize(void) const437 size_t CSeqTable_sparse_index::GetSize(void) const
438 {
439 switch ( Which() ) {
440 case e_Indexes:
441 {
442 const TIndexes& indexes = GetIndexes();
443 return indexes.empty()? 0: indexes.back()+1;
444 }
445 case e_Indexes_delta:
446 {
447 const TIndexes_delta& deltas = GetIndexes_delta();
448 return deltas.empty()? 0: x_GetDeltaSum(deltas.size()-1)+1;
449 }
450 case e_Bit_set:
451 return GetBit_set().size()*8;
452 case e_Bit_set_bvector:
453 return GetBit_set_bvector().GetSize();
454 default:
455 return 0;
456 }
457 }
458
459
x_GetFirstRowWithValue(void) const460 size_t CSeqTable_sparse_index::x_GetFirstRowWithValue(void) const
461 {
462 switch ( Which() ) {
463 case e_Indexes:
464 {
465 const TIndexes& indexes = GetIndexes();
466 return indexes.empty()? kInvalidRow: indexes.front();
467 }
468 case e_Indexes_delta:
469 {
470 const TIndexes_delta& deltas = GetIndexes_delta();
471 return deltas.empty()? kInvalidRow: deltas.front();
472 }
473 case e_Bit_set:
474 {
475 const TBit_set& bytes = GetBit_set();
476 size_t byte_index = sx_FindFirstNonZeroByte(bytes, 0);
477 if ( byte_index == kInvalidRow ) {
478 return kInvalidRow;
479 }
480 return byte_index*8 + sx_FindFirstNonZeroBit(Uint1(bytes[byte_index]));
481 }
482 case e_Bit_set_bvector:
483 return GetBit_set_bvector().GetBitVector().get_first();
484 default:
485 return kInvalidRow;
486 }
487 }
488
489
x_GetNextRowWithValue(size_t row,size_t value_index) const490 size_t CSeqTable_sparse_index::x_GetNextRowWithValue(size_t row,
491 size_t value_index) const
492 {
493 switch ( Which() ) {
494 case e_Indexes:
495 {
496 const TIndexes& indexes = GetIndexes();
497 return ++value_index >= indexes.size()?
498 kInvalidRow: indexes[value_index];
499 }
500 case e_Indexes_delta:
501 {
502 const TIndexes_delta& deltas = GetIndexes_delta();
503 return ++value_index >= deltas.size()?
504 kInvalidRow: row + deltas[value_index];
505 }
506 case e_Bit_set:
507 {
508 const TBit_set& bytes = GetBit_set();
509 size_t byte_index = row / 8;
510 size_t bit_index = row % 8;
511 bit_index = sx_FindNextNonZeroBit(Uint1(bytes[byte_index]), bit_index);
512 if ( bit_index != kInvalidRow ) {
513 return byte_index*8 + bit_index;
514 }
515 byte_index = sx_FindFirstNonZeroByte(bytes, byte_index + 1);
516 if ( byte_index == kInvalidRow ) {
517 return kInvalidRow;
518 }
519 return byte_index*8 + sx_FindFirstNonZeroBit(Uint1(bytes[byte_index]));
520 }
521 case e_Bit_set_bvector:
522 {
523 row = GetBit_set_bvector().GetBitVector().get_next(row);
524 return row == 0? kInvalidRow: row;
525 }
526 default:
527 return kInvalidRow;
528 };
529 }
530
531
GetIndexAt(size_t row) const532 size_t CSeqTable_sparse_index::GetIndexAt(size_t row) const
533 {
534 switch ( Which() ) {
535 case e_Indexes:
536 {
537 const TIndexes& indexes = GetIndexes();
538 TIndexes::const_iterator iter =
539 lower_bound(indexes.begin(), indexes.end(), row);
540 if ( iter != indexes.end() && *iter == row ) {
541 return iter - indexes.begin();
542 }
543 else {
544 return kSkipped;
545 }
546 }
547 case e_Indexes_delta:
548 return x_FindDeltaSum(row);
549 case e_Bit_set:
550 {
551 const TBit_set& bytes = GetBit_set();
552 size_t byte_index = row/8;
553 if ( byte_index >= bytes.size() ) {
554 return kSkipped;
555 }
556 Uint1 byte = bytes[byte_index];
557 size_t bit_index = row%8; // most significant bit has index 0
558 if ( !((byte<<bit_index)&0x80) ) {
559 return kSkipped;
560 }
561 size_t count = sx_CalcByteBitCount(Uint1(byte>>(8-bit_index)));
562 if ( byte_index ) {
563 count += x_GetBitSetCache(byte_index);
564 }
565 return count;
566 }
567 case e_Bit_set_bvector:
568 {
569 const bm::bvector<>& bv = GetBit_set_bvector().GetBitVector();
570 if ( row >= bv.size() || !bv.get_bit(row) ) {
571 return kSkipped;
572 }
573 return row == 0? 0: bv.count_range(0, row-1);
574 }
575 default:
576 return kSkipped;
577 }
578 }
579
580
HasValueAt(size_t row) const581 bool CSeqTable_sparse_index::HasValueAt(size_t row) const
582 {
583 switch ( Which() ) {
584 case e_Indexes:
585 {
586 const TIndexes& indexes = GetIndexes();
587 TIndexes::const_iterator iter =
588 lower_bound(indexes.begin(), indexes.end(), row);
589 return iter != indexes.end() && *iter == row;
590 }
591 case e_Indexes_delta:
592 return x_FindDeltaSum(row) != kInvalidRow;
593 case e_Bit_set:
594 {
595 const TBit_set& bits = GetBit_set();
596 size_t i = row/8, j = row%8;
597 return i < bits.size() && ((bits[i]<<j)&0x80) != 0;
598 }
599 case e_Bit_set_bvector:
600 {
601 const bm::bvector<>& bv = GetBit_set_bvector().GetBitVector();
602 return row < bv.size() && bv.get_bit(row);
603 }
604 default:
605 return false;
606 }
607 }
608
609
ChangeTo(E_Choice type)610 void CSeqTable_sparse_index::ChangeTo(E_Choice type)
611 {
612 if ( Which() == type ) {
613 return;
614 }
615 switch ( type ) {
616 case e_Indexes:
617 ChangeToIndexes();
618 break;
619 case e_Indexes_delta:
620 ChangeToIndexes_delta();
621 break;
622 case e_Bit_set:
623 ChangeToBit_set();
624 break;
625 case e_Bit_set_bvector:
626 ChangeToBit_set_bvector();
627 break;
628 default:
629 NCBI_THROW(CSeqTableException, eIncompatibleValueType,
630 "CSeqTable_sparse_index::ChangeTo(): "
631 "requested sparse index type is invalid");
632 }
633 }
634
635
ChangeToIndexes(void)636 void CSeqTable_sparse_index::ChangeToIndexes(void)
637 {
638 if ( IsIndexes() ) {
639 return;
640 }
641 TIndexes indexes;
642 if ( IsIndexes_delta() ) {
643 // convert delta to running sum
644 indexes.swap(SetIndexes_delta());
645 size_t row = 0;
646 NON_CONST_ITERATE ( TIndexes, it, indexes ) {
647 row += *it;
648 *it = row;
649 }
650 }
651 else {
652 for ( const_iterator it = begin(); it; ++it ) {
653 indexes.push_back(it.GetRow());
654 }
655 }
656 SetIndexes().swap(indexes);
657 }
658
659
ChangeToIndexes_delta(void)660 void CSeqTable_sparse_index::ChangeToIndexes_delta(void)
661 {
662 if ( IsIndexes_delta() ) {
663 return;
664 }
665 TIndexes_delta indexes;
666 if ( IsIndexes() ) {
667 // convert to delta
668 indexes.swap(SetIndexes());
669 size_t prev_row = 0;
670 NON_CONST_ITERATE ( TIndexes_delta, it, indexes ) {
671 size_t row = *it;
672 *it = row - prev_row;
673 prev_row = row;
674 }
675 }
676 else {
677 size_t prev_row = 0;
678 for ( const_iterator it = begin(); it; ++it ) {
679 size_t row = it.GetRow();
680 indexes.push_back(row-prev_row);
681 prev_row = row;
682 }
683 }
684 SetIndexes_delta().swap(indexes);
685 }
686
687
688
ChangeToBit_set(void)689 void CSeqTable_sparse_index::ChangeToBit_set(void)
690 {
691 if ( IsBit_set() ) {
692 return;
693 }
694 TBit_set bytes;
695 size_t size = GetSize();
696 if ( size != kInvalidRow ) {
697 bytes.reserve((GetSize()+7)/8);
698 }
699 size_t last_byte_index = 0;
700 Uint1 last_byte = 0;
701 for ( const_iterator it = begin(); it; ++it ) {
702 size_t row = it.GetRow();
703 size_t byte_index = row / 8;
704 if ( byte_index != last_byte_index ) {
705 if ( bytes.capacity() < byte_index+1 ) {
706 bytes.reserve(max(bytes.capacity(), byte_index+1)*2);
707 }
708 bytes.resize(last_byte_index);
709 bytes.push_back(last_byte);
710 last_byte_index = byte_index;
711 last_byte = 0;
712 }
713 size_t bit_index = row % 8;
714 last_byte |= 0x80 >> bit_index;
715 }
716 if ( last_byte ) {
717 bytes.reserve(last_byte_index+1);
718 bytes.resize(last_byte_index);
719 bytes.push_back(last_byte);
720 }
721 SetBit_set().swap(bytes);
722 }
723
724
725
ChangeToBit_set_bvector(void)726 void CSeqTable_sparse_index::ChangeToBit_set_bvector(void)
727 {
728 if ( IsBit_set_bvector() ) {
729 return;
730 }
731 AutoPtr<bm::bvector<> > bv(new bm::bvector<>(GetSize()));
732 for ( const_iterator it = begin(); it; ++it ) {
733 size_t row = it.GetRow();
734 bv->set_bit(row);
735 }
736 bv->optimize();
737 SetBit_set_bvector().SetBitVector(bv.release());
738 }
739
740
741 END_objects_SCOPE // namespace ncbi::objects::
742
743 END_NCBI_SCOPE
744