From b416a67bb90ed4c0ac8129add7e01ca84ab6ff7d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 23 Sep 2023 19:39:08 +0200 Subject: [PATCH] Library: extract summation of pipeline results ...first used as part of the test harness; seemingly this is a generic and generally useful shortcut, similar to algorithm::reduce (or some kind of fold-left operation) --- src/lib/iter-explorer.hpp | 36 +++++++++++++++++++++++----- src/lib/sync-barrier.hpp | 14 +++-------- tests/library/iter-explorer-test.cpp | 19 +++++++++++++++ 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/src/lib/iter-explorer.hpp b/src/lib/iter-explorer.hpp index 422af1900..6b61fcabc 100644 --- a/src/lib/iter-explorer.hpp +++ b/src/lib/iter-explorer.hpp @@ -389,12 +389,13 @@ namespace lib { * within the same processing step; and in addition, it allows the processing step to * remain agnostic with respect to the adaptation and concrete type of the functor/lambda. * @tparam FUN either the signature, or something _"function-like"_ passed as functor to be bound - * @tparam SRC (optional) but need to specify the source iterator type to apply when passing - * a generic lambda or template as FUN. Such a generic functor will be _instantiated_ - * passing the type `SRC&` as argument. This instantiation may fail (and abort compilation), - * but when it succeeds, we can infer the result type `Res` from the generic lambda + * @tparam SRC source type to feed to the function to be adapted. + * @remark Especially need to specify the source iterator type to apply when passing a generic lambda + * or template as FUN. Such a generic functor will be _instantiated_ passing the type `SRC&` + * as argument. This instantiation may fail (and abort compilation), but when it succeeds, + * the result type `Res` can be inferred from the generic lambda. */ - template + template struct _FunTraits { /** handle all regular "function-like" entities */ @@ -1588,7 +1589,7 @@ namespace lib { } /** - * _terminal builder_ to invoke a functor for side effect on the complete pipeline. + * _terminal builder_ to invoke a functor for side effect on the complete pipeline. * @note exhausts and discards the pipeline itself */ template @@ -1601,6 +1602,29 @@ namespace lib { consumeFun (pipeline); } + /** + * _terminal builder_ to invoke sum up resulting number values from the pipeline. + * @return accumulation of all results from the pipeline, combined by `std::plus` + */ + template + auto + resultSum (FUN&& accessor) + { + auto accessVal = iter_explorer::_FunTraits::adaptFunctor (forward (accessor)); + value_type sum{}; + SRC& pipeline = *this; + for ( ; pipeline; ++pipeline) + sum += accessVal (pipeline); + return sum; + } + + auto + resultSum() + { + return IterExplorer::resultSum ([](const reference val){ return val; }); + } + + /** _terminal builder_ to pour and materialise all results from this Pipeline. * @tparam CON a STL compliant container to store generated values (defaults to `vector`) * @return new instance of the target container, filled with all values diff --git a/src/lib/sync-barrier.hpp b/src/lib/sync-barrier.hpp index 9782d6120..e3964f4ec 100644 --- a/src/lib/sync-barrier.hpp +++ b/src/lib/sync-barrier.hpp @@ -44,9 +44,6 @@ #include "lib/error.hpp" #include "lib/nocopy.hpp" -//#include "include/logging.h" -//#include "lib/meta/function.hpp" -//#include "lib/result.hpp" #include #include @@ -54,12 +51,6 @@ namespace lib { -// using lib::Literal; -// namespace error = lumiera::error; -// using error::LERR_(STATE); -// using error::LERR_(EXTERNAL); - - /** * A one time N-fold mutual synchronisation barrier. @@ -76,12 +67,13 @@ namespace lib { std::atomic_int latch_; public: - /** @param nFold the number of participants to sync */ + /** @param nFold the number of participants to sync (min. 2)*/ explicit SyncBarrier (uint nFold =2) : latch_{int(nFold)} { REQUIRE (nFold >= 2, "Pointless to sync less than two participants."); + ENSURE (nFold < 100'000, "Danger territory.... sync 100k Threads??"); } void @@ -93,7 +85,7 @@ namespace lib { while (0 < latch_.load (std::memory_order_relaxed)); else latch_.store (0, std::memory_order_relaxed); - } + } // prevent spurious calls from wrapping }; diff --git a/tests/library/iter-explorer-test.cpp b/tests/library/iter-explorer-test.cpp index e4a6117d5..ff7a47ec6 100644 --- a/tests/library/iter-explorer-test.cpp +++ b/tests/library/iter-explorer-test.cpp @@ -286,6 +286,7 @@ namespace test{ verify_FilterChanges(); verify_asIterSource(); verify_IterSource(); + verify_resultSum(); verify_effuse(); verify_depthFirstExploration(); @@ -1069,6 +1070,24 @@ namespace test{ + /** @test verify _terminal operation_ to sum up all values from the pipeline. + */ + void + verify_resultSum() + { + auto accumulated = explore(CountDown{6}) + .transform([](int i){ return i-1; }) + .resultSum(); + + using Res = decltype(accumulated); + CHECK (lib::test::showType() == "int"_expect); + + auto expectedSum = [](auto N){ return N*(N+1) / 2; }; + CHECK (accumulated == expectedSum(5)); + } + + + /** @test verify _terminal operation_ to append all results into a container. */ void