1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2014 Benoit Steiner <[email protected]> 5 // 6 // This Source Code Form is subject to the terms of the Mozilla 7 // Public License v. 2.0. If a copy of the MPL was not distributed 8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 10 #ifndef EIGEN_FIXEDSIZEVECTOR_H 11 #define EIGEN_FIXEDSIZEVECTOR_H 12 13 namespace Eigen { 14 15 /** \class MaxSizeVector 16 * \ingroup Core 17 * 18 * \brief The MaxSizeVector class. 19 * 20 * The %MaxSizeVector provides a subset of std::vector functionality. 21 * 22 * The goal is to provide basic std::vector operations when using 23 * std::vector is not an option (e.g. on GPU or when compiling using 24 * FMA/AVX, as this can cause either compilation failures or illegal 25 * instruction failures). 26 * 27 * Beware: The constructors are not API compatible with these of 28 * std::vector. 29 */ 30 template <typename T> 31 class MaxSizeVector { 32 static const size_t alignment = EIGEN_PLAIN_ENUM_MAX(EIGEN_ALIGNOF(T), sizeof(void*)); 33 public: 34 // Construct a new MaxSizeVector, reserve n elements. 35 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE MaxSizeVector(size_t n)36 explicit MaxSizeVector(size_t n) 37 : reserve_(n), size_(0), 38 data_(static_cast<T*>(internal::handmade_aligned_malloc(n * sizeof(T), alignment))) { 39 } 40 41 // Construct a new MaxSizeVector, reserve and resize to n. 42 // Copy the init value to all elements. 43 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE MaxSizeVector(size_t n,const T & init)44 MaxSizeVector(size_t n, const T& init) 45 : reserve_(n), size_(n), 46 data_(static_cast<T*>(internal::handmade_aligned_malloc(n * sizeof(T), alignment))) { 47 size_t i = 0; 48 EIGEN_TRY 49 { 50 for(; i < size_; ++i) { new (&data_[i]) T(init); } 51 } 52 EIGEN_CATCH(...) 53 { 54 // Construction failed, destruct in reverse order: 55 for(; (i+1) > 0; --i) { data_[i-1].~T(); } 56 internal::handmade_aligned_free(data_); 57 EIGEN_THROW; 58 } 59 } 60 61 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ~MaxSizeVector()62 ~MaxSizeVector() { 63 for (size_t i = size_; i > 0; --i) { 64 data_[i-1].~T(); 65 } 66 internal::handmade_aligned_free(data_); 67 } 68 resize(size_t n)69 void resize(size_t n) { 70 eigen_assert(n <= reserve_); 71 for (; size_ < n; ++size_) { 72 new (&data_[size_]) T; 73 } 74 for (; size_ > n; --size_) { 75 data_[size_-1].~T(); 76 } 77 eigen_assert(size_ == n); 78 } 79 80 // Append new elements (up to reserved size). 81 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE push_back(const T & t)82 void push_back(const T& t) { 83 eigen_assert(size_ < reserve_); 84 new (&data_[size_++]) T(t); 85 } 86 87 // For C++03 compatibility this only takes one argument 88 template<class X> 89 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE emplace_back(const X & x)90 void emplace_back(const X& x) { 91 eigen_assert(size_ < reserve_); 92 new (&data_[size_++]) T(x); 93 } 94 95 96 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 97 const T& operator[] (size_t i) const { 98 eigen_assert(i < size_); 99 return data_[i]; 100 } 101 102 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 103 T& operator[] (size_t i) { 104 eigen_assert(i < size_); 105 return data_[i]; 106 } 107 108 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE back()109 T& back() { 110 eigen_assert(size_ > 0); 111 return data_[size_ - 1]; 112 } 113 114 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE back()115 const T& back() const { 116 eigen_assert(size_ > 0); 117 return data_[size_ - 1]; 118 } 119 120 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE pop_back()121 void pop_back() { 122 eigen_assert(size_ > 0); 123 data_[--size_].~T(); 124 } 125 126 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size()127 size_t size() const { return size_; } 128 129 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE empty()130 bool empty() const { return size_ == 0; } 131 132 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE data()133 T* data() { return data_; } 134 135 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE data()136 const T* data() const { return data_; } 137 138 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE begin()139 T* begin() { return data_; } 140 141 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE end()142 T* end() { return data_ + size_; } 143 144 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE begin()145 const T* begin() const { return data_; } 146 147 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE end()148 const T* end() const { return data_ + size_; } 149 150 private: 151 size_t reserve_; 152 size_t size_; 153 T* data_; 154 }; 155 156 } // namespace Eigen 157 158 #endif // EIGEN_FIXEDSIZEVECTOR_H 159