Panda3D
Loading...
Searching...
No Matches
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
14template<class BMType>
16
17/**
18 * Returns a DoubleBitMask whose bits are all on.
19 */
20template<class BMType>
22all_on() {
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 */
32template<class BMType>
34all_off() {
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 */
44template<class BMType>
46lower_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 }
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 */
65template<class BMType>
67bit(int index) {
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 */
76template<class BMType>
78range(int low_bit, int size) {
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 */
87template<class BMType>
89get_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 */
97template<class BMType>
99get_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 */
110template<class BMType>
112set_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 */
123template<class BMType>
125clear_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 */
137template<class BMType>
139set_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 */
150template<class BMType>
152is_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 */
159template<class BMType>
161is_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 */
169template<class BMType>
170INLINE typename DoubleBitMask<BMType>::WordType DoubleBitMask<BMType>::
171extract(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 */
188template<class BMType>
190store(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 */
207template<class BMType>
209has_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 */
225template<class BMType>
227has_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 */
243template<class BMType>
245set_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 */
262template<class BMType>
264clear_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 */
281template<class BMType>
283set_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 */
294template<class BMType>
296get_num_on_bits() const {
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 */
303template<class BMType>
305get_num_off_bits() const {
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 */
313template<class BMType>
315get_lowest_on_bit() const {
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 */
330template<class BMType>
332get_lowest_off_bit() const {
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 */
347template<class BMType>
349get_highest_on_bit() const {
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 */
363template<class BMType>
365get_highest_off_bit() const {
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 */
382template<class BMType>
384get_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 */
407template<class 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 */
422template<class BMType>
424has_bits_in_common(const DoubleBitMask<BMType> &other) const {
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 */
432template<class BMType>
434clear() {
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 */
443template<class BMType>
445output(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 */
453template<class BMType>
455output_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 */
465template<class BMType>
467output_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 */
477template<class BMType>
479write(std::ostream &out, int indent_level) const {
480 indent(out, indent_level) << *this << "\n";
481}
482
483/**
484 *
485 */
486template<class BMType>
487INLINE bool DoubleBitMask<BMType>::
488operator == (const DoubleBitMask<BMType> &other) const {
489 return _lo == other._lo && _hi == other._hi;
490}
491
492/**
493 *
494 */
495template<class BMType>
496INLINE bool DoubleBitMask<BMType>::
497operator != (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 */
508template<class BMType>
510operator < (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 */
524template<class BMType>
526compare_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 */
537template<class BMType>
539operator & (const DoubleBitMask<BMType> &other) const {
540 DoubleBitMask<BMType> result(*this);
541 result &= other;
542 return result;
543}
544
545/**
546 *
547 */
548template<class BMType>
550operator | (const DoubleBitMask<BMType> &other) const {
551 DoubleBitMask<BMType> result(*this);
552 result |= other;
553 return result;
554}
555
556/**
557 *
558 */
559template<class BMType>
561operator ^ (const DoubleBitMask<BMType> &other) const {
562 DoubleBitMask<BMType> result(*this);
563 result ^= other;
564 return result;
565}
566
567/**
568 *
569 */
570template<class BMType>
572operator ~ () const {
573 DoubleBitMask<BMType> result(*this);
574 result.invert_in_place();
575 return result;
576}
577
578/**
579 *
580 */
581template<class BMType>
583operator << (int shift) const {
584 DoubleBitMask<BMType> result(*this);
585 result <<= shift;
586 return result;
587}
588
589/**
590 *
591 */
592template<class BMType>
594operator >> (int shift) const {
595 DoubleBitMask<BMType> result(*this);
596 result >>= shift;
597 return result;
598}
599
600/**
601 *
602 */
603template<class BMType>
604INLINE void DoubleBitMask<BMType>::
606 _lo &= other._lo;
607 _hi &= other._hi;
608}
609
610/**
611 *
612 */
613template<class BMType>
614INLINE void DoubleBitMask<BMType>::
616 _lo |= other._lo;
617 _hi |= other._hi;
618}
619
620/**
621 *
622 */
623template<class BMType>
624INLINE void DoubleBitMask<BMType>::
626 _lo ^= other._lo;
627 _hi ^= other._hi;
628}
629
630/**
631 *
632 */
633template<class BMType>
634INLINE void DoubleBitMask<BMType>::
635operator <<= (int shift) {
636 _hi = (_hi << shift) | ((_lo >> (half_bits - shift)) & BitMaskType::lower_on(shift));
637 _lo <<= shift;
638}
639
640/**
641 *
642 */
643template<class BMType>
644INLINE void DoubleBitMask<BMType>::
645operator >>= (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 */
653template<class BMType>
655generate_hash(ChecksumHashGenerator &hashgen) const {
656 _hi.generate_hash(hashgen);
657 _lo.generate_hash(hashgen);
658}
659
660/**
661 *
662 */
663template<class BMType>
665init_type() {
666 std::ostringstream str;
667 str << "DoubleBitMask" << num_bits;
668 register_type(_type_handle, str.str());
669}
This is a specific kind of HashGenerator that simply adds up all of the ints.
This is a special BitMask type that is implemented as a pair of lesser BitMask types,...
void clear_bit(int index)
Sets the nth bit off.
void output(std::ostream &out) const
Writes the DoubleBitMask out as a binary or a hex number, according to the number of bits.
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...
bool is_zero() const
Returns true if the entire doubleBitMask is zero, false otherwise.
void generate_hash(ChecksumHashGenerator &hashgen) const
Adds the doubleBitMask to the indicated hash generator.
int get_num_on_bits() const
Returns the number of bits that are set to 1 in the mask.
void set_range(int low_bit, int size)
Sets the indicated range of bits on.
int compare_to(const DoubleBitMask< BMType > &other) const
Returns a number less than zero if this DoubleBitMask sorts before the indicated other DoubleBitMask,...
int get_lowest_off_bit() const
Returns the index of the lowest 0 bit in the mask.
void set_bit(int index)
Sets the nth bit on.
constexpr int get_num_bits() const
Returns the number of bits available to set in the doubleBitMask.
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.
void set_bit_to(int index, bool value)
Sets the nth bit either on or off, according to the indicated bool value.
void invert_in_place()
Inverts all the bits in the DoubleBitMask.
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.
int get_highest_on_bit() const
Returns the index of the highest 1 bit in the mask.
static DoubleBitMask< BMType > lower_on(int on_bits)
Returns a DoubleBitMask whose lower on_bits bits are on.
void output_hex(std::ostream &out, int spaces_every=4) const
Writes the DoubleBitMask out as a hexadecimal number, with spaces every four digits.
bool operator<(const DoubleBitMask< BMType > &other) const
The ordering operator is of limited usefulness with a DoubleBitMask, however, it has a definition whi...
void clear()
Sets all the bits in the DoubleBitMask off.
bool has_all_of(int low_bit, int size) const
Returns true if all bits in the indicated range are set, false otherwise.
static DoubleBitMask< BMType > range(int low_bit, int size)
Returns a DoubleBitMask whose size bits, beginning at low_bit, are on.
static DoubleBitMask< BMType > all_on()
Returns a DoubleBitMask whose bits are all on.
int get_lowest_on_bit() const
Returns the index of the lowest 1 bit in the mask.
void clear_range(int low_bit, int size)
Sets the indicated range of bits off.
void store(WordType value, int low_bit, int size)
Stores the indicated word into the indicated range of bits with this DoubleBitMask.
static DoubleBitMask< BMType > bit(int index)
Returns a DoubleBitMask with only the indicated bit on.
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
void set_range_to(bool value, int low_bit, int size)
Sets the indicated range of bits to either on or off.
int get_highest_off_bit() const
Returns the index of the highest 0 bit in the mask.
WordType extract(int low_bit, int size) const
Returns a word that represents only the indicated range of bits within this DoubleBitMask,...
bool is_all_on() const
Returns true if the entire doubleBitMask is one, false otherwise.
bool has_any_of(int low_bit, int size) const
Returns true if any bit in the indicated range is set, 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.
int get_num_off_bits() const
Returns the number of bits that are set to 0 in the mask.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition indent.cxx:20
void register_type(TypeHandle &type_handle, const std::string &name)
This inline function is just a convenient way to call TypeRegistry::register_type(),...