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