/*
 * Copyright (c) 2001, 2014, 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.
 *
 */

#include "precompiled.hpp"
#include "memory/allocation.inline.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/numberSeq.hpp"

AbsSeq::AbsSeq(double alpha) :
  _num(0), _sum(0.0), _sum_of_squares(0.0),
  _davg(0.0), _dvariance(0.0), _alpha(alpha) {
}

void AbsSeq::add(double val) {
  if (_num == 0) {
    // if the sequence is empty, the davg is the same as the value
    _davg = val;
    // and the variance is 0
    _dvariance = 0.0;
  } else {
    // otherwise, calculate both
    _davg = (1.0 - _alpha) * val + _alpha * _davg;
    double diff = val - _davg;
    _dvariance = (1.0 - _alpha) * diff * diff + _alpha * _dvariance;
  }
}

double AbsSeq::avg() const {
  if (_num == 0)
    return 0.0;
  else
    return _sum / total();
}

double AbsSeq::variance() const {
  if (_num <= 1)
    return 0.0;

  double x_bar = avg();
  double result = _sum_of_squares / total() - x_bar * x_bar;
  if (result < 0.0) {
    // due to loss-of-precision errors, the variance might be negative
    // by a small bit

    //    guarantee(-0.1 < result && result < 0.0,
    //        "if variance is negative, it should be very small");
    result = 0.0;
  }
  return result;
}

double AbsSeq::sd() const {
  double var = variance();
  guarantee( var >= 0.0, "variance should not be negative" );
  return sqrt(var);
}

double AbsSeq::davg() const {
  return _davg;
}

double AbsSeq::dvariance() const {
  if (_num <= 1)
    return 0.0;

  double result = _dvariance;
  if (result < 0.0) {
    // due to loss-of-precision errors, the variance might be negative
    // by a small bit

    guarantee(-0.1 < result && result < 0.0,
               "if variance is negative, it should be very small");
    result = 0.0;
  }
  return result;
}

double AbsSeq::dsd() const {
  double var = dvariance();
  guarantee( var >= 0.0, "variance should not be negative" );
  return sqrt(var);
}

NumberSeq::NumberSeq(double alpha) :
  AbsSeq(alpha), _maximum(0.0), _last(0.0) {
}

bool NumberSeq::check_nums(NumberSeq *total, int n, NumberSeq **parts) {
  for (int i = 0; i < n; ++i) {
    if (parts[i] != NULL && total->num() != parts[i]->num())
      return false;
  }
  return true;
}

void NumberSeq::add(double val) {
  AbsSeq::add(val);

  _last = val;
  if (_num == 0) {
    _maximum = val;
  } else {
    if (val > _maximum)
      _maximum = val;
  }
  _sum += val;
  _sum_of_squares += val * val;
  ++_num;
}


TruncatedSeq::TruncatedSeq(int length, double alpha):
  AbsSeq(alpha), _length(length), _next(0) {
  _sequence = NEW_C_HEAP_ARRAY(double, _length, mtInternal);
  for (int i = 0; i < _length; ++i)
    _sequence[i] = 0.0;
}

TruncatedSeq::~TruncatedSeq() {
  FREE_C_HEAP_ARRAY(double, _sequence, mtGC);
}

void TruncatedSeq::add(double val) {
  AbsSeq::add(val);

  // get the oldest value in the sequence...
  double old_val = _sequence[_next];
  // ...remove it from the sum and sum of squares
  _sum -= old_val;
  _sum_of_squares -= old_val * old_val;

  // ...and update them with the new value
  _sum += val;
  _sum_of_squares += val * val;

  // now replace the old value with the new one
  _sequence[_next] = val;
  _next = (_next + 1) % _length;

  // only increase it if the buffer is not full
  if (_num < _length)
    ++_num;

  guarantee( variance() > -1.0, "variance should be >= 0" );
}

// can't easily keep track of this incrementally...
double TruncatedSeq::maximum() const {
  if (_num == 0)
    return 0.0;
  double ret = _sequence[0];
  for (int i = 1; i < _num; ++i) {
    double val = _sequence[i];
    if (val > ret)
      ret = val;
  }
  return ret;
}

double TruncatedSeq::last() const {
  if (_num == 0)
    return 0.0;
  unsigned last_index = (_next + _length - 1) % _length;
  return _sequence[last_index];
}

double TruncatedSeq::oldest() const {
  if (_num == 0)
    return 0.0;
  else if (_num < _length)
    // index 0 always oldest value until the array is full
    return _sequence[0];
  else {
    // since the array is full, _next is over the oldest value
    return _sequence[_next];
  }
}

double TruncatedSeq::predict_next() const {
  if (_num == 0)
    return 0.0;

  double num           = (double) _num;
  double x_squared_sum = 0.0;
  double x_sum         = 0.0;
  double y_sum         = 0.0;
  double xy_sum        = 0.0;
  double x_avg         = 0.0;
  double y_avg         = 0.0;

  int first = (_next + _length - _num) % _length;
  for (int i = 0; i < _num; ++i) {
    double x = (double) i;
    double y =  _sequence[(first + i) % _length];

    x_squared_sum += x * x;
    x_sum         += x;
    y_sum         += y;
    xy_sum        += x * y;
  }
  x_avg = x_sum / num;
  y_avg = y_sum / num;

  double Sxx = x_squared_sum - x_sum * x_sum / num;
  double Sxy = xy_sum - x_sum * y_sum / num;
  double b1 = Sxy / Sxx;
  double b0 = y_avg - b1 * x_avg;

  return b0 + b1 * num;
}


// Printing/Debugging Support

void AbsSeq::dump() { dump_on(gclog_or_tty); }

void AbsSeq::dump_on(outputStream* s) {
  s->print_cr("\t _num = %d, _sum = %7.3f, _sum_of_squares = %7.3f",
                  _num,      _sum,         _sum_of_squares);
  s->print_cr("\t _davg = %7.3f, _dvariance = %7.3f, _alpha = %7.3f",
                  _davg,         _dvariance,         _alpha);
}

void NumberSeq::dump_on(outputStream* s) {
  AbsSeq::dump_on(s);
  s->print_cr("\t\t _last = %7.3f, _maximum = %7.3f", _last, _maximum);
}

void TruncatedSeq::dump_on(outputStream* s) {
  AbsSeq::dump_on(s);
  s->print_cr("\t\t _length = %d, _next = %d", _length, _next);
  for (int i = 0; i < _length; i++) {
    if (i%5 == 0) {
      s->cr();
      s->print("\t");
    }
    s->print("\t[%d]=%7.3f", i, _sequence[i]);
  }
  s->cr();
}
