blob: 9110eb19eb014adcdd4801084820c2fd3d60b161 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright 2016 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/tracing/base/range.html">
<script>
'use strict';
tr.exportTo('tr.b', function() {
/***
* An object of this class computes basic statistics online in O(1).
* Usage:
* 1. Create an instance.
* 2. Add numbers using the |add| method.
* 3. Query statistics.
* 4. Repeat from step 2.
*
* @constructor
*/
function RunningStatistics() {
this.mean_ = 0;
this.count_ = 0;
this.max_ = -Infinity;
this.min_ = Infinity;
this.sum_ = 0;
this.variance_ = 0;
}
RunningStatistics.prototype = {
get count() {
return this.count_;
},
get mean() {
if (this.count_ == 0)
return undefined;
return this.mean_;
},
get max() {
return this.max_;
},
get min() {
return this.min_;
},
get sum() {
return this.sum_;
},
get variance() {
if (this.count_ == 0)
return undefined;
if (this.count_ == 1)
return 0;
return this.variance_ / (this.count_ - 1);
},
get stddev() {
if (this.count_ == 0)
return undefined;
return Math.sqrt(this.variance);
},
add: function(x) {
this.count_++;
this.max_ = Math.max(this.max_, x);
this.min_ = Math.min(this.min_, x);
this.sum_ += x;
// The following uses Welford's algorithm for computing running mean
// and variance. See http://www.johndcook.com/blog/standard_deviation.
if (this.count_ === 1) {
this.mean_ = x;
this.variance_ = 0;
} else {
var oldMean = this.mean_;
var oldVariance = this.variance_;
this.mean_ = oldMean + (x - oldMean) / this.count_;
this.variance_ = oldVariance + (x - oldMean) * (x - this.mean_);
}
},
merge: function(other) {
var result = new RunningStatistics();
result.count_ = this.count_ + other.count_;
result.sum_ = this.sum_ + other.sum_;
result.min_ = Math.min(this.min_, other.min_);
result.max_ = Math.max(this.max_, other.max_);
if (other.count_ === 0 && this.count_ === 0) {
result.mean_ = 0;
result.variance_ = 0;
} else {
// Combine the mean and the variance using the formulas from
// https://goo.gl/ddcAep.
var mx = this.mean_, my = other.mean_;
var vx = this.variance_, vy = other.variance_;
var n = this.count_, m = other.count_;
result.mean_ = (n * mx + m * my) / (n + m);
result.variance_ = vx + vy + n * m * (mx - my) * (mx - my) / (n + m);
}
return result;
},
asDict: function() {
return {
mean: this.mean_,
count: this.count_,
max: this.max_,
min: this.min_,
sum: this.sum_,
variance: this.variance_
};
}
};
RunningStatistics.fromDict = function(d) {
var result = new RunningStatistics();
result.mean_ = d.mean;
result.count_ = d.count;
result.max_ = d.max;
result.min_ = d.min;
result.sum_ = d.sum;
result.variance_ = d.variance;
return result;
};
return {
RunningStatistics: RunningStatistics
};
});
</script>