From 489dbbc6516f6729fa8e5c8bddc9ea446d5ef032 Mon Sep 17 00:00:00 2001 From: Charles Schlosser Date: Tue, 12 Nov 2024 23:34:26 +0000 Subject: [PATCH] make fixed_size matrices conform to std::is_standard_layout --- Eigen/src/Core/DenseStorage.h | 704 ++++++++++++++++++++++------------ Eigen/src/Core/util/Memory.h | 7 +- test/MovableScalar.h | 44 ++- test/dense_storage.cpp | 145 +++++-- 4 files changed, 603 insertions(+), 297 deletions(-) diff --git a/Eigen/src/Core/DenseStorage.h b/Eigen/src/Core/DenseStorage.h index 90bc94ef2..d62586c99 100644 --- a/Eigen/src/Core/DenseStorage.h +++ b/Eigen/src/Core/DenseStorage.h @@ -30,10 +30,10 @@ namespace internal { #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 @@ namespace internal { * 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 ::value> struct plain_array { @@ -78,92 +79,454 @@ struct plain_array { 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 -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 +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap_plain_array(plain_array& a, + plain_array& 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 +class DenseStorage_impl { + plain_array 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 -struct DenseStorageIndices { - Index m_cols; +template +class DenseStorage_impl { + plain_array 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); + } + 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; } -}; -template -struct DenseStorageIndices { - 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 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 { - Index m_rows; - Index m_cols; +template +class DenseStorage_impl { + plain_array 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 +class DenseStorage_impl { + plain_array 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 -struct use_trivial_ctors { - static constexpr bool value = (Size >= 0) && (Rows >= 0) && (Cols >= 0) && (Size == Rows * Cols); +// null matrix variants +template +class DenseStorage_impl { + 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 +class DenseStorage_impl { + 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 +class DenseStorage_impl { + 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 +class DenseStorage_impl { + 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 +class DenseStorage_impl {}; +// dynamic-sized variants +template +class DenseStorage_impl { + 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(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(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(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(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(m_data, oldSize); + m_data = conditional_aligned_new_auto(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 +class DenseStorage_impl { + 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(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(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(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(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(m_data, oldSize); + m_data = conditional_aligned_new_auto(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 +class DenseStorage_impl { + 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(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(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(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(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(m_data, oldSize); + m_data = conditional_aligned_new_auto(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 +struct use_default_move { + static constexpr bool DynamicObject = Size == Dynamic; + static constexpr bool TrivialObject = + (!NumTraits::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 @@ struct use_trivial_ctors { * \sa Matrix */ template ::value> -class DenseStorage; - -// fixed-size storage with fixed dimensions -template -class DenseStorage : internal::DenseStorageIndices { - using Base = internal::DenseStorageIndices; - - internal::plain_array m_data; + bool Trivial = internal::use_default_move::value> +class DenseStorage : public internal::DenseStorage_impl { + using Base = internal::DenseStorage_impl; 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 -class DenseStorage : internal::DenseStorageIndices { - using Base = internal::DenseStorageIndices; - - internal::plain_array 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 -class DenseStorage : internal::DenseStorageIndices { - using Base = internal::DenseStorageIndices; - - 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 -class DenseStorage : internal::DenseStorageIndices { - using Base = internal::DenseStorageIndices; - static constexpr int Size = Dynamic; - static constexpr bool Align = (Options & DontAlign) == 0; - - T* m_data; +template +class DenseStorage + : public internal::DenseStorage_impl { + using Base = internal::DenseStorage_impl; 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(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(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(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(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(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(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(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(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 d59071f06..2acdd9df5 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -147,7 +147,7 @@ EIGEN_DEVICE_FUNC inline void* handmade_aligned_malloc(std::size_t size, 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(alignment - (reinterpret_cast(original) & (alignment - 1))); void* aligned = static_cast(static_cast(original) + offset); *(static_cast(aligned) - 1) = offset; @@ -391,7 +391,8 @@ EIGEN_DEVICE_FUNC inline T* move_construct_elements_of_array(T* ptr, T* src, std template 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 @@ EIGEN_DEVICE_FUNC inline T* conditional_aligned_realloc_new(T* pts, std::size_t template 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(size); T* result = static_cast(conditional_aligned_malloc(sizeof(T) * size)); if (NumTraits::RequireInitialization) { diff --git a/test/MovableScalar.h b/test/MovableScalar.h index c8bf546df..6a046dea6 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 - namespace Eigen { -template > -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 +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 -struct NumTraits> : GenericNumTraits { +struct NumTraits> : NumTraits { enum { RequireInitialization = 1 }; }; diff --git a/test/dense_storage.cpp b/test/dense_storage.cpp index 5d0083fa7..0f6ab64a1 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 using DenseStorageD3x3 = Eigen::DenseStorage; -static_assert(std::is_trivially_move_constructible::value, - "DenseStorage not trivially_move_constructible"); -static_assert(std::is_trivially_move_assignable::value, "DenseStorage not trivially_move_assignable"); #if !defined(EIGEN_DENSE_STORAGE_CTOR_PLUGIN) static_assert(std::is_trivially_copy_constructible::value, "DenseStorage not trivially_copy_constructible"); +static_assert(std::is_trivially_move_constructible::value, + "DenseStorage not trivially_move_constructible"); static_assert(std::is_trivially_copy_assignable::value, "DenseStorage not trivially_copy_assignable"); -static_assert(std::is_trivially_copyable::value, "DenseStorage not trivially_copyable"); +static_assert(std::is_trivially_move_assignable::value, "DenseStorage not trivially_move_assignable"); #endif - +// all plain object types conform to standard layout +static_assert(std::is_standard_layout::value, "Matrix4f not standard_layout"); +static_assert(std::is_standard_layout::value, "Array4f not standard_layout"); +static_assert(std::is_standard_layout::value, "VectorXf not standard_layout"); +static_assert(std::is_standard_layout::value, "ArrayXf not standard_layout"); +static_assert(std::is_standard_layout::value, "MatrixXf not standard_layout"); +static_assert(std::is_standard_layout::value, "ArrayXXf not standard_layout"); +// all fixed-size, fixed-dimension plain object types are trivially default constructible +static_assert(std::is_trivially_default_constructible::value, "Matrix4f not trivially_default_constructible"); +static_assert(std::is_trivially_default_constructible::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::value, "Matrix4f not trivially_move_constructible"); static_assert(std::is_trivially_move_constructible::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::value, "Matrix4f not trivially_copy_constructible"); static_assert(std::is_trivially_copy_constructible::value, "Array4f not trivially_copy_constructible"); #endif -static_assert(std::is_trivially_default_constructible::value, "Matrix4f not trivially_default_constructible"); -static_assert(std::is_trivially_default_constructible::value, "Array4f not trivially_default_constructible"); template void dense_storage_copy(int rows, int cols) { @@ -42,7 +51,7 @@ void dense_storage_copy(int rows, int cols) { 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(i); + for (int i = 0; i < size; ++i) raw_reference[i] = internal::random(); DenseStorageType copied_reference(reference); const T* raw_copied_reference = copied_reference.data(); @@ -56,7 +65,7 @@ void dense_storage_assignment(int rows, int cols) { 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(i); + for (int i = 0; i < size; ++i) raw_reference[i] = internal::random(); DenseStorageType copied_reference; copied_reference = reference; @@ -65,30 +74,25 @@ void dense_storage_assignment(int rows, int cols) { } template -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 DenseStorageType; - const int size0 = rows0 * cols0; - DenseStorageType a(size0, rows0, cols0); - for (int i = 0; i < size0; ++i) { - a.data()[i] = static_cast(i); - } + const int sizea = rowsa * colsa; + ArrayX 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(-i); - } + const int sizeb = rowsb * colsb; + ArrayX 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(i)); - } - - for (int i = 0; i < size1; ++i) { - VERIFY_IS_EQUAL(a.data()[i], static_cast(-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 @@ -104,12 +108,12 @@ void dense_storage_alignment() { }; VERIFY_IS_EQUAL(std::alignment_of::value, Alignment); - VERIFY_IS_EQUAL((std::alignment_of >::value), Alignment); + VERIFY_IS_EQUAL((std::alignment_of>::value), Alignment); const std::size_t default_alignment = internal::compute_default_alignment::value; if (default_alignment > 0) { - VERIFY_IS_EQUAL((std::alignment_of >::value), default_alignment); - VERIFY_IS_EQUAL((std::alignment_of >::value), default_alignment); + VERIFY_IS_EQUAL((std::alignment_of>::value), default_alignment); + VERIFY_IS_EQUAL((std::alignment_of>::value), default_alignment); struct Nested2 { Matrix mat; }; @@ -185,11 +189,90 @@ void dense_storage_tests() { dense_storage_alignment(); } +template +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(minRows, maxRows); + const Index cols = internal::random(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(); dense_storage_tests(); - dense_storage_tests >(); + dense_storage_tests>(); + dense_storage_tests>(); dense_storage_tests(); + for (int i = 0; i < g_repeat; i++) { + plaintype_tests>(); + plaintype_tests>(); + + plaintype_tests>(); + plaintype_tests>(); + plaintype_tests>(); + plaintype_tests>(); + + plaintype_tests, 16, 16, ColMajor>>(); + plaintype_tests, 16, Dynamic, ColMajor>>(); + plaintype_tests, Dynamic, Dynamic, ColMajor>>(); + plaintype_tests, Dynamic, Dynamic, ColMajor, 16, 16>>(); + + plaintype_tests, 16, 16, ColMajor>>(); + plaintype_tests, 16, Dynamic, ColMajor>>(); + plaintype_tests, Dynamic, Dynamic, ColMajor>>(); + plaintype_tests, Dynamic, Dynamic, ColMajor, 16, 16>>(); + + plaintype_tests>(); + plaintype_tests>(); + plaintype_tests>(); + plaintype_tests>(); + } } #undef EIGEN_TESTING_PLAINOBJECT_CTOR \ No newline at end of file