make fixed_size matrices conform to std::is_standard_layout
diff --git a/Eigen/src/Core/DenseStorage.h b/Eigen/src/Core/DenseStorage.h index 90bc94e..d62586c 100644 --- a/Eigen/src/Core/DenseStorage.h +++ b/Eigen/src/Core/DenseStorage.h
@@ -30,10 +30,10 @@ #if defined(EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT) #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(Alignment) #else -#define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(Alignment) \ - eigen_assert((internal::is_constant_evaluated() || (std::uintptr_t(array) % Alignment == 0)) && \ - "this assertion is explained here: " \ - "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \ +#define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(Alignment) \ + eigen_assert((is_constant_evaluated() || (std::uintptr_t(array) % Alignment == 0)) && \ + "this assertion is explained here: " \ + "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \ " **** READ THIS WEB PAGE !!! ****"); #endif @@ -48,6 +48,7 @@ * Static array. If the MatrixOrArrayOptions require auto-alignment, the array will be automatically aligned: * to 16 bytes boundary if the total size is a multiple of 16 bytes. */ + template <typename T, int Size, int MatrixOrArrayOptions, int Alignment = (MatrixOrArrayOptions & DontAlign) ? 0 : compute_default_alignment<T, Size>::value> struct plain_array { @@ -78,92 +79,454 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr plain_array() = default; }; -// this class is intended to be inherited by DenseStorage to take advantage of empty base optimization -template <int Rows, int Cols> -struct DenseStorageIndices { - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices() = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices(const DenseStorageIndices&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices(DenseStorageIndices&&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices& operator=(const DenseStorageIndices&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices& operator=(DenseStorageIndices&&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices(Index /*rows*/, Index /*cols*/) {} +template <typename T, int Size, int Options, int Alignment> +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap_plain_array(plain_array<T, Size, Options, Alignment>& a, + plain_array<T, Size, Options, Alignment>& b, + Index a_size, Index b_size) { + Index common_size = numext::mini(a_size, b_size); + std::swap_ranges(a.array, a.array + common_size, b.array); + if (a_size > b_size) + smart_copy(a.array + common_size, a.array + a_size, b.array + common_size); + else if (b_size > a_size) + smart_copy(b.array + common_size, b.array + b_size, a.array + common_size); +} + +template <typename T, int Size, int Rows, int Cols, int Options> +class DenseStorage_impl { + plain_array<T, Size, Options> m_data; + + public: +#ifndef EIGEN_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl&) = default; +#else + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl() { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size) + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size) + smart_copy(other.m_data.array, other.m_data.array + Size, m_data.array); + } +#endif + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index /*size*/, Index /*rows*/, Index /*cols*/) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) { + numext::swap(m_data, other.m_data); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index /*size*/, Index /*rows*/, + Index /*cols*/) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index /*size*/, Index /*rows*/, Index /*cols*/) {} EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return Rows; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return Cols; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index size() const { return Rows * Cols; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void set(Index /*rows*/, Index /*cols*/) {} - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void swap(DenseStorageIndices& /*other*/) noexcept {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return m_data.array; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return m_data.array; } }; -template <int Rows> -struct DenseStorageIndices<Rows, Dynamic> { - Index m_cols; +template <typename T, int Size, int Cols, int Options> +class DenseStorage_impl<T, Size, Dynamic, Cols, Options> { + plain_array<T, Size, Options> m_data; + Index m_rows = 0; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices() : m_cols(0) {} - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices(const DenseStorageIndices&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices(DenseStorageIndices&&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices& operator=(const DenseStorageIndices&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices& operator=(DenseStorageIndices&&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices(Index /*rows*/, Index cols) : m_cols(cols) {} - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return Rows; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return m_cols; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index size() const { return Rows * m_cols; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void set(Index /*rows*/, Index cols) { m_cols = cols; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void swap(DenseStorageIndices& other) noexcept { - numext::swap(m_cols, other.m_cols); + public: + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) + : m_rows(other.m_rows) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = other.size()) + smart_copy(other.m_data.array, other.m_data.array + other.size(), m_data.array); } -}; -template <int Cols> -struct DenseStorageIndices<Dynamic, Cols> { - Index m_rows; - - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices() : m_rows(0) {} - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices(const DenseStorageIndices&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices(DenseStorageIndices&&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices& operator=(const DenseStorageIndices&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices& operator=(DenseStorageIndices&&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices(Index rows, Index /*cols*/) : m_rows(rows) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index size, Index rows, Index /*cols*/) + : m_rows(rows) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + EIGEN_UNUSED_VARIABLE(size) + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl& other) { + smart_copy(other.m_data.array, other.m_data.array + other.size(), m_data.array); + m_rows = other.m_rows; + return *this; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) { + swap_plain_array(m_data, other.m_data, size(), other.size()); + numext::swap(m_rows, other.m_rows); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index /*size*/, Index rows, Index /*cols*/) { + m_rows = rows; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index /*size*/, Index rows, Index /*cols*/) { + m_rows = rows; + } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return m_rows; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return Cols; } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index size() const { return m_rows * Cols; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void set(Index rows, Index /*cols*/) { m_rows = rows; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void swap(DenseStorageIndices& other) noexcept { - numext::swap(m_rows, other.m_rows); - } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return m_data.array; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return m_data.array; } }; -template <> -struct DenseStorageIndices<Dynamic, Dynamic> { - Index m_rows; - Index m_cols; +template <typename T, int Size, int Rows, int Options> +class DenseStorage_impl<T, Size, Rows, Dynamic, Options> { + plain_array<T, Size, Options> m_data; + Index m_cols = 0; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices() : m_rows(0), m_cols(0) {} - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices(const DenseStorageIndices&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices(DenseStorageIndices&&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices& operator=(const DenseStorageIndices&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices& operator=(DenseStorageIndices&&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorageIndices(Index rows, Index cols) - : m_rows(rows), m_cols(cols) {} - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return m_rows; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return m_cols; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index size() const { return m_rows * m_cols; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void set(Index rows, Index cols) { - m_rows = rows; + public: + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) + : m_cols(other.m_cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = other.size()) + smart_copy(other.m_data.array, other.m_data.array + other.size(), m_data.array); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index size, Index /*rows*/, Index cols) + : m_cols(cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + EIGEN_UNUSED_VARIABLE(size) + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl& other) { + smart_copy(other.m_data.array, other.m_data.array + other.size(), m_data.array); + m_cols = other.m_cols; + return *this; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) { + swap_plain_array(m_data, other.m_data, size(), other.size()); + numext::swap(m_cols, other.m_cols); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index /*size*/, Index /*rows*/, Index cols) { m_cols = cols; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void swap(DenseStorageIndices& other) noexcept { + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index /*size*/, Index /*rows*/, Index cols) { + m_cols = cols; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return Rows; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return m_cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index size() const { return Rows * m_cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return m_data.array; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return m_data.array; } +}; +template <typename T, int Size, int Options> +class DenseStorage_impl<T, Size, Dynamic, Dynamic, Options> { + plain_array<T, Size, Options> m_data; + Index m_rows = 0; + Index m_cols = 0; + + public: + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) + : m_rows(other.m_rows), m_cols(other.m_cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = other.size()) + smart_copy(other.m_data.array, other.m_data.array + other.size(), m_data.array); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index size, Index rows, Index cols) + : m_rows(rows), m_cols(cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + EIGEN_UNUSED_VARIABLE(size) + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl& other) { + smart_copy(other.m_data.array, other.m_data.array + other.size(), m_data.array); + m_rows = other.m_rows; + m_cols = other.m_cols; + return *this; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) { + swap_plain_array(m_data, other.m_data, size(), other.size()); numext::swap(m_rows, other.m_rows); numext::swap(m_cols, other.m_cols); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index /*size*/, Index rows, Index cols) { + m_rows = rows; + m_cols = cols; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index /*size*/, Index rows, Index cols) { + m_rows = rows; + m_cols = cols; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return m_rows; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return m_cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index size() const { return m_rows * m_cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return m_data.array; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return m_data.array; } }; - -template <int Size, int Rows, int Cols> -struct use_trivial_ctors { - static constexpr bool value = (Size >= 0) && (Rows >= 0) && (Cols >= 0) && (Size == Rows * Cols); +// null matrix variants +template <typename T, int Rows, int Cols, int Options> +class DenseStorage_impl<T, 0, Rows, Cols, Options> { + public: + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index /*size*/, Index /*rows*/, Index /*cols*/) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl&) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index /*size*/, Index /*rows*/, + Index /*cols*/) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index /*size*/, Index /*rows*/, Index /*cols*/) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return Rows; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return Cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index size() const { return Rows * Cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return nullptr; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return nullptr; } }; +template <typename T, int Cols, int Options> +class DenseStorage_impl<T, 0, Dynamic, Cols, Options> { + Index m_rows = 0; + public: + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index /*size*/, Index rows, Index /*cols*/) + : m_rows(rows) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) noexcept { + numext::swap(m_rows, other.m_rows); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index /*size*/, Index rows, Index /*cols*/) { + m_rows = rows; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index /*size*/, Index rows, Index /*cols*/) { + m_rows = rows; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return m_rows; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return Cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index size() const { return m_rows * Cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return nullptr; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return nullptr; } +}; +template <typename T, int Rows, int Options> +class DenseStorage_impl<T, 0, Rows, Dynamic, Options> { + Index m_cols = 0; + + public: + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index /*size*/, Index /*rows*/, Index cols) + : m_cols(cols) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) noexcept { + numext::swap(m_cols, other.m_cols); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index /*size*/, Index /*rows*/, Index cols) { + m_cols = cols; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index /*size*/, Index /*rows*/, Index cols) { + m_cols = cols; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return Rows; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return m_cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index size() const { return Rows * m_cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return nullptr; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return nullptr; } +}; +template <typename T, int Options> +class DenseStorage_impl<T, 0, Dynamic, Dynamic, Options> { + Index m_rows = 0; + Index m_cols = 0; + + public: + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index /*size*/, Index rows, Index cols) + : m_rows(rows), m_cols(cols) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) noexcept { + numext::swap(m_rows, other.m_rows); + numext::swap(m_cols, other.m_cols); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index /*size*/, Index rows, Index cols) { + m_rows = rows; + m_cols = cols; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index /*size*/, Index rows, Index cols) { + m_rows = rows; + m_cols = cols; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return m_rows; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return m_cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index size() const { return m_rows * m_cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return nullptr; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return nullptr; } +}; +// fixed-size matrix with dynamic memory allocation not currently supported +template <typename T, int Rows, int Cols, int Options> +class DenseStorage_impl<T, Dynamic, Rows, Cols, Options> {}; +// dynamic-sized variants +template <typename T, int Cols, int Options> +class DenseStorage_impl<T, Dynamic, Dynamic, Cols, Options> { + static constexpr bool Align = (Options & DontAlign) == 0; + T* m_data = nullptr; + Index m_rows = 0; + + public: + static constexpr int Size = Dynamic; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) + : m_data(conditional_aligned_new_auto<T, Align>(other.size())), m_rows(other.m_rows) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = other.size()) + smart_copy(other.m_data, other.m_data + other.size(), m_data); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index size, Index rows, Index /*cols*/) + : m_data(conditional_aligned_new_auto<T, Align>(size)), m_rows(rows) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(DenseStorage_impl&& other) noexcept + : m_data(other.m_data), m_rows(other.m_rows) { + other.m_data = nullptr; + other.m_rows = 0; + } + EIGEN_DEVICE_FUNC ~DenseStorage_impl() { conditional_aligned_delete_auto<T, Align>(m_data, size()); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl& other) { + resize(other.size(), other.rows(), other.cols()); + smart_copy(other.m_data, other.m_data + other.size(), m_data); + return *this; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(DenseStorage_impl&& other) noexcept { + this->swap(other); + return *this; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) noexcept { + numext::swap(m_data, other.m_data); + numext::swap(m_rows, other.m_rows); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index size, Index rows, Index /*cols*/) { + m_data = conditional_aligned_realloc_new_auto<T, Align>(m_data, size, this->size()); + m_rows = rows; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index size, Index rows, Index /*cols*/) { + Index oldSize = this->size(); + if (oldSize != size) { + conditional_aligned_delete_auto<T, Align>(m_data, oldSize); + m_data = conditional_aligned_new_auto<T, Align>(size); + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + } + m_rows = rows; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return m_rows; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return Cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index size() const { return m_rows * Cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return m_data; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return m_data; } +}; +template <typename T, int Rows, int Options> +class DenseStorage_impl<T, Dynamic, Rows, Dynamic, Options> { + static constexpr bool Align = (Options & DontAlign) == 0; + T* m_data = nullptr; + Index m_cols = 0; + + public: + static constexpr int Size = Dynamic; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) + : m_data(conditional_aligned_new_auto<T, Align>(other.size())), m_cols(other.m_cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = other.size()) + smart_copy(other.m_data, other.m_data + other.size(), m_data); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index size, Index /*rows*/, Index cols) + : m_data(conditional_aligned_new_auto<T, Align>(size)), m_cols(cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(DenseStorage_impl&& other) noexcept + : m_data(other.m_data), m_cols(other.m_cols) { + other.m_data = nullptr; + other.m_cols = 0; + } + EIGEN_DEVICE_FUNC ~DenseStorage_impl() { conditional_aligned_delete_auto<T, Align>(m_data, size()); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl& other) { + resize(other.size(), other.rows(), other.cols()); + smart_copy(other.m_data, other.m_data + other.size(), m_data); + return *this; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(DenseStorage_impl&& other) noexcept { + this->swap(other); + return *this; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) noexcept { + numext::swap(m_data, other.m_data); + numext::swap(m_cols, other.m_cols); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index size, Index /*rows*/, Index cols) { + m_data = conditional_aligned_realloc_new_auto<T, Align>(m_data, size, this->size()); + m_cols = cols; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index size, Index /*rows*/, Index cols) { + Index oldSize = this->size(); + if (oldSize != size) { + conditional_aligned_delete_auto<T, Align>(m_data, oldSize); + m_data = conditional_aligned_new_auto<T, Align>(size); + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + } + m_cols = cols; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return Rows; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return m_cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index size() const { return Rows * m_cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return m_data; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return m_data; } +}; +template <typename T, int Options> +class DenseStorage_impl<T, Dynamic, Dynamic, Dynamic, Options> { + static constexpr bool Align = (Options & DontAlign) == 0; + T* m_data = nullptr; + Index m_rows = 0; + Index m_cols = 0; + + public: + static constexpr int Size = Dynamic; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) + : m_data(conditional_aligned_new_auto<T, Align>(other.size())), m_rows(other.m_rows), m_cols(other.m_cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = other.size()) + smart_copy(other.m_data, other.m_data + other.size(), m_data); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index size, Index rows, Index cols) + : m_data(conditional_aligned_new_auto<T, Align>(size)), m_rows(rows), m_cols(cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(DenseStorage_impl&& other) noexcept + : m_data(other.m_data), m_rows(other.m_rows), m_cols(other.m_cols) { + other.m_data = nullptr; + other.m_rows = 0; + other.m_cols = 0; + } + EIGEN_DEVICE_FUNC ~DenseStorage_impl() { conditional_aligned_delete_auto<T, Align>(m_data, size()); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl& other) { + resize(other.size(), other.rows(), other.cols()); + smart_copy(other.m_data, other.m_data + other.size(), m_data); + return *this; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(DenseStorage_impl&& other) noexcept { + this->swap(other); + return *this; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) noexcept { + numext::swap(m_data, other.m_data); + numext::swap(m_rows, other.m_rows); + numext::swap(m_cols, other.m_cols); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index size, Index rows, Index cols) { + m_data = conditional_aligned_realloc_new_auto<T, Align>(m_data, size, this->size()); + m_rows = rows; + m_cols = cols; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index size, Index rows, Index cols) { + Index oldSize = this->size(); + if (oldSize != size) { + conditional_aligned_delete_auto<T, Align>(m_data, oldSize); + m_data = conditional_aligned_new_auto<T, Align>(size); + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + } + m_rows = rows; + m_cols = cols; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return m_rows; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return m_cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index size() const { return m_rows * m_cols; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return m_data; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return m_data; } +}; +template <typename T, int Size, int Rows, int Cols> +struct use_default_move { + static constexpr bool DynamicObject = Size == Dynamic; + static constexpr bool TrivialObject = + (!NumTraits<T>::RequireInitialization) && (Rows >= 0) && (Cols >= 0) && (Size == Rows * Cols); + static constexpr bool value = DynamicObject || TrivialObject; +}; } // end namespace internal /** \internal * - * \class DenseStorage + * \class DenseStorage_impl * \ingroup Core_Module * * \brief Stores the data of a matrix @@ -174,201 +537,42 @@ * \sa Matrix */ template <typename T, int Size, int Rows, int Cols, int Options, - bool Trivial = internal::use_trivial_ctors<Size, Rows, Cols>::value> -class DenseStorage; - -// fixed-size storage with fixed dimensions -template <typename T, int Size, int Rows, int Cols, int Options> -class DenseStorage<T, Size, Rows, Cols, Options, true> : internal::DenseStorageIndices<Rows, Cols> { - using Base = internal::DenseStorageIndices<Rows, Cols>; - - internal::plain_array<T, Size, Options> m_data; + bool Trivial = internal::use_default_move<T, Size, Rows, Cols>::value> +class DenseStorage : public internal::DenseStorage_impl<T, Size, Rows, Cols, Options> { + using Base = internal::DenseStorage_impl<T, Size, Rows, Cols, Options>; public: - using Base::cols; - using Base::rows; -#ifndef EIGEN_DENSE_STORAGE_CTOR_PLUGIN - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseStorage() = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(const DenseStorage&) = default; -#else - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseStorage() { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size) } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(const DenseStorage& other) - : Base(other), m_data(other.m_data) { - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size) - } -#endif - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(DenseStorage&&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage& operator=(const DenseStorage&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage& operator=(DenseStorage&&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(Index size, Index rows, Index cols) : Base(rows, cols) { - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) - EIGEN_UNUSED_VARIABLE(size); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage& other) { - numext::swap(m_data, other.m_data); - Base::swap(other); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index /*size*/, Index rows, Index cols) { - Base::set(rows, cols); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index /*size*/, Index rows, Index cols) { - Base::set(rows, cols); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return m_data.array; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return m_data.array; } -}; -// fixed-size storage with dynamic dimensions -template <typename T, int Size, int Rows, int Cols, int Options> -class DenseStorage<T, Size, Rows, Cols, Options, false> : internal::DenseStorageIndices<Rows, Cols> { - using Base = internal::DenseStorageIndices<Rows, Cols>; - - internal::plain_array<T, Size, Options> m_data; - - public: - using Base::cols; - using Base::rows; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseStorage() = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(const DenseStorage& other) : Base(other), m_data() { - Index size = other.size(); - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) - internal::smart_copy(other.m_data.array, other.m_data.array + size, m_data.array); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(DenseStorage&& other) : Base(other), m_data() { - Index size = other.size(); - internal::smart_move(other.m_data.array, other.m_data.array + size, m_data.array); - other.resize(Size, 0, 0); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage& operator=(const DenseStorage& other) { - Base::set(other.rows(), other.cols()); - Index size = other.size(); - internal::smart_copy(other.m_data.array, other.m_data.array + size, m_data.array); - return *this; - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage& operator=(DenseStorage&& other) { - Base::set(other.rows(), other.cols()); - Index size = other.size(); - internal::smart_move(other.m_data.array, other.m_data.array + size, m_data.array); - other.resize(Size, 0, 0); - return *this; - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(Index size, Index rows, Index cols) : Base(rows, cols) { - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) - EIGEN_UNUSED_VARIABLE(size); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage& other) { - Index thisSize = this->size(); - Index otherSize = other.size(); - Index commonSize = numext::mini(thisSize, otherSize); - std::swap_ranges(m_data.array, m_data.array + commonSize, other.m_data.array); - if (thisSize > otherSize) - internal::smart_move(m_data.array + commonSize, m_data.array + thisSize, other.m_data.array + commonSize); - else if (otherSize > thisSize) - internal::smart_move(other.m_data.array + commonSize, other.m_data.array + otherSize, m_data.array + commonSize); - Base::swap(other); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index /*size*/, Index rows, Index cols) { - Base::set(rows, cols); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index /*size*/, Index rows, Index cols) { - Base::set(rows, cols); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return m_data.array; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return m_data.array; } -}; -// null matrix specialization -template <typename T, int Rows, int Cols, int Options> -class DenseStorage<T, 0, Rows, Cols, Options, true> : internal::DenseStorageIndices<Rows, Cols> { - using Base = internal::DenseStorageIndices<Rows, Cols>; - - public: - using Base::cols; - using Base::rows; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage() = default; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(const DenseStorage&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(DenseStorage&&) = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(Index size, Index rows, Index cols) + : Base(size, rows, cols) {} EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage& operator=(const DenseStorage&) = default; + // if DenseStorage meets the requirements of use_default_move, then use the move construction and move assignment + // operation defined in DenseStorage_impl, or the compiler-generated version if none is defined + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(DenseStorage&&) = default; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage& operator=(DenseStorage&&) = default; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(Index /*size*/, Index rows, Index cols) - : Base(rows, cols) {} - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage& other) noexcept { Base::swap(other); } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index /*size*/, Index rows, Index cols) { - Base::set(rows, cols); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index /*size*/, Index rows, Index cols) { - Base::set(rows, cols); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return nullptr; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return nullptr; } }; -// dynamic matrix specialization -template <typename T, int Rows, int Cols, int Options> -class DenseStorage<T, Dynamic, Rows, Cols, Options, false> : internal::DenseStorageIndices<Rows, Cols> { - using Base = internal::DenseStorageIndices<Rows, Cols>; - static constexpr int Size = Dynamic; - static constexpr bool Align = (Options & DontAlign) == 0; - - T* m_data; +template <typename T, int Size, int Rows, int Cols, int Options> +class DenseStorage<T, Size, Rows, Cols, Options, false> + : public internal::DenseStorage_impl<T, Size, Rows, Cols, Options> { + using Base = internal::DenseStorage_impl<T, Size, Rows, Cols, Options>; public: - using Base::cols; - using Base::rows; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage() : m_data(nullptr) {} - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(const DenseStorage& other) - : Base(other), m_data(internal::conditional_aligned_new_auto<T, Align>(other.size())) { - Index size = other.size(); - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) - internal::smart_copy(other.m_data, other.m_data + size, m_data); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(DenseStorage&& other) noexcept - : Base(other), m_data(other.m_data) { - other.set(0, 0); - other.m_data = nullptr; - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage& operator=(const DenseStorage& other) { - Base::set(other.rows(), other.cols()); - Index size = other.size(); - m_data = internal::conditional_aligned_new_auto<T, Align>(size); - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) - internal::smart_copy(other.m_data, other.m_data + size, m_data); - return *this; - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage& operator=(DenseStorage&& other) noexcept { - this->swap(other); - return *this; - } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(const DenseStorage&) = default; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(Index size, Index rows, Index cols) - : Base(rows, cols), m_data(internal::conditional_aligned_new_auto<T, Align>(size)) { - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + : Base(size, rows, cols) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage& operator=(const DenseStorage&) = default; + // if DenseStorage does not meet the requirements of use_default_move, then defer to the copy construction and copy + // assignment behavior + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage(DenseStorage&& other) + : DenseStorage(static_cast<const DenseStorage&>(other)) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage& operator=(DenseStorage&& other) { + *this = other; + return *this; } - EIGEN_DEVICE_FUNC ~DenseStorage() { - Index size = this->size(); - internal::conditional_aligned_delete_auto<T, Align>(m_data, size); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage& other) noexcept { - numext::swap(m_data, other.m_data); - Base::swap(other); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index size, Index rows, Index cols) { - Index oldSize = this->size(); - m_data = internal::conditional_aligned_realloc_new_auto<T, Align>(m_data, size, oldSize); - Base::set(rows, cols); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index size, Index rows, Index cols) { - Index oldSize = this->size(); - if (size != oldSize) { - internal::conditional_aligned_delete_auto<T, Align>(m_data, oldSize); - if (size > 0) // >0 and not simply !=0 to let the compiler knows that size cannot be negative - { - m_data = internal::conditional_aligned_new_auto<T, Align>(size); - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) - } else - m_data = nullptr; - } - Base::set(rows, cols); - } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr T* data() { return m_data; } - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const T* data() const { return m_data; } }; + } // end namespace Eigen #endif // EIGEN_MATRIX_H
diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index d59071f..2acdd9d 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h
@@ -147,7 +147,7 @@ check_that_malloc_is_allowed(); EIGEN_USING_STD(malloc) void* original = malloc(size + alignment); - if (original == 0) return 0; + if (original == nullptr) return nullptr; uint8_t offset = static_cast<uint8_t>(alignment - (reinterpret_cast<std::size_t>(original) & (alignment - 1))); void* aligned = static_cast<void*>(static_cast<uint8_t*>(original) + offset); *(static_cast<uint8_t*>(aligned) - 1) = offset; @@ -391,7 +391,8 @@ template <typename T> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void check_size_for_overflow(std::size_t size) { - if (size > std::size_t(-1) / sizeof(T)) throw_std_bad_alloc(); + constexpr std::size_t max_elements = PTRDIFF_MAX / sizeof(T); + if (size > max_elements) throw_std_bad_alloc(); } /** \internal Allocates \a size objects of type T. The returned pointer is guaranteed to have 16 bytes alignment. @@ -473,7 +474,7 @@ template <typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned_new_auto(std::size_t size) { - if (size == 0) return 0; // short-cut. Also fixes Bug 884 + if (size == 0) return nullptr; // short-cut. Also fixes Bug 884 check_size_for_overflow<T>(size); T* result = static_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T) * size)); if (NumTraits<T>::RequireInitialization) {
diff --git a/test/MovableScalar.h b/test/MovableScalar.h index c8bf546..6a046de 100644 --- a/test/MovableScalar.h +++ b/test/MovableScalar.h
@@ -10,24 +10,42 @@ #ifndef EIGEN_MISC_MOVABLE_SCALAR_H #define EIGEN_MISC_MOVABLE_SCALAR_H -#include <vector> - namespace Eigen { -template <typename Scalar, typename Base = std::vector<Scalar>> -struct MovableScalar : public Base { - MovableScalar() = default; - ~MovableScalar() = default; - MovableScalar(const MovableScalar&) = default; - MovableScalar(MovableScalar&& other) = default; - MovableScalar& operator=(const MovableScalar&) = default; - MovableScalar& operator=(MovableScalar&& other) = default; - MovableScalar(Scalar scalar) : Base(100, scalar) {} +template <typename Scalar> +struct MovableScalar { + MovableScalar() : m_data(new Scalar) {} + ~MovableScalar() { delete m_data; } + MovableScalar(const MovableScalar& other) : m_data(new Scalar) { set(other.get()); } + MovableScalar(MovableScalar&& other) noexcept : m_data(other.m_data) { other.m_data = nullptr; } + MovableScalar& operator=(const MovableScalar& other) { + set(other.get()); + return *this; + } + MovableScalar& operator=(MovableScalar&& other) noexcept { + m_data = other.m_data; + other.m_data = nullptr; + return *this; + } + MovableScalar(const Scalar& scalar) : m_data(new Scalar) { set(scalar); } - operator Scalar() const { return this->size() > 0 ? this->back() : Scalar(); } + operator Scalar() const { return get(); } + + private: + void set(const Scalar& value) { + eigen_assert(m_data != nullptr); + // suppress compiler warnings + if (m_data != nullptr) *m_data = value; + } + Scalar get() const { + eigen_assert(m_data != nullptr); + // suppress compiler warnings + return m_data == nullptr ? Scalar() : *m_data; + } + Scalar* m_data = nullptr; }; template <typename Scalar> -struct NumTraits<MovableScalar<Scalar>> : GenericNumTraits<Scalar> { +struct NumTraits<MovableScalar<Scalar>> : NumTraits<Scalar> { enum { RequireInitialization = 1 }; };
diff --git a/test/dense_storage.cpp b/test/dense_storage.cpp index 5d0083f..0f6ab64 100644 --- a/test/dense_storage.cpp +++ b/test/dense_storage.cpp
@@ -11,29 +11,38 @@ #include "main.h" #include "AnnoyingScalar.h" +#include "MovableScalar.h" #include "SafeScalar.h" #include <Eigen/Core> using DenseStorageD3x3 = Eigen::DenseStorage<double, 9, 3, 3, 0>; -static_assert(std::is_trivially_move_constructible<DenseStorageD3x3>::value, - "DenseStorage not trivially_move_constructible"); -static_assert(std::is_trivially_move_assignable<DenseStorageD3x3>::value, "DenseStorage not trivially_move_assignable"); #if !defined(EIGEN_DENSE_STORAGE_CTOR_PLUGIN) static_assert(std::is_trivially_copy_constructible<DenseStorageD3x3>::value, "DenseStorage not trivially_copy_constructible"); +static_assert(std::is_trivially_move_constructible<DenseStorageD3x3>::value, + "DenseStorage not trivially_move_constructible"); static_assert(std::is_trivially_copy_assignable<DenseStorageD3x3>::value, "DenseStorage not trivially_copy_assignable"); -static_assert(std::is_trivially_copyable<DenseStorageD3x3>::value, "DenseStorage not trivially_copyable"); +static_assert(std::is_trivially_move_assignable<DenseStorageD3x3>::value, "DenseStorage not trivially_move_assignable"); #endif - +// all plain object types conform to standard layout +static_assert(std::is_standard_layout<Matrix4f>::value, "Matrix4f not standard_layout"); +static_assert(std::is_standard_layout<Array4f>::value, "Array4f not standard_layout"); +static_assert(std::is_standard_layout<VectorXf>::value, "VectorXf not standard_layout"); +static_assert(std::is_standard_layout<ArrayXf>::value, "ArrayXf not standard_layout"); +static_assert(std::is_standard_layout<MatrixXf>::value, "MatrixXf not standard_layout"); +static_assert(std::is_standard_layout<ArrayXXf>::value, "ArrayXXf not standard_layout"); +// all fixed-size, fixed-dimension plain object types are trivially default constructible +static_assert(std::is_trivially_default_constructible<Matrix4f>::value, "Matrix4f not trivially_default_constructible"); +static_assert(std::is_trivially_default_constructible<Array4f>::value, "Array4f not trivially_default_constructible"); +// all fixed-size, fixed-dimension plain object types are trivially move constructible static_assert(std::is_trivially_move_constructible<Matrix4f>::value, "Matrix4f not trivially_move_constructible"); static_assert(std::is_trivially_move_constructible<Array4f>::value, "Array4f not trivially_move_constructible"); #if !defined(EIGEN_DENSE_STORAGE_CTOR_PLUGIN) +// all fixed-size, fixed-dimension plain object types are trivially copy constructible static_assert(std::is_trivially_copy_constructible<Matrix4f>::value, "Matrix4f not trivially_copy_constructible"); static_assert(std::is_trivially_copy_constructible<Array4f>::value, "Array4f not trivially_copy_constructible"); #endif -static_assert(std::is_trivially_default_constructible<Matrix4f>::value, "Matrix4f not trivially_default_constructible"); -static_assert(std::is_trivially_default_constructible<Array4f>::value, "Array4f not trivially_default_constructible"); template <typename T, int Size, int Rows, int Cols> void dense_storage_copy(int rows, int cols) { @@ -42,7 +51,7 @@ const int size = rows * cols; DenseStorageType reference(size, rows, cols); T* raw_reference = reference.data(); - for (int i = 0; i < size; ++i) raw_reference[i] = static_cast<T>(i); + for (int i = 0; i < size; ++i) raw_reference[i] = internal::random<T>(); DenseStorageType copied_reference(reference); const T* raw_copied_reference = copied_reference.data(); @@ -56,7 +65,7 @@ const int size = rows * cols; DenseStorageType reference(size, rows, cols); T* raw_reference = reference.data(); - for (int i = 0; i < size; ++i) raw_reference[i] = static_cast<T>(i); + for (int i = 0; i < size; ++i) raw_reference[i] = internal::random<T>(); DenseStorageType copied_reference; copied_reference = reference; @@ -65,30 +74,25 @@ } template <typename T, int Size, int Rows, int Cols> -void dense_storage_swap(int rows0, int cols0, int rows1, int cols1) { +void dense_storage_swap(int rowsa, int colsa, int rowsb, int colsb) { typedef DenseStorage<T, Size, Rows, Cols, 0> DenseStorageType; - const int size0 = rows0 * cols0; - DenseStorageType a(size0, rows0, cols0); - for (int i = 0; i < size0; ++i) { - a.data()[i] = static_cast<T>(i); - } + const int sizea = rowsa * colsa; + ArrayX<T> referencea(sizea); + referencea.setRandom(); + DenseStorageType a(sizea, rowsa, colsa); + for (int i = 0; i < sizea; ++i) a.data()[i] = referencea(i); - const int size1 = rows1 * cols1; - DenseStorageType b(size1, rows1, cols1); - for (int i = 0; i < size1; ++i) { - b.data()[i] = static_cast<T>(-i); - } + const int sizeb = rowsb * colsb; + ArrayX<T> referenceb(sizeb); + referenceb.setRandom(); + DenseStorageType b(sizeb, rowsb, colsb); + for (int i = 0; i < sizeb; ++i) b.data()[i] = referenceb(i); a.swap(b); - for (int i = 0; i < size0; ++i) { - VERIFY_IS_EQUAL(b.data()[i], static_cast<T>(i)); - } - - for (int i = 0; i < size1; ++i) { - VERIFY_IS_EQUAL(a.data()[i], static_cast<T>(-i)); - } + for (int i = 0; i < sizea; i++) VERIFY_IS_EQUAL(b.data()[i], referencea(i)); + for (int i = 0; i < sizeb; i++) VERIFY_IS_EQUAL(a.data()[i], referenceb(i)); } template <typename T, int Size, std::size_t Alignment> @@ -104,12 +108,12 @@ }; VERIFY_IS_EQUAL(std::alignment_of<Nested1>::value, Alignment); - VERIFY_IS_EQUAL((std::alignment_of<internal::plain_array<T, Size, AutoAlign, Alignment> >::value), Alignment); + VERIFY_IS_EQUAL((std::alignment_of<internal::plain_array<T, Size, AutoAlign, Alignment>>::value), Alignment); const std::size_t default_alignment = internal::compute_default_alignment<T, Size>::value; if (default_alignment > 0) { - VERIFY_IS_EQUAL((std::alignment_of<DenseStorage<T, Size, 1, 1, AutoAlign> >::value), default_alignment); - VERIFY_IS_EQUAL((std::alignment_of<Matrix<T, Size, 1, AutoAlign> >::value), default_alignment); + VERIFY_IS_EQUAL((std::alignment_of<DenseStorage<T, Size, 1, 1, AutoAlign>>::value), default_alignment); + VERIFY_IS_EQUAL((std::alignment_of<Matrix<T, Size, 1, AutoAlign>>::value), default_alignment); struct Nested2 { Matrix<T, Size, 1, AutoAlign> mat; }; @@ -185,11 +189,90 @@ dense_storage_alignment<T, 16, 64>(); } +template <typename PlainType> +void plaintype_tests() { + constexpr int RowsAtCompileTime = PlainType::RowsAtCompileTime; + constexpr int ColsAtCompileTime = PlainType::ColsAtCompileTime; + constexpr int MaxRowsAtCompileTime = PlainType::MaxRowsAtCompileTime; + constexpr int MaxColsAtCompileTime = PlainType::MaxColsAtCompileTime; + const Index expectedDefaultRows = RowsAtCompileTime == Dynamic ? 0 : RowsAtCompileTime; + const Index expectedDefaultCols = ColsAtCompileTime == Dynamic ? 0 : ColsAtCompileTime; + const Index minRows = RowsAtCompileTime == Dynamic ? 0 : RowsAtCompileTime; + const Index minCols = ColsAtCompileTime == Dynamic ? 0 : ColsAtCompileTime; + const Index maxRows = MaxRowsAtCompileTime == Dynamic ? 100 : MaxRowsAtCompileTime; + const Index maxCols = MaxColsAtCompileTime == Dynamic ? 100 : MaxColsAtCompileTime; + const Index rows = internal::random<Index>(minRows, maxRows); + const Index cols = internal::random<Index>(minCols, maxCols); + // default construction + PlainType m0; + VERIFY_IS_EQUAL(m0.rows(), expectedDefaultRows); + VERIFY_IS_EQUAL(m0.cols(), expectedDefaultCols); + m0.resize(rows, cols); + m0.setRandom(); + // copy construction + PlainType m1(m0); + VERIFY_IS_EQUAL(m1.rows(), m0.rows()); + VERIFY_IS_EQUAL(m1.cols(), m0.cols()); + VERIFY_IS_CWISE_EQUAL(m1, m0); + // move construction + PlainType m2(std::move(m1)); + VERIFY_IS_EQUAL(m2.rows(), m0.rows()); + VERIFY_IS_EQUAL(m2.cols(), m0.cols()); + VERIFY_IS_CWISE_EQUAL(m2, m0); + // check that object is usable after move construction + m1.resize(minRows, minCols); + m1.setRandom(); + // copy assignment + m1 = m0; + VERIFY_IS_EQUAL(m1.rows(), m0.rows()); + VERIFY_IS_EQUAL(m1.cols(), m0.cols()); + VERIFY_IS_CWISE_EQUAL(m1, m0); + // move assignment + m2.resize(minRows, minCols); + m2.setRandom(); + m2 = std::move(m1); + VERIFY_IS_EQUAL(m2.rows(), m0.rows()); + VERIFY_IS_EQUAL(m2.cols(), m0.cols()); + VERIFY_IS_CWISE_EQUAL(m2, m0); + // check that object is usable after move assignment + m1.resize(minRows, minCols); + m1.setRandom(); + m1 = m2; + VERIFY_IS_EQUAL(m1.rows(), m0.rows()); + VERIFY_IS_EQUAL(m1.cols(), m0.cols()); + VERIFY_IS_CWISE_EQUAL(m1, m0); +} + EIGEN_DECLARE_TEST(dense_storage) { dense_storage_tests<int>(); dense_storage_tests<float>(); - dense_storage_tests<SafeScalar<float> >(); + dense_storage_tests<SafeScalar<float>>(); + dense_storage_tests<MovableScalar<float>>(); dense_storage_tests<AnnoyingScalar>(); + for (int i = 0; i < g_repeat; i++) { + plaintype_tests<Matrix<float, 0, 0, ColMajor>>(); + plaintype_tests<Matrix<float, Dynamic, Dynamic, ColMajor, 0, 0>>(); + + plaintype_tests<Matrix<float, 16, 16, ColMajor>>(); + plaintype_tests<Matrix<float, 16, Dynamic, ColMajor>>(); + plaintype_tests<Matrix<float, Dynamic, Dynamic, ColMajor>>(); + plaintype_tests<Matrix<float, Dynamic, Dynamic, ColMajor, 16, 16>>(); + + plaintype_tests<Matrix<SafeScalar<float>, 16, 16, ColMajor>>(); + plaintype_tests<Matrix<SafeScalar<float>, 16, Dynamic, ColMajor>>(); + plaintype_tests<Matrix<SafeScalar<float>, Dynamic, Dynamic, ColMajor>>(); + plaintype_tests<Matrix<SafeScalar<float>, Dynamic, Dynamic, ColMajor, 16, 16>>(); + + plaintype_tests<Matrix<MovableScalar<float>, 16, 16, ColMajor>>(); + plaintype_tests<Matrix<MovableScalar<float>, 16, Dynamic, ColMajor>>(); + plaintype_tests<Matrix<MovableScalar<float>, Dynamic, Dynamic, ColMajor>>(); + plaintype_tests<Matrix<MovableScalar<float>, Dynamic, Dynamic, ColMajor, 16, 16>>(); + + plaintype_tests<Matrix<AnnoyingScalar, 16, 16, ColMajor>>(); + plaintype_tests<Matrix<AnnoyingScalar, 16, Dynamic, ColMajor>>(); + plaintype_tests<Matrix<AnnoyingScalar, Dynamic, Dynamic, ColMajor>>(); + plaintype_tests<Matrix<AnnoyingScalar, Dynamic, Dynamic, ColMajor, 16, 16>>(); + } } #undef EIGEN_TESTING_PLAINOBJECT_CTOR \ No newline at end of file