From 5ed7a4cbfd9103ad3255ed7d37f2c56f3d3bec51 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Fri, 29 Dec 2023 07:33:53 -0500 Subject: [PATCH 01/40] braket annotation generation revised --- SeQuant/core/eval_expr.cpp | 71 +++++++++++++++-------------------- SeQuant/core/eval_expr.hpp | 37 +++--------------- SeQuant/domain/eval/eval.cpp | 7 ++-- tests/unit/test_eval_expr.cpp | 37 ------------------ 4 files changed, 39 insertions(+), 113 deletions(-) diff --git a/SeQuant/core/eval_expr.cpp b/SeQuant/core/eval_expr.cpp index a3aa82d99..337f9baae 100644 --- a/SeQuant/core/eval_expr.cpp +++ b/SeQuant/core/eval_expr.cpp @@ -1,6 +1,8 @@ #include "eval_expr.hpp" #include +#include #include +#include #include #include @@ -23,29 +25,36 @@ std::wstring_view const var_label = L"Z"; } // namespace -template < - typename Iterable, - std::enable_if_t>, - bool> = true> -std::string indices_to_annot(Iterable const& indices) noexcept { - using ranges::views::intersperse; - using ranges::views::join; - using ranges::views::transform; +std::string EvalExpr::braket_annot() const noexcept { + if (!is_tensor()) return {}; + auto const& tnsr = as_tensor(); + + // select indices from @c tnsr's braket that satisfy @c pred + // and return their 'full_label's separated by commas + auto annot_group = [&tnsr](auto&& pred) -> std::string { + using namespace ranges::views; + auto full_labels = tnsr.const_braket() // + | filter(pred) // + | transform(&Index::full_label) // + | transform([](auto&& fl) { // + return sequant::to_string(fl); // + }); + return full_labels // + | intersperse(std::string{","}) // + | join // + | ranges::to; + }; - auto idx_label = [](Index const& idx) { return to_string(idx.label()); }; + auto outer_annot = annot_group( // + ranges::not_fn( // + &Index::has_proto_indices) // + ); - return indices | transform(idx_label) | intersperse(",") | join | - ranges::to; -} + auto inner_annot = annot_group(&Index::has_proto_indices); -std::string indices_to_annot(InnerOuterIndices const& inout) noexcept { - auto const& in = inout.inner; - auto const& out = inout.outer; - if (out.empty()) { - return indices_to_annot(in); - } else { - return indices_to_annot(in) + ";" + indices_to_annot(out); - } + return inner_annot.empty() // + ? outer_annot + : outer_annot + ";" + inner_annot; } size_t EvalExpr::global_id_{}; @@ -123,29 +132,9 @@ Variable const& EvalExpr::as_variable() const noexcept { return expr().as(); } -InnerOuterIndices EvalExpr::inner_outer_indices() const noexcept { - if (is_scalar()) return {}; - - assert(is_tensor()); - auto const& t = expr()->as(); - - container::svector inner; - container::svector outer; - for (auto const& idx : t.const_braket()) { - inner.emplace_back(idx); - for (auto const& pidx : idx.proto_indices()) outer.emplace_back(pidx); - } - ranges::stable_sort(outer, Index::LabelCompare{}); - ranges::actions::unique(outer); - ranges::actions::remove_if( - inner, [&outer](Index const& i) { return ranges::contains(outer, i); }); - return {std::move(inner), std::move(outer)}; -} - std::string EvalExpr::label() const noexcept { if (is_tensor()) - return to_string(as_tensor().label()) + "(" + - indices_to_annot(inner_outer_indices()) + ")"; + return to_string(as_tensor().label()) + "(" + braket_annot() + ")"; else if (is_constant()) { auto const& c = as_constant(); auto real = Constant{c.value().real()}.value(); diff --git a/SeQuant/core/eval_expr.hpp b/SeQuant/core/eval_expr.hpp index 22832baef..b7596e00a 100644 --- a/SeQuant/core/eval_expr.hpp +++ b/SeQuant/core/eval_expr.hpp @@ -40,21 +40,6 @@ enum class EvalOp { /// enum class ResultType { Tensor, Scalar }; -/// -/// @see EvalExpr::inner_outer_indices -/// -struct InnerOuterIndices { - container::svector const inner; - container::svector const outer; -}; - -/// -/// \param inout InnerOuterIndices object. -/// \return String of comma-separated labels of inner indices followed by the -/// labels of outer indices, separated by a semicolon. -/// -std::string indices_to_annot(InnerOuterIndices const& inout) noexcept; - /// /// \brief The EvalExpr class represents the object that go into the nodes of /// the binary tree that is used to evaluate the sequant expressions. @@ -167,7 +152,6 @@ class EvalExpr { /// [[nodiscard]] Constant const& as_constant() const noexcept; - /// /// \brief Calls to() on ExprPtr held by this object. /// @@ -176,26 +160,15 @@ class EvalExpr { [[nodiscard]] Variable const& as_variable() const noexcept; /// - /// \brief Separates indices of a tensor into inner and outer index groups. - /// - /// \details - If the expression this object holds is a Constant, then the - /// resulting inner and outer indices are empty. - /// - The outer indices are empty if neither of the indices in the - /// tensor's braket have at least one proto-index. - /// - The proto-indices are collected, sorted using - /// Index::LabelCompare, and de-duplicated to form the outer - /// indices. - /// - The non-proto indices make up the inner indices if they are not - /// already in the outer indices. - /// - /// \return InnerOuterIndices object. + /// \brief Get the label for this object useful for logging. /// - [[nodiscard]] InnerOuterIndices inner_outer_indices() const noexcept; + [[nodiscard]] std::string label() const noexcept; /// - /// \brief Get the label for this object useful for logging. + /// \return A string usable as TiledArray annotation if is_tensor() true, + /// empty string otherwise. /// - [[nodiscard]] std::string label() const noexcept; + [[nodiscard]] std::string braket_annot() const noexcept; private: EvalOp op_type_; diff --git a/SeQuant/domain/eval/eval.cpp b/SeQuant/domain/eval/eval.cpp index 653cfb9f5..17615d28a 100644 --- a/SeQuant/domain/eval/eval.cpp +++ b/SeQuant/domain/eval/eval.cpp @@ -7,8 +7,9 @@ namespace sequant { std::string const& EvalExprTA::annot() const { return annot_; } -EvalExprTA::EvalExprTA(Tensor const& tnsr) - : EvalExpr(tnsr), annot_{indices_to_annot(inner_outer_indices())} {} +EvalExprTA::EvalExprTA(Tensor const& tnsr) : EvalExpr(tnsr) { + annot_ = braket_annot(); +} EvalExprTA::EvalExprTA(Constant const& c) : EvalExpr(c), annot_{} {} @@ -22,7 +23,7 @@ EvalExprTA::EvalExprTA(const EvalExprTA& left, const EvalExprTA& right, using TA::expressions::GEMMPermutationOptimizer; if (result_type() == ResultType::Tensor) { - annot_ = indices_to_annot(inner_outer_indices()); + annot_ = braket_annot(); if (left.result_type() == right.result_type() && op_type() == EvalOp::Prod && !tot()) { // tensor x tensor confirmed diff --git a/tests/unit/test_eval_expr.cpp b/tests/unit/test_eval_expr.cpp index 6ebecd05c..9928f1967 100644 --- a/tests/unit/test_eval_expr.cpp +++ b/tests/unit/test_eval_expr.cpp @@ -272,43 +272,6 @@ TEST_CASE("TEST_EVAL_EXPR", "[EvalExpr]") { REQUIRE(symmetry(imed(t5, t6)) == Symmetry::nonsymm); } - SECTION("Inner and outer indices") { - auto same_inner_outer = [](Tensor const& t, IndexList inner, - IndexList outer) -> bool { - auto [in, out] = EvalExpr{t}.inner_outer_indices(); - return same_index_labels(in, inner) && same_index_labels(out, outer); - }; - - auto c1 = parse_expr(L"3/2")->as(); - - REQUIRE(EvalExpr{c1}.inner_outer_indices().inner.empty()); - REQUIRE(EvalExpr{c1}.inner_outer_indices().outer.empty()); - - auto f1 = parse_expr(L"f{i2;a2}")->as(); - REQUIRE(same_inner_outer(f1, // - {Index{L"i_2"}, Index{L"a_2"}}, // inner - {} // outer - )); - - auto f2 = parse_expr(L"f{i2;a2}")->as(); - REQUIRE(same_inner_outer(f2, // - {Index{L"a_2"}}, // inner - {Index{L"i_1"}, Index{L"i_2"}} // outer - )); - - auto t1 = parse_expr(L"t{a2,a3;i1,i2}")->as(); - REQUIRE(same_inner_outer( - t1, // - {Index{L"a_2"}, Index{L"a_3"}, Index{L"i_1"}, Index{L"i_2"}}, // inner - {} // outer - )); - auto t2 = parse_expr(L"t{a2,a3;i1,i2}")->as(); - REQUIRE(same_inner_outer(t2, // - {Index{L"a_2"}, Index{L"a_3"}}, // inner - {Index{L"i_1"}, Index{L"i_2"}} // outer - )); - } - SECTION("Debug") { auto t1 = EvalExpr{parse_expr(L"O{a_1;a_1}", Symmetry::nonsymm) From 0157a974164a1d0815c6332b681b9a8eabb2501a Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Tue, 2 Jan 2024 14:46:45 -0500 Subject: [PATCH 02/40] Use generic random_tensor genrator for unit-tests. --- INSTALL.md | 2 +- SeQuant/core/eval_expr.cpp | 53 ++++++---- SeQuant/core/eval_expr.hpp | 15 +++ external/versions.cmake | 2 +- tests/unit/test_eval_ta.cpp | 197 ++++++++++++++++++++++-------------- 5 files changed, 174 insertions(+), 95 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index d1149c886..47883fde5 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -11,7 +11,7 @@ prerequisites: * [Range-V3](https://github.com/ericniebler/range-v3.git), tag 0.12.0, *if not found, SeQuant will download and build Range-V3* * optional: * for building coupled-cluster evaluation tests: - * [TiledArray](https://github.com/ValeevGroup/tiledarray.git), tag 81bafdc39568d7d5f981d4453e4a2f49a9c0c428 + * [TiledArray](https://github.com/ValeevGroup/tiledarray.git), tag efb852e9efa864d965fd29dff5d7bb5100694da1 * for building `stcc*` example programs * [Eigen](http://eigen.tuxfamily.org/), version 3 diff --git a/SeQuant/core/eval_expr.cpp b/SeQuant/core/eval_expr.cpp index 337f9baae..4bb3247eb 100644 --- a/SeQuant/core/eval_expr.cpp +++ b/SeQuant/core/eval_expr.cpp @@ -25,19 +25,41 @@ std::wstring_view const var_label = L"Z"; } // namespace +NestedTensorIndices::NestedTensorIndices(const sequant::Tensor& tnsr) { + auto push_ix = [this](Index const& ix) { + if (ix.has_proto_indices()) + inner.push_back(ix); + else + outer.push_back(ix); + }; + + for (auto const& ix : tnsr.const_braket()) { + push_ix(ix); + for (auto const& ix_proto : ix.proto_indices()) push_ix(ix_proto); + } + + if (!inner.empty()) { + ranges::actions::stable_sort(outer, Index::LabelCompare{}); + ranges::actions::unique(outer, [](Index const& ix1, Index const& ix2) { + return ix1.label() == ix2.label(); + }); + } +} + std::string EvalExpr::braket_annot() const noexcept { if (!is_tensor()) return {}; - auto const& tnsr = as_tensor(); - // select indices from @c tnsr's braket that satisfy @c pred - // and return their 'full_label's separated by commas - auto annot_group = [&tnsr](auto&& pred) -> std::string { + // given an iterable of sequant::Index objects, returns a string made + // of their full labels separted by comma + // eg. (a_1^{i_1,i_2},a_2^{i_2,i_3}) -> "a_1i_1i_2,a_2i_2i_3" + // eg. (i_1, i_2) -> "i_1,i_2" + auto annot = [](auto&& ixs) -> std::string { using namespace ranges::views; - auto full_labels = tnsr.const_braket() // - | filter(pred) // - | transform(&Index::full_label) // - | transform([](auto&& fl) { // - return sequant::to_string(fl); // + + auto full_labels = ixs // + | transform(&Index::full_label) // + | transform([](auto&& fl) { // + return sequant::to_string(fl); }); return full_labels // | intersperse(std::string{","}) // @@ -45,16 +67,11 @@ std::string EvalExpr::braket_annot() const noexcept { | ranges::to; }; - auto outer_annot = annot_group( // - ranges::not_fn( // - &Index::has_proto_indices) // - ); - - auto inner_annot = annot_group(&Index::has_proto_indices); + auto nested = NestedTensorIndices{as_tensor()}; - return inner_annot.empty() // - ? outer_annot - : outer_annot + ";" + inner_annot; + return nested.inner.empty() // + ? annot(nested.outer) + : annot(nested.outer) + ";" + annot(nested.inner); } size_t EvalExpr::global_id_{}; diff --git a/SeQuant/core/eval_expr.hpp b/SeQuant/core/eval_expr.hpp index b7596e00a..a8a893bd6 100644 --- a/SeQuant/core/eval_expr.hpp +++ b/SeQuant/core/eval_expr.hpp @@ -40,6 +40,21 @@ enum class EvalOp { /// enum class ResultType { Tensor, Scalar }; +/// +/// \brief Represents the outer indices and the inner indices of a nested +/// tensor. +/// +/// \note The nested tensor is a concept that generalizes the sequant::Tensor +/// with and without proto indices. sequant::Tensors with proto indices have +/// outer and inner indices, whereas, those without proto indices only have +/// outer indices. +/// +struct NestedTensorIndices { + container::svector outer, inner; + + explicit NestedTensorIndices(Tensor const&); +}; + /// /// \brief The EvalExpr class represents the object that go into the nodes of /// the binary tree that is used to evaluate the sequant expressions. diff --git a/external/versions.cmake b/external/versions.cmake index e3d4828e4..4ea764bc9 100644 --- a/external/versions.cmake +++ b/external/versions.cmake @@ -9,5 +9,5 @@ set(SEQUANT_TRACKED_BOOST_PREVIOUS_VERSION 1.72) set(SEQUANT_TRACKED_RANGEV3_TAG 0.12.0) set(SEQUANT_TRACKED_RANGEV3_PREVIOUS_TAG d800a032132512a54c291ce55a2a43e0460591c7) -set(SEQUANT_TRACKED_TILEDARRAY_TAG 81bafdc39568d7d5f981d4453e4a2f49a9c0c428) +set(SEQUANT_TRACKED_TILEDARRAY_TAG efb852e9efa864d965fd29dff5d7bb5100694da1) set(SEQUANT_TRACKED_TILEDARRAY_PREVIOUS_TAG d33511dac8e8baaaa28e295bffbd2503ef830c9d) diff --git a/tests/unit/test_eval_ta.cpp b/tests/unit/test_eval_ta.cpp index fa48efb39..ab8bd8383 100644 --- a/tests/unit/test_eval_ta.cpp +++ b/tests/unit/test_eval_ta.cpp @@ -31,78 +31,50 @@ auto tensor_to_key(std::wstring_view spec) { return tensor_to_key(sequant::parse_expr(spec, sequant::Symmetry::nonsymm) ->as()); } +template +auto random_tensor(TA::Range const& rng) { + TA::Tensor result{rng}; + std::generate(result.begin(), result.end(), + TA::detail::MakeRandom::generate_value); + return result; +} -template -class rand_tensor_yield { - public: - using numeric_t = typename Tensor_t::numeric_type; +// note: all the inner tensors (elements of the outer tensor) +// have the same @c inner_rng +template +auto random_tensor_of_tensor(TA::Range const& outer_rng, + TA::Range const& inner_rng) { + TA::Tensor> result{outer_rng}; - private: - TA::World& world_; - size_t const nocc_; - size_t const nvirt_; - mutable std::map label_to_er_; + std::generate(result.begin(), result.end(), + [&inner_rng]() -> decltype(result)::value_type { + return random_tensor(inner_rng); + }); - public: - [[nodiscard]] Tensor_t make_rand_tensor(sequant::Tensor const& tnsr) const { - using ranges::views::transform; - using sequant::IndexSpace; - - assert(ranges::all_of(tnsr.const_braket(), - [](auto const& idx) { - return idx.space() == IndexSpace::active_occupied || - idx.space() == IndexSpace::active_unoccupied; - }) && - "Unsupported IndexSpace type found while generating tensor."); - - auto trange_vec = - tnsr.const_braket() | - transform([no = nocc_, nv = nvirt_](auto const& idx) { - return TA::TiledRange1{ - 0, idx.space() == IndexSpace::active_occupied ? no : nv}; - }) | - ranges::to_vector; - - Tensor_t result{world_, - TA::TiledRange{trange_vec.begin(), trange_vec.end()}}; - result.template init_elements([](auto const&) { - return static_cast(std::rand()) / - static_cast(RAND_MAX); - }); - return result; - } + return result; +} - rand_tensor_yield(TA::World& world, size_t noccupied, size_t nvirtual) - : world_{world}, nocc_{noccupied}, nvirt_{nvirtual} {} +template +class rand_tensor_yield { + TA::World& world; + size_t nocc_; + size_t nvirt_; + mutable sequant::container::map label_to_er_; - sequant::ERPtr operator()(sequant::Tensor const& tnsr) const { - using result_t = sequant::EvalTensorTA; - std::wstring const label = tensor_to_key(tnsr); - if (auto&& found = label_to_er_.find(label); found != label_to_er_.end()) { - // std::cout << "label = [" << sequant::to_string(label) - // << "] FOUND in cache. Returning.." << std::endl; - return found->second; - } - Tensor_t t = make_rand_tensor(tnsr); - auto success = label_to_er_.emplace( - label, sequant::eval_result(std::move(t))); - assert(success.second && "couldn't store ERPtr!"); - // std::cout << "label = [" << sequant::to_string(label) - // << "] NotFound in cache. Creating.." << std::endl; - return success.first->second; - } + public: + rand_tensor_yield(TA::World& world_, size_t nocc, size_t nvirt) + : world{world_}, nocc_{nocc}, nvirt_{nvirt} {} sequant::ERPtr operator()(sequant::Variable const& var) const { - using result_t = sequant::EvalScalar; - std::wstring const key{var.label()}; - if (auto&& found = label_to_er_.find(key); found != label_to_er_.end()) - return found->second; - auto success = label_to_er_.emplace( - key, - sequant::eval_result(static_cast(std::rand()) / - static_cast(RAND_MAX))); - assert(success.second && "couldn't store ERPtr!"); - return success.first->second; + using result_t = sequant::EvalScalar; + + auto make_var = []() { + return sequant::eval_result( + TA::detail::MakeRandom::generate_value()); + }; + + return label_to_er_.try_emplace(std::wstring{var.label()}, make_var()) + .first->second; } template >> @@ -114,18 +86,91 @@ class rand_tensor_yield { assert(node->is_constant()); - using result_t = EvalScalar; + using result_t = EvalScalar; - auto d = node->as_constant().template value(); + auto d = (node->as_constant()).template value(); return eval_result(d); } + sequant::ERPtr operator()(sequant::Tensor const& tnsr) const { + using namespace ranges::views; + using namespace sequant; + + std::wstring const label = tensor_to_key(tnsr); + if (auto&& found = label_to_er_.find(label); found != label_to_er_.end()) { + // std::cout << "label = [" << sequant::to_string(label) + // << "] FOUND in cache. Returning.." << std::endl; + return found->second; + } + + ERPtr result{nullptr}; + + auto make_extents = [this](auto&& ixs) -> container::svector { + return ixs | transform([this](auto const& ix) -> size_t { + assert(ix.space() == IndexSpace::active_occupied || + ix.space() == IndexSpace::active_unoccupied); + return ix.space() == IndexSpace::active_occupied ? nocc_ + : nvirt_; + }) | + ranges::to>; + }; + + NestedTensorIndices nested{tnsr}; + + auto const outer_extent = make_extents(nested.outer); + auto const outer_tr = TA::TiledRange{outer_extent | transform([](auto&& e) { + return TA::TiledRange1{0, e}; + }) | + ranges::to_vector}; + auto const outer_r = TA::Range(outer_extent); + + if (nested.inner.empty()) { + // regular tensor + using ArrayT = TA::DistArray, TAPolicyT>; + ArrayT array{world, outer_tr}; + for (auto it = array.begin(); it != array.end(); ++it) + if (array.is_local(it.index())) + *it = world.taskq.add(random_tensor, it.make_range()); + result = eval_result>(array); + } else { + // tensor of tensor + using ArrayT = TA::DistArray>, TAPolicyT>; + + auto const inner_extent = make_extents(nested.inner); + auto const inner_r = TA::Range(inner_extent); + + auto make_tile = [&inner_r](TA::Range const& orng) { + return random_tensor_of_tensor(orng, inner_r); + }; + + ArrayT array{world, outer_tr}; + + for (auto it = array.begin(); it != array.end(); ++it) + if (array.is_local(it.index())) + *it = world.taskq.add(make_tile, it.make_range()); + + result = eval_result>(array); + } + + auto success = label_to_er_.emplace(label, result); + assert(success.second && "couldn't store ERPtr!"); + // std::cout << "label = [" << sequant::to_string(label) + // << "] NotFound in cache. Creating.." << std::endl; + return success.first->second; + } + + /// + /// \param label eg. + /// - 't_vvoo', 'f_ov' for generic tensor key strings + /// - 't{a1,a2;i1,i2}', 'f{i1;a1}' supported by sequant::parse_expr + /// + /// \return ERPtr + /// + /// \note The ERPtr should already exist in the cache otherwise throws. + /// This overload is only intended to access already existing ERPtrs + /// from the cache. To create a new cache entry use the + /// operator()(Tesnor const&) overload. /// - /// \param label eg. t_vvoo, f_ov - /// \return const ref to Tensor_t type tensor - /// \note The tensor should be already present in the yielder cache - /// otherwise throws assertion error. To avoid that use the other - /// overload of operator() that takes sequant::Tensor const& sequant::ERPtr operator()(std::wstring_view label) const { auto&& found = label_to_er_.find(label.data()); if (found == label_to_er_.end()) @@ -135,6 +180,7 @@ class rand_tensor_yield { return found->second; } }; + } // namespace TEST_CASE("TEST_EVAL_USING_TA", "[eval]") { @@ -158,7 +204,7 @@ TEST_CASE("TEST_EVAL_USING_TA", "[eval]") { auto& world = TA::get_default_world(); const size_t nocc = 2, nvirt = 20; - auto yield_ = rand_tensor_yield{world, nocc, nvirt}; + auto yield_ = rand_tensor_yield{world, nocc, nvirt}; auto yield = [&yield_](std::wstring_view lbl) -> TA::TArrayD const& { return yield_(lbl)->get(); }; @@ -380,7 +426,8 @@ TEST_CASE("TEST_EVAL_USING_TA_COMPLEX", "[eval]") { const size_t nocc = 2, nvirt = 20; auto& world = TA::get_default_world(); - auto yield_ = rand_tensor_yield{world, nocc, nvirt}; + auto yield_ = rand_tensor_yield, TA::DensePolicy>{ + world, nocc, nvirt}; auto yield = [&yield_](std::wstring_view lbl) -> TArrayC const& { return yield_(lbl)->get(); @@ -590,4 +637,4 @@ TEST_CASE("TEST_EVAL_USING_TA_COMPLEX", "[eval]") { REQUIRE(norm(eval1) == Approx(norm(eval2))); } -} \ No newline at end of file +} From a77671c1d4f39418563354e16b428a44f5867ae5 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Tue, 2 Jan 2024 15:46:49 -0500 Subject: [PATCH 03/40] Tiny cleanups. --- tests/unit/test_eval_ta.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/unit/test_eval_ta.cpp b/tests/unit/test_eval_ta.cpp index ab8bd8383..19439a9c8 100644 --- a/tests/unit/test_eval_ta.cpp +++ b/tests/unit/test_eval_ta.cpp @@ -47,9 +47,7 @@ auto random_tensor_of_tensor(TA::Range const& outer_rng, TA::Tensor> result{outer_rng}; std::generate(result.begin(), result.end(), - [&inner_rng]() -> decltype(result)::value_type { - return random_tensor(inner_rng); - }); + [&inner_rng]() { return random_tensor(inner_rng); }); return result; } @@ -199,8 +197,6 @@ TEST_CASE("TEST_EVAL_USING_TA", "[eval]") { // tnsr is assumed to be single-tiled auto norm = [](TArrayD const& tnsr) { return TA::norm2(tnsr); }; - std::srand(2021); - auto& world = TA::get_default_world(); const size_t nocc = 2, nvirt = 20; @@ -422,7 +418,6 @@ TEST_CASE("TEST_EVAL_USING_TA_COMPLEX", "[eval]") { using TArrayC = TA::DistArray>>; auto norm = [](TArrayC const& tnsr) { return TA::norm2(tnsr); }; - std::srand(2023); const size_t nocc = 2, nvirt = 20; auto& world = TA::get_default_world(); From 5ce01ab2d97b774b402da39d249816d608298c60 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Wed, 3 Jan 2024 09:42:13 -0500 Subject: [PATCH 04/40] Refactor, and restrict template argument to EvalTensorTA class template. --- SeQuant/domain/eval/eval_result.hpp | 60 ++++++++++++++++------------- tests/unit/test_eval_ta.cpp | 3 +- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/SeQuant/domain/eval/eval_result.hpp b/SeQuant/domain/eval/eval_result.hpp index a59afac06..25dd44844 100644 --- a/SeQuant/domain/eval/eval_result.hpp +++ b/SeQuant/domain/eval/eval_result.hpp @@ -710,34 +710,38 @@ class EvalScalar final : public EvalResult { /// /// \brief EvalResult for a tensor value of TA::DistArray type. -/// \tparam T TA::DistArray type. Must be a specialization of TA::DistArray. +/// \tparam ArrayT TA::DistArray type. Tile type of ArrayT is regular tensor of +/// scalars (not a tensor of tensors) /// -template +template >> class EvalTensorTA final : public EvalResult { public: using EvalResult::id_t; - using numeric_type = std::decay_t; + using numeric_type = std::decay_t; - explicit EvalTensorTA(T arr) : EvalResult{std::move(arr)} {} + explicit EvalTensorTA(ArrayT arr) : EvalResult{std::move(arr)} {} private: + using this_type = EvalTensorTA; using annot_wrap = Annot; [[nodiscard]] id_t type_id() const noexcept override { - return id_for_type>(); + return id_for_type(); } [[nodiscard]] ERPtr sum(EvalResult const& other, std::array const& annot) const override { - assert(other.is>()); + assert(other.is()); auto const a = annot_wrap{annot}; log_ta(a.lannot, " + ", a.rannot, " = ", a.this_annot, "\n"); - T result; - result(a.this_annot) = get()(a.lannot) + other.get()(a.rannot); + ArrayT result; + result(a.this_annot) = + get()(a.lannot) + other.get()(a.rannot); decltype(result)::wait_for_lazy_cleanup(result.world()); - return eval_result>(std::move(result)); + return eval_result(std::move(result)); } [[nodiscard]] ERPtr prod( @@ -746,7 +750,7 @@ class EvalTensorTA final : public EvalResult { auto const a = annot_wrap{annot}; if (other.is>()) { - auto result = get(); + auto result = get(); auto scalar = other.get(); log_ta(a.lannot, " * ", scalar, " = ", a.this_annot, "\n"); @@ -754,16 +758,17 @@ class EvalTensorTA final : public EvalResult { result(a.this_annot) = scalar * result(a.lannot); decltype(result)::wait_for_lazy_cleanup(result.world()); - return eval_result>(std::move(result)); + return eval_result(std::move(result)); } - assert(other.is>()); + assert(other.is()); if (a.this_annot.empty()) { // DOT product - numeric_type d = TA::dot(get()(a.lannot), other.get()(a.rannot)); - T::wait_for_lazy_cleanup(get().world()); - T::wait_for_lazy_cleanup(other.get().world()); + numeric_type d = + TA::dot(get()(a.lannot), other.get()(a.rannot)); + ArrayT::wait_for_lazy_cleanup(get().world()); + ArrayT::wait_for_lazy_cleanup(other.get().world()); log_ta(a.lannot, " * ", a.rannot, " = ", d, "\n"); @@ -772,10 +777,11 @@ class EvalTensorTA final : public EvalResult { log_ta(a.lannot, " * ", a.rannot, " = ", a.this_annot, "\n"); - T result; - result(a.this_annot) = get()(a.lannot) * other.get()(a.rannot); + ArrayT result; + result(a.this_annot) = + get()(a.lannot) * other.get()(a.rannot); decltype(result)::wait_for_lazy_cleanup(result.world()); - return eval_result>(std::move(result)); + return eval_result(std::move(result)); } [[nodiscard]] ERPtr permute( @@ -785,15 +791,15 @@ class EvalTensorTA final : public EvalResult { log_ta(pre_annot, " = ", post_annot, "\n"); - T result; - result(post_annot) = get()(pre_annot); - T::wait_for_lazy_cleanup(result.world()); - return eval_result>(std::move(result)); + ArrayT result; + result(post_annot) = get()(pre_annot); + ArrayT::wait_for_lazy_cleanup(result.world()); + return eval_result(std::move(result)); } void add_inplace(EvalResult const& other) override { - auto& t = get(); - auto const& o = other.get(); + auto& t = get(); + auto const& o = other.get(); assert(t.trange() == o.trange()); auto ann = TA::detail::dummy_annotation(t.trange().rank()); @@ -801,17 +807,17 @@ class EvalTensorTA final : public EvalResult { log_ta(ann, " += ", ann, "\n"); t(ann) += o(ann); - T::wait_for_lazy_cleanup(t.world()); + ArrayT::wait_for_lazy_cleanup(t.world()); } [[nodiscard]] ERPtr symmetrize( container::svector> const& groups) const override { - return eval_result>(symmetrize_ta(get(), groups)); + return eval_result(symmetrize_ta(get(), groups)); } [[nodiscard]] ERPtr antisymmetrize( container::svector> const& groups) const override { - return eval_result>(antisymmetrize_ta(get(), groups)); + return eval_result(antisymmetrize_ta(get(), groups)); } }; diff --git a/tests/unit/test_eval_ta.cpp b/tests/unit/test_eval_ta.cpp index 19439a9c8..25038844d 100644 --- a/tests/unit/test_eval_ta.cpp +++ b/tests/unit/test_eval_ta.cpp @@ -147,7 +147,8 @@ class rand_tensor_yield { if (array.is_local(it.index())) *it = world.taskq.add(make_tile, it.make_range()); - result = eval_result>(array); + // todo + // result = eval_result>(array); } auto success = label_to_er_.emplace(label, result); From 0d4b16bcd8c1c33614727bd2423208bfd1e1e418 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Wed, 3 Jan 2024 10:48:24 -0500 Subject: [PATCH 05/40] [wip] ToT support in SeQuant. --- SeQuant/domain/eval/eval_result.hpp | 140 +++++++++++++++++++++++++++- tests/unit/test_eval_ta.cpp | 3 +- 2 files changed, 138 insertions(+), 5 deletions(-) diff --git a/SeQuant/domain/eval/eval_result.hpp b/SeQuant/domain/eval/eval_result.hpp index 25dd44844..f9c2aa2cb 100644 --- a/SeQuant/domain/eval/eval_result.hpp +++ b/SeQuant/domain/eval/eval_result.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -718,7 +719,7 @@ template ; + using numeric_type = typename ArrayT::numeric_type; explicit EvalTensorTA(ArrayT arr) : EvalResult{std::move(arr)} {} @@ -761,10 +762,9 @@ class EvalTensorTA final : public EvalResult { return eval_result(std::move(result)); } - assert(other.is()); - if (a.this_annot.empty()) { // DOT product + assert(other.is()); numeric_type d = TA::dot(get()(a.lannot), other.get()(a.rannot)); ArrayT::wait_for_lazy_cleanup(get().world()); @@ -775,6 +775,15 @@ class EvalTensorTA final : public EvalResult { return eval_result>(d); } + if (!other.is()) { + // potential T * ToT + auto annot_swap = annot; + std::swap(annot_swap[0], annot_swap[1]); + return other.prod(*this, annot_swap); + } + + // confirmed: other.is() is true + log_ta(a.lannot, " * ", a.rannot, " = ", a.this_annot, "\n"); ArrayT result; @@ -798,6 +807,8 @@ class EvalTensorTA final : public EvalResult { } void add_inplace(EvalResult const& other) override { + assert(other.is()); + auto& t = get(); auto const& o = other.get(); @@ -821,6 +832,129 @@ class EvalTensorTA final : public EvalResult { } }; +template >> +class EvalTensorOfTensorTA final : public EvalResult { + public: + using EvalResult::id_t; + using numeric_type = typename ArrayT::numeric_type; + + explicit EvalTensorOfTensorTA(ArrayT arr) : EvalResult{std::move(arr)} {} + + private: + using this_type = EvalTensorOfTensorTA; + using annot_wrap = Annot; + + using _inner_tensor_type = typename ArrayT::value_type::value_type; + + using compatible_regular_distarray_type = + TA::DistArray<_inner_tensor_type, typename ArrayT::policy_type>; + + // Only @c that_type type is allowed for ToT * T computation + using that_type = EvalTensorTA; + + [[nodiscard]] id_t type_id() const noexcept override { + return id_for_type(); + } + + [[nodiscard]] ERPtr sum(EvalResult const& other, + std::array const& annot) const override { + assert(other.is()); + auto const a = annot_wrap{annot}; + + log_ta(a.lannot, " + ", a.rannot, " = ", a.this_annot, "\n"); + + ArrayT result; + result(a.this_annot) = + get()(a.lannot) + other.get()(a.rannot); + decltype(result)::wait_for_lazy_cleanup(result.world()); + return eval_result(std::move(result)); + } + + [[nodiscard]] ERPtr prod( + EvalResult const& other, + std::array const& annot) const override { + auto const a = annot_wrap{annot}; + + if (other.is>()) { + auto result = get(); + auto scalar = other.get(); + + log_ta(a.lannot, " * ", scalar, " = ", a.this_annot, "\n"); + + result(a.this_annot) = scalar * result(a.lannot); + + decltype(result)::wait_for_lazy_cleanup(result.world()); + return eval_result(std::move(result)); + } else if (a.this_annot.empty()) { + // DOT product + assert(other.is()); + numeric_type d = + TA::dot(get()(a.lannot), other.get()(a.rannot)); + ArrayT::wait_for_lazy_cleanup(get().world()); + ArrayT::wait_for_lazy_cleanup(other.get().world()); + + log_ta(a.lannot, " * ", a.rannot, " = ", d, "\n"); + + return eval_result>(d); + + } else if (other.is() || other.is()) { + // ToT * ToT -> ToT OR ToT * T -> ToT + log_ta(a.lannot, " * ", a.rannot, " = ", a.this_annot, "\n"); + ArrayT result = + TA::einsum(get()(a.lannot), + other.get()(a.rannot), + a.this_annot); + return eval_result(std::move(result)); + } else { + throw invalid_operand(); + } + } + + [[nodiscard]] ERPtr permute( + std::array const& ann) const override { + auto const pre_annot = std::any_cast(ann[0]); + auto const post_annot = std::any_cast(ann[1]); + + log_ta(pre_annot, " = ", post_annot, "\n"); + + ArrayT result; + result(post_annot) = get()(pre_annot); + ArrayT::wait_for_lazy_cleanup(result.world()); + return eval_result(std::move(result)); + } + + void add_inplace(EvalResult const& other) override { + assert(other.is()); + + auto& t = get(); + auto const& o = other.get(); + + assert(t.trange() == o.trange()); + auto ann = TA::detail::dummy_annotation(t.trange().rank()); + + log_ta(ann, " += ", ann, "\n"); + + t(ann) += o(ann); + ArrayT::wait_for_lazy_cleanup(t.world()); + } + + [[nodiscard]] ERPtr symmetrize( + container::svector> const& groups) const override { + // todo + // return eval_result(symmetrize_ta(get(), groups)); + return nullptr; + } + + [[nodiscard]] ERPtr antisymmetrize( + container::svector> const& groups) const override { + // todo + // return eval_result(antisymmetrize_ta(get(), groups)); + return nullptr; + } +}; + /// /// \brief EvalResult for a tensor value of btas::Tensor type. /// \tparam T btas::Tensor type. Must be a specialization of btas::Tensor. diff --git a/tests/unit/test_eval_ta.cpp b/tests/unit/test_eval_ta.cpp index 25038844d..a5c84580c 100644 --- a/tests/unit/test_eval_ta.cpp +++ b/tests/unit/test_eval_ta.cpp @@ -147,8 +147,7 @@ class rand_tensor_yield { if (array.is_local(it.index())) *it = world.taskq.add(make_tile, it.make_range()); - // todo - // result = eval_result>(array); + result = eval_result>(array); } auto success = label_to_er_.emplace(label, result); From 97cc169637176bc28831057d1d283506262701be Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Thu, 4 Jan 2024 08:00:01 -0500 Subject: [PATCH 06/40] Bug fix. --- SeQuant/domain/eval/eval_result.hpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/SeQuant/domain/eval/eval_result.hpp b/SeQuant/domain/eval/eval_result.hpp index f9c2aa2cb..0c6453857 100644 --- a/SeQuant/domain/eval/eval_result.hpp +++ b/SeQuant/domain/eval/eval_result.hpp @@ -898,18 +898,27 @@ class EvalTensorOfTensorTA final : public EvalResult { log_ta(a.lannot, " * ", a.rannot, " = ", d, "\n"); return eval_result>(d); + } + + log_ta(a.lannot, " * ", a.rannot, " = ", a.this_annot, "\n"); + ArrayT result; - } else if (other.is() || other.is()) { - // ToT * ToT -> ToT OR ToT * T -> ToT - log_ta(a.lannot, " * ", a.rannot, " = ", a.this_annot, "\n"); - ArrayT result = + if (other.is()) { + // ToT * T -> ToT + result = TA::einsum(get()(a.lannot), other.get()(a.rannot), a.this_annot); - return eval_result(std::move(result)); + + } else if (other.is()) { + // ToT * ToT -> ToT + result = TA::einsum(get()(a.lannot), + other.get()(a.rannot), a.this_annot); } else { throw invalid_operand(); } + + return eval_result(std::move(result)); } [[nodiscard]] ERPtr permute( From b13e173648f98af8835588601bf9ee5fe11bab4b Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Fri, 19 Jan 2024 11:48:58 -0500 Subject: [PATCH 07/40] Add tests involving tot times t, and tot times tot. --- tests/unit/test_eval_ta.cpp | 100 +++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_eval_ta.cpp b/tests/unit/test_eval_ta.cpp index a5c84580c..d70cc86b5 100644 --- a/tests/unit/test_eval_ta.cpp +++ b/tests/unit/test_eval_ta.cpp @@ -31,6 +31,7 @@ auto tensor_to_key(std::wstring_view spec) { return tensor_to_key(sequant::parse_expr(spec, sequant::Symmetry::nonsymm) ->as()); } + template auto random_tensor(TA::Range const& rng) { TA::Tensor result{rng}; @@ -47,7 +48,7 @@ auto random_tensor_of_tensor(TA::Range const& outer_rng, TA::Tensor> result{outer_rng}; std::generate(result.begin(), result.end(), - [&inner_rng]() { return random_tensor(inner_rng); }); + [inner_rng]() { return random_tensor(inner_rng); }); return result; } @@ -60,6 +61,11 @@ class rand_tensor_yield { mutable sequant::container::map label_to_er_; public: + using array_type = TA::DistArray, TAPolicyT>; + using array_tot_type = + TA::DistArray>, TAPolicyT>; + using numeric_type = NumericT; + rand_tensor_yield(TA::World& world_, size_t nocc, size_t nvirt) : world{world_}, nocc_{nocc}, nvirt_{nvirt} {} @@ -137,7 +143,7 @@ class rand_tensor_yield { auto const inner_extent = make_extents(nested.inner); auto const inner_r = TA::Range(inner_extent); - auto make_tile = [&inner_r](TA::Range const& orng) { + auto make_tile = [inner_r](TA::Range const& orng) { return random_tensor_of_tensor(orng, inner_r); }; @@ -154,6 +160,7 @@ class rand_tensor_yield { assert(success.second && "couldn't store ERPtr!"); // std::cout << "label = [" << sequant::to_string(label) // << "] NotFound in cache. Creating.." << std::endl; + assert(success.first->second); return success.first->second; } @@ -633,3 +640,92 @@ TEST_CASE("TEST_EVAL_USING_TA_COMPLEX", "[eval]") { REQUIRE(norm(eval1) == Approx(norm(eval2))); } } + +TEST_CASE("TEST_EVAL_USING_TA_TOT", "[eval_tot]") { + using namespace sequant; + + // + // eg: approx_equal("i,j;a,b", arr1, arr2) + // - arr1 and arr2 are DistArrays with equal TiledRange and matching Range for + // the inner tensors at the corresponding tile positions. + // - 'i', 'j', 'a', and 'b' are dummy indices that annotate the modes of outer + // and inner tensors. Why? Because TA::norm2 function is not supported for + // tensor-of-tensor tiles + // + auto approx_equal = [](std::string const& annot, auto const& lhs, + auto const& rhs) -> bool { + return Approx(lhs(annot).dot(lhs(annot))) == rhs(annot).dot(rhs(annot)); + }; + + auto& world = TA::get_default_world(); + + size_t const nocc = 2; + size_t const nvirt = 3; + + rand_tensor_yield yield{world, nocc, nvirt}; + + using ArrayT = typename decltype(yield)::array_type; + using ArrayToT = typename decltype(yield)::array_tot_type; + using NumericT = typename decltype(yield)::numeric_type; + + SECTION("T_times_ToT_to_ToT") { + constexpr std::wstring_view expr_str = + L"3" + L" * " + L"f{i3;i1}" + L" * " + L"t{a3,a4;i2,i3}"; + auto const node = eval_node(parse_expr(expr_str)); + std::string const target_layout{"i_1,i_2,i_3;a_3i_2i_3,a_4i_2i_3"}; + auto result = evaluate(node, target_layout, yield)->get(); + ArrayToT ref; + { + auto const& lhs = yield(L"f{i3;i1}")->get(); + auto const& rhs = yield(L"t{a3,a4;i2,i3}")->get(); + ref = TA::einsum(lhs("i_3,i_1"), rhs("i_2,i_3;a_3i_2i_3,a_4i_2i_3"), + target_layout); + ref(target_layout) = 3 * ref(target_layout); + } + REQUIRE(approx_equal("i,j,k;a,b", result, ref)); + } + + SECTION("ToT_times_ToT_to_ToT") { + constexpr std::wstring_view expr_str = + L"I{a4,a1;i1,i2}" + L" * " + L"s{a2;a4}"; + + auto const node = eval_node(parse_expr(expr_str)); + std::string const target_layout{"i_2,i_1;a_1i_1i_2,a_2i_1i_2"}; + + auto result = evaluate(node, target_layout, yield)->get(); + + ArrayToT ref; + { + auto const& lhs = yield(L"I{a4,a1;i1,i2}")->get(); + auto const& rhs = yield(L"s{a2;a4}")->get(); + ref = TA::einsum(lhs("i_1,i_2,i_3;a_4i_2i_3,a_1i_1i_2"), + rhs("i_1,i_2,i_3;a_2i_1i_2,a_4i_2i_3"), target_layout); + } + REQUIRE(approx_equal("i,j;a,b", result, ref)); + } + + SECTION("ToT_times_ToT_to_Scalar") { + constexpr std::wstring_view expr_str = + L"I{a1,a2;i1,i2}" + L" * " + L"g{i1,i2;a2,a1}"; + auto const node = eval_node(parse_expr(expr_str)); + + auto result = evaluate(node, yield)->get(); + + NumericT ref; + { + auto const& lhs = yield(L"I{a1,a2;i1,i2}")->get(); + auto const& rhs = yield(L"g{i1,i2;a2,a1}")->get(); + ref = TA::dot(lhs("i_1,i_2;a_1i_1i_2,a_2i_1i_2"), + rhs("i_1,i_2;a_2i_1i_2,a_1i_1i_2")); + } + REQUIRE(result == Approx(ref)); + } +} From a8aa3bcbb10c82e1b2d93e10bdaa560c7160edf2 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Fri, 19 Jan 2024 11:52:06 -0500 Subject: [PATCH 08/40] Update tracked TiledArray version. --- INSTALL.md | 2 +- external/versions.cmake | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 47883fde5..cbfb45624 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -11,7 +11,7 @@ prerequisites: * [Range-V3](https://github.com/ericniebler/range-v3.git), tag 0.12.0, *if not found, SeQuant will download and build Range-V3* * optional: * for building coupled-cluster evaluation tests: - * [TiledArray](https://github.com/ValeevGroup/tiledarray.git), tag efb852e9efa864d965fd29dff5d7bb5100694da1 + * [TiledArray](https://github.com/ValeevGroup/tiledarray.git), tag df0b808f46cc05bfc797e85b82f1397ac3824893 * for building `stcc*` example programs * [Eigen](http://eigen.tuxfamily.org/), version 3 diff --git a/external/versions.cmake b/external/versions.cmake index 4ea764bc9..0f73c8edc 100644 --- a/external/versions.cmake +++ b/external/versions.cmake @@ -9,5 +9,5 @@ set(SEQUANT_TRACKED_BOOST_PREVIOUS_VERSION 1.72) set(SEQUANT_TRACKED_RANGEV3_TAG 0.12.0) set(SEQUANT_TRACKED_RANGEV3_PREVIOUS_TAG d800a032132512a54c291ce55a2a43e0460591c7) -set(SEQUANT_TRACKED_TILEDARRAY_TAG efb852e9efa864d965fd29dff5d7bb5100694da1) -set(SEQUANT_TRACKED_TILEDARRAY_PREVIOUS_TAG d33511dac8e8baaaa28e295bffbd2503ef830c9d) +set(SEQUANT_TRACKED_TILEDARRAY_TAG df0b808f46cc05bfc797e85b82f1397ac3824893) +set(SEQUANT_TRACKED_TILEDARRAY_PREVIOUS_TAG efb852e9efa864d965fd29dff5d7bb5100694da1) From 5df89365077fb877fbf9e414f8958304a26dfb51 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Fri, 19 Jan 2024 15:15:09 -0500 Subject: [PATCH 09/40] Trying to appease Apple Clang 14 --- tests/unit/test_eval_ta.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_eval_ta.cpp b/tests/unit/test_eval_ta.cpp index d70cc86b5..24b31f3c9 100644 --- a/tests/unit/test_eval_ta.cpp +++ b/tests/unit/test_eval_ta.cpp @@ -123,7 +123,7 @@ class rand_tensor_yield { auto const outer_extent = make_extents(nested.outer); auto const outer_tr = TA::TiledRange{outer_extent | transform([](auto&& e) { - return TA::TiledRange1{0, e}; + return TA::TiledRange1(0, e); }) | ranges::to_vector}; auto const outer_r = TA::Range(outer_extent); From c9ede232fa18e5e3dd4c9a5d5965322656008f30 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Fri, 19 Jan 2024 15:40:04 -0500 Subject: [PATCH 10/40] Trying to appease Apple Clang 14 --- tests/unit/test_eval_ta.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/unit/test_eval_ta.cpp b/tests/unit/test_eval_ta.cpp index 24b31f3c9..0e1c5d272 100644 --- a/tests/unit/test_eval_ta.cpp +++ b/tests/unit/test_eval_ta.cpp @@ -122,10 +122,9 @@ class rand_tensor_yield { NestedTensorIndices nested{tnsr}; auto const outer_extent = make_extents(nested.outer); - auto const outer_tr = TA::TiledRange{outer_extent | transform([](auto&& e) { - return TA::TiledRange1(0, e); - }) | - ranges::to_vector}; + auto const outer_tr = TA::TiledRange{ + outer_extent | transform([](auto e) { return TA::TiledRange1(0, e); }) | + ranges::to_vector}; auto const outer_r = TA::Range(outer_extent); if (nested.inner.empty()) { From 54d67b6e052907e407f441e03b6d0d162f721543 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Fri, 19 Jan 2024 16:04:30 -0500 Subject: [PATCH 11/40] Trying to appease Apple Clang 14 --- tests/unit/test_eval_ta.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/unit/test_eval_ta.cpp b/tests/unit/test_eval_ta.cpp index 0e1c5d272..3520272e1 100644 --- a/tests/unit/test_eval_ta.cpp +++ b/tests/unit/test_eval_ta.cpp @@ -122,9 +122,14 @@ class rand_tensor_yield { NestedTensorIndices nested{tnsr}; auto const outer_extent = make_extents(nested.outer); - auto const outer_tr = TA::TiledRange{ - outer_extent | transform([](auto e) { return TA::TiledRange1(0, e); }) | - ranges::to_vector}; + + auto const outer_tr = [&outer_extent]() { + container::vector tr1s; + tr1s.reserve(outer_extent.size()); + for (auto e : outer_extent) tr1s.emplace_back(TA::TiledRange1(0, e)); + return TA::TiledRange(tr1s.begin(), tr1s.end()); + }(); + auto const outer_r = TA::Range(outer_extent); if (nested.inner.empty()) { From 9c042729a55f340edddf799d4b29bb8e0e011b18 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Sat, 17 Feb 2024 11:10:18 -0500 Subject: [PATCH 12/40] TiledArray tag update. --- external/versions.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/external/versions.cmake b/external/versions.cmake index 51fe8955f..2cbc5c121 100644 --- a/external/versions.cmake +++ b/external/versions.cmake @@ -6,8 +6,8 @@ set(SEQUANT_TRACKED_VGCMAKEKIT_TAG 1d1a13673c9acf6b5a58f19504dd1ad399a20f54) set(SEQUANT_TRACKED_RANGEV3_TAG 0.12.0) set(SEQUANT_TRACKED_RANGEV3_PREVIOUS_TAG d800a032132512a54c291ce55a2a43e0460591c7) -set(SEQUANT_TRACKED_TILEDARRAY_TAG 3f6629db047417e814b75ad5069b7f4ce26428e7) -set(SEQUANT_TRACKED_TILEDARRAY_PREVIOUS_TAG 954d861f553e938c3cfc4892fce9234bf4bf7193) +set(SEQUANT_TRACKED_TILEDARRAY_TAG 924c15fc57058b8d9a4dd4a41b5e1e8736c2e339) +set(SEQUANT_TRACKED_TILEDARRAY_PREVIOUS_TAG df0b808f46cc05bfc797e85b82f1397ac3824893) # oldest Boost we can tolerate ... with some compilers should be able to use an earlier version, but: # - Boost.ContainerHash <1.81 uses unary_function that has been deprecated in C++11 and removed in C++17: From 4d6c8986cf36c5e589bd91284a8c1bb9c56c2085 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Sun, 18 Feb 2024 10:56:48 -0500 Subject: [PATCH 13/40] [skip ci][unit test] `tensor_to_key` function updated to support `sequant::Tensor` with non-empty proto-indices. --- tests/unit/test_eval_ta.cpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_eval_ta.cpp b/tests/unit/test_eval_ta.cpp index 3520272e1..18f7bc90e 100644 --- a/tests/unit/test_eval_ta.cpp +++ b/tests/unit/test_eval_ta.cpp @@ -23,8 +23,30 @@ auto tensor_to_key(sequant::Tensor const& tnsr) { return (mo[1].str() == L"i" ? L"o" : L"v") + mo[2].str(); }; - auto const tnsr_deparsed = sequant::deparse_expr(tnsr.clone(), false); - return boost::regex_replace(tnsr_deparsed, idx_rgx, formatter); + sequant::NestedTensorIndices oixs{tnsr}; + if (oixs.inner.empty()) { + auto const tnsr_deparsed = sequant::deparse_expr(tnsr.clone(), false); + return boost::regex_replace(tnsr_deparsed, idx_rgx, formatter); + } else { + using ranges::views::intersperse; + using ranges::views::join; + using ranges::views::transform; + using namespace sequant; + + auto ix_lbl = [&formatter](Index const& ix) -> std::wstring { + std::wstring lbl(ix.label().data()); + return boost::regex_replace(lbl, idx_rgx, formatter); + }; + + auto ixs_lbl = [&ix_lbl](auto const& ixs) -> std::wstring { + return ixs | transform(ix_lbl) | intersperse(L",") | join | + ranges::to; + }; + + std::wstring result(tnsr.label()); + result += L"{" + ixs_lbl(oixs.outer) + L";" + ixs_lbl(oixs.inner) + L"}"; + return result; + } } auto tensor_to_key(std::wstring_view spec) { From 2999038fc623aed13036af199eeb6ed6e53f2713 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Thu, 22 Feb 2024 07:45:36 -0500 Subject: [PATCH 14/40] Call `TA::einsum` for product of regular tensors. --- SeQuant/domain/eval/eval_result.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SeQuant/domain/eval/eval_result.hpp b/SeQuant/domain/eval/eval_result.hpp index f799de23a..4ce097a11 100644 --- a/SeQuant/domain/eval/eval_result.hpp +++ b/SeQuant/domain/eval/eval_result.hpp @@ -787,8 +787,9 @@ class EvalTensorTA final : public EvalResult { log_ta(a.lannot, " * ", a.rannot, " = ", a.this_annot, "\n"); ArrayT result; - result(a.this_annot) = - get()(a.lannot) * other.get()(a.rannot); + + result = TA::einsum(get()(a.lannot), other.get()(a.rannot), + a.this_annot); decltype(result)::wait_for_lazy_cleanup(result.world()); return eval_result(std::move(result)); } From 93e2adc2d5247ddb6cc2d8a8765844edce2efb63 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Thu, 7 Mar 2024 10:18:03 -0500 Subject: [PATCH 15/40] gemm permutation optimization temporarily disabled in sequant TA eval expression tensor. --- SeQuant/domain/eval/eval.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/SeQuant/domain/eval/eval.cpp b/SeQuant/domain/eval/eval.cpp index 17615d28a..e9142e49c 100644 --- a/SeQuant/domain/eval/eval.cpp +++ b/SeQuant/domain/eval/eval.cpp @@ -24,18 +24,21 @@ EvalExprTA::EvalExprTA(const EvalExprTA& left, const EvalExprTA& right, if (result_type() == ResultType::Tensor) { annot_ = braket_annot(); - if (left.result_type() == right.result_type() && - op_type() == EvalOp::Prod && !tot()) { - // tensor x tensor confirmed - auto lh = hash::value(left); - auto rh = hash::value(right); - auto const& left_ = lh <= rh ? left : right; - auto const& right_ = lh <= rh ? right : left; - annot_ = GEMMPermutationOptimizer(Tidxs{left_.annot()}, // - Tidxs{right_.annot()}) - .target_result_indices() - .string(); - } + // clang-format off +// todo: fix the following so that it works for ToT x ToT -> T +// if (left.result_type() == right.result_type() && +// op_type() == EvalOp::Prod && !tot()) { +// // tensor x tensor confirmed +// auto lh = hash::value(left); +// auto rh = hash::value(right); +// auto const& left_ = lh <= rh ? left : right; +// auto const& right_ = lh <= rh ? right : left; +// annot_ = GEMMPermutationOptimizer(Tidxs{left_.annot()}, // +// Tidxs{right_.annot()}) +// .target_result_indices() +// .string(); +// } + // clang-format on } } From a926a4ee41bba3803f9083cbf6018abb14b93781 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Thu, 7 Mar 2024 10:18:45 -0500 Subject: [PATCH 16/40] typo --- SeQuant/core/eval_expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SeQuant/core/eval_expr.cpp b/SeQuant/core/eval_expr.cpp index 4bb3247eb..6eb548776 100644 --- a/SeQuant/core/eval_expr.cpp +++ b/SeQuant/core/eval_expr.cpp @@ -50,7 +50,7 @@ std::string EvalExpr::braket_annot() const noexcept { if (!is_tensor()) return {}; // given an iterable of sequant::Index objects, returns a string made - // of their full labels separted by comma + // of their full labels separated by comma // eg. (a_1^{i_1,i_2},a_2^{i_2,i_3}) -> "a_1i_1i_2,a_2i_2i_3" // eg. (i_1, i_2) -> "i_1,i_2" auto annot = [](auto&& ixs) -> std::string { From afef272c6c01d60ce34f34afb1e360774c86f55d Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Thu, 7 Mar 2024 13:08:23 -0500 Subject: [PATCH 17/40] Support ToT x ToT -> ToS. --- SeQuant/domain/eval/eval.hpp | 6 ++-- SeQuant/domain/eval/eval_result.hpp | 50 ++++++++++++++++------------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/SeQuant/domain/eval/eval.hpp b/SeQuant/domain/eval/eval.hpp index 9e5358b86..091bd1a22 100644 --- a/SeQuant/domain/eval/eval.hpp +++ b/SeQuant/domain/eval/eval.hpp @@ -245,8 +245,10 @@ ERPtr evaluate_core(NodeT const& node, Le const& le, Args&&... args) { log_eval("[PRODUCT] ", node.left()->label(), " * ", node.right()->label(), " = ", node->label(), "\n"); - - return left->prod(*right, ann); + auto const de_nest = + node.left()->tot() && node.right()->tot() && !node->tot(); + return left->prod(*right, ann, + de_nest ? TA::DeNest::True : TA::DeNest::False); } } } diff --git a/SeQuant/domain/eval/eval_result.hpp b/SeQuant/domain/eval/eval_result.hpp index 4ce097a11..60c71f9be 100644 --- a/SeQuant/domain/eval/eval_result.hpp +++ b/SeQuant/domain/eval/eval_result.hpp @@ -552,7 +552,8 @@ class EvalResult { /// respectively. /// [[nodiscard]] virtual ERPtr prod(EvalResult const&, - std::array const&) const = 0; + std::array const&, + TA::DeNest DeNestFlag) const = 0; /// /// \brief Permute this object according to the annotations in the argument. @@ -665,9 +666,9 @@ class EvalScalar final : public EvalResult { } } - [[nodiscard]] ERPtr prod( - EvalResult const& other, - std::array const& maybe_empty) const override { + [[nodiscard]] ERPtr prod(EvalResult const& other, + std::array const& maybe_empty, + TA::DeNest DeNestFlag) const override { if (other.is>()) { auto const& o = other.as>(); auto p = value() * o.value(); @@ -678,7 +679,7 @@ class EvalScalar final : public EvalResult { } else { auto maybe_empty_ = maybe_empty; std::swap(maybe_empty_[0], maybe_empty_[1]); - return other.prod(*this, maybe_empty_); + return other.prod(*this, maybe_empty_, DeNestFlag); } } @@ -745,9 +746,9 @@ class EvalTensorTA final : public EvalResult { return eval_result(std::move(result)); } - [[nodiscard]] ERPtr prod( - EvalResult const& other, - std::array const& annot) const override { + [[nodiscard]] ERPtr prod(EvalResult const& other, + std::array const& annot, + TA::DeNest DeNestFlag) const override { auto const a = annot_wrap{annot}; if (other.is>()) { @@ -779,7 +780,7 @@ class EvalTensorTA final : public EvalResult { // potential T * ToT auto annot_swap = annot; std::swap(annot_swap[0], annot_swap[1]); - return other.prod(*this, annot_swap); + return other.prod(*this, annot_swap, DeNestFlag); } // confirmed: other.is() is true @@ -873,9 +874,9 @@ class EvalTensorOfTensorTA final : public EvalResult { return eval_result(std::move(result)); } - [[nodiscard]] ERPtr prod( - EvalResult const& other, - std::array const& annot) const override { + [[nodiscard]] ERPtr prod(EvalResult const& other, + std::array const& annot, + TA::DeNest DeNestFlag) const override { auto const a = annot_wrap{annot}; if (other.is>()) { @@ -902,24 +903,29 @@ class EvalTensorOfTensorTA final : public EvalResult { } log_ta(a.lannot, " * ", a.rannot, " = ", a.this_annot, "\n"); - ArrayT result; if (other.is()) { // ToT * T -> ToT - result = + auto result = TA::einsum(get()(a.lannot), other.get()(a.rannot), a.this_annot); + return eval_result(std::move(result)); + + } else if (other.is() && DeNestFlag == TA::DeNest::True) { + // ToT * ToT -> T + auto result = TA::einsum( + get()(a.lannot), other.get()(a.rannot), a.this_annot); + return eval_result(std::move(result)); - } else if (other.is()) { + } else if (other.is() && DeNestFlag == TA::DeNest::False) { // ToT * ToT -> ToT - result = TA::einsum(get()(a.lannot), - other.get()(a.rannot), a.this_annot); + auto result = TA::einsum(get()(a.lannot), + other.get()(a.rannot), a.this_annot); + return eval_result(std::move(result)); } else { throw invalid_operand(); } - - return eval_result(std::move(result)); } [[nodiscard]] ERPtr permute( @@ -997,9 +1003,9 @@ class EvalTensorBTAS final : public EvalResult { return eval_result>(lres + rres); } - [[nodiscard]] ERPtr prod( - EvalResult const& other, - std::array const& annot) const override { + [[nodiscard]] ERPtr prod(EvalResult const& other, + std::array const& annot, + TA::DeNest DeNestFlag) const override { auto const a = annot_wrap{annot}; if (other.is>()) { From 6b8260e54b2763a3e6a1d6d3c66ef8ccf5057295 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Thu, 7 Mar 2024 13:10:27 -0500 Subject: [PATCH 18/40] Update sequant-tracked TiledArray tag. --- external/versions.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/external/versions.cmake b/external/versions.cmake index 2cbc5c121..fe7b6bc5e 100644 --- a/external/versions.cmake +++ b/external/versions.cmake @@ -6,8 +6,8 @@ set(SEQUANT_TRACKED_VGCMAKEKIT_TAG 1d1a13673c9acf6b5a58f19504dd1ad399a20f54) set(SEQUANT_TRACKED_RANGEV3_TAG 0.12.0) set(SEQUANT_TRACKED_RANGEV3_PREVIOUS_TAG d800a032132512a54c291ce55a2a43e0460591c7) -set(SEQUANT_TRACKED_TILEDARRAY_TAG 924c15fc57058b8d9a4dd4a41b5e1e8736c2e339) -set(SEQUANT_TRACKED_TILEDARRAY_PREVIOUS_TAG df0b808f46cc05bfc797e85b82f1397ac3824893) +set(SEQUANT_TRACKED_TILEDARRAY_TAG 6a134f31f38a1e643583d5c8f19ed85fb61b04ae) +set(SEQUANT_TRACKED_TILEDARRAY_PREVIOUS_TAG 924c15fc57058b8d9a4dd4a41b5e1e8736c2e339) # oldest Boost we can tolerate ... with some compilers should be able to use an earlier version, but: # - Boost.ContainerHash <1.81 uses unary_function that has been deprecated in C++11 and removed in C++17: From c1edcec360196a317805f438a419799a1e25d90b Mon Sep 17 00:00:00 2001 From: Bimal Gaudel Date: Tue, 2 Apr 2024 20:42:12 -0400 Subject: [PATCH 19/40] Amend merge. --- SeQuant/core/eval_expr.cpp | 86 ++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/SeQuant/core/eval_expr.cpp b/SeQuant/core/eval_expr.cpp index c10e113db..7d905429d 100644 --- a/SeQuant/core/eval_expr.cpp +++ b/SeQuant/core/eval_expr.cpp @@ -1,8 +1,8 @@ -#include #include #include #include #include +#include #include #include #include @@ -42,29 +42,53 @@ std::wstring_view const var_label = L"Z"; } // namespace -template < - typename Iterable, - std::enable_if_t>, - bool> = true> -std::string indices_to_annot(Iterable const& indices) noexcept { - using ranges::views::intersperse; - using ranges::views::join; - using ranges::views::transform; +NestedTensorIndices::NestedTensorIndices(const sequant::Tensor& tnsr) { + auto push_ix = [this](Index const& ix) { + if (ix.has_proto_indices()) + inner.push_back(ix); + else + outer.push_back(ix); + }; - auto idx_label = [](Index const& idx) { return to_string(idx.label()); }; + for (auto const& ix : tnsr.const_braket()) { + push_ix(ix); + for (auto const& ix_proto : ix.proto_indices()) push_ix(ix_proto); + } - return indices | transform(idx_label) | intersperse(",") | join | - ranges::to; + if (!inner.empty()) { + ranges::actions::stable_sort(outer, Index::LabelCompare{}); + ranges::actions::unique(outer, [](Index const& ix1, Index const& ix2) { + return ix1.label() == ix2.label(); + }); + } } -std::string indices_to_annot(InnerOuterIndices const& inout) noexcept { - auto const& in = inout.inner; - auto const& out = inout.outer; - if (out.empty()) { - return indices_to_annot(in); - } else { - return indices_to_annot(in) + ";" + indices_to_annot(out); - } +std::string EvalExpr::braket_annot() const noexcept { + if (!is_tensor()) return {}; + + // given an iterable of sequant::Index objects, returns a string made + // of their full labels separated by comma + // eg. (a_1^{i_1,i_2},a_2^{i_2,i_3}) -> "a_1i_1i_2,a_2i_2i_3" + // eg. (i_1, i_2) -> "i_1,i_2" + auto annot = [](auto&& ixs) -> std::string { + using namespace ranges::views; + + auto full_labels = ixs // + | transform(&Index::full_label) // + | transform([](auto&& fl) { // + return sequant::to_string(fl); + }); + return full_labels // + | intersperse(std::string{","}) // + | join // + | ranges::to; + }; + + auto nested = NestedTensorIndices{as_tensor()}; + + return nested.inner.empty() // + ? annot(nested.outer) + : annot(nested.outer) + ";" + annot(nested.inner); } size_t EvalExpr::global_id_{}; @@ -142,29 +166,9 @@ Variable const& EvalExpr::as_variable() const noexcept { return expr().as(); } -InnerOuterIndices EvalExpr::inner_outer_indices() const noexcept { - if (is_scalar()) return {}; - - assert(is_tensor()); - auto const& t = expr()->as(); - - container::svector inner; - container::svector outer; - for (auto const& idx : t.const_braket()) { - inner.emplace_back(idx); - for (auto const& pidx : idx.proto_indices()) outer.emplace_back(pidx); - } - ranges::stable_sort(outer, Index::LabelCompare{}); - ranges::actions::unique(outer); - ranges::actions::remove_if( - inner, [&outer](Index const& i) { return ranges::contains(outer, i); }); - return {std::move(inner), std::move(outer)}; -} - std::string EvalExpr::label() const noexcept { if (is_tensor()) - return to_string(as_tensor().label()) + "(" + - indices_to_annot(inner_outer_indices()) + ")"; + return to_string(as_tensor().label()) + "(" + braket_annot() + ")"; else if (is_constant()) { auto const& c = as_constant(); auto real = Constant{c.value().real()}.value(); From 4e7ec00556a9b5bee08618d4bbc562fafed708cc Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 11 Apr 2024 11:11:58 -0400 Subject: [PATCH 20/40] [mbpt] fixup mr::combine(qns, qns) --- SeQuant/domain/mbpt/mr.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/SeQuant/domain/mbpt/mr.cpp b/SeQuant/domain/mbpt/mr.cpp index a9e5fda89..1bd7d9f00 100644 --- a/SeQuant/domain/mbpt/mr.cpp +++ b/SeQuant/domain/mbpt/mr.cpp @@ -113,12 +113,15 @@ qninterval_t nann_uocc(qns_t qns) { qninterval_t nann(qns_t qns) { return qns[1] + qns[3] + qns[5]; } qns_t combine(qns_t a, qns_t b) { + // particle contractions (i.e. above Fermi level; N.B. active are above + // closed-shell Fermi level) const auto ncontr_uocc = qninterval_t{0, std::min(ncre(b, IndexSpace::active_unoccupied).upper(), nann(a, IndexSpace::active_unoccupied).upper())}; const auto ncontr_act = - qninterval_t{0, std::min(nann(b, IndexSpace::active).upper(), - ncre(a, IndexSpace::active).upper())}; + qninterval_t{0, std::min(ncre(b, IndexSpace::active).upper(), + nann(a, IndexSpace::active).upper())}; + // hole contractions (i.e. below Fermi level) const auto ncontr_occ = qninterval_t{0, std::min(nann(b, IndexSpace::active_occupied).upper(), ncre(a, IndexSpace::active_occupied).upper())}; From 911a240c6642a79e5701f2b816b7734d051b746f Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 11 Apr 2024 11:13:20 -0400 Subject: [PATCH 21/40] [mbpt] move {sr,mr}::can_change to public API --- SeQuant/domain/mbpt/mr.cpp | 2 +- SeQuant/domain/mbpt/mr.hpp | 6 ++++++ SeQuant/domain/mbpt/sr.cpp | 2 +- SeQuant/domain/mbpt/sr.hpp | 4 ++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/SeQuant/domain/mbpt/mr.cpp b/SeQuant/domain/mbpt/mr.cpp index 1bd7d9f00..796b762e7 100644 --- a/SeQuant/domain/mbpt/mr.cpp +++ b/SeQuant/domain/mbpt/mr.cpp @@ -620,7 +620,7 @@ ExprPtr A(std::int64_t K) { // } bool can_change_qns(const ExprPtr& op_or_op_product, const qns_t target_qns, - const qns_t source_qns = {}) { + const qns_t source_qns) { qns_t qns = source_qns; if (op_or_op_product.is()) { const auto& op_product = op_or_op_product.as(); diff --git a/SeQuant/domain/mbpt/mr.hpp b/SeQuant/domain/mbpt/mr.hpp index f4154de4f..9a027ef2f 100644 --- a/SeQuant/domain/mbpt/mr.hpp +++ b/SeQuant/domain/mbpt/mr.hpp @@ -220,6 +220,12 @@ ExprPtr Λ_(std::size_t K); /// \p K ExprPtr Λ(std::size_t K); +/// @} + +/// @return true if \p op_or_op_product can change quantum numbers from \p source_qns to \p target_qns +bool can_change_qns(const ExprPtr& op_or_op_product, const qns_t target_qns, + const qns_t source_qns = {}); + #include } // namespace op diff --git a/SeQuant/domain/mbpt/sr.cpp b/SeQuant/domain/mbpt/sr.cpp index d5ea582c6..1f2e99b0a 100644 --- a/SeQuant/domain/mbpt/sr.cpp +++ b/SeQuant/domain/mbpt/sr.cpp @@ -468,7 +468,7 @@ ExprPtr Λ_pt(std::size_t order, std::size_t K, bool skip1) { } bool can_change_qns(const ExprPtr& op_or_op_product, const qns_t target_qns, - const qns_t source_qns = {}) { + const qns_t source_qns) { qns_t qns = source_qns; if (op_or_op_product.is()) { const auto& op_product = op_or_op_product.as(); diff --git a/SeQuant/domain/mbpt/sr.hpp b/SeQuant/domain/mbpt/sr.hpp index d86d9a29d..176199ff7 100644 --- a/SeQuant/domain/mbpt/sr.hpp +++ b/SeQuant/domain/mbpt/sr.hpp @@ -274,6 +274,10 @@ ExprPtr Λ_pt(std::size_t order, std::size_t K, bool skip1 = false); /// @} +/// @return true if \p op_or_op_product can change quantum numbers from \p source_qns to \p target_qns +bool can_change_qns(const ExprPtr& op_or_op_product, const qns_t target_qns, + const qns_t source_qns = {}); + /// @return true if \p op_or_op_product can produce determinant of excitation /// rank \p k when applied to reference bool raises_vacuum_to_rank(const ExprPtr& op_or_op_product, From e903c3d719a3d171273ca32e88c84ed5501bf009 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 11 Apr 2024 11:15:13 -0400 Subject: [PATCH 22/40] [mbpt] introduced mr{::op::,::}T_act_ --- SeQuant/domain/mbpt/mr.cpp | 53 ++++++++++++++++++++++++++++++-------- SeQuant/domain/mbpt/mr.hpp | 20 +++++++++++++- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/SeQuant/domain/mbpt/mr.cpp b/SeQuant/domain/mbpt/mr.cpp index 796b762e7..c97772247 100644 --- a/SeQuant/domain/mbpt/mr.cpp +++ b/SeQuant/domain/mbpt/mr.cpp @@ -2,9 +2,10 @@ // Created by Eduard Valeyev on 2019-02-19. // -#include #include +#include + #include #include #include @@ -16,16 +17,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include #include #include @@ -37,6 +28,16 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + namespace sequant { namespace mbpt { namespace mr { @@ -182,8 +183,22 @@ OpMaker::OpMaker(OpType op, std::size_t nbra, std::size_t nket) } } +OpMaker::OpMaker(OpType op, + const container::svector& cre_spaces, + const container::svector& ann_spaces) + : base_type(op) { + bra_spaces_ = cre_spaces; + ket_spaces_ = ann_spaces; +} + #include +ExprPtr T_act_(std::size_t K) { + return OpMaker(OpType::t, + container::svector(K, IndexSpace::active), + container::svector(K, IndexSpace::active))(); +} + ExprPtr H_(std::size_t k) { assert(k > 0 && k <= 2); switch (k) { @@ -529,6 +544,22 @@ ExprPtr T_(std::size_t K) { }); } +ExprPtr T_act_(std::size_t K) { + assert(K > 0); + return ex( + []() -> std::wstring_view { return optype2label.at(OpType::t); }, + [=]() -> ExprPtr { + using namespace sequant::mbpt::sr; + return mr::T_act_(K); + }, + [=](qnc_t& qns) { + qns = combine( + qnc_t{ + {0ul, 0ul}, {0ul, 0ul}, {K, K}, {K, K}, {0ul, 0ul}, {0ul, 0ul}}, + qns); + }); +} + ExprPtr T(std::size_t K) { assert(K > 0); diff --git a/SeQuant/domain/mbpt/mr.hpp b/SeQuant/domain/mbpt/mr.hpp index 9a027ef2f..0e19bdd40 100644 --- a/SeQuant/domain/mbpt/mr.hpp +++ b/SeQuant/domain/mbpt/mr.hpp @@ -153,6 +153,14 @@ class OpMaker : public mbpt::OpMaker { OpMaker(OpType op, std::size_t nbra, std::size_t nket = std::numeric_limits::max()); + // clang-format off + /// Generic constructor for arbitrary cre/ann spaces + /// @param[in] op the operator type (is not considered for assigning the cre/ann spaces, but used to assign CSV index dependencies, if needed) + /// @param[in] cre_spaces spaces of creators + /// @param[in] ann_spaces spaces of annihilators + // clang-format off + OpMaker(OpType op, const container::svector& cre_spaces, const container::svector& ann_spaces); + using base_type::operator(); }; @@ -161,6 +169,8 @@ class OpMaker : public mbpt::OpMaker { /// @name tensor-level operators /// @{ +ExprPtr T_act_(std::size_t K); + // clang-format off /// @brief `k`-body contribution to the "generic" Hamiltonian (in normal order relative to the default vacuum) /// @param[in] k the rank of the particle interactions; only `k<=2` is @@ -194,6 +204,10 @@ ExprPtr vac_av(ExprPtr expr, // these produce operator-level expressions namespace op { +/// @name MR MBPT operators + +/// @{ + // clang-format off /// @brief `k`-body contribution to the "generic" Hamiltonian (in normal order relative to the default vacuum) /// @param[in] k the rank of the particle interactions; only `k<=2` is @@ -209,6 +223,9 @@ ExprPtr H(std::size_t k = 2); /// makes particle-conserving excitation operator of rank \p K ExprPtr T_(std::size_t K); +/// makes particle-conserving active replacement operator of rank \p K +ExprPtr T_act_(std::size_t K); + /// makes sum of particle-conserving excitation operators of all ranks up to \p /// K ExprPtr T(std::size_t K); @@ -222,7 +239,8 @@ ExprPtr Λ(std::size_t K); /// @} -/// @return true if \p op_or_op_product can change quantum numbers from \p source_qns to \p target_qns +/// @return true if \p op_or_op_product can change quantum numbers from \p +/// source_qns to \p target_qns bool can_change_qns(const ExprPtr& op_or_op_product, const qns_t target_qns, const qns_t source_qns = {}); From f31ad55831e2d0cb93a423188b0b595d06d0829a Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 11 Apr 2024 11:16:48 -0400 Subject: [PATCH 23/40] [unit] NBodyOp/screen: added MR screening tests + minor addition to SR screening test --- tests/unit/test_mbpt.cpp | 56 ++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/tests/unit/test_mbpt.cpp b/tests/unit/test_mbpt.cpp index fbbd1fe5c..47c25282e 100644 --- a/tests/unit/test_mbpt.cpp +++ b/tests/unit/test_mbpt.cpp @@ -2,6 +2,13 @@ // Created by Eduard Valeyev on 2019-02-19. // +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -10,26 +17,19 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include #include "catch.hpp" #include "test_config.hpp" -#include #include #include +#include #include #include #include #include #include -#include +#include #include @@ -387,17 +387,39 @@ TEST_CASE("NBodyOp", "[mbpt]") { } // SECTION("adjoint") SECTION("screen") { - using namespace sequant::mbpt::sr::op; + // SR + { + using namespace sequant::mbpt::sr::op; + using sequant::mbpt::sr::qns_t; + + auto g_t2_t2 = H_(2) * T_(2) * T_(2); + REQUIRE(!can_change_qns(g_t2_t2, qns_t{0, 0, 0, 0})); + REQUIRE(raises_vacuum_up_to_rank(g_t2_t2, 2)); - auto g_t2_t2 = H_(2) * T_(2) * T_(2); - REQUIRE(raises_vacuum_to_rank(g_t2_t2, 2)); - REQUIRE(raises_vacuum_up_to_rank(g_t2_t2, 2)); + auto g_t2 = H_(2) * T_(2); + REQUIRE(raises_vacuum_to_rank(g_t2, 3)); - auto g_t2 = H_(2) * T_(2); - REQUIRE(raises_vacuum_to_rank(g_t2, 3)); + auto lambda2_f = Λ_(2) * H_(1); + REQUIRE(lowers_rank_to_vacuum(lambda2_f, 2)); + } + + // MR + { + using namespace sequant::mbpt::mr::op; + using sequant::mbpt::mr::qns_t; - auto lambda2_f = Λ_(2) * H_(1); - REQUIRE(lowers_rank_to_vacuum(lambda2_f, 2)); + auto g_t2 = H_(2) * T_(2); + REQUIRE(can_change_qns(g_t2, qns_t{0, 0, 0, 0, 0, 0})); + REQUIRE(can_change_qns(g_t2, qns_t{0, 0, 4, 4, 0, 0})); + + auto g_t2_t2 = H_(2) * T_(2) * T_(2); + // unlike SR, this can produce vacuum since T2^2 can combine ij -> uv and + // uv -> ab to produce a double excitation + REQUIRE(can_change_qns(g_t2_t2, qns_t{0, 0, 0, 0, 0, 0})); + + auto g_t2a_t2a = H_(2) * T_act_(2) * T_act_(2); + REQUIRE(can_change_qns(g_t2a_t2a, qns_t{0, 0, 0, 0, 0, 0})); + } } // SECTION("screen") From b6298956a5b684b512e1cd99c026158d658ed3cc Mon Sep 17 00:00:00 2001 From: Ajay Date: Fri, 26 Apr 2024 11:22:28 -0400 Subject: [PATCH 24/40] [ci] Bump GCC version for macOS runners --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 2a1ee816f..4c9bf558a 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -46,7 +46,7 @@ jobs: - name: Install prerequisite MacOS packages if: ${{ matrix.os == 'macos-latest' }} - run: brew install ninja gcc@10 boost@1.76 eigen open-mpi ccache + run: brew install ninja gcc@11 boost@1.76 eigen open-mpi ccache - name: Install prerequisites Ubuntu packages if: ${{ matrix.os == 'ubuntu-22.04' }} From 946ff3457564fd805deeaa586c618e742ef9b68f Mon Sep 17 00:00:00 2001 From: Ajay Date: Fri, 26 Apr 2024 14:27:12 -0400 Subject: [PATCH 25/40] [ci] Drop hard-coded Boost version --- .github/workflows/cmake.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 4c9bf558a..5f9607ac8 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -31,7 +31,7 @@ jobs: -DBUILD_SHARED_LIBS=OFF -DCMAKE_UNITY_BUILD=${{ matrix.build_type == 'Debug' }} -DMPIEXEC_PREFLAGS='--bind-to;none;--allow-run-as-root' - -DCMAKE_PREFIX_PATH='/usr/local/opt/boost@1.76' + -DCMAKE_PREFIX_PATH='/usr/local/opt/boost' -DSEQUANT_EVAL_TESTS=ON -DSEQUANT_USE_SYSTEM_BOOST_HASH=OFF -DCMAKE_CXX_STANDARD=20 @@ -46,7 +46,7 @@ jobs: - name: Install prerequisite MacOS packages if: ${{ matrix.os == 'macos-latest' }} - run: brew install ninja gcc@11 boost@1.76 eigen open-mpi ccache + run: brew install ninja gcc@11 boost eigen open-mpi ccache - name: Install prerequisites Ubuntu packages if: ${{ matrix.os == 'ubuntu-22.04' }} From ca5d09a6e7cb84d0d662e37ce35ebc9247863d7f Mon Sep 17 00:00:00 2001 From: Ajay Date: Fri, 26 Apr 2024 14:38:18 -0400 Subject: [PATCH 26/40] [ci] macOS runner doesn't need GCC --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 5f9607ac8..22bcee39d 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -46,7 +46,7 @@ jobs: - name: Install prerequisite MacOS packages if: ${{ matrix.os == 'macos-latest' }} - run: brew install ninja gcc@11 boost eigen open-mpi ccache + run: brew install ninja boost eigen open-mpi ccache - name: Install prerequisites Ubuntu packages if: ${{ matrix.os == 'ubuntu-22.04' }} From 9bef80527f5d4152e5d5f46679ad613adf6f2256 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Thu, 18 Apr 2024 15:31:43 +0200 Subject: [PATCH 27/40] Add libPerm FetchContent --- CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d9cbb0d9..93a47f340 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,13 @@ FetchContent_Declare( BINARY_DIR ${${VG_CMAKE_KIT_PREFIX_DIR}}/cmake/vg-build SUBBUILD_DIR ${${VG_CMAKE_KIT_PREFIX_DIR}}/cmake/vg-subbuild ) -FetchContent_MakeAvailable(vg_cmake_kit) +FetchContent_Declare( + libperm + QUIET + GIT_REPOSITORY git@github.com:Krzmbrzl/libPerm.git + GIT_TAG develop +) +FetchContent_MakeAvailable(vg_cmake_kit libperm) list(APPEND CMAKE_MODULE_PATH "${vg_cmake_kit_SOURCE_DIR}/modules") # Set SeQuant version From e8ae485047a24ad9a60c9b59e58d7956edd2f356 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Thu, 18 Apr 2024 15:41:48 +0200 Subject: [PATCH 28/40] Switch to use https URL --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 93a47f340..e42ba5ce7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ FetchContent_Declare( FetchContent_Declare( libperm QUIET - GIT_REPOSITORY git@github.com:Krzmbrzl/libPerm.git + GIT_REPOSITORY https://github.com/Krzmbrzl/libPerm.git GIT_TAG develop ) FetchContent_MakeAvailable(vg_cmake_kit libperm) From 4e427f5e2f2ba8f4b906e867e28b8d495418d0e5 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 2 May 2024 07:47:26 -0400 Subject: [PATCH 29/40] bump VG CMake kit to pull in https://github.com/ValeevGroup/kit-cmake/pull/7 --- external/versions.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/versions.cmake b/external/versions.cmake index fe7b6bc5e..176a7d670 100644 --- a/external/versions.cmake +++ b/external/versions.cmake @@ -1,7 +1,7 @@ # for each dependency track both current and previous id (the variable for the latter must contain PREVIOUS) # to be able to auto-update them -set(SEQUANT_TRACKED_VGCMAKEKIT_TAG 1d1a13673c9acf6b5a58f19504dd1ad399a20f54) +set(SEQUANT_TRACKED_VGCMAKEKIT_TAG cd11b3c86dfb95441646d34bfeaa243328ef0c74) set(SEQUANT_TRACKED_RANGEV3_TAG 0.12.0) set(SEQUANT_TRACKED_RANGEV3_PREVIOUS_TAG d800a032132512a54c291ce55a2a43e0460591c7) From 30b595a97e6c24f464c8a3320355e150929f934d Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 2 May 2024 07:54:42 -0400 Subject: [PATCH 30/40] introduced FindOrFetchLibPerm --- CMakeLists.txt | 11 ++++------- cmake/modules/FindOrFetchLibPerm.cmake | 13 +++++++++++++ 2 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 cmake/modules/FindOrFetchLibPerm.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index e42ba5ce7..20c34d84f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,13 +19,7 @@ FetchContent_Declare( BINARY_DIR ${${VG_CMAKE_KIT_PREFIX_DIR}}/cmake/vg-build SUBBUILD_DIR ${${VG_CMAKE_KIT_PREFIX_DIR}}/cmake/vg-subbuild ) -FetchContent_Declare( - libperm - QUIET - GIT_REPOSITORY https://github.com/Krzmbrzl/libPerm.git - GIT_TAG develop -) -FetchContent_MakeAvailable(vg_cmake_kit libperm) +FetchContent_MakeAvailable(vg_cmake_kit) list(APPEND CMAKE_MODULE_PATH "${vg_cmake_kit_SOURCE_DIR}/modules") # Set SeQuant version @@ -152,6 +146,9 @@ include(FindOrFetchRangeV3) # Boost will be added after defining SeQuant include(external/boost.cmake) +# LibPerm +include(FindOrFetchLibPerm) + # embedded bliss-0.73 add_library(SeQuant-bliss SeQuant/external/bliss/defs.cc diff --git a/cmake/modules/FindOrFetchLibPerm.cmake b/cmake/modules/FindOrFetchLibPerm.cmake new file mode 100644 index 000000000..d2f369fc5 --- /dev/null +++ b/cmake/modules/FindOrFetchLibPerm.cmake @@ -0,0 +1,13 @@ +if (NOT TARGET libperm) + + include(${vg_cmake_kit_SOURCE_DIR}/modules/VRGFindOrFetchPackage.cmake) + VRGFindOrFetchPackage(libperm "https://github.com/Krzmbrzl/libPerm.git" "develop" + ADD_SUBDIR + CONFIG_SUBDIR + ) +endif() + +# postcond check +if (NOT TARGET libperm) + message(FATAL_ERROR "FindOrFetchLibPerm could not make TARGET libperm available") +endif(NOT TARGET libperm) From ab98646e47bbfa0db206e06e6afa0edf7f5fdc78 Mon Sep 17 00:00:00 2001 From: Bimal Gaudel <44385776+bimalgaudel@users.noreply.github.com> Date: Fri, 3 May 2024 08:30:24 -0400 Subject: [PATCH 31/40] inlclude boost numeric cast header. Required since Boost 1.85 --- SeQuant/core/rational.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/SeQuant/core/rational.hpp b/SeQuant/core/rational.hpp index d19c54bda..52c1af712 100644 --- a/SeQuant/core/rational.hpp +++ b/SeQuant/core/rational.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include From 78a43b8da92c9ae41860cf49ce56ae1fc61dc8a1 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Thu, 2 May 2024 15:06:38 +0200 Subject: [PATCH 32/40] CI: Add formatting check --- .github/workflows/formatting_check.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/workflows/formatting_check.yml diff --git a/.github/workflows/formatting_check.yml b/.github/workflows/formatting_check.yml new file mode 100644 index 000000000..436c82a77 --- /dev/null +++ b/.github/workflows/formatting_check.yml @@ -0,0 +1,15 @@ +name: Formatting check + +on: [push, pull_request] + +jobs: + check: + name: "Check formatting" + runs-on: "ubuntu-latest" + steps: + - uses: actions/checkout@v4 + - uses: jidicula/clang-format-action@v4.11.0 + with: + clang-format-version: "17" + + From ad98a0e0a409f030223216b24ad85ca784b73842 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Thu, 2 May 2024 15:33:50 +0200 Subject: [PATCH 33/40] Pin clang-format version to v17 --- bin/admin/clang-format.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/admin/clang-format.sh b/bin/admin/clang-format.sh index 3531dcc1b..d3a7d6219 100755 --- a/bin/admin/clang-format.sh +++ b/bin/admin/clang-format.sh @@ -2,7 +2,7 @@ # these are the versions of clang-format that are supported required # should be ordered from oldest to newest to make sure the newest is picked -supported_clang_format_versions="16 17" +supported_clang_format_versions="17" preferred_clang_format_version="" # prefer most recent supported clang-format version for v in $supported_clang_format_versions; do preferred_clang_format_version=$v From d2bd283ef4755c0e0eec735cb068ab45f065744c Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Thu, 2 May 2024 15:34:10 +0200 Subject: [PATCH 34/40] Format all source files with clang-format 17 --- SeQuant/core/abstract_tensor.cpp | 4 +- SeQuant/core/abstract_tensor.hpp | 1 - SeQuant/core/any.hpp | 4 +- SeQuant/core/asy_cost.cpp | 8 +- SeQuant/core/complex.hpp | 6 +- SeQuant/core/context.cpp | 2 +- SeQuant/core/eval_node.hpp | 2 +- SeQuant/core/expr.cpp | 2 +- SeQuant/core/expr.hpp | 2 - SeQuant/core/index.cpp | 2 +- SeQuant/core/latex.ipp | 18 ++- SeQuant/core/meta.hpp | 1 - SeQuant/core/op.cpp | 2 +- SeQuant/core/optimize/optimize.cpp | 14 +- SeQuant/core/parse/ast_conversions.hpp | 2 +- SeQuant/core/parse/deparse.cpp | 6 +- SeQuant/core/parse/parse.cpp | 10 +- SeQuant/core/parse_expr.hpp | 9 +- SeQuant/core/ranges.hpp | 74 +++++----- SeQuant/core/space.cpp | 2 +- SeQuant/core/tag.hpp | 2 +- SeQuant/core/tensor.cpp | 2 +- SeQuant/core/tensor_network.cpp | 2 +- SeQuant/core/utility/string.cpp | 2 +- SeQuant/domain/mbpt/models/cc.cpp | 8 +- SeQuant/domain/mbpt/op.cpp | 9 +- SeQuant/domain/mbpt/op.hpp | 2 +- SeQuant/domain/mbpt/rdm.hpp | 178 +++++++++++++------------ SeQuant/domain/mbpt/sr.cpp | 4 +- SeQuant/domain/mbpt/sr.hpp | 3 +- examples/eval/eval_utils.hpp | 10 +- examples/eval/options.hpp | 2 +- examples/eval/scf.cpp | 2 +- python/src/sequant/mbpt.h | 7 +- tests/unit/test_asy_cost.cpp | 2 +- tests/unit/test_binary_node.cpp | 2 +- tests/unit/test_bliss.cpp | 4 +- tests/unit/test_canonicalize.cpp | 4 +- tests/unit/test_eval_expr.cpp | 10 +- tests/unit/test_eval_node.cpp | 4 +- tests/unit/test_expr.cpp | 4 +- tests/unit/test_fusion.cpp | 4 +- tests/unit/test_iterator.cpp | 21 ++- tests/unit/test_main.cpp | 2 +- tests/unit/test_math.cpp | 4 +- tests/unit/test_optimize.cpp | 4 +- tests/unit/test_parse_expr.cpp | 8 +- tests/unit/test_runtime.cpp | 2 +- tests/unit/test_spin.cpp | 4 +- tests/unit/test_tensor_network.cpp | 16 +-- tests/unit/test_wick.cpp | 4 +- 51 files changed, 255 insertions(+), 248 deletions(-) diff --git a/SeQuant/core/abstract_tensor.cpp b/SeQuant/core/abstract_tensor.cpp index 0fa484f85..75c6b0ad2 100644 --- a/SeQuant/core/abstract_tensor.cpp +++ b/SeQuant/core/abstract_tensor.cpp @@ -2,10 +2,10 @@ // Created by Eduard Valeyev on 2019-03-24. // -#include -#include #include #include +#include +#include #include diff --git a/SeQuant/core/abstract_tensor.hpp b/SeQuant/core/abstract_tensor.hpp index b0f0cfea6..6268767e0 100644 --- a/SeQuant/core/abstract_tensor.hpp +++ b/SeQuant/core/abstract_tensor.hpp @@ -27,7 +27,6 @@ #include - namespace sequant { /// This interface class defines a Tensor concept. Object @c t of a type that diff --git a/SeQuant/core/any.hpp b/SeQuant/core/any.hpp index c9667bbb7..51e9d3cb1 100644 --- a/SeQuant/core/any.hpp +++ b/SeQuant/core/any.hpp @@ -17,8 +17,8 @@ #define SEQUANT_HAS_CXX17_ANY #endif // 10.14 or later #endif // have macos version -//#else // libc++ on macos -//#define SEQUANT_HAS_CXX17_ANY +// #else // libc++ on macos +// #define SEQUANT_HAS_CXX17_ANY #endif // libc++ on macos #endif // c++17 diff --git a/SeQuant/core/asy_cost.cpp b/SeQuant/core/asy_cost.cpp index e7a22a561..bfd6faa99 100644 --- a/SeQuant/core/asy_cost.cpp +++ b/SeQuant/core/asy_cost.cpp @@ -155,12 +155,12 @@ AsyCost const &AsyCost::zero() { return zero; } -AsyCost& AsyCost::operator+=(AsyCost const& other) { +AsyCost &AsyCost::operator+=(AsyCost const &other) { *this = *this + other; return *this; } -AsyCost& AsyCost::operator-=(AsyCost const& other) { +AsyCost &AsyCost::operator-=(AsyCost const &other) { *this = *this - other; return *this; } @@ -226,11 +226,11 @@ bool operator>(AsyCost const &lhs, AsyCost const &rhs) { return !(lhs < rhs || lhs == rhs); } -bool operator<=(AsyCost const& lhs, AsyCost const& rhs) { +bool operator<=(AsyCost const &lhs, AsyCost const &rhs) { return lhs < rhs || lhs == rhs; } -bool operator>=(AsyCost const& lhs, AsyCost const& rhs) { +bool operator>=(AsyCost const &lhs, AsyCost const &rhs) { return lhs > rhs || lhs == rhs; } diff --git a/SeQuant/core/complex.hpp b/SeQuant/core/complex.hpp index 894082d7c..1e65299f1 100644 --- a/SeQuant/core/complex.hpp +++ b/SeQuant/core/complex.hpp @@ -44,9 +44,11 @@ struct Complex { std::wstring result = L"{"; result += to_latex(this->real()); if (this->imag() > 0) { - result = L"\\bigl(" + result + L" + i " + to_latex(this->imag()) + L"\\bigr)"; + result = + L"\\bigl(" + result + L" + i " + to_latex(this->imag()) + L"\\bigr)"; } else if (this->imag() < 0) - result = L"\\bigl(" + result + L" - i " + to_latex(-this->imag()) + L"\\bigr)"; + result = + L"\\bigl(" + result + L" - i " + to_latex(-this->imag()) + L"\\bigr)"; result += L"}"; return result; } diff --git a/SeQuant/core/context.cpp b/SeQuant/core/context.cpp index 88b22b940..072ba93f6 100644 --- a/SeQuant/core/context.cpp +++ b/SeQuant/core/context.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include namespace sequant { diff --git a/SeQuant/core/eval_node.hpp b/SeQuant/core/eval_node.hpp index 0fb2977e1..0ae623fa4 100644 --- a/SeQuant/core/eval_node.hpp +++ b/SeQuant/core/eval_node.hpp @@ -8,8 +8,8 @@ #include #include #include -#include #include +#include namespace sequant { diff --git a/SeQuant/core/expr.cpp b/SeQuant/core/expr.cpp index 835478f5e..980ac8e61 100644 --- a/SeQuant/core/expr.cpp +++ b/SeQuant/core/expr.cpp @@ -2,9 +2,9 @@ // Created by Eduard Valeyev on 2019-02-06. // -#include #include #include +#include #include #include #include diff --git a/SeQuant/core/expr.hpp b/SeQuant/core/expr.hpp index 7ea560c60..09e117b3b 100644 --- a/SeQuant/core/expr.hpp +++ b/SeQuant/core/expr.hpp @@ -40,7 +40,6 @@ namespace sequant { namespace { - template constexpr bool is_an_expr_v = meta::is_base_of_v; template @@ -1684,7 +1683,6 @@ T &ExprPtr::as() { } // namespace sequant - #endif // SEQUANT_EXPR_HPP #include "expr_operator.hpp" diff --git a/SeQuant/core/index.cpp b/SeQuant/core/index.cpp index f5a8e86e0..e3a1bac28 100644 --- a/SeQuant/core/index.cpp +++ b/SeQuant/core/index.cpp @@ -2,8 +2,8 @@ // Created by Eduard Valeyev on 4/30/20. // -#include #include +#include #include #include diff --git a/SeQuant/core/latex.ipp b/SeQuant/core/latex.ipp index f7c7d49c5..53ba3e395 100644 --- a/SeQuant/core/latex.ipp +++ b/SeQuant/core/latex.ipp @@ -65,13 +65,11 @@ std::basic_string greek_characters_to_latex_impl( const auto end = cend(str); /// TODO iterate over characters (graphemes) for (auto it = begin; it != end; ++it) { - auto append = [&result,&str,&it,&begin](const auto& s) { + auto append = [&result, &str, &it, &begin](const auto& s) { if (result.empty()) result = str.substr(0, it - begin); result += s; }; - auto is_ascii = [](Char c) { - return static_cast(c) <= 0x7F; - }; + auto is_ascii = [](Char c) { return static_cast(c) <= 0x7F; }; const Char ch = *it; if (sizeof(Char) == 1 && !is_ascii(ch)) @@ -94,8 +92,7 @@ std::basic_string greek_characters_to_latex_impl( const auto& uc_str = uc[static_cast(ch_addr)]; assert(uc_str.size() > 0); append(uc_str); - } - else { // pass through unknown non-ASCII characters + } else { // pass through unknown non-ASCII characters if (!result.empty()) result.push_back(ch); } } else { // ASCII character @@ -135,7 +132,8 @@ std::basic_string diactrics_to_latex_impl( "non-ASCII characters in str if Char is a wide character (wchar_t, " "char16_t, or char32_t)"); } - // Combining diacritics: https://www.ncbi.nlm.nih.gov/staff/beck/charents/accents.html + // Combining diacritics: + // https://www.ncbi.nlm.nih.gov/staff/beck/charents/accents.html if (next_ch && !is_ascii(*next_ch)) { auto append_latex = [&](auto prefix) { append(prefix); @@ -167,9 +165,9 @@ std::basic_string diactrics_to_latex_impl( } } - if (!is_ascii(ch)) { // check for combined characters - { // tilde - // lower-case characters with tilde + if (!is_ascii(ch)) { // check for combined characters + { // tilde + // lower-case characters with tilde const std::map lc = { {SQ_STRLIT(Char, "ã"), SQ_STRLIT(Char, "\\tilde{a}")}, {SQ_STRLIT(Char, "ẽ"), SQ_STRLIT(Char, "\\tilde{e}")}, diff --git a/SeQuant/core/meta.hpp b/SeQuant/core/meta.hpp index b9e89726f..697673b86 100644 --- a/SeQuant/core/meta.hpp +++ b/SeQuant/core/meta.hpp @@ -226,7 +226,6 @@ static constexpr bool is_range_v = (is_detected_v && is_detected_v); - /// is_same /// Checks whether \c T is a \c Base (is either the same class or a sub-class /// ignoring CV and reference qualifiers diff --git a/SeQuant/core/op.cpp b/SeQuant/core/op.cpp index 68815221f..044f922b9 100644 --- a/SeQuant/core/op.cpp +++ b/SeQuant/core/op.cpp @@ -2,10 +2,10 @@ // Created by Eduard Valeyev on 2019-02-18. // -#include #include #include #include +#include #include diff --git a/SeQuant/core/optimize/optimize.cpp b/SeQuant/core/optimize/optimize.cpp index cc7aea5c1..1cb5708b9 100644 --- a/SeQuant/core/optimize/optimize.cpp +++ b/SeQuant/core/optimize/optimize.cpp @@ -1,11 +1,11 @@ +#include +#include +#include #include #include #include -#include #include -#include -#include -#include +#include #include #include @@ -13,11 +13,11 @@ #include #include -#include -#include +#include #include #include -#include +#include +#include #include #include diff --git a/SeQuant/core/parse/ast_conversions.hpp b/SeQuant/core/parse/ast_conversions.hpp index 2e37f75b2..47e735b49 100644 --- a/SeQuant/core/parse/ast_conversions.hpp +++ b/SeQuant/core/parse/ast_conversions.hpp @@ -5,10 +5,10 @@ #ifndef SEQUANT_CORE_PARSE_AST_CONVERSIONS_HPP #define SEQUANT_CORE_PARSE_AST_CONVERSIONS_HPP -#include #include #include #include +#include #include #include #include diff --git a/SeQuant/core/parse/deparse.cpp b/SeQuant/core/parse/deparse.cpp index ba6173a5c..e64b3dd09 100644 --- a/SeQuant/core/parse/deparse.cpp +++ b/SeQuant/core/parse/deparse.cpp @@ -1,20 +1,20 @@ #include #include +#include #include #include #include -#include #include #include #include -#include -#include #include +#include #include #include +#include #include #include diff --git a/SeQuant/core/parse/parse.cpp b/SeQuant/core/parse/parse.cpp index 28d9fc845..04638ba3d 100644 --- a/SeQuant/core/parse/parse.cpp +++ b/SeQuant/core/parse/parse.cpp @@ -2,12 +2,12 @@ // Created by Robert Adam on 2023-09-20 // -#include +#include +#include #include #include #include -#include -#include +#include #include #define BOOST_SPIRIT_X3_UNICODE @@ -17,14 +17,14 @@ #include #include +#include +#include #include #include #include #include #include #include -#include -#include namespace sequant { diff --git a/SeQuant/core/parse_expr.hpp b/SeQuant/core/parse_expr.hpp index af5f7e005..7def28485 100644 --- a/SeQuant/core/parse_expr.hpp +++ b/SeQuant/core/parse_expr.hpp @@ -4,10 +4,9 @@ #include #include -#include -#include #include #include +#include /// /// Create SeQuant expression from string input. @@ -19,10 +18,10 @@ namespace sequant { struct ParseError : std::runtime_error { - std::size_t offset; - std::size_t length; + std::size_t offset; + std::size_t length; - ParseError(std::size_t offset, std::size_t length, std::string message); + ParseError(std::size_t offset, std::size_t length, std::string message); }; // clang-format off diff --git a/SeQuant/core/ranges.hpp b/SeQuant/core/ranges.hpp index 97e2dfa2c..bfae89641 100644 --- a/SeQuant/core/ranges.hpp +++ b/SeQuant/core/ranges.hpp @@ -10,25 +10,28 @@ namespace sequant { /// @brief a flattened view over a nest of ranges -/// @note this is just like view::join, but its iterator provides not only elements but also their indices as well as the host ranges. -/// this is needed to be able to iterate over pairs of elements while skipping pairs of elements from the same subrange -/// @tparam RangeNest the type of a nest of ranges; use flattened_rangenest for RangeNest if you want recursive flattening. +/// @note this is just like view::join, but its iterator provides not only +/// elements but also their indices as well as the host ranges. +/// this is needed to be able to iterate over pairs of elements while +/// skipping pairs of elements from the same subrange +/// @tparam RangeNest the type of a nest of ranges; use flattened_rangenest for +/// RangeNest if you want recursive flattening. template class flattened_rangenest : public ranges::view_facade> { -public: + public: using base_type = ranges::view_facade>; flattened_rangenest() = default; explicit flattened_rangenest(RangeNest *r) : range_(r) {} - flattened_rangenest(const flattened_rangenest&) = default; - flattened_rangenest(flattened_rangenest&&) = default; - flattened_rangenest& operator=(const flattened_rangenest&) = default; - flattened_rangenest& operator=(flattened_rangenest&&) = default; + flattened_rangenest(const flattened_rangenest &) = default; + flattened_rangenest(flattened_rangenest &&) = default; + flattened_rangenest &operator=(const flattened_rangenest &) = default; + flattened_rangenest &operator=(flattened_rangenest &&) = default; - RangeNest* range() const{ return range_; } + RangeNest *range() const { return range_; } using value_type = typename RangeNest::value_type::value_type; @@ -41,20 +44,21 @@ class flattened_rangenest /// the cursor type struct cursor { - private: + private: RangeNest *range_; - std::conditional_t, typename RangeNest::const_iterator, typename RangeNest::iterator> - range_iter_; // sequence iterator pointing to the current element's - // range in the sequence - std::conditional_t, typename Range::const_iterator, typename Range::iterator> - elem_iter_; // iterator pointing to the current element + std::conditional_t, + typename RangeNest::const_iterator, + typename RangeNest::iterator> + range_iter_; // sequence iterator pointing to the current element's + // range in the sequence + std::conditional_t, typename Range::const_iterator, + typename Range::iterator> + elem_iter_; // iterator pointing to the current element mutable int64_t ordinal_ = - -1; // index of the current element within the sequence + -1; // index of the current element within the sequence // *range_iter_ produces a const lvalue ref, this return nonconst lvalue ref - Range& current_range() const { - return const_cast(*range_iter_); - } + Range ¤t_range() const { return const_cast(*range_iter_); } void compute_ordinal() const { // accumulate all elements before this range_iter_ @@ -66,20 +70,20 @@ class flattened_rangenest ordinal_ += elem_iter_ - this->_begin(current_range()); } - static auto _begin(Range& rng) { + static auto _begin(Range &rng) { using std::begin; return begin(rng); } - static auto _end(Range& rng) { + static auto _end(Range &rng) { using std::end; return end(rng); } - static auto _begin(RangeNest& rng) { + static auto _begin(RangeNest &rng) { using std::begin; return begin(rng); } - static auto _end(RangeNest& rng) { + static auto _end(RangeNest &rng) { using std::end; return end(rng); } @@ -90,8 +94,15 @@ class flattened_rangenest /// constructs a cursor pointing to the begin, if range is not empty /// @note has O(1) complexity cursor(RangeNest *range) - : range_(range), range_iter_(std::find_if(this->_begin(*range), this->_end(*range), [](const auto& e) { using std::empty; return !empty(e); } )), - elem_iter_(range_iter_ != this->_end(*range) ? this->_begin(current_range()) : decltype(elem_iter_){}), + : range_(range), + range_iter_(std::find_if(this->_begin(*range), this->_end(*range), + [](const auto &e) { + using std::empty; + return !empty(e); + })), + elem_iter_(range_iter_ != this->_end(*range) + ? this->_begin(current_range()) + : decltype(elem_iter_){}), ordinal_{range_iter_ != this->_end(*range) ? 0 : -1} {} /// constructs a cursor pointing to the end /// @note has O(1) complexity @@ -118,8 +129,7 @@ class flattened_rangenest return false; else return elem_iter_ == that.elem_iter_; - } - else // this points to a different range from that + } else // this points to a different range from that return false; } void next() { @@ -142,10 +152,10 @@ class flattened_rangenest const auto range_ordinal() const { return range_iter_ - _begin(*range_); } /// @return the iterator pointing to the element at which this is located const auto elem_iter() const { return elem_iter_; } - /// @return ordinal index of the element at which this is located (i.e. distance to the first element of the first range) + /// @return ordinal index of the element at which this is located (i.e. + /// distance to the first element of the first range) const auto ordinal() const { - if (ordinal_ < 0) - compute_ordinal(); + if (ordinal_ < 0) compute_ordinal(); return ordinal_; } @@ -179,6 +189,6 @@ class flattened_rangenest using const_iterator = ranges::basic_iterator; }; -} // namespace sequant +} // namespace sequant -#endif // SEQUANT_RANGES_HPP +#endif // SEQUANT_RANGES_HPP diff --git a/SeQuant/core/space.cpp b/SeQuant/core/space.cpp index 32ebd1c48..f9c788782 100644 --- a/SeQuant/core/space.cpp +++ b/SeQuant/core/space.cpp @@ -2,8 +2,8 @@ // Created by Eduard Valeyev on 3/27/18. // -#include #include +#include #include diff --git a/SeQuant/core/tag.hpp b/SeQuant/core/tag.hpp index 25fa8e5b8..1b92a8371 100644 --- a/SeQuant/core/tag.hpp +++ b/SeQuant/core/tag.hpp @@ -5,8 +5,8 @@ #ifndef SEQUANT_TAG_HPP #define SEQUANT_TAG_HPP -#include #include +#include namespace sequant { diff --git a/SeQuant/core/tensor.cpp b/SeQuant/core/tensor.cpp index 45c710c0e..9e80be70f 100644 --- a/SeQuant/core/tensor.cpp +++ b/SeQuant/core/tensor.cpp @@ -2,10 +2,10 @@ // Created by Eduard Valeyev on 2019-01-30. // -#include #include #include #include +#include namespace sequant { diff --git a/SeQuant/core/tensor_network.cpp b/SeQuant/core/tensor_network.cpp index 7e4d634b1..767fdb397 100644 --- a/SeQuant/core/tensor_network.cpp +++ b/SeQuant/core/tensor_network.cpp @@ -2,7 +2,6 @@ // Created by Eduard Valeyev on 2019-02-26. // -#include #include #include #include @@ -15,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/SeQuant/core/utility/string.cpp b/SeQuant/core/utility/string.cpp index 9d9fae936..0f558589f 100644 --- a/SeQuant/core/utility/string.cpp +++ b/SeQuant/core/utility/string.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include #include diff --git a/SeQuant/domain/mbpt/models/cc.cpp b/SeQuant/domain/mbpt/models/cc.cpp index 0e09f2fae..8776a6940 100644 --- a/SeQuant/domain/mbpt/models/cc.cpp +++ b/SeQuant/domain/mbpt/models/cc.cpp @@ -1,15 +1,15 @@ -#include -#include +#include #include #include -#include +#include +#include #include #include #include -#include #include #include +#include namespace sequant::mbpt::sr { diff --git a/SeQuant/domain/mbpt/op.cpp b/SeQuant/domain/mbpt/op.cpp index e0584ebf3..35f9263cc 100644 --- a/SeQuant/domain/mbpt/op.cpp +++ b/SeQuant/domain/mbpt/op.cpp @@ -1,16 +1,15 @@ -#include #include +#include -#include -#include -#include -#include #include #include +#include #include +#include #include #include #include +#include #include diff --git a/SeQuant/domain/mbpt/op.hpp b/SeQuant/domain/mbpt/op.hpp index 5257a6aae..5e170519f 100644 --- a/SeQuant/domain/mbpt/op.hpp +++ b/SeQuant/domain/mbpt/op.hpp @@ -23,12 +23,12 @@ #include #include -#include #include #include #include #include #include +#include #include #include #include diff --git a/SeQuant/domain/mbpt/rdm.hpp b/SeQuant/domain/mbpt/rdm.hpp index 3e7743534..e9c2ed344 100644 --- a/SeQuant/domain/mbpt/rdm.hpp +++ b/SeQuant/domain/mbpt/rdm.hpp @@ -286,92 +286,96 @@ three_body_decomposition(ExprPtr ex_, int rank, bool fast = false) { } simplify(ex_); + } else if (rank == 2) { + if (fast) { + assert(ex_->is()); + // FNOp does not store a list of indices so I have to do this + auto down_0 = ex_->as().annihilators()[0].index(); + auto down_1 = ex_->as().annihilators()[1].index(); + auto down_2 = ex_->as().annihilators()[2].index(); + + std::vector initial_lower{down_0, down_1, down_2}; + + auto up_0 = ex_->as().creators()[0].index(); + auto up_1 = ex_->as().creators()[1].index(); + auto up_2 = ex_->as().creators()[2].index(); + + std::vector initial_upper{up_0, up_1, up_2}; + initial_pairing.first = initial_lower; + initial_pairing.second = initial_upper; + // make tensors which can be decomposed into the constituent pieces later + // in the procedure. + auto DE2 = ex( + L"DE2", std::initializer_list{down_0, down_1, down_2}, + std::initializer_list{up_0, up_1, up_2}); + auto DDE = ex( + L"DDE", std::initializer_list{down_0, down_1, down_2}, + std::initializer_list{up_0, up_1, up_2}); + auto D2E = ex( + L"D2E", std::initializer_list{down_0, down_1, down_2}, + std::initializer_list{up_0, up_1, up_2}); + auto result = DE2 + D2E - ex(2) * DDE; + return {result, initial_pairing}; } - else if (rank == 2) { - if (fast) { - assert(ex_->is()); - //FNOp does not store a list of indices so I have to do this - auto down_0 = ex_->as().annihilators()[0].index(); - auto down_1 = ex_->as().annihilators()[1].index(); - auto down_2 = ex_->as().annihilators()[2].index(); - - std::vector initial_lower{down_0, down_1, down_2}; - - auto up_0 = ex_->as().creators()[0].index(); - auto up_1 = ex_->as().creators()[1].index(); - auto up_2 = ex_->as().creators()[2].index(); - - std::vector initial_upper{up_0, up_1, up_2}; - initial_pairing.first = initial_lower; initial_pairing.second = initial_upper; - // make tensors which can be decomposed into the constituent pieces later in the procedure. - auto DE2 = ex(L"DE2",std::initializer_list{down_0,down_1,down_2},std::initializer_list{up_0,up_1,up_2}); - auto DDE = ex(L"DDE",std::initializer_list{down_0,down_1,down_2},std::initializer_list{up_0,up_1,up_2}); - auto D2E = ex(L"D2E",std::initializer_list{down_0,down_1,down_2},std::initializer_list{up_0,up_1,up_2}); - auto result = DE2 + D2E - ex(2) * DDE; - return {result,initial_pairing}; - } - auto ex_pair = three_body_decomp(ex_, true); - ex_ = ex_pair.first; - initial_pairing = ex_pair.second; - simplify(ex_); - for (auto&& product : ex_->as().summands()) { - if (product->is()) { - for (auto&& factor : product->as().factors()) { - if (factor->is()) { - if (factor->as().label() == - optype2label.at(OpType::RDMCumulant) && - factor->as().rank() > 2) { - factor = ex(0); - } else if (factor->as().label() == - optype2label.at(OpType::RDMCumulant) && - factor->as().rank() == 2) { - factor = cumu2_to_density(factor); - } else if (factor->as().label() == - optype2label.at(OpType::RDMCumulant)) { - factor = cumu_to_density(factor); - } else { - assert(factor->as().label() != - optype2label.at(OpType::RDMCumulant)); - } + auto ex_pair = three_body_decomp(ex_, true); + ex_ = ex_pair.first; + initial_pairing = ex_pair.second; + simplify(ex_); + for (auto&& product : ex_->as().summands()) { + if (product->is()) { + for (auto&& factor : product->as().factors()) { + if (factor->is()) { + if (factor->as().label() == + optype2label.at(OpType::RDMCumulant) && + factor->as().rank() > 2) { + factor = ex(0); + } else if (factor->as().label() == + optype2label.at(OpType::RDMCumulant) && + factor->as().rank() == 2) { + factor = cumu2_to_density(factor); + } else if (factor->as().label() == + optype2label.at(OpType::RDMCumulant)) { + factor = cumu_to_density(factor); + } else { + assert(factor->as().label() != + optype2label.at(OpType::RDMCumulant)); } } } } - simplify(ex_); - // std::wcout << " cumulant replacment: " << to_latex_align(_ex,20, 7) << - // std::endl; } - else if (rank == 1) { - auto ex_pair = three_body_decomp(ex_, true); - ex_ = ex_pair.first; - initial_pairing = ex_pair.second; - simplify(ex_); - for (auto&& product : ex_->as().summands()) { - if (product->is()) { - for (auto&& factor : product->as().factors()) { - if (factor->is()) { - if (factor->as().label() == - optype2label.at(OpType::RDMCumulant) && - factor->as().rank() > 1) { - factor = ex(0); - } else if (factor->as().label() == - optype2label.at(OpType::RDMCumulant)) { - factor = cumu_to_density(factor); - } else { - assert(factor->as().label() != - optype2label.at(OpType::RDMCumulant)); - } + simplify(ex_); + // std::wcout << " cumulant replacment: " << to_latex_align(_ex,20, 7) << + // std::endl; + } else if (rank == 1) { + auto ex_pair = three_body_decomp(ex_, true); + ex_ = ex_pair.first; + initial_pairing = ex_pair.second; + simplify(ex_); + for (auto&& product : ex_->as().summands()) { + if (product->is()) { + for (auto&& factor : product->as().factors()) { + if (factor->is()) { + if (factor->as().label() == + optype2label.at(OpType::RDMCumulant) && + factor->as().rank() > 1) { + factor = ex(0); + } else if (factor->as().label() == + optype2label.at(OpType::RDMCumulant)) { + factor = cumu_to_density(factor); + } else { + assert(factor->as().label() != + optype2label.at(OpType::RDMCumulant)); } } } } - simplify(ex_); - } - else { - throw "rank not supported!"; } - return {ex_, initial_pairing}; - + simplify(ex_); + } else { + throw "rank not supported!"; + } + return {ex_, initial_pairing}; } // in general a three body substitution can be approximated with 1, 2, or 3 body @@ -388,14 +392,17 @@ ExprPtr three_body_substitution(ExprPtr& input, int rank, bool fast = false) { if (input == ex(0)) { return input; } - if(fast){ + if (fast) { assert(rank == 2); if (input->is()) { for (auto&& product : input->as().summands()) { if (product->is()) { for (auto&& factor : product->as().factors()) { - if (factor->is() && (factor->as().rank() ==3)) { // find the 3-body terms - auto fac_pair = decompositions::three_body_decomposition(factor,rank,fast); // decompose that term and replace the existing term. + if (factor->is() && (factor->as().rank() == + 3)) { // find the 3-body terms + auto fac_pair = decompositions::three_body_decomposition( + factor, rank, + fast); // decompose that term and replace the existing term. factor = fac_pair.first; } } @@ -403,27 +410,26 @@ ExprPtr three_body_substitution(ExprPtr& input, int rank, bool fast = false) { } simplify(input); return input; - } - else if (input->is()) { + } else if (input->is()) { for (auto&& factor : input->as().factors()) { if (factor->is() && (factor->as().rank() == 3)) { // find the 3-body terms auto fac_pair = decompositions::three_body_decomposition( - factor, - rank,fast); // decompose that term and replace the existing term. + factor, rank, + fast); // decompose that term and replace the existing term. factor = fac_pair.first; } } simplify(input); return input; - } - else if (input->is()) { + } else if (input->is()) { auto fac_pair = decompositions::three_body_decomposition( - input, rank,fast); // decompose that term and replace the existing term. + input, rank, + fast); // decompose that term and replace the existing term. input = fac_pair.first; simplify(input); return input; - } + } } std::pair, std::vector> initial_pairing; if (input->is()) { diff --git a/SeQuant/domain/mbpt/sr.cpp b/SeQuant/domain/mbpt/sr.cpp index 1f2e99b0a..669711cf8 100644 --- a/SeQuant/domain/mbpt/sr.cpp +++ b/SeQuant/domain/mbpt/sr.cpp @@ -2,8 +2,8 @@ // Created by Eduard Valeyev on 2019-02-19. // -#include #include +#include #include #include @@ -14,8 +14,8 @@ #include #include -#include #include +#include #include #include #include diff --git a/SeQuant/domain/mbpt/sr.hpp b/SeQuant/domain/mbpt/sr.hpp index 176199ff7..d33cebd36 100644 --- a/SeQuant/domain/mbpt/sr.hpp +++ b/SeQuant/domain/mbpt/sr.hpp @@ -274,7 +274,8 @@ ExprPtr Λ_pt(std::size_t order, std::size_t K, bool skip1 = false); /// @} -/// @return true if \p op_or_op_product can change quantum numbers from \p source_qns to \p target_qns +/// @return true if \p op_or_op_product can change quantum numbers from \p +/// source_qns to \p target_qns bool can_change_qns(const ExprPtr& op_or_op_product, const qns_t target_qns, const qns_t source_qns = {}); diff --git a/examples/eval/eval_utils.hpp b/examples/eval/eval_utils.hpp index 41dcadfe8..161b4ec33 100644 --- a/examples/eval/eval_utils.hpp +++ b/examples/eval/eval_utils.hpp @@ -55,12 +55,12 @@ auto range1_limits(sequant::Tensor const& tensor, size_t nocc, size_t nvirt) { static auto const ao = sequant::IndexSpace::active_occupied; static auto const au = sequant::IndexSpace::active_unoccupied; return tensor.const_braket() | - ranges::views::transform([nocc, nvirt](auto const& idx) { - const auto& sp = idx.space(); - assert(sp == ao || sp == au); + ranges::views::transform([nocc, nvirt](auto const& idx) { + const auto& sp = idx.space(); + assert(sp == ao || sp == au); - return sp == ao ? nocc : nvirt; - }); + return sp == ao ? nocc : nvirt; + }); } template diff --git a/examples/eval/options.hpp b/examples/eval/options.hpp index 2b9c41779..7e4b8b366 100644 --- a/examples/eval/options.hpp +++ b/examples/eval/options.hpp @@ -171,7 +171,7 @@ class ParseOptionsSCF { std::string_view const tightness = "tightness"; - std::string_view const maxiter = "maxiter"; + std::string_view const maxiter = "maxiter"; public: [[nodiscard]] std::string help() const; diff --git a/examples/eval/scf.cpp b/examples/eval/scf.cpp index 1c7f5c78e..cec72676e 100644 --- a/examples/eval/scf.cpp +++ b/examples/eval/scf.cpp @@ -87,7 +87,7 @@ void SequantEvalScf::scf(std::basic_ostream& log) { if (info_.log_opts.level > 0) log_iter(iter, energy_, ediff, norm_diff, t_beg_iter, t_end_iter); } while (!converged_ && iter < info_.scf_opts.max_iter); -// reset_cache_all(); + // reset_cache_all(); auto t_end_scf = HRC::now(); if (info_.log_opts.level > 0) log << std::wstring(20, L'-') << "\n" diff --git a/python/src/sequant/mbpt.h b/python/src/sequant/mbpt.h index 24e48828d..07f73c03d 100644 --- a/python/src/sequant/mbpt.h +++ b/python/src/sequant/mbpt.h @@ -25,10 +25,9 @@ ExprPtr VacuumAverage(const ExprPtr& e, const Args&... args) { return sequant::mbpt::sr::vac_av(e, args...); } -#define SR_OP(OP) \ -#OP, [](std::int64_t Rank) { return sequant::mbpt::sr::OP(Rank); }, \ - py::arg( \ - "Bra") +#define SR_OP(OP) \ + #OP, [](std::int64_t Rank) { return sequant::mbpt::sr::OP(Rank); }, \ + py::arg("Bra") inline void __init__(py::module m) { sequant::mbpt::set_default_convention(); diff --git a/tests/unit/test_asy_cost.cpp b/tests/unit/test_asy_cost.cpp index 0f81ddfff..98ac9c334 100644 --- a/tests/unit/test_asy_cost.cpp +++ b/tests/unit/test_asy_cost.cpp @@ -3,8 +3,8 @@ #include #include -#include #include +#include #include struct MatFlops { diff --git a/tests/unit/test_binary_node.cpp b/tests/unit/test_binary_node.cpp index f4299b60f..c1ec8659a 100644 --- a/tests/unit/test_binary_node.cpp +++ b/tests/unit/test_binary_node.cpp @@ -3,8 +3,8 @@ #include #include -#include #include +#include #include #include diff --git a/tests/unit/test_bliss.cpp b/tests/unit/test_bliss.cpp index 18c1c0cb6..67ec709e3 100644 --- a/tests/unit/test_bliss.cpp +++ b/tests/unit/test_bliss.cpp @@ -7,10 +7,10 @@ #include #include -#include -#include #include +#include #include +#include constexpr const bool use_colors = true; diff --git a/tests/unit/test_canonicalize.cpp b/tests/unit/test_canonicalize.cpp index 1dad8ad8a..7c0b2d274 100644 --- a/tests/unit/test_canonicalize.cpp +++ b/tests/unit/test_canonicalize.cpp @@ -1,13 +1,13 @@ #include "catch.hpp" -#include -#include #include #include +#include #include #include #include #include +#include #include #include diff --git a/tests/unit/test_eval_expr.cpp b/tests/unit/test_eval_expr.cpp index 7940797ee..02465054c 100644 --- a/tests/unit/test_eval_expr.cpp +++ b/tests/unit/test_eval_expr.cpp @@ -1,19 +1,19 @@ #include "catch.hpp" -#include -#include -#include -#include #include #include #include +#include +#include #include #include +#include +#include -#include #include #include #include +#include #include diff --git a/tests/unit/test_eval_node.cpp b/tests/unit/test_eval_node.cpp index e3a95145d..dbb8c98f5 100644 --- a/tests/unit/test_eval_node.cpp +++ b/tests/unit/test_eval_node.cpp @@ -1,13 +1,13 @@ #include "catch.hpp" -#include -#include #include #include #include #include #include +#include #include +#include #include #include diff --git a/tests/unit/test_expr.cpp b/tests/unit/test_expr.cpp index bc71dfc52..be37ff9b0 100644 --- a/tests/unit/test_expr.cpp +++ b/tests/unit/test_expr.cpp @@ -4,17 +4,17 @@ #include "catch.hpp" -#include #include #include #include +#include #include #include #include +#include #include #include -#include #include #include #include diff --git a/tests/unit/test_fusion.cpp b/tests/unit/test_fusion.cpp index 6cd48fbdd..d6018c07e 100644 --- a/tests/unit/test_fusion.cpp +++ b/tests/unit/test_fusion.cpp @@ -1,9 +1,9 @@ #include "catch.hpp" -#include -#include #include #include +#include +#include #include #include diff --git a/tests/unit/test_iterator.cpp b/tests/unit/test_iterator.cpp index 2094382ad..12f2a1ac0 100644 --- a/tests/unit/test_iterator.cpp +++ b/tests/unit/test_iterator.cpp @@ -4,9 +4,9 @@ #include "catch.hpp" +#include #include #include -#include #include #include @@ -16,19 +16,18 @@ #include TEST_CASE("Iterators", "[elements]") { - using namespace sequant; SECTION("constructor") { - { REQUIRE_NOTHROW(flattened_rangenest{}); [[maybe_unused]] auto rng0 = flattened_rangenest{}; } { - auto opseq1 = FNOperatorSeq{{FNOperator({L"i_1", L"i_3"}, {L"i_2", L"i_4"}), - FNOperator({L"i_5"}, {L"i_6"})}}; + auto opseq1 = + FNOperatorSeq{{FNOperator({L"i_1", L"i_3"}, {L"i_2", L"i_4"}), + FNOperator({L"i_5"}, {L"i_6"})}}; REQUIRE_NOTHROW(flattened_rangenest{&opseq1}); auto rng1 = flattened_rangenest{&opseq1}; @@ -73,11 +72,11 @@ TEST_CASE("Iterators", "[elements]") { // flatten recursively { - auto opseq1 = std::vector{FNOperatorSeq{{FNOperator({L"i_1", L"i_3"}, {L"i_2", L"i_4"}), - FNOperator({L"i_5"}, {L"i_6"})}}, - FNOperatorSeq{{FNOperator({L"i_7"}, {L"i_8"}), - FNOperator({L"i_9"}, {L"i_10"})}} - }; + auto opseq1 = std::vector{ + FNOperatorSeq{{FNOperator({L"i_1", L"i_3"}, {L"i_2", L"i_4"}), + FNOperator({L"i_5"}, {L"i_6"})}}, + FNOperatorSeq{{FNOperator({L"i_7"}, {L"i_8"}), + FNOperator({L"i_9"}, {L"i_10"})}}}; auto rng1 = flattened_rangenest{&opseq1}; auto rng2 = flattened_rangenest{&rng1}; @@ -139,8 +138,6 @@ TEST_CASE("Iterators", "[elements]") { REQUIRE(it2 == end(rng2)); REQUIRE(ranges::get_cursor(end(rng2)).ordinal() == 10); } - } - } // TEST_CASE("Iterators") diff --git a/tests/unit/test_main.cpp b/tests/unit/test_main.cpp index f8d982f6a..abb81cfe3 100644 --- a/tests/unit/test_main.cpp +++ b/tests/unit/test_main.cpp @@ -3,13 +3,13 @@ // #define CATCH_CONFIG_RUNNER -#include #include #include #include #include #include #include +#include #include "catch.hpp" #ifdef SEQUANT_HAS_TILEDARRAY diff --git a/tests/unit/test_math.cpp b/tests/unit/test_math.cpp index 94b40e253..2339c091d 100644 --- a/tests/unit/test_math.cpp +++ b/tests/unit/test_math.cpp @@ -5,13 +5,13 @@ #include "catch.hpp" #include +#include #include #include #include -#include -#include #include +#include #include #include #include diff --git a/tests/unit/test_optimize.cpp b/tests/unit/test_optimize.cpp index d5713fb81..20272152d 100644 --- a/tests/unit/test_optimize.cpp +++ b/tests/unit/test_optimize.cpp @@ -1,11 +1,11 @@ #include "catch.hpp" -#include -#include #include #include #include #include +#include +#include #include #include diff --git a/tests/unit/test_parse_expr.cpp b/tests/unit/test_parse_expr.cpp index 6db2743cf..3dbb66826 100644 --- a/tests/unit/test_parse_expr.cpp +++ b/tests/unit/test_parse_expr.cpp @@ -1,19 +1,19 @@ #include "catch.hpp" -#include -#include #include #include #include #include +#include #include +#include #include +#include #include +#include #include #include -#include -#include #include #include #include diff --git a/tests/unit/test_runtime.cpp b/tests/unit/test_runtime.cpp index 0ca156f2b..3a09c4c78 100644 --- a/tests/unit/test_runtime.cpp +++ b/tests/unit/test_runtime.cpp @@ -4,8 +4,8 @@ #include "catch.hpp" -#include #include +#include TEST_CASE("Context", "[runtime]") { using namespace sequant; diff --git a/tests/unit/test_spin.cpp b/tests/unit/test_spin.cpp index 6167a05d0..528f7e155 100644 --- a/tests/unit/test_spin.cpp +++ b/tests/unit/test_spin.cpp @@ -2,8 +2,6 @@ // Created by Nakul Teke on 12/20/19. // -#include -#include #include #include #include @@ -11,9 +9,11 @@ #include #include #include +#include #include #include #include +#include #include "catch.hpp" #include "test_config.hpp" diff --git a/tests/unit/test_tensor_network.cpp b/tests/unit/test_tensor_network.cpp index d0ad705dc..cdee8bc21 100644 --- a/tests/unit/test_tensor_network.cpp +++ b/tests/unit/test_tensor_network.cpp @@ -4,25 +4,25 @@ #include "catch.hpp" -#include -#include -#include -#include -#include -#include #include #include #include +#include #include #include #include #include +#include +#include +#include +#include +#include -#include -#include #include #include +#include #include +#include #include #include #include diff --git a/tests/unit/test_wick.cpp b/tests/unit/test_wick.cpp index cc79a8d06..3d6b6bcba 100644 --- a/tests/unit/test_wick.cpp +++ b/tests/unit/test_wick.cpp @@ -2,7 +2,6 @@ // Created by Eduard Valeyev on 3/23/18. // -#include #include #include #include @@ -13,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -22,8 +22,8 @@ #include -#include #include +#include #include #include #include From 35156791249e6466a5d6bade6d3abf3c415f5370 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Thu, 2 May 2024 15:38:05 +0200 Subject: [PATCH 35/40] Don't format-check external code --- .github/workflows/formatting_check.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/formatting_check.yml b/.github/workflows/formatting_check.yml index 436c82a77..4eef6ae48 100644 --- a/.github/workflows/formatting_check.yml +++ b/.github/workflows/formatting_check.yml @@ -11,5 +11,6 @@ jobs: - uses: jidicula/clang-format-action@v4.11.0 with: clang-format-version: "17" + exclude-regex: "/external/" From 20bdbf641a756088bf8872f76287ca9aefc0b672 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Fri, 3 May 2024 10:50:15 -0400 Subject: [PATCH 36/40] find or fetch catch2, use slim headers --- CMakeLists.txt | 6 +- cmake/modules/FindOrFetchCatch2.cmake | 13 + external/versions.cmake | 4 +- tests/unit/catch.hpp | 17970 ------------------------ tests/unit/test_asy_cost.cpp | 2 +- tests/unit/test_binary_node.cpp | 2 +- tests/unit/test_bliss.cpp | 2 +- tests/unit/test_cache_manager.cpp | 2 +- tests/unit/test_canonicalize.cpp | 2 +- tests/unit/test_eval_btas.cpp | 2 +- tests/unit/test_eval_expr.cpp | 2 +- tests/unit/test_eval_node.cpp | 2 +- tests/unit/test_eval_ta.cpp | 2 +- tests/unit/test_expr.cpp | 2 +- tests/unit/test_fusion.cpp | 2 +- tests/unit/test_index.cpp | 2 +- tests/unit/test_iterator.cpp | 2 +- tests/unit/test_latex.cpp | 2 +- tests/unit/test_main.cpp | 7 +- tests/unit/test_math.cpp | 2 +- tests/unit/test_mbpt.cpp | 2 +- tests/unit/test_mbpt_cc.cpp | 2 +- tests/unit/test_op.cpp | 2 +- tests/unit/test_optimize.cpp | 2 +- tests/unit/test_parse_expr.cpp | 5 +- tests/unit/test_runtime.cpp | 2 +- tests/unit/test_space.cpp | 2 +- tests/unit/test_spin.cpp | 2 +- tests/unit/test_string.cpp | 2 +- tests/unit/test_tensor.cpp | 2 +- tests/unit/test_tensor_network.cpp | 2 +- tests/unit/test_wick.cpp | 2 +- 32 files changed, 54 insertions(+), 18003 deletions(-) create mode 100644 cmake/modules/FindOrFetchCatch2.cmake delete mode 100644 tests/unit/catch.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 20c34d84f..997e53ab0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -393,6 +393,9 @@ include(CTest) if (BUILD_TESTING) + # need catch2 + include(FindOrFetchCatch2) + set(utests_src tests/unit/test_space.cpp tests/unit/test_index.cpp @@ -431,12 +434,11 @@ if (BUILD_TESTING) tests/unit/test_eval_btas.cpp tests/unit/test_eval_ta.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON) endif (TARGET tiledarray) - set(utests_deps SeQuant) + set(utests_deps SeQuant Catch2) set(unit_test_executable unit_tests-sequant) add_executable(${unit_test_executable} EXCLUDE_FROM_ALL tests/unit/test_main.cpp - tests/unit/catch.hpp tests/unit/test_config.hpp ${utests_src}) target_link_libraries(${unit_test_executable} ${utests_deps}) diff --git a/cmake/modules/FindOrFetchCatch2.cmake b/cmake/modules/FindOrFetchCatch2.cmake new file mode 100644 index 000000000..2a1bf0480 --- /dev/null +++ b/cmake/modules/FindOrFetchCatch2.cmake @@ -0,0 +1,13 @@ +if (NOT TARGET Catch2) + + include(${vg_cmake_kit_SOURCE_DIR}/modules/VRGFindOrFetchPackage.cmake) + VRGFindOrFetchPackage(Catch2 "https://github.com/catchorg/Catch2.git" "${SEQUANT_TRACKED_CATCH2_TAG}" + ADD_SUBDIR + CONFIG_SUBDIR + ) +endif() + +# postcond check +if (NOT TARGET Catch2) + message(FATAL_ERROR "FindOrFetchCatch2 could not make TARGET Catch2 available") +endif(NOT TARGET Catch2) diff --git a/external/versions.cmake b/external/versions.cmake index 176a7d670..06b1d02b0 100644 --- a/external/versions.cmake +++ b/external/versions.cmake @@ -1,7 +1,7 @@ # for each dependency track both current and previous id (the variable for the latter must contain PREVIOUS) # to be able to auto-update them -set(SEQUANT_TRACKED_VGCMAKEKIT_TAG cd11b3c86dfb95441646d34bfeaa243328ef0c74) +set(SEQUANT_TRACKED_VGCMAKEKIT_TAG 533e4097415a4e9878b42fd4ffd58b95c9253587) set(SEQUANT_TRACKED_RANGEV3_TAG 0.12.0) set(SEQUANT_TRACKED_RANGEV3_PREVIOUS_TAG d800a032132512a54c291ce55a2a43e0460591c7) @@ -14,3 +14,5 @@ set(SEQUANT_TRACKED_TILEDARRAY_PREVIOUS_TAG 924c15fc57058b8d9a4dd4a41b5e1e8736c2 # https://github.com/boostorg/container_hash/blob/boost-1.80.0/include/boost/container_hash/hash.hpp#L132 # Recent stdlibs have removed this class when using C++17 (e.g. Apple Clang 15) set(SEQUANT_OLDEST_BOOST_VERSION 1.81) + +set(SEQUANT_TRACKED_CATCH2_TAG v3.5.4) diff --git a/tests/unit/catch.hpp b/tests/unit/catch.hpp deleted file mode 100644 index d2a12427b..000000000 --- a/tests/unit/catch.hpp +++ /dev/null @@ -1,17970 +0,0 @@ -/* - * Catch v2.13.9 - * Generated: 2022-04-12 22:37:23.260201 - * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved. - * - * Distributed under the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - */ -#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -// start catch.hpp - - -#define CATCH_VERSION_MAJOR 2 -#define CATCH_VERSION_MINOR 13 -#define CATCH_VERSION_PATCH 9 - -#ifdef __clang__ -# pragma clang system_header -#elif defined __GNUC__ -# pragma GCC system_header -#endif - -// start catch_suppress_warnings.h - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(push) -# pragma warning(disable: 161 1682) -# else // __ICC -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wswitch-enum" -# pragma clang diagnostic ignored "-Wcovered-switch-default" -# endif -#elif defined __GNUC__ - // Because REQUIREs trigger GCC's -Wparentheses, and because still - // supported version of g++ have only buggy support for _Pragmas, - // Wparentheses have to be suppressed globally. -# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details - -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic ignored "-Wpadded" -#endif -// end catch_suppress_warnings.h -#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) -# define CATCH_IMPL -# define CATCH_CONFIG_ALL_PARTS -#endif - -// In the impl file, we want to have access to all parts of the headers -// Can also be used to sanely support PCHs -#if defined(CATCH_CONFIG_ALL_PARTS) -# define CATCH_CONFIG_EXTERNAL_INTERFACES -# if defined(CATCH_CONFIG_DISABLE_MATCHERS) -# undef CATCH_CONFIG_DISABLE_MATCHERS -# endif -# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) -# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER -# endif -#endif - -#if !defined(CATCH_CONFIG_IMPL_ONLY) -// start catch_platform.h - -// See e.g.: -// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html -#ifdef __APPLE__ -# include -# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ - (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) -# define CATCH_PLATFORM_MAC -# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) -# define CATCH_PLATFORM_IPHONE -# endif - -#elif defined(linux) || defined(__linux) || defined(__linux__) -# define CATCH_PLATFORM_LINUX - -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) -# define CATCH_PLATFORM_WINDOWS -#endif - -// end catch_platform.h - -#ifdef CATCH_IMPL -# ifndef CLARA_CONFIG_MAIN -# define CLARA_CONFIG_MAIN_NOT_DEFINED -# define CLARA_CONFIG_MAIN -# endif -#endif - -// start catch_user_interfaces.h - -namespace Catch { - unsigned int rngSeed(); -} - -// end catch_user_interfaces.h -// start catch_tag_alias_autoregistrar.h - -// start catch_common.h - -// start catch_compiler_capabilities.h - -// Detect a number of compiler features - by compiler -// The following features are defined: -// -// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? -// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? -// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? -// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? -// **************** -// Note to maintainers: if new toggles are added please document them -// in configuration.md, too -// **************** - -// In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -#ifdef __cplusplus - -# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) -# define CATCH_CPP14_OR_GREATER -# endif - -# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) -# define CATCH_CPP17_OR_GREATER -# endif - -#endif - -// Only GCC compiler should be used in this block, so other compilers trying to -// mask themselves as GCC should be ignored. -#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) - -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) - -#endif - -#if defined(__clang__) - -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) - -// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug -// which results in calls to destructors being emitted for each temporary, -// without a matching initialization. In practice, this can result in something -// like `std::string::~string` being called on an uninitialized value. -// -// For example, this code will likely segfault under IBM XL: -// ``` -// REQUIRE(std::string("12") + "34" == "1234") -// ``` -// -// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. -# if !defined(__ibmxl__) && !defined(__CUDACC__) -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ -# endif - -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ - _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") - -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) - -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) - -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) - -# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// Assume that non-Windows platforms support posix signals by default -#if !defined(CATCH_PLATFORM_WINDOWS) - #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS -#endif - -//////////////////////////////////////////////////////////////////////////////// -// We know some environments not to support full POSIX signals -#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) - #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -#endif - -#ifdef __OS400__ -# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -# define CATCH_CONFIG_COLOUR_NONE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Android somehow still does not support std::to_string -#if defined(__ANDROID__) -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING -# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Not all Windows environments support SEH properly -#if defined(__MINGW32__) -# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH -#endif - -//////////////////////////////////////////////////////////////////////////////// -// PS4 -#if defined(__ORBIS__) -# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Cygwin -#ifdef __CYGWIN__ - -// Required for some versions of Cygwin to declare gettimeofday -// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin -# define _BSD_SOURCE -// some versions of cygwin (most) do not support std::to_string. Use the libstd check. -// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 -# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ - && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) - -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING - -# endif -#endif // __CYGWIN__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#if defined(_MSC_VER) - -// Universal Windows platform does not support SEH -// Or console colours (or console at all...) -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -# define CATCH_CONFIG_COLOUR_NONE -# else -# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH -# endif - -# if !defined(__clang__) // Handle Clang masquerading for msvc - -// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ -// _MSVC_TRADITIONAL == 0 means new conformant preprocessor -// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) -# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -# endif // MSVC_TRADITIONAL - -// Only do this if we're not using clang on Windows, which uses `diagnostic push` & `diagnostic pop` -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) -# endif // __clang__ - -#endif // _MSC_VER - -#if defined(_REENTRANT) || defined(_MSC_VER) -// Enable async processing, as -pthread is specified or no additional linking is required -# define CATCH_INTERNAL_CONFIG_USE_ASYNC -#endif // _MSC_VER - -//////////////////////////////////////////////////////////////////////////////// -// Check if we are compiled with -fno-exceptions or equivalent -#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) -# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED -#endif - -//////////////////////////////////////////////////////////////////////////////// -// DJGPP -#ifdef __DJGPP__ -# define CATCH_INTERNAL_CONFIG_NO_WCHAR -#endif // __DJGPP__ - -//////////////////////////////////////////////////////////////////////////////// -// Embarcadero C++Build -#if defined(__BORLANDC__) - #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// Use of __COUNTER__ is suppressed during code analysis in -// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly -// handled by it. -// Otherwise all supported compilers support COUNTER macro, -// but user still might want to turn it off -#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) - #define CATCH_INTERNAL_CONFIG_COUNTER -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// RTX is a special version of Windows that is real time. -// This means that it is detected as Windows, but does not provide -// the same set of capabilities as real Windows does. -#if defined(UNDER_RTSS) || defined(RTX64_BUILD) - #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH - #define CATCH_INTERNAL_CONFIG_NO_ASYNC - #define CATCH_CONFIG_COLOUR_NONE -#endif - -#if !defined(_GLIBCXX_USE_C99_MATH_TR1) -#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER -#endif - -// Various stdlib support checks that require __has_include -#if defined(__has_include) - // Check if string_view is available and usable - #if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW - #endif - - // Check if optional is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) - - // Check if byte is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # include - # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0) - # define CATCH_INTERNAL_CONFIG_CPP17_BYTE - # endif - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) - - // Check if variant is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # if defined(__clang__) && (__clang_major__ < 8) - // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 - // fix should be in clang 8, workaround in libstdc++ 8.2 - # include - # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) - # define CATCH_CONFIG_NO_CPP17_VARIANT - # else - # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT - # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) - # else - # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT - # endif // defined(__clang__) && (__clang_major__ < 8) - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) -#endif // defined(__has_include) - -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) -# define CATCH_CONFIG_COUNTER -#endif -#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) -# define CATCH_CONFIG_WINDOWS_SEH -#endif -// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. -#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) -# define CATCH_CONFIG_POSIX_SIGNALS -#endif -// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. -#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) -# define CATCH_CONFIG_WCHAR -#endif - -#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) -# define CATCH_CONFIG_CPP11_TO_STRING -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) -# define CATCH_CONFIG_CPP17_OPTIONAL -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) -# define CATCH_CONFIG_CPP17_STRING_VIEW -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) -# define CATCH_CONFIG_CPP17_VARIANT -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) -# define CATCH_CONFIG_CPP17_BYTE -#endif - -#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) -# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE -#endif - -#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) -# define CATCH_CONFIG_NEW_CAPTURE -#endif - -#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -# define CATCH_CONFIG_DISABLE_EXCEPTIONS -#endif - -#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) -# define CATCH_CONFIG_POLYFILL_ISNAN -#endif - -#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) -# define CATCH_CONFIG_USE_ASYNC -#endif - -#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) -# define CATCH_CONFIG_ANDROID_LOGWRITE -#endif - -#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) -# define CATCH_CONFIG_GLOBAL_NEXTAFTER -#endif - -// Even if we do not think the compiler has that warning, we still have -// to provide a macro that can be used by the code. -#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION -#endif -#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS -#endif - -// The goal of this macro is to avoid evaluation of the arguments, but -// still have the compiler warn on problems inside... -#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) -#endif - -#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) -# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#elif defined(__clang__) && (__clang_major__ < 5) -# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#endif - -#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#endif - -#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -#define CATCH_TRY if ((true)) -#define CATCH_CATCH_ALL if ((false)) -#define CATCH_CATCH_ANON(type) if ((false)) -#else -#define CATCH_TRY try -#define CATCH_CATCH_ALL catch (...) -#define CATCH_CATCH_ANON(type) catch (type) -#endif - -#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) -#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#endif - -// end catch_compiler_capabilities.h -#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line -#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) -#ifdef CATCH_CONFIG_COUNTER -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) -#else -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) -#endif - -#include -#include -#include - -// We need a dummy global operator<< so we can bring it into Catch namespace later -struct Catch_global_namespace_dummy {}; -std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); - -namespace Catch { - - struct CaseSensitive { enum Choice { - Yes, - No - }; }; - - class NonCopyable { - NonCopyable( NonCopyable const& ) = delete; - NonCopyable( NonCopyable && ) = delete; - NonCopyable& operator = ( NonCopyable const& ) = delete; - NonCopyable& operator = ( NonCopyable && ) = delete; - - protected: - NonCopyable(); - virtual ~NonCopyable(); - }; - - struct SourceLineInfo { - - SourceLineInfo() = delete; - SourceLineInfo( char const* _file, std::size_t _line ) noexcept - : file( _file ), - line( _line ) - {} - - SourceLineInfo( SourceLineInfo const& other ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo( SourceLineInfo&& ) noexcept = default; - SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; - - bool empty() const noexcept { return file[0] == '\0'; } - bool operator == ( SourceLineInfo const& other ) const noexcept; - bool operator < ( SourceLineInfo const& other ) const noexcept; - - char const* file; - std::size_t line; - }; - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); - - // Bring in operator<< from global namespace into Catch namespace - // This is necessary because the overload of operator<< above makes - // lookup stop at namespace Catch - using ::operator<<; - - // Use this in variadic streaming macros to allow - // >> +StreamEndStop - // as well as - // >> stuff +StreamEndStop - struct StreamEndStop { - std::string operator+() const; - }; - template - T const& operator + ( T const& value, StreamEndStop ) { - return value; - } -} - -#define CATCH_INTERNAL_LINEINFO \ - ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) - -// end catch_common.h -namespace Catch { - - struct RegistrarForTagAliases { - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - }; - -} // end namespace Catch - -#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION - -// end catch_tag_alias_autoregistrar.h -// start catch_test_registry.h - -// start catch_interfaces_testcase.h - -#include - -namespace Catch { - - class TestSpec; - - struct ITestInvoker { - virtual void invoke () const = 0; - virtual ~ITestInvoker(); - }; - - class TestCase; - struct IConfig; - - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector const& getAllTests() const = 0; - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; - }; - - bool isThrowSafe( TestCase const& testCase, IConfig const& config ); - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); - std::vector const& getAllTestCasesSorted( IConfig const& config ); - -} - -// end catch_interfaces_testcase.h -// start catch_stringref.h - -#include -#include -#include -#include - -namespace Catch { - - /// A non-owning string class (similar to the forthcoming std::string_view) - /// Note that, because a StringRef may be a substring of another string, - /// it may not be null terminated. - class StringRef { - public: - using size_type = std::size_t; - using const_iterator = const char*; - - private: - static constexpr char const* const s_empty = ""; - - char const* m_start = s_empty; - size_type m_size = 0; - - public: // construction - constexpr StringRef() noexcept = default; - - StringRef( char const* rawChars ) noexcept; - - constexpr StringRef( char const* rawChars, size_type size ) noexcept - : m_start( rawChars ), - m_size( size ) - {} - - StringRef( std::string const& stdString ) noexcept - : m_start( stdString.c_str() ), - m_size( stdString.size() ) - {} - - explicit operator std::string() const { - return std::string(m_start, m_size); - } - - public: // operators - auto operator == ( StringRef const& other ) const noexcept -> bool; - auto operator != (StringRef const& other) const noexcept -> bool { - return !(*this == other); - } - - auto operator[] ( size_type index ) const noexcept -> char { - assert(index < m_size); - return m_start[index]; - } - - public: // named queries - constexpr auto empty() const noexcept -> bool { - return m_size == 0; - } - constexpr auto size() const noexcept -> size_type { - return m_size; - } - - // Returns the current start pointer. If the StringRef is not - // null-terminated, throws std::domain_exception - auto c_str() const -> char const*; - - public: // substrings and searches - // Returns a substring of [start, start + length). - // If start + length > size(), then the substring is [start, size()). - // If start > size(), then the substring is empty. - auto substr( size_type start, size_type length ) const noexcept -> StringRef; - - // Returns the current start pointer. May not be null-terminated. - auto data() const noexcept -> char const*; - - constexpr auto isNullTerminated() const noexcept -> bool { - return m_start[m_size] == '\0'; - } - - public: // iterators - constexpr const_iterator begin() const { return m_start; } - constexpr const_iterator end() const { return m_start + m_size; } - }; - - auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; - auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; - - constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { - return StringRef( rawChars, size ); - } -} // namespace Catch - -constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { - return Catch::StringRef( rawChars, size ); -} - -// end catch_stringref.h -// start catch_preprocessor.hpp - - -#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ -#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) - -#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ -// MSVC needs more evaluations -#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) -#else -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) -#endif - -#define CATCH_REC_END(...) -#define CATCH_REC_OUT - -#define CATCH_EMPTY() -#define CATCH_DEFER(id) id CATCH_EMPTY() - -#define CATCH_REC_GET_END2() 0, CATCH_REC_END -#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 -#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 -#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT -#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) -#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) - -#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) - -#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) - -// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, -// and passes userdata as the first parameter to each invocation, -// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) -#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) - -#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) - -#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) -#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ -#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ -#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF -#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ -#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) -#else -// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF -#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) -#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ -#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) -#endif - -#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ -#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) - -#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) - -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) -#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) -#else -#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) -#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) -#endif - -#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ - CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) - -#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) -#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) -#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) -#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) -#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) -#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) -#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) -#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) -#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) -#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) -#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) - -#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N - -#define INTERNAL_CATCH_TYPE_GEN\ - template struct TypeList {};\ - template\ - constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ - template class...> struct TemplateTypeList{};\ - template class...Cs>\ - constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ - template\ - struct append;\ - template\ - struct rewrap;\ - template class, typename...>\ - struct create;\ - template class, typename>\ - struct convert;\ - \ - template \ - struct append { using type = T; };\ - template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ - struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ - template< template class L1, typename...E1, typename...Rest>\ - struct append, TypeList, Rest...> { using type = L1; };\ - \ - template< template class Container, template class List, typename...elems>\ - struct rewrap, List> { using type = TypeList>; };\ - template< template class Container, template class List, class...Elems, typename...Elements>\ - struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ - \ - template