1 #ifndef GAUDIKERNEL_COUNTERS_H 2 #define GAUDIKERNEL_COUNTERS_H 1 129 #include "boost/algorithm/string/predicate.hpp" 130 #include "boost/format.hpp" 133 #include <initializer_list> 138 #include <type_traits> 146 namespace Accumulators
155 template <
unsigned long N>
157 template <
typename U>
168 template <
typename U>
169 constexpr decltype(
auto )
operator()( U&& v )
const noexcept
171 return std::forward<U>( v );
179 template <
typename U>
180 constexpr decltype(
auto )
operator()( U&& v )
const noexcept
189 template <
typename T,
typename =
int>
191 template <
typename T>
192 using has_fetch_add =
typename Gaudi::cpp17::is_detected<has_fetch_add_, T>::value_t;
197 template <
typename Arithmetic,
typename Result =
double>
198 using fp_result_type = std::conditional_t<std::is_integral<Arithmetic>::value, Result, Arithmetic>;
203 template <
typename Arithmetic, atomicity Atomicity>
209 template <
typename Arithmetic>
220 template <
typename Arithmetic>
226 return v.load( std::memory_order_relaxed );
235 template <
typename Arithmetic, atomicity Atomicity = atomicity::full>
241 template <
typename Arithmetic>
252 template <
typename Arithmetic>
257 #if __cplusplus > 201402L 258 static void merge(
InternalType& a, Arithmetic b ) noexcept
260 if ( DefaultValue() == b )
return;
273 template <
typename T>
276 auto current = a.
load( std::memory_order_relaxed );
280 template <
typename T>
283 a.
fetch_add( b, std::memory_order_relaxed );
289 if ( DefaultValue() == b )
return;
299 template <
typename Arithmetic, atomicity Atomicity,
typename Compare, Arithmetic ( *Initial )()>
305 template <
typename Arithmetic,
typename Compare, Arithmetic ( *Initial )()>
312 if ( Compare{}( b, a ) ) a = b;
319 template <
typename Arithmetic,
typename Compare, Arithmetic ( *Initial )()>
327 while ( Compare{}( b, prev_value ) && !a.compare_exchange_weak( prev_value, b ) )
336 template <
typename Arithmetic, atomicity Atomicity = atomicity::full>
343 template <
typename Arithmetic, atomicity Atomicity = atomicity::full>
368 template <
typename A,
typename B, atomicity C,
typename D,
typename E,
typename F>
372 using OutputType = std::decay_t<std::result_of_t<OutputTransform( InnerType )>>;
375 ValueHandler::merge( m_value, InputTransform{}( by ) );
382 m_value = ValueHandler::getValue( other.
m_value );
385 OutputType value()
const {
return OutputTransform{}( ValueHandler::getValue( m_value ) ); }
387 template <atomicity ato,
typename VH>
390 auto otherValue = VH::exchange( other.m_value, VH::DefaultValue() );
391 ValueHandler::merge( m_value, otherValue );
406 template <
typename Arithmetic, atomicity Atomicity,
template <
typename, atomicity>
class... Bases>
420 template <atomicity Ato>
424 ( Bases<Arithmetic, Atomicity>::mergeAndReset(
static_cast<Bases<Arithmetic, Ato>&&
>( other ) ), 0 )...};
428 void reset(
const std::tuple<
typename Bases<Arithmetic, Atomicity>::OutputType...>& t )
431 [
this](
const auto&... i ) {
442 template <
typename Arithmetic =
double, atomicity Atomicity = atomicity::full>
444 :
GenericAccumulator<Arithmetic, Arithmetic, Atomicity, Identity, Identity, Maximum<Arithmetic, Atomicity>> {
445 Arithmetic
max()
const {
return this->value(); }
452 template <
typename Arithmetic =
double, atomicity Atomicity = atomicity::full>
454 :
GenericAccumulator<Arithmetic, Arithmetic, Atomicity, Identity, Identity, Minimum<Arithmetic, Atomicity>> {
455 Arithmetic
min()
const {
return this->value(); }
462 template <
typename Arithmetic =
double, atomicity Atomicity = atomicity::full>
464 unsigned long nEntries()
const {
return this->value(); }
471 template <
typename Arithmetic =
double, atomicity Atomicity = atomicity::full>
473 Arithmetic
sum()
const {
return this->value(); }
480 template <
typename Arithmetic =
double, atomicity Atomicity = atomicity::full>
482 Arithmetic
sum2()
const {
return this->value(); };
495 template <
typename Arithmetic, atomicity Atomicity>
510 template <
typename Arithmetic, atomicity Atomicity>
520 template <
typename Arithmetic, atomicity Atomicity = atomicity::full>
522 unsigned long nEntries()
const {
return this->nTrueEntries() + this->nFalseEntries(); };
524 template <
typename Result = fp_result_type<Arithmetic>>
528 if ( 1 > nbEntries )
return Result{-1};
529 return static_cast<Result
>( this->nTrueEntries() ) / nbEntries;
531 auto eff()
const {
return efficiency(); }
533 template <
typename Result = fp_result_type<Arithmetic>>
540 if ( 1 > nbEntries )
return Result{-1};
541 return sqrt( static_cast<Result>( this->nTrueEntries() * this->nFalseEntries() ) / nbEntries ) / nbEntries;
543 auto effErr()
const {
return efficiencyErr(); }
550 template <
typename Arithmetic, atomicity Atomicity = atomicity::full>
553 template <
typename Result = fp_result_type<Arithmetic>>
557 return (
n > 0 ) ?
static_cast<Result
>( this->
sum() ) /
n : Result{};
565 template <
typename Arithmetic, atomicity Atomicity = atomicity::full>
568 template <
typename Result = fp_result_type<Arithmetic>>
573 return (
n > 0 ) ? ( this->sum2() - sum * ( sum /
n ) ) /
n : Result{};
576 template <
typename Result = fp_result_type<Arithmetic>>
581 return (
n > 1 ) ? ( this->sum2() - sum * ( sum /
n ) ) / (
n - 1 ) : Result{};
584 template <
typename Result = fp_result_type<Arithmetic>>
590 Result v = biased_sample_variance();
591 return ( 0 > v ) ? Result{} : sqrt( v );
593 [[deprecated(
"The name 'rms' has changed to standard_deviation" )]] Arithmetic
rms()
const 595 return standard_deviation();
598 template <
typename Result = fp_result_type<Arithmetic>>
602 if ( 0 ==
n )
return Result{};
606 Result v = biased_sample_variance();
607 return ( 0 > v ) ? Result{} : sqrt( v /
n );
615 template <
typename Arithmetic, atomicity Atomicity = atomicity::full>
624 template <
typename Arithmetic,
template <
typename Int, atomicity Ato>
class ContainedAccumulator>
625 class Buffer :
public ContainedAccumulator<Arithmetic, atomicity::none>
627 using prime_type = ContainedAccumulator<Arithmetic, atomicity::full>;
628 using base_type = ContainedAccumulator<Arithmetic, atomicity::none>;
636 void push() { m_prime.mergeAndReset( static_cast<base_type&&>( *
this ) ); }
649 template <
class OWNER>
652 o->registerCounter( tag, *
this );
661 o <<
boost::format{
" | %|-48.48s|%|50t|"} % (
"\"" + tag +
"\"" );
662 return print( o,
true );
681 return counter.
print( stream );
689 template <
typename Arithmetic, atomicity Atomicity,
template <
typename Int, atomicity Ato>
class Accumulator>
699 template <
typename Arithmetic =
double, atomicity Atomicity = atomicity::full>
704 ( *this ) += Arithmetic{};
735 template <
typename Arithmetic =
double, atomicity Atomicity = atomicity::full>
744 fmt =
"|%|10d| |%|11.7g| |%|#11.5g| |";
746 fmt =
"#=%|-7lu| Sum=%|-11.5g| Mean=%|#10.4g|";
756 template <
typename Arithmetic =
double, atomicity Atomicity = atomicity::full>
763 template <
typename Arithmetic =
double, atomicity Atomicity = atomicity::full>
772 fmt =
"|%|10d| |%|11.7g| |%|#11.5g| |%|#11.5g| |";
774 fmt =
"#=%|-7lu| Sum=%|-11.5g| Mean=%|#10.4g| +- %|-#10.5g|";
789 template <
typename Arithmetic =
double, atomicity Atomicity = atomicity::full>
797 fmt =
"|%|10d| |%|11.7g| |%|#11.5g| |%|#11.5g| |%|#12.5g| |%|#12.5g| |";
799 fmt =
"#=%|-7lu| Sum=%|-11.5g| Mean=%|#10.4g| +- %|-#10.5g| Min/Max=%|#10.4g|/%|-#10.4g|";
802 this->min() % this->max();
811 template <
typename Arithmetic =
double, atomicity Atomicity = atomicity::full>
819 fmt =
"|%|10d| |%|11.5g| |(%|#9.7g| +- %|-#8.7g|)%% |";
821 fmt =
"#=%|-7lu| Sum=%|-11.5g| Eff=|(%|#9.7g| +- %|-#8.6g|)%%|";
823 return o <<
boost::format{fmt} % this->
nEntries() % this->nTrueEntries() % ( this->efficiency() * 100 ) %
824 ( this->efficiencyErr() * 100 );
830 o <<
boost::format{
" |*%|-48.48s|%|50t|"} % (
"\"" + tag +
"\"" );
831 return print( o,
true );
840 template <
typename Counter,
typename Container,
typename Fun>
843 auto b = counter.
buffer();
844 for (
const auto& elem : container ) b += f( elem );
857 Gaudi::Accumulators::StatAccumulator,
858 Gaudi::Accumulators::BinomialAccumulator>
866 using AccParent::reset;
869 template <
class OWNER>
872 o->registerCounter( tag, *
this );
874 StatEntity(
const unsigned long entries,
const double flag,
const double flag2,
const double minFlag,
875 const double maxFlag )
881 void reset() { AccParent::reset(); }
889 ( *this ) += ( -by );
917 std::make_tuple( se.nEntries(), se.sum(), se.min(), se.max(), se.sum2() );
930 unsigned long add(
const double v )
940 double rms()
const {
return standard_deviation(); }
941 double Rms()
const {
return standard_deviation(); }
942 double RMS()
const {
return standard_deviation(); }
943 double Eff()
const {
return eff(); }
944 double Min()
const {
return min(); }
945 double Max()
const {
return max(); }
948 double flag2()
const {
return sum2(); }
950 double flagRMS()
const {
return standard_deviation(); }
956 using boost::algorithm::icontains;
957 return icontains( name,
"eff" ) || icontains( name,
"acc" ) || icontains( name,
"filt" ) ||
958 icontains( name,
"fltr" ) || icontains( name,
"pass" );
963 fmt %
nEntries() %
sum() %
mean() % standard_deviation() % min() % max();
964 return o << fmt.str();
970 if ( flag && effCounter( name ) && 0 <= eff() && 0 <= effErr() &&
sum() <=
nEntries() &&
971 ( 0 == min() || 1 == min() ) && ( 0 == max() || 1 == max() ) ) {
975 if ( name.
empty() ) {
976 fmt =
"|%|10d| |%|11.5g| |(%|#9.7g| +- %|-#8.7g|)%%| ------- | ------- |";
978 ( efficiencyErr() * 100 );
980 fmt =
" |*" + fmtHead +
"|%|10d| |%|11.5g| |(%|#9.7g| +- %|-#8.7g|)%%| ------- | ------- |";
982 ( efficiency() * 100 ) % ( efficiencyErr() * 100 );
985 fmt =
"#=%|-7lu| Sum=%|-11.5g| Eff=|(%|#9.7g| +- %|-#8.6g|)%%|";
987 ( efficiencyErr() * 100 );
993 if ( name.
empty() ) {
994 fmt =
"|%|10d| |%|11.7g| |%|#11.5g| |%|#11.5g| |%|#12.5g| |%|#12.5g| |";
998 fmt =
" | " + fmtHead +
"|%|10d| |%|11.7g| |%|#11.5g| |%|#11.5g| |%|#12.5g| |%|#12.5g| |";
1003 fmt =
"#=%|-7lu| Sum=%|-11.5g| Mean=%|#10.4g| +- %|-#10.5g| Min/Max=%|#10.4g|/%|-#10.4g|";
1010 return print( o,
true, tag,
true );
1015 return print( o, tableFormat, emptyName,
true );
1026 #endif // GAUDIKERNEL_COUNTERS_H constexpr unsigned long operator()(U &&) const noexcept
ContainedAccumulator< Arithmetic, atomicity::full > prime_type
virtual std::ostream & print(std::ostream &o, const std::string &tag) const override
prints the counter to a stream in table format, with the given tag
std::string toString() const
auto biased_sample_variance() const
static void merge(InternalType &a, Arithmetic b) noexcept
static void merge(InternalType &a, Arithmetic b) noexcept
void mergeAndReset(AccumulatorSet< Arithmetic, Ato, Bases... > &&other)
unsigned long nEntries() const
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
PrintableCounter()=default
std::ostream & print(std::ostream &o, bool tableFormat=false) const override
prints the counter to a stream
decltype(std::atomic< T >{}.fetch_add(0)) has_fetch_add_
type_traits for checking the presence of fetch_add in std::atomic<T>
std::ostream & fillStream(std::ostream &o) const
unsigned long nEntries() const
unsigned long nFalseEntries() const
std::ostream & print(std::ostream &o, bool tableFormat=false) const override
prints the counter to a stream
An empty ancester of all counters that provides a buffer method that returns a buffer on itself...
double sum(double x, double y, double z)
unsigned long nTrueEntries() const
virtual bool toBePrinted() const override
hint whether we should print that counter or not.
atomicity
Defines atomicity of the accumulators.
A counter aiming at computing average and sum2 / variance / standard deviation.
typename Gaudi::cpp17::is_detected< has_fetch_add_, T >::value_t has_fetch_add
Gaudi::Accumulators::BinomialAccumulator< double, Gaudi::Accumulators::atomicity::full > BinomialAccParent
An Adder ValueHandler operator(a, b) means a += b.
Gaudi::Accumulators::AccumulatorSet< double, Gaudi::Accumulators::atomicity::full, Gaudi::Accumulators::StatAccumulator, Gaudi::Accumulators::BinomialAccumulator > AccParent
A counter aiming at computing sum and average.
class MergingTransformer< Out(const vector_of_const_< In > void
decltype(auto) constexpr apply(F &&f, Tuple &&t) noexcept(noexcept( detail::apply_impl(std::forward< F >(f), std::forward< Tuple >(t), std::make_index_sequence< std::tuple_size< std::remove_reference_t< Tuple >>::value >{})))
virtual std::ostream & print(std::ostream &o, const std::string &tag) const
prints the counter to a stream in table format, with the given tag
An functor always returning the value N.
An empty ancester of all counters that knows how to print themselves.
double flagMeanErr() const
std::ostream & printFormatted(std::ostream &o, const std::string &format) const
bool operator<(const StatEntity &se) const
StatEntity operator++(int)
static void add(InternalType &a, T b, std::true_type)
virtual bool toBePrinted() const override
hint whether we should print that counter or not.
std::decay_t< std::result_of_t< Identity(unsigned long)>> OutputType
virtual bool toBePrinted() const override
hint whether we should print that counter or not.
static constexpr OutputType getValue(const InternalType &v) noexcept
static constexpr OutputType DefaultValue()
PropertyMgr & operator=(const PropertyMgr &)=delete
std::ostream & print(std::ostream &o, bool tableFormat=false) const override
prints the counter to a stream
StatEntity & operator++()
static constexpr OutputType DefaultValue()
PrintableCounter(OWNER *o, const std::string &tag)
GenericAccumulator operator+=(const InputType by)
void accumulate(Counter &counter, const Container &container, Fun f=Identity{})
A helper function for accumulating data from a container into a counter This is internally using buff...
std::conditional_t< std::is_integral< Arithmetic >::value, Result, Arithmetic > fp_result_type
type_trait for the result type of a floating point operation on the type Arithmetic ...
static void add(InternalType &a, T b, std::false_type)
virtual bool toBePrinted() const
hint whether we should print that counter or not.
static Arithmetic exchange(InternalType &v, Arithmetic newv) noexcept
auto efficiencyErr() const
unsigned int operator()(bool v) const
AccumulatorSet & operator+=(const InputType by)
StatEntity & operator-=(double by)
StatEntity(OWNER *o, const std::string &tag)
Buffer is a non atomic Accumulator which, when it goes out-of-scope, updates the underlying thread-sa...
Buffer< Arithmetic, Accumulator > buffer()
virtual std::ostream & print(std::ostream &o, const std::string &tag) const override
prints the counter to a stream in table format, with the given tag
std::ostream & print(std::ostream &o, bool tableFormat, const std::string &name, bool flag=true, std::string fmtHead="%|-48.48s|%|27t|") const
virtual std::ostream & print(std::ostream &, bool tableFormat=false) const =0
prints the counter to a stream
auto standard_deviation() const
GenericAccumulator & operator=(const GenericAccumulator &other)
std::string toString() const
get a string representation
A counter aiming at computing average and sum2 / variance / standard deviation.
auto unbiased_sample_variance() const
void mergeAndReset(GenericAccumulator< InputType, InnerType, ato, InputTransform, OutputTransform, VH > &&other)
std::ostream & print(std::ostream &o, bool tableFormat=false) const override
prints the counter to a stream
AccumulatorSet is an Accumulator that holds a set of Accumulators templated by same Arithmetic and At...
virtual bool toBePrinted() const override
hint whether we should print that counter or not.
StatEntity & operator+=(StatEntity by)
AccumulatorSet< Arithmetic, Atomicity, SigmaAccumulator, MinAccumulator, MaxAccumulator > StatAccumulator
StatAccumulator.
StatEntity & operator--()
void reset(const std::tuple< typename Bases< Arithmetic, Atomicity >::OutputType... > &t)
A counter dealing with binomial data.
static bool effCounter(const std::string &name)
virtual Out operator()(const vector_of_const_< In > &inputs) const =0
ValueHandler::InternalType m_value
static constexpr OutputType DefaultValue()
std::ostream & operator<<(std::ostream &stream, const PrintableCounter &counter)
external printout operator to std::ostream
helper functor for the TrueAccumulator
helper functor for the FalseAccumulator
unsigned long addFlag(const double v)
Base type for all functors used as ValuesHandler.
GenericAccumulator(const GenericAccumulator &other)
std::ostream & print(std::ostream &o, bool tableFormat=false) const override
prints the counter to a stream
A basic counter counting input values.
T compare_exchange_weak(T...args)
static constexpr OutputType DefaultValue()
static void merge(InternalType &a, Arithmetic b) noexcept
static void merge(InternalType &a, Arithmetic b) noexcept
static Arithmetic exchange(InternalType &v, Arithmetic newv) noexcept
StatEntity(const unsigned long entries, const double flag, const double flag2, const double minFlag, const double maxFlag)
static constexpr OutputType getValue(const InternalType &v) noexcept
backward compatible StatEntity class.
StatEntity operator--(int)
StatEntity & operator+=(double by)
ContainedAccumulator< Arithmetic, atomicity::none > base_type
An Extremum ValueHandler, to be reused for Minimum and Maximum operator(a, b) means if (Compare(b...
std::ostream & print(std::ostream &o, bool tableFormat=false) const override
prints the counter to a stream
unsigned int operator()(bool v) const
Generic Accumulator, templated by.
Helper functions to set/get the application return code.
void operator=(double by)
unsigned long add(const double v)