File: bitarray.hpp

package info (click to toggle)
netgen 6.2.2601%2Bdfsg1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,076 kB
  • sloc: cpp: 166,627; tcl: 6,310; python: 2,868; sh: 528; makefile: 90
file content (240 lines) | stat: -rw-r--r-- 5,319 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#ifndef NETGEN_CORE_BITARRAY
#define NETGEN_CORE_BITARRAY

/**************************************************************************/
/* File:   bitarray.hpp                                                   */
/* Author: Joachim Schoeberl                                              */
/* Date:   01. Jun. 95                                                    */
/**************************************************************************/

#include <climits>
#include <cstring>
#include <ostream>

#include "array.hpp"
#include "localheap.hpp"
#include "ngcore_api.hpp"
#include "utils.hpp"

namespace ngcore
{

/**
   A compressed array of bools.

   Provides bit-operations and whole array operations.
*/
class BitArray
{
protected:
  /// number of bits
  size_t size;

  /// the data
  unsigned char * data;
  ///
  bool owns_data = true;
public:
  /// empty array
  BitArray ()
    : size(0), data(nullptr) { ; }
  /// array of asize bits
  NGCORE_API BitArray (size_t asize);
  /// array of asize bits
  NGCORE_API BitArray (size_t asize, LocalHeap & lh);
  ///
  NGCORE_API BitArray (const BitArray & ba2);
  BitArray (BitArray && ba2)
    : size(ba2.size), data(ba2.data), owns_data(ba2.owns_data)
  {
    ba2.owns_data = false;
    ba2.data = nullptr;
    mt = std::move(ba2.mt);
  }

  template <typename T>
  NETGEN_INLINE BitArray (std::initializer_list<T> list)
    : BitArray (list.size())
  {
    Clear();
    int cnt = 0;
    for (auto i = list.begin(); i < list.end(); i++, cnt++)
      if (*i) SetBit(cnt);
    StartMemoryTracing();
  }

  /// delete data
  ~BitArray ()
  {
    if (owns_data)
    {
      delete [] data;
      mt.Free(GetMemoryUsage());
    }
  }

  /// Set size, loose values
  NGCORE_API void SetSize (size_t asize);

  /// the size
  size_t Size () const { return size; }

  /// set all bits
  NGCORE_API BitArray & Set () throw();

  /// clear all bits
  NGCORE_API BitArray & Clear () throw();

  /// set bit i
  [[deprecated("Use either SetBit() or SetBitAtomic()")]]
  void Set (size_t i) { SetBitAtomic(i); }

  /// set bit i ( not thread safe )
  void SetBit (size_t i)
  {
    NETGEN_CHECK_RANGE(i, 0, size);
    data[Addr(i)] |= Mask(i);
  }

  /// set bit i ( thread safe )
  void SetBitAtomic (size_t i)
  {
    NETGEN_CHECK_RANGE(i, 0, size);
    unsigned char * p = data+Addr(i);
    unsigned char mask = Mask(i);

    AsAtomic(*p) |= mask;
  }

  /// clear bit i
  void Clear (size_t i)
  {
    NETGEN_CHECK_RANGE(i, 0, size);
    data[Addr(i)] &= ~Mask(i);
  }

  /// check bit i
  bool Test (size_t i) const
  {
    NETGEN_CHECK_RANGE(i, 0, size);
    return (data[Addr(i)] & Mask(i)) ? true : false;
  }

  /// set all bits to b
  BitArray & operator= (bool b)
  {
    if (b) Set();
    else   Clear();
    return *this;
  }

  /// check bit i
  bool operator[] (size_t i) const
  {
    NETGEN_CHECK_RANGE(i, 0, size);
    return Test(i);
  }

  NGCORE_API bool operator==(const BitArray& other) const;

  /// invert all bits
  NGCORE_API BitArray & Invert ();

  /// logical AND with ba2
  NGCORE_API BitArray & And (const BitArray & ba2);

  /// logical OR with ba2
  NGCORE_API BitArray & Or (const BitArray & ba2);

  /// copy from ba2
  NGCORE_API BitArray & operator= (const BitArray & ba2);

  NGCORE_API size_t NumSet () const;

  NGCORE_API void DoArchive(class Archive& archive);
  
  NGCORE_API auto * Data() const { return data; }

  size_t GetMemoryUsage() const { return owns_data ? (size+CHAR_BIT-1)/CHAR_BIT : 0; }
  const MemoryTracer& GetMemoryTracer() const { return mt; }
  void StartMemoryTracing() const
  {
    mt.Alloc(GetMemoryUsage());
  }

private:
  ///
  unsigned char Mask (size_t i) const
  { return char(1) << (i % CHAR_BIT); }

  ///
  size_t Addr (size_t i) const
  { return (i / CHAR_BIT); }

  MemoryTracer mt;
};


  inline BitArray & operator|= (BitArray & me, const BitArray & you)
  {
    me.Or(you);
    return me;
  }

  inline BitArray & operator&= (BitArray & me, const BitArray & you)
  {
    me.And(you);
    return me;
  }

  inline BitArray operator| (const BitArray & a, const BitArray & b)
  {
    BitArray res = a;
    res |= b;
    return res;
  }

  inline BitArray operator& (const BitArray & a, const BitArray & b)
  {
    BitArray res = a;
    res &= b;
    return res;
  }

  inline BitArray operator~ (const BitArray & a)
  {
    BitArray res = a;
    res.Invert();
    return res;
  }

  NGCORE_API std::ostream & operator<<(std::ostream & s, const BitArray & ba);



  template <typename IndexType>
  class TBitArray : public BitArray
  {
  public:
    using BitArray::BitArray;

    void SetBit (IndexType i) { BitArray::SetBit(i-IndexBASE<IndexType>()); }
    void Clear () { BitArray::Clear(); }
    void Clear (IndexType i) { BitArray::Clear(i-IndexBASE<IndexType>()); }
    void SetBitAtomic (IndexType i) { BitArray::SetBitAtomic(i-IndexBASE<IndexType>()); }
    bool Test (IndexType i) const { return BitArray::Test(i-IndexBASE<IndexType>()); }
    
    bool operator[] (IndexType i) const { return Test(i); } 
    T_Range<IndexType> Range() const { return { IndexBASE<IndexType>(), IndexBASE<IndexType>()+Size() }; }
    NGCORE_API TBitArray & Or (const TBitArray & ba2)
    {
      BitArray::Or(ba2);
      return *this;
    }

  };

} // namespace ngcore

  
#endif // NETGEN_CORE_BITARRAY