#pragma once
#include <cmath>
#include <chrono>

struct Stats {
  using TimeBullshit = std::chrono::time_point<std::chrono::high_resolution_clock>;

  double sum = 0.0;
  double sumsq = 0.0;
  double n = 0.0;
  double min = 0.0;
  double max = 0.0;

  inline void reset() {
    sum = 0.0;
    sumsq = 0.0;
    n = 0.0;
    min = 0.0;
    max = 0.0;
  }

  inline double mean() {
    return sum / n;
  }

  inline double stddev() {
    return std::sqrt((sumsq - (sum * sum / n)) / (n - 1));
  }

  inline void sample(double s) {
    sum += s;
    sumsq += s * s;

    if (n == 0) {
      min = s;
      max = s;
    } else {
      if (min > s) min = s;
      if (max < s) max = s;
    }

    n += 1;
  }

  inline TimeBullshit time_start() {
    return std::chrono::high_resolution_clock::now();
  }

  inline void sample_time(TimeBullshit start) {
    auto end = std::chrono::high_resolution_clock::now();
    auto elapsed = std::chrono::duration<double>(end - start);
    sample(1/elapsed.count());
  }

  void dump(std::string msg="");
};
