/*
 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCUTIL_HPP
#define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCUTIL_HPP

#include "memory/allocation.hpp"
#include "runtime/timer.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/ostream.hpp"

// Catch-all file for utility classes

// A weighted average maintains a running, weighted average
// of some float value (templates would be handy here if we
// need different types).
//
// The average is adaptive in that we smooth it for the
// initial samples; we don't use the weight until we have
// enough samples for it to be meaningful.
//
// This serves as our best estimate of a future unknown.
//
class AdaptiveWeightedAverage : public CHeapObj<mtGC> {
 private:
  float            _average;        // The last computed average
  unsigned         _sample_count;   // How often we've sampled this average
  unsigned         _weight;         // The weight used to smooth the averages
                                    //   A higher weight favors the most
                                    //   recent data.
  bool             _is_old;         // Has enough historical data

  const static unsigned OLD_THRESHOLD = 100;

 protected:
  float            _last_sample;    // The last value sampled.

  void  increment_count() {
    _sample_count++;
    if (!_is_old && _sample_count > OLD_THRESHOLD) {
      _is_old = true;
    }
  }

  void  set_average(float avg)  { _average = avg;        }

  // Helper function, computes an adaptive weighted average
  // given a sample and the last average
  float compute_adaptive_average(float new_sample, float average);

 public:
  // Input weight must be between 0 and 100
  AdaptiveWeightedAverage(unsigned weight, float avg = 0.0) :
    _average(avg), _sample_count(0), _weight(weight), _last_sample(0.0),
    _is_old(false) {
  }

  void clear() {
    _average = 0;
    _sample_count = 0;
    _last_sample = 0;
    _is_old = false;
  }

  // Useful for modifying static structures after startup.
  void  modify(size_t avg, unsigned wt, bool force = false)  {
    assert(force, "Are you sure you want to call this?");
    _average = (float)avg;
    _weight  = wt;
  }

  // Accessors
  float    average() const       { return _average;       }
  unsigned weight()  const       { return _weight;        }
  unsigned count()   const       { return _sample_count;  }
  float    last_sample() const   { return _last_sample;   }
  bool     is_old()  const       { return _is_old;        }

  // Update data with a new sample.
  void sample(float new_sample);

  static inline float exp_avg(float avg, float sample,
                               unsigned int weight) {
    assert(0 <= weight && weight <= 100, "weight must be a percent");
    return (100.0F - weight) * avg / 100.0F + weight * sample / 100.0F;
  }
  static inline size_t exp_avg(size_t avg, size_t sample,
                               unsigned int weight) {
    // Convert to float and back to avoid integer overflow.
    return (size_t)exp_avg((float)avg, (float)sample, weight);
  }

  // Printing
  void print_on(outputStream* st) const;
  void print() const;
};


// A weighted average that includes a deviation from the average,
// some multiple of which is added to the average.
//
// This serves as our best estimate of an upper bound on a future
// unknown.
class AdaptivePaddedAverage : public AdaptiveWeightedAverage {
 private:
  float          _padded_avg;     // The last computed padded average
  float          _deviation;      // Running deviation from the average
  unsigned       _padding;        // A multiple which, added to the average,
                                  // gives us an upper bound guess.

 protected:
  void set_padded_average(float avg)  { _padded_avg = avg;  }
  void set_deviation(float dev)       { _deviation  = dev;  }

 public:
  AdaptivePaddedAverage() :
    AdaptiveWeightedAverage(0),
    _padded_avg(0.0), _deviation(0.0), _padding(0) {}

  AdaptivePaddedAverage(unsigned weight, unsigned padding) :
    AdaptiveWeightedAverage(weight),
    _padded_avg(0.0), _deviation(0.0), _padding(padding) {}

  // Placement support
  void* operator new(size_t ignored, void* p) throw() { return p; }
  // Allocator
  void* operator new(size_t size) throw() { return CHeapObj<mtGC>::operator new(size); }

  // Accessor
  float padded_average() const         { return _padded_avg; }
  float deviation()      const         { return _deviation;  }
  unsigned padding()     const         { return _padding;    }

  void clear() {
    AdaptiveWeightedAverage::clear();
    _padded_avg = 0;
    _deviation = 0;
  }

  // Override
  void  sample(float new_sample);

  // Printing
  void print_on(outputStream* st) const;
  void print() const;
};

// A weighted average that includes a deviation from the average,
// some multiple of which is added to the average.
//
// This serves as our best estimate of an upper bound on a future
// unknown.
// A special sort of padded average:  it doesn't update deviations
// if the sample is zero. The average is allowed to change. We're
// preventing the zero samples from drastically changing our padded
// average.
class AdaptivePaddedNoZeroDevAverage : public AdaptivePaddedAverage {
public:
  AdaptivePaddedNoZeroDevAverage(unsigned weight, unsigned padding) :
    AdaptivePaddedAverage(weight, padding)  {}
  // Override
  void  sample(float new_sample);

  // Printing
  void print_on(outputStream* st) const;
  void print() const;
};

// Use a least squares fit to a set of data to generate a linear
// equation.
//              y = intercept + slope * x

class LinearLeastSquareFit : public CHeapObj<mtGC> {
  double _sum_x;        // sum of all independent data points x
  double _sum_x_squared; // sum of all independent data points x**2
  double _sum_y;        // sum of all dependent data points y
  double _sum_xy;       // sum of all x * y.
  double _intercept;     // constant term
  double _slope;        // slope
  // The weighted averages are not currently used but perhaps should
  // be used to get decaying averages.
  AdaptiveWeightedAverage _mean_x; // weighted mean of independent variable
  AdaptiveWeightedAverage _mean_y; // weighted mean of dependent variable

 public:
  LinearLeastSquareFit(unsigned weight);
  void update(double x, double y);
  double y(double x);
  double slope() { return _slope; }
  // Methods to decide if a change in the dependent variable will
  // achive a desired goal.  Note that these methods are not
  // complementary and both are needed.
  bool decrement_will_decrease();
  bool increment_will_decrease();
};

class GCPauseTimer : StackObj {
  elapsedTimer* _timer;
 public:
  GCPauseTimer(elapsedTimer* timer) {
    _timer = timer;
    _timer->stop();
  }
  ~GCPauseTimer() {
    _timer->start();
  }
};

#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_GCUTIL_HPP
