OLD | NEW |
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 <!-- | 2 <!-- |
3 Copyright 2014 The Chromium Authors. All rights reserved. | 3 Copyright 2014 The Chromium Authors. All rights reserved. |
4 Use of this source code is governed by a BSD-style license that can be | 4 Use of this source code is governed by a BSD-style license that can be |
5 found in the LICENSE file. | 5 found in the LICENSE file. |
6 --> | 6 --> |
7 | 7 |
8 <link rel="import" href="/tracing/base/math/math.html"> | 8 <link rel="import" href="/tracing/base/math/math.html"> |
9 <link rel="import" href="/tracing/base/math/range.html"> | 9 <link rel="import" href="/tracing/base/math/range.html"> |
10 <script src="/mannwhitneyu/mannwhitneyu.js"></script> | 10 <script src="/mannwhitneyu/mannwhitneyu.js"></script> |
(...skipping 18 matching lines...) Expand all Loading... |
29 })(this); | 29 })(this); |
30 </script> | 30 </script> |
31 | 31 |
32 <script> | 32 <script> |
33 'use strict'; | 33 'use strict'; |
34 | 34 |
35 // TODO(charliea): Remove: | 35 // TODO(charliea): Remove: |
36 /* eslint-disable catapult-camelcase */ | 36 /* eslint-disable catapult-camelcase */ |
37 | 37 |
38 tr.exportTo('tr.b.math', function() { | 38 tr.exportTo('tr.b.math', function() { |
39 const identity = x => x; | |
40 | |
41 const Statistics = {}; | 39 const Statistics = {}; |
42 | 40 |
43 /* Returns the quotient, or zero if the denominator is zero.*/ | 41 /* Returns the quotient, or zero if the denominator is zero.*/ |
44 Statistics.divideIfPossibleOrZero = function(numerator, denominator) { | 42 Statistics.divideIfPossibleOrZero = function(numerator, denominator) { |
45 if (denominator === 0) return 0; | 43 if (denominator === 0) return 0; |
46 return numerator / denominator; | 44 return numerator / denominator; |
47 }; | 45 }; |
48 | 46 |
49 Statistics.sum = function(ary, opt_func, opt_this) { | 47 Statistics.sum = function(ary, opt_func, opt_this) { |
50 const func = opt_func || identity; | 48 const func = opt_func || (x => x); |
51 let ret = 0; | 49 let ret = 0; |
52 let i = 0; | 50 let i = 0; |
53 for (const elt of ary) { | 51 for (const elt of ary) { |
54 ret += func.call(opt_this, elt, i++); | 52 ret += func.call(opt_this, elt, i++); |
55 } | 53 } |
56 return ret; | 54 return ret; |
57 }; | 55 }; |
58 | 56 |
59 Statistics.mean = function(ary, opt_func, opt_this) { | 57 Statistics.mean = function(ary, opt_func, opt_this) { |
60 const func = opt_func || identity; | 58 const func = opt_func || (x => x); |
61 let sum = 0; | 59 let sum = 0; |
62 let i = 0; | 60 let i = 0; |
63 | 61 |
64 for (const elt of ary) { | 62 for (const elt of ary) { |
65 sum += func.call(opt_this, elt, i++); | 63 sum += func.call(opt_this, elt, i++); |
66 } | 64 } |
67 | 65 |
68 if (i === 0) return undefined; | 66 if (i === 0) return undefined; |
69 | 67 |
70 return sum / i; | 68 return sum / i; |
71 }; | 69 }; |
72 | 70 |
73 Statistics.geometricMean = function(ary, opt_func, opt_this) { | 71 Statistics.geometricMean = function(ary, opt_func, opt_this) { |
74 const func = opt_func || identity; | 72 const func = opt_func || (x => x); |
75 let i = 0; | 73 let i = 0; |
76 let logsum = 0; | 74 let logsum = 0; |
77 | 75 |
78 // The geometric mean is expressed as the arithmetic mean of logarithms | 76 // The geometric mean is expressed as the arithmetic mean of logarithms |
79 // in order to prevent overflow. | 77 // in order to prevent overflow. |
80 for (const elt of ary) { | 78 for (const elt of ary) { |
81 const x = func.call(opt_this, elt, i++); | 79 const x = func.call(opt_this, elt, i++); |
82 if (x <= 0) return 0; | 80 if (x <= 0) return 0; |
83 logsum += Math.log(Math.abs(x)); | 81 logsum += Math.log(Math.abs(x)); |
84 } | 82 } |
85 | 83 |
86 if (i === 0) return 1; | 84 if (i === 0) return 1; |
87 | 85 |
88 return Math.exp(logsum / i); | 86 return Math.exp(logsum / i); |
89 }; | 87 }; |
90 | 88 |
91 // Returns undefined if the sum of the weights is zero. | 89 // Returns undefined if the sum of the weights is zero. |
92 Statistics.weightedMean = function( | 90 Statistics.weightedMean = function( |
93 ary, weightCallback, opt_valueCallback, opt_this) { | 91 ary, weightCallback, opt_valueCallback, opt_this) { |
94 const valueCallback = opt_valueCallback || identity; | 92 const valueCallback = opt_valueCallback || (x => x); |
95 let numerator = 0; | 93 let numerator = 0; |
96 let denominator = 0; | 94 let denominator = 0; |
97 let i = -1; | 95 let i = -1; |
98 | 96 |
99 for (const elt of ary) { | 97 for (const elt of ary) { |
100 i++; | 98 i++; |
101 const value = valueCallback.call(opt_this, elt, i); | 99 const value = valueCallback.call(opt_this, elt, i); |
102 if (value === undefined) continue; | 100 if (value === undefined) continue; |
103 const weight = weightCallback.call(opt_this, elt, i, value); | 101 const weight = weightCallback.call(opt_this, elt, i, value); |
104 numerator += weight * value; | 102 numerator += weight * value; |
105 denominator += weight; | 103 denominator += weight; |
106 } | 104 } |
107 | 105 |
108 if (denominator === 0) return undefined; | 106 if (denominator === 0) return undefined; |
109 | 107 |
110 return numerator / denominator; | 108 return numerator / denominator; |
111 }; | 109 }; |
112 | 110 |
113 Statistics.variance = function(ary, opt_func, opt_this) { | 111 Statistics.variance = function(ary, opt_func, opt_this) { |
114 if (ary.length === 0) return undefined; | 112 if (ary.length === 0) return undefined; |
115 if (ary.length === 1) return 0; | 113 if (ary.length === 1) return 0; |
116 const func = opt_func || identity; | 114 const func = opt_func || (x => x); |
117 const mean = Statistics.mean(ary, func, opt_this); | 115 const mean = Statistics.mean(ary, func, opt_this); |
118 const sumOfSquaredDistances = Statistics.sum( | 116 const sumOfSquaredDistances = Statistics.sum( |
119 ary, | 117 ary, |
120 function(d, i) { | 118 function(d, i) { |
121 const v = func.call(this, d, i) - mean; | 119 const v = func.call(this, d, i) - mean; |
122 return v * v; | 120 return v * v; |
123 }, | 121 }, |
124 opt_this); | 122 opt_this); |
125 return sumOfSquaredDistances / (ary.length - 1); | 123 return sumOfSquaredDistances / (ary.length - 1); |
126 }; | 124 }; |
127 | 125 |
128 Statistics.stddev = function(ary, opt_func, opt_this) { | 126 Statistics.stddev = function(ary, opt_func, opt_this) { |
129 if (ary.length === 0) return undefined; | 127 if (ary.length === 0) return undefined; |
130 return Math.sqrt( | 128 return Math.sqrt( |
131 Statistics.variance(ary, opt_func, opt_this)); | 129 Statistics.variance(ary, opt_func, opt_this)); |
132 }; | 130 }; |
133 | 131 |
134 Statistics.max = function(ary, opt_func, opt_this) { | 132 Statistics.max = function(ary, opt_func, opt_this) { |
135 const func = opt_func || identity; | 133 const func = opt_func || (x => x); |
136 let ret = -Infinity; | 134 let ret = -Infinity; |
137 let i = 0; | 135 let i = 0; |
138 for (const elt of ary) { | 136 for (const elt of ary) { |
139 ret = Math.max(ret, func.call(opt_this, elt, i++)); | 137 ret = Math.max(ret, func.call(opt_this, elt, i++)); |
140 } | 138 } |
141 return ret; | 139 return ret; |
142 }; | 140 }; |
143 | 141 |
144 Statistics.min = function(ary, opt_func, opt_this) { | 142 Statistics.min = function(ary, opt_func, opt_this) { |
145 const func = opt_func || identity; | 143 const func = opt_func || (x => x); |
146 let ret = Infinity; | 144 let ret = Infinity; |
147 let i = 0; | 145 let i = 0; |
148 for (const elt of ary) { | 146 for (const elt of ary) { |
149 ret = Math.min(ret, func.call(opt_this, elt, i++)); | 147 ret = Math.min(ret, func.call(opt_this, elt, i++)); |
150 } | 148 } |
151 return ret; | 149 return ret; |
152 }; | 150 }; |
153 | 151 |
154 Statistics.range = function(ary, opt_func, opt_this) { | 152 Statistics.range = function(ary, opt_func, opt_this) { |
155 const func = opt_func || identity; | 153 const func = opt_func || (x => x); |
156 const ret = new tr.b.math.Range(); | 154 const ret = new tr.b.math.Range(); |
157 let i = 0; | 155 let i = 0; |
158 for (const elt of ary) { | 156 for (const elt of ary) { |
159 ret.addValue(func.call(opt_this, elt, i++)); | 157 ret.addValue(func.call(opt_this, elt, i++)); |
160 } | 158 } |
161 return ret; | 159 return ret; |
162 }; | 160 }; |
163 | 161 |
164 Statistics.percentile = function(ary, percent, opt_func, opt_this) { | 162 Statistics.percentile = function(ary, percent, opt_func, opt_this) { |
165 if (!(percent >= 0 && percent <= 1)) { | 163 if (!(percent >= 0 && percent <= 1)) { |
166 throw new Error('percent must be [0,1]'); | 164 throw new Error('percent must be [0,1]'); |
167 } | 165 } |
168 | 166 |
169 const func = opt_func || identity; | 167 const func = opt_func || (x => x); |
170 const tmp = new Array(ary.length); | 168 const tmp = new Array(ary.length); |
171 let i = 0; | 169 let i = 0; |
172 for (const elt of ary) { | 170 for (const elt of ary) { |
173 tmp[i] = func.call(opt_this, elt, i++); | 171 tmp[i] = func.call(opt_this, elt, i++); |
174 } | 172 } |
175 tmp.sort((a, b) => a - b); | 173 tmp.sort((a, b) => a - b); |
176 const idx = Math.floor((ary.length - 1) * percent); | 174 const idx = Math.floor((ary.length - 1) * percent); |
177 return tmp[idx]; | 175 return tmp[idx]; |
178 }; | 176 }; |
179 | 177 |
(...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 result.significance = Statistics.Significance.INSIGNIFICANT; | 830 result.significance = Statistics.Significance.INSIGNIFICANT; |
833 } | 831 } |
834 return result; | 832 return result; |
835 }; | 833 }; |
836 | 834 |
837 return { | 835 return { |
838 Statistics, | 836 Statistics, |
839 }; | 837 }; |
840 }); | 838 }); |
841 </script> | 839 </script> |
OLD | NEW |