GEOSX
ComponentMask.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University
7  * Copyright (c) 2018-2020 TotalEnergies
8  * Copyright (c) 2019- GEOSX Contributors
9  * All rights reserved
10  *
11  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
12  * ------------------------------------------------------------------------------------------------------------
13  */
14 
19 #ifndef GEOS_LINEARALGEBRA_UTILITIES_COMPONENTMASK_HPP_
20 #define GEOS_LINEARALGEBRA_UTILITIES_COMPONENTMASK_HPP_
21 
22 #include "common/GeosxMacros.hpp"
23 #include "common/Logger.hpp"
24 
25 #include <cstdint>
26 
27 namespace geos
28 {
29 
30 namespace internal
31 {
32 
34 template< typename T >
35 constexpr bool always_false( T )
36 {
37  return false;
38 }
39 
40 template< int N >
41 struct ComponentMaskType
42 {
43  static_assert( always_false( N ), "Unsupported template parameter N for ComponentMask. Use a value between 8 and 64." );
44 };
45 
49 #define GEOS_LAI_COMPONENTMASK_DECL( N ) \
50  template<> \
51  struct ComponentMaskType< N > \
52  { \
53  using type = std::uint ## N ## _t; \
54  }
55 
60 
61 #undef GEOS_LAI_COMPONENTMASK_DECL
62 
63 constexpr std::uint32_t roundToNextPowerOfTwo( std::uint32_t v )
64 {
65  if( v <= 8 ) return 8;
66  v--;
67  v |= v >> 1;
68  v |= v >> 2;
69  v |= v >> 4;
70  v |= v >> 8;
71  v |= v >> 16;
72  v++;
73  return v;
74 }
75 
76 }
77 
88 template< int MAX_COMP >
90 {
91 private:
92 
94  static constexpr int NUM_BITS = internal::roundToNextPowerOfTwo( MAX_COMP );
95 
97  using mask_t = typename internal::ComponentMaskType< NUM_BITS >::type;
98 
99 public:
100 
105 
112  ComponentMask( int const numComp, bool const includeAll )
113  : m_mask( includeAll ? -1 : 0 )
114  {
115  setNumComp( numComp );
116  }
117 
123  explicit ComponentMask( int const numComp = 0 )
124  : ComponentMask( numComp, false )
125  {}
126 
135  ComponentMask( int const numComp, int const lo, int const hi )
137  {
138  for( int i = lo; i < hi; ++i )
139  {
140  set( i );
141  }
142  }
143 
149  template< int N, typename = std::enable_if_t< ( N < MAX_COMP ) > >
150  GEOS_HOST_DEVICE
151  ComponentMask( ComponentMask< N > const & other )
152  : m_numComp( other.numComp() )
153  {
154  for( int i : other )
155  {
156  set( i );
157  }
158  }
159 
161 
166 
171  class Iterator
172  {
173 public:
174 
175  using difference_type = int;
176  using value_type = int;
177  using pointer = void;
178  using reference = int;
179  using iterator_category = std::forward_iterator_tag;
180 
185  GEOS_HOST_DEVICE
186  GEOS_FORCE_INLINE
187  reference operator*() const
188  {
189  return m_index;
190  }
191 
196  GEOS_HOST_DEVICE
197  GEOS_FORCE_INLINE
198  Iterator & operator++()
199  {
200  GEOS_ASSERT_NE( m_mask, 0 );
201  skipOne();
202  findNextBit();
203  return *this;
204  }
205 
210  GEOS_HOST_DEVICE
211  GEOS_FORCE_INLINE
212  Iterator operator++( int ) &
213  {
214  Iterator old = *this;
215  ++*this;
216  return old;
217  }
218 
224  GEOS_HOST_DEVICE
225  GEOS_FORCE_INLINE
226  bool operator==( Iterator const & other ) const
227  {
228  return m_mask == other.m_mask;
229  }
230 
236  GEOS_HOST_DEVICE
237  GEOS_FORCE_INLINE
238  bool operator!=( Iterator const & other ) const
239  {
240  return !(*this == other);
241  }
242 
243 private:
244 
245  GEOS_HOST_DEVICE
246  inline
247  void skipOne()
248  {
249  m_mask >>= 1;
250  ++m_index;
251  }
252 
255  void findNextBit()
256  {
257  if( m_mask )
258  {
259  // TODO: use hardware intrinsics (ffs/ctz) where possible
260  while( !( m_mask & 1 ) )
261  {
262  skipOne();
263  }
264  }
265  }
266 
268  Iterator( mask_t const mask, int const index )
269  : m_mask( mask ),
270  m_index( index )
271  {
272  findNextBit();
273  }
274 
275  friend class ComponentMask;
276 
277  mask_t m_mask;
278  int m_index;
279  };
280 
285  Iterator begin() const
286  {
287  return Iterator( m_mask, 0 );
288  }
289 
294  Iterator end() const
295  {
296  return Iterator( 0, -1 );
297  }
298 
303  int size() const
304  {
305  mask_t mask = m_mask;
306  int c = 0;
307  for(; mask != 0; ++c )
308  {
309  mask &= mask - 1;
310  }
311  return c;
312  }
313 
318  int numComp() const
319  {
320  return m_numComp;
321  }
322 
327  bool empty() const
328  {
329  return m_mask == 0;
330  }
331 
338  bool operator[]( int const i ) const
339  {
340  GEOS_ASSERT_GT( m_numComp, i );
341  return m_mask & (mask_t( 1 ) << i);
342  }
343 
345 
350 
355  void clear()
356  {
357  m_mask = 0;
358  }
359 
365  void setNumComp( int const numComp )
366  {
367  GEOS_ASSERT_GE( numComp, 0 );
368  GEOS_ASSERT_GE( MAX_COMP, numComp );
369  m_numComp = numComp;
370  if( numComp < NUM_BITS )
371  {
372  m_mask &= ( mask_t( 1 ) << numComp ) - 1;
373  }
374  }
375 
381  void set( int const i )
382  {
383  GEOS_ASSERT_GE( i, 0 );
384  GEOS_ASSERT_GT( m_numComp, i );
385  m_mask |= mask_t( 1 ) << i;
386  }
387 
393  void unset( int const i )
394  {
395  GEOS_ASSERT_GE( i, 0 );
396  GEOS_ASSERT_GT( m_numComp, i );
397  m_mask &= ~(mask_t( 1 ) << i);
398  }
399 
404  void invert()
405  {
406  m_mask = ~m_mask;
407  setNumComp( m_numComp );
408  }
409 
416  ComponentMask & operator+=( int const i )
417  {
418  set( i );
419  return *this;
420  }
421 
428  ComponentMask & operator-=( int const i )
429  {
430  unset( i );
431  return *this;
432  }
433 
440  {
441  ComponentMask mask( *this );
442  mask.invert();
443  return mask;
444  }
445 
453  friend ComponentMask operator+( ComponentMask const & mask, int const i )
454  {
455  ComponentMask new_mask = mask;
456  new_mask += i;
457  return new_mask;
458  }
459 
467  friend ComponentMask operator+( int const i, ComponentMask const & mask )
468  {
469  return mask + i;
470  }
471 
479  friend ComponentMask operator-( ComponentMask const & mask, int const i )
480  {
481  ComponentMask new_mask = mask;
482  new_mask -= i;
483  return new_mask;
484  }
485 
493  friend ComponentMask operator-( int const i, ComponentMask const & mask )
494  {
495  return mask - i;
496  }
497 
499 
500 private:
501 
503  mask_t m_mask = 0;
504 
506  int m_numComp = MAX_COMP;
507 };
508 
509 }
510 
511 #endif //GEOS_LINEARALGEBRA_UTILITIES_COMPONENTMASK_HPP_
#define GEOS_LAI_COMPONENTMASK_DECL(N)
Macro for declaring a specialization of ComponentMaskTypeImpl template.
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:48
#define GEOS_FORCE_INLINE
Marks a function or lambda for inlining.
Definition: GeosxMacros.hpp:50
#define GEOS_ASSERT_GT(lhs, rhs)
Assert that one value compares greater than the other in debug builds.
Definition: Logger.hpp:405
#define GEOS_ASSERT_GE(lhs, rhs)
Assert that one value compares greater than or equal to the other in debug builds.
Definition: Logger.hpp:420
Forward const iterator over the set components (bits).
Utility class that represents a mask for included/excluded component of a mask.
GEOS_HOST_DEVICE bool empty() const
GEOS_HOST_DEVICE void invert()
Invert component selection.
GEOS_HOST_DEVICE int numComp() const
GEOS_HOST_DEVICE void clear()
Clear the mask, removing selected components.
GEOS_HOST_DEVICE void unset(int const i)
Remove a component.
GEOS_HOST_DEVICE bool operator[](int const i) const
Check if a particular component is selected.
GEOS_HOST_DEVICE ComponentMask & operator-=(int const i)
Remove a component.
GEOS_HOST_DEVICE ComponentMask operator~() const
Negation operator (inverts component selection).
GEOS_HOST_DEVICE ComponentMask(int const numComp, int const lo, int const hi)
Range constructor, includes contiguous range of components.
GEOS_HOST_DEVICE Iterator end() const
GEOS_HOST_DEVICE ComponentMask(int const numComp, bool const includeAll)
Constructor.
GEOS_HOST_DEVICE int size() const
GEOS_HOST_DEVICE void setNumComp(int const numComp)
Set new component limit and truncate all components above.
GEOS_HOST_DEVICE void set(int const i)
Add a component.
GEOS_HOST_DEVICE Iterator begin() const
GEOS_HOST_DEVICE ComponentMask & operator+=(int const i)
Add a component.
GEOS_HOST_DEVICE ComponentMask(int const numComp=0)
Constructor.
GEOS_HOST_DEVICE friend ComponentMask operator+(int const i, ComponentMask const &mask)
Make a new mask by adding a component.
GEOS_HOST_DEVICE friend ComponentMask operator-(ComponentMask const &mask, int const i)
Make a new mask by removing a component.
GEOS_HOST_DEVICE friend ComponentMask operator+(ComponentMask const &mask, int const i)
Make a new mask by adding a component.
GEOS_HOST_DEVICE friend ComponentMask operator-(int const i, ComponentMask const &mask)
Make a new mask by removing a component.
std::set< T > set
A set of local indices.
Definition: DataTypes.hpp:303