API Documentation
Loading...
Searching...
No Matches
BoolBuffer.hpp
Go to the documentation of this file.
1/**--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Base
28File: BoolBuffer
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/ObjectAllocator.h>
34#include <NDEVR/BitReference.h>
35#include <NDEVR/BitIterator.h>
36namespace NDEVR
37{
38 #define bitset_wrd(pos) ((pos) >> 3)
39 #define bitset_idx(pos) ((pos) & 7)
40 #define bitmaskt(nbits,type) ((nbits) ? ~(type)0 >> (sizeof(type)*8-(nbits)): (type)0)
41 #define bitmask(nbits) cast<uint01>(bitmaskt(nbits,uint32_t))
42 template<class t_index_type>
43 class BufferAllocator<bool, t_index_type, false>
44 {
45 public:
46 explicit BufferAllocator()
47 : m_buffer(nullptr)
48 , m_filled_size(0)
50 {}
51
52 BufferAllocator(BufferAllocator&& allocator) noexcept
53 : m_buffer(nullptr)
54 , m_filled_size(0)
56 {
57 std::swap(allocator.m_buffer, m_buffer);
58 std::swap(allocator.m_filled_size, m_filled_size);
59 std::swap(allocator.m_allocated_size, m_allocated_size);
60 }
62 {
63 if (m_allocated_size != 0)
64 free(m_buffer);
65 }
66 template<bool t_managed>
67 void createSpace(t_index_type size)
68 {
69 m_filled_size += size;
71 }
72 template<bool t_managed>
73 void createSpace(t_index_type location, t_index_type size)
74 {
76 bitmove(begin() + location + size, begin() + location, m_filled_size - (size + location));
77 }
78 void addLast()
79 {
81 }
83 {
85 }
86 void addIndex()
87 {
89 }
90 void addIndex(t_index_type location)
91 {
92 lib_assert(location <= m_filled_size, "Out of bounds add all");
94 bitmove(begin() + location + 1, begin() + location, (m_filled_size - location - 1));
95 }
96 void removeIndex(t_index_type location)
97 {
98 lib_assert(location <= m_filled_size, "Out of bounds add all");
99 bitmove(begin() + location, begin() + location + 1, (m_filled_size - location));
101 }
102 sint04 compare(const BufferAllocator& allocator) const
103 {
104 t_index_type min_size = bitset_wrd(getMin(allocator.filledSize(), filledSize()));
105 sint04 cmp_value = cast<sint04>(memcmp(m_buffer, allocator.m_buffer, min_size));
106 return cmp_value;
107 }
108 sint04 compare(const BufferAllocator& allocator, t_index_type start, t_index_type end) const
109 {
110 sint04 cmp_value = memcmp(&(m_buffer[start]), &(allocator.m_buffer[start]), getMin(allocator.filledSize(), filledSize(), end));
111 return cmp_value;
112 }
113 void swap(t_index_type index_a, t_index_type index_b)
114 {
115 std::swap(m_buffer[index_a], m_buffer[index_b]);
116 }
117 void clear()
118 {
119 m_filled_size = 0;
120 }
121 void setSize(t_index_type size)
122 {
123 m_filled_size = size;
125 }
126 BitReference get(t_index_type index)
127 {
128 lib_assert(index < m_filled_size, "Array out of bounds");
129 return BitReference(m_buffer[bitset_wrd(index)], bitset_idx(index));
130 }
131 bool get(t_index_type index) const
132 {
133 lib_assert(index < m_filled_size, "Array out of bounds");
134 return m_buffer[bitset_wrd(index)][bitset_idx(index)];
135 }
137 {
138 return BitIterator(m_buffer, 0);
139 }
141 {
142 return ConstBitIterator(m_buffer, 0);
143 }
144 BitIterator begin(t_index_type index) const
145 {
146 return BitIterator(m_buffer, cast<sint04>(index));
147 }
148
149 t_index_type capacity() const
150 {
151 return m_allocated_size;
152 }
154 {
156 }
158 {
160 }
161 BitIterator end(t_index_type index)
162 {
163 return BitIterator(m_buffer, m_filled_size - index);
164 }
165
167 {
168 return m_buffer;
169 }
170
171 const BitFlag* ptr() const
172 {
173 return m_buffer;
174 }
175 t_index_type memSize() const
176 {
177 if (m_filled_size == 0)
178 return 0;
179 return bitset_wrd(m_filled_size - 1) + 1;
180 }
181 void setAll(const bool& object, t_index_type offset, t_index_type size)
182 {
183 if (size == 0)
184 return;
185
186 t_index_type first_word = bitset_wrd(offset);
187 t_index_type last_word = bitset_wrd(offset + size - 1);
188 t_index_type foffset = bitset_idx(offset);
189 t_index_type loffset = bitset_idx(offset + size - 1);
190
191 if (first_word == last_word)
192 {
193 uint01 mask = bitmask(size) << foffset;
194 if(object)
195 m_buffer[first_word] |= BitFlag(mask);
196 else
197 m_buffer[first_word] &= BitFlag(~mask);
198 }
199 else
200 {
201 // Set first word
202 if (object)
203 m_buffer[first_word] |= BitFlag(~bitmask(foffset));
204 else
205 m_buffer[first_word] &= BitFlag(bitmask(foffset));
206 memset(m_buffer + first_word + 1, object ? 0xFF : 0, last_word - (first_word + 1));
207
208 if (object)
209 m_buffer[last_word] |= BitFlag(bitmask(loffset + 1));
210 else
211 m_buffer[last_word] &= BitFlag(~bitmask(loffset + 1));
212 }
213#ifdef _DEBUG
214 for (uint04 i = 0; i < size; i++)
215 lib_assert(get(i + offset) == object, "Bad optimized set");
216#endif
217 }
218 template<bool is_primitive>
219 void setAll(const bool* src, t_index_type offset, t_index_type size)
220 {
221 for (t_index_type i = 0; i < size; i++)
222 {
223 get(i + offset) = src[i];
224 }
225 }
226
227 template<bool is_primitive>
228 void setAll(const BufferAllocator& allocator, t_index_type offset, t_index_type other_offset, t_index_type size)
229 {
230 if(bitset_idx(offset) == 0 && bitset_idx(other_offset) == 0)//if we are memory aligned
231 {
232 t_index_type new_size = bitset_wrd(size);
233 t_index_type new_offset = bitset_wrd(offset);
234 t_index_type new_other_offset = bitset_wrd(other_offset);
235 memmove(m_buffer + new_offset, allocator.m_buffer + new_other_offset, new_size);
236 for (t_index_type i = 8 * new_size; i < size; i++)
237 {
238 get(i + offset) = allocator.get(i + other_offset);
239 }
240 }
241 for (t_index_type i = 0; i < size; i++)
242 {
243 get(i + offset) = allocator.get(i + other_offset);
244 }
245 }
246 template<class t_other_allocator>
247 void setAllFromSource(const t_other_allocator& allocator, t_index_type offset, t_index_type other_offset, t_index_type size)
248 {
249 for (t_index_type i = 0; i < size; i++)
250 get(i + offset) = allocator.get(i + other_offset);
251 }
252 template<bool t_managed>
254 {
255 if ((t_managed && m_filled_size > m_allocated_size) || m_filled_size == m_allocated_size + 1)//We only 1, assume more to come shortly and allocate more space than required
256 {
257 lib_assert(cast<uint08>((t_managed ? m_filled_size : m_allocated_size) * 3) / 2 < cast<uint08>(Constant<uint04>::Max), "Buffer overflow");
259 }
260 else if (m_filled_size > m_allocated_size) //We added more than 1, increase buffer only once for compaction
261 {
263 }
264 }
265 void removeAllIndex(t_index_type start, t_index_type end)
266 {
267 if (end == m_filled_size)
268 {
269 m_filled_size = start;
270 }
271 else
272 {
273 bitmove(begin() + start, begin() + end, (m_filled_size - end));
274 m_filled_size -= (end - start);
275 }
276 }
277
278 t_index_type filledSize() const
279 {
280 return m_filled_size;
281 }
282 t_index_type count(const bool& value) const
283 {
284 uint04 count = 0;
285 for (uint04 i = 0; i < m_filled_size; i++)
286 {
287 if (get(i) == value)
288 ++count;
289 }
290 return count;
291 //return value ? numSet() : filledSize() - numSet();
292 }
293
294 inline BufferAllocator& operator=(BufferAllocator&& value) noexcept
295 {
296 std::swap(value.m_buffer, m_buffer);
297 std::swap(value.m_filled_size, m_filled_size);
298 std::swap(value.m_allocated_size, m_allocated_size);
299 return *this;
300 }
301
302 inline void resizeSpace(t_index_type new_size)
303 {
304 t_index_type byte_size = new_size == 0 ? 0 : bitset_wrd(new_size - 1) + 1;
305 if (new_size == 0)
306 {
307 if (m_allocated_size != 0)
308 free(m_buffer);
309 m_buffer = nullptr;
310 }
311 else
312 {
313 if (m_allocated_size == 0)
314 m_buffer = cast<BitFlag*>(malloc(byte_size));
315 else
316 m_buffer = cast<BitFlag*>(realloc(m_buffer, byte_size));
317 lib_assert(m_buffer != nullptr, "Unable to allocate buffer");
318 }
319 m_allocated_size = 8 * byte_size;
320 }
321
322 public:
323 t_index_type numSet() const
324 {
325 static const t_index_type BitsSetTable256[256] =
326 {
327 # define NDV_B2(n) n, n+1, n+1, n+2
328 # define NDV_B4(n) NDV_B2(n), NDV_B2(n+1), NDV_B2(n+1), NDV_B2(n+2)
329 # define NDV_B6(n) NDV_B4(n), NDV_B4(n+1), NDV_B4(n+1), NDV_B4(n+2)
330 NDV_B6(0), NDV_B6(1), NDV_B6(1), NDV_B6(2)
331 };
332 t_index_type flag_size = bitset_wrd(filledSize());
333 t_index_type num_set = 0;
334 uint01* mask = new uint01(1 << (filledSize() + 1)) - 1;
335 flag_size = flag_size ^ ((flag_size ^ filledSize()) & *mask);
336 BitFlag k(~*mask);
337 for (t_index_type i = 0; i < flag_size; i++)
338 {
339 num_set += BitsSetTable256[m_buffer[i]];
340 }
341 const uint01 size_mod_8 = bitset_idx(filledSize());
342 if (size_mod_8 != 0)
343 {
344 for (t_index_type i = 0; i < size_mod_8; i++)
345 {
346 num_set += m_buffer[flag_size][i] ? 1 : 0;
347 }
348 }
349 return num_set;
350 }
351
352 protected:
353 static void bitmove(BitIterator dst, BitIterator src, t_index_type size)
354 {
355 if (dst == src)
356 {
357 return;
358 }
359 if (dst < src)//prevent overlap
360 {
361 for (t_index_type i = 0; i < size; i++)
362 {
363 *dst = *src;
364 ++dst;
365 ++src;
366 }
367 }
368 else
369 {
370 for (t_index_type i = size - 1; !isNaN(i); i--)
371 {
372 *(dst + i) = *(src + i);
373 }
374 }
375 }
376 void setFlag(const t_index_type index, const bool value)
377 {
378 m_buffer[bitset_wrd(index)](index & 7, value);
379 }
380
381 public:
382 void invert()
383 {
384 const t_index_type byte_size = memSize();
385 for (t_index_type i = 0; i < byte_size; i++)
386 {
387 m_buffer[i] = ~m_buffer[i];
388 }
389 }
391 {
392 lib_assert(memSize() == buffer.memSize(), "Cannot ^= two buffers of different length");
393 const t_index_type byte_size = memSize();
394 for (t_index_type i = 0; i < byte_size; i++)
395 m_buffer[i] &= (~buffer.m_buffer[i]);
396 }
398 {
399 lib_assert(memSize() == buffer.memSize(), "Cannot ^= two buffers of different length");
400 const t_index_type byte_size = memSize();
401 for (t_index_type i = 0; i < byte_size; i++)
402 m_buffer[i] ^= buffer.m_buffer[i];
403 }
405 {
406 lib_assert(memSize() == buffer.memSize(), "Cannot |= two buffers of different length");
407 const t_index_type byte_size = memSize();
408 for (t_index_type i = 0; i < byte_size; i++)
409 m_buffer[i] |= buffer.m_buffer[i];
410 }
412 {
413 lib_assert(memSize() == buffer.memSize(), "Cannot &= two buffers of different length");
414 const t_index_type byte_size = memSize();
415 for (t_index_type i = 0; i < byte_size; i++)
416 m_buffer[i] &= buffer.m_buffer[i];
417 }
418 protected:
420 t_index_type m_filled_size;
421 t_index_type m_allocated_size;
422 };
423#undef bitset_wrd
424#undef bitset_idx
425#undef bitmaskt
426#undef bitmask
427}
428
#define NDV_B6(n)
#define bitset_idx(pos)
Definition BoolBuffer.hpp:39
#define bitmask(nbits)
Definition BoolBuffer.hpp:41
#define bitset_wrd(pos)
Definition BoolBuffer.hpp:38
#define lib_assert(expression, message)
Asserts some logic in the code. Disabled in non debug mode by default. Can be re-enabled in release u...
Definition LibAssert.h:70
A bitset that stores 8 bits (elements with only two possible values: 0 or 1, true or false,...
Definition BitFlag.hpp:68
Definition BitIterator.hpp:40
Definition BitReference.hpp:38
void createSpace(t_index_type location, t_index_type size)
Definition BoolBuffer.hpp:73
void inverseAndEquals(const BufferAllocator< bool, t_index_type > &buffer)
Definition BoolBuffer.hpp:390
sint04 compare(const BufferAllocator &allocator, t_index_type start, t_index_type end) const
Definition BoolBuffer.hpp:108
void setAllFromSource(const t_other_allocator &allocator, t_index_type offset, t_index_type other_offset, t_index_type size)
Definition BoolBuffer.hpp:247
void createSpace(t_index_type size)
Definition BoolBuffer.hpp:67
BitIterator begin()
Definition BoolBuffer.hpp:136
t_index_type m_filled_size
Definition BoolBuffer.hpp:420
void addIndex(t_index_type location)
Definition BoolBuffer.hpp:90
ConstBitIterator end() const
Definition BoolBuffer.hpp:157
sint04 compare(const BufferAllocator &allocator) const
Definition BoolBuffer.hpp:102
t_index_type numSet() const
Definition BoolBuffer.hpp:323
static void bitmove(BitIterator dst, BitIterator src, t_index_type size)
Definition BoolBuffer.hpp:353
t_index_type capacity() const
Definition BoolBuffer.hpp:149
BitIterator end()
Definition BoolBuffer.hpp:153
void allocationSizeCheck()
Definition BoolBuffer.hpp:253
void removeAllIndex(t_index_type start, t_index_type end)
Definition BoolBuffer.hpp:265
const ConstBitIterator begin() const
Definition BoolBuffer.hpp:140
void operator|=(const BufferAllocator< bool, t_index_type > &buffer)
Definition BoolBuffer.hpp:404
void setAll(const bool *src, t_index_type offset, t_index_type size)
Definition BoolBuffer.hpp:219
t_index_type filledSize() const
Definition BoolBuffer.hpp:278
BitReference get(t_index_type index)
Definition BoolBuffer.hpp:126
void swap(t_index_type index_a, t_index_type index_b)
Definition BoolBuffer.hpp:113
BufferAllocator(BufferAllocator &&allocator) noexcept
Definition BoolBuffer.hpp:52
void operator^=(const BufferAllocator< bool, t_index_type > &buffer)
Definition BoolBuffer.hpp:397
BufferAllocator & operator=(BufferAllocator &&value) noexcept
Definition BoolBuffer.hpp:294
void invert()
Definition BoolBuffer.hpp:382
BitIterator end(t_index_type index)
Definition BoolBuffer.hpp:161
void removeIndex(t_index_type location)
Definition BoolBuffer.hpp:96
void setFlag(const t_index_type index, const bool value)
Definition BoolBuffer.hpp:376
t_index_type m_allocated_size
Definition BoolBuffer.hpp:421
BitFlag * ptr()
Definition BoolBuffer.hpp:166
void addLast()
Definition BoolBuffer.hpp:78
bool get(t_index_type index) const
Definition BoolBuffer.hpp:131
t_index_type memSize() const
Definition BoolBuffer.hpp:175
t_index_type count(const bool &value) const
Definition BoolBuffer.hpp:282
void clear()
Definition BoolBuffer.hpp:117
BitIterator begin(t_index_type index) const
Definition BoolBuffer.hpp:144
~BufferAllocator()
Definition BoolBuffer.hpp:61
void resizeSpace(t_index_type new_size)
Definition BoolBuffer.hpp:302
BitFlag * m_buffer
Definition BoolBuffer.hpp:419
void setAll(const bool &object, t_index_type offset, t_index_type size)
Definition BoolBuffer.hpp:181
void setAll(const BufferAllocator &allocator, t_index_type offset, t_index_type other_offset, t_index_type size)
Definition BoolBuffer.hpp:228
void operator&=(const BufferAllocator< bool, t_index_type > &buffer)
Definition BoolBuffer.hpp:411
const BitFlag * ptr() const
Definition BoolBuffer.hpp:171
void setSize(t_index_type size)
Definition BoolBuffer.hpp:121
void removeLast()
Definition BoolBuffer.hpp:82
void addIndex()
Definition BoolBuffer.hpp:86
Definition Pointer.hpp:297
void createSpace(t_index_type size)
Definition MemoryManager.h:461
t_index_type m_filled_size
Definition MemoryManager.h:1294
t_type * end()
Definition MemoryManager.h:855
void allocationSizeCheck()
Definition MemoryManager.h:1120
constexpr t_index_type filledSize() const
Definition MemoryManager.h:1261
t_type & get(t_index_type index)
Definition MemoryManager.h:723
t_index_type m_allocated_size
Definition MemoryManager.h:1296
t_index_type memSize() const
Definition MemoryManager.h:758
t_type * begin()
Definition MemoryManager.h:775
void resizeSpace(t_index_type new_size)
Definition MemoryManager.h:914
t_type * m_buffer
Definition MemoryManager.h:1293
t_index_type count(const t_type &value) const
Definition MemoryManager.h:534
Definition BitIterator.hpp:173
Definition ACIColor.h:37
int32_t sint04
-Defines an alias representing a 4 byte, signed integer. -Can represent exact integer values -2147483...
Definition BaseValues.hpp:76
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:98
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:120
constexpr t_to cast(const Angle< t_from > &value)
Definition Angle.h:514
constexpr bool isNaN(const t_type &value)
Query if 'value' is valid or invalid.
Definition BaseFunctions.hpp:200
constexpr t_type getMin(const t_type &left, const t_type &right)
Finds the minimum of the given arguments based on the < operator.
Definition BaseFunctions.hpp:67
Definition BaseValues.hpp:272