OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 | |
6 /** | |
7 * @fileoverview Helper functions for doing intersections and iteration | |
8 * over sorted arrays and intervals. | |
9 * | |
10 */ | |
11 cr.define('gpu', function() { | |
12 /** | |
13 * Finds the first index in the array whose value is >= loVal. | |
14 * | |
15 * The key for the search is defined by the mapFn. This array must | |
16 * be prearranged such that ary.map(mapFn) would also be sorted in | |
17 * ascending order. | |
18 * | |
19 * @param {Array} ary An array of arbitrary objects. | |
20 * @param {function():*} mapFn Callback that produces a key value | |
21 * from an element in ary. | |
22 * @param {number} loVal Value for which to search. | |
23 * @return {Number} Offset o into ary where all ary[i] for i <= o | |
24 * are < loVal, or ary.length if loVal is greater than all elements in | |
25 * the array. | |
26 */ | |
27 function findLowIndexInSortedArray(ary, mapFn, loVal) { | |
28 if (ary.length == 0) | |
29 return 1; | |
30 | |
31 var low = 0; | |
32 var high = ary.length - 1; | |
33 var i, comparison; | |
34 var hitPos = -1; | |
35 while (low <= high) { | |
36 i = Math.floor((low + high) / 2); | |
37 comparison = mapFn(ary[i]) - loVal; | |
38 if (comparison < 0) { | |
39 low = i + 1; continue; | |
40 } else if (comparison > 0) { | |
41 high = i - 1; continue; | |
42 } else { | |
43 hitPos = i; | |
44 high = i - 1; | |
45 } | |
46 } | |
47 // return where we hit, or failing that the low pos | |
48 return hitPos != -1 ? hitPos : low; | |
49 } | |
50 | |
51 /** | |
52 * Finds an index in an array of intervals that either | |
53 * intersects the provided loVal, or if no intersection is found, | |
54 * the index of the first interval whose start is > loVal. | |
55 * | |
56 * The array of intervals is defined implicitly via two mapping functions | |
57 * over the provided ary. mapLoFn determines the lower value of the interval, | |
58 * mapWidthFn the width. Intersection is lower-inclusive, e.g. [lo,lo+w). | |
59 * | |
60 * The array of intervals formed by this mapping must be non-overlapping and | |
61 * sorted in ascending order by loVal. | |
62 * | |
63 * @param {Array} ary An array of objects that can be converted into sorted | |
64 * nonoverlapping ranges [x,y) using the mapLoFn and mapWidth. | |
65 * @param {function():*} mapLoFn Callback that produces the low value for the | |
66 * interval represented by an element in the array. | |
67 * @param {function():*} mapLoFn Callback that produces the width for the | |
68 * interval represented by an element in the array. | |
69 * @param {number} loVal The low value for the search. | |
70 * @return {Number} An index in the array that intersects or is first-above | |
71 * loVal, -1 if none found and loVal is below than all the intervals, | |
72 * ary.length if loVal is greater than all the intervals. | |
73 */ | |
74 function findLowIndexInSortedIntervals(ary, mapLoFn, mapWidthFn, loVal) { | |
75 var first = findLowIndexInSortedArray(ary, mapLoFn, loVal); | |
76 if (first == 0) { | |
77 if (loVal >= mapLoFn(ary[0]) && | |
78 loVal < mapLoFn(ary[0] + mapWidthFn(ary[0]))) { | |
79 return 0; | |
80 } else { | |
81 return -1; | |
82 } | |
83 } else if (first <= ary.length && | |
84 loVal >= mapLoFn(ary[first - 1]) && | |
85 loVal < mapLoFn(ary[first - 1]) + mapWidthFn(ary[first - 1])) { | |
86 return first - 1; | |
87 } else { | |
88 return ary.length; | |
89 } | |
90 } | |
91 | |
92 /** | |
93 * Calls cb for all intervals in the implicit array of intervals | |
94 * defnied by ary, mapLoFn and mapHiFn that intersect the range | |
95 * [loVal,hiVal) | |
96 * | |
97 * This function uses the same scheme as findLowIndexInSortedArray | |
98 * to define the intervals. The same restrictions on sortedness and | |
99 * non-overlappingness apply. | |
100 * | |
101 * @param {Array} ary An array of objects that can be converted into sorted | |
102 * nonoverlapping ranges [x,y) using the mapLoFn and mapWidth. | |
103 * @param {function():*} mapLoFn Callback that produces the low value for the | |
104 * interval represented by an element in the array. | |
105 * @param {function():*} mapLoFn Callback that produces the width for the | |
106 * interval represented by an element in the array. | |
107 * @param {number} The low value for the search, inclusive. | |
108 * @param {number} loVal The high value for the search, non inclusive. | |
109 * @param {function():*} cb The function to run for intersecting intervals. | |
110 */ | |
111 function iterateOverIntersectingIntervals(ary, mapLoFn, mapWidthFn, loVal, | |
112 hiVal, cb) { | |
113 if (loVal > hiVal) return; | |
114 | |
115 var i = findLowIndexInSortedArray(ary, mapLoFn, loVal); | |
116 if (i == -1) { | |
117 return; | |
118 } | |
119 if (i > 0) { | |
120 var hi = mapLoFn(ary[i - 1]) + mapWidthFn(ary[i - 1]); | |
121 if (hi >= loVal) { | |
122 cb(ary[i - 1]); | |
123 } | |
124 } | |
125 if (i == ary.length) { | |
126 return; | |
127 } | |
128 | |
129 for (var n = ary.length; i < n; i++) { | |
130 var lo = mapLoFn(ary[i]); | |
131 if (lo >= hiVal) | |
132 break; | |
133 cb(ary[i]); | |
134 } | |
135 } | |
136 | |
137 /** | |
138 * Non iterative version of iterateOverIntersectingIntervals. | |
139 * | |
140 * @return {Array} Array of elements in ary that intersect loVal, hiVal. | |
141 */ | |
142 function getIntersectingIntervals(ary, mapLoFn, mapWidthFn, loVal, hiVal) { | |
143 var tmp = []; | |
144 iterateOverIntersectingIntervals(ary, mapLoFn, mapWidthFn, loVal, hiVal, | |
145 function(d) { | |
146 tmp.push(d); | |
147 }); | |
148 return tmp; | |
149 } | |
150 | |
151 return { | |
152 findLowIndexInSortedArray: findLowIndexInSortedArray, | |
153 findLowIndexInSortedIntervals: findLowIndexInSortedIntervals, | |
154 iterateOverIntersectingIntervals: iterateOverIntersectingIntervals, | |
155 getIntersectingIntervals: getIntersectingIntervals | |
156 }; | |
157 }); | |
OLD | NEW |