26#ifndef GUL17_STATISTICS_H_
27#define GUL17_STATISTICS_H_
61template <
typename ElementT>
81 DataT min{ std::numeric_limits<DataT>::max() };
82 DataT max{ std::numeric_limits<DataT>::lowest() };
85template <
typename DataT>
86struct MinMax<
DataT, std::
enable_if_t<std::is_floating_point<DataT>::value>> {
165 typename ElementT =
typename ContainerT::value_type,
167 typename DataT =
typename std::decay_t<std::invoke_result_t<Accessor, ElementT>>,
168 typename = std::enable_if_t<IsContainerLike<ContainerT>::value>
172 auto const sum = std::accumulate(
176 return accu + static_cast<ResultT>(accessor(el)); } );
203 typename ElementT =
typename ContainerT::value_type,
205 typename DataT =
typename std::decay_t<std::invoke_result_t<Accessor, ElementT>>,
206 typename = std::enable_if_t<IsContainerLike<ContainerT>::value>
210 auto const sum = std::accumulate(
214 return accu + std::pow(static_cast<ResultT>(accessor(el)), 2); } );
244 typename ElementT =
typename ContainerT::value_type,
246 typename DataT =
typename std::decay_t<std::invoke_result_t<Accessor, ElementT>>,
247 typename = std::enable_if_t<IsContainerLike<ContainerT>::value>
253 return std::numeric_limits<ResultT>::quiet_NaN();
312 typename ElementT =
typename ContainerT::value_type,
314 typename DataT =
typename std::decay_t<std::invoke_result_t<Accessor, ElementT>>,
315 typename = std::enable_if_t<IsContainerLike<ContainerT>::value>
319 constexpr auto initial_value = std::numeric_limits<DataT>::has_quiet_NaN ?
320 std::numeric_limits<DataT>::quiet_NaN() : std::numeric_limits<DataT>::lowest();
322 return std::accumulate(
325 auto const val = accessor(el);
329 if (not (val <= accu))
365template <
typename ContainerT,
366 typename ElementT =
typename ContainerT::value_type,
367 typename Accessor = std::invoke_result_t<decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
368 typename DataT =
typename std::decay_t<std::invoke_result_t<Accessor, ElementT>>,
369 typename = std::enable_if_t<IsContainerLike<ContainerT>::value>
371auto minimum(ContainerT
const& container, Accessor accessor = ElementAccessor<ElementT>()) -> DataT
373 constexpr auto initial_value = std::numeric_limits<DataT>::has_quiet_NaN ?
374 std::numeric_limits<DataT>::quiet_NaN() : std::numeric_limits<DataT>::max();
376 return std::accumulate(
377 container.cbegin(), container.cend(), initial_value,
378 [&accessor](DataT
const& accu, ElementT
const& el) -> DataT {
379 auto const val = accessor(el);
383 if (not (val >= accu))
424template <
typename ContainerT,
425 typename ElementT =
typename ContainerT::value_type,
426 typename Accessor = std::invoke_result_t<decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
427 typename DataT =
typename std::decay_t<std::invoke_result_t<Accessor, ElementT>>,
428 typename = std::enable_if_t<IsContainerLike<ContainerT>::value>
433 auto const sum = std::accumulate(
434 container.cbegin(), container.cend(),
436 [accessor] (MinMaxT
const& accu, ElementT
const& el) -> MinMaxT {
438 auto const val = accessor(el);
443 if (not (val >= out.min))
445 if (not (val <= out.max))
472template <
typename ContainerT,
473 typename ElementT =
typename ContainerT::value_type,
474 typename Accessor = std::invoke_result_t<decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
475 typename DataT =
typename std::decay_t<std::invoke_result_t<Accessor, ElementT>>,
476 typename = std::enable_if_t<IsContainerLike<ContainerT>::value>
479 Accessor accessor = ElementAccessor<ElementT>()) -> ContainerT&
481 while (outliers-- > 0 and cont.size() > 0) {
482 auto max_distant = std::max_element(cont.begin(), cont.end(),
483 [
mean =
mean(cont, accessor), accessor] (ElementT
const& a, ElementT
const& b)
484 {
return std::abs(accessor(a) -
mean) < std::abs(accessor(b) -
mean); });
485 cont.erase(max_distant);
496template <
typename ContainerT,
497 typename ElementT =
typename ContainerT::value_type,
498 typename Accessor = std::invoke_result_t<decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
499 typename DataT =
typename std::decay_t<std::invoke_result_t<Accessor, ElementT>>,
500 typename = std::enable_if_t<IsContainerLike<ContainerT>::value>
503 Accessor accessor = ElementAccessor<ElementT>()) -> std::vector<ElementT>
505 auto c = std::vector<ElementT>(cont.size());
506 std::copy(cont.cbegin(), cont.cend(), c.begin());
548template <
typename ResultT = statistics_result_type,
550 typename ElementT =
typename ContainerT::value_type,
551 typename Accessor = std::invoke_result_t<decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
552 typename DataT =
typename std::decay_t<std::invoke_result_t<Accessor, ElementT>>,
553 typename = std::enable_if_t<IsContainerLike<ContainerT>::value>
557 auto const len = container.size();
562 auto mean_val = mean<ResultT>(container, accessor);
565 return { std::numeric_limits<ResultT>::quiet_NaN(), mean_val };
567 auto sum = std::accumulate(container.cbegin(), container.cend(),
569 [mean_val, accessor] (ResultT
const& accu, ElementT
const& el)
570 { return accu + std::pow(static_cast<ResultT>(accessor(el)) - mean_val, 2); });
572 sum /=
static_cast<ResultT
>(container.size() - 1);
574 return { std::sqrt(sum), mean_val };
601template <
typename ResultT = statistics_result_type,
603 typename ElementT =
typename ContainerT::value_type,
604 typename Accessor = std::invoke_result_t<decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
605 typename DataT =
typename std::decay_t<std::invoke_result_t<Accessor, ElementT>>,
607 typename = std::enable_if_t<IsContainerLike<ContainerT>::value>
609auto accumulate(ContainerT
const& container, OpClosure op, Accessor accessor = ElementAccessor<ElementT>()) -> ResultT
611 auto const sum = std::accumulate(
612 container.cbegin(), container.cend(),
614 [accessor, op] (ResultT
const& accu, ElementT
const& el) {
615 return op(accu, accessor(el)); } );
623 template <
typename IteratorT>
624 struct ContainerView {
625 IteratorT
const& begin_;
626 IteratorT
const& end_;
627 using value_type = std::decay_t<
decltype(*begin_)>;
629 ContainerView(IteratorT
const& i1, IteratorT
const& i2)
637 auto cbegin() const noexcept -> IteratorT const&
641 auto cend() const noexcept -> IteratorT const&
646 auto size() const noexcept -> std::
size_t
648 return static_cast<std::size_t
>(std::distance(begin_, end_));
652 template<
typename IteratorT>
653 auto make_view(IteratorT
const& cbegin, IteratorT
const& cend) -> ContainerView<IteratorT>
const
655 return ContainerView<IteratorT>{ cbegin, cend };
671 typename ElementT = std::decay_t<decltype(*std::declval<IteratorT>())>,
672 typename Accessor = std::invoke_result_t<
decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
673 typename DataT = std::decay_t<std::invoke_result_t<Accessor, ElementT>>>
674auto mean(IteratorT
const& begin, IteratorT
const& end,
675 Accessor accessor = ElementAccessor<ElementT>()) -> ResultT
677 return mean<ResultT>(make_view(begin, end), accessor);
689template <
typename ResultT = statistics_result_type,
691 typename ElementT = std::decay_t<decltype(*std::declval<IteratorT>())>,
692 typename Accessor = std::invoke_result_t<
decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
693 typename DataT = std::decay_t<std::invoke_result_t<Accessor, ElementT>>>
694auto rms(IteratorT
const& begin, IteratorT
const& end,
695 Accessor accessor = ElementAccessor<ElementT>()) -> ResultT
697 return rms<ResultT>(make_view(begin, end), accessor);
709template <
typename ResultT = statistics_result_type,
711 typename ElementT = std::decay_t<decltype(*std::declval<IteratorT>())>,
712 typename Accessor = std::invoke_result_t<
decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
713 typename DataT = std::decay_t<std::invoke_result_t<Accessor, ElementT>>>
714auto median(IteratorT
const& begin, IteratorT
const& end,
715 Accessor accessor = ElementAccessor<ElementT>()) -> ResultT
717 return median<ResultT>(make_view(begin, end), accessor);
729template <
typename IteratorT,
730 typename ElementT = std::decay_t<decltype(*std::declval<IteratorT>())>,
731 typename Accessor = std::invoke_result_t<
decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
732 typename DataT = std::decay_t<std::invoke_result_t<Accessor, ElementT>>>
733 auto maximum(IteratorT
const& begin, IteratorT
const& end,
734 Accessor accessor = ElementAccessor<ElementT>()) -> DataT
736 return maximum(make_view(begin, end), accessor);
748template <
typename IteratorT,
749 typename ElementT = std::decay_t<decltype(*std::declval<IteratorT>())>,
750 typename Accessor = std::invoke_result_t<
decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
751 typename DataT = std::decay_t<std::invoke_result_t<Accessor, ElementT>>>
752 auto minimum(IteratorT
const& begin, IteratorT
const& end,
753 Accessor accessor = ElementAccessor<ElementT>()) -> DataT
755 return minimum(make_view(begin, end), accessor);
767template <
typename IteratorT,
768 typename ElementT = std::decay_t<decltype(*std::declval<IteratorT>())>,
769 typename Accessor = std::invoke_result_t<
decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
770 typename DataT = std::decay_t<std::invoke_result_t<Accessor, ElementT>>>
771auto min_max(IteratorT
const& begin, IteratorT
const& end,
772 Accessor accessor = ElementAccessor<ElementT>()) ->
MinMax<DataT>
774 return min_max(make_view(begin, end), accessor);
788template <
typename IteratorT,
789 typename ElementT = std::decay_t<decltype(*std::declval<IteratorT>())>,
790 typename Accessor = std::invoke_result_t<
decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
791 typename DataT = std::decay_t<std::invoke_result_t<Accessor, ElementT>>>
793 std::size_t outliers, Accessor accessor = ElementAccessor<ElementT>()) -> std::vector<ElementT>
808template <
typename ResultT = statistics_result_type,
810 typename ElementT = std::decay_t<decltype(*std::declval<IteratorT>())>,
811 typename Accessor = std::invoke_result_t<
decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
812 typename DataT = std::decay_t<std::invoke_result_t<Accessor, ElementT>>>
816 return standard_deviation<ResultT>(make_view(begin, end), accessor);
830template <
typename ResultT = statistics_result_type,
832 typename ElementT = std::decay_t<decltype(*std::declval<IteratorT>())>,
833 typename Accessor = std::invoke_result_t<
decltype(ElementAccessor<ElementT>()), ElementT>(*)(ElementT
const&),
834 typename DataT = std::decay_t<std::invoke_result_t<Accessor, ElementT>>,
836auto accumulate(IteratorT
const& begin, IteratorT
const& end, OpClosure op,
837 Accessor accessor = ElementAccessor<ElementT>()) -> ResultT
839 return accumulate<ResultT>(make_view(begin, end), op, accessor);
A struct holding a standard deviation and a mean value.
Definition statistics.h:108
auto constexpr bit_set(unsigned bit) noexcept -> ReturnT
Set a bit in an integral type.
Definition bit_manip.h:124
auto min_max(ContainerT const &container, Accessor accessor=ElementAccessor< ElementT >()) -> MinMax< DataT >
Find the minimum and maximum element values in a container.
Definition statistics.h:430
auto minimum(ContainerT const &container, Accessor accessor=ElementAccessor< ElementT >()) -> DataT
Return the minimum element value in a container.
Definition statistics.h:371
DataT sigma_
The standard deviation (sigma) value.
Definition statistics.h:110
auto rms(ContainerT const &container, Accessor accessor=ElementAccessor< ElementT >()) -> ResultT
Calculate the root mean square of all elements in a container.
Definition statistics.h:208
double statistics_result_type
Type used to return statistic properties.
Definition statistics.h:47
DataT max
Maximum value.
Definition statistics.h:82
auto median(ContainerT const &container, Accessor accessor=ElementAccessor< ElementT >()) -> ResultT
Find the median of all elements in a container.
Definition statistics.h:249
auto remove_outliers(ContainerT &&cont, std::size_t outliers, Accessor accessor=ElementAccessor< ElementT >()) -> ContainerT &
Remove elements that are far away from other elements.
Definition statistics.h:478
auto accumulate(ContainerT const &container, OpClosure op, Accessor accessor=ElementAccessor< ElementT >()) -> ResultT
Calculate some aggregate value from all elements of a container.
Definition statistics.h:609
auto standard_deviation(ContainerT const &container, Accessor accessor=ElementAccessor< ElementT >()) -> StandardDeviationMean< ResultT >
Calculate the standard deviation of all elements in a container.
Definition statistics.h:555
auto sigma() const noexcept -> DataT
Get the standard deviation value.
Definition statistics.h:129
DataT mean_
The mean value.
Definition statistics.h:111
auto mean(ContainerT const &container, Accessor accessor=ElementAccessor< ElementT >()) -> ResultT
Calculate the arithmetic mean value of all elements in a container.
Definition statistics.h:170
auto ElementAccessor()
Return a mock element accessor for containers.
Definition statistics.h:62
auto mean() const noexcept -> DataT
Get the arithmetic mean value.
Definition statistics.h:133
auto maximum(ContainerT const &container, Accessor accessor=ElementAccessor< ElementT >()) -> DataT
Return the maximum element value in a container.
Definition statistics.h:317
DataT min
Minimum value.
Definition statistics.h:81
Definition of macros used internally by GUL.
Namespace gul17 contains all functions and classes of the General Utility Library.
Definition doxygen.h:29
Object that is designed to holds two values: minimum and maximum of something.
Definition statistics.h:80
Some metaprogramming traits for the General Utility Library.