1 /* 2 * Copyright Michael Schellenberger Costa 3 * Copyright © 2020 Valve Corporation 4 * 5 * SPDX-License-Identifier: MIT 6 */ 7 8 #ifndef ACO_UTIL_H 9 #define ACO_UTIL_H 10 11 #include "util/bitscan.h" 12 #include "util/macros.h" 13 #include "util/u_math.h" 14 15 #include <array> 16 #include <cassert> 17 #include <cstddef> 18 #include <functional> 19 #include <iterator> 20 #include <map> 21 #include <type_traits> 22 #include <unordered_map> 23 #include <vector> 24 25 namespace aco { 26 27 /*! \brief Definition of a span object 28 * 29 * \details A "span" is an "array view" type for holding a view of contiguous 30 * data. The "span" object does not own the data itself. 31 */ 32 template <typename T> class span { 33 public: 34 using value_type = T; 35 using pointer = value_type*; 36 using const_pointer = const value_type*; 37 using reference = value_type&; 38 using const_reference = const value_type&; 39 using iterator = pointer; 40 using const_iterator = const_pointer; 41 using reverse_iterator = std::reverse_iterator<iterator>; 42 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 43 using size_type = uint16_t; 44 using difference_type = std::ptrdiff_t; 45 46 /*! \brief Compiler generated default constructor 47 */ 48 constexpr span() = default; 49 50 /*! \brief Constructor taking a pointer and the length of the span 51 * \param[in] data Pointer to the underlying data array 52 * \param[in] length The size of the span 53 */ span(uint16_t offset_,const size_type length_)54 constexpr span(uint16_t offset_, const size_type length_) : offset{offset_}, length{length_} {} 55 56 /*! \brief Returns an iterator to the begin of the span 57 * \return data 58 */ begin()59 constexpr iterator begin() noexcept { return (pointer)((uintptr_t)this + offset); } 60 61 /*! \brief Returns a const_iterator to the begin of the span 62 * \return data 63 */ begin()64 constexpr const_iterator begin() const noexcept 65 { 66 return (const_pointer)((uintptr_t)this + offset); 67 } 68 69 /*! \brief Returns an iterator to the end of the span 70 * \return data + length 71 */ end()72 constexpr iterator end() noexcept { return std::next(begin(), length); } 73 74 /*! \brief Returns a const_iterator to the end of the span 75 * \return data + length 76 */ end()77 constexpr const_iterator end() const noexcept { return std::next(begin(), length); } 78 79 /*! \brief Returns a const_iterator to the begin of the span 80 * \return data 81 */ cbegin()82 constexpr const_iterator cbegin() const noexcept { return begin(); } 83 84 /*! \brief Returns a const_iterator to the end of the span 85 * \return data + length 86 */ cend()87 constexpr const_iterator cend() const noexcept { return std::next(begin(), length); } 88 89 /*! \brief Returns a reverse_iterator to the end of the span 90 * \return reverse_iterator(end()) 91 */ rbegin()92 constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } 93 94 /*! \brief Returns a const_reverse_iterator to the end of the span 95 * \return reverse_iterator(end()) 96 */ rbegin()97 constexpr const_reverse_iterator rbegin() const noexcept 98 { 99 return const_reverse_iterator(end()); 100 } 101 102 /*! \brief Returns a reverse_iterator to the begin of the span 103 * \return reverse_iterator(begin()) 104 */ rend()105 constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); } 106 107 /*! \brief Returns a const_reverse_iterator to the begin of the span 108 * \return reverse_iterator(begin()) 109 */ rend()110 constexpr const_reverse_iterator rend() const noexcept 111 { 112 return const_reverse_iterator(begin()); 113 } 114 115 /*! \brief Returns a const_reverse_iterator to the end of the span 116 * \return rbegin() 117 */ crbegin()118 constexpr const_reverse_iterator crbegin() const noexcept 119 { 120 return const_reverse_iterator(cend()); 121 } 122 123 /*! \brief Returns a const_reverse_iterator to the begin of the span 124 * \return rend() 125 */ crend()126 constexpr const_reverse_iterator crend() const noexcept 127 { 128 return const_reverse_iterator(cbegin()); 129 } 130 131 /*! \brief Unchecked access operator 132 * \param[in] index Index of the element we want to access 133 * \return *(std::next(data, index)) 134 */ 135 constexpr reference operator[](const size_type index) noexcept 136 { 137 assert(length > index); 138 return *(std::next(begin(), index)); 139 } 140 141 /*! \brief Unchecked const access operator 142 * \param[in] index Index of the element we want to access 143 * \return *(std::next(data, index)) 144 */ 145 constexpr const_reference operator[](const size_type index) const noexcept 146 { 147 assert(length > index); 148 return *(std::next(begin(), index)); 149 } 150 151 /*! \brief Returns a reference to the last element of the span 152 * \return *(std::next(data, length - 1)) 153 */ back()154 constexpr reference back() noexcept 155 { 156 assert(length > 0); 157 return *(std::next(begin(), length - 1)); 158 } 159 160 /*! \brief Returns a const_reference to the last element of the span 161 * \return *(std::next(data, length - 1)) 162 */ back()163 constexpr const_reference back() const noexcept 164 { 165 assert(length > 0); 166 return *(std::next(begin(), length - 1)); 167 } 168 169 /*! \brief Returns a reference to the first element of the span 170 * \return *begin() 171 */ front()172 constexpr reference front() noexcept 173 { 174 assert(length > 0); 175 return *begin(); 176 } 177 178 /*! \brief Returns a const_reference to the first element of the span 179 * \return *cbegin() 180 */ front()181 constexpr const_reference front() const noexcept 182 { 183 assert(length > 0); 184 return *cbegin(); 185 } 186 187 /*! \brief Returns true if the span is empty 188 * \return length == 0 189 */ empty()190 constexpr bool empty() const noexcept { return length == 0; } 191 192 /*! \brief Returns the size of the span 193 * \return length == 0 194 */ size()195 constexpr size_type size() const noexcept { return length; } 196 197 /*! \brief Decreases the size of the span by 1 198 */ pop_back()199 constexpr void pop_back() noexcept 200 { 201 assert(length > 0); 202 --length; 203 } 204 205 /*! \brief Adds an element to the end of the span 206 */ push_back(const_reference val)207 constexpr void push_back(const_reference val) noexcept { *std::next(begin(), length++) = val; } 208 209 /*! \brief Clears the span 210 */ clear()211 constexpr void clear() noexcept 212 { 213 offset = 0; 214 length = 0; 215 } 216 217 private: 218 uint16_t offset{0}; //!> Byte offset from span to data 219 size_type length{0}; //!> Size of the span 220 }; 221 222 /* 223 * Light-weight memory resource which allows to sequentially allocate from 224 * a buffer. Both, the release() method and the destructor release all managed 225 * memory. 226 * 227 * The memory resource is not thread-safe. 228 * This class mimics std::pmr::monotonic_buffer_resource 229 */ 230 class monotonic_buffer_resource final { 231 public: 232 explicit monotonic_buffer_resource(size_t size = initial_size) 233 { 234 /* The size parameter refers to the total size of the buffer. 235 * The usable data_size is size - sizeof(Buffer). 236 */ 237 size = MAX2(size, minimum_size); 238 buffer = (Buffer*)malloc(size); 239 buffer->next = nullptr; 240 buffer->data_size = size - sizeof(Buffer); 241 buffer->current_idx = 0; 242 } 243 ~monotonic_buffer_resource()244 ~monotonic_buffer_resource() 245 { 246 release(); 247 free(buffer); 248 } 249 250 /* Move-constructor and -assignment */ monotonic_buffer_resource(monotonic_buffer_resource && other)251 monotonic_buffer_resource(monotonic_buffer_resource&& other) : monotonic_buffer_resource() 252 { 253 *this = std::move(other); 254 } 255 monotonic_buffer_resource& operator=(monotonic_buffer_resource&& other) 256 { 257 release(); 258 std::swap(buffer, other.buffer); 259 return *this; 260 } 261 262 /* Delete copy-constructor and -assignment to avoid double free() */ 263 monotonic_buffer_resource(const monotonic_buffer_resource&) = delete; 264 monotonic_buffer_resource& operator=(const monotonic_buffer_resource&) = delete; 265 allocate(size_t size,size_t alignment)266 void* allocate(size_t size, size_t alignment) 267 { 268 buffer->current_idx = align(buffer->current_idx, alignment); 269 if (buffer->current_idx + size <= buffer->data_size) { 270 uint8_t* ptr = &buffer->data[buffer->current_idx]; 271 buffer->current_idx += size; 272 return ptr; 273 } 274 275 /* create new larger buffer */ 276 uint32_t total_size = buffer->data_size + sizeof(Buffer); 277 do { 278 total_size *= 2; 279 } while (total_size - sizeof(Buffer) < size); 280 Buffer* next = buffer; 281 buffer = (Buffer*)malloc(total_size); 282 buffer->next = next; 283 buffer->data_size = total_size - sizeof(Buffer); 284 buffer->current_idx = 0; 285 286 return allocate(size, alignment); 287 } 288 release()289 void release() 290 { 291 while (buffer->next) { 292 Buffer* next = buffer->next; 293 free(buffer); 294 buffer = next; 295 } 296 buffer->current_idx = 0; 297 } 298 299 bool operator==(const monotonic_buffer_resource& other) { return buffer == other.buffer; } 300 301 private: 302 struct Buffer { 303 Buffer* next; 304 uint32_t current_idx; 305 uint32_t data_size; 306 uint8_t data[]; 307 }; 308 309 Buffer* buffer; 310 static constexpr size_t initial_size = 4096; 311 static constexpr size_t minimum_size = 128; 312 static_assert(minimum_size > sizeof(Buffer)); 313 }; 314 315 /* 316 * Small memory allocator which wraps monotonic_buffer_resource 317 * in order to implement <allocator_traits>. 318 * 319 * This class mimics std::pmr::polymorphic_allocator with monotonic_buffer_resource 320 * as memory resource. The advantage of this specialization is the absence of 321 * virtual function calls and the propagation on swap, copy- and move assignment. 322 */ 323 template <typename T> class monotonic_allocator { 324 public: 325 monotonic_allocator() = delete; monotonic_allocator(monotonic_buffer_resource & m)326 monotonic_allocator(monotonic_buffer_resource& m) : memory_resource(m) {} 327 template <typename U> monotonic_allocator(const monotonic_allocator<U> & rhs)328 explicit monotonic_allocator(const monotonic_allocator<U>& rhs) 329 : memory_resource(rhs.memory_resource) 330 {} 331 332 /* Memory Allocation */ allocate(size_t size)333 T* allocate(size_t size) 334 { 335 uint32_t bytes = sizeof(T) * size; 336 return (T*)memory_resource.get().allocate(bytes, alignof(T)); 337 } 338 339 /* Memory will be freed on destruction of memory_resource */ deallocate(T * ptr,size_t size)340 void deallocate(T* ptr, size_t size) {} 341 342 /* Implement <allocator_traits> */ 343 using value_type = T; 344 template <class U> struct rebind { 345 using other = monotonic_allocator<U>; 346 }; 347 348 typedef std::true_type propagate_on_container_copy_assignment; 349 typedef std::true_type propagate_on_container_move_assignment; 350 typedef std::true_type propagate_on_container_swap; 351 352 template <typename> friend class monotonic_allocator; 353 template <typename X, typename Y> 354 friend bool operator==(monotonic_allocator<X> const& a, monotonic_allocator<Y> const& b); 355 template <typename X, typename Y> 356 friend bool operator!=(monotonic_allocator<X> const& a, monotonic_allocator<Y> const& b); 357 358 private: 359 std::reference_wrapper<monotonic_buffer_resource> memory_resource; 360 }; 361 362 /* Necessary for <allocator_traits>. */ 363 template <typename X, typename Y> 364 inline bool 365 operator==(monotonic_allocator<X> const& a, monotonic_allocator<Y> const& b) 366 { 367 return a.memory_resource.get() == b.memory_resource.get(); 368 } 369 template <typename X, typename Y> 370 inline bool 371 operator!=(monotonic_allocator<X> const& a, monotonic_allocator<Y> const& b) 372 { 373 return !(a == b); 374 } 375 376 /* 377 * aco::map - alias for std::map with monotonic_allocator 378 * 379 * This template specialization mimics std::pmr::map. 380 */ 381 template <class Key, class T, class Compare = std::less<Key>> 382 using map = std::map<Key, T, Compare, aco::monotonic_allocator<std::pair<const Key, T>>>; 383 384 /* 385 * aco::unordered_map - alias for std::unordered_map with monotonic_allocator 386 * 387 * This template specialization mimics std::pmr::unordered_map. 388 */ 389 template <class Key, class T, class Hash = std::hash<Key>, class Pred = std::equal_to<Key>> 390 using unordered_map = 391 std::unordered_map<Key, T, Hash, Pred, aco::monotonic_allocator<std::pair<const Key, T>>>; 392 393 /* 394 * Cache-friendly set of 32-bit IDs with fast insert/erase/lookup and 395 * the ability to efficiently iterate over contained elements. 396 * 397 * Internally implemented as a map of fixed-size bit vectors: If the set contains an ID, the 398 * corresponding bit in the appropriate bit vector is set. It doesn't use std::vector<bool> since 399 * we then couldn't efficiently iterate over the elements. 400 * 401 * The interface resembles a subset of std::set/std::unordered_set. 402 */ 403 struct IDSet { 404 static const uint32_t block_size = 1024u; 405 using block_t = std::array<uint64_t, block_size / 64>; 406 407 struct Iterator { 408 const IDSet* set; 409 aco::map<uint32_t, block_t>::const_iterator block; 410 uint32_t id; 411 412 Iterator& operator++(); 413 414 bool operator!=(const Iterator& other) const; 415 416 uint32_t operator*() const; 417 }; 418 countIDSet419 size_t count(uint32_t id) const { return find(id) != end(); } 420 findIDSet421 Iterator find(uint32_t id) const 422 { 423 uint32_t block_index = id / block_size; 424 auto it = words.find(block_index); 425 if (it == words.end()) 426 return end(); 427 428 const block_t& block = it->second; 429 uint32_t sub_id = id % block_size; 430 431 if (block[sub_id / 64u] & (1ull << (sub_id % 64u))) 432 return Iterator{this, it, id}; 433 else 434 return end(); 435 } 436 insertIDSet437 std::pair<Iterator, bool> insert(uint32_t id) 438 { 439 uint32_t block_index = id / block_size; 440 auto it = words.try_emplace(block_index).first; 441 block_t& block = it->second; 442 uint32_t sub_id = id % block_size; 443 444 uint64_t* word = &block[sub_id / 64u]; 445 uint64_t mask = 1ull << (sub_id % 64u); 446 if (*word & mask) 447 return std::make_pair(Iterator{this, it, id}, false); 448 449 *word |= mask; 450 return std::make_pair(Iterator{this, it, id}, true); 451 } 452 insertIDSet453 bool insert(const IDSet other) 454 { 455 bool inserted = false; 456 457 for (auto it = other.words.begin(); it != other.words.end(); ++it) { 458 const block_t& src = it->second; 459 if (src == block_t{0}) 460 continue; 461 462 block_t& dst = words[it->first]; 463 for (unsigned j = 0; j < src.size(); j++) { 464 uint64_t new_bits = src[j] & ~dst[j]; 465 if (new_bits) { 466 inserted = true; 467 dst[j] |= new_bits; 468 } 469 } 470 } 471 return inserted; 472 } 473 eraseIDSet474 size_t erase(uint32_t id) 475 { 476 uint32_t block_index = id / block_size; 477 auto it = words.find(block_index); 478 if (it == words.end()) 479 return 0; 480 481 block_t& block = it->second; 482 uint32_t sub_id = id % block_size; 483 484 uint64_t* word = &block[sub_id / 64u]; 485 uint64_t mask = 1ull << (sub_id % 64u); 486 if (!(*word & mask)) 487 return 0; 488 489 *word ^= mask; 490 return 1; 491 } 492 cbeginIDSet493 Iterator cbegin() const 494 { 495 Iterator res; 496 res.set = this; 497 498 for (auto it = words.begin(); it != words.end(); ++it) { 499 uint32_t first = get_first_set(it->second); 500 if (first != UINT32_MAX) { 501 res.block = it; 502 res.id = it->first * block_size + first; 503 return res; 504 } 505 } 506 507 return cend(); 508 } 509 cendIDSet510 Iterator cend() const { return Iterator{this, words.end(), UINT32_MAX}; } 511 beginIDSet512 Iterator begin() const { return cbegin(); } 513 endIDSet514 Iterator end() const { return cend(); } 515 sizeIDSet516 size_t size() const 517 { 518 size_t bits_set = 0; 519 for (auto block : words) { 520 for (uint64_t word : block.second) 521 bits_set += util_bitcount64(word); 522 } 523 return bits_set; 524 } 525 emptyIDSet526 bool empty() const { return !size(); } 527 IDSetIDSet528 explicit IDSet(monotonic_buffer_resource& m) : words(m) {} IDSetIDSet529 explicit IDSet(const IDSet& other, monotonic_buffer_resource& m) : words(other.words, m) {} 530 531 bool operator==(const IDSet& other) const 532 { 533 auto it = words.begin(); 534 for (auto block : other.words) { 535 if (block.second == block_t{0}) 536 continue; 537 while (it != words.end() && it->second == block_t{0}) 538 it++; 539 if (it == words.end() || block != *it) 540 return false; 541 it++; 542 } 543 544 return true; 545 } 546 bool operator!=(const IDSet& other) const { return !(*this == other); } 547 548 private: get_first_setIDSet549 static uint32_t get_first_set(const block_t& words) 550 { 551 for (size_t i = 0; i < words.size(); i++) { 552 if (words[i]) 553 return i * 64u + (ffsll(words[i]) - 1); 554 } 555 return UINT32_MAX; 556 } 557 558 aco::map<uint32_t, block_t> words; 559 }; 560 561 inline IDSet::Iterator& 562 IDSet::Iterator::operator++() 563 { 564 uint32_t block_index = id / block_size; 565 const block_t& block_words = block->second; 566 uint32_t sub_id = id % block_size; 567 568 uint64_t m = block_words[sub_id / 64u]; 569 uint32_t bit = sub_id % 64u; 570 m = (m >> bit) >> 1; 571 if (m) { 572 id += ffsll(m); 573 return *this; 574 } 575 576 for (uint32_t i = sub_id / 64u + 1; i < block_words.size(); i++) { 577 if (block_words[i]) { 578 id = block_index * block_size + i * 64u + ffsll(block_words[i]) - 1; 579 return *this; 580 } 581 } 582 583 for (++block; block != set->words.end(); ++block) { 584 uint32_t first = get_first_set(block->second); 585 if (first != UINT32_MAX) { 586 id = block->first * block_size + first; 587 return *this; 588 } 589 } 590 591 id = UINT32_MAX; 592 return *this; 593 } 594 595 inline bool 596 IDSet::Iterator::operator!=(const IDSet::Iterator& other) const 597 { 598 assert(set == other.set); 599 assert(id != other.id || block == other.block); 600 return id != other.id; 601 } 602 603 inline uint32_t 604 IDSet::Iterator::operator*() const 605 { 606 return id; 607 } 608 609 /* 610 * Helper class for a integer/bool (access_type) packed into 611 * a bigger integer (data_type) with an offset and size. 612 * It can be implicitly converted to access_type and supports 613 * all arithmetic assignment operators. 614 * 615 * When used together with a union, this allows storing 616 * multiple fields packed into a single integer. 617 * 618 * Example usage: 619 * union { 620 * bitfield_uint<uint32_t, 0, 5, uint8_t> int5; 621 * bitfield_uint<uint32_t, 5, 26, uint32_t> int26; 622 * bitfield_uint<uint32_t, 31, 1, bool> bool1; 623 * }; 624 * 625 */ 626 template <typename data_type, unsigned offset, unsigned size, typename access_type> 627 class bitfield_uint { 628 public: 629 static_assert(sizeof(data_type) >= sizeof(access_type), ""); 630 static_assert(std::is_unsigned<access_type>::value, ""); 631 static_assert(std::is_unsigned<data_type>::value, ""); 632 static_assert(sizeof(data_type) * 8 >= offset + size, ""); 633 static_assert(sizeof(access_type) * 8 >= size, ""); 634 static_assert(size > 0, ""); 635 static_assert(!std::is_same_v<access_type, bool> || size == 1, ""); 636 637 bitfield_uint() = default; 638 bitfield_uint(const access_type & value)639 constexpr bitfield_uint(const access_type& value) { *this = value; } 640 access_type()641 constexpr operator access_type() const { return (storage >> offset) & mask; } 642 643 constexpr bitfield_uint& operator=(const access_type& value) 644 { 645 storage &= ~(mask << offset); 646 storage |= data_type(value & mask) << offset; 647 return *this; 648 } 649 650 constexpr bitfield_uint& operator=(const bitfield_uint& value) 651 { 652 return *this = access_type(value); 653 } 654 655 constexpr bitfield_uint& operator|=(const access_type& value) 656 { 657 storage |= data_type(value & mask) << offset; 658 return *this; 659 } 660 661 constexpr bitfield_uint& operator^=(const access_type& value) 662 { 663 storage ^= data_type(value & mask) << offset; 664 return *this; 665 } 666 667 constexpr bitfield_uint& operator&=(const access_type& value) 668 { 669 storage &= (data_type(value & mask) << offset) | ~(mask << offset); 670 return *this; 671 } 672 673 constexpr bitfield_uint& operator<<=(const access_type& shift) 674 { 675 static_assert(!std::is_same_v<access_type, bool>, ""); 676 assert(shift < size); 677 return *this = access_type(*this) << shift; 678 } 679 680 constexpr bitfield_uint& operator>>=(const access_type& shift) 681 { 682 static_assert(!std::is_same_v<access_type, bool>, ""); 683 assert(shift < size); 684 return *this = access_type(*this) >> shift; 685 } 686 687 constexpr bitfield_uint& operator*=(const access_type& op) 688 { 689 static_assert(!std::is_same_v<access_type, bool>, ""); 690 return *this = access_type(*this) * op; 691 } 692 693 constexpr bitfield_uint& operator/=(const access_type& op) 694 { 695 static_assert(!std::is_same_v<access_type, bool>, ""); 696 return *this = access_type(*this) / op; 697 } 698 699 constexpr bitfield_uint& operator%=(const access_type& op) 700 { 701 static_assert(!std::is_same_v<access_type, bool>, ""); 702 return *this = access_type(*this) % op; 703 } 704 705 constexpr bitfield_uint& operator+=(const access_type& op) 706 { 707 static_assert(!std::is_same_v<access_type, bool>, ""); 708 return *this = access_type(*this) + op; 709 } 710 711 constexpr bitfield_uint& operator-=(const access_type& op) 712 { 713 static_assert(!std::is_same_v<access_type, bool>, ""); 714 return *this = access_type(*this) - op; 715 } 716 717 constexpr bitfield_uint& operator++() 718 { 719 static_assert(!std::is_same_v<access_type, bool>, ""); 720 return *this += 1; 721 } 722 723 constexpr access_type operator++(int) 724 { 725 static_assert(!std::is_same_v<access_type, bool>, ""); 726 access_type temp = *this; 727 ++*this; 728 return temp; 729 } 730 731 constexpr bitfield_uint& operator--() 732 { 733 static_assert(!std::is_same_v<access_type, bool>, ""); 734 return *this -= 1; 735 } 736 737 constexpr access_type operator--(int) 738 { 739 static_assert(!std::is_same_v<access_type, bool>, ""); 740 access_type temp = *this; 741 --*this; 742 return temp; 743 } 744 swap(access_type & other)745 constexpr void swap(access_type& other) 746 { 747 access_type tmp = *this; 748 *this = other; 749 other = tmp; 750 } 751 752 template <typename other_dt, unsigned other_off, unsigned other_s> swap(bitfield_uint<other_dt,other_off,other_s,access_type> & other)753 constexpr void swap(bitfield_uint<other_dt, other_off, other_s, access_type>& other) 754 { 755 access_type tmp = *this; 756 *this = other; 757 other = tmp; 758 } 759 760 protected: 761 static const data_type mask = BITFIELD64_MASK(size); 762 763 data_type storage; 764 }; 765 766 /* 767 * Reference to a single bit in an integer that can be converted to a bool 768 * and supports bool (bitwise) assignment operators. 769 */ 770 template <typename T> struct bit_reference { bit_referencebit_reference771 constexpr bit_reference(T& s, unsigned b) : storage(s), bit(b) {} 772 773 constexpr bit_reference& operator=(const bit_reference& other) { return *this = (bool)other; } 774 775 constexpr bit_reference& operator=(bool val) 776 { 777 storage &= ~(T(0x1) << bit); 778 storage |= T(val) << bit; 779 return *this; 780 } 781 782 constexpr bit_reference& operator^=(bool val) 783 { 784 storage ^= T(val) << bit; 785 return *this; 786 } 787 788 constexpr bit_reference& operator|=(bool val) 789 { 790 storage |= T(val) << bit; 791 return *this; 792 } 793 794 constexpr bit_reference& operator&=(bool val) 795 { 796 storage &= T(val) << bit; 797 return *this; 798 } 799 800 constexpr operator bool() const { return (storage >> bit) & 0x1; } 801 swapbit_reference802 constexpr void swap(bool& other) 803 { 804 bool tmp = (bool)*this; 805 *this = other; 806 other = tmp; 807 } 808 swapbit_reference809 template <typename other_T> constexpr void swap(bit_reference<other_T> other) 810 { 811 bool tmp = (bool)*this; 812 *this = (bool)other; 813 other = tmp; 814 } 815 816 T& storage; 817 unsigned bit; 818 }; 819 820 /* 821 * Base template for (const) bit iterators over an integer. 822 * Only intended to be used with the two specializations 823 * bitfield_array::iterator and bitfield_array::const_iterator. 824 */ 825 template <typename T, typename refT, typename ptrT> struct bitfield_iterator { 826 using difference_type = int; 827 using value_type = bool; 828 using iterator_category = std::random_access_iterator_tag; 829 using reference = refT; 830 using const_reference = bool; 831 using pointer = ptrT; 832 using iterator = bitfield_iterator<T, refT, ptrT>; 833 using ncT = std::remove_const_t<T>; 834 bitfield_iteratorbitfield_iterator835 constexpr bitfield_iterator() : bf(nullptr), index(0) {} bitfield_iteratorbitfield_iterator836 constexpr bitfield_iterator(T* p, unsigned i) : bf(p), index(i) {} 837 838 /* const iterator must be constructable from iterator */ bitfield_iteratorbitfield_iterator839 constexpr bitfield_iterator( 840 const bitfield_iterator<ncT, bit_reference<ncT>, bit_reference<ncT>*>& x) 841 : bf(x.bf), index(x.index) 842 {} 843 844 constexpr bool operator==(const bitfield_iterator& other) const 845 { 846 return bf == other.bf && index == other.index; 847 } 848 849 constexpr bool operator<(const bitfield_iterator& other) const { return index < other.index; } 850 851 constexpr bool operator!=(const bitfield_iterator& other) const { return !(*this == other); } 852 853 constexpr bool operator>(const bitfield_iterator& other) const { return other < *this; } 854 855 constexpr bool operator<=(const bitfield_iterator& other) const { return !(other < *this); } 856 857 constexpr bool operator>=(const bitfield_iterator& other) const { return !(*this < other); } 858 859 constexpr reference operator*() const { return bit_reference<T>(*bf, index); } 860 861 constexpr iterator& operator++() 862 { 863 index++; 864 return *this; 865 } 866 867 constexpr iterator operator++(int) 868 { 869 iterator tmp = *this; 870 index++; 871 return tmp; 872 } 873 874 constexpr iterator& operator--() 875 { 876 index--; 877 return *this; 878 } 879 880 constexpr iterator operator--(int) 881 { 882 iterator tmp = *this; 883 index--; 884 return tmp; 885 } 886 887 constexpr iterator& operator+=(difference_type value) 888 { 889 index += value; 890 return *this; 891 } 892 893 constexpr iterator& operator-=(difference_type value) 894 { 895 *this += -value; 896 return *this; 897 } 898 899 constexpr iterator operator+(difference_type value) const 900 { 901 iterator tmp = *this; 902 return tmp += value; 903 } 904 905 constexpr iterator operator-(difference_type value) const 906 { 907 iterator tmp = *this; 908 return tmp -= value; 909 } 910 911 constexpr reference operator[](difference_type value) const { return *(*this + value); } 912 913 T* bf; 914 unsigned index; 915 }; 916 917 template <typename T, typename refT, typename ptrT> 918 constexpr inline bitfield_iterator<T, refT, ptrT> 919 operator+(int n, const bitfield_iterator<T, refT, ptrT>& x) 920 { 921 return x + n; 922 } 923 924 template <typename T, typename refT, typename ptrT> 925 constexpr inline int 926 operator-(const bitfield_iterator<T, refT, ptrT> x, const bitfield_iterator<T, refT, ptrT>& y) 927 { 928 return x.index - y.index; 929 } 930 931 /* 932 * Extends bitfield_uint with operator[] and iterators that 933 * allow accessing single bits within the uint. Can be used 934 * as a more compact version of bool arrays that also still 935 * allows accessing the whole array as an integer. 936 */ 937 template <typename data_type, unsigned offset, unsigned size, typename access_type> 938 class bitfield_array : public bitfield_uint<data_type, offset, size, access_type> { 939 public: 940 using value_type = bool; 941 using size_type = unsigned; 942 using difference_type = int; 943 using reference = bit_reference<data_type>; 944 using const_reference = bool; 945 using pointer = bit_reference<data_type>*; 946 using const_pointer = const bool*; 947 using iterator = 948 bitfield_iterator<data_type, bit_reference<data_type>, bit_reference<data_type>*>; 949 using const_iterator = bitfield_iterator<const data_type, bool, const bool*>; 950 using reverse_iterator = std::reverse_iterator<iterator>; 951 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 952 953 bitfield_array() = default; 954 bitfield_array(const access_type & value)955 constexpr bitfield_array(const access_type& value) { *this = value; } 956 957 constexpr bitfield_array& operator=(const access_type& value) 958 { 959 storage &= ~(mask << offset); 960 storage |= data_type(value & mask) << offset; 961 return *this; 962 } 963 964 constexpr bitfield_array& operator=(const bitfield_array& value) 965 { 966 return *this = access_type(value); 967 } 968 969 constexpr reference operator[](unsigned index) 970 { 971 assert(index < size); 972 return reference(storage, offset + index); 973 } 974 975 constexpr bool operator[](unsigned index) const 976 { 977 assert(index < size); 978 return (storage >> (offset + index)) & 0x1; 979 } 980 begin()981 constexpr iterator begin() noexcept { return iterator(&storage, offset); } 982 end()983 constexpr iterator end() noexcept { return std::next(begin(), size); } 984 begin()985 constexpr const_iterator begin() const noexcept { return const_iterator(&storage, offset); } 986 end()987 constexpr const_iterator end() const noexcept { return std::next(begin(), size); } 988 cbegin()989 constexpr const_iterator cbegin() const noexcept { return begin(); } 990 cend()991 constexpr const_iterator cend() const noexcept { return std::next(begin(), size); } 992 rbegin()993 constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } 994 rend()995 constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); } 996 rbegin()997 constexpr const_reverse_iterator rbegin() const noexcept 998 { 999 return const_reverse_iterator(end()); 1000 } 1001 rend()1002 constexpr const_reverse_iterator rend() const noexcept 1003 { 1004 return const_reverse_iterator(begin()); 1005 } 1006 crbegin()1007 constexpr const_reverse_iterator crbegin() const noexcept 1008 { 1009 return const_reverse_iterator(cend()); 1010 } 1011 crend()1012 constexpr const_reverse_iterator crend() const noexcept 1013 { 1014 return const_reverse_iterator(cbegin()); 1015 } 1016 1017 private: 1018 using bitfield_uint<data_type, offset, size, access_type>::storage; 1019 using bitfield_uint<data_type, offset, size, access_type>::mask; 1020 }; 1021 1022 template <typename T, unsigned offset> using bitfield_bool = bitfield_uint<T, offset, 1, bool>; 1023 1024 template <typename T, unsigned offset, unsigned size> 1025 using bitfield_uint8 = bitfield_uint<T, offset, size, uint8_t>; 1026 1027 template <typename T, unsigned offset, unsigned size> 1028 using bitfield_uint16 = bitfield_uint<T, offset, size, uint16_t>; 1029 1030 template <typename T, unsigned offset, unsigned size> 1031 using bitfield_uint32 = bitfield_uint<T, offset, size, uint32_t>; 1032 1033 template <typename T, unsigned offset, unsigned size> 1034 using bitfield_uint64 = bitfield_uint<T, offset, size, uint64_t>; 1035 1036 template <typename T, unsigned offset, unsigned size> 1037 using bitfield_array8 = bitfield_array<T, offset, size, uint8_t>; 1038 1039 template <typename T, unsigned offset, unsigned size> 1040 using bitfield_array16 = bitfield_array<T, offset, size, uint16_t>; 1041 1042 template <typename T, unsigned offset, unsigned size> 1043 using bitfield_array32 = bitfield_array<T, offset, size, uint32_t>; 1044 1045 template <typename T, unsigned offset, unsigned size> 1046 using bitfield_array64 = bitfield_array<T, offset, size, uint64_t>; 1047 1048 using bitarray8 = bitfield_array<uint8_t, 0, 8, uint8_t>; 1049 1050 /* 1051 * Resizable array optimized for small lengths. If it's smaller than Size, the elements will be 1052 * inlined into the object. 1053 */ 1054 template <typename T, uint32_t Size> class small_vec { 1055 public: 1056 static_assert(std::is_trivial<T>::value); 1057 1058 using value_type = T; 1059 using pointer = value_type*; 1060 using const_pointer = const value_type*; 1061 using reference = value_type&; 1062 using const_reference = const value_type&; 1063 using iterator = pointer; 1064 using const_iterator = const_pointer; 1065 using reverse_iterator = std::reverse_iterator<iterator>; 1066 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 1067 using size_type = uint16_t; 1068 using difference_type = std::ptrdiff_t; 1069 1070 constexpr small_vec() = default; 1071 constexpr small_vec(const small_vec&) = delete; small_vec(small_vec && other)1072 constexpr small_vec(small_vec&& other) { *this = std::move(other); } 1073 ~small_vec()1074 ~small_vec() 1075 { 1076 if (capacity > Size) 1077 free(data); 1078 } 1079 1080 constexpr small_vec& operator=(const small_vec&) = delete; 1081 constexpr small_vec& operator=(small_vec&& other) 1082 { 1083 clear(); 1084 void* ptr = this; 1085 memcpy(ptr, &other, sizeof(*this)); 1086 other.length = 0; 1087 other.capacity = Size; 1088 return *this; 1089 } 1090 begin()1091 constexpr iterator begin() noexcept { return capacity > Size ? data : inline_data; } 1092 begin()1093 constexpr const_iterator begin() const noexcept { return capacity > Size ? data : inline_data; } 1094 end()1095 constexpr iterator end() noexcept { return std::next(begin(), length); } 1096 end()1097 constexpr const_iterator end() const noexcept { return std::next(begin(), length); } 1098 cbegin()1099 constexpr const_iterator cbegin() const noexcept { return begin(); } 1100 cend()1101 constexpr const_iterator cend() const noexcept { return std::next(begin(), length); } 1102 rbegin()1103 constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } 1104 rbegin()1105 constexpr const_reverse_iterator rbegin() const noexcept 1106 { 1107 return const_reverse_iterator(end()); 1108 } 1109 rend()1110 constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); } 1111 rend()1112 constexpr const_reverse_iterator rend() const noexcept 1113 { 1114 return const_reverse_iterator(begin()); 1115 } 1116 crbegin()1117 constexpr const_reverse_iterator crbegin() const noexcept 1118 { 1119 return const_reverse_iterator(cend()); 1120 } 1121 crend()1122 constexpr const_reverse_iterator crend() const noexcept 1123 { 1124 return const_reverse_iterator(cbegin()); 1125 } 1126 1127 constexpr reference operator[](const size_type index) noexcept 1128 { 1129 assert(length > index); 1130 return *(std::next(begin(), index)); 1131 } 1132 1133 constexpr const_reference operator[](const size_type index) const noexcept 1134 { 1135 assert(length > index); 1136 return *(std::next(begin(), index)); 1137 } 1138 back()1139 constexpr reference back() noexcept 1140 { 1141 assert(length > 0); 1142 return *(std::next(begin(), length - 1)); 1143 } 1144 back()1145 constexpr const_reference back() const noexcept 1146 { 1147 assert(length > 0); 1148 return *(std::next(begin(), length - 1)); 1149 } 1150 front()1151 constexpr reference front() noexcept 1152 { 1153 assert(length > 0); 1154 return *begin(); 1155 } 1156 front()1157 constexpr const_reference front() const noexcept 1158 { 1159 assert(length > 0); 1160 return *cbegin(); 1161 } 1162 empty()1163 constexpr bool empty() const noexcept { return length == 0; } 1164 size()1165 constexpr size_type size() const noexcept { return length; } 1166 pop_back()1167 constexpr void pop_back() noexcept 1168 { 1169 assert(length > 0); 1170 --length; 1171 } 1172 reserve(size_type n)1173 constexpr void reserve(size_type n) 1174 { 1175 if (n > capacity) { 1176 if (capacity > Size) { 1177 data = (T*)realloc(data, sizeof(T) * n); 1178 } else { 1179 T* ptr = (T*)malloc(sizeof(T) * n); 1180 memcpy(ptr, inline_data, sizeof(T) * length); 1181 data = ptr; 1182 } 1183 capacity = n; 1184 } 1185 } 1186 push_back(const value_type & val)1187 constexpr void push_back(const value_type& val) noexcept 1188 { 1189 if (length == capacity) 1190 reserve(2 * capacity); 1191 1192 *std::next(begin(), length++) = val; 1193 } 1194 emplace_back(Args...args)1195 template <typename... Args> constexpr void emplace_back(Args... args) noexcept 1196 { 1197 if (length == capacity) 1198 reserve(2 * capacity); 1199 1200 *std::next(begin(), length++) = T(args...); 1201 } 1202 clear()1203 constexpr void clear() noexcept 1204 { 1205 if (capacity > Size) 1206 free(data); 1207 length = 0; 1208 capacity = Size; 1209 } 1210 1211 constexpr bool operator==(const small_vec& other) const 1212 { 1213 if (size() != other.size()) 1214 return false; 1215 for (unsigned i = 0; i < size(); i++) { 1216 if (*(std::next(begin(), i)) != other[i]) 1217 return false; 1218 } 1219 return true; 1220 } 1221 1222 private: 1223 uint32_t length = 0; 1224 uint32_t capacity = Size; 1225 union { 1226 T* data = NULL; 1227 T inline_data[Size]; 1228 }; 1229 }; 1230 1231 } // namespace aco 1232 1233 #endif // ACO_UTIL_H 1234