Skip to content

Commit 1e87f40

Browse files
authored
Fix stack overflow for some degenerate data cases (#65)
* fix pivot selection * add regression test * fix linting
1 parent 3a6f0f0 commit 1e87f40

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

index.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,22 @@ function upperBound(value, arr) {
343343
function sort(values, boxes, indices, left, right, nodeSize) {
344344
if (Math.floor(left / nodeSize) >= Math.floor(right / nodeSize)) return;
345345

346-
const pivot = values[(left + right) >> 1];
346+
// apply median of three method
347+
const start = values[left];
348+
const mid = values[(left + right) >> 1];
349+
const end = values[right];
350+
351+
let pivot = end;
352+
353+
const x = Math.max(start, mid);
354+
if (end > x) {
355+
pivot = x;
356+
} else if (x === start) {
357+
pivot = Math.max(mid, end);
358+
} else if (x === mid) {
359+
pivot = Math.max(start, end);
360+
}
361+
347362
let i = left - 1;
348363
let j = right + 1;
349364

test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,32 @@ test('reconstructs an index from SharedArrayBuffer', () => {
222222
assert.deepEqual(index, index2);
223223
});
224224

225+
test('quicksort should work with an inbalanced dataset', () => {
226+
const n = 15000;
227+
const index = new Flatbush(2 * n);
228+
229+
function linspace(start, stop, num, endpoint = true) {
230+
const div = endpoint ? (num - 1) : num;
231+
const step = (stop - start) / div;
232+
return Array.from({length: num}, (_, i) => start + step * i);
233+
}
234+
235+
const items = linspace(0, 1000, n);
236+
const items2 = linspace(0, 1000, n);
237+
238+
for (const p of items) {
239+
index.add(p, 0, p, 0);
240+
}
241+
242+
for (const p of items2) {
243+
index.add(p, 0, p, 0);
244+
}
245+
246+
index.finish();
247+
248+
assert.doesNotThrow(() => {
249+
index.search(-100, -1, 15000, 1);
250+
});
251+
});
252+
225253
function compare(a, b) { return a - b; }

0 commit comments

Comments
 (0)