From 0742c81d9399771e0c342e2162ae731e56c05893 Mon Sep 17 00:00:00 2001 From: Erica Mitchell Date: Mon, 2 Feb 2026 16:16:25 -0500 Subject: [PATCH 01/10] Eigen version moved in 5.x.x, find version for both 3.x.x and 5.x.x --- cmake/modules/FindEigen3.cmake | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/cmake/modules/FindEigen3.cmake b/cmake/modules/FindEigen3.cmake index e143d5dc09..6944873f6f 100644 --- a/cmake/modules/FindEigen3.cmake +++ b/cmake/modules/FindEigen3.cmake @@ -31,7 +31,18 @@ if(NOT Eigen3_FIND_VERSION) endif(NOT Eigen3_FIND_VERSION) macro(_eigen3_check_version) - file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header) + # Try the Eigen 5.x location first + if(EXISTS "${EIGEN3_INCLUDE_DIR}/Eigen/Version") + file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/Version" _eigen3_version_header) + # Fall back to Eigen 3.x location + elseif(EXISTS "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h") + file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header) + else() + # Could not locate any known Eigen version header; mark version as not OK and return. + set(EIGEN3_VERSION_OK FALSE) + message(STATUS "Could not find Eigen version header under ${EIGEN3_INCLUDE_DIR}") + return() + endif() string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}") set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}") From db1319605716975b2d4449193c6d8ee0d684417d Mon Sep 17 00:00:00 2001 From: Erica Mitchell Date: Tue, 3 Feb 2026 13:02:41 -0500 Subject: [PATCH 02/10] Do assertions before constructing --- tests/sparse_tile.h | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/tests/sparse_tile.h b/tests/sparse_tile.h index ef5bd13dff..8465311e85 100644 --- a/tests/sparse_tile.h +++ b/tests/sparse_tile.h @@ -66,28 +66,31 @@ class EigenSparseTile { /// makes an uninitialized matrix explicit EigenSparseTile(const range_type& r) - : impl_(std::make_shared( - std::make_tuple(matrix_type(r.extent()[0], r.extent()[1]), r))) { - TA_ASSERT(r.extent()[0] > 0); - TA_ASSERT(r.extent()[1] > 0); - } + : impl_([&]() { + TA_ASSERT(r.extent()[0] > 0); + TA_ASSERT(r.extent()[1] > 0); + return std::make_shared( + std::make_tuple(matrix_type(r.extent()[0], r.extent()[1]), r)); + }()) {} /// ctor using sparse matrix EigenSparseTile(matrix_type&& mat, const range_type& range) - : impl_(std::make_shared( - std::make_tuple(std::move(mat), range))) { - using extent_type = typename range_type::extent_type::value_type; - TA_ASSERT(static_cast(mat.rows()) == range.extent()[0]); - TA_ASSERT(static_cast(mat.cols()) == range.extent()[1]); - } + : impl_([&]() { + using extent_type = typename range_type::extent_type::value_type; + TA_ASSERT(static_cast(mat.rows()) == range.extent()[0]); + TA_ASSERT(static_cast(mat.cols()) == range.extent()[1]); + return std::make_shared( + std::make_tuple(std::move(mat), range)); + }()) {} /// ctor using sparse matrix EigenSparseTile(const matrix_type& mat, const range_type& range) - : impl_(std::make_shared(std::make_tuple(mat, range))) { - using extent_type = typename range_type::extent_type::value_type; - TA_ASSERT(static_cast(mat.rows()) == range.extent()[0]); - TA_ASSERT(static_cast(mat.cols()) == range.extent()[1]); - } + : impl_([&]() { + using extent_type = typename range_type::extent_type::value_type; + TA_ASSERT(static_cast(mat.rows()) == range.extent()[0]); + TA_ASSERT(static_cast(mat.cols()) == range.extent()[1]); + return std::make_shared(std::make_tuple(mat, range)); + }()) {} // Deep copy EigenSparseTile clone() const { @@ -683,7 +686,7 @@ struct ArchiveLoadImpl> { static inline void load(const Archive& ar, Eigen::Triplet& obj) { int row, col; T value; - ar & row & col & value; + ar& row& col& value; obj = Eigen::Triplet(row, col, value); } }; @@ -691,7 +694,7 @@ struct ArchiveLoadImpl> { template struct ArchiveStoreImpl> { static inline void store(const Archive& ar, const Eigen::Triplet& obj) { - ar & obj.row() & obj.col() & obj.value(); + ar& obj.row() & obj.col() & obj.value(); } }; } // namespace archive From bb429dda1aa2dcabd214813e53e748b5ac336e5d Mon Sep 17 00:00:00 2001 From: Erica Mitchell Date: Tue, 3 Feb 2026 17:07:07 -0500 Subject: [PATCH 03/10] check if data_ is empty, NOT data --- src/TiledArray/tensor/tensor_interface.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TiledArray/tensor/tensor_interface.h b/src/TiledArray/tensor/tensor_interface.h index b09dc11665..787ebb0b28 100644 --- a/src/TiledArray/tensor/tensor_interface.h +++ b/src/TiledArray/tensor/tensor_interface.h @@ -179,7 +179,7 @@ class TensorInterface { /// \param data The data pointer for this tensor TensorInterface(const range_type& range, pointer data) : range_(range), data_(data) { - TA_ASSERT(data); + TA_ASSERT(data_); } /// Construct a new view of \c tensor @@ -188,7 +188,7 @@ class TensorInterface { /// \param data The data pointer for this tensor TensorInterface(range_type&& range, pointer data) : range_(std::move(range)), data_(data) { - TA_ASSERT(data); + TA_ASSERT(data_); } template Date: Tue, 3 Feb 2026 18:07:04 -0500 Subject: [PATCH 04/10] [copilot] fix spacing from VSCode auto-format --- tests/sparse_tile.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/sparse_tile.h b/tests/sparse_tile.h index 8465311e85..d9868e1519 100644 --- a/tests/sparse_tile.h +++ b/tests/sparse_tile.h @@ -686,7 +686,7 @@ struct ArchiveLoadImpl> { static inline void load(const Archive& ar, Eigen::Triplet& obj) { int row, col; T value; - ar& row& col& value; + ar & row & col & value; obj = Eigen::Triplet(row, col, value); } }; @@ -694,7 +694,7 @@ struct ArchiveLoadImpl> { template struct ArchiveStoreImpl> { static inline void store(const Archive& ar, const Eigen::Triplet& obj) { - ar& obj.row() & obj.col() & obj.value(); + ar & obj.row() & obj.col() & obj.value(); } }; } // namespace archive From 0e8f5f237bf7b0224759efaa00b47c9caa5d265e Mon Sep 17 00:00:00 2001 From: Erica Mitchell Date: Wed, 4 Feb 2026 00:10:48 -0500 Subject: [PATCH 05/10] Intro macro EIGEN_HAS_MAJOR_VERSION_5 --- src/TiledArray/external/eigen.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/TiledArray/external/eigen.h b/src/TiledArray/external/eigen.h index cd2c50b522..6d173d9f6d 100644 --- a/src/TiledArray/external/eigen.h +++ b/src/TiledArray/external/eigen.h @@ -63,6 +63,10 @@ TILEDARRAY_PRAGMA_GCC(diagnostic pop) #endif #endif // EIGEN_USE_LAPACKE || EIGEN_USE_LAPACKE_STRICT +#if EIGEN_VERSION_AT_LEAST(3, 5, 0) +#define EIGEN_HAS_MAJOR_VERSION_5 1 +#endif + TILEDARRAY_PRAGMA_GCC(diagnostic pop) namespace madness { From bb5e2f14f659e1809930b1e1d723e16046bcc93e Mon Sep 17 00:00:00 2001 From: Erica Mitchell Date: Wed, 4 Feb 2026 00:13:36 -0500 Subject: [PATCH 06/10] if empty trange1, ptr is nullptr using Eigen3.5.x but 0 using Eigen3.4.x --- src/TiledArray/tensor/tensor.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/TiledArray/tensor/tensor.h b/src/TiledArray/tensor/tensor.h index ba684cc768..d632439cc8 100644 --- a/src/TiledArray/tensor/tensor.h +++ b/src/TiledArray/tensor/tensor.h @@ -185,7 +185,14 @@ class Tensor { : range_(range), nbatch_(nbatch) { size_t size = range_.volume() * nbatch; allocator_type allocator; +#if EIGEN_HAS_MAJOR_VERSION_5 + // Eigen 3.5.x returns nullptr if size=0 + auto* ptr = (!size && range_.rank()) + ? static_cast(std::malloc(size)) + : allocator.allocate(size); +#else auto* ptr = allocator.allocate(size); +#endif // default construct elements of data only if can have any effect ... if constexpr (!std::is_trivially_default_constructible_v) { // .. and requested @@ -1186,10 +1193,10 @@ class Tensor { bool empty = this->empty(); auto range = this->range_; auto nbatch = this->nbatch_; - ar & empty; + ar& empty; if (!empty) { - ar & range; - ar & nbatch; + ar& range; + ar& nbatch; if constexpr (madness::is_input_archive_v) { *this = Tensor(std::move(range), nbatch, default_construct{true}); } From d03ec02124286e63ad466849b2bdcb424e10a516 Mon Sep 17 00:00:00 2001 From: Erica Mitchell Date: Wed, 4 Feb 2026 00:33:41 -0500 Subject: [PATCH 07/10] Use typedef pointer for static_cast --- src/TiledArray/tensor/tensor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TiledArray/tensor/tensor.h b/src/TiledArray/tensor/tensor.h index d632439cc8..3b74756635 100644 --- a/src/TiledArray/tensor/tensor.h +++ b/src/TiledArray/tensor/tensor.h @@ -188,7 +188,7 @@ class Tensor { #if EIGEN_HAS_MAJOR_VERSION_5 // Eigen 3.5.x returns nullptr if size=0 auto* ptr = (!size && range_.rank()) - ? static_cast(std::malloc(size)) + ? static_cast(std::malloc(size)) : allocator.allocate(size); #else auto* ptr = allocator.allocate(size); From 4232c6eb6b93f67f64db52c7d2ba8e3ab5b26d40 Mon Sep 17 00:00:00 2001 From: Erica Mitchell Date: Wed, 4 Feb 2026 00:44:32 -0500 Subject: [PATCH 08/10] [ci skip] [copilot] fix comment, Eigen >=3.5.0 --- src/TiledArray/tensor/tensor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TiledArray/tensor/tensor.h b/src/TiledArray/tensor/tensor.h index 3b74756635..f07f5bd2fe 100644 --- a/src/TiledArray/tensor/tensor.h +++ b/src/TiledArray/tensor/tensor.h @@ -186,7 +186,7 @@ class Tensor { size_t size = range_.volume() * nbatch; allocator_type allocator; #if EIGEN_HAS_MAJOR_VERSION_5 - // Eigen 3.5.x returns nullptr if size=0 + // Eigen >=3.5.0 returns nullptr if size=0 auto* ptr = (!size && range_.rank()) ? static_cast(std::malloc(size)) : allocator.allocate(size); From 06025744242de07cb3b07825a39b4d53f985d832 Mon Sep 17 00:00:00 2001 From: Erica Mitchell Date: Wed, 4 Feb 2026 01:00:09 -0500 Subject: [PATCH 09/10] Missed change for ptr in move constructor --- src/TiledArray/tensor/tensor.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/TiledArray/tensor/tensor.h b/src/TiledArray/tensor/tensor.h index f07f5bd2fe..1828296eb6 100644 --- a/src/TiledArray/tensor/tensor.h +++ b/src/TiledArray/tensor/tensor.h @@ -233,7 +233,14 @@ class Tensor { : range_(std::move(range)), nbatch_(nbatch) { size_t size = range_.volume() * nbatch; allocator_type allocator; +#if EIGEN_HAS_MAJOR_VERSION_5 + // Eigen >=3.5.0 returns nullptr if size=0 + auto* ptr = (!size && range_.rank()) + ? static_cast(std::malloc(size)) + : allocator.allocate(size); +#else auto* ptr = allocator.allocate(size); +#endif // default construct elements of data only if can have any effect ... if constexpr (!std::is_trivially_default_constructible_v) { // .. and requested From f2695c6eb498dde45fc6e27cf862de97d2b6bb7c Mon Sep 17 00:00:00 2001 From: Erica Mitchell Date: Wed, 4 Feb 2026 10:06:22 -0500 Subject: [PATCH 10/10] EIGEN_HAS_MAJOR_VERSION_5 -> EIGEN_HAS_CXX17, more dox --- src/TiledArray/external/eigen.h | 6 ++++-- src/TiledArray/fwd.h | 2 ++ src/TiledArray/tensor/tensor.h | 8 ++++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/TiledArray/external/eigen.h b/src/TiledArray/external/eigen.h index 6d173d9f6d..3df2fd5197 100644 --- a/src/TiledArray/external/eigen.h +++ b/src/TiledArray/external/eigen.h @@ -63,8 +63,10 @@ TILEDARRAY_PRAGMA_GCC(diagnostic pop) #endif #endif // EIGEN_USE_LAPACKE || EIGEN_USE_LAPACKE_STRICT -#if EIGEN_VERSION_AT_LEAST(3, 5, 0) -#define EIGEN_HAS_MAJOR_VERSION_5 1 +// Eigen >= 5.x is last to support C++14, future releases require C++17 +// https://gitlab.com/libeigen/eigen/-/releases/5.0.0 +#if EIGEN_MAJOR_VERSION > 4 +#define EIGEN_HAS_CXX17 1 #endif TILEDARRAY_PRAGMA_GCC(diagnostic pop) diff --git a/src/TiledArray/fwd.h b/src/TiledArray/fwd.h index 00c36a5092..dc26ce54de 100644 --- a/src/TiledArray/fwd.h +++ b/src/TiledArray/fwd.h @@ -29,6 +29,8 @@ // #include // fwddecl Eigen::aligned_allocator +// N.B. with Eigen >= 5.x, aligned_allocator no longer inherits from +// std::allocator https://gitlab.com/libeigen/eigen/-/merge_requests/1795 namespace Eigen { template class aligned_allocator; diff --git a/src/TiledArray/tensor/tensor.h b/src/TiledArray/tensor/tensor.h index 1828296eb6..e2407a2d23 100644 --- a/src/TiledArray/tensor/tensor.h +++ b/src/TiledArray/tensor/tensor.h @@ -185,8 +185,8 @@ class Tensor { : range_(range), nbatch_(nbatch) { size_t size = range_.volume() * nbatch; allocator_type allocator; -#if EIGEN_HAS_MAJOR_VERSION_5 - // Eigen >=3.5.0 returns nullptr if size=0 +#if EIGEN_HAS_CXX17 + // Eigen (>= 5.x) allocate returns nullptr if size=0 auto* ptr = (!size && range_.rank()) ? static_cast(std::malloc(size)) : allocator.allocate(size); @@ -233,8 +233,8 @@ class Tensor { : range_(std::move(range)), nbatch_(nbatch) { size_t size = range_.volume() * nbatch; allocator_type allocator; -#if EIGEN_HAS_MAJOR_VERSION_5 - // Eigen >=3.5.0 returns nullptr if size=0 +#if EIGEN_HAS_CXX17 + // Eigen (>= 5.x) allocate returns nullptr if size=0 auto* ptr = (!size && range_.rank()) ? static_cast(std::malloc(size)) : allocator.allocate(size);