/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_BASE_HISTOGRAM_INL_H_
#define ART_RUNTIME_BASE_HISTOGRAM_INL_H_

#include "histogram.h"

#include "utils.h"

#include <algorithm>
#include <cmath>
#include <limits>
#include <ostream>

namespace art {

template <class Value> inline void Histogram<Value>::AddValue(Value value) {
  CHECK_GE(value, 0.0);
  if (value >= max_) {
    Value new_max = ((value + 1) / bucket_width_ + 1) * bucket_width_;
    DCHECK_GT(new_max, max_);
    GrowBuckets(new_max);
  }

  BucketiseValue(value);
  new_values_added_ = true;
}

template <class Value>
inline Histogram<Value>::Histogram(const std::string name)
    : kAdjust(1000),
      kBucketWidth(5),
      kInitialBucketCount(10),
      bucket_width_(kBucketWidth),
      bucket_count_(kInitialBucketCount) {
  name_ = name;
  Reset();
}

template <class Value>
inline void Histogram<Value>::GrowBuckets(Value new_max) {
  while (max_ < new_max) {
    max_ += bucket_width_;
    ranges_.push_back(max_);
    frequency_.push_back(0);
    bucket_count_++;
  }
}

template <class Value> inline size_t Histogram<Value>::FindBucket(Value val) {
  // Since this is only a linear histogram, bucket index can be found simply with
  // dividing the value by the bucket width.
  DCHECK_GE(val, min_);
  DCHECK_LE(val, max_);
  size_t bucket_idx = static_cast<size_t>((double)(val - min_) / bucket_width_);
  DCHECK_GE(bucket_idx, 0ul);
  DCHECK_LE(bucket_idx, bucket_count_);
  return bucket_idx;
}

template <class Value>
inline void Histogram<Value>::BucketiseValue(Value value) {
  CHECK_LT(value, max_);
  sum_ += value;
  sum_of_squares_ += value * value;
  size_t bucket_idx = FindBucket(value);
  sample_size_++;
  if (value > max_value_added_) {
    max_value_added_ = value;
  }
  if (value < min_value_added_) {
    min_value_added_ = value;
  }
  frequency_[bucket_idx]++;
}

template <class Value> inline void Histogram<Value>::Initialize() {
  DCHECK_GT(bucket_count_, 0ul);
  size_t idx = 0;
  for (; idx < bucket_count_; idx++) {
    ranges_.push_back(min_ + static_cast<Value>(idx) * (bucket_width_));
    frequency_.push_back(0);
  }
  // Cumulative frequency and ranges has a length of 1 over frequency.
  ranges_.push_back(min_ + idx * bucket_width_);
  max_ = bucket_width_ * bucket_count_;
}

template <class Value> inline void Histogram<Value>::Reset() {
  bucket_width_ = kBucketWidth;
  bucket_count_ = kInitialBucketCount;
  max_ = bucket_width_ * bucket_count_;
  sum_of_squares_ = 0;
  sample_size_ = 0;
  min_ = 0;
  sum_ = 0;
  min_value_added_ = std::numeric_limits<Value>::max();
  max_value_added_ = std::numeric_limits<Value>::min();
  new_values_added_ = false;
  ranges_.clear();
  frequency_.clear();
  cumulative_freq_.clear();
  cumulative_perc_.clear();
  Initialize();
}

template <class Value> inline void Histogram<Value>::BuildRanges() {
  for (size_t idx = 0; idx < bucket_count_; ++idx) {
    ranges_.push_back(min_ + idx * bucket_width_);
  }
}

template <class Value> inline double Histogram<Value>::Mean() const {
  DCHECK_GT(sample_size_, 0ull);
  return static_cast<double>(sum_) / static_cast<double>(sample_size_);
}

template <class Value> inline double Histogram<Value>::Variance() const {
  DCHECK_GT(sample_size_, 0ull);
  // Using algorithms for calculating variance over a population:
  // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
  Value sum_squared = sum_ * sum_;
  double sum_squared_by_n_squared =
      static_cast<double>(sum_squared) /
      static_cast<double>(sample_size_ * sample_size_);
  double sum_of_squares_by_n =
      static_cast<double>(sum_of_squares_) / static_cast<double>(sample_size_);
  return sum_of_squares_by_n - sum_squared_by_n_squared;
}

template <class Value>
inline void Histogram<Value>::PrintBins(std::ostream &os) {
  DCHECK_GT(sample_size_, 0ull);
  DCHECK(!new_values_added_);
  size_t bin_idx = 0;
  while (bin_idx < cumulative_freq_.size()) {
    if (bin_idx > 0 &&
        cumulative_perc_[bin_idx] == cumulative_perc_[bin_idx - 1]) {
      bin_idx++;
      continue;
    }
    os << ranges_[bin_idx] << ": " << cumulative_freq_[bin_idx] << "\t"
       << cumulative_perc_[bin_idx] * 100.0 << "%\n";
    bin_idx++;
  }
}

template <class Value>
inline void Histogram<Value>::PrintConfidenceIntervals(std::ostream &os,
                                                       double interval) const {
  DCHECK_GT(interval, 0);
  DCHECK_LT(interval, 1.0);

  double per_0 = (1.0 - interval) / 2.0;
  double per_1 = per_0 + interval;
  os << Name() << ":\t";
  TimeUnit unit = GetAppropriateTimeUnit(Mean() * kAdjust);
  os << (interval * 100) << "% C.I. "
     << FormatDuration(Percentile(per_0) * kAdjust, unit);
  os << "-" << FormatDuration(Percentile(per_1) * kAdjust, unit) << " ";
  os << "Avg: " << FormatDuration(Mean() * kAdjust, unit) << " Max: ";
  os << FormatDuration(Max() * kAdjust, unit) << "\n";
}

template <class Value> inline void Histogram<Value>::BuildCDF() {
  DCHECK_EQ(cumulative_freq_.size(), 0ull);
  DCHECK_EQ(cumulative_perc_.size(), 0ull);
  uint64_t accumulated = 0;

  cumulative_freq_.push_back(accumulated);
  cumulative_perc_.push_back(0.0);
  for (size_t idx = 0; idx < frequency_.size(); idx++) {
    accumulated += frequency_[idx];
    cumulative_freq_.push_back(accumulated);
    cumulative_perc_.push_back(static_cast<double>(accumulated) /
                               static_cast<double>(sample_size_));
  }
  DCHECK_EQ(*(cumulative_freq_.end() - 1), sample_size_);
  DCHECK_EQ(*(cumulative_perc_.end() - 1), 1.0);
}

template <class Value> inline void Histogram<Value>::CreateHistogram() {
  DCHECK_GT(sample_size_, 0ull);

  // Create a histogram only if new values are added.
  if (!new_values_added_)
    return;

  // Reset cumulative values in case this is not the first time creating histogram.
  cumulative_freq_.clear();
  cumulative_perc_.clear();
  BuildCDF();
  new_values_added_ = false;
}

template <class Value>
inline double Histogram<Value>::Percentile(double per) const {
  DCHECK_GT(cumulative_perc_.size(), 0ull);
  size_t idx, upper_idx = 0, lower_idx = 0;
  for (idx = 0; idx < cumulative_perc_.size(); idx++) {
    if (per <= cumulative_perc_[idx]) {
      upper_idx = idx;
      break;
    }

    if (per >= cumulative_perc_[idx] && idx != 0 &&
        cumulative_perc_[idx] != cumulative_perc_[idx - 1]) {
      lower_idx = idx;
    }
  }

  double upper_value = static_cast<double>(ranges_[upper_idx]);
  double lower_value = static_cast<double>(ranges_[lower_idx]);

  double lower_perc = cumulative_perc_[lower_idx];
  double upper_perc = cumulative_perc_[upper_idx];

  if (per == lower_perc) {
    return lower_value;
  }
  if (per == upper_perc) {
    return upper_value;
  }
  DCHECK_GT(upper_perc, lower_perc);

  double value = lower_value + (upper_value - lower_value) *
                               (per - lower_perc) / (upper_perc - lower_perc);

  if (value < min_value_added_) {
    value = min_value_added_;
  } else if (value > max_value_added_) {
    value = max_value_added_;
  }

  return value;
}

}  // namespace art
#endif  // ART_RUNTIME_BASE_HISTOGRAM_INL_H_

