(f)
| 2 | import descending from "./descending.js"; |
| 3 | |
| 4 | export default function bisector(f) { |
| 5 | let compare1, compare2, delta; |
| 6 | |
| 7 | // If an accessor is specified, promote it to a comparator. In this case we |
| 8 | // can test whether the search value is (self-) comparable. We can’t do this |
| 9 | // for a comparator (except for specific, known comparators) because we can’t |
| 10 | // tell if the comparator is symmetric, and an asymmetric comparator can’t be |
| 11 | // used to test whether a single value is comparable. |
| 12 | if (f.length !== 2) { |
| 13 | compare1 = ascending; |
| 14 | compare2 = (d, x) => ascending(f(d), x); |
| 15 | delta = (d, x) => f(d) - x; |
| 16 | } else { |
| 17 | compare1 = f === ascending || f === descending ? f : zero; |
| 18 | compare2 = f; |
| 19 | delta = f; |
| 20 | } |
| 21 | |
| 22 | function left(a, x, lo = 0, hi = a.length) { |
| 23 | if (lo < hi) { |
| 24 | if (compare1(x, x) !== 0) return hi; |
| 25 | do { |
| 26 | const mid = (lo + hi) >>> 1; |
| 27 | if (compare2(a[mid], x) < 0) lo = mid + 1; |
| 28 | else hi = mid; |
| 29 | } while (lo < hi); |
| 30 | } |
| 31 | return lo; |
| 32 | } |
| 33 | |
| 34 | function right(a, x, lo = 0, hi = a.length) { |
| 35 | if (lo < hi) { |
| 36 | if (compare1(x, x) !== 0) return hi; |
| 37 | do { |
| 38 | const mid = (lo + hi) >>> 1; |
| 39 | if (compare2(a[mid], x) <= 0) lo = mid + 1; |
| 40 | else hi = mid; |
| 41 | } while (lo < hi); |
| 42 | } |
| 43 | return lo; |
| 44 | } |
| 45 | |
| 46 | function center(a, x, lo = 0, hi = a.length) { |
| 47 | const i = left(a, x, lo, hi - 1); |
| 48 | return i > lo && delta(a[i - 1], x) > -delta(a[i], x) ? i - 1 : i; |
| 49 | } |
| 50 | |
| 51 | return {left, center, right}; |
| 52 | } |
| 53 | |
| 54 | function zero() { |
| 55 | return 0; |
no test coverage detected
searching dependent graphs…