LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
BitMask.h
Go to the documentation of this file.
1 
14 #ifndef LARDATAOBJ_UTILITIES_BITMASK_H
15 #define LARDATAOBJ_UTILITIES_BITMASK_H
16 
17 
18 // C/C++ standard library
19 #include <ostream>
20 #include <string>
21 #include <exception>
22 
23 namespace util {
24 
57  namespace flags {
58 
60  using Index_t = unsigned int;
61 
62  namespace details {
63 
66  template <unsigned int NBits>
68 
70  template <unsigned int NBits>
72 
74  template <typename Storage>
75  constexpr unsigned int computePages(unsigned int bits);
76 
78  template <typename Storage>
79  constexpr Storage makeBits(Index_t index)
80  { return Storage(1) << index; }
81 
82  } // namespace details
83 
84 
85 
86  //--------------------------------------------------------------------------
88  template <typename Storage>
89  struct Flag_t {
90  using Storage_t = Storage;
92 
94 
96  constexpr Flag_t(Index_t flagIndex)
97  : bits(details::makeBits<Storage_t>(flagIndex))
98  {}
99 
101  constexpr Index_t index() const;
102 
111  constexpr Flag_t copy() const { return *this; }
112 
115 
116  constexpr bool operator== (This_t other) const
117  { return bits == other.bits; }
118  constexpr bool operator!= (This_t other) const
119  { return bits != other.bits; }
120  constexpr bool operator< (This_t other) const
121  { return bits < other.bits; }
122  constexpr bool operator> (This_t other) const
123  { return bits > other.bits; }
124  constexpr bool operator<= (This_t other) const
125  { return bits <= other.bits; }
126  constexpr bool operator>= (This_t other) const
127  { return bits >= other.bits; }
128 
130 
131  }; // Flag_t
132 
133 
136  template <typename Storage>
138  { return left == right.index(); }
139  template <typename Storage>
141  { return left.index() == right; }
142 
143  template <typename Storage>
145  { return left != right.index(); }
146  template <typename Storage>
148  { return left.index() != right; }
149 
150  template <typename Storage>
151  constexpr bool operator< (Index_t left, Flag_t<Storage> right)
152  { return left < right.index(); }
153  template <typename Storage>
154  constexpr bool operator< (Flag_t<Storage> left, Index_t right)
155  { return left.index() < right; }
156 
157  template <typename Storage>
158  constexpr bool operator> (Index_t left, Flag_t<Storage> right)
159  { return left > right.index(); }
160  template <typename Storage>
161  constexpr bool operator> (Flag_t<Storage> left, Index_t right)
162  { return left.index() > right; }
163 
164  template <typename Storage>
165  constexpr bool operator<= (Index_t left, Flag_t<Storage> right)
166  { return left <= right.index(); }
167  template <typename Storage>
168  constexpr bool operator<= (Flag_t<Storage> left, Index_t right)
169  { return left.index() <= right; }
170 
171  template <typename Storage>
172  constexpr bool operator>= (Index_t left, Flag_t<Storage> right)
173  { return left >= right.index(); }
174  template <typename Storage>
175  constexpr bool operator>= (Flag_t<Storage> left, Index_t right)
176  { return left.index() >= right; }
177 
179 
181  template <typename Storage>
182  std::ostream& operator<< (std::ostream& out, Flag_t<Storage> flag)
183  { out << '[' << flag.index() << ']'; return out; }
184 
186  template <typename Storage>
187  std::string to_string(Flag_t<Storage> const flag)
188  { return std::to_string(flag.index()); }
189 
190 
191  //--------------------------------------------------------------------------
193  template <typename Storage>
194  struct Bits_t {
195  using Storage_t = Storage;
197 
200 
201  Storage_t data = { 0 };
202 
204  constexpr Bits_t() = default;
205 
207  constexpr Bits_t(Flag_t flag)
208  : data(flag.bits)
209  {}
210 
212  explicit constexpr Bits_t(Storage_t bits)
213  : data(bits)
214  {}
215 
218 
220  constexpr bool empty() const
221  { return data == Storage_t(0); }
222 
224  constexpr bool all(This_t bits) const;
225 
227  constexpr bool any(This_t bits) const;
228 
230  constexpr bool none(This_t bits) const;
231 
233  constexpr bool only(This_t bits) const;
234 
236 
237 
240 
242  void set(This_t bits);
243 
245  void unset(This_t bits);
246 
248  void keepOnly(This_t bits);
249 
251  void clear()
252  { data = 0; }
253 
255 
256 
259 
261  constexpr This_t select(This_t bits) const;
262 
264  constexpr This_t exclude(This_t bits) const;
265 
267  constexpr This_t combine(This_t bits) const;
268 
270  constexpr This_t invert() const;
271 
273 
274 
277 
278  constexpr bool operator== (This_t other) const
279  { return data == other.data; }
280  constexpr bool operator!= (This_t other) const
281  { return data != other.data; }
282  constexpr bool operator< (This_t other) const
283  { return data < other.data; }
284  constexpr bool operator> (This_t other) const
285  { return data > other.data; }
286  constexpr bool operator<= (This_t other) const
287  { return data <= other.data; }
288  constexpr bool operator>= (This_t other) const
289  { return data >= other.data; }
290 
292 
294  explicit constexpr operator bool() const { return bool(data); }
295 
297  constexpr bool operator!() const { return !data; }
298 
299 
301  static void setBits(Storage_t& base, Storage_t bits)
302  { base |= bits; }
303 
306  static void onlyBits(Storage_t& base, Storage_t bits)
307  { base &= bits; }
308 
310  static void unsetBits(Storage_t& base, Storage_t bits)
311  { onlyBits(base, ~bits); }
312 
313  }; // Bits_t
314 
315 
317 
324  template <typename Storage>
326  constexpr Bits_t<Storage> operator|
328 
330  template <typename Storage>
331  constexpr Bits_t<Storage> operator|
333 
335  template <typename Storage>
336  constexpr Bits_t<Storage> operator|
338 
340  template <typename Storage>
341  constexpr Bits_t<Storage> operator|
343 
345  template <typename Storage>
346  constexpr Bits_t<Storage> operator+
348 
350  template <typename Storage>
351  constexpr Bits_t<Storage> operator+
353 
355  template <typename Storage>
356  constexpr Bits_t<Storage> operator+
358 
360  template <typename Storage>
361  constexpr Bits_t<Storage> operator+
363 
365 
366 
367  //--------------------------------------------------------------------------
369  namespace errors {
370 
373 
375  struct Exception: public std::exception {
376  explicit Exception(std::string msg = "Flag error"): message(msg) {}
377  virtual const char* what() const noexcept override
378  { return message.c_str(); }
379  std::string message;
380  }; // Exception
381 
383  struct FlagNotDefined: public Exception {
384  explicit FlagNotDefined(std::string msg = "Flag undefined-flag error")
385  : Exception(msg)
386  {}
387  }; // FlagNotDefined
388 
390  struct OutOfRange: public Exception {
391  explicit OutOfRange(std::string msg = "Flag out-of-range error")
392  : Exception(msg)
393  {}
394  }; // OutOfRange
395 
397 
398  } // namespace errors
399 
400 
402 
405 
419  template <typename Storage>
420  class BitMask {
421 
423  using Storage_t = Storage;
424 
425  public:
426 
428 
430 
432 
434  using Flag_t = typename Bits_t::Flag_t;
435 
438 
441 
444 
447 
449 
451  static constexpr auto fromValues = maskFromValues;
452 
453 
454  // -- BEGIN Constructors from values -------------------------------------
463 
466  explicit constexpr BitMask() = default;
467 
468 
480  constexpr BitMask(BitMaskFromValuesTag, Storage_t defined);
481 
482 
496  constexpr BitMask
497  (BitMaskFromValuesTag, Storage_t defined, Storage_t values);
498 
499 
504  constexpr BitMask(BitMaskFromValuesTag, Bits_t values);
505 
506 
515  constexpr BitMask(BitMaskFromValuesTag, Bits_t defined, Bits_t values);
516 
517 
519  // -- END Constructors from values ---------------------------------------
520 
521 
522  // -- BEGIN Constructors combining flags ---------------------------------
525 
535  template <typename... Others>
536  constexpr BitMask(Flag_t first, Others... others)
537  : BitMask(create(first, others...))
538  {}
539 
549  template <typename... Others>
550  constexpr BitMask(Bits_t first, Others... others)
551  : BitMask(create(first, others...))
552  {}
553 
565  // NOTE: if the first argument passed as reference prevent constexpr,
566  // two separate constructors will be needed;
567  // also note that this works as copy constructor as well
568  template <typename Second, typename... Others>
569  constexpr BitMask(Mask_t first, Second second, Others... others)
570  : BitMask(create(first, second, others...))
571  {}
572 
574  // -- END Constructors combining flags -----------------------------------
575 
576 
577  // -- BEGIN Access to flags ----------------------------------------------
580 
592  constexpr bool isDefined(Flag_t flag) const;
593 
604  constexpr bool isDefined(Bits_t bits) const;
605 
614  constexpr bool isUndefined(Flag_t flag) const;
615 
624  constexpr bool isUndefined(Bits_t bits) const;
625 
635  constexpr bool get(Flag_t flag) const;
636 
646  constexpr bool isSet(Flag_t flag) const;
647 
657  constexpr bool isUnset(Flag_t flag) const;
658 
669  constexpr bool all(Bits_t bits) const;
670 
681  constexpr bool any(Bits_t bits) const;
682 
693  constexpr bool none(Bits_t bits) const;
694 
695 
704  constexpr bool anySet(Mask_t const& mask) const;
705 
714  constexpr bool noneSet(Mask_t const& mask) const;
715 
727  constexpr bool match(Mask_t const& mask) const;
728 
730  // -- END Access to flags ------------------------------------------------
731 
732 
733  // -- BEGIN Setting flags ------------------------------------------------
736 
750  template <typename Flag, typename... OtherFlags>
751  void set(Flag first, OtherFlags... others)
752  { setImpl(first, others...); }
753 
764  template <typename BeginIter, typename EndIter>
765  void rangeSet(BeginIter begin, EndIter end);
766 
778  template <typename Flag, typename... OtherFlags>
779  void unset(Flag first, OtherFlags... others)
780  { unsetImpl(first, others...); }
781 
792  template <typename BeginIter, typename EndIter>
793  void rangeUnset(BeginIter begin, EndIter end);
794 
795 
816  template <typename Flag, typename... OtherFlags>
817  void remove(Flag first, OtherFlags... others)
818  { undefineImpl(first, others...); }
819 
821  void clear()
822  { presence.clear(); values.clear(); }
823 
825  // -- END Setting flags --------------------------------------------------
826 
827 
828  // -- BEGIN Number of flags ----------------------------------------------
831 
833  static constexpr size_t capacity();
834 
836  // -- END Number of flags ------------------------------------------------
837 
840  constexpr bool operator== (Mask_t const& other) const
841  { return (values == other.values) && (presence == other.presence); }
842 
845  constexpr bool operator!= (Mask_t const& other) const
846  { return (values != other.values) || (presence != other.presence); }
847 
848 
850  template <typename Stream>
851  void dump(Stream&& out, unsigned int nBits) const;
852 
854  template <typename Stream>
855  void dump(Stream&& out) const
856  { dump(std::forward<Stream>(out), capacity()); }
857 
858 
859  // -- BEGIN Static mask manipulation -------------------------------------
862 
876  template <typename... Args>
877  static constexpr Mask_t create(Args... args);
878 
901  static constexpr Mask_t mergeIntoMask(Mask_t baseMask, Mask_t mask);
902 
920  static constexpr Mask_t mergeIntoMask(Mask_t baseMask, Bits_t bits);
921 
929  static constexpr Mask_t mergeIntoMask(Mask_t baseMask, Flag_t flag);
930 
961  static constexpr Mask_t combineWithMask(Mask_t A, Mask_t B);
962 
981  static constexpr Mask_t combineWithMask(Mask_t baseMask, Bits_t bits);
982 
989  static constexpr Mask_t combineWithMask(Mask_t baseMask, Flag_t flag);
990 
1016  static constexpr Mask_t intersectWithMask(Mask_t A, Mask_t B);
1017 
1038  static constexpr Mask_t intersectWithMask(Mask_t baseMask, Bits_t bits);
1039 
1046  static constexpr Mask_t intersectWithMask(Mask_t baseMask, Flag_t flag);
1047 
1070  static constexpr Mask_t unsetMask(Mask_t baseMask, Mask_t mask);
1071 
1092  static constexpr Mask_t unsetMask(Mask_t baseMask, Bits_t bits);
1093 
1100  static constexpr Mask_t unsetMask(Mask_t baseMask, Flag_t flag);
1101 
1119  static constexpr Mask_t negateMask(Mask_t mask);
1120 
1128  static constexpr Mask_t negateMask(Bits_t bits);
1129 
1135  static constexpr Mask_t negateMask(Flag_t flag);
1136 
1138  // -- END Static mask manipulation ---------------------------------------
1139 
1140  private:
1141 
1144 
1145  // Storage details
1146  // We store values and definition information in two different bit
1147  // buckets; the same Flag_t pattern is good for both.
1148 
1150  void defineSingle(Flag_t flag);
1151 
1153  void undefineSingle(Flag_t flag);
1154 
1156  void undefineImpl() {}
1157 
1159  template <typename... Flags>
1160  void undefineImpl(Flag_t flag, Flags... others);
1161 
1163  void setImpl() {}
1164 
1166  template <typename... Flags>
1167  void setImpl(Flag_t flag, Flags... others);
1168 
1170  void setSingle(Flag_t flag);
1171 
1173  void unsetImpl() {}
1174 
1176  constexpr Bits_t definedOnly() const;
1177 
1179  template <typename... Flags>
1180  void unsetImpl(Flag_t flag, Flags... others);
1181 
1183  void unsetSingle(Flag_t flag);
1184 
1186  static constexpr bool testBits(Storage_t data, Storage_t bits)
1187  { return data & bits; }
1188 
1190  static constexpr bool testBitmask(Storage_t data, Storage_t mask)
1191  { return (data & mask) == mask; }
1192 
1194  static constexpr bool testUnsetBitmask(Storage_t data, Storage_t mask)
1195  { return (data & ~mask) == data; }
1196 
1197 
1198  }; // BitMask<>
1199 
1200 
1202  template <typename Stream, typename Storage>
1203  Stream& operator<< (Stream&& out, BitMask<Storage> const& mask)
1204  { mask.dump(std::forward<Stream>(out)); return out; }
1205 
1206 
1207  // -- BEGIN Flag and mask management ---------------------------------------
1228 
1230 
1233  template <typename Storage>
1234  constexpr BitMask<Storage> operator|
1236 
1239  template <typename Storage>
1240  constexpr BitMask<Storage> operator|
1242 
1245  template <typename Storage>
1246  constexpr BitMask<Storage> operator|
1248 
1249  // operator|(Bits_t, Bits_t) is still a Bits_t
1250 
1251 
1254  template <typename Storage>
1255  constexpr BitMask<Storage> operator&
1257 
1260  template <typename Storage>
1261  constexpr BitMask<Storage> operator&
1263 
1266  template <typename Storage>
1267  constexpr BitMask<Storage> operator&
1269 
1272  template <typename Storage>
1273  constexpr BitMask<Storage> operator&
1275 
1276 
1279  template <typename Storage>
1280  constexpr BitMask<Storage> operator+
1281  (BitMask<Storage> baseMask, BitMask<Storage> mask);
1282 
1285  template <typename Storage>
1286  constexpr BitMask<Storage> operator+
1287  (BitMask<Storage> baseMask, typename BitMask<Storage>::Bits_t bits);
1288 
1291  template <typename Storage>
1292  constexpr BitMask<Storage> operator+
1293  (typename BitMask<Storage>::Bits_t baseBits, BitMask<Storage> mask);
1294 
1295  // operator+(Bits_t, Bits_t) is still a Bits_t
1296 
1297 
1300  template <typename Storage>
1301  constexpr BitMask<Storage> operator-
1302  (BitMask<Storage> baseMask, BitMask<Storage> mask);
1303 
1306  template <typename Storage>
1307  constexpr BitMask<Storage> operator-
1308  (BitMask<Storage> baseMask, typename BitMask<Storage>::Bits_t bits);
1309 
1312  template <typename Storage>
1313  constexpr BitMask<Storage> operator-
1314  (typename BitMask<Storage>::Bits_t baseBits, BitMask<Storage> mask);
1315 
1318  template <typename Storage>
1319  constexpr BitMask<Storage> operator-
1320  (Bits_t<Storage> baseBits, Bits_t<Storage> bits);
1321 
1322 
1324  template <typename Storage>
1326 
1328  template <typename Storage>
1330 
1331 
1333  template <typename Storage>
1335 
1337  template <typename Storage>
1339 
1340 
1342  template <typename Storage>
1343  constexpr BitMask<Storage> operator~
1344  (BitMask<Storage> mask);
1345 
1346  /*
1348  template <typename Storage>
1349  constexpr BitMask<Storage> operator~ (Bits_t<Storage> bits);
1350  */
1351 
1352 
1354  template <typename Storage>
1355  constexpr BitMask<Storage> Set(Flag_t<Storage> flag);
1356 
1358  template <typename Storage>
1359  constexpr BitMask<Storage> Unset(Flag_t<Storage> flag);
1360 
1361 
1363  // -- END Flag and mask management -----------------------------------------
1364 
1366  template <typename Storage>
1367  constexpr BitMask<Storage> makeMask(Bits_t<Storage> bits);
1368 
1369 
1370  } // namespace flags
1371 
1372 } // namespace util
1373 
1374 
1375 //------------------------------------------------------------------------------
1376 //--- template implementation
1377 //---
1378 
1380 
1381 //------------------------------------------------------------------------------
1382 
1383 
1384 #endif // LARDATAOBJ_UTILITIES_BITMASK_H
typename Bits_t::Flag_t Flag_t
Type identifying a single flag.
Definition: BitMask.h:434
Storage_t bits
The bits representing this flag (only one is set)
Definition: BitMask.h:93
constexpr unsigned int computePages(unsigned int bits)
Returns the number of Storage variables needed to hold that many bits.
constexpr Bits_t(Flag_t flag)
Constructs from a single flag.
Definition: BitMask.h:207
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:17
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
typename SmallestUIntType< NBits >::type smallestUInt_t
The smallest integral type accommodating NBits bits.
Definition: BitMask.h:71
constexpr bool operator<(Index_t left, Flag_t< Storage > right)
Definition: BitMask.h:151
constexpr bool operator>(Index_t left, Flag_t< Storage > right)
Definition: BitMask.h:158
constexpr bool operator<=(Index_t left, Flag_t< Storage > right)
Definition: BitMask.h:165
Int_t B
Definition: plot.C:25
Base class for exceptions thrown by flag-related utilities.
Definition: BitMask.h:375
FlagNotDefined(std::string msg="Flag undefined-flag error")
Definition: BitMask.h:384
Type identifying a flag. Operations are implemented as free functions.
Definition: BitMask.h:89
static void onlyBits(Storage_t &base, Storage_t bits)
Definition: BitMask.h:306
void unsetImpl()
Implementation detail of unset()
Definition: BitMask.h:1173
constexpr bool operator>=(Index_t left, Flag_t< Storage > right)
Definition: BitMask.h:172
unsigned int Index_t
Type to denote the index of the flag.
Definition: BitMask.h:60
util::flags::Index_t FlagIndex_t
Type of index of flag.
Definition: BitMask.h:429
void dump(Stream &&out) const
Prints into the specified stream all bits.
Definition: BitMask.h:855
Type for constructor tag from values.
Definition: BitMask.h:401
static constexpr bool testUnsetBitmask(Storage_t data, Storage_t mask)
Returns whether all the specified bits in the mask are set.
Definition: BitMask.h:1194
static constexpr bool testBits(Storage_t data, Storage_t bits)
Returns whether any of the specified bits is set.
Definition: BitMask.h:1186
constexpr BitMask< Storage > operator-(BitMask< Storage > baseMask, BitMask< Storage > mask)
A class containing a set of flags.
Definition: BitMask.h:420
constexpr Storage makeBits(Index_t index)
Returns a set of bits with only the one at the specified index set.
Definition: BitMask.h:79
constexpr bool empty() const
Returns whether there is no bit set at all.
Definition: BitMask.h:220
constexpr Flag_t(Index_t flagIndex)
Constructs from the flag index.
Definition: BitMask.h:96
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
constexpr BitMask< Storage > Set(Flag_t< Storage > flag)
Returns a bit mask which sets the specified flag.
static void setBits(Storage_t &base, Storage_t bits)
Returns data with all bits from base and from bits set.
Definition: BitMask.h:301
Storage Storage_t
Type of underlying bit data representation.
Definition: BitMask.h:423
Storage Storage_t
Definition: BitMask.h:90
void clear()
Unsets all bits.
Definition: BitMask.h:251
bool invert(ublas::matrix< T, L, A > &m)
constexpr Bits_t< Storage > operator+(Bits_t< Storage > left, Bits_t< Storage > right)
Returns a new Bits_t with all the bits from both arguments set.
static constexpr bool testBitmask(Storage_t data, Storage_t mask)
Returns whether all the specified bits in the mask are set.
Definition: BitMask.h:1190
constexpr bool operator!=(Index_t left, Flag_t< Storage > right)
Definition: BitMask.h:144
Type identifying a set of bits.
Definition: BitMask.h:194
constexpr BitMask< Storage > makeMask(Bits_t< Storage > bits)
Constructs a mask from bits.
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
constexpr bool operator==(Index_t left, Flag_t< Storage > right)
Definition: BitMask.h:137
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:104
constexpr BitMask(Bits_t first, Others...others)
Constructor: merges all arguments in the argument list.
Definition: BitMask.h:550
void unset(Flag first, OtherFlags...others)
Unsets all specified flags.
Definition: BitMask.h:779
constexpr BitMask(Flag_t first, Others...others)
Constructor: merges all arguments in the argument list.
Definition: BitMask.h:536
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
virtual const char * what() const noexcept override
Definition: BitMask.h:377
static void unsetBits(Storage_t &base, Storage_t bits)
Returns data with all bits from base, but the ones from bits unset.
Definition: BitMask.h:310
Exception(std::string msg="Flag error")
Definition: BitMask.h:376
util::flags::Flag_t< Storage_t > Flag_t
Type of flag matching our storage.
Definition: BitMask.h:199
Bits_t values
Storage of value bits.
Definition: BitMask.h:1142
constexpr Bits_t(Storage_t bits)
Constructs from a set of bits.
Definition: BitMask.h:212
void setImpl()
Implementation detail of set()
Definition: BitMask.h:1163
Exception thrown to convey that an invalid flag index was used.
Definition: BitMask.h:390
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
constexpr BitMaskFromValuesTag maskFromValues
Value useful for BitMask constructors from value.
Definition: BitMask.h:404
Bits_t presence
Storage of definition bits.
Definition: BitMask.h:1143
void clear()
Undefines all bits.
Definition: BitMask.h:821
OutOfRange(std::string msg="Flag out-of-range error")
Definition: BitMask.h:391
Storage_t data
The bits representing all set bits.
Definition: BitMask.h:201
constexpr Flag_t copy() const
Returns a copy of this object.
Definition: BitMask.h:111
constexpr Index_t index() const
Returns the index of the (first) bit set.
Exception thrown to convey that an undefined flag index was tested.
Definition: BitMask.h:383
constexpr BitMask< Storage > Unset(Flag_t< Storage > flag)
Returns a bit mask which unsets the specified flag.
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
void undefineImpl()
Implementation detail of remove()
Definition: BitMask.h:1156
constexpr bool operator!() const
Returns true if there is no bit set.
Definition: BitMask.h:297
constexpr BitMask(Mask_t first, Second second, Others...others)
Constructor: merges all arguments in the argument list.
Definition: BitMask.h:569