1 #ifndef GENESIS_UTILS_MATH_STATISTICS_H_
2 #define GENESIS_UTILS_MATH_STATISTICS_H_
58 std::numeric_limits<double>::is_iec559,
59 "IEC 559/IEEE 754 floating-point types required (wrong double type)."
62 std::numeric_limits<double>::has_infinity,
63 "IEC 559/IEEE 754 floating-point types required (does not have infinity)."
66 std::numeric_limits<double>::has_quiet_NaN,
67 "IEC 559/IEEE 754 floating-point types required (does not have quite NaN)."
70 - std::numeric_limits<double>::infinity() < std::numeric_limits<double>::lowest(),
71 "IEC 559/IEEE 754 floating-point types required (infinity is not the lowest value)."
81 std::isinf( - std::numeric_limits<double>::infinity() ),
82 "IEC 559/IEEE 754 floating-point types required (infinity is not working properly)."
85 std::isinf( -1 * std::numeric_limits<double>::infinity()),
86 "IEC 559/IEEE 754 floating-point types required."
89 -1 * std::numeric_limits<double>::infinity() < std::numeric_limits<double>::lowest(),
90 "IEC 559/IEEE 754 floating-point types required."
104 template<
typename T >
149 template <
class ForwardIterator>
157 while( first != last ) {
158 if( std::isfinite( *first ) ) {
165 return { valid, total };
174 template <
class ForwardIterator>
178 double min = std::numeric_limits<double>::max();
182 while( first != last ) {
183 if( std::isfinite( *first ) ) {
194 return std::numeric_limits<double>::quiet_NaN();
206 template <
class ForwardIterator>
210 double max = std::numeric_limits<double>::lowest();
214 while( first != last ) {
215 if( std::isfinite( *first ) ) {
226 return std::numeric_limits<double>::quiet_NaN();
238 template <
class ForwardIterator>
243 result.
min = std::numeric_limits<double>::max();
244 result.
max = std::numeric_limits<double>::lowest();
248 while( first != last ) {
249 if( std::isfinite( *first ) ) {
250 if( *first < result.
min ) {
253 if( *first > result.
max ) {
263 result.
min = std::numeric_limits<double>::quiet_NaN();
264 result.
max = std::numeric_limits<double>::quiet_NaN();
287 template <
class ForwardIterator>
288 void closure( ForwardIterator first, ForwardIterator last )
296 while( it != last ) {
297 if( std::isfinite( *it ) ) {
299 throw std::invalid_argument(
300 "Cannot calculate closure of negative numbers."
317 while( it != last ) {
318 if( std::isfinite( *it ) ) {
330 inline void closure( std::vector<double>& vec )
332 return closure( vec.begin(), vec.end() );
357 template <
class ForwardIterator>
368 while( it != last ) {
369 if( std::isfinite( *it ) ) {
382 result.
mean /=
static_cast<double>( count );
386 while( it != last ) {
387 if( std::isfinite( *it ) ) {
393 result.
stddev /=
static_cast<double>( count );
398 assert( result.
stddev >= 0.0 );
399 if( result.
stddev <= epsilon ){
415 return mean_stddev( vec.begin(), vec.end(), epsilon );
437 template <
class ForwardIterator>
446 while( it != last ) {
447 if( std::isfinite( *it ) ) {
456 assert(
mean == 0.0 );
462 return mean /
static_cast<double>( count );
495 template <
class ForwardIterator>
497 ForwardIterator first_value, ForwardIterator last_value,
498 ForwardIterator first_weight, ForwardIterator last_weight
506 first_value, last_value,
507 first_weight, last_weight,
508 [&](
double value,
double weight ){
510 throw std::invalid_argument(
511 "Cannot calculate weighted arithmetic mean with negative weights."
515 num += weight * value;
526 throw std::invalid_argument(
527 "Cannot calculate weighted arithmetic mean with all weights being 0."
534 return ( num / den );
548 std::vector<double>
const& values,
549 std::vector<double>
const& weights
573 template <
class ForwardIterator>
582 while( it != last ) {
583 if( std::isfinite( *it ) ) {
585 throw std::invalid_argument(
586 "Cannot calculate geometric mean of non-positive numbers."
589 sum += std::log( *it );
602 assert( std::isfinite(
sum ));
603 return std::exp(
sum /
static_cast<double>( count ));
648 template <
class ForwardIterator>
650 ForwardIterator first_value, ForwardIterator last_value,
651 ForwardIterator first_weight, ForwardIterator last_weight
659 first_value, last_value,
660 first_weight, last_weight,
661 [&](
double value,
double weight ){
663 throw std::invalid_argument(
664 "Cannot calculate weighted geometric mean of non-positive values."
668 throw std::invalid_argument(
669 "Cannot calculate weighted geometric mean with negative weights."
673 num += weight * std::log( value );
684 throw std::invalid_argument(
685 "Cannot calculate weighted geometric mean with all weights being 0."
691 assert( std::isfinite( num ));
692 assert( std::isfinite( den ) && ( den > 0.0 ));
693 return std::exp( num / den );
707 std::vector<double>
const& values,
708 std::vector<double>
const& weights
774 template <
class ForwardIterator>
776 ForwardIterator first, ForwardIterator last,
789 while( it != last ) {
790 if( std::isfinite( *it ) ) {
792 throw std::invalid_argument(
793 "Cannot calculate harmonic mean of negative values."
798 sum += 1.0 /
static_cast<double>( *it );
801 assert( *it == 0.0 );
802 switch( zero_policy ) {
804 throw std::invalid_argument(
805 "Zero value found when calculating harmonic mean."
829 if( count == 0 || count == zeroes ) {
833 assert( count > zeroes );
834 assert( std::isfinite(
sum ));
838 auto const correction =
static_cast<double>( count - zeroes ) /
static_cast<double>( count );
839 return correction *
static_cast<double>( count - zeroes ) /
sum;
850 std::vector<double>
const& vec,
883 template <
class ForwardIterator>
885 ForwardIterator first_value, ForwardIterator last_value,
886 ForwardIterator first_weight, ForwardIterator last_weight,
893 double weights = 0.0;
901 first_value, last_value,
902 first_weight, last_weight,
903 [&](
double value,
double weight ){
905 throw std::invalid_argument(
906 "Cannot calculate weighted harmonic mean of negative values."
910 throw std::invalid_argument(
911 "Cannot calculate weighted harmonic mean with negative weights."
917 den += weight /
static_cast<double>( value );
920 assert( value == 0.0 );
921 switch( zero_policy ) {
923 throw std::invalid_argument(
924 "Zero value found when calculating weighted harmonic mean."
949 if( count == 0 || count == zeroes ) {
956 if( num == 0.0 || den == 0.0 ) {
957 throw std::invalid_argument(
958 "Cannot calculate weighted harmonic mean with all weights being 0."
963 assert( weights == num );
966 assert( count > zeroes );
967 assert( weights >= num );
968 assert( std::isfinite( num ) && ( num > 0.0 ));
969 assert( std::isfinite( den ) && ( den > 0.0 ));
970 assert( std::isfinite( weights ) && ( weights > 0.0 ));
974 auto const correction = num / weights;
975 return correction * num / den;
989 std::vector<double>
const& values,
990 std::vector<double>
const& weights,
994 values.begin(), values.end(),
995 weights.begin(), weights.end(),
1013 template <
class RandomAccessIterator>
1014 double median( RandomAccessIterator first, RandomAccessIterator last )
1017 if( ! std::is_sorted( first, last )) {
1018 throw std::runtime_error(
"Range has to be sorted for median calculation." );
1020 auto const size =
static_cast<size_t>( std::distance( first, last ));
1026 if( size % 2 == 0 ) {
1029 size_t pl = size / 2 - 1;
1030 size_t pu = size / 2;
1031 assert( pl < size && pu < size );
1033 return ( *(first + pl) + *(first + pu) ) / 2.0;
1038 size_t p = size / 2;
1041 return *(first + p);
1050 inline double median( std::vector<double>
const& vec )
1052 return median( vec.begin(), vec.end() );
1065 template <
class RandomAccessIterator>
1072 if( ! std::is_sorted( first, last )) {
1073 throw std::runtime_error(
"Range has to be sorted for quartiles calculation." );
1075 auto const size =
static_cast<size_t>( std::distance( first, last ));
1083 result.
q4 = *(first + size - 1);
1087 if( size % 2 == 0 ) {
1090 result.
q1 =
median( first, first + size / 2 );
1091 result.
q3 =
median( first + size / 2, first + size );
1096 result.
q1 =
median( first, first + size / 2 );
1097 result.
q3 =
median( first + size / 2 + 1, first + size );
1110 return quartiles( vec.begin(), vec.end() );
1135 auto res = std::vector<double>( ms.size() );
1136 for(
size_t i = 0; i < ms.size(); ++i ) {
1161 auto res = std::vector<double>( ms.size() );
1162 for(
size_t i = 0; i < ms.size(); ++i ) {
1177 return ( q.
q3 - q.
q1 ) / ( q.
q3 + q.
q1 );
1185 auto res = std::vector<double>( q.size() );
1186 for(
size_t i = 0; i < q.size(); ++i ) {
1195 #endif // include guard