| OLD | NEW |
| 1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
| 2 <!-- | 2 <!-- |
| 3 Copyright 2016 The Chromium Authors. All rights reserved. | 3 Copyright 2016 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/iteration_helpers.html"> | 8 <link rel="import" href="/tracing/base/iteration_helpers.html"> |
| 9 <link rel="import" href="/tracing/base/range.html"> | 9 <link rel="import" href="/tracing/base/math/range.html"> |
| 10 <link rel="import" href="/tracing/base/running_statistics.html"> | 10 <link rel="import" href="/tracing/base/math/running_statistics.html"> |
| 11 <link rel="import" href="/tracing/base/math/sorted_array_utils.html"> |
| 12 <link rel="import" href="/tracing/base/math/statistics.html"> |
| 11 <link rel="import" href="/tracing/base/scalar.html"> | 13 <link rel="import" href="/tracing/base/scalar.html"> |
| 12 <link rel="import" href="/tracing/base/sorted_array_utils.html"> | |
| 13 <link rel="import" href="/tracing/base/statistics.html"> | |
| 14 <link rel="import" href="/tracing/base/unit.html"> | 14 <link rel="import" href="/tracing/base/unit.html"> |
| 15 <link rel="import" href="/tracing/value/diagnostics/diagnostic_map.html"> | 15 <link rel="import" href="/tracing/value/diagnostics/diagnostic_map.html"> |
| 16 | 16 |
| 17 <script> | 17 <script> |
| 18 'use strict'; | 18 'use strict'; |
| 19 | 19 |
| 20 tr.exportTo('tr.v', function() { | 20 tr.exportTo('tr.v', function() { |
| 21 const MAX_DIAGNOSTIC_MAPS = 16; | 21 const MAX_DIAGNOSTIC_MAPS = 16; |
| 22 | 22 |
| 23 const DEFAULT_SAMPLE_VALUES_PER_BIN = 10; | 23 const DEFAULT_SAMPLE_VALUES_PER_BIN = 10; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 * Converts the given string to a percent between 0 and 1. | 56 * Converts the given string to a percent between 0 and 1. |
| 57 * @param {string} | 57 * @param {string} |
| 58 * @return {number} | 58 * @return {number} |
| 59 */ | 59 */ |
| 60 function percentFromString(s) { | 60 function percentFromString(s) { |
| 61 return parseFloat(s[0] + '.' + s.substr(1).replace(/_/g, '')); | 61 return parseFloat(s[0] + '.' + s.substr(1).replace(/_/g, '')); |
| 62 } | 62 } |
| 63 | 63 |
| 64 class HistogramBin { | 64 class HistogramBin { |
| 65 /** | 65 /** |
| 66 * @param {!tr.b.Range} range | 66 * @param {!tr.b.math.Range} range |
| 67 */ | 67 */ |
| 68 constructor(range) { | 68 constructor(range) { |
| 69 this.range = range; | 69 this.range = range; |
| 70 this.count = 0; | 70 this.count = 0; |
| 71 this.diagnosticMaps = []; | 71 this.diagnosticMaps = []; |
| 72 } | 72 } |
| 73 | 73 |
| 74 /** | 74 /** |
| 75 * @param {*} value | 75 * @param {*} value |
| 76 */ | 76 */ |
| 77 addSample(value) { | 77 addSample(value) { |
| 78 this.count += 1; | 78 this.count += 1; |
| 79 } | 79 } |
| 80 | 80 |
| 81 /** | 81 /** |
| 82 * @param {!tr.v.d.DiagnosticMap} diagnostics | 82 * @param {!tr.v.d.DiagnosticMap} diagnostics |
| 83 */ | 83 */ |
| 84 addDiagnosticMap(diagnostics) { | 84 addDiagnosticMap(diagnostics) { |
| 85 tr.b.Statistics.uniformlySampleStream( | 85 tr.b.math.Statistics.uniformlySampleStream( |
| 86 this.diagnosticMaps, this.count, diagnostics, MAX_DIAGNOSTIC_MAPS); | 86 this.diagnosticMaps, this.count, diagnostics, MAX_DIAGNOSTIC_MAPS); |
| 87 } | 87 } |
| 88 | 88 |
| 89 addBin(other) { | 89 addBin(other) { |
| 90 if (!this.range.equals(other.range)) { | 90 if (!this.range.equals(other.range)) { |
| 91 throw new Error('Merging incompatible Histogram bins.'); | 91 throw new Error('Merging incompatible Histogram bins.'); |
| 92 } | 92 } |
| 93 tr.b.Statistics.mergeSampledStreams(this.diagnosticMaps, this.count, | 93 tr.b.math.Statistics.mergeSampledStreams(this.diagnosticMaps, this.count, |
| 94 other.diagnosticMaps, other.count, MAX_DIAGNOSTIC_MAPS); | 94 other.diagnosticMaps, other.count, MAX_DIAGNOSTIC_MAPS); |
| 95 this.count += other.count; | 95 this.count += other.count; |
| 96 } | 96 } |
| 97 | 97 |
| 98 fromDict(dict) { | 98 fromDict(dict) { |
| 99 this.count = dict[0]; | 99 this.count = dict[0]; |
| 100 if (dict.length > 1) { | 100 if (dict.length > 1) { |
| 101 for (let map of dict[1]) { | 101 for (let map of dict[1]) { |
| 102 this.diagnosticMaps.push(tr.v.d.DiagnosticMap.fromDict(map)); | 102 this.diagnosticMaps.push(tr.v.d.DiagnosticMap.fromDict(map)); |
| 103 } | 103 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 get running() { | 186 get running() { |
| 187 return this.running_; | 187 return this.running_; |
| 188 } | 188 } |
| 189 | 189 |
| 190 get maxNumSampleValues() { | 190 get maxNumSampleValues() { |
| 191 return this.maxNumSampleValues_; | 191 return this.maxNumSampleValues_; |
| 192 } | 192 } |
| 193 | 193 |
| 194 set maxNumSampleValues(n) { | 194 set maxNumSampleValues(n) { |
| 195 this.maxNumSampleValues_ = n; | 195 this.maxNumSampleValues_ = n; |
| 196 tr.b.Statistics.uniformlySampleArray( | 196 tr.b.math.Statistics.uniformlySampleArray( |
| 197 this.sampleValues_, this.maxNumSampleValues_); | 197 this.sampleValues_, this.maxNumSampleValues_); |
| 198 } | 198 } |
| 199 | 199 |
| 200 get name() { | 200 get name() { |
| 201 return this.name_; | 201 return this.name_; |
| 202 } | 202 } |
| 203 | 203 |
| 204 get guid() { | 204 get guid() { |
| 205 if (this.guid_ === undefined) { | 205 if (this.guid_ === undefined) { |
| 206 this.guid_ = tr.b.GUID.allocateUUID4(); | 206 this.guid_ = tr.b.GUID.allocateUUID4(); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 235 for (let i = 0; i < dict.allBins.length; ++i) { | 235 for (let i = 0; i < dict.allBins.length; ++i) { |
| 236 hist.allBins[i].fromDict(dict.allBins[i]); | 236 hist.allBins[i].fromDict(dict.allBins[i]); |
| 237 } | 237 } |
| 238 } else { | 238 } else { |
| 239 for (var [i, binDict] of Object.entries(dict.allBins)) { | 239 for (var [i, binDict] of Object.entries(dict.allBins)) { |
| 240 hist.allBins[i].fromDict(binDict); | 240 hist.allBins[i].fromDict(binDict); |
| 241 } | 241 } |
| 242 } | 242 } |
| 243 } | 243 } |
| 244 if (dict.running) { | 244 if (dict.running) { |
| 245 hist.running_ = tr.b.RunningStatistics.fromDict(dict.running); | 245 hist.running_ = tr.b.math.RunningStatistics.fromDict(dict.running); |
| 246 } | 246 } |
| 247 if (dict.summaryOptions) { | 247 if (dict.summaryOptions) { |
| 248 hist.customizeSummaryOptions(dict.summaryOptions); | 248 hist.customizeSummaryOptions(dict.summaryOptions); |
| 249 } | 249 } |
| 250 if (dict.maxNumSampleValues !== undefined) { | 250 if (dict.maxNumSampleValues !== undefined) { |
| 251 hist.maxNumSampleValues = dict.maxNumSampleValues; | 251 hist.maxNumSampleValues = dict.maxNumSampleValues; |
| 252 } | 252 } |
| 253 if (dict.sampleValues) { | 253 if (dict.sampleValues) { |
| 254 hist.sampleValues_ = dict.sampleValues; | 254 hist.sampleValues_ = dict.sampleValues; |
| 255 } | 255 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 | 294 |
| 295 /** | 295 /** |
| 296 * Requires that units agree. | 296 * Requires that units agree. |
| 297 * Returns DONT_CARE if that is the units' improvementDirection. | 297 * Returns DONT_CARE if that is the units' improvementDirection. |
| 298 * Returns SIGNIFICANT if the Mann-Whitney U test returns a | 298 * Returns SIGNIFICANT if the Mann-Whitney U test returns a |
| 299 * p-value less than opt_alpha or DEFAULT_ALPHA. Returns INSIGNIFICANT if | 299 * p-value less than opt_alpha or DEFAULT_ALPHA. Returns INSIGNIFICANT if |
| 300 * the p-value is greater than alpha. | 300 * the p-value is greater than alpha. |
| 301 * | 301 * |
| 302 * @param {!tr.v.Histogram} other | 302 * @param {!tr.v.Histogram} other |
| 303 * @param {number=} opt_alpha | 303 * @param {number=} opt_alpha |
| 304 * @return {!tr.b.Statistics.Significance} | 304 * @return {!tr.b.math.Statistics.Significance} |
| 305 */ | 305 */ |
| 306 getDifferenceSignificance(other, opt_alpha) { | 306 getDifferenceSignificance(other, opt_alpha) { |
| 307 if (this.unit !== other.unit) { | 307 if (this.unit !== other.unit) { |
| 308 throw new Error('Cannot compare Histograms with different units'); | 308 throw new Error('Cannot compare Histograms with different units'); |
| 309 } | 309 } |
| 310 | 310 |
| 311 if (this.unit.improvementDirection === | 311 if (this.unit.improvementDirection === |
| 312 tr.b.ImprovementDirection.DONT_CARE) { | 312 tr.b.ImprovementDirection.DONT_CARE) { |
| 313 return tr.b.Statistics.Significance.DONT_CARE; | 313 return tr.b.math.Statistics.Significance.DONT_CARE; |
| 314 } | 314 } |
| 315 | 315 |
| 316 if (!(other instanceof Histogram)) { | 316 if (!(other instanceof Histogram)) { |
| 317 throw new Error('Unable to compute a p-value'); | 317 throw new Error('Unable to compute a p-value'); |
| 318 } | 318 } |
| 319 | 319 |
| 320 let testResult = tr.b.Statistics.mwu( | 320 let testResult = tr.b.math.Statistics.mwu( |
| 321 this.sampleValues, other.sampleValues, opt_alpha); | 321 this.sampleValues, other.sampleValues, opt_alpha); |
| 322 return testResult.significance; | 322 return testResult.significance; |
| 323 } | 323 } |
| 324 | 324 |
| 325 /* | 325 /* |
| 326 * Compute an approximation of percentile based on the counts in the bins. | 326 * Compute an approximation of percentile based on the counts in the bins. |
| 327 * If the real percentile lies within |this.range| then the result of | 327 * If the real percentile lies within |this.range| then the result of |
| 328 * the function will deviate from the real percentile by at most | 328 * the function will deviate from the real percentile by at most |
| 329 * the maximum width of the bin(s) within which the point(s) | 329 * the maximum width of the bin(s) within which the point(s) |
| 330 * from which the real percentile would be calculated lie. | 330 * from which the real percentile would be calculated lie. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 356 return bin.range.max; | 356 return bin.range.max; |
| 357 if (bin.range.max === Number.MAX_VALUE) | 357 if (bin.range.max === Number.MAX_VALUE) |
| 358 return bin.range.min; | 358 return bin.range.min; |
| 359 return bin.range.center; | 359 return bin.range.center; |
| 360 } | 360 } |
| 361 return this.allBins[this.allBins.length - 1].range.min; | 361 return this.allBins[this.allBins.length - 1].range.min; |
| 362 } | 362 } |
| 363 | 363 |
| 364 getBinForValue(value) { | 364 getBinForValue(value) { |
| 365 // Don't use subtraction to avoid arithmetic overflow. | 365 // Don't use subtraction to avoid arithmetic overflow. |
| 366 let binIndex = tr.b.findHighIndexInSortedArray( | 366 let binIndex = tr.b.math.findHighIndexInSortedArray( |
| 367 this.allBins, b => ((value < b.range.max) ? -1 : 1)); | 367 this.allBins, b => ((value < b.range.max) ? -1 : 1)); |
| 368 return this.allBins[binIndex] || this.allBins[this.allBins.length - 1]; | 368 return this.allBins[binIndex] || this.allBins[this.allBins.length - 1]; |
| 369 } | 369 } |
| 370 | 370 |
| 371 /** | 371 /** |
| 372 * @param {number|*} value | 372 * @param {number|*} value |
| 373 * @param {(!Object|!tr.v.d.DiagnosticMap)=} opt_diagnostics | 373 * @param {(!Object|!tr.v.d.DiagnosticMap)=} opt_diagnostics |
| 374 */ | 374 */ |
| 375 addSample(value, opt_diagnostics) { | 375 addSample(value, opt_diagnostics) { |
| 376 if (opt_diagnostics && | 376 if (opt_diagnostics && |
| 377 !(opt_diagnostics instanceof tr.v.d.DiagnosticMap)) { | 377 !(opt_diagnostics instanceof tr.v.d.DiagnosticMap)) { |
| 378 opt_diagnostics = tr.v.d.DiagnosticMap.fromObject(opt_diagnostics); | 378 opt_diagnostics = tr.v.d.DiagnosticMap.fromObject(opt_diagnostics); |
| 379 } | 379 } |
| 380 | 380 |
| 381 if (typeof(value) !== 'number' || isNaN(value)) { | 381 if (typeof(value) !== 'number' || isNaN(value)) { |
| 382 this.numNans++; | 382 this.numNans++; |
| 383 if (opt_diagnostics) { | 383 if (opt_diagnostics) { |
| 384 tr.b.Statistics.uniformlySampleStream(this.nanDiagnosticMaps, | 384 tr.b.math.Statistics.uniformlySampleStream(this.nanDiagnosticMaps, |
| 385 this.numNans, opt_diagnostics, MAX_DIAGNOSTIC_MAPS); | 385 this.numNans, opt_diagnostics, MAX_DIAGNOSTIC_MAPS); |
| 386 } | 386 } |
| 387 } else { | 387 } else { |
| 388 if (this.running_ === undefined) { | 388 if (this.running_ === undefined) { |
| 389 this.running_ = new tr.b.RunningStatistics(); | 389 this.running_ = new tr.b.math.RunningStatistics(); |
| 390 } | 390 } |
| 391 this.running_.add(value); | 391 this.running_.add(value); |
| 392 | 392 |
| 393 let bin = this.getBinForValue(value); | 393 let bin = this.getBinForValue(value); |
| 394 bin.addSample(value); | 394 bin.addSample(value); |
| 395 if (opt_diagnostics) { | 395 if (opt_diagnostics) { |
| 396 bin.addDiagnosticMap(opt_diagnostics); | 396 bin.addDiagnosticMap(opt_diagnostics); |
| 397 } | 397 } |
| 398 } | 398 } |
| 399 | 399 |
| 400 tr.b.Statistics.uniformlySampleStream(this.sampleValues_, | 400 tr.b.math.Statistics.uniformlySampleStream(this.sampleValues_, |
| 401 this.numValues + this.numNans, value, this.maxNumSampleValues); | 401 this.numValues + this.numNans, value, this.maxNumSampleValues); |
| 402 } | 402 } |
| 403 | 403 |
| 404 sampleValuesInto(samples) { | 404 sampleValuesInto(samples) { |
| 405 for (let sampleValue of this.sampleValues) { | 405 for (let sampleValue of this.sampleValues) { |
| 406 samples.push(sampleValue); | 406 samples.push(sampleValue); |
| 407 } | 407 } |
| 408 } | 408 } |
| 409 | 409 |
| 410 /** | 410 /** |
| (...skipping 14 matching lines...) Expand all Loading... |
| 425 return false; | 425 return false; |
| 426 } | 426 } |
| 427 for (let i = 0; i < this.binBoundariesDict_.length; ++i) { | 427 for (let i = 0; i < this.binBoundariesDict_.length; ++i) { |
| 428 let slice = this.binBoundariesDict_[i]; | 428 let slice = this.binBoundariesDict_[i]; |
| 429 let otherSlice = other.binBoundariesDict_[i]; | 429 let otherSlice = other.binBoundariesDict_[i]; |
| 430 if (slice instanceof Array) { | 430 if (slice instanceof Array) { |
| 431 if (!(otherSlice instanceof Array)) { | 431 if (!(otherSlice instanceof Array)) { |
| 432 return false; | 432 return false; |
| 433 } | 433 } |
| 434 if (slice[0] !== otherSlice[0] || | 434 if (slice[0] !== otherSlice[0] || |
| 435 !tr.b.approximately(slice[1], otherSlice[1]) || | 435 !tr.b.math.approximately(slice[1], otherSlice[1]) || |
| 436 slice[2] !== otherSlice[2]) { | 436 slice[2] !== otherSlice[2]) { |
| 437 return false; | 437 return false; |
| 438 } | 438 } |
| 439 } else { | 439 } else { |
| 440 if (otherSlice instanceof Array) { | 440 if (otherSlice instanceof Array) { |
| 441 return false; | 441 return false; |
| 442 } | 442 } |
| 443 if (!tr.b.approximately(slice, otherSlice)) { | 443 if (!tr.b.math.approximately(slice, otherSlice)) { |
| 444 return false; | 444 return false; |
| 445 } | 445 } |
| 446 } | 446 } |
| 447 } | 447 } |
| 448 return true; | 448 return true; |
| 449 } | 449 } |
| 450 | 450 |
| 451 /** | 451 /** |
| 452 * Add |other| to this Histogram in-place if they can be added. | 452 * Add |other| to this Histogram in-place if they can be added. |
| 453 * | 453 * |
| 454 * @param {!tr.v.Histogram} other | 454 * @param {!tr.v.Histogram} other |
| 455 */ | 455 */ |
| 456 addHistogram(other) { | 456 addHistogram(other) { |
| 457 if (!this.canAddHistogram(other)) { | 457 if (!this.canAddHistogram(other)) { |
| 458 throw new Error('Merging incompatible Histograms'); | 458 throw new Error('Merging incompatible Histograms'); |
| 459 } | 459 } |
| 460 | 460 |
| 461 tr.b.Statistics.mergeSampledStreams(this.nanDiagnosticMaps, this.numNans, | 461 tr.b.math.Statistics.mergeSampledStreams(this.nanDiagnosticMaps, |
| 462 other.nanDiagnosticMaps, other.numNans, MAX_DIAGNOSTIC_MAPS); | 462 this.numNans, other.nanDiagnosticMaps, other.numNans, |
| 463 tr.b.Statistics.mergeSampledStreams( | 463 MAX_DIAGNOSTIC_MAPS); |
| 464 tr.b.math.Statistics.mergeSampledStreams( |
| 464 this.sampleValues, this.numValues + this.numNans, | 465 this.sampleValues, this.numValues + this.numNans, |
| 465 other.sampleValues, other.numValues + other.numNans, | 466 other.sampleValues, other.numValues + other.numNans, |
| 466 (this.maxNumSampleValues + other.maxNumSampleValues) / 2); | 467 (this.maxNumSampleValues + other.maxNumSampleValues) / 2); |
| 467 this.numNans += other.numNans; | 468 this.numNans += other.numNans; |
| 468 | 469 |
| 469 if (other.running_ !== undefined) { | 470 if (other.running_ !== undefined) { |
| 470 if (this.running_ === undefined) { | 471 if (this.running_ === undefined) { |
| 471 this.running_ = new tr.b.RunningStatistics(); | 472 this.running_ = new tr.b.math.RunningStatistics(); |
| 472 } | 473 } |
| 473 this.running_ = this.running_.merge(other.running_); | 474 this.running_ = this.running_.merge(other.running_); |
| 474 } | 475 } |
| 475 | 476 |
| 476 for (let i = 0; i < this.allBins.length; ++i) { | 477 for (let i = 0; i < this.allBins.length; ++i) { |
| 477 this.allBins[i].addBin(other.allBins[i]); | 478 this.allBins[i].addBin(other.allBins[i]); |
| 478 } | 479 } |
| 479 | 480 |
| 480 let mergedFrom = this.diagnostics.get(tr.v.d.MERGED_FROM_DIAGNOSTIC_KEY); | 481 let mergedFrom = this.diagnostics.get(tr.v.d.MERGED_FROM_DIAGNOSTIC_KEY); |
| 481 if (!mergedFrom) { | 482 if (!mergedFrom) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 } | 544 } |
| 544 if (statName === 'std') { | 545 if (statName === 'std') { |
| 545 if (this.standardDeviation === undefined) return undefined; | 546 if (this.standardDeviation === undefined) return undefined; |
| 546 return new tr.b.Scalar(this.unit, this.standardDeviation); | 547 return new tr.b.Scalar(this.unit, this.standardDeviation); |
| 547 } | 548 } |
| 548 if (statName === 'geometricMean') { | 549 if (statName === 'geometricMean') { |
| 549 return new tr.b.Scalar(this.unit, this.geometricMean); | 550 return new tr.b.Scalar(this.unit, this.geometricMean); |
| 550 } | 551 } |
| 551 if (statName === 'min' || statName === 'max' || statName === 'sum') { | 552 if (statName === 'min' || statName === 'max' || statName === 'sum') { |
| 552 if (this.running_ === undefined) { | 553 if (this.running_ === undefined) { |
| 553 this.running_ = new tr.b.RunningStatistics(); | 554 this.running_ = new tr.b.math.RunningStatistics(); |
| 554 } | 555 } |
| 555 return new tr.b.Scalar(this.unit, this.running_[statName]); | 556 return new tr.b.Scalar(this.unit, this.running_[statName]); |
| 556 } | 557 } |
| 557 if (statName === 'nans') { | 558 if (statName === 'nans') { |
| 558 return new tr.b.Scalar( | 559 return new tr.b.Scalar( |
| 559 tr.b.Unit.byName.count_smallerIsBetter, this.numNans); | 560 tr.b.Unit.byName.count_smallerIsBetter, this.numNans); |
| 560 } | 561 } |
| 561 if (statName === 'count') { | 562 if (statName === 'count') { |
| 562 return new tr.b.Scalar( | 563 return new tr.b.Scalar( |
| 563 tr.b.Unit.byName.count_smallerIsBetter, this.numValues); | 564 tr.b.Unit.byName.count_smallerIsBetter, this.numValues); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 594 thisStat.unit.correspondingDeltaUnit, deltaValue); | 595 thisStat.unit.correspondingDeltaUnit, deltaValue); |
| 595 } | 596 } |
| 596 | 597 |
| 597 if (statName === Z_SCORE_NAME) { | 598 if (statName === Z_SCORE_NAME) { |
| 598 return new tr.b.Scalar( | 599 return new tr.b.Scalar( |
| 599 tr.b.Unit.byName['sigmaDelta' + suffix], | 600 tr.b.Unit.byName['sigmaDelta' + suffix], |
| 600 (this.average - opt_referenceHistogram.average) / | 601 (this.average - opt_referenceHistogram.average) / |
| 601 opt_referenceHistogram.standardDeviation); | 602 opt_referenceHistogram.standardDeviation); |
| 602 } | 603 } |
| 603 | 604 |
| 604 let mwu = opt_mwu || tr.b.Statistics.mwu( | 605 let mwu = opt_mwu || tr.b.math.Statistics.mwu( |
| 605 this.sampleValues, opt_referenceHistogram.sampleValues); | 606 this.sampleValues, opt_referenceHistogram.sampleValues); |
| 606 if (statName === P_VALUE_NAME) { | 607 if (statName === P_VALUE_NAME) { |
| 607 return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber, mwu.p); | 608 return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber, mwu.p); |
| 608 } | 609 } |
| 609 if (statName === U_STATISTIC_NAME) { | 610 if (statName === U_STATISTIC_NAME) { |
| 610 return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber, mwu.U); | 611 return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber, mwu.U); |
| 611 } | 612 } |
| 612 | 613 |
| 613 throw new Error('Unrecognized statistic name: ' + statName); | 614 throw new Error('Unrecognized statistic name: ' + statName); |
| 614 } | 615 } |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 945 * If no other bin boundaries are added, then |minBinBoundary| will be the | 946 * If no other bin boundaries are added, then |minBinBoundary| will be the |
| 946 * boundary between the underflow bin and the overflow bin. | 947 * boundary between the underflow bin and the overflow bin. |
| 947 * If no other bin boundaries are added and |minBinBoundary| is either | 948 * If no other bin boundaries are added and |minBinBoundary| is either |
| 948 * -Number.MAX_VALUE or +Number.MAX_VALUE, then only a single binRange will | 949 * -Number.MAX_VALUE or +Number.MAX_VALUE, then only a single binRange will |
| 949 * be built. | 950 * be built. |
| 950 * | 951 * |
| 951 * @param {number} minBinBoundary The minimum boundary between bins. | 952 * @param {number} minBinBoundary The minimum boundary between bins. |
| 952 */ | 953 */ |
| 953 constructor(minBinBoundary) { | 954 constructor(minBinBoundary) { |
| 954 this.builder_ = [minBinBoundary]; | 955 this.builder_ = [minBinBoundary]; |
| 955 this.range_ = new tr.b.Range(); | 956 this.range_ = new tr.b.math.Range(); |
| 956 this.range_.addValue(minBinBoundary); | 957 this.range_.addValue(minBinBoundary); |
| 957 this.binRanges_ = undefined; | 958 this.binRanges_ = undefined; |
| 958 } | 959 } |
| 959 | 960 |
| 960 get range() { | 961 get range() { |
| 961 return this.range_; | 962 return this.range_; |
| 962 } | 963 } |
| 963 | 964 |
| 964 asDict() { | 965 asDict() { |
| 965 if (this.builder_.length === 1 && this.builder_[0] === Number.MAX_VALUE) { | 966 if (this.builder_.length === 1 && this.builder_[0] === Number.MAX_VALUE) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1009 | 1010 |
| 1010 default: | 1011 default: |
| 1011 throw new Error('Unrecognized HistogramBinBoundaries slice type'); | 1012 throw new Error('Unrecognized HistogramBinBoundaries slice type'); |
| 1012 } | 1013 } |
| 1013 } | 1014 } |
| 1014 HISTOGRAM_BIN_BOUNDARIES_CACHE.set(cacheKey, binBoundaries); | 1015 HISTOGRAM_BIN_BOUNDARIES_CACHE.set(cacheKey, binBoundaries); |
| 1015 return binBoundaries; | 1016 return binBoundaries; |
| 1016 } | 1017 } |
| 1017 | 1018 |
| 1018 /** | 1019 /** |
| 1019 * @return {!Array.<!tr.b.Range>} | 1020 * @return {!Array.<!tr.b.math.Range>} |
| 1020 */ | 1021 */ |
| 1021 get binRanges() { | 1022 get binRanges() { |
| 1022 if (this.binRanges_ === undefined) { | 1023 if (this.binRanges_ === undefined) { |
| 1023 this.build_(); | 1024 this.build_(); |
| 1024 } | 1025 } |
| 1025 return this.binRanges_; | 1026 return this.binRanges_; |
| 1026 } | 1027 } |
| 1027 | 1028 |
| 1028 build_() { | 1029 build_() { |
| 1029 if (typeof this.builder_[0] !== 'number') { | 1030 if (typeof this.builder_[0] !== 'number') { |
| 1030 throw new Error('Invalid start of builder_'); | 1031 throw new Error('Invalid start of builder_'); |
| 1031 } | 1032 } |
| 1032 this.binRanges_ = []; | 1033 this.binRanges_ = []; |
| 1033 let prevBoundary = this.builder_[0]; | 1034 let prevBoundary = this.builder_[0]; |
| 1034 | 1035 |
| 1035 if (prevBoundary > -Number.MAX_VALUE) { | 1036 if (prevBoundary > -Number.MAX_VALUE) { |
| 1036 // underflow bin | 1037 // underflow bin |
| 1037 this.binRanges_.push(tr.b.Range.fromExplicitRange(-Number.MAX_VALUE, | 1038 this.binRanges_.push(tr.b.math.Range.fromExplicitRange( |
| 1038 prevBoundary)); | 1039 -Number.MAX_VALUE, prevBoundary)); |
| 1039 } | 1040 } |
| 1040 | 1041 |
| 1041 for (let slice of this.builder_.slice(1)) { | 1042 for (let slice of this.builder_.slice(1)) { |
| 1042 if (!(slice instanceof Array)) { | 1043 if (!(slice instanceof Array)) { |
| 1043 this.binRanges_.push( | 1044 this.binRanges_.push( |
| 1044 tr.b.Range.fromExplicitRange(prevBoundary, slice)); | 1045 tr.b.math.Range.fromExplicitRange(prevBoundary, slice)); |
| 1045 prevBoundary = slice; | 1046 prevBoundary = slice; |
| 1046 continue; | 1047 continue; |
| 1047 } | 1048 } |
| 1048 let nextMaxBinBoundary = slice[1]; | 1049 let nextMaxBinBoundary = slice[1]; |
| 1049 let binCount = slice[2]; | 1050 let binCount = slice[2]; |
| 1050 let sliceMinBinBoundary = prevBoundary; | 1051 let sliceMinBinBoundary = prevBoundary; |
| 1051 | 1052 |
| 1052 switch (slice[0]) { | 1053 switch (slice[0]) { |
| 1053 case HistogramBinBoundaries.SLICE_TYPE.LINEAR: | 1054 case HistogramBinBoundaries.SLICE_TYPE.LINEAR: |
| 1054 { | 1055 { |
| 1055 let binWidth = (nextMaxBinBoundary - prevBoundary) / binCount; | 1056 let binWidth = (nextMaxBinBoundary - prevBoundary) / binCount; |
| 1056 for (let i = 1; i < binCount; i++) { | 1057 for (let i = 1; i < binCount; i++) { |
| 1057 let boundary = sliceMinBinBoundary + i * binWidth; | 1058 let boundary = sliceMinBinBoundary + i * binWidth; |
| 1058 this.binRanges_.push(tr.b.Range.fromExplicitRange( | 1059 this.binRanges_.push(tr.b.math.Range.fromExplicitRange( |
| 1059 prevBoundary, boundary)); | 1060 prevBoundary, boundary)); |
| 1060 prevBoundary = boundary; | 1061 prevBoundary = boundary; |
| 1061 } | 1062 } |
| 1062 break; | 1063 break; |
| 1063 } | 1064 } |
| 1064 | 1065 |
| 1065 case HistogramBinBoundaries.SLICE_TYPE.EXPONENTIAL: | 1066 case HistogramBinBoundaries.SLICE_TYPE.EXPONENTIAL: |
| 1066 { | 1067 { |
| 1067 let binExponentWidth = | 1068 let binExponentWidth = |
| 1068 Math.log(nextMaxBinBoundary / prevBoundary) / binCount; | 1069 Math.log(nextMaxBinBoundary / prevBoundary) / binCount; |
| 1069 for (let i = 1; i < binCount; i++) { | 1070 for (let i = 1; i < binCount; i++) { |
| 1070 let boundary = sliceMinBinBoundary * Math.exp( | 1071 let boundary = sliceMinBinBoundary * Math.exp( |
| 1071 i * binExponentWidth); | 1072 i * binExponentWidth); |
| 1072 this.binRanges_.push(tr.b.Range.fromExplicitRange( | 1073 this.binRanges_.push(tr.b.math.Range.fromExplicitRange( |
| 1073 prevBoundary, boundary)); | 1074 prevBoundary, boundary)); |
| 1074 prevBoundary = boundary; | 1075 prevBoundary = boundary; |
| 1075 } | 1076 } |
| 1076 break; | 1077 break; |
| 1077 } | 1078 } |
| 1078 | 1079 |
| 1079 default: | 1080 default: |
| 1080 throw new Error('Unrecognized HistogramBinBoundaries slice type'); | 1081 throw new Error('Unrecognized HistogramBinBoundaries slice type'); |
| 1081 } | 1082 } |
| 1082 this.binRanges_.push(tr.b.Range.fromExplicitRange( | 1083 this.binRanges_.push(tr.b.math.Range.fromExplicitRange( |
| 1083 prevBoundary, nextMaxBinBoundary)); | 1084 prevBoundary, nextMaxBinBoundary)); |
| 1084 prevBoundary = nextMaxBinBoundary; | 1085 prevBoundary = nextMaxBinBoundary; |
| 1085 } | 1086 } |
| 1086 if (prevBoundary < Number.MAX_VALUE) { | 1087 if (prevBoundary < Number.MAX_VALUE) { |
| 1087 // overflow bin | 1088 // overflow bin |
| 1088 this.binRanges_.push(tr.b.Range.fromExplicitRange( | 1089 this.binRanges_.push(tr.b.math.Range.fromExplicitRange( |
| 1089 prevBoundary, Number.MAX_VALUE)); | 1090 prevBoundary, Number.MAX_VALUE)); |
| 1090 } | 1091 } |
| 1091 } | 1092 } |
| 1092 | 1093 |
| 1093 /** | 1094 /** |
| 1094 * Add a bin boundary |nextMaxBinBoundary| to the builder. | 1095 * Add a bin boundary |nextMaxBinBoundary| to the builder. |
| 1095 * | 1096 * |
| 1096 * This operation effectively corresponds to appending a new central bin | 1097 * This operation effectively corresponds to appending a new central bin |
| 1097 * with the range [this.range.max, nextMaxBinBoundary]. | 1098 * with the range [this.range.max, nextMaxBinBoundary]. |
| 1098 * | 1099 * |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 Histogram, | 1260 Histogram, |
| 1260 HistogramBinBoundaries, | 1261 HistogramBinBoundaries, |
| 1261 P_VALUE_NAME, | 1262 P_VALUE_NAME, |
| 1262 U_STATISTIC_NAME, | 1263 U_STATISTIC_NAME, |
| 1263 Z_SCORE_NAME, | 1264 Z_SCORE_NAME, |
| 1264 percentFromString, | 1265 percentFromString, |
| 1265 percentToString, | 1266 percentToString, |
| 1266 }; | 1267 }; |
| 1267 }); | 1268 }); |
| 1268 </script> | 1269 </script> |
| OLD | NEW |