| import ascending from "./ascending.js"; |
| import descending from "./descending.js"; |
|
|
| export default function bisector(f) { |
| let compare1, compare2, delta; |
|
|
| |
| |
| |
| |
| |
| if (f.length !== 2) { |
| compare1 = ascending; |
| compare2 = (d, x) => ascending(f(d), x); |
| delta = (d, x) => f(d) - x; |
| } else { |
| compare1 = f === ascending || f === descending ? f : zero; |
| compare2 = f; |
| delta = f; |
| } |
|
|
| function left(a, x, lo = 0, hi = a.length) { |
| if (lo < hi) { |
| if (compare1(x, x) !== 0) return hi; |
| do { |
| const mid = (lo + hi) >>> 1; |
| if (compare2(a[mid], x) < 0) lo = mid + 1; |
| else hi = mid; |
| } while (lo < hi); |
| } |
| return lo; |
| } |
|
|
| function right(a, x, lo = 0, hi = a.length) { |
| if (lo < hi) { |
| if (compare1(x, x) !== 0) return hi; |
| do { |
| const mid = (lo + hi) >>> 1; |
| if (compare2(a[mid], x) <= 0) lo = mid + 1; |
| else hi = mid; |
| } while (lo < hi); |
| } |
| return lo; |
| } |
|
|
| function center(a, x, lo = 0, hi = a.length) { |
| const i = left(a, x, lo, hi - 1); |
| return i > lo && delta(a[i - 1], x) > -delta(a[i], x) ? i - 1 : i; |
| } |
|
|
| return {left, center, right}; |
| } |
|
|
| function zero() { |
| return 0; |
| } |
|
|