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)
This commit is contained in:
Fischlurch 2023-09-23 19:39:08 +02:00
parent b15281d44b
commit b416a67bb9
3 changed files with 52 additions and 17 deletions

View file

@ -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<class FUN, typename SRC =void>
template<class FUN, typename SRC>
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<class FUN>
@ -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<class FUN>
auto
resultSum (FUN&& accessor)
{
auto accessVal = iter_explorer::_FunTraits<FUN,SRC>::adaptFunctor (forward<FUN> (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

View file

@ -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 <thread>
#include <atomic>
@ -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
};

View file

@ -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<Res>() == "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