123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- #ifndef CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
- #define CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
- #include <Eigen/Core> // For Eigen::aligned_allocator
- #include <algorithm>
- #include <array>
- #include <cstddef>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include "ceres/internal/memory.h"
- #include "glog/logging.h"
- namespace ceres::internal {
- constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);
- template <typename T>
- using FixedArrayDefaultAllocator =
- typename std::conditional<std::is_trivial<T>::value,
- std::allocator<T>,
- Eigen::aligned_allocator<T>>::type;
- template <typename T,
- size_t N = kFixedArrayUseDefault,
- typename A = FixedArrayDefaultAllocator<T>>
- class FixedArray {
- static_assert(!std::is_array<T>::value || std::extent<T>::value > 0,
- "Arrays with unknown bounds cannot be used with FixedArray.");
- static constexpr size_t kInlineBytesDefault = 256;
- using AllocatorTraits = std::allocator_traits<A>;
-
-
- template <typename Iterator>
- using EnableIfForwardIterator = typename std::enable_if<std::is_convertible<
- typename std::iterator_traits<Iterator>::iterator_category,
- std::forward_iterator_tag>::value>::type;
- static constexpr bool DefaultConstructorIsNonTrivial() {
- return !std::is_trivially_default_constructible<StorageElement>::value;
- }
- public:
- using allocator_type = typename AllocatorTraits::allocator_type;
- using value_type = typename AllocatorTraits::value_type;
- using pointer = typename AllocatorTraits::pointer;
- using const_pointer = typename AllocatorTraits::const_pointer;
- using reference = value_type&;
- using const_reference = const value_type&;
- using size_type = typename AllocatorTraits::size_type;
- using difference_type = typename AllocatorTraits::difference_type;
- using iterator = pointer;
- using const_iterator = const_pointer;
- using reverse_iterator = std::reverse_iterator<iterator>;
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- static constexpr size_type inline_elements =
- (N == kFixedArrayUseDefault ? kInlineBytesDefault / sizeof(value_type)
- : static_cast<size_type>(N));
- FixedArray(const FixedArray& other,
- const allocator_type& a = allocator_type())
- : FixedArray(other.begin(), other.end(), a) {}
- FixedArray(FixedArray&& other, const allocator_type& a = allocator_type())
- : FixedArray(std::make_move_iterator(other.begin()),
- std::make_move_iterator(other.end()),
- a) {}
-
-
- explicit FixedArray(size_type n, const allocator_type& a = allocator_type())
- : storage_(n, a) {
- if (DefaultConstructorIsNonTrivial()) {
- ConstructRange(storage_.alloc(), storage_.begin(), storage_.end());
- }
- }
-
- FixedArray(size_type n,
- const value_type& val,
- const allocator_type& a = allocator_type())
- : storage_(n, a) {
- ConstructRange(storage_.alloc(), storage_.begin(), storage_.end(), val);
- }
-
- FixedArray(std::initializer_list<value_type> init_list,
- const allocator_type& a = allocator_type())
- : FixedArray(init_list.begin(), init_list.end(), a) {}
-
-
-
- template <typename Iterator, EnableIfForwardIterator<Iterator>* = nullptr>
- FixedArray(Iterator first,
- Iterator last,
- const allocator_type& a = allocator_type())
- : storage_(std::distance(first, last), a) {
- CopyRange(storage_.alloc(), storage_.begin(), first, last);
- }
- ~FixedArray() noexcept {
- for (auto* cur = storage_.begin(); cur != storage_.end(); ++cur) {
- AllocatorTraits::destroy(storage_.alloc(), cur);
- }
- }
-
-
- void operator=(FixedArray&&) = delete;
- void operator=(const FixedArray&) = delete;
-
-
-
- size_type size() const { return storage_.size(); }
-
-
-
-
-
- constexpr size_type max_size() const {
- return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);
- }
-
-
-
- bool empty() const { return size() == 0; }
-
-
-
- size_t memsize() const { return size() * sizeof(value_type); }
-
-
-
-
- const_pointer data() const { return AsValueType(storage_.begin()); }
-
-
-
- pointer data() { return AsValueType(storage_.begin()); }
-
-
-
-
- reference operator[](size_type i) {
- DCHECK_LT(i, size());
- return data()[i];
- }
-
-
-
- const_reference operator[](size_type i) const {
- DCHECK_LT(i, size());
- return data()[i];
- }
-
-
-
- reference front() { return *begin(); }
-
-
- const_reference front() const { return *begin(); }
-
-
-
- reference back() { return *(end() - 1); }
-
-
- const_reference back() const { return *(end() - 1); }
-
-
-
- iterator begin() { return data(); }
-
-
- const_iterator begin() const { return data(); }
-
-
-
- const_iterator cbegin() const { return begin(); }
-
-
-
- iterator end() { return data() + size(); }
-
-
- const_iterator end() const { return data() + size(); }
-
-
-
- const_iterator cend() const { return end(); }
-
-
-
- reverse_iterator rbegin() { return reverse_iterator(end()); }
-
-
- const_reverse_iterator rbegin() const {
- return const_reverse_iterator(end());
- }
-
-
-
- const_reverse_iterator crbegin() const { return rbegin(); }
-
-
-
- reverse_iterator rend() { return reverse_iterator(begin()); }
-
-
- const_reverse_iterator rend() const {
- return const_reverse_iterator(begin());
- }
-
-
-
- const_reverse_iterator crend() const { return rend(); }
-
-
-
- void fill(const value_type& val) { std::fill(begin(), end(), val); }
-
-
- friend bool operator==(const FixedArray& lhs, const FixedArray& rhs) {
- return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
- }
- friend bool operator!=(const FixedArray& lhs, const FixedArray& rhs) {
- return !(lhs == rhs);
- }
- friend bool operator<(const FixedArray& lhs, const FixedArray& rhs) {
- return std::lexicographical_compare(
- lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
- }
- friend bool operator>(const FixedArray& lhs, const FixedArray& rhs) {
- return rhs < lhs;
- }
- friend bool operator<=(const FixedArray& lhs, const FixedArray& rhs) {
- return !(rhs < lhs);
- }
- friend bool operator>=(const FixedArray& lhs, const FixedArray& rhs) {
- return !(lhs < rhs);
- }
- private:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- template <typename OuterT,
- typename InnerT = typename std::remove_extent<OuterT>::type,
- size_t InnerN = std::extent<OuterT>::value>
- struct StorageElementWrapper {
- InnerT array[InnerN];
- };
- using StorageElement =
- typename std::conditional<std::is_array<value_type>::value,
- StorageElementWrapper<value_type>,
- value_type>::type;
- static pointer AsValueType(pointer ptr) { return ptr; }
- static pointer AsValueType(StorageElementWrapper<value_type>* ptr) {
- return std::addressof(ptr->array);
- }
- static_assert(sizeof(StorageElement) == sizeof(value_type));
- static_assert(alignof(StorageElement) == alignof(value_type));
- class NonEmptyInlinedStorage {
- public:
- StorageElement* data() { return reinterpret_cast<StorageElement*>(buff_); }
- void AnnotateConstruct(size_type) {}
- void AnnotateDestruct(size_type) {}
-
-
-
-
- private:
-
- alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
-
- };
- class EmptyInlinedStorage {
- public:
- StorageElement* data() { return nullptr; }
- void AnnotateConstruct(size_type) {}
- void AnnotateDestruct(size_type) {}
- };
- using InlinedStorage =
- typename std::conditional<inline_elements == 0,
- EmptyInlinedStorage,
- NonEmptyInlinedStorage>::type;
-
-
-
-
-
-
-
-
- class Storage : public InlinedStorage {
- public:
- Storage(size_type n, const allocator_type& a)
- : size_alloc_(n, a), data_(InitializeData()) {}
- ~Storage() noexcept {
- if (UsingInlinedStorage(size())) {
- InlinedStorage::AnnotateDestruct(size());
- } else {
- AllocatorTraits::deallocate(alloc(), AsValueType(begin()), size());
- }
- }
- size_type size() const { return std::get<0>(size_alloc_); }
- StorageElement* begin() const { return data_; }
- StorageElement* end() const { return begin() + size(); }
- allocator_type& alloc() { return std::get<1>(size_alloc_); }
- private:
- static bool UsingInlinedStorage(size_type n) {
- return n <= inline_elements;
- }
- StorageElement* InitializeData() {
- if (UsingInlinedStorage(size())) {
- InlinedStorage::AnnotateConstruct(size());
- return InlinedStorage::data();
- } else {
- return reinterpret_cast<StorageElement*>(
- AllocatorTraits::allocate(alloc(), size()));
- }
- }
-
-
- std::tuple<size_type, allocator_type> size_alloc_;
- StorageElement* data_;
- };
- Storage storage_;
- };
- template <typename T, size_t N, typename A>
- constexpr size_t FixedArray<T, N, A>::kInlineBytesDefault;
- template <typename T, size_t N, typename A>
- constexpr typename FixedArray<T, N, A>::size_type
- FixedArray<T, N, A>::inline_elements;
- }
- #endif
|