From 96742725e206bcc7f4f03272e988afe005131b71 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 13 Jan 2026 11:05:03 -0500 Subject: [PATCH 1/2] concept-check + cleanup Tensor::add* and tile_interface/add to support heterogeneous addition --- src/TiledArray/tensor/tensor.h | 87 ++++++++++++++++++----------- src/TiledArray/tile_interface/add.h | 30 +++------- src/TiledArray/type_traits.h | 18 ++++++ 3 files changed, 80 insertions(+), 55 deletions(-) diff --git a/src/TiledArray/tensor/tensor.h b/src/TiledArray/tensor/tensor.h index 019a4e05d1..ba684cc768 100644 --- a/src/TiledArray/tensor/tensor.h +++ b/src/TiledArray/tensor/tensor.h @@ -1745,9 +1745,11 @@ class Tensor { /// \param right The tensor that will be added to this tensor /// \return A new tensor where the elements are the sum of the elements of /// \c this and \c other - template ::value>::type* = nullptr> - Tensor add(const Right& right) const& { + template + requires(is_tensor::value && + detail::sum_convertible_to&>) + Tensor add(const Right& right) const { // early exit for empty right if (right.empty()) return this->clone(); @@ -1780,13 +1782,31 @@ class Tensor { /// \param right The tensor that will be added to this tensor /// \return A new tensor where the elements are the sum of the elements of /// \c this and \c other - template ::value>::type* = nullptr> + template + requires(is_tensor::value && + detail::addable_to&>) Tensor add(const Right& right) && { add_to(right); return std::move(*this); } + /// Add this and \c other to construct a new tensor of type that differs from + /// this + + /// \tparam Right The right-hand tensor type + /// \param right The tensor that will be added to this tensor + /// \return A new tensor where the elements are the sum of the elements of + /// \c this and \c other + template + requires(detail::is_tensor_v && + !detail::sum_convertible_to&>) + auto add(const Right& right) const { + return binary(right, [](const value_type& l, const value_t& r) { + return l + r; + }); + } + /// Add this and \c other to construct a new, permuted tensor /// \tparam Right The right-hand tensor type @@ -1795,13 +1815,13 @@ class Tensor { /// \param perm The permutation to be applied to this tensor /// \return A new tensor where the elements are the sum of the elements of /// \c this and \c other - template < - typename Right, typename Perm, - typename std::enable_if::value && - detail::is_permutation_v>::type* = nullptr> - Tensor add(const Right& right, const Perm& perm) const { + template + requires(is_tensor::value && detail::is_permutation_v && + detail::addable&>) + auto add(const Right& right, const Perm& perm) const { return binary( - right, [](const value_type& l, const value_type& r) { return l + r; }, + right, + [](const value_type& l, const value_t& r) { return l + r; }, perm); } @@ -1813,14 +1833,14 @@ class Tensor { /// \param factor The scaling factor /// \return A new tensor where the elements are the sum of the elements of /// \c this and \c other, scaled by \c factor - template < - typename Right, typename Scalar, - typename std::enable_if::value && - detail::is_numeric_v>::type* = nullptr> - Tensor add(const Right& right, const Scalar factor) const { - return binary(right, [factor](const value_type& l, const value_type& r) { - return (l + r) * factor; - }); + template + requires(is_tensor::value && detail::is_numeric_v && + detail::addable&>) + auto add(const Right& right, const Scalar factor) const { + return binary(right, + [factor](const value_type& l, const value_t& r) { + return (l + r) * factor; + }); } /// Scale and add this and \c other to construct a new, permuted tensor @@ -1833,14 +1853,14 @@ class Tensor { /// \param perm The permutation to be applied to this tensor /// \return A new tensor where the elements are the sum of the elements of /// \c this and \c other, scaled by \c factor - template ::value && detail::is_numeric_v && - detail::is_permutation_v>::type* = nullptr> - Tensor add(const Right& right, const Scalar factor, const Perm& perm) const { + template + requires(is_tensor::value && detail::is_numeric_v && + detail::is_permutation_v && + detail::addable&>) + auto add(const Right& right, const Scalar factor, const Perm& perm) const { return binary( right, - [factor](const value_type& l, const value_type& r) { + [factor](const value_type& l, const value_t& r) { return (l + r) * factor; }, perm); @@ -1879,8 +1899,9 @@ class Tensor { /// \tparam Right The right-hand tensor type /// \param right The tensor that will be added to this tensor /// \return A reference to this tensor - template ::value>::type* = nullptr> + template + requires(is_tensor::value && + detail::addable_to&>) Tensor& add_to(const Right& right) { // early exit for empty right if (right.empty()) return *this; @@ -1902,10 +1923,9 @@ class Tensor { /// \param right The tensor that will be added to this tensor /// \param factor The scaling factor /// \return A reference to this tensor - template < - typename Right, typename Scalar, - typename std::enable_if::value && - detail::is_numeric_v>::type* = nullptr> + template + requires(is_tensor::value && detail::is_numeric_v && + detail::addable_to&>) Tensor& add_to(const Right& right, const Scalar factor) { return inplace_binary( right, [factor](value_type& MADNESS_RESTRICT l, @@ -1916,8 +1936,9 @@ class Tensor { /// \param value The constant to be added /// \return A reference to this tensor - template >> + template + requires(detail::is_numeric_v && + detail::addable_to) Tensor& add_to(const Scalar value) { return inplace_unary( [value](value_type& MADNESS_RESTRICT res) { res += value; }); diff --git a/src/TiledArray/tile_interface/add.h b/src/TiledArray/tile_interface/add.h index d621e2731e..ced9987d45 100644 --- a/src/TiledArray/tile_interface/add.h +++ b/src/TiledArray/tile_interface/add.h @@ -46,10 +46,8 @@ template && - detail::has_member_function_add_anyreturn_v && - !std::is_reference_v && std::is_reference_v) || - (detail::has_member_function_add_anyreturn_v && - !detail::has_member_function_add_anyreturn_v); + !std::is_reference_v) || + (!detail::has_member_function_add_anyreturn_v); if constexpr (left_right) return std::forward(left).add(std::forward(right)); else @@ -76,12 +74,8 @@ inline decltype(auto) add(Left&& left, Right&& right, const Scalar factor) { constexpr auto left_right = (detail::has_member_function_add_anyreturn_v && - detail::has_member_function_add_anyreturn_v && - !std::is_reference_v && std::is_reference_v) || - (detail::has_member_function_add_anyreturn_v && - !detail::has_member_function_add_anyreturn_v) || + (!detail::has_member_function_add_anyreturn_v); if constexpr (left_right) return std::forward(left).add(std::forward(right), factor); @@ -108,12 +102,8 @@ inline decltype(auto) add(Left&& left, Right&& right, const Perm& perm) { constexpr auto left_right = (detail::has_member_function_add_anyreturn_v && - detail::has_member_function_add_anyreturn_v && - !std::is_reference_v && std::is_reference_v) || - (detail::has_member_function_add_anyreturn_v && - !detail::has_member_function_add_anyreturn_v) || + (!detail::has_member_function_add_anyreturn_v); if constexpr (left_right) return std::forward(left).add(std::forward(right), perm); @@ -143,12 +133,8 @@ inline decltype(auto) add(Left&& left, Right&& right, const Scalar factor, constexpr auto left_right = (detail::has_member_function_add_anyreturn_v && - detail::has_member_function_add_anyreturn_v && - !std::is_reference_v && std::is_reference_v) || - (detail::has_member_function_add_anyreturn_v && - !detail::has_member_function_add_anyreturn_v) || + (!detail::has_member_function_add_anyreturn_v); if constexpr (left_right) return std::forward(left).add(std::forward(right), factor, diff --git a/src/TiledArray/type_traits.h b/src/TiledArray/type_traits.h index f3842387c3..09d2824464 100644 --- a/src/TiledArray/type_traits.h +++ b/src/TiledArray/type_traits.h @@ -1585,6 +1585,24 @@ struct is_invocable_void : is_invocable_void_helper {}; template struct type_printer; + +// concepts + +template +concept addable = requires(Summand1 t, Summand2 u) { + { t + u }; +}; + +template +concept addable_to = requires(Sum t, Summand u) { + { t += u }; +}; + +template +concept sum_convertible_to = requires(Summand1 t, Summand2 u) { + { t + u } -> std::convertible_to; +}; + } // namespace detail } // namespace TiledArray From 156458e51e7065b0e1647f363c032fea44f568d7 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 13 Jan 2026 16:50:14 -0500 Subject: [PATCH 2/2] bump CUDA to c++20 --- external/cuda.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/cuda.cmake b/external/cuda.cmake index d174b67f7a..8f96d70b4a 100644 --- a/external/cuda.cmake +++ b/external/cuda.cmake @@ -1,7 +1,7 @@ # cmake 3.17 decouples C++ and CUDA standards, see https://gitlab.kitware.com/cmake/cmake/issues/19123 # cmake 3.18 knows that CUDA 11 provides cuda_std_17 cmake_minimum_required(VERSION 3.18.0) -set(CMAKE_CUDA_STANDARD 17) +set(CMAKE_CUDA_STANDARD 20) set(CMAKE_CUDA_EXTENSIONS OFF) set(CMAKE_CUDA_STANDARD_REQUIRED ON) set(CMAKE_CUDA_SEPARABLE_COMPILATION ON)