diff --git a/Eigen/src/SparseCore/SparseMatrix.h b/Eigen/src/SparseCore/SparseMatrix.h index 8d57cbcf1..b7f437ede 100644 --- a/Eigen/src/SparseCore/SparseMatrix.h +++ b/Eigen/src/SparseCore/SparseMatrix.h @@ -694,6 +694,11 @@ class SparseMatrix Base::operator=(other); } + inline SparseMatrix(SparseMatrix&& other) : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) + { + *this = other.derived().markAsRValue(); + } + /** Copy constructor (it performs a deep copy) */ inline SparseMatrix(const SparseMatrix& other) : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) @@ -742,6 +747,7 @@ class SparseMatrix internal::conditional_aligned_delete_auto(m_innerNonZeros, m_outerSize); m_innerNonZeros = 0; } + inline SparseMatrix& operator=(const SparseMatrix& other) { if (other.isRValue()) @@ -767,6 +773,10 @@ class SparseMatrix return *this; } + inline SparseMatrix& operator=(SparseMatrix&& other) { + return *this = other.derived().markAsRValue(); + } + #ifndef EIGEN_PARSED_BY_DOXYGEN template inline SparseMatrix& operator=(const EigenBase& other) @@ -1497,8 +1507,8 @@ struct evaluator > } // Specialization for SparseMatrix. -// Serializes [rows, cols, isCompressed, outerSize, numNonZeros, innerNonZeros, -// outerIndices, innerIndices, values]. +// Serializes [rows, cols, isCompressed, outerSize, innerBufferSize, +// innerNonZeros, outerIndices, innerIndices, values]. template class Serializer, void> { public: @@ -1509,19 +1519,19 @@ class Serializer, void> { typename SparseMat::Index cols; bool compressed; Index outer_size; - Index num_non_zeros; + Index inner_buffer_size; }; EIGEN_DEVICE_FUNC size_t size(const SparseMat& value) const { // innerNonZeros. - std::size_t num_storage_indices = - value.isCompressed() ? 0 : value.outerSize(); + std::size_t num_storage_indices = value.isCompressed() ? 0 : value.outerSize(); // Outer indices. num_storage_indices += value.outerSize() + 1; // Inner indices. - num_storage_indices += value.nonZeros(); + const StorageIndex inner_buffer_size = value.outerIndexPtr()[value.outerSize()]; + num_storage_indices += inner_buffer_size; // Values. - std::size_t num_values = value.nonZeros(); + std::size_t num_values = inner_buffer_size; return sizeof(Header) + sizeof(Scalar) * num_values + sizeof(StorageIndex) * num_storage_indices; } @@ -1533,30 +1543,30 @@ class Serializer, void> { const size_t header_bytes = sizeof(Header); Header header = {value.rows(), value.cols(), value.isCompressed(), - value.outerSize(), value.nonZeros()}; + value.outerSize(), value.outerIndexPtr()[value.outerSize()]}; EIGEN_USING_STD(memcpy) memcpy(dest, &header, header_bytes); dest += header_bytes; // innerNonZeros. - size_t data_bytes = sizeof(StorageIndex) * header.outer_size; if (!header.compressed) { + std:size_t data_bytes = sizeof(StorageIndex) * header.outer_size; memcpy(dest, value.innerNonZeroPtr(), data_bytes); dest += data_bytes; } // Outer indices. - data_bytes = sizeof(StorageIndex) * (header.outer_size + 1); + std::size_t data_bytes = sizeof(StorageIndex) * (header.outer_size + 1); memcpy(dest, value.outerIndexPtr(), data_bytes); dest += data_bytes; // Inner indices. - data_bytes = sizeof(StorageIndex) * header.num_non_zeros; + data_bytes = sizeof(StorageIndex) * header.inner_buffer_size; memcpy(dest, value.innerIndexPtr(), data_bytes); dest += data_bytes; // Values. - data_bytes = sizeof(Scalar) * header.num_non_zeros; + data_bytes = sizeof(Scalar) * header.inner_buffer_size; memcpy(dest, value.valuePtr(), data_bytes); dest += data_bytes; @@ -1577,37 +1587,38 @@ class Serializer, void> { value.setZero(); value.resize(header.rows, header.cols); - - // Initialize compressed state and inner non-zeros. - size_t data_bytes = sizeof(StorageIndex) * header.outer_size; - if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr; if (header.compressed) { value.makeCompressed(); - value.resizeNonZeros(header.num_non_zeros); } else { - // Temporarily load inner sizes, then reserve. - std::vector inner_sizes(header.outer_size); - memcpy(inner_sizes.data(), src, data_bytes); - src += data_bytes; - value.uncompress(); - value.reserve(inner_sizes); - memcpy(value.innerNonZeroPtr(), inner_sizes.data(), data_bytes); + } + + // Adjust value ptr size. + value.data().resize(header.inner_buffer_size); + + // Initialize compressed state and inner non-zeros. + if (!header.compressed) { + // Inner non-zero counts. + std::size_t data_bytes = sizeof(StorageIndex) * header.outer_size; + if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr; + memcpy(value.innerNonZeroPtr(), src, data_bytes); + src += data_bytes; } // Outer indices. - data_bytes = sizeof(StorageIndex) * (header.outer_size + 1); + std::size_t data_bytes = sizeof(StorageIndex) * (header.outer_size + 1); + if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr; memcpy(value.outerIndexPtr(), src, data_bytes); src += data_bytes; // Inner indices. - data_bytes = sizeof(StorageIndex) * header.num_non_zeros; + data_bytes = sizeof(StorageIndex) * header.inner_buffer_size; if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr; memcpy(value.innerIndexPtr(), src, data_bytes); src += data_bytes; // Values. - data_bytes = sizeof(Scalar) * header.num_non_zeros; + data_bytes = sizeof(Scalar) * header.inner_buffer_size; if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr; memcpy(value.valuePtr(), src, data_bytes); src += data_bytes; diff --git a/test/serializer.cpp b/test/serializer.cpp index b48301310..d3e7ba5b2 100644 --- a/test/serializer.cpp +++ b/test/serializer.cpp @@ -30,7 +30,7 @@ struct RandomImpl> { double density = 0.1; // Reserve some space along each inner dim. - int nnz = static_cast(density * 1.5 * M.innerSize()); + int nnz = static_cast(std::ceil(density * 1.5 * M.innerSize())); M.reserve(Eigen::VectorXi::Constant(M.outerSize(), nnz)); for (int j = 0; j < M.outerSize(); j++) {