Panda3D
doubleBitMask.I
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file doubleBitMask.I
10  * @author drose
11  * @date 2000-06-08
12  */
13 
14 template<class BMType>
16 
17 /**
18  * Returns a DoubleBitMask whose bits are all on.
19  */
20 template<class BMType>
22 all_on() {
23  DoubleBitMask<BMType> result;
24  result._lo = BitMaskType::all_on();
25  result._hi = BitMaskType::all_on();
26  return result;
27 }
28 
29 /**
30  * Returns a DoubleBitMask whose bits are all off.
31  */
32 template<class BMType>
35  DoubleBitMask<BMType> result;
36  result._lo.clear();
37  result._hi.clear();
38  return result;
39 }
40 
41 /**
42  * Returns a DoubleBitMask whose lower on_bits bits are on.
43  */
44 template<class BMType>
46 lower_on(int on_bits) {
47  if (on_bits <= 0) {
48  return all_off();
49  } else if (on_bits >= num_bits) {
50  return all_on();
51  }
52  DoubleBitMask<BMType> result;
53  if (on_bits <= half_bits) {
54  result._lo = BitMaskType::lower_on(on_bits);
55  } else {
56  result._lo = BitMaskType::all_on();
57  result._hi = BitMaskType::lower_on(on_bits - half_bits);
58  }
59  return result;
60 }
61 
62 /**
63  * Returns a DoubleBitMask with only the indicated bit on.
64  */
65 template<class BMType>
67 bit(int index) {
68  DoubleBitMask<BMType> result;
69  result.set_bit(index);
70  return result;
71 }
72 
73 /**
74  * Returns a DoubleBitMask whose size bits, beginning at low_bit, are on.
75  */
76 template<class BMType>
78 range(int low_bit, int size) {
79  DoubleBitMask<BMType> result;
80  result.set_range(low_bit, size);
81  return result;
82 }
83 
84 /**
85  * Returns the number of bits available to set in the doubleBitMask.
86  */
87 template<class BMType>
88 constexpr int DoubleBitMask<BMType>::
89 get_num_bits() const {
90  return num_bits;
91 }
92 
93 /**
94  * Returns true if the nth bit is set, false if it is cleared. index must be
95  * in the range [0, num_bits).
96  */
97 template<class BMType>
98 INLINE bool DoubleBitMask<BMType>::
99 get_bit(int index) const {
100  if (index < half_bits) {
101  return _lo.get_bit(index);
102  } else {
103  return _hi.get_bit(index - half_bits);
104  }
105 }
106 
107 /**
108  * Sets the nth bit on. index must be in the range [0, num_bits).
109  */
110 template<class BMType>
111 INLINE void DoubleBitMask<BMType>::
112 set_bit(int index) {
113  if (index < half_bits) {
114  _lo.set_bit(index);
115  } else {
116  _hi.set_bit(index - half_bits);
117  }
118 }
119 
120 /**
121  * Sets the nth bit off. index must be in the range [0, num_bits).
122  */
123 template<class BMType>
124 INLINE void DoubleBitMask<BMType>::
125 clear_bit(int index) {
126  if (index < half_bits) {
127  _lo.clear_bit(index);
128  } else {
129  _hi.clear_bit(index - half_bits);
130  }
131 }
132 
133 /**
134  * Sets the nth bit either on or off, according to the indicated bool value.
135  * index must be in the range [0, num_bits).
136  */
137 template<class BMType>
138 INLINE void DoubleBitMask<BMType>::
139 set_bit_to(int index, bool value) {
140  if (index < half_bits) {
141  _lo.set_bit_to(index, value);
142  } else {
143  _hi.set_bit_to(index - half_bits, value);
144  }
145 }
146 
147 /**
148  * Returns true if the entire doubleBitMask is zero, false otherwise.
149  */
150 template<class BMType>
151 INLINE bool DoubleBitMask<BMType>::
152 is_zero() const {
153  return (_lo.is_zero() && _hi.is_zero());
154 }
155 
156 /**
157  * Returns true if the entire doubleBitMask is one, false otherwise.
158  */
159 template<class BMType>
160 INLINE bool DoubleBitMask<BMType>::
161 is_all_on() const {
162  return (_lo.is_all_on() && _hi.is_all_on());
163 }
164 
165 /**
166  * Returns a word that represents only the indicated range of bits within this
167  * DoubleBitMask, shifted to the least-significant position.
168  */
169 template<class BMType>
170 INLINE typename DoubleBitMask<BMType>::WordType DoubleBitMask<BMType>::
171 extract(int low_bit, int size) const {
172  if (low_bit >= half_bits) {
173  return _hi.extract(low_bit - half_bits, size);
174  } else if (low_bit + size < half_bits) {
175  return _lo.extract(low_bit, size);
176  } else {
177  int hi_portion = low_bit + size - half_bits;
178  int lo_portion = size - hi_portion;
179  return (_hi.extract(0, hi_portion) << lo_portion) |
180  _lo.extract(low_bit, lo_portion);
181  }
182 }
183 
184 /**
185  * Stores the indicated word into the indicated range of bits with this
186  * DoubleBitMask.
187  */
188 template<class BMType>
189 INLINE void DoubleBitMask<BMType>::
190 store(WordType value, int low_bit, int size) {
191  if (low_bit >= half_bits) {
192  _hi.store(value, low_bit - half_bits, size);
193  } else if (low_bit + size < half_bits) {
194  _lo.store(value, low_bit, size);
195  } else {
196  int hi_portion = low_bit + size - half_bits;
197  int lo_portion = size - hi_portion;
198 
199  _hi.store(value >> lo_portion, 0, hi_portion);
200  _lo.store(value, low_bit, lo_portion);
201  }
202 }
203 
204 /**
205  * Returns true if any bit in the indicated range is set, false otherwise.
206  */
207 template<class BMType>
208 INLINE bool DoubleBitMask<BMType>::
209 has_any_of(int low_bit, int size) const {
210  if (low_bit >= half_bits) {
211  return _hi.has_any_of(low_bit - half_bits, size);
212  } else if (low_bit + size < half_bits) {
213  return _lo.has_any_of(low_bit, size);
214  } else {
215  int hi_portion = low_bit + size - half_bits;
216  int lo_portion = size - hi_portion;
217  return _hi.has_any_of(0, hi_portion)
218  || _lo.has_any_of(low_bit, lo_portion);
219  }
220 }
221 
222 /**
223  * Returns true if all bits in the indicated range are set, false otherwise.
224  */
225 template<class BMType>
226 INLINE bool DoubleBitMask<BMType>::
227 has_all_of(int low_bit, int size) const {
228  if (low_bit >= half_bits) {
229  return _hi.has_all_of(low_bit - half_bits, size);
230  } else if (low_bit + size < half_bits) {
231  return _lo.has_all_of(low_bit, size);
232  } else {
233  int hi_portion = low_bit + size - half_bits;
234  int lo_portion = size - hi_portion;
235  return _hi.has_all_of(0, hi_portion)
236  && _lo.has_all_of(low_bit, lo_portion);
237  }
238 }
239 
240 /**
241  * Sets the indicated range of bits on.
242  */
243 template<class BMType>
244 INLINE void DoubleBitMask<BMType>::
245 set_range(int low_bit, int size) {
246  if (low_bit >= half_bits) {
247  _hi.set_range(low_bit - half_bits, size);
248  } else if (low_bit + size < half_bits) {
249  _lo.set_range(low_bit, size);
250  } else {
251  int hi_portion = low_bit + size - half_bits;
252  int lo_portion = size - hi_portion;
253 
254  _hi.set_range(0, hi_portion);
255  _lo.set_range(low_bit, lo_portion);
256  }
257 }
258 
259 /**
260  * Sets the indicated range of bits off.
261  */
262 template<class BMType>
263 INLINE void DoubleBitMask<BMType>::
264 clear_range(int low_bit, int size) {
265  if (low_bit >= half_bits) {
266  _hi.clear_range(low_bit - half_bits, size);
267  } else if (low_bit + size < half_bits) {
268  _lo.clear_range(low_bit, size);
269  } else {
270  int hi_portion = low_bit + size - half_bits;
271  int lo_portion = size - hi_portion;
272 
273  _hi.clear_range(0, hi_portion);
274  _lo.clear_range(low_bit, lo_portion);
275  }
276 }
277 
278 /**
279  * Sets the indicated range of bits to either on or off.
280  */
281 template<class BMType>
282 INLINE void DoubleBitMask<BMType>::
283 set_range_to(bool value, int low_bit, int size) {
284  if (value) {
285  set_range(low_bit, size);
286  } else {
287  clear_range(low_bit, size);
288  }
289 }
290 
291 /**
292  * Returns the number of bits that are set to 1 in the mask.
293  */
294 template<class BMType>
295 INLINE int DoubleBitMask<BMType>::
297  return _lo.get_num_on_bits() + _hi.get_num_on_bits();
298 }
299 
300 /**
301  * Returns the number of bits that are set to 0 in the mask.
302  */
303 template<class BMType>
304 INLINE int DoubleBitMask<BMType>::
306  return _lo.get_num_off_bits() + _hi.get_num_off_bits();
307 }
308 
309 /**
310  * Returns the index of the lowest 1 bit in the mask. Returns -1 if there are
311  * no 1 bits.
312  */
313 template<class BMType>
314 INLINE int DoubleBitMask<BMType>::
316  int result = _lo.get_lowest_on_bit();
317  if (result == -1) {
318  result = _hi.get_lowest_on_bit();
319  if (result != -1) {
320  result += half_bits;
321  }
322  }
323  return result;
324 }
325 
326 /**
327  * Returns the index of the lowest 0 bit in the mask. Returns -1 if there are
328  * no 0 bits.
329  */
330 template<class BMType>
331 INLINE int DoubleBitMask<BMType>::
333  int result = _lo.get_lowest_off_bit();
334  if (result == -1) {
335  result = _hi.get_lowest_off_bit();
336  if (result != -1) {
337  result += half_bits;
338  }
339  }
340  return result;
341 }
342 
343 /**
344  * Returns the index of the highest 1 bit in the mask. Returns -1 if there
345  * are no 1 bits.
346  */
347 template<class BMType>
348 INLINE int DoubleBitMask<BMType>::
350  int result = _hi.get_highest_on_bit();
351  if (result == -1) {
352  result = _lo.get_highest_on_bit();
353  } else {
354  result += half_bits;
355  }
356  return result;
357 }
358 
359 /**
360  * Returns the index of the highest 0 bit in the mask. Returns -1 if there
361  * are no 0 bits.
362  */
363 template<class BMType>
364 INLINE int DoubleBitMask<BMType>::
366  int result = _hi.get_highest_off_bit();
367  if (result == -1) {
368  result = _lo.get_highest_off_bit();
369  } else {
370  result += half_bits;
371  }
372  return result;
373 }
374 
375 /**
376  * Returns the index of the next bit in the mask, above low_bit, whose value
377  * is different that the value of low_bit. Returns low_bit again if all bits
378  * higher than low_bit have the same value.
379  *
380  * This can be used to quickly iterate through all of the bits in the mask.
381  */
382 template<class BMType>
383 INLINE int DoubleBitMask<BMType>::
384 get_next_higher_different_bit(int low_bit) const {
385  if (low_bit > half_bits) {
386  return _hi.get_next_higher_different_bit(low_bit - half_bits) + half_bits;
387  }
388  int result = _lo.get_next_higher_different_bit(low_bit);
389  if (result != low_bit) {
390  return result;
391  }
392  if (_lo.get_bit(low_bit)) {
393  result = _hi.get_lowest_off_bit();
394  } else {
395  result = _hi.get_lowest_on_bit();
396  }
397  if (result == -1) {
398  return low_bit;
399  }
400  return result + half_bits;
401 }
402 
403 /**
404  * Inverts all the bits in the DoubleBitMask. This is equivalent to mask =
405  * ~mask.
406  */
407 template<class BMType>
408 INLINE void DoubleBitMask<BMType>::
410  _lo.invert_in_place();
411  _hi.invert_in_place();
412 }
413 
414 /**
415  * Returns true if this DoubleBitMask has any "one" bits in common with the
416  * other one, false otherwise.
417  *
418  * This is equivalent to (mask & other) != 0, but may be faster. (Actually,
419  * it should only be faster in the BitArray case, but this method is provided
420  * for the benefit of generic programming algorithms).
421  */
422 template<class BMType>
423 INLINE bool DoubleBitMask<BMType>::
425  return _lo.has_bits_in_common(other._lo) ||
426  _hi.has_bits_in_common(other._hi);
427 }
428 
429 /**
430  * Sets all the bits in the DoubleBitMask off.
431  */
432 template<class BMType>
433 INLINE void DoubleBitMask<BMType>::
434 clear() {
435  _lo.clear();
436  _hi.clear();
437 }
438 
439 /**
440  * Writes the DoubleBitMask out as a binary or a hex number, according to the
441  * number of bits.
442  */
443 template<class BMType>
445 output(std::ostream &out) const {
446  output_hex(out);
447 }
448 
449 /**
450  * Writes the DoubleBitMask out as a binary number, with spaces every four
451  * bits.
452  */
453 template<class BMType>
455 output_binary(std::ostream &out, int spaces_every) const {
456  _hi.output_binary(out);
457  out << ' ';
458  _lo.output_binary(out);
459 }
460 
461 /**
462  * Writes the DoubleBitMask out as a hexadecimal number, with spaces every
463  * four digits.
464  */
465 template<class BMType>
467 output_hex(std::ostream &out, int spaces_every) const {
468  _hi.output_hex(out);
469  out << ' ';
470  _lo.output_hex(out);
471 }
472 
473 /**
474  * Writes the DoubleBitMask out as a binary or a hex number, according to the
475  * number of bits.
476  */
477 template<class BMType>
479 write(std::ostream &out, int indent_level) const {
480  indent(out, indent_level) << *this << "\n";
481 }
482 
483 /**
484  *
485  */
486 template<class BMType>
487 INLINE bool DoubleBitMask<BMType>::
488 operator == (const DoubleBitMask<BMType> &other) const {
489  return _lo == other._lo && _hi == other._hi;
490 }
491 
492 /**
493  *
494  */
495 template<class BMType>
496 INLINE bool DoubleBitMask<BMType>::
497 operator != (const DoubleBitMask<BMType> &other) const {
498  return _lo != other._lo && _hi != other._hi;
499 }
500 
501 /**
502  * The ordering operator is of limited usefulness with a DoubleBitMask,
503  * however, it has a definition which places all unique DoubleBitMasks into a
504  * unique ordering. It may be useful when defining ordered STL containers of
505  * DoubleBitMasks, for instance; and it's required in order to export any STL
506  * container (ordered or unordered) of DoubleBitMask under Windows.
507  */
508 template<class BMType>
509 INLINE bool DoubleBitMask<BMType>::
510 operator < (const DoubleBitMask<BMType> &other) const {
511  int cmp = _hi.compare_to(other._hi);
512  if (cmp != 0) {
513  return cmp < 0;
514  }
515  return _lo < other._lo;
516 }
517 
518 /**
519  * Returns a number less than zero if this DoubleBitMask sorts before the
520  * indicated other DoubleBitMask, greater than zero if it sorts after, or 0 if
521  * they are equivalent. This is based on the same ordering defined by
522  * operator <.
523  */
524 template<class BMType>
525 INLINE int DoubleBitMask<BMType>::
526 compare_to(const DoubleBitMask<BMType> &other) const {
527  int cmp = _hi.compare_to(other._hi);
528  if (cmp != 0) {
529  return cmp;
530  }
531  return _lo.compare_to(other._lo);
532 }
533 
534 /**
535  *
536  */
537 template<class BMType>
539 operator & (const DoubleBitMask<BMType> &other) const {
540  DoubleBitMask<BMType> result(*this);
541  result &= other;
542  return result;
543 }
544 
545 /**
546  *
547  */
548 template<class BMType>
550 operator | (const DoubleBitMask<BMType> &other) const {
551  DoubleBitMask<BMType> result(*this);
552  result |= other;
553  return result;
554 }
555 
556 /**
557  *
558  */
559 template<class BMType>
561 operator ^ (const DoubleBitMask<BMType> &other) const {
562  DoubleBitMask<BMType> result(*this);
563  result ^= other;
564  return result;
565 }
566 
567 /**
568  *
569  */
570 template<class BMType>
572 operator ~ () const {
573  DoubleBitMask<BMType> result(*this);
574  result.invert_in_place();
575  return result;
576 }
577 
578 /**
579  *
580  */
581 template<class BMType>
583 operator << (int shift) const {
584  DoubleBitMask<BMType> result(*this);
585  result <<= shift;
586  return result;
587 }
588 
589 /**
590  *
591  */
592 template<class BMType>
594 operator >> (int shift) const {
595  DoubleBitMask<BMType> result(*this);
596  result >>= shift;
597  return result;
598 }
599 
600 /**
601  *
602  */
603 template<class BMType>
604 INLINE void DoubleBitMask<BMType>::
605 operator &= (const DoubleBitMask<BMType> &other) {
606  _lo &= other._lo;
607  _hi &= other._hi;
608 }
609 
610 /**
611  *
612  */
613 template<class BMType>
614 INLINE void DoubleBitMask<BMType>::
615 operator |= (const DoubleBitMask<BMType> &other) {
616  _lo |= other._lo;
617  _hi |= other._hi;
618 }
619 
620 /**
621  *
622  */
623 template<class BMType>
624 INLINE void DoubleBitMask<BMType>::
625 operator ^= (const DoubleBitMask<BMType> &other) {
626  _lo ^= other._lo;
627  _hi ^= other._hi;
628 }
629 
630 /**
631  *
632  */
633 template<class BMType>
634 INLINE void DoubleBitMask<BMType>::
635 operator <<= (int shift) {
636  _hi = (_hi << shift) | ((_lo >> (half_bits - shift)) & BitMaskType::lower_on(shift));
637  _lo <<= shift;
638 }
639 
640 /**
641  *
642  */
643 template<class BMType>
644 INLINE void DoubleBitMask<BMType>::
645 operator >>= (int shift) {
646  _lo = (_lo >> shift) | ((_hi & BitMaskType::lower_on(shift)) << (half_bits - shift));
647  _hi >>= shift;
648 }
649 
650 /**
651  * Adds the doubleBitMask to the indicated hash generator.
652  */
653 template<class BMType>
654 INLINE void DoubleBitMask<BMType>::
656  _hi.generate_hash(hashgen);
657  _lo.generate_hash(hashgen);
658 }
659 
660 /**
661  *
662  */
663 template<class BMType>
665 init_type() {
666  std::ostringstream str;
667  str << "DoubleBitMask" << num_bits;
668  register_type(_type_handle, str.str());
669 }
bool is_all_on() const
Returns true if the entire doubleBitMask is one, false otherwise.
void output_binary(std::ostream &out, int spaces_every=4) const
Writes the DoubleBitMask out as a binary number, with spaces every four bits.
This is a specific kind of HashGenerator that simply adds up all of the ints.
void clear_range(int low_bit, int size)
Sets the indicated range of bits off.
static DoubleBitMask< BMType > range(int low_bit, int size)
Returns a DoubleBitMask whose size bits, beginning at low_bit, are on.
Definition: doubleBitMask.I:78
constexpr int get_num_bits() const
Returns the number of bits available to set in the doubleBitMask.
Definition: doubleBitMask.I:89
bool operator<(const DoubleBitMask< BMType > &other) const
The ordering operator is of limited usefulness with a DoubleBitMask, however, it has a definition whi...
int get_lowest_on_bit() const
Returns the index of the lowest 1 bit in the mask.
void register_type(TypeHandle &type_handle, const std::string &name)
This inline function is just a convenient way to call TypeRegistry::register_type(),...
Definition: register_type.I:22
void set_range_to(bool value, int low_bit, int size)
Sets the indicated range of bits to either on or off.
void generate_hash(ChecksumHashGenerator &hashgen) const
Adds the doubleBitMask to the indicated hash generator.
int get_highest_on_bit() const
Returns the index of the highest 1 bit in the mask.
This is a special BitMask type that is implemented as a pair of lesser BitMask types,...
Definition: doubleBitMask.h:28
void write(std::ostream &out, int indent_level=0) const
Writes the DoubleBitMask out as a binary or a hex number, according to the number of bits.
void store(WordType value, int low_bit, int size)
Stores the indicated word into the indicated range of bits with this DoubleBitMask.
bool has_any_of(int low_bit, int size) const
Returns true if any bit in the indicated range is set, false otherwise.
void clear_bit(int index)
Sets the nth bit off.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
int get_next_higher_different_bit(int low_bit) const
Returns the index of the next bit in the mask, above low_bit, whose value is different that the value...
static DoubleBitMask< BMType > lower_on(int on_bits)
Returns a DoubleBitMask whose lower on_bits bits are on.
Definition: doubleBitMask.I:46
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
Definition: doubleBitMask.I:99
int get_lowest_off_bit() const
Returns the index of the lowest 0 bit in the mask.
void output(std::ostream &out) const
Writes the DoubleBitMask out as a binary or a hex number, according to the number of bits.
void set_range(int low_bit, int size)
Sets the indicated range of bits on.
WordType extract(int low_bit, int size) const
Returns a word that represents only the indicated range of bits within this DoubleBitMask,...
void clear()
Sets all the bits in the DoubleBitMask off.
void set_bit_to(int index, bool value)
Sets the nth bit either on or off, according to the indicated bool value.
int get_num_off_bits() const
Returns the number of bits that are set to 0 in the mask.
void set_bit(int index)
Sets the nth bit on.
static DoubleBitMask< BMType > all_on()
Returns a DoubleBitMask whose bits are all on.
Definition: doubleBitMask.I:22
bool is_zero() const
Returns true if the entire doubleBitMask is zero, false otherwise.
void output_hex(std::ostream &out, int spaces_every=4) const
Writes the DoubleBitMask out as a hexadecimal number, with spaces every four digits.
static DoubleBitMask< BMType > bit(int index)
Returns a DoubleBitMask with only the indicated bit on.
Definition: doubleBitMask.I:67
int get_num_on_bits() const
Returns the number of bits that are set to 1 in the mask.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
int compare_to(const DoubleBitMask< BMType > &other) const
Returns a number less than zero if this DoubleBitMask sorts before the indicated other DoubleBitMask,...
void invert_in_place()
Inverts all the bits in the DoubleBitMask.
int get_highest_off_bit() const
Returns the index of the highest 0 bit in the mask.
bool has_bits_in_common(const DoubleBitMask< BMType > &other) const
Returns true if this DoubleBitMask has any "one" bits in common with the other one,...
static DoubleBitMask< BMType > all_off()
Returns a DoubleBitMask whose bits are all off.
Definition: doubleBitMask.I:34
bool has_all_of(int low_bit, int size) const
Returns true if all bits in the indicated range are set, false otherwise.