aoqi@0: /* aoqi@0: * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #include "precompiled.hpp" aoqi@0: #include "memory/allocation.inline.hpp" aoqi@0: #include "utilities/debug.hpp" aoqi@0: #include "utilities/globalDefinitions.hpp" aoqi@0: #include "utilities/numberSeq.hpp" aoqi@0: aoqi@0: AbsSeq::AbsSeq(double alpha) : aoqi@0: _num(0), _sum(0.0), _sum_of_squares(0.0), aoqi@0: _davg(0.0), _dvariance(0.0), _alpha(alpha) { aoqi@0: } aoqi@0: aoqi@0: void AbsSeq::add(double val) { aoqi@0: if (_num == 0) { aoqi@0: // if the sequence is empty, the davg is the same as the value aoqi@0: _davg = val; aoqi@0: // and the variance is 0 aoqi@0: _dvariance = 0.0; aoqi@0: } else { aoqi@0: // otherwise, calculate both aoqi@0: _davg = (1.0 - _alpha) * val + _alpha * _davg; aoqi@0: double diff = val - _davg; aoqi@0: _dvariance = (1.0 - _alpha) * diff * diff + _alpha * _dvariance; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: double AbsSeq::avg() const { aoqi@0: if (_num == 0) aoqi@0: return 0.0; aoqi@0: else aoqi@0: return _sum / total(); aoqi@0: } aoqi@0: aoqi@0: double AbsSeq::variance() const { aoqi@0: if (_num <= 1) aoqi@0: return 0.0; aoqi@0: aoqi@0: double x_bar = avg(); aoqi@0: double result = _sum_of_squares / total() - x_bar * x_bar; aoqi@0: if (result < 0.0) { aoqi@0: // due to loss-of-precision errors, the variance might be negative aoqi@0: // by a small bit aoqi@0: aoqi@0: // guarantee(-0.1 < result && result < 0.0, aoqi@0: // "if variance is negative, it should be very small"); aoqi@0: result = 0.0; aoqi@0: } aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: double AbsSeq::sd() const { aoqi@0: double var = variance(); aoqi@0: guarantee( var >= 0.0, "variance should not be negative" ); aoqi@0: return sqrt(var); aoqi@0: } aoqi@0: aoqi@0: double AbsSeq::davg() const { aoqi@0: return _davg; aoqi@0: } aoqi@0: aoqi@0: double AbsSeq::dvariance() const { aoqi@0: if (_num <= 1) aoqi@0: return 0.0; aoqi@0: aoqi@0: double result = _dvariance; aoqi@0: if (result < 0.0) { aoqi@0: // due to loss-of-precision errors, the variance might be negative aoqi@0: // by a small bit aoqi@0: aoqi@0: guarantee(-0.1 < result && result < 0.0, aoqi@0: "if variance is negative, it should be very small"); aoqi@0: result = 0.0; aoqi@0: } aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: double AbsSeq::dsd() const { aoqi@0: double var = dvariance(); aoqi@0: guarantee( var >= 0.0, "variance should not be negative" ); aoqi@0: return sqrt(var); aoqi@0: } aoqi@0: aoqi@0: NumberSeq::NumberSeq(double alpha) : aoqi@0: AbsSeq(alpha), _maximum(0.0), _last(0.0) { aoqi@0: } aoqi@0: aoqi@0: bool NumberSeq::check_nums(NumberSeq *total, int n, NumberSeq **parts) { aoqi@0: for (int i = 0; i < n; ++i) { aoqi@0: if (parts[i] != NULL && total->num() != parts[i]->num()) aoqi@0: return false; aoqi@0: } aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: void NumberSeq::add(double val) { aoqi@0: AbsSeq::add(val); aoqi@0: aoqi@0: _last = val; aoqi@0: if (_num == 0) { aoqi@0: _maximum = val; aoqi@0: } else { aoqi@0: if (val > _maximum) aoqi@0: _maximum = val; aoqi@0: } aoqi@0: _sum += val; aoqi@0: _sum_of_squares += val * val; aoqi@0: ++_num; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: TruncatedSeq::TruncatedSeq(int length, double alpha): aoqi@0: AbsSeq(alpha), _length(length), _next(0) { aoqi@0: _sequence = NEW_C_HEAP_ARRAY(double, _length, mtInternal); aoqi@0: for (int i = 0; i < _length; ++i) aoqi@0: _sequence[i] = 0.0; aoqi@0: } aoqi@0: aoqi@0: TruncatedSeq::~TruncatedSeq() { aoqi@0: FREE_C_HEAP_ARRAY(double, _sequence, mtGC); aoqi@0: } aoqi@0: aoqi@0: void TruncatedSeq::add(double val) { aoqi@0: AbsSeq::add(val); aoqi@0: aoqi@0: // get the oldest value in the sequence... aoqi@0: double old_val = _sequence[_next]; aoqi@0: // ...remove it from the sum and sum of squares aoqi@0: _sum -= old_val; aoqi@0: _sum_of_squares -= old_val * old_val; aoqi@0: aoqi@0: // ...and update them with the new value aoqi@0: _sum += val; aoqi@0: _sum_of_squares += val * val; aoqi@0: aoqi@0: // now replace the old value with the new one aoqi@0: _sequence[_next] = val; aoqi@0: _next = (_next + 1) % _length; aoqi@0: aoqi@0: // only increase it if the buffer is not full aoqi@0: if (_num < _length) aoqi@0: ++_num; aoqi@0: aoqi@0: guarantee( variance() > -1.0, "variance should be >= 0" ); aoqi@0: } aoqi@0: aoqi@0: // can't easily keep track of this incrementally... aoqi@0: double TruncatedSeq::maximum() const { aoqi@0: if (_num == 0) aoqi@0: return 0.0; aoqi@0: double ret = _sequence[0]; aoqi@0: for (int i = 1; i < _num; ++i) { aoqi@0: double val = _sequence[i]; aoqi@0: if (val > ret) aoqi@0: ret = val; aoqi@0: } aoqi@0: return ret; aoqi@0: } aoqi@0: aoqi@0: double TruncatedSeq::last() const { aoqi@0: if (_num == 0) aoqi@0: return 0.0; aoqi@0: unsigned last_index = (_next + _length - 1) % _length; aoqi@0: return _sequence[last_index]; aoqi@0: } aoqi@0: aoqi@0: double TruncatedSeq::oldest() const { aoqi@0: if (_num == 0) aoqi@0: return 0.0; aoqi@0: else if (_num < _length) aoqi@0: // index 0 always oldest value until the array is full aoqi@0: return _sequence[0]; aoqi@0: else { aoqi@0: // since the array is full, _next is over the oldest value aoqi@0: return _sequence[_next]; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: double TruncatedSeq::predict_next() const { aoqi@0: if (_num == 0) aoqi@0: return 0.0; aoqi@0: aoqi@0: double num = (double) _num; aoqi@0: double x_squared_sum = 0.0; aoqi@0: double x_sum = 0.0; aoqi@0: double y_sum = 0.0; aoqi@0: double xy_sum = 0.0; aoqi@0: double x_avg = 0.0; aoqi@0: double y_avg = 0.0; aoqi@0: aoqi@0: int first = (_next + _length - _num) % _length; aoqi@0: for (int i = 0; i < _num; ++i) { aoqi@0: double x = (double) i; aoqi@0: double y = _sequence[(first + i) % _length]; aoqi@0: aoqi@0: x_squared_sum += x * x; aoqi@0: x_sum += x; aoqi@0: y_sum += y; aoqi@0: xy_sum += x * y; aoqi@0: } aoqi@0: x_avg = x_sum / num; aoqi@0: y_avg = y_sum / num; aoqi@0: aoqi@0: double Sxx = x_squared_sum - x_sum * x_sum / num; aoqi@0: double Sxy = xy_sum - x_sum * y_sum / num; aoqi@0: double b1 = Sxy / Sxx; aoqi@0: double b0 = y_avg - b1 * x_avg; aoqi@0: aoqi@0: return b0 + b1 * num; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: // Printing/Debugging Support aoqi@0: aoqi@0: void AbsSeq::dump() { dump_on(gclog_or_tty); } aoqi@0: aoqi@0: void AbsSeq::dump_on(outputStream* s) { aoqi@0: s->print_cr("\t _num = %d, _sum = %7.3f, _sum_of_squares = %7.3f", aoqi@0: _num, _sum, _sum_of_squares); aoqi@0: s->print_cr("\t _davg = %7.3f, _dvariance = %7.3f, _alpha = %7.3f", aoqi@0: _davg, _dvariance, _alpha); aoqi@0: } aoqi@0: aoqi@0: void NumberSeq::dump_on(outputStream* s) { aoqi@0: AbsSeq::dump_on(s); aoqi@0: s->print_cr("\t\t _last = %7.3f, _maximum = %7.3f", _last, _maximum); aoqi@0: } aoqi@0: aoqi@0: void TruncatedSeq::dump_on(outputStream* s) { aoqi@0: AbsSeq::dump_on(s); aoqi@0: s->print_cr("\t\t _length = %d, _next = %d", _length, _next); aoqi@0: for (int i = 0; i < _length; i++) { aoqi@0: if (i%5 == 0) { aoqi@0: s->cr(); aoqi@0: s->print("\t"); aoqi@0: } aoqi@0: s->print("\t[%d]=%7.3f", i, _sequence[i]); aoqi@0: } aoqi@0: s->cr(); aoqi@0: }