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}") diff --git a/src/TiledArray/external/eigen.h b/src/TiledArray/external/eigen.h index cd2c50b522..3df2fd5197 100644 --- a/src/TiledArray/external/eigen.h +++ b/src/TiledArray/external/eigen.h @@ -63,6 +63,12 @@ TILEDARRAY_PRAGMA_GCC(diagnostic pop) #endif #endif // EIGEN_USE_LAPACKE || EIGEN_USE_LAPACKE_STRICT +// 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) namespace madness { 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 ba684cc768..e2407a2d23 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_CXX17 + // Eigen (>= 5.x) allocate 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 @@ -226,7 +233,14 @@ class Tensor { : range_(std::move(range)), nbatch_(nbatch) { size_t size = range_.volume() * nbatch; allocator_type allocator; +#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); +#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 +1200,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}); } 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 ( - 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 {