diff options
Diffstat (limited to '3rdparty/benchmark/src/stat.h')
-rw-r--r-- | 3rdparty/benchmark/src/stat.h | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/3rdparty/benchmark/src/stat.h b/3rdparty/benchmark/src/stat.h new file mode 100644 index 00000000000..c4ecfe8e044 --- /dev/null +++ b/3rdparty/benchmark/src/stat.h @@ -0,0 +1,307 @@ +#ifndef BENCHMARK_STAT_H_ +#define BENCHMARK_STAT_H_ + +#include <cmath> +#include <limits> +#include <ostream> +#include <type_traits> + + +namespace benchmark { + +template <typename VType, typename NumType> +class Stat1; + +template <typename VType, typename NumType> +class Stat1MinMax; + +typedef Stat1<float, int64_t> Stat1_f; +typedef Stat1<double, int64_t> Stat1_d; +typedef Stat1MinMax<float, int64_t> Stat1MinMax_f; +typedef Stat1MinMax<double, int64_t> Stat1MinMax_d; + +template <typename VType> +class Vector2; +template <typename VType> +class Vector3; +template <typename VType> +class Vector4; + +template <typename VType, typename NumType> +class Stat1 { + public: + typedef Stat1<VType, NumType> Self; + + Stat1() { Clear(); } + // Create a sample of value dat and weight 1 + explicit Stat1(const VType &dat) { + sum_ = dat; + sum_squares_ = Sqr(dat); + numsamples_ = 1; + } + // Create statistics for all the samples between begin (included) + // and end(excluded) + explicit Stat1(const VType *begin, const VType *end) { + Clear(); + for (const VType *item = begin; item < end; ++item) { + (*this) += Stat1(*item); + } + } + // Create a sample of value dat and weight w + Stat1(const VType &dat, const NumType &w) { + sum_ = w * dat; + sum_squares_ = w * Sqr(dat); + numsamples_ = w; + } + // Copy operator + Stat1(const Self &stat) { + sum_ = stat.sum_; + sum_squares_ = stat.sum_squares_; + numsamples_ = stat.numsamples_; + } + + void Clear() { + numsamples_ = NumType(); + sum_squares_ = sum_ = VType(); + } + + Self &operator=(const Self &stat) { + sum_ = stat.sum_; + sum_squares_ = stat.sum_squares_; + numsamples_ = stat.numsamples_; + return (*this); + } + // Merge statistics from two sample sets. + Self &operator+=(const Self &stat) { + sum_ += stat.sum_; + sum_squares_ += stat.sum_squares_; + numsamples_ += stat.numsamples_; + return (*this); + } + // The operation opposite to += + Self &operator-=(const Self &stat) { + sum_ -= stat.sum_; + sum_squares_ -= stat.sum_squares_; + numsamples_ -= stat.numsamples_; + return (*this); + } + // Multiply the weight of the set of samples by a factor k + Self &operator*=(const VType &k) { + sum_ *= k; + sum_squares_ *= k; + numsamples_ *= k; + return (*this); + } + + // Merge statistics from two sample sets. + Self operator+(const Self &stat) const { return Self(*this) += stat; } + + // The operation opposite to + + Self operator-(const Self &stat) const { return Self(*this) -= stat; } + + // Multiply the weight of the set of samples by a factor k + Self operator*(const VType &k) const { return Self(*this) *= k; } + + // Return the total weight of this sample set + NumType numSamples() const { return numsamples_; } + + // Return the sum of this sample set + VType Sum() const { return sum_; } + + // Return the mean of this sample set + VType Mean() const { + if (numsamples_ == 0) return VType(); + return sum_ * (1.0 / numsamples_); + } + + // Return the mean of this sample set and compute the standard deviation at + // the same time. + VType Mean(VType *stddev) const { + if (numsamples_ == 0) return VType(); + VType mean = sum_ * (1.0 / numsamples_); + if (stddev) { + VType avg_squares = sum_squares_ * (1.0 / numsamples_); + *stddev = Sqrt(avg_squares - Sqr(mean)); + } + return mean; + } + + // Return the standard deviation of the sample set + VType StdDev() const { + if (numsamples_ == 0) return VType(); + VType mean = Mean(); + VType avg_squares = sum_squares_ * (1.0 / numsamples_); + return Sqrt(avg_squares - Sqr(mean)); + } + + private: + static_assert(std::is_integral<NumType>::value && + !std::is_same<NumType, bool>::value, + "NumType must be an integral type that is not bool."); + // Let i be the index of the samples provided (using +=) + // and weight[i],value[i] be the data of sample #i + // then the variables have the following meaning: + NumType numsamples_; // sum of weight[i]; + VType sum_; // sum of weight[i]*value[i]; + VType sum_squares_; // sum of weight[i]*value[i]^2; + + // Template function used to square a number. + // For a vector we square all components + template <typename SType> + static inline SType Sqr(const SType &dat) { + return dat * dat; + } + + template <typename SType> + static inline Vector2<SType> Sqr(const Vector2<SType> &dat) { + return dat.MulComponents(dat); + } + + template <typename SType> + static inline Vector3<SType> Sqr(const Vector3<SType> &dat) { + return dat.MulComponents(dat); + } + + template <typename SType> + static inline Vector4<SType> Sqr(const Vector4<SType> &dat) { + return dat.MulComponents(dat); + } + + // Template function used to take the square root of a number. + // For a vector we square all components + template <typename SType> + static inline SType Sqrt(const SType &dat) { + // Avoid NaN due to imprecision in the calculations + if (dat < 0) return 0; + return sqrt(dat); + } + + template <typename SType> + static inline Vector2<SType> Sqrt(const Vector2<SType> &dat) { + // Avoid NaN due to imprecision in the calculations + return Max(dat, Vector2<SType>()).Sqrt(); + } + + template <typename SType> + static inline Vector3<SType> Sqrt(const Vector3<SType> &dat) { + // Avoid NaN due to imprecision in the calculations + return Max(dat, Vector3<SType>()).Sqrt(); + } + + template <typename SType> + static inline Vector4<SType> Sqrt(const Vector4<SType> &dat) { + // Avoid NaN due to imprecision in the calculations + return Max(dat, Vector4<SType>()).Sqrt(); + } +}; + +// Useful printing function +template <typename VType, typename NumType> +std::ostream &operator<<(std::ostream &out, const Stat1<VType, NumType> &s) { + out << "{ avg = " << s.Mean() << " std = " << s.StdDev() + << " nsamples = " << s.NumSamples() << "}"; + return out; +} + +// Stat1MinMax: same as Stat1, but it also +// keeps the Min and Max values; the "-" +// operator is disabled because it cannot be implemented +// efficiently +template <typename VType, typename NumType> +class Stat1MinMax : public Stat1<VType, NumType> { + public: + typedef Stat1MinMax<VType, NumType> Self; + + Stat1MinMax() { Clear(); } + // Create a sample of value dat and weight 1 + explicit Stat1MinMax(const VType &dat) : Stat1<VType, NumType>(dat) { + max_ = dat; + min_ = dat; + } + // Create statistics for all the samples between begin (included) + // and end(excluded) + explicit Stat1MinMax(const VType *begin, const VType *end) { + Clear(); + for (const VType *item = begin; item < end; ++item) { + (*this) += Stat1MinMax(*item); + } + } + // Create a sample of value dat and weight w + Stat1MinMax(const VType &dat, const NumType &w) + : Stat1<VType, NumType>(dat, w) { + max_ = dat; + min_ = dat; + } + // Copy operator + Stat1MinMax(const Self &stat) : Stat1<VType, NumType>(stat) { + max_ = stat.max_; + min_ = stat.min_; + } + + void Clear() { + Stat1<VType, NumType>::Clear(); + if (std::numeric_limits<VType>::has_infinity) { + min_ = std::numeric_limits<VType>::infinity(); + max_ = -std::numeric_limits<VType>::infinity(); + } else { + min_ = std::numeric_limits<VType>::max(); + max_ = std::numeric_limits<VType>::min(); + } + } + + Self &operator=(const Self &stat) { + this->Stat1<VType, NumType>::operator=(stat); + max_ = stat.max_; + min_ = stat.min_; + return (*this); + } + // Merge statistics from two sample sets. + Self &operator+=(const Self &stat) { + this->Stat1<VType, NumType>::operator+=(stat); + if (stat.max_ > max_) max_ = stat.max_; + if (stat.min_ < min_) min_ = stat.min_; + return (*this); + } + // Multiply the weight of the set of samples by a factor k + Self &operator*=(const VType &stat) { + this->Stat1<VType, NumType>::operator*=(stat); + return (*this); + } + // Merge statistics from two sample sets. + Self operator+(const Self &stat) const { return Self(*this) += stat; } + // Multiply the weight of the set of samples by a factor k + Self operator*(const VType &k) const { return Self(*this) *= k; } + + // Return the maximal value in this sample set + VType Max() const { return max_; } + // Return the minimal value in this sample set + VType Min() const { return min_; } + + private: + // The - operation makes no sense with Min/Max + // unless we keep the full list of values (but we don't) + // make it private, and let it undefined so nobody can call it + Self &operator-=(const Self &stat); // senseless. let it undefined. + + // The operation opposite to - + Self operator-(const Self &stat) const; // senseless. let it undefined. + + // Let i be the index of the samples provided (using +=) + // and weight[i],value[i] be the data of sample #i + // then the variables have the following meaning: + VType max_; // max of value[i] + VType min_; // min of value[i] +}; + +// Useful printing function +template <typename VType, typename NumType> +std::ostream &operator<<(std::ostream &out, + const Stat1MinMax<VType, NumType> &s) { + out << "{ avg = " << s.Mean() << " std = " << s.StdDev() + << " nsamples = " << s.NumSamples() << " min = " << s.Min() + << " max = " << s.Max() << "}"; + return out; +} +} // end namespace benchmark + +#endif // BENCHMARK_STAT_H_ |