GEOS
ComponentMask.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 TotalEnergies
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
20 #ifndef GEOS_LINEARALGEBRA_UTILITIES_COMPONENTMASK_HPP_
21 #define GEOS_LINEARALGEBRA_UTILITIES_COMPONENTMASK_HPP_
22 
23 #include "common/GeosxMacros.hpp"
24 #include "common/logger/Logger.hpp"
25 
26 #include <cstdint>
27 
28 namespace geos
29 {
30 
31 namespace internal
32 {
33 
35 template< typename T >
36 constexpr bool always_false( T )
37 {
38  return false;
39 }
40 
41 template< int N >
42 struct ComponentMaskType
43 {
44  static_assert( always_false( N ), "Unsupported template parameter N for ComponentMask. Use a value between 8 and 64." );
45 };
46 
50 #define GEOS_LAI_COMPONENTMASK_DECL( N ) \
51  template<> \
52  struct ComponentMaskType< N > \
53  { \
54  using type = std::uint ## N ## _t; \
55  }
56 
61 
62 #undef GEOS_LAI_COMPONENTMASK_DECL
63 
64 constexpr std::uint32_t roundToNextPowerOfTwo( std::uint32_t v )
65 {
66  if( v <= 8 ) return 8;
67  v--;
68  v |= v >> 1;
69  v |= v >> 2;
70  v |= v >> 4;
71  v |= v >> 8;
72  v |= v >> 16;
73  v++;
74  return v;
75 }
76 
77 }
78 
89 template< int MAX_COMP >
91 {
92 private:
93 
95  static constexpr int NUM_BITS = internal::roundToNextPowerOfTwo( MAX_COMP );
96 
98  using mask_t = typename internal::ComponentMaskType< NUM_BITS >::type;
99 
100 public:
101 
106 
113  ComponentMask( int const numComp, bool const includeAll )
114  : m_mask( includeAll ? -1 : 0 )
115  {
116  setNumComp( numComp );
117  }
118 
124  explicit ComponentMask( int const numComp = 0 )
125  : ComponentMask( numComp, false )
126  {}
127 
136  ComponentMask( int const numComp, int const lo, int const hi )
138  {
139  for( int i = lo; i < hi; ++i )
140  {
141  set( i );
142  }
143  }
144 
150  template< int N, typename = std::enable_if_t< ( N < MAX_COMP ) > >
151  GEOS_HOST_DEVICE
152  ComponentMask( ComponentMask< N > const & other )
153  : m_numComp( other.numComp() )
154  {
155  for( int i : other )
156  {
157  set( i );
158  }
159  }
160 
162 
167 
172  class Iterator
173  {
174 public:
175 
176  using difference_type = int;
177  using value_type = int;
178  using pointer = void;
179  using reference = int;
180  using iterator_category = std::forward_iterator_tag;
181 
186  GEOS_HOST_DEVICE
187  GEOS_FORCE_INLINE
188  reference operator*() const
189  {
190  return m_index;
191  }
192 
197  GEOS_HOST_DEVICE
198  GEOS_FORCE_INLINE
199  Iterator & operator++()
200  {
201  GEOS_ASSERT_NE( m_mask, 0 );
202  skipOne();
203  findNextBit();
204  return *this;
205  }
206 
211  GEOS_HOST_DEVICE
212  GEOS_FORCE_INLINE
213  Iterator operator++( int ) &
214  {
215  Iterator old = *this;
216  ++*this;
217  return old;
218  }
219 
225  GEOS_HOST_DEVICE
226  GEOS_FORCE_INLINE
227  bool operator==( Iterator const & other ) const
228  {
229  return m_mask == other.m_mask;
230  }
231 
237  GEOS_HOST_DEVICE
238  GEOS_FORCE_INLINE
239  bool operator!=( Iterator const & other ) const
240  {
241  return !(*this == other);
242  }
243 
244 private:
245 
246  GEOS_HOST_DEVICE
247  inline
248  void skipOne()
249  {
250  m_mask >>= 1;
251  ++m_index;
252  }
253 
256  void findNextBit()
257  {
258  if( m_mask )
259  {
260  // TODO: use hardware intrinsics (ffs/ctz) where possible
261  while( !( m_mask & 1 ) )
262  {
263  skipOne();
264  }
265  }
266  }
267 
269  Iterator( mask_t const mask, int const index )
270  : m_mask( mask ),
271  m_index( index )
272  {
273  findNextBit();
274  }
275 
276  friend class ComponentMask;
277 
278  mask_t m_mask;
279  int m_index;
280  };
281 
286  Iterator begin() const
287  {
288  return Iterator( m_mask, 0 );
289  }
290 
295  Iterator end() const
296  {
297  return Iterator( 0, -1 );
298  }
299 
304  int size() const
305  {
306  mask_t mask = m_mask;
307  int c = 0;
308  for(; mask != 0; ++c )
309  {
310  mask &= mask - 1;
311  }
312  return c;
313  }
314 
319  int numComp() const
320  {
321  return m_numComp;
322  }
323 
328  bool empty() const
329  {
330  return m_mask == 0;
331  }
332 
339  bool operator[]( int const i ) const
340  {
341  GEOS_ASSERT_GT( m_numComp, i );
342  return m_mask & (mask_t( 1 ) << i);
343  }
344 
346 
351 
356  void clear()
357  {
358  m_mask = 0;
359  }
360 
366  void setNumComp( int const numComp )
367  {
368  GEOS_ASSERT_GE( numComp, 0 );
369  GEOS_ASSERT_GE( MAX_COMP, numComp );
370  m_numComp = numComp;
371  if( numComp < NUM_BITS )
372  {
373  m_mask &= ( mask_t( 1 ) << numComp ) - 1;
374  }
375  }
376 
382  void set( int const i )
383  {
384  GEOS_ASSERT_GE( i, 0 );
385  GEOS_ASSERT_GT( m_numComp, i );
386  m_mask |= mask_t( 1 ) << i;
387  }
388 
394  void unset( int const i )
395  {
396  GEOS_ASSERT_GE( i, 0 );
397  GEOS_ASSERT_GT( m_numComp, i );
398  m_mask &= ~(mask_t( 1 ) << i);
399  }
400 
405  void invert()
406  {
407  m_mask = ~m_mask;
408  setNumComp( m_numComp );
409  }
410 
417  ComponentMask & operator+=( int const i )
418  {
419  set( i );
420  return *this;
421  }
422 
429  ComponentMask & operator-=( int const i )
430  {
431  unset( i );
432  return *this;
433  }
434 
441  {
442  ComponentMask mask( *this );
443  mask.invert();
444  return mask;
445  }
446 
454  friend ComponentMask operator+( ComponentMask const & mask, int const i )
455  {
456  ComponentMask new_mask = mask;
457  new_mask += i;
458  return new_mask;
459  }
460 
468  friend ComponentMask operator+( int const i, ComponentMask const & mask )
469  {
470  return mask + i;
471  }
472 
480  friend ComponentMask operator-( ComponentMask const & mask, int const i )
481  {
482  ComponentMask new_mask = mask;
483  new_mask -= i;
484  return new_mask;
485  }
486 
494  friend ComponentMask operator-( int const i, ComponentMask const & mask )
495  {
496  return mask - i;
497  }
498 
500 
501 private:
502 
504  mask_t m_mask = 0;
505 
507  int m_numComp = MAX_COMP;
508 };
509 
510 }
511 
512 #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:49
#define GEOS_FORCE_INLINE
Marks a function or lambda for inlining.
Definition: GeosxMacros.hpp:51
#define GEOS_ASSERT_GT(lhs, rhs)
Assert that one value compares greater than the other in debug builds.
Definition: Logger.hpp:440
#define GEOS_ASSERT_GE(lhs, rhs)
Assert that one value compares greater than or equal to the other in debug builds.
Definition: Logger.hpp:455
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:263