source: trunk/lib/bitblock_iterator.hpp @ 3207

Last change on this file since 3207 was 3207, checked in by cameron, 6 years ago

BitStreamScanner? template class for multiblock bitstream segments.

File size: 20.1 KB
Line 
1#ifndef BITBLOCK_ITERATOR_H_
2#define BITBLOCK_ITERATOR_H_
3
4#include <iterator>
5#include <iostream>
6#include "bitblock.hpp"
7
8/*=============================================================================
9  bitblock_iterator.hpp
10
11  Created on: Sept 2011, revised May 2013
12  Authors: Ken Herdy and Rob Cameron
13
14  Description:
15
16        Scanner classes implement the low level methods to scan through
17        the 'scanwords' of a 'bitblock'. Scanner classes are templated
18        on bitblock type and scanword type.
19
20*/
21
22
23//
24// The following implementation of BitBlockScanner is optimized
25// to eliminate branch mispredictions during scanning.  Only the
26// essential methods are included.   RDC May 2013.
27//
28// Usage:
29//   (1) declare:  BitBlockScanner myscanner;
30//   (2) initialize:  myscanner.init(&mybitblock);
31//   (3) iterate:  while (myscanner.has_next()) { pos = myscanner.scan_to_next();  ...}
32//
33
34//
35// We could use FW=32 bit scan units, but 8 seems to be faster.
36#define FW 8
37#define _FW _8
38template <class bitblock_t, class scanblock_t>
39class BitBlockScanner {
40public:
41        BitBlockScanner() {}
42
43        IDISA_ALWAYS_INLINE int init(const BitBlock *s) {
44                remaining._bitblock = *s;
45                mask = hsimd<FW>::signmask(simd<FW>::sub(simd<1>::constant<0>(), remaining._bitblock));
46        }
47
48        IDISA_ALWAYS_INLINE int has_next() {
49               
50                     return mask != 0;
51        }
52
53        IDISA_ALWAYS_INLINE int scan_to_next() {
54               
55                     int item_pos = scan_forward_zeroes(mask);
56                     uint32_t scan_item = remaining._FW[item_pos];
57                     int bitpos = scan_forward_zeroes(scan_item);
58                     scan_item = scan_item & (scan_item - 1);
59                     remaining._FW[item_pos] = scan_item;
60                     // We could recalculate the mask, but updating it is faster.
61                     // Note that this update code compiles to a SETcc instruction.
62                     mask = mask & (mask - ((scan_item == 0) ? 1 : 0));
63                     int pos = item_pos * FW + bitpos;
64                     return pos;
65        }
66        // It slows things down to store the position.
67        //IDISA_ALWAYS_INLINE int32_t get_pos() { return pos;}
68private:
69        union {bitblock_t _bitblock;
70               uint8_t _8[sizeof(bitblock_t)];
71               uint32_t _32[sizeof(bitblock_t)/sizeof(uint32_t)];} remaining;
72        scanblock_t mask;                       
73};
74#undef _FW
75#undef FW
76
77
78/*
79    A scanner to successively generate the positions marked by 1 bits
80    in a bit stream segment of bitblock_count bit blocks.
81
82    Usage:
83
84    (1) declaration, e.g.
85        BitStreamScanner<BitBlock, uint32_t, u8int_t, 8> s;
86        (There is considerable flexibility for using different
87         scanblock sizes for the main mask, as well as the
88         scan field sizes within each block.)
89
90    (2) initialization/reinitialization
91        s.init();
92
93    (3) load the blocks;
94        for (i = 0; i++; i < n) {mybitblock = ...; s.load_block(mybitblock, i);}
95
96    (4) Iterative scan loop (generates each position exactly once.)
97        while (s.has_next()) { pos = s.scan_to_next(); ...   };
98*/
99
100template <class bitblock_t, class scanblock_t, class scanfield_t, int bitblock_count>
101class BitStreamScanner {
102public:
103        /* Make sure that the number of bits in the mask at least equals
104           the number of scanblocks. */
105        /* Requires flag -std=gnu++0x 
106        static_assert(sizeof(scanblock_t) * 8 >= bitblock_count * sizeof(bitblock_t)/sizeof(scanfield_t),
107                      "Too many bitblocks for a single scanword mask");
108        */
109
110        BitStreamScanner() {}
111
112        IDISA_ALWAYS_INLINE void init() { mask = 0;}
113
114        IDISA_ALWAYS_INLINE void load_block(BitBlock b, int i) {
115                remaining._bitblock[i] = b;
116                BitBlock mask_i = simd<sizeof(scanfield_t)*8>::sub(simd<1>::constant<0>(), b);
117                mask |= hsimd<sizeof(scanfield_t)*8>::signmask(mask_i) << (i * sizeof(bitblock_t)/sizeof(scanfield_t));
118        }
119
120        IDISA_ALWAYS_INLINE bool has_next() {
121               
122                     return mask != 0;
123        }
124
125        IDISA_ALWAYS_INLINE int scan_to_next() {
126               
127                     int item_pos = scan_forward_zeroes(mask);
128                     scanfield_t scan_item = remaining._scanfield[item_pos];
129                     int bitpos = scan_forward_zeroes(scan_item);
130                     scan_item = scan_item & (scan_item - 1);
131                     remaining._scanfield[item_pos] = scan_item;
132                     mask = mask & (mask - ((scan_item == 0) ? 1 : 0));
133                     int pos = item_pos * sizeof(scanfield_t) * 8 + bitpos;
134                     return pos;
135        }
136
137private:
138        union {bitblock_t _bitblock[bitblock_count];
139               scanfield_t _scanfield[bitblock_count * sizeof(bitblock_t)/sizeof(scanfield_t)];} remaining;
140        scanblock_t mask;                       
141};
142
143
144
145/*=============================================================================
146
147   Deprecated:
148
149        BitBlock iterator classes provide Standard Template Library (STL)
150        Input iterator 'like' interface implementations as a programmer
151        convenience and allow iterator classes to be used
152        with STL Algorithms.
153        Forward iterators can only step forward (++) marker-bit by marker-bit.
154        Reverse iterators can only step backwards (--) marker-bit by marker-bit.
155
156        BitStream iterator class provide an STL Input iterator interface to scan
157        through an array of scanwords (stream) in the forward direction.
158
159
160  Classes Descriptions:
161
162        *       BitBlock Scanners
163
164        Scanner - Scanner base class.
165        ForwardScanner - Scans a bitblock of scanwords in the forward direction.
166        ReverseScanner - Scans a bitblock of scanwords in the reverse direction.
167
168        * BitBlock Iterators
169
170  ForwardIterator template class wraps ForwardScanner.
171       
172        - Implements STL Input iterator interface.
173        - Reads elements only once.     
174  - '->' - Not implemented.
175
176  ReverseIterator template class wraps ReverseScanner.
177
178        - An STL 'like' iterator that implements prefix and postfix decrement operators.
179    Under STL, a reverse iterator implementation necessitates the implementation of
180                the STL bidirectional interface and hence scanning in both directions.
181                This functionality is not yet required and hence not implemented.
182        - Reads elements only once.
183  - '->' - Not implemented.
184
185        BitBlockForwardIterator - ForwardIterator derived specialization of ForwardIterator<BitBlock, Scanword>
186
187        BitBlockReverseIterator - ForwardIterator derived specialization of ReverseIterator<BitBlock, Scanword>
188
189        * BitStreamIterators
190
191  BitStreamIterator class wraps ForwardScanner.
192        - Scans an array (stream) of scanwords in contiguous memory.
193        - Implements STL Input iterator interface.
194        - Reads elements only once.     
195  - '->' - Not implemented.
196        - May be more appropriately named ForwardBitStreamIterator.
197
198=============================================================================*/
199//
200// Scanner Classes
201//
202#define has_bit(x) (x != 0)
203#define EOS -1
204
205template <class bitblock_t, class scanblock_t>
206class Scanner {
207
208protected:
209        Scanner(): strm(NULL), pos(EOS), blk(-1), scan_blk(-1) {}
210        Scanner(const bitblock_t * s, uint32_t start_pos, uint32_t start_blk, scanblock_t start_scan_blk): strm(s), pos(start_pos), blk(start_blk), scan_blk(start_scan_blk) {}
211
212        const bitblock_t * strm;
213        int32_t pos;
214        int32_t blk;
215        scanblock_t scan_blk;
216};
217
218template <class bitblock_t, class scanblock_t>
219class ForwardScanner: public Scanner<bitblock_t, scanblock_t> {
220
221public:
222
223        ForwardScanner(){}
224        ForwardScanner(const bitblock_t * s) {
225                init(s);
226        }
227
228        IDISA_ALWAYS_INLINE void init(const bitblock_t * s) {
229                this->strm = s;
230                this->pos = 0;
231                this->blk = 0;
232                this->scan_blk = *(scanblock_t *)s;
233        }
234
235        IDISA_ALWAYS_INLINE int32_t scan_to_next() {
236                while (this->blk < BLOCK_COUNT){
237                        if(has_bit(this->scan_blk)){
238                                this->pos = scan_forward_zeroes(this->scan_blk) + (this->blk * (sizeof(scanblock_t)*8));
239                                this->scan_blk = this->scan_blk & (this->scan_blk-1);  // clear rightmost bit
240
241                                return (this->pos);
242                        }
243
244                        this->blk++;
245                        this->scan_blk = *((scanblock_t *)this->strm + this->blk);
246                };
247
248                this->pos = EOS;
249                return (this->pos);
250        }
251
252        /* Set or reset the iterator to position new_pos. */
253        IDISA_ALWAYS_INLINE void move_to(uint32_t new_pos) {           
254                const scanblock_t one_bit = 1;
255                this->blk = new_pos / (sizeof(scanblock_t)*8);
256                this->pos = new_pos % (sizeof(scanblock_t)*8);
257                this->scan_blk = ((scanblock_t *)this->strm)[this->blk];
258                // clear bit at pos and all positions to the right.
259                scanblock_t marker = one_bit << this->pos;
260                this->scan_blk = this->scan_blk &~((marker-1)|marker); 
261        }
262
263        IDISA_ALWAYS_INLINE bool is_done() const {return (EOS==this->pos);}
264        IDISA_ALWAYS_INLINE void set_strm(const bitblock_t * strm) {this->strm = strm;}
265        IDISA_ALWAYS_INLINE const bitblock_t * get_strm() const {return this->strm;}
266        IDISA_ALWAYS_INLINE int32_t get_pos() const {return this->pos;}
267        IDISA_ALWAYS_INLINE void set_pos(int32_t pos) {(this->pos = pos);}
268        static const int32_t BLOCK_COUNT = sizeof(bitblock_t)/sizeof(scanblock_t);
269
270};
271
272class BitBlockForwardScanner: public ForwardScanner<BitBlock, ScanWord> {
273public:
274        BitBlockForwardScanner(){}
275        BitBlockForwardScanner(BitBlock * s): ForwardScanner<BitBlock, ScanWord>(s){}
276};
277
278
279template <class bitblock_t, class scanblock_t>
280class ReverseScanner: public Scanner<bitblock_t, scanblock_t> {
281
282public:
283        ReverseScanner(){}
284        ReverseScanner(const bitblock_t * s) {
285                init(s);
286        }
287        IDISA_ALWAYS_INLINE void init(const bitblock_t * s) {
288                this->strm = s;
289                this->pos = 0;
290                this->blk = BLOCK_COUNT-1;
291                this->scan_blk = *((scanblock_t *)s + (BLOCK_COUNT-1));
292        }
293
294        IDISA_ALWAYS_INLINE int32_t scan_to_next() {
295                const scanblock_t one_bit = 1;  /* ensure enough bits for shift: one_bit << this->pos */
296                while (this->blk > -1){
297                        if(has_bit(this->scan_blk)){
298                                this->pos = (sizeof(scanblock_t)*8 - scan_backward_zeroes(this->scan_blk) -1) + ( (this->blk) * sizeof(scanblock_t)*8 );
299                                this->scan_blk = this->scan_blk ^ (one_bit << this->pos); // clear leftmost bit
300                                return (this->pos);
301                        }
302
303                        this->blk--;
304                        this->scan_blk = *((scanblock_t *)this->strm + this->blk);
305                };
306
307                this->pos = EOS;
308                return (this->pos);
309        }
310
311        /* Set or reset the iterator to position new_pos. */
312        IDISA_ALWAYS_INLINE void move_to(uint32_t new_pos) {
313                const scanblock_t one_bit = 1;
314                this->blk = (new_pos / (sizeof(scanblock_t)*8));
315                this->pos = new_pos % (sizeof(scanblock_t)*8);
316                this->scan_blk = ((scanblock_t *)this->strm)[this->blk];
317                // clear bit at pos and all positions to the left.
318                scanblock_t marker = one_bit << this->pos;
319                this->scan_blk = this->scan_blk & (marker-1);
320        }
321
322        IDISA_ALWAYS_INLINE bool is_done() const {return (EOS==this->pos);}
323        IDISA_ALWAYS_INLINE void set_strm(const bitblock_t * strm) {this->strm = strm;}
324        IDISA_ALWAYS_INLINE const bitblock_t * get_strm() const {return this->strm;}
325        IDISA_ALWAYS_INLINE int32_t get_pos() const {return this->pos;}
326        IDISA_ALWAYS_INLINE void set_pos(int32_t pos) {(this->pos = pos);}
327        static const uint32_t BLOCK_COUNT = sizeof(bitblock_t)/sizeof(scanblock_t);
328
329};
330
331
332//
333// BitBlock Iterator Classses
334//
335template<class bitblock_t, class scanblock_t>
336class ForwardIterator : public std::iterator<std::input_iterator_tag, int>
337{
338public:
339
340        ForwardIterator(bitblock_t * s): scanner(s)
341        {
342                scanner.scan_to_next();
343        }
344
345        // set scanner to first pos of
346        void init(bitblock_t * s)
347        {
348                scanner.init(s);
349                scanner.scan_to_next();
350        }
351
352        // equal position and stream
353        bool operator==(const ForwardIterator& iter)
354        {
355                return ((scanner.get_strm() == iter.scanner.get_strm()) && 
356                        (scanner.get_pos() == iter.scanner.get_pos()));
357        }
358
359        // not equal position and stream
360        bool operator!=(const ForwardIterator& iter)
361        {
362                return ((scanner.get_strm() != iter.scanner.get_strm()) && 
363                        (scanner.get_pos() != iter.scanner.get_pos()));
364        }
365
366        // Returns absolute position.
367        IDISA_ALWAYS_INLINE int32_t operator*()
368        {
369                return scanner.get_pos();
370        }
371
372        // prefix increment
373        IDISA_ALWAYS_INLINE ForwardIterator& operator++()
374        {
375                scanner.scan_to_next();
376                return(*this);
377        }
378
379        // postfix increment
380        ForwardIterator operator++(int)
381        {
382                ForwardIterator temp(*this);
383                ++(*this);
384                return(temp);
385        }
386
387        IDISA_ALWAYS_INLINE bool isDone() const
388        {
389                return scanner.is_done();
390        }
391
392protected:
393        ForwardIterator() {}
394
395private:
396        ForwardScanner<bitblock_t, scanblock_t> scanner;
397};
398
399class BitBlockForwardIterator: public ForwardIterator<BitBlock, ScanWord> {
400public:
401        BitBlockForwardIterator(){}
402        BitBlockForwardIterator(BitBlock * s): ForwardIterator<BitBlock, ScanWord>(s){}
403};
404
405
406template<class bitblock_t, class scanblock_t>
407class ReverseIterator 
408{
409public:
410        ReverseIterator(BitBlock * s): scanner(s)
411        {
412                scanner.scan_to_next();
413        }
414
415        void init(bitblock_t * s)
416        {
417                scanner.init(s);
418                scanner.scan_to_next();
419        }
420
421        // equal position and stream
422        bool operator==(const ReverseIterator& iter)
423        {
424                return ((scanner.get_strm() == iter.scanner.get_strm()) && (scanner.get_pos() == iter.scanner.get_pos));
425        }
426
427        // not equal position and stream
428        bool operator!=(const ReverseIterator& iter)
429        {
430                return ((scanner.get_strm() != iter.scanner.get_strm()) && (scanner.get_pos() != iter.scanner.get_pos()));
431        }
432
433        // Returns absolute position.
434        IDISA_ALWAYS_INLINE int32_t operator*()
435        {
436                return scanner.get_pos();
437        }
438
439        // prefix decrement
440        IDISA_ALWAYS_INLINE ReverseIterator& operator--()
441        {
442                scanner.scan_to_next();
443                return(*this);
444        }
445
446        // postfix decrement
447        ReverseIterator operator--(int)
448        {
449                ReverseIterator temp(*this);
450                --(*this);
451                return(temp);
452        }
453
454        IDISA_ALWAYS_INLINE bool isDone() const
455        {
456                return scanner.is_done();
457        }
458
459protected:
460        ReverseIterator() {}
461        ReverseScanner<bitblock_t, scanblock_t> scanner;
462};
463
464class BitBlockReverseIterator: public ReverseIterator<BitBlock, ScanWord> 
465{
466public:
467        BitBlockReverseIterator(BitBlock * s): ReverseIterator<BitBlock, ScanWord>(s){}
468private:
469        BitBlockReverseIterator(){}
470};
471
472//
473// BitStream Iterator classes
474//
475class BitStreamIterator: public std::iterator<std::input_iterator_tag, int>
476{
477public:
478        BitStreamIterator():pos(EOS), blk(-1), blk_pos(-1), strm(NULL), scan_blk(-1), scan_blk_cnt(0)
479        {
480                // default constructor defines past-the-end of bit stream semantics, pos == EOS
481        }
482
483        BitStreamIterator(const BitBlock * s, int cnt):pos(0), 
484                                                                                         blk(0),
485                                                                                         blk_pos(0),
486                                                                                         strm((ScanWord *)s),
487                                                                                         scan_blk(*((ScanWord *)s)),
488                                                                                         scan_blk_cnt(cnt)
489        {
490                scan_to_next();
491        }
492
493        virtual ~BitStreamIterator() {};
494
495        // shallow copy, bit stream iterators refer to shared data
496        BitStreamIterator& operator=(const BitStreamIterator& iter)
497        {
498                pos = iter.pos;
499                blk = iter.blk;
500                blk_pos = iter.blk_pos;
501                strm = iter.strm;                       // No copy, both
502                scan_blk =  iter.scan_blk;
503                scan_blk_cnt = iter.scan_blk_cnt;
504                return(*this);
505        }
506
507        // equal position and stream
508        bool operator==(const BitStreamIterator& iter)
509        {
510                return((strm == iter.strm) && (pos == iter.pos));
511        }
512
513        // not equal position and stream
514        bool operator!=(const BitStreamIterator& iter)
515        {
516                return((strm != iter.strm) || (pos != iter.pos));
517        }
518
519        // prefix
520        inline BitStreamIterator& operator++()
521        {
522                scan_to_next();
523                return(*this);
524        }
525
526        // postfix
527        BitStreamIterator operator++(int)
528        {
529                BitStreamIterator temp(*this);
530                ++(*this);
531                return(temp);
532        }
533
534        // Returns absolute position.
535        inline int32_t operator*()
536        {
537                return pos;
538        }
539
540        /*
541        int operator->()
542        {
543                return(&*(BitStreamIterator)*this);
544        }
545        */
546
547        IDISA_ALWAYS_INLINE bool isDone() const
548        {
549                return (EOS == pos);
550        }
551
552        void debug() {
553        std::cout << "pos: " << pos << std::endl;
554        std::cout << "blk: " << blk << std::endl;
555        std::cout << "blk_pos: " << blk_pos << std::endl;
556        }
557
558private:
559        int32_t pos;
560        uint32_t blk;
561        int32_t blk_pos;
562        const ScanWord * strm;
563        ScanWord scan_blk;
564        uint32_t scan_blk_cnt;
565
566        // Helpers
567        inline void scan_to_next() {
568                while (blk<scan_blk_cnt) {
569                        if(scan_blk > 0){
570                                pos = scan_forward_zeroes(scan_blk) + blk_pos;
571                                scan_blk = scan_blk & (scan_blk-1);  // clear rightmost bit
572                                return;
573                        }
574
575                        blk_pos += (sizeof(ScanWord)*8);
576                        blk++;
577                        scan_blk = strm[blk];
578                };
579
580                pos = EOS;
581                return;
582        }
583};
584
585/*=============================================================================
586 
587   Special iterators for content buffers with 16-bit right deletion results.
588   Input: (a) a bitblock with undeleted positions rightmost in each 16-bit field.
589          (b) a bitblock of 16-bit fields with a partial sum of the nondeleted
590              positions in this field and all the ones to the right.
591         
592          The partial sum may be computed given B, a bitblock containg the count
593          of nondeleted positions in each field using PartialSum16(B).
594       
595   
596*/
597
598
599static inline BitBlock PartialSum16(BitBlock BaseCounts16) {
600        BitBlock t = simd<16>::add(BaseCounts16, mvmd<16>::slli<1>(BaseCounts16));
601        BitBlock u = simd<16>::add(t, mvmd<16>::slli<2>(t));
602        return simd<16>::add(u, mvmd<16>::slli<4>(u));
603}
604
605template <class bitblock_t, class scanblock_t>
606class ForwardScannerWithBaseCounts16: public Scanner<bitblock_t, scanblock_t> {
607
608public:
609
610        ForwardScannerWithBaseCounts16(){}
611        ForwardScannerWithBaseCounts16(const bitblock_t * s, bitblock_t partial_sums_16) {
612                init(s, partial_sums_16);
613        }
614
615        IDISA_ALWAYS_INLINE void init(const bitblock_t * s, bitblock_t partial_sums_16) {
616                this->strm = s;
617                this->pos = 0;
618                this->blk = 0;
619                this->scan_blk = *(scanblock_t *)s;
620                /* Shift by one field so that the base is the sum for the prev. fields. */
621                this->base_per_field16._128 = mvmd<16>::slli<1>(partial_sums_16);
622        }
623
624        IDISA_ALWAYS_INLINE int32_t scan_to_next() {
625                while (this->blk < BLOCK_COUNT){
626                        if(has_bit(this->scan_blk)){
627                                int pos = scan_forward_zeroes(this->scan_blk) + (this->blk * (sizeof(scanblock_t)*8));
628                                this->scan_blk = this->scan_blk & (this->scan_blk-1);  // clear rightmost bit
629               
630                                this->pos = this->base_per_field16._16[pos/16] + (pos & 15);
631
632                                return (this->pos);
633                        }
634
635                        this->blk++;
636                        this->scan_blk = *((scanblock_t *)this->strm + this->blk);
637                };
638
639                this->pos = EOS;
640                return (this->pos);
641        }
642
643
644        IDISA_ALWAYS_INLINE bool is_done() {return (EOS==this->pos);}
645        IDISA_ALWAYS_INLINE void set_strm(const bitblock_t * strm) {this->strm = strm;}
646        IDISA_ALWAYS_INLINE const bitblock_t * get_strm() const {return this->strm;}
647        IDISA_ALWAYS_INLINE int32_t get_pos() const {return this->pos;}
648
649        static const int32_t BLOCK_COUNT = sizeof(bitblock_t)/sizeof(scanblock_t);
650        ubitblock base_per_field16;
651};
652
653template <class bitblock_t> static inline bool eq_bitblocks(bitblock_t x, bitblock_t y) {
654  return bitblock::all(simd<16>::eq(x, y));
655}
656
657
658template<class bitblock_t, class scanblock_t>
659class ForwardIteratorWithBaseCounts16 : public std::iterator<std::input_iterator_tag, int>
660{
661public:
662        ForwardIteratorWithBaseCounts16() {}
663
664        ForwardIteratorWithBaseCounts16(bitblock_t * s, bitblock_t partial_sums_16): scanner(s, partial_sums_16)
665        {
666                scanner.scan_to_next();
667        }
668
669        void init(bitblock_t * s, bitblock_t partial_sums_16)
670        {
671                scanner.init(s, partial_sums_16);
672                scanner.scan_to_next();
673        }
674
675        // equal position and stream
676        bool operator==(const ForwardIteratorWithBaseCounts16& iter)
677        {
678                return (scanner.get_strm() == iter.scanner.get_strm()) && 
679                       (scanner.get_pos() == iter.scanner.get_pos) &&
680                       (eq_bitblocks<bitblock_t>(scanner.base_per_field16, iter.scanner.base_per_field16));
681        }
682
683        // not equal position and stream
684        bool operator!=(const ForwardIteratorWithBaseCounts16& iter)
685        {
686                return (scanner.get_strm() != iter.scanner.get_strm()) || 
687                       (scanner.get_pos() != iter.scanner.get_pos) ||
688                       (!eq_bitblocks<bitblock_t>(scanner.base_per_field16, iter.scanner.base_per_field16));
689        }
690
691        // Returns absolute position.
692        IDISA_ALWAYS_INLINE int32_t operator*()
693        {
694                return scanner.get_pos();
695        }
696
697        // prefix increment
698        IDISA_ALWAYS_INLINE ForwardIteratorWithBaseCounts16& operator++()
699        {
700                scanner.scan_to_next();
701                return(*this);
702        }
703
704        // postfix increment
705        ForwardIteratorWithBaseCounts16 operator++(int)
706        {
707                ForwardIteratorWithBaseCounts16 temp(*this);
708                ++(*this);
709                return(temp);
710        }
711
712private:
713        ForwardScannerWithBaseCounts16<bitblock_t, scanblock_t> scanner;
714};
715
716
717class BitBlockForwardIteratorWithBaseCounts16: public ForwardIteratorWithBaseCounts16<BitBlock, ScanWord> {
718public:
719        BitBlockForwardIteratorWithBaseCounts16(){}
720        BitBlockForwardIteratorWithBaseCounts16(BitBlock * s, BitBlock partial_sums_16): ForwardIteratorWithBaseCounts16<BitBlock, ScanWord>(s, partial_sums_16){}
721};
722
723
724#undef has_bit
725
726
727#endif // BITBLOCK_ITERATOR_H_
728
Note: See TracBrowser for help on using the repository browser.