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 |