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:
parent
b15281d44b
commit
b416a67bb9
3 changed files with 52 additions and 17 deletions
|
|
@ -389,12 +389,13 @@ namespace lib {
|
||||||
* within the same processing step; and in addition, it allows the processing step to
|
* 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.
|
* 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 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
|
* @tparam SRC source type to feed to the function to be adapted.
|
||||||
* a generic lambda or template as FUN. Such a generic functor will be _instantiated_
|
* @remark Especially need to specify the source iterator type to apply when passing a generic lambda
|
||||||
* passing the type `SRC&` as argument. This instantiation may fail (and abort compilation),
|
* or template as FUN. Such a generic functor will be _instantiated_ passing the type `SRC&`
|
||||||
* but when it succeeds, we can infer the result type `Res` from the generic lambda
|
* 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
|
struct _FunTraits
|
||||||
{
|
{
|
||||||
/** handle all regular "function-like" entities */
|
/** 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
|
* @note exhausts and discards the pipeline itself
|
||||||
*/
|
*/
|
||||||
template<class FUN>
|
template<class FUN>
|
||||||
|
|
@ -1601,6 +1602,29 @@ namespace lib {
|
||||||
consumeFun (pipeline);
|
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.
|
/** _terminal builder_ to pour and materialise all results from this Pipeline.
|
||||||
* @tparam CON a STL compliant container to store generated values (defaults to `vector`)
|
* @tparam CON a STL compliant container to store generated values (defaults to `vector`)
|
||||||
* @return new instance of the target container, filled with all values
|
* @return new instance of the target container, filled with all values
|
||||||
|
|
|
||||||
|
|
@ -44,9 +44,6 @@
|
||||||
|
|
||||||
#include "lib/error.hpp"
|
#include "lib/error.hpp"
|
||||||
#include "lib/nocopy.hpp"
|
#include "lib/nocopy.hpp"
|
||||||
//#include "include/logging.h"
|
|
||||||
//#include "lib/meta/function.hpp"
|
|
||||||
//#include "lib/result.hpp"
|
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
@ -54,12 +51,6 @@
|
||||||
|
|
||||||
namespace lib {
|
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.
|
* A one time N-fold mutual synchronisation barrier.
|
||||||
|
|
@ -76,12 +67,13 @@ namespace lib {
|
||||||
std::atomic_int latch_;
|
std::atomic_int latch_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** @param nFold the number of participants to sync */
|
/** @param nFold the number of participants to sync (min. 2)*/
|
||||||
explicit
|
explicit
|
||||||
SyncBarrier (uint nFold =2)
|
SyncBarrier (uint nFold =2)
|
||||||
: latch_{int(nFold)}
|
: latch_{int(nFold)}
|
||||||
{
|
{
|
||||||
REQUIRE (nFold >= 2, "Pointless to sync less than two participants.");
|
REQUIRE (nFold >= 2, "Pointless to sync less than two participants.");
|
||||||
|
ENSURE (nFold < 100'000, "Danger territory.... sync 100k Threads??");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -93,7 +85,7 @@ namespace lib {
|
||||||
while (0 < latch_.load (std::memory_order_relaxed));
|
while (0 < latch_.load (std::memory_order_relaxed));
|
||||||
else
|
else
|
||||||
latch_.store (0, std::memory_order_relaxed);
|
latch_.store (0, std::memory_order_relaxed);
|
||||||
}
|
} // prevent spurious calls from wrapping
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -286,6 +286,7 @@ namespace test{
|
||||||
verify_FilterChanges();
|
verify_FilterChanges();
|
||||||
verify_asIterSource();
|
verify_asIterSource();
|
||||||
verify_IterSource();
|
verify_IterSource();
|
||||||
|
verify_resultSum();
|
||||||
verify_effuse();
|
verify_effuse();
|
||||||
|
|
||||||
verify_depthFirstExploration();
|
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.
|
/** @test verify _terminal operation_ to append all results into a container.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue