LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
BitMask.tcc
Go to the documentation of this file.
1 /**
2  * @file BitMask.tcc
3  * @brief Class holding flags: template implementation file.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date January 25, 2017
6  * @see BitMask.h
7  *
8  */
9 
10 #ifndef LARDATAOBJ_UTILITIES_BITMASK_TCC
11 #define LARDATAOBJ_UTILITIES_BITMASK_TCC
12 
13 #ifndef LARDATAOBJ_UTILITIES_BITMASK_H
14 # error "Do not include BitMask.tcc directly: include BitMask.h instead."
15 #endif // !LARDATAOBJ_UTILITIES_BITMASK_H
16 
17 
18 // C/C++ standard library
19 #include <type_traits> // std::integral_constant, std::make_unsigned_t, ...
20 #include <algorithm> // std::for_each()
21 
22 
23 namespace util {
24 
25  namespace flags {
26 
27  namespace details {
28 
29  //------------------------------------------------------------------------
30  template <typename First, typename... Others>
31  struct GrowingSizeTypes;
32 
33  template <typename First, typename Next, typename... Others>
34  struct GrowingSizeTypes<First, Next, Others...>
35  : public std::integral_constant<
36  bool,
37  (sizeof(First) <= sizeof(Next))
38  && GrowingSizeTypes<Next, Others...>::value
39  >
40  {};
41 
42  template <typename First>
43  struct GrowingSizeTypes<First>: public std::true_type {};
44 
45 
46  //------------------------------------------------------------------------
47  template <unsigned int NBits, typename... TestTypes>
48  struct FirstUnsignedTypeNoSmallerThanImpl;
49 
50  template <unsigned int NBits, typename TestType, typename... Others>
51  struct FirstUnsignedTypeNoSmallerThanImpl<NBits, TestType, Others...> {
52  static_assert(sizeof...(Others) > 0, "Wrong specialisation!");
53  static_assert(GrowingSizeTypes<TestType, Others...>(),
54  "Types are not in increasing size order!");
55 
56  using unsigned_test_type = std::make_unsigned_t<TestType>;
57  static_assert(sizeof(TestType) == sizeof(unsigned_test_type),
58  "Strange: signed and unsigned type sizes differ.");
59 
60  using type = std::conditional_t<
61  (sizeof(unsigned_test_type) * 8 >= NBits),
62  unsigned_test_type,
63  typename FirstUnsignedTypeNoSmallerThanImpl<NBits, Others...>::type
64  >;
65 
66  }; // FirstUnsignedTypeNoSmallerThanImpl<>
67 
68  template <unsigned int NBits, typename TestType>
69  struct FirstUnsignedTypeNoSmallerThanImpl<NBits, TestType>
70  { using type = TestType; };
71 
72  template <unsigned int NBits, typename... TestTypes>
73  struct FirstUnsignedTypeNoSmallerThan {
74 
75  using type =
76  typename FirstUnsignedTypeNoSmallerThanImpl<NBits, TestTypes...>
77  ::type;
78 
79  static_assert(sizeof(type) * 8 >= NBits, "No type is large enough!");
80  }; // FirstUnsignedTypeNoSmallerThan
81 
82  /// Trait containing the smallest integral type accommodating `NBits`
83  /// bits.
84  template <unsigned int NBits>
85  struct SmallestUIntType {
86 
87  using type = typename FirstUnsignedTypeNoSmallerThan
88  <NBits, char, short int, int, long int, long long int>::type;
89 
90  }; // struct SmallestUIntType
91 
92  /// Returns the number of Storage variables needed to hold that many bits
93  template <typename Storage>
94  constexpr unsigned int computePages(unsigned int bits) {
95  return 1
96  + ((sizeof(Storage) * 8 >= bits)? 0: computePages<Storage>(bits - 8));
97  }
98 
99  //------------------------------------------------------------------------
100 
101  template <typename T>
102  constexpr Index_t firstBitIndexImpl(T bits, Index_t carry)
103  { return (bits & 1) ? carry: firstBitIndexImpl(bits >> 1, carry + 1); }
104 
105  /// Returns the index of the least significant set bit, or max() if none.
106  template <typename T>
107  constexpr Index_t firstBitIndex(T bits) {
108  return bits? firstBitIndexImpl(bits, 0): sizeof(T) * 8;
109  }
110 
111 
112  //------------------------------------------------------------------------
113  template <typename Storage>
114  char flagChar(
115  BitMask<Storage> const& flags,
116  typename BitMask<Storage>::Flag_t flag,
117  char const unset = '0', char const set = '1', char const undefined = '-',
118  char const unexpected = '?'
119  )
120  {
121  if (flags.isUndefined(flag)) return undefined;
122  if (flags.isSet(flag)) return set;
123  if (flags.isUnset(flag)) return unset;
124  return unexpected;
125  } // flagChar()
126 
127  //------------------------------------------------------------------------
128  template <typename Storage>
129  constexpr typename util::flags::BitMask<Storage>::Mask_t createMaskImpl
130  (util::flags::BitMask<Storage> const baseMask)
131  { return baseMask; }
132 
133  template <typename Storage, typename First, typename... Others>
134  constexpr typename util::flags::BitMask<Storage>::Mask_t createMaskImpl(
135  util::flags::BitMask<Storage> const baseMask,
136  First first, Others... others
137  )
138  {
139  return createMaskImpl(
140  util::flags::BitMask<Storage>::mergeIntoMask(baseMask, first),
141  others...
142  );
143  }
144 
145 
146  //------------------------------------------------------------------------
147 
148  } // namespace details
149 
150  } // namespace flags
151 
152 } // namespace util
153 
154 
155 
156 //------------------------------------------------------------------------------
157 //--- Flag_t<>
158 //---
159 template <typename Storage>
160 constexpr util::flags::Index_t util::flags::Flag_t<Storage>::index() const
161  { return details::firstBitIndex(bits); }
162 
163 
164 //------------------------------------------------------------------------------
165 //--- Bits_t<>
166 //---
167 template <typename Storage>
168 constexpr bool util::flags::Bits_t<Storage>::all(This_t bits) const
169  { return select(bits) == bits; }
170 
171 template <typename Storage>
172 constexpr bool util::flags::Bits_t<Storage>::any(This_t bits) const
173  { return bool(select(bits)) || !bits; }
174 
175 template <typename Storage>
176 constexpr bool util::flags::Bits_t<Storage>::none(This_t bits) const
177  { return !any(bits) || !bits; }
178 
179 template <typename Storage>
180 constexpr bool util::flags::Bits_t<Storage>::only(This_t bits) const
181  { return !exclude(bits); }
182 
183 
184 //------------------------------------------------------------------------------
185 template <typename Storage>
186 constexpr util::flags::Bits_t<Storage> util::flags::Bits_t<Storage>::combine
187  (This_t bits) const
188  { return This_t(Storage_t(data | bits.data)); }
189 
190 template <typename Storage>
191 constexpr util::flags::Bits_t<Storage> util::flags::Bits_t<Storage>::select
192  (This_t bits) const
193  { return This_t(Storage_t(data & bits.data)); }
194 
195 template <typename Storage>
196 constexpr util::flags::Bits_t<Storage> util::flags::Bits_t<Storage>::exclude
197  (This_t bits) const
198  { return select(bits.invert()); }
199 
200 template <typename Storage>
201 constexpr util::flags::Bits_t<Storage> util::flags::Bits_t<Storage>::invert
202  () const
203  { return This_t(Storage_t(~data)); }
204 
205 
206 //------------------------------------------------------------------------------
207 template <typename Storage>
208 void util::flags::Bits_t<Storage>::set(This_t bits)
209  { setBits(data, bits.data); }
210 
211 template <typename Storage>
212 void util::flags::Bits_t<Storage>::unset(This_t bits)
213  { unsetBits(data, bits.data); }
214 
215 template <typename Storage>
216 void util::flags::Bits_t<Storage>::keepOnly(This_t bits)
217  { unsetBits(data, bits.negate().data); }
218 
219 
220 //------------------------------------------------------------------------------
221 template <typename Storage>
222 constexpr util::flags::Bits_t<Storage> util::flags::operator|
223  (util::flags::Bits_t<Storage> left, util::flags::Bits_t<Storage> right)
224  { return left.combine(right); }
225 
226 template <typename Storage>
227 constexpr util::flags::Bits_t<Storage> util::flags::operator| (
228  util::flags::Bits_t<Storage> left,
229  typename util::flags::Bits_t<Storage>::Flag_t right
230  )
231  { return left | util::flags::Bits_t<Storage>(right); }
232 
233 template <typename Storage>
234 constexpr util::flags::Bits_t<Storage> util::flags::operator| (
235  typename util::flags::Bits_t<Storage>::Flag_t left,
236  util::flags::Bits_t<Storage> right
237  )
238  { return right | left; }
239 
240 template <typename Storage>
241 constexpr util::flags::Bits_t<Storage> util::flags::operator| (
242  util::flags::Flag_t<Storage> left,
243  util::flags::Flag_t<Storage> right
244  )
245  { return util::flags::Bits_t<Storage>(left) | right; }
246 
247 
248 template <typename Storage>
249 constexpr util::flags::Bits_t<Storage> util::flags::operator+
250  (util::flags::Bits_t<Storage> left, util::flags::Bits_t<Storage> right)
251  { return left | right; }
252 
253 template <typename Storage>
254 constexpr util::flags::Bits_t<Storage> util::flags::operator+ (
255  util::flags::Bits_t<Storage> left,
256  typename util::flags::Bits_t<Storage>::Flag_t right
257  )
258  { return left | right; }
259 
260 template <typename Storage>
261 constexpr util::flags::Bits_t<Storage> util::flags::operator+ (
262  typename util::flags::Bits_t<Storage>::Flag_t left,
263  util::flags::Bits_t<Storage> right
264  )
265  { return left | right; }
266 
267 template <typename Storage>
268 constexpr util::flags::Bits_t<Storage> util::flags::operator+ (
269  util::flags::Flag_t<Storage> left,
270  util::flags::Flag_t<Storage> right
271  )
272  { return left | right; }
273 
274 
275 
276 //------------------------------------------------------------------------------
277 //--- BitMask<>
278 //---
279 template <typename Storage>
280 constexpr util::flags::BitMask<Storage>::BitMask
281  (BitMaskFromValuesTag, Bits_t defined, Bits_t values)
282  : values(values)
283  , presence(defined.combine(values))
284  {}
285 
286 template <typename Storage>
287 constexpr util::flags::BitMask<Storage>::BitMask
288  (BitMaskFromValuesTag tag, Bits_t bits)
289  : BitMask(tag, bits, bits)
290  {}
291 
292 template <typename Storage>
293 constexpr util::flags::BitMask<Storage>::BitMask
294  (BitMaskFromValuesTag tag, Storage_t defined, Storage_t values)
295  : BitMask(tag, Bits_t(defined), Bits_t(values))
296  {}
297 
298 template <typename Storage>
299 constexpr util::flags::BitMask<Storage>::BitMask
300  (BitMaskFromValuesTag tag, Storage_t values)
301  : BitMask(tag, Bits_t(values))
302  {}
303 
304 //------------------------------------------------------------------------------
305 template <typename Storage>
306 constexpr typename util::flags::BitMask<Storage>::Bits_t
307 util::flags::BitMask<Storage>::definedOnly() const
308  { return values.select(presence); }
309 
310 //------------------------------------------------------------------------------
311 template <typename Storage>
312 constexpr size_t util::flags::BitMask<Storage>::capacity()
313  { return sizeof(Storage) * 8; }
314 
315 //------------------------------------------------------------------------------
316 template <typename Storage>
317 constexpr bool util::flags::BitMask<Storage>::isDefined(Flag_t flag) const
318  { return presence.any(flag); }
319 
320 template <typename Storage>
321 constexpr bool util::flags::BitMask<Storage>::isDefined(Bits_t bits) const
322  { return presence.all(bits); }
323 
324 //------------------------------------------------------------------------------
325 template <typename Storage>
326 constexpr bool util::flags::BitMask<Storage>::isUndefined(Flag_t flag) const
327  { return !isDefined(flag); }
328 
329 template <typename Storage>
330 constexpr bool util::flags::BitMask<Storage>::isUndefined(Bits_t bits) const
331  { return !isDefined(bits); }
332 
333 //------------------------------------------------------------------------------
334 template <typename Storage>
335 constexpr bool util::flags::BitMask<Storage>::get(Flag_t flag) const
336  { return values.any(flag); }
337 
338 //------------------------------------------------------------------------------
339 template <typename Storage>
340 constexpr bool util::flags::BitMask<Storage>::isSet(Flag_t flag) const
341  { return get(flag) && isDefined(flag); }
342 
343 //------------------------------------------------------------------------------
344 template <typename Storage>
345 constexpr bool util::flags::BitMask<Storage>::isUnset(Flag_t flag) const
346  { return !get(flag) && isDefined(flag); }
347 
348 //------------------------------------------------------------------------------
349 template <typename Storage>
350 constexpr bool util::flags::BitMask<Storage>::all(Bits_t bits) const
351  { return isDefined(bits) && values.all(bits); }
352 
353 //------------------------------------------------------------------------------
354 template <typename Storage>
355 constexpr bool util::flags::BitMask<Storage>::any(Bits_t bits) const {
356  // check values only for the flags in bits that are actually defined;
357  // values.any() will return true if no bit is specified,
358  // which is semantically correct but does not serve the scope here;
359  // if no bits are defined, this method should return false instead.
360  return values.any(presence.select(bits)) && !(presence.select(bits).empty());
361 }
362 
363 //------------------------------------------------------------------------------
364 template <typename Storage>
365 constexpr bool util::flags::BitMask<Storage>::none(Bits_t bits) const
366  { return isDefined(bits) && values.none(bits); }
367 
368 //------------------------------------------------------------------------------
369 template <typename Storage>
370 constexpr bool util::flags::BitMask<Storage>::anySet(Mask_t const& mask) const {
371  return
372  !definedOnly().select(mask.definedOnly()).empty()
373  || mask.values.select(mask.presence).empty();
374 }
375 
376 //------------------------------------------------------------------------------
377 template <typename Storage>
378 constexpr bool util::flags::BitMask<Storage>::noneSet(Mask_t const& mask) const
379  { return !anySet(mask); }
380 
381 
382 //------------------------------------------------------------------------------
383 template <typename Storage>
384 constexpr bool util::flags::BitMask<Storage>::match(Mask_t const& mask) const {
385  // 1) no undefined flags that are defined in mask
386  // 2) all our flags defined also in mask must have the same values as in mask
387  return mask.presence.exclude(presence).empty()
388  && values.select(mask.presence) == mask.definedOnly();
389 }
390 
391 
392 //------------------------------------------------------------------------------
393 template <typename Storage>
394 template <typename Stream>
395 void util::flags::BitMask<Storage>::dump(Stream&& out, unsigned int nBits) const
396 {
397  out << '{';
398 
399  if (nBits > 0) {
400 
401  typename BitMask<Storage>::FlagIndex_t i = nBits;
402  out << details::flagChar(*this, --i);
403 
404  while (i-- > 0) {
405  if ((i % 4) == 3) out << ':';
406  out << details::flagChar(*this, i);
407  } // while
408 
409  } // if we have bits
410 
411  out << '}';
412 } // util::flags::BitMask<>::dump()
413 
414 
415 //------------------------------------------------------------------------------
416 template <typename Storage>
417 template <typename... Args>
418 constexpr typename util::flags::BitMask<Storage>::Mask_t
419 util::flags::BitMask<Storage>::create(Args... args)
420  { return details::createMaskImpl(Mask_t(), args...); }
421 
422 //------------------------------------------------------------------------------
423 template <typename Storage>
424 void util::flags::BitMask<Storage>::defineSingle(Flag_t flag)
425  { presence.set(flag); }
426 
427 //------------------------------------------------------------------------------
428 template <typename Storage>
429 template <typename... Flags>
430 void util::flags::BitMask<Storage>::undefineImpl(Flag_t flag, Flags... others)
431  { undefineSingle(flag); undefineImpl(others...); }
432 
433 //------------------------------------------------------------------------------
434 template <typename Storage>
435 void util::flags::BitMask<Storage>::undefineSingle(Flag_t flag)
436  { presence.unset(flag); }
437 
438 //------------------------------------------------------------------------------
439 template <typename Storage>
440 template <typename... Flags>
441 void util::flags::BitMask<Storage>::setImpl(Flag_t flag, Flags... others)
442  { setSingle(flag); setImpl(others...); }
443 
444 //------------------------------------------------------------------------------
445 template <typename Storage>
446 void util::flags::BitMask<Storage>::setSingle(Flag_t flag)
447  { defineSingle(flag); values.set(flag); }
448 
449 //------------------------------------------------------------------------------
450 template <typename Storage>
451 template <typename... Flags>
452 void util::flags::BitMask<Storage>::unsetImpl(Flag_t flag, Flags... others)
453  { unsetSingle(flag); unsetImpl(others...); }
454 
455 //------------------------------------------------------------------------------
456 template <typename Storage>
457 void util::flags::BitMask<Storage>::unsetSingle(Flag_t flag)
458  { defineSingle(flag); values.unset(flag); }
459 
460 //------------------------------------------------------------------------------
461 template <typename Storage>
462 template <typename BeginIter, typename EndIter>
463 void util::flags::BitMask<Storage>::rangeSet(BeginIter begin, EndIter end)
464  { std::for_each(begin, end, [this](auto&& flag){ this->set(flag); }); }
465 
466 //------------------------------------------------------------------------------
467 template <typename Storage>
468 template <typename BeginIter, typename EndIter>
469 void util::flags::BitMask<Storage>::rangeUnset(BeginIter begin, EndIter end)
470  { std::for_each(begin, end, [this](auto&& flag){ this->unset(flag); }); }
471 
472 
473 //------------------------------------------------------------------------------
474 template <typename Storage>
475 constexpr typename util::flags::BitMask<Storage>::Mask_t
476 util::flags::BitMask<Storage>::mergeIntoMask
477  (Mask_t baseMask, Mask_t mask)
478 {
479  return Mask_t(fromValues,
480  baseMask.presence.combine(mask.presence),
481  (baseMask.values.exclude(mask.presence)) | mask.values
482  );
483 } // util::flags::BitMask<>::mergeIntoMask(Mask_t)
484 
485 
486 //------------------------------------------------------------------------------
487 template <typename Storage>
488 constexpr typename util::flags::BitMask<Storage>::Mask_t
489 util::flags::BitMask<Storage>::mergeIntoMask
490  (Mask_t baseMask, Bits_t bits)
491 {
492  return Mask_t(fromValues,
493  baseMask.presence.combine(bits),
494  baseMask.values.combine(bits)
495  );
496 } // util::flags::BitMask<>::mergeIntoMask(Mask_t)
497 
498 
499 //------------------------------------------------------------------------------
500 template <typename Storage>
501 constexpr typename util::flags::BitMask<Storage>::Mask_t
502 util::flags::BitMask<Storage>::mergeIntoMask
503  (Mask_t baseMask, Flag_t flags)
504  { return mergeIntoMask(baseMask, Bits_t(flags)); }
505 
506 
507 //------------------------------------------------------------------------------
508 template <typename Storage>
509 constexpr typename util::flags::BitMask<Storage>::Mask_t
510 util::flags::BitMask<Storage>::combineWithMask
511  (Mask_t A, Mask_t B)
512 {
513  return Mask_t(fromValues,
514  A.presence.combine(B.presence),
515  A.presence.combine(B.presence).select(A.values.combine(B.values))
516  );
517 } // util::flags::BitMask<>::combineWithMask(Mask_t)
518 
519 
520 //------------------------------------------------------------------------------
521 template <typename Storage>
522 constexpr typename util::flags::BitMask<Storage>::Mask_t
523 util::flags::BitMask<Storage>::combineWithMask
524  (Mask_t baseMask, Bits_t bits)
525  { return mergeIntoMask(baseMask, bits); }
526 
527 
528 //------------------------------------------------------------------------------
529 template <typename Storage>
530 constexpr typename util::flags::BitMask<Storage>::Mask_t
531 util::flags::BitMask<Storage>::combineWithMask
532  (Mask_t baseMask, Flag_t flags)
533  { return combineWithMask(baseMask, Bits_t(flags)); }
534 
535 
536 //------------------------------------------------------------------------------
537 template <typename Storage>
538 constexpr typename util::flags::BitMask<Storage>::Mask_t
539 util::flags::BitMask<Storage>::intersectWithMask
540  (Mask_t A, Mask_t B)
541 {
542  //
543  // flags undefined in B are copied from A; for the others, B wins.
544  //
545  return Mask_t(fromValues,
546  A.presence.combine(B.presence),
547  // the bits that are defined in both get AND'ed:
548  A.presence.select(B.presence).select(A.values).select(B.values)
549  // the bits that are not, are copied:
550  .combine(
551  A.values.combine(B.values).exclude(A.presence.select(B.presence))
552  )
553  );
554 }
555 
556 //------------------------------------------------------------------------------
557 template <typename Storage>
558 constexpr typename util::flags::BitMask<Storage>::Mask_t
559 util::flags::BitMask<Storage>::intersectWithMask
560  (Mask_t baseMask, Bits_t bits)
561 {
562  // defined: (presentInA | B)
563  // values: (presentInA & B) & (valuesA & B) : if in both terms, use AND
564  // | (!(presentInA & B) & (valuesA | B) : otherwise, set from either
565  return Mask_t(fromValues,
566  baseMask.presence.combine(bits),
567  // the bits that are defined in both get AND'ed:
568  baseMask.presence.select(bits).select(baseMask.values)
569  // the bits that are not, are copied:
570  .combine(
571  baseMask.values.combine(bits).exclude(baseMask.presence.select(bits))
572  )
573  );
574 } // util::flags::BitMask<>::intersectWithMask(Mask_t)
575 
576 
577 //------------------------------------------------------------------------------
578 template <typename Storage>
579 constexpr typename util::flags::BitMask<Storage>::Mask_t
580 util::flags::BitMask<Storage>::intersectWithMask
581  (Mask_t baseMask, Flag_t flags)
582  { return intersectWithMask(baseMask, Bits_t(flags)); }
583 
584 
585 //------------------------------------------------------------------------------
586 template <typename Storage>
587 constexpr typename util::flags::BitMask<Storage>::Mask_t
588 util::flags::BitMask<Storage>::unsetMask(Mask_t baseMask, Mask_t mask) {
589  return Mask_t(fromValues,
590  baseMask.presence.combine(mask.presence),
591  baseMask.presence.combine(mask.presence)
592  .select(baseMask.values.exclude(mask.values))
593  );
594 }
595 
596 //------------------------------------------------------------------------------
597 template <typename Storage>
598 constexpr typename util::flags::BitMask<Storage>::Mask_t
599 util::flags::BitMask<Storage>::unsetMask(Mask_t baseMask, Bits_t bits) {
600  return Mask_t(fromValues,
601  baseMask.presence.combine(bits),
602  baseMask.values.exclude(bits)
603  );
604 } // util::flags::BitMask<>::unsetMask(Mask_t)
605 
606 
607 //------------------------------------------------------------------------------
608 template <typename Storage>
609 constexpr typename util::flags::BitMask<Storage>::Mask_t
610 util::flags::BitMask<Storage>::unsetMask
611  (Mask_t baseMask, Flag_t flags)
612  { return unsetMask(baseMask, Bits_t(flags)); }
613 
614 
615 //------------------------------------------------------------------------------
616 template <typename Storage>
617 constexpr typename util::flags::BitMask<Storage>::Mask_t
618 util::flags::BitMask<Storage>::negateMask(Mask_t mask) {
619  return Mask_t
620  (fromValues, mask.presence, mask.presence.select(mask.values.invert()));
621 }
622 
623 //------------------------------------------------------------------------------
624 template <typename Storage>
625 constexpr typename util::flags::BitMask<Storage>::Mask_t
626 util::flags::BitMask<Storage>::negateMask(Bits_t bits)
627  { return Mask_t(fromValues, bits, Bits_t(0)); }
628 
629 template <typename Storage>
630 constexpr typename util::flags::BitMask<Storage>::Mask_t
631 util::flags::BitMask<Storage>::negateMask(Flag_t flags)
632  { return negateMask(Bits_t(flags)); }
633 
634 
635 //------------------------------------------------------------------------------
636 //--- free functions and operators
637 //---
638 template <typename Storage>
639 constexpr util::flags::BitMask<Storage> util::flags::makeMask
640  (Bits_t<Storage> bits)
641  { return BitMask<Storage>(BitMask<Storage>::fromValues, bits); }
642 
643 
644 //------------------------------------------------------------------------------
645 template <typename Storage>
646 constexpr util::flags::BitMask<Storage> util::flags::operator|
647  (BitMask<Storage> left, BitMask<Storage> right)
648  { return BitMask<Storage>::combineWithMask(left, right); }
649 
650 template <typename Storage>
651 constexpr util::flags::BitMask<Storage> util::flags::operator|
652  (BitMask<Storage> left, typename BitMask<Storage>::Bits_t right)
653  { return BitMask<Storage>::combineWithMask(left, right); }
654 
655 template <typename Storage>
656 constexpr util::flags::BitMask<Storage> util::flags::operator|
657  (typename BitMask<Storage>::Bits_t left, BitMask<Storage> right)
658  { return BitMask<Storage>::combineWithMask(right, left); }
659 
660 
661 //------------------------------------------------------------------------------
662 template <typename Storage>
663 constexpr util::flags::BitMask<Storage> util::flags::operator&
664  (BitMask<Storage> left, BitMask<Storage> right)
665  { return BitMask<Storage>::intersectWithMask(left, right); }
666 
667 template <typename Storage>
668 constexpr util::flags::BitMask<Storage> util::flags::operator&
669  (BitMask<Storage> left, typename BitMask<Storage>::Bits_t right)
670  { return BitMask<Storage>::intersectWithMask(left, right); }
671 
672 template <typename Storage>
673 constexpr util::flags::BitMask<Storage> util::flags::operator&
674  (typename BitMask<Storage>::Bits_t left, BitMask<Storage> right)
675  { return makeMask(left) & right; }
676 
677 
678 template <typename Storage>
679 constexpr util::flags::BitMask<Storage> util::flags::operator&
680  (Bits_t<Storage> left, Bits_t<Storage> right)
681  { return BitMask<Storage>(left) & right; }
682 
683 //------------------------------------------------------------------------------
684 template <typename Storage>
685 constexpr util::flags::BitMask<Storage> util::flags::operator+
686  (BitMask<Storage> baseMask, BitMask<Storage> mask)
687  { return BitMask<Storage>::mergeIntoMask(baseMask, mask); }
688 
689 template <typename Storage>
690 constexpr util::flags::BitMask<Storage> util::flags::operator+
691  (BitMask<Storage> baseMask, typename BitMask<Storage>::Bits_t bits)
692  { return BitMask<Storage>::mergeIntoMask(baseMask, bits); }
693 
694 template <typename Storage>
695 constexpr util::flags::BitMask<Storage> util::flags::operator+
696  (typename BitMask<Storage>::Bits_t baseBits, BitMask<Storage> mask)
697  { return makeMask(baseBits) + mask; }
698 
699 //------------------------------------------------------------------------------
700 template <typename Storage>
701 constexpr util::flags::BitMask<Storage> util::flags::operator-
702  (BitMask<Storage> baseMask, BitMask<Storage> mask)
703  { return BitMask<Storage>::unsetMask(baseMask, mask); }
704 
705 template <typename Storage>
706 constexpr util::flags::BitMask<Storage> util::flags::operator-
707  (BitMask<Storage> baseMask, typename BitMask<Storage>::Bits_t bits)
708  { return BitMask<Storage>::unsetMask(baseMask, bits); }
709 
710 template <typename Storage>
711 constexpr util::flags::BitMask<Storage> util::flags::operator-
712  (typename BitMask<Storage>::Bits_t baseBits, BitMask<Storage> mask)
713  { return makeMask(baseBits) - mask; }
714 
715 template <typename Storage>
716 constexpr util::flags::BitMask<Storage> util::flags::operator-
717  (Bits_t<Storage> baseBits, Bits_t<Storage> bits)
718  { return makeMask(baseBits) - bits; }
719 
720 //------------------------------------------------------------------------------
721 template <typename Storage>
722 constexpr util::flags::BitMask<Storage> util::flags::operator+
723  (BitMask<Storage> mask)
724  { return mask; }
725 
726 template <typename Storage>
727 constexpr util::flags::BitMask<Storage> util::flags::operator+
728  (Bits_t<Storage> bits)
729  { return makeMask(bits); }
730 
731 //------------------------------------------------------------------------------
732 template <typename Storage>
733 constexpr util::flags::BitMask<Storage> util::flags::operator-
734  (Bits_t<Storage> bits)
735  { return BitMask<Storage>::negateMask(makeMask(bits)); }
736 
737 template <typename Storage>
738 constexpr util::flags::BitMask<Storage> util::flags::operator-
739  (Flag_t<Storage> flag)
740  { return -(Bits_t<Storage>(flag)); }
741 
742 //------------------------------------------------------------------------------
743 template <typename Storage>
744 constexpr util::flags::BitMask<Storage> util::flags::operator~
745  (BitMask<Storage> mask)
746  { return BitMask<Storage>::negateMask(mask); }
747 
748 /*
749 template <typename Storage>
750 constexpr BitMask<Storage> operator~ (typename Bits_t<Storage> bits)
751  { return ~BitMask<Storage>(bits); }
752 */
753 
754 //------------------------------------------------------------------------------
755 template <typename Storage>
756 constexpr util::flags::BitMask<Storage> util::flags::Set(Flag_t<Storage> flag)
757  { return BitMask<Storage>(BitMask<Storage>::fromValues, flag, flag); }
758 
759 template <typename Storage>
760 constexpr util::flags::BitMask<Storage> util::flags::Unset(Flag_t<Storage> flag)
761 {
762  return BitMask<Storage>
763  (BitMask<Storage>::fromValues, flag, Bits_t<Storage>(0));
764 }
765 
766 //------------------------------------------------------------------------------
767 
768 
769 
770 #endif // LARDATAOBJ_UTILITIES_BITMASK_TCC