| OLD | NEW |
| (Empty) |
| 1 <!DOCTYPE html> | |
| 2 <!-- | |
| 3 Copyright (c) 2014 The Chromium Authors. All rights reserved. | |
| 4 Use of this source code is governed by a BSD-style license that can be | |
| 5 found in the LICENSE file. | |
| 6 --> | |
| 7 | |
| 8 <link rel="import" href="/tracing/base/base.html"> | |
| 9 <link rel="import" href="/tracing/base/iteration_helpers.html"> | |
| 10 <link rel="import" href="/tracing/base/math.html"> | |
| 11 | |
| 12 <script> | |
| 13 'use strict'; | |
| 14 | |
| 15 /** | |
| 16 * @fileoverview Quick range computations. | |
| 17 */ | |
| 18 tr.exportTo('tr.b', function() { | |
| 19 function Range() { | |
| 20 this.isEmpty_ = true; | |
| 21 this.min_ = undefined; | |
| 22 this.max_ = undefined; | |
| 23 } | |
| 24 | |
| 25 Range.prototype = { | |
| 26 __proto__: Object.prototype, | |
| 27 | |
| 28 reset: function() { | |
| 29 this.isEmpty_ = true; | |
| 30 this.min_ = undefined; | |
| 31 this.max_ = undefined; | |
| 32 }, | |
| 33 | |
| 34 get isEmpty() { | |
| 35 return this.isEmpty_; | |
| 36 }, | |
| 37 | |
| 38 addRange: function(range) { | |
| 39 if (range.isEmpty) | |
| 40 return; | |
| 41 this.addValue(range.min); | |
| 42 this.addValue(range.max); | |
| 43 }, | |
| 44 | |
| 45 addValue: function(value) { | |
| 46 if (this.isEmpty_) { | |
| 47 this.max_ = value; | |
| 48 this.min_ = value; | |
| 49 this.isEmpty_ = false; | |
| 50 return; | |
| 51 } | |
| 52 this.max_ = Math.max(this.max_, value); | |
| 53 this.min_ = Math.min(this.min_, value); | |
| 54 }, | |
| 55 | |
| 56 set min(min) { | |
| 57 this.isEmpty_ = false; | |
| 58 this.min_ = min; | |
| 59 }, | |
| 60 | |
| 61 get min() { | |
| 62 if (this.isEmpty_) | |
| 63 return undefined; | |
| 64 return this.min_; | |
| 65 }, | |
| 66 | |
| 67 get max() { | |
| 68 if (this.isEmpty_) | |
| 69 return undefined; | |
| 70 return this.max_; | |
| 71 }, | |
| 72 | |
| 73 set max(max) { | |
| 74 this.isEmpty_ = false; | |
| 75 this.max_ = max; | |
| 76 }, | |
| 77 | |
| 78 get range() { | |
| 79 if (this.isEmpty_) | |
| 80 return undefined; | |
| 81 return this.max_ - this.min_; | |
| 82 }, | |
| 83 | |
| 84 get center() { | |
| 85 return (this.min_ + this.max_) * 0.5; | |
| 86 }, | |
| 87 | |
| 88 get duration() { | |
| 89 if (this.isEmpty_) | |
| 90 return 0; | |
| 91 return this.max_ - this.min_; | |
| 92 }, | |
| 93 | |
| 94 /** | |
| 95 * Get a new Range spanning the powers (of opt_base || 10) that enclose | |
| 96 * |this| Range. | |
| 97 * If |this| is empty, returns a new empty Range. | |
| 98 * | |
| 99 * @param {number=} opt_base Defaults to 10. | |
| 100 * @return {!Range} | |
| 101 */ | |
| 102 enclosingPowers(opt_base) { | |
| 103 if (this.isEmpty) return new Range(); | |
| 104 return Range.fromExplicitRange( | |
| 105 tr.b.lesserPower(this.min_, opt_base), | |
| 106 tr.b.greaterPower(this.max_, opt_base)); | |
| 107 }, | |
| 108 | |
| 109 normalize: function(x) { | |
| 110 return tr.b.normalize(x, this.min, this.max); | |
| 111 }, | |
| 112 | |
| 113 lerp: function(x) { | |
| 114 return tr.b.lerp(x, this.min, this.max); | |
| 115 }, | |
| 116 | |
| 117 clamp: function(x) { | |
| 118 return tr.b.clamp(x, this.min, this.max); | |
| 119 }, | |
| 120 | |
| 121 equals: function(that) { | |
| 122 if (this.isEmpty && that.isEmpty) | |
| 123 return true; | |
| 124 if (this.isEmpty !== that.isEmpty) | |
| 125 return false; | |
| 126 return (tr.b.approximately(this.min, that.min) && | |
| 127 tr.b.approximately(this.max, that.max)); | |
| 128 }, | |
| 129 | |
| 130 containsExplicitRangeInclusive: function(min, max) { | |
| 131 if (this.isEmpty) | |
| 132 return false; | |
| 133 return this.min_ <= min && max <= this.max_; | |
| 134 }, | |
| 135 | |
| 136 containsExplicitRangeExclusive: function(min, max) { | |
| 137 if (this.isEmpty) | |
| 138 return false; | |
| 139 return this.min_ < min && max < this.max_; | |
| 140 }, | |
| 141 | |
| 142 intersectsExplicitRangeInclusive: function(min, max) { | |
| 143 if (this.isEmpty) | |
| 144 return false; | |
| 145 return this.min_ <= max && min <= this.max_; | |
| 146 }, | |
| 147 | |
| 148 intersectsExplicitRangeExclusive: function(min, max) { | |
| 149 if (this.isEmpty) | |
| 150 return false; | |
| 151 return this.min_ < max && min < this.max_; | |
| 152 }, | |
| 153 | |
| 154 containsRangeInclusive: function(range) { | |
| 155 if (range.isEmpty) | |
| 156 return false; | |
| 157 return this.containsExplicitRangeInclusive(range.min_, range.max_); | |
| 158 }, | |
| 159 | |
| 160 containsRangeExclusive: function(range) { | |
| 161 if (range.isEmpty) | |
| 162 return false; | |
| 163 return this.containsExplicitRangeExclusive(range.min_, range.max_); | |
| 164 }, | |
| 165 | |
| 166 intersectsRangeInclusive: function(range) { | |
| 167 if (range.isEmpty) | |
| 168 return false; | |
| 169 return this.intersectsExplicitRangeInclusive(range.min_, range.max_); | |
| 170 }, | |
| 171 | |
| 172 intersectsRangeExclusive: function(range) { | |
| 173 if (range.isEmpty) | |
| 174 return false; | |
| 175 return this.intersectsExplicitRangeExclusive(range.min_, range.max_); | |
| 176 }, | |
| 177 | |
| 178 findExplicitIntersectionDuration: function(min, max) { | |
| 179 var min = Math.max(this.min, min); | |
| 180 var max = Math.min(this.max, max); | |
| 181 if (max < min) | |
| 182 return 0; | |
| 183 return max - min; | |
| 184 }, | |
| 185 | |
| 186 findIntersection: function(range) { | |
| 187 if (this.isEmpty || range.isEmpty) | |
| 188 return new Range(); | |
| 189 | |
| 190 var min = Math.max(this.min, range.min); | |
| 191 var max = Math.min(this.max, range.max); | |
| 192 | |
| 193 if (max < min) | |
| 194 return new Range(); | |
| 195 | |
| 196 return Range.fromExplicitRange(min, max); | |
| 197 }, | |
| 198 | |
| 199 toJSON: function() { | |
| 200 if (this.isEmpty_) | |
| 201 return {isEmpty: true}; | |
| 202 return { | |
| 203 isEmpty: false, | |
| 204 max: this.max, | |
| 205 min: this.min | |
| 206 }; | |
| 207 }, | |
| 208 | |
| 209 /** | |
| 210 * Returns a slice of the input array that intersects with this range | |
| 211 * inclusively. | |
| 212 * If the range does not have a min, it is treated as unbounded from below. | |
| 213 * Similarly, if max is undefined, the range is unbounded from above. | |
| 214 * | |
| 215 * @param {Array} array The array of elements to be filtered. | |
| 216 * @param {Funcation=} opt_keyFunc A function that extracts a numeric value, | |
| 217 * to be used in comparisons, from an element of the array. If not | |
| 218 * specified, array elements themselves will be used. | |
| 219 * @param {Object=} opt_this An optional this argument to be passed to | |
| 220 * opt_keyFunc. | |
| 221 */ | |
| 222 filterArray: function(array, opt_keyFunc, opt_this) { | |
| 223 if (this.isEmpty_) | |
| 224 return []; | |
| 225 // Binary search. |test| is a function that should return true when we | |
| 226 // need to explore the left branch and false to explore the right branch. | |
| 227 function binSearch(test) { | |
| 228 var i0 = 0; | |
| 229 var i1 = array.length; | |
| 230 while (i0 < i1) { | |
| 231 var i = Math.trunc((i0 + i1) / 2); | |
| 232 if (test(i)) | |
| 233 i1 = i; // Explore the left branch. | |
| 234 else | |
| 235 i0 = i + 1; // Explore the right branch. | |
| 236 } | |
| 237 return i1; | |
| 238 } | |
| 239 | |
| 240 var keyFunc = opt_keyFunc || tr.b.identity; | |
| 241 function getValue(index) { | |
| 242 return keyFunc.call(opt_this, array[index]); | |
| 243 } | |
| 244 | |
| 245 var first = binSearch(function(i) { | |
| 246 return this.min_ === undefined || this.min_ <= getValue(i); | |
| 247 }.bind(this)); | |
| 248 var last = binSearch(function(i) { | |
| 249 return this.max_ !== undefined && this.max_ < getValue(i); | |
| 250 }.bind(this)); | |
| 251 return array.slice(first, last); | |
| 252 } | |
| 253 }; | |
| 254 | |
| 255 Range.fromDict = function(d) { | |
| 256 if (d.isEmpty === true) | |
| 257 return new Range(); | |
| 258 if (d.isEmpty === false) { | |
| 259 var range = new Range(); | |
| 260 range.min = d.min; | |
| 261 range.max = d.max; | |
| 262 return range; | |
| 263 } | |
| 264 throw new Error('Not a range'); | |
| 265 }; | |
| 266 | |
| 267 Range.fromExplicitRange = function(min, max) { | |
| 268 var range = new Range(); | |
| 269 range.min = min; | |
| 270 range.max = max; | |
| 271 return range; | |
| 272 }; | |
| 273 | |
| 274 Range.compareByMinTimes = function(a, b) { | |
| 275 if (!a.isEmpty && !b.isEmpty) | |
| 276 return a.min_ - b.min_; | |
| 277 | |
| 278 if (a.isEmpty && !b.isEmpty) | |
| 279 return -1; | |
| 280 | |
| 281 if (!a.isEmpty && b.isEmpty) | |
| 282 return 1; | |
| 283 | |
| 284 return 0; | |
| 285 }; | |
| 286 | |
| 287 Range.PERCENT_RANGE = Range.fromExplicitRange(0, 1); | |
| 288 Object.freeze(Range.PERCENT_RANGE); | |
| 289 | |
| 290 return { | |
| 291 Range, | |
| 292 }; | |
| 293 }); | |
| 294 </script> | |
| OLD | NEW |