// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2014 Benoit Steiner // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_FIXEDSIZEVECTOR_H #define EIGEN_FIXEDSIZEVECTOR_H namespace Eigen { /** \class MaxSizeVector * \ingroup Core * * \brief The MaxSizeVector class. * * The %MaxSizeVector provides a subset of std::vector functionality. * * The goal is to provide basic std::vector operations when using * std::vector is not an option (e.g. on GPU or when compiling using * FMA/AVX, as this can cause either compilation failures or illegal * instruction failures). * * Beware: The constructors are not API compatible with these of * std::vector. */ template class MaxSizeVector { static const size_t alignment = EIGEN_PLAIN_ENUM_MAX(EIGEN_ALIGNOF(T), sizeof(void*)); public: // Construct a new MaxSizeVector, reserve n elements. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit MaxSizeVector(size_t n) : reserve_(n), size_(0), data_(static_cast(internal::handmade_aligned_malloc(n * sizeof(T), alignment))) { } // Construct a new MaxSizeVector, reserve and resize to n. // Copy the init value to all elements. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE MaxSizeVector(size_t n, const T& init) : reserve_(n), size_(n), data_(static_cast(internal::handmade_aligned_malloc(n * sizeof(T), alignment))) { size_t i = 0; EIGEN_TRY { for(; i < size_; ++i) { new (&data_[i]) T(init); } } EIGEN_CATCH(...) { // Construction failed, destruct in reverse order: for(; (i+1) > 0; --i) { data_[i-1].~T(); } internal::handmade_aligned_free(data_); EIGEN_THROW; } } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ~MaxSizeVector() { for (size_t i = size_; i > 0; --i) { data_[i-1].~T(); } internal::handmade_aligned_free(data_); } void resize(size_t n) { eigen_assert(n <= reserve_); for (; size_ < n; ++size_) { new (&data_[size_]) T; } for (; size_ > n; --size_) { data_[size_-1].~T(); } eigen_assert(size_ == n); } // Append new elements (up to reserved size). EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void push_back(const T& t) { eigen_assert(size_ < reserve_); new (&data_[size_++]) T(t); } // For C++03 compatibility this only takes one argument template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void emplace_back(const X& x) { eigen_assert(size_ < reserve_); new (&data_[size_++]) T(x); } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& operator[] (size_t i) const { eigen_assert(i < size_); return data_[i]; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& operator[] (size_t i) { eigen_assert(i < size_); return data_[i]; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& back() { eigen_assert(size_ > 0); return data_[size_ - 1]; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& back() const { eigen_assert(size_ > 0); return data_[size_ - 1]; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pop_back() { eigen_assert(size_ > 0); data_[--size_].~T(); } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t size() const { return size_; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool empty() const { return size_ == 0; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T* data() { return data_; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T* data() const { return data_; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T* begin() { return data_; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T* end() { return data_ + size_; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T* begin() const { return data_; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T* end() const { return data_ + size_; } private: size_t reserve_; size_t size_; T* data_; }; } // namespace Eigen #endif // EIGEN_FIXEDSIZEVECTOR_H