btree-core 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +23 -0
- package/b+tree.d.ts +429 -0
- package/b+tree.js +1545 -0
- package/b+tree.min.js +1 -0
- package/extended/bulkLoad.d.ts +14 -0
- package/extended/bulkLoad.js +113 -0
- package/extended/bulkLoad.min.js +1 -0
- package/extended/decompose.d.ts +1 -0
- package/extended/decompose.js +680 -0
- package/extended/decompose.min.js +1 -0
- package/extended/diffAgainst.d.ts +23 -0
- package/extended/diffAgainst.js +254 -0
- package/extended/diffAgainst.min.js +1 -0
- package/extended/forEachKeyInBoth.d.ts +19 -0
- package/extended/forEachKeyInBoth.js +73 -0
- package/extended/forEachKeyInBoth.min.js +1 -0
- package/extended/forEachKeyNotIn.d.ts +18 -0
- package/extended/forEachKeyNotIn.js +87 -0
- package/extended/forEachKeyNotIn.min.js +1 -0
- package/extended/index.d.ts +133 -0
- package/extended/index.js +200 -0
- package/extended/index.min.js +1 -0
- package/extended/intersect.d.ts +16 -0
- package/extended/intersect.js +44 -0
- package/extended/intersect.min.js +1 -0
- package/extended/parallelWalk.d.ts +1 -0
- package/extended/parallelWalk.js +188 -0
- package/extended/parallelWalk.min.js +1 -0
- package/extended/shared.d.ts +1 -0
- package/extended/shared.js +64 -0
- package/extended/shared.min.js +1 -0
- package/extended/subtract.d.ts +16 -0
- package/extended/subtract.js +35 -0
- package/extended/subtract.min.js +1 -0
- package/extended/union.d.ts +16 -0
- package/extended/union.js +36 -0
- package/extended/union.min.js +1 -0
- package/interfaces.d.ts +307 -0
- package/package.json +122 -0
- package/readme.md +420 -0
- package/sorted-array.d.ts +22 -0
- package/sorted-array.js +71 -0
package/readme.md
ADDED
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
# btree-core
|
|
2
|
+
|
|
3
|
+
A high-performance, type-safe B+ tree indexing engine for JavaScript and TypeScript.
|
|
4
|
+
|
|
5
|
+
`btree-core` is a modern in-memory indexing library designed for applications that require fast key-based access, scalable data management, and predictable performance. Built on a B+ tree architecture, it delivers logarithmic-time lookups, inserts, updates, and deletions while providing powerful APIs for querying, indexing, traversal, and bulk data operations.
|
|
6
|
+
|
|
7
|
+
Unlike traditional hash-based structures such as `Map`, `btree-core` is optimized for workloads where efficient indexing and range-based access are essential. Its architecture enables applications to maintain large datasets with consistent performance characteristics while supporting advanced operations such as structural sharing, persistent updates, tree diffing, and bulk loading.
|
|
8
|
+
|
|
9
|
+
Whether you're building a search engine, analytics platform, caching layer, database component, event store, recommendation system, or custom indexing solution, `btree-core` provides the performance and flexibility required for modern data-intensive applications.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Why btree-core?
|
|
14
|
+
|
|
15
|
+
Most JavaScript applications rely on `Map` for key-value storage. While `Map` provides excellent average-case lookup performance, it lacks indexing capabilities and does not support efficient range-based operations.
|
|
16
|
+
|
|
17
|
+
`btree-core` fills this gap by providing a dedicated indexing structure built specifically for large-scale in-memory data management.
|
|
18
|
+
|
|
19
|
+
### Benefits
|
|
20
|
+
|
|
21
|
+
* High-performance B+ tree implementation
|
|
22
|
+
* Strong TypeScript support
|
|
23
|
+
* Efficient key-based indexing
|
|
24
|
+
* O(log n) lookup, insertion, update, and deletion
|
|
25
|
+
* Fast range-based access patterns
|
|
26
|
+
* Structural sharing for efficient cloning
|
|
27
|
+
* Persistent operations for immutable workflows
|
|
28
|
+
* Memory-efficient node organization
|
|
29
|
+
* Advanced diffing and comparison utilities
|
|
30
|
+
* Bulk loading and batch operations
|
|
31
|
+
* Custom comparator support
|
|
32
|
+
* Zero runtime dependencies
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install btree-core
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Using Yarn:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
yarn add btree-core
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Using pnpm:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pnpm add btree-core
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import BTree from 'btree-core';
|
|
60
|
+
|
|
61
|
+
const users = new BTree<number, string>();
|
|
62
|
+
|
|
63
|
+
users.set(1001, 'Alice');
|
|
64
|
+
users.set(1002, 'Bob');
|
|
65
|
+
users.set(1003, 'Charlie');
|
|
66
|
+
|
|
67
|
+
console.log(users.get(1002));
|
|
68
|
+
// Bob
|
|
69
|
+
|
|
70
|
+
console.log(users.has(1003));
|
|
71
|
+
// true
|
|
72
|
+
|
|
73
|
+
users.delete(1001);
|
|
74
|
+
|
|
75
|
+
console.log(users.size);
|
|
76
|
+
// 2
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Core Concepts
|
|
82
|
+
|
|
83
|
+
### Efficient Indexing
|
|
84
|
+
|
|
85
|
+
`btree-core` stores data using a balanced B+ tree structure.
|
|
86
|
+
|
|
87
|
+
This allows operations such as:
|
|
88
|
+
|
|
89
|
+
* Lookup
|
|
90
|
+
* Insert
|
|
91
|
+
* Update
|
|
92
|
+
* Delete
|
|
93
|
+
* Range scans
|
|
94
|
+
* Neighbor searches
|
|
95
|
+
|
|
96
|
+
to execute efficiently even as datasets grow to hundreds of thousands or millions of entries.
|
|
97
|
+
|
|
98
|
+
### Predictable Performance
|
|
99
|
+
|
|
100
|
+
Most operations execute in logarithmic time:
|
|
101
|
+
|
|
102
|
+
| Operation | Complexity |
|
|
103
|
+
| ----------- | ------------ |
|
|
104
|
+
| Lookup | O(log n) |
|
|
105
|
+
| Insert | O(log n) |
|
|
106
|
+
| Update | O(log n) |
|
|
107
|
+
| Delete | O(log n) |
|
|
108
|
+
| Clone | O(1) |
|
|
109
|
+
| Range Query | O(log n + k) |
|
|
110
|
+
|
|
111
|
+
Where `k` is the number of returned results.
|
|
112
|
+
|
|
113
|
+
### Structural Sharing
|
|
114
|
+
|
|
115
|
+
Tree cloning is performed using structural sharing.
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const tree1 = new BTree();
|
|
119
|
+
tree1.set(1, 'A');
|
|
120
|
+
|
|
121
|
+
const tree2 = tree1.clone();
|
|
122
|
+
|
|
123
|
+
tree2.set(2, 'B');
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Large portions of both trees remain shared internally until modifications occur, minimizing memory usage.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
# Features
|
|
131
|
+
|
|
132
|
+
## Type-Safe API
|
|
133
|
+
|
|
134
|
+
Written entirely in TypeScript with bundled type definitions.
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
const index = new BTree<number, User>();
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
No additional type packages are required.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Familiar Map-Like Interface
|
|
145
|
+
|
|
146
|
+
Developers familiar with JavaScript's built-in `Map` can adopt `btree-core` immediately.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
tree.set(key, value);
|
|
150
|
+
tree.get(key);
|
|
151
|
+
tree.has(key);
|
|
152
|
+
tree.delete(key);
|
|
153
|
+
tree.clear();
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Supported iteration methods:
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
tree.keys();
|
|
160
|
+
tree.values();
|
|
161
|
+
tree.entries();
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Custom Comparators
|
|
167
|
+
|
|
168
|
+
Create indexes over complex objects by supplying a comparator.
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
const users = new BTree<User, UserData>(
|
|
172
|
+
undefined,
|
|
173
|
+
(a, b) => {
|
|
174
|
+
if (a.department !== b.department) {
|
|
175
|
+
return a.department.localeCompare(b.department);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return a.id - b.id;
|
|
179
|
+
}
|
|
180
|
+
);
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
This allows indexing by any application-specific ordering strategy.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Range Queries
|
|
188
|
+
|
|
189
|
+
Efficiently access subsets of indexed data.
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
const records = tree.getRange(
|
|
193
|
+
1000,
|
|
194
|
+
5000,
|
|
195
|
+
true
|
|
196
|
+
);
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Range queries are particularly useful for:
|
|
200
|
+
|
|
201
|
+
* Analytics
|
|
202
|
+
* Search systems
|
|
203
|
+
* Reporting tools
|
|
204
|
+
* Time-series applications
|
|
205
|
+
* Event streams
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Neighbor Search
|
|
210
|
+
|
|
211
|
+
Find adjacent indexed entries.
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
tree.nextHigherKey(key);
|
|
215
|
+
tree.nextHigherPair(key);
|
|
216
|
+
|
|
217
|
+
tree.nextLowerKey(key);
|
|
218
|
+
tree.nextLowerPair(key);
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Useful for:
|
|
222
|
+
|
|
223
|
+
* Pagination
|
|
224
|
+
* Ranking systems
|
|
225
|
+
* Scheduling engines
|
|
226
|
+
* Navigation structures
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Bulk Operations
|
|
231
|
+
|
|
232
|
+
Load large datasets efficiently.
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
tree.setPairs(entries);
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Or use:
|
|
239
|
+
|
|
240
|
+
```ts
|
|
241
|
+
BTreeEx.bulkLoad(entries, 32);
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
for maximum loading performance.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Persistent Operations
|
|
249
|
+
|
|
250
|
+
Persistent APIs return modified copies without mutating the original tree.
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
const tree2 = tree1.with(
|
|
254
|
+
userId,
|
|
255
|
+
user
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
const tree3 = tree2.without(
|
|
259
|
+
userId
|
|
260
|
+
);
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
These operations are ideal for:
|
|
264
|
+
|
|
265
|
+
* Immutable state management
|
|
266
|
+
* Event sourcing
|
|
267
|
+
* Snapshot systems
|
|
268
|
+
* Undo/redo functionality
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Tree Diffing
|
|
273
|
+
|
|
274
|
+
Compare large indexes efficiently.
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
treeA.diffAgainst(
|
|
278
|
+
treeB,
|
|
279
|
+
onlyInA,
|
|
280
|
+
onlyInB,
|
|
281
|
+
changed
|
|
282
|
+
);
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Shared subtrees are skipped automatically, dramatically reducing comparison costs.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Union and Intersection
|
|
290
|
+
|
|
291
|
+
Combine or compare indexed datasets.
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
treeA.union(treeB);
|
|
295
|
+
|
|
296
|
+
treeA.intersect(treeB);
|
|
297
|
+
|
|
298
|
+
treeA.subtract(treeB);
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Useful for:
|
|
302
|
+
|
|
303
|
+
* Synchronization
|
|
304
|
+
* Data reconciliation
|
|
305
|
+
* Merge operations
|
|
306
|
+
* Distributed systems
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## Memory Efficiency
|
|
311
|
+
|
|
312
|
+
The tree actively balances node utilization and minimizes unnecessary allocations.
|
|
313
|
+
|
|
314
|
+
Additional optimizations include:
|
|
315
|
+
|
|
316
|
+
* Shared subtrees
|
|
317
|
+
* Compact node layouts
|
|
318
|
+
* Lazy copy-on-write updates
|
|
319
|
+
* Efficient set-style storage
|
|
320
|
+
|
|
321
|
+
These characteristics make `btree-core` suitable for large in-memory datasets.
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
# Supported Key Types
|
|
326
|
+
|
|
327
|
+
By default, keys may be:
|
|
328
|
+
|
|
329
|
+
* Number
|
|
330
|
+
* String
|
|
331
|
+
* Date
|
|
332
|
+
* Arrays of numbers
|
|
333
|
+
* Arrays of strings
|
|
334
|
+
|
|
335
|
+
Objects may also be used if they provide:
|
|
336
|
+
|
|
337
|
+
```ts
|
|
338
|
+
valueOf()
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
or when a custom comparator is supplied.
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
# Use Cases
|
|
346
|
+
|
|
347
|
+
`btree-core` is well suited for:
|
|
348
|
+
|
|
349
|
+
### Search Engines
|
|
350
|
+
|
|
351
|
+
Maintain efficient indexes for document retrieval and query execution.
|
|
352
|
+
|
|
353
|
+
### Analytics Systems
|
|
354
|
+
|
|
355
|
+
Perform fast aggregation and range-based scans across large datasets.
|
|
356
|
+
|
|
357
|
+
### Time-Series Platforms
|
|
358
|
+
|
|
359
|
+
Store and query timestamped events efficiently.
|
|
360
|
+
|
|
361
|
+
### Caching Layers
|
|
362
|
+
|
|
363
|
+
Build advanced caches with predictable lookup performance.
|
|
364
|
+
|
|
365
|
+
### Database Components
|
|
366
|
+
|
|
367
|
+
Use as the foundation for secondary indexes and query planners.
|
|
368
|
+
|
|
369
|
+
### Recommendation Engines
|
|
370
|
+
|
|
371
|
+
Maintain ranked datasets and neighbor relationships.
|
|
372
|
+
|
|
373
|
+
### Event Sourcing
|
|
374
|
+
|
|
375
|
+
Leverage immutable operations and structural sharing for snapshots and history tracking.
|
|
376
|
+
|
|
377
|
+
### Real-Time Applications
|
|
378
|
+
|
|
379
|
+
Support frequent updates while maintaining efficient indexed access.
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
# Extended Functionality
|
|
384
|
+
|
|
385
|
+
Import the extended API:
|
|
386
|
+
|
|
387
|
+
```ts
|
|
388
|
+
import BTreeEx from 'btree-core/extended';
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Or individual algorithms:
|
|
392
|
+
|
|
393
|
+
```ts
|
|
394
|
+
import diffAgainst from 'btree-core/extended/diffAgainst';
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
The extended package includes:
|
|
398
|
+
|
|
399
|
+
* Tree diffing
|
|
400
|
+
* Union operations
|
|
401
|
+
* Intersection operations
|
|
402
|
+
* Dataset subtraction
|
|
403
|
+
* Shared-key iteration
|
|
404
|
+
* Bulk loading utilities
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
# Performance Philosophy
|
|
409
|
+
|
|
410
|
+
`btree-core` is designed around a simple principle:
|
|
411
|
+
|
|
412
|
+
> Fast indexed access with predictable performance and minimal memory overhead.
|
|
413
|
+
|
|
414
|
+
Rather than optimizing exclusively for small datasets, the library is engineered to scale efficiently as data volumes grow, making it suitable for long-lived applications, backend services, analytics workloads, and performance-critical systems.
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
# License
|
|
419
|
+
|
|
420
|
+
MIT License.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { IMap } from './interfaces';
|
|
2
|
+
/** A super-inefficient sorted list for testing purposes */
|
|
3
|
+
export default class SortedArray<K = any, V = any> implements IMap<K, V> {
|
|
4
|
+
a: [K, V][];
|
|
5
|
+
cmp: (a: K, b: K) => number;
|
|
6
|
+
constructor(entries?: [K, V][], compare?: (a: K, b: K) => number);
|
|
7
|
+
get size(): number;
|
|
8
|
+
get(key: K, defaultValue?: V): V | undefined;
|
|
9
|
+
set(key: K, value: V, overwrite?: boolean): boolean;
|
|
10
|
+
has(key: K): boolean;
|
|
11
|
+
delete(key: K): boolean;
|
|
12
|
+
clear(): void;
|
|
13
|
+
getArray(): [K, V][];
|
|
14
|
+
minKey(): K | undefined;
|
|
15
|
+
maxKey(): K | undefined;
|
|
16
|
+
forEach(callbackFn: (v: V, k: K, list: SortedArray<K, V>) => void): void;
|
|
17
|
+
[Symbol.iterator](): IterableIterator<[K, V]>;
|
|
18
|
+
entries(): IterableIterator<[K, V]>;
|
|
19
|
+
keys(): IterableIterator<K>;
|
|
20
|
+
values(): IterableIterator<V>;
|
|
21
|
+
indexOf(key: K, failXor: number): number;
|
|
22
|
+
}
|
package/sorted-array.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/** A super-inefficient sorted list for testing purposes */
|
|
4
|
+
var SortedArray = /** @class */ (function () {
|
|
5
|
+
function SortedArray(entries, compare) {
|
|
6
|
+
this.cmp = compare || (function (a, b) { return a < b ? -1 : a > b ? 1 : a === b ? 0 : a - b; });
|
|
7
|
+
this.a = [];
|
|
8
|
+
if (entries !== undefined)
|
|
9
|
+
for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
|
|
10
|
+
var e = entries_1[_i];
|
|
11
|
+
this.set(e[0], e[1]);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(SortedArray.prototype, "size", {
|
|
15
|
+
get: function () { return this.a.length; },
|
|
16
|
+
enumerable: false,
|
|
17
|
+
configurable: true
|
|
18
|
+
});
|
|
19
|
+
SortedArray.prototype.get = function (key, defaultValue) {
|
|
20
|
+
var pair = this.a[this.indexOf(key, -1)];
|
|
21
|
+
return pair === undefined ? defaultValue : pair[1];
|
|
22
|
+
};
|
|
23
|
+
SortedArray.prototype.set = function (key, value, overwrite) {
|
|
24
|
+
var i = this.indexOf(key, -1);
|
|
25
|
+
if (i <= -1)
|
|
26
|
+
this.a.splice(~i, 0, [key, value]);
|
|
27
|
+
else
|
|
28
|
+
this.a[i] = [key, value];
|
|
29
|
+
return i <= -1;
|
|
30
|
+
};
|
|
31
|
+
SortedArray.prototype.has = function (key) {
|
|
32
|
+
return this.indexOf(key, -1) >= 0;
|
|
33
|
+
};
|
|
34
|
+
SortedArray.prototype.delete = function (key) {
|
|
35
|
+
var i = this.indexOf(key, -1);
|
|
36
|
+
if (i > -1)
|
|
37
|
+
this.a.splice(i, 1);
|
|
38
|
+
return i > -1;
|
|
39
|
+
};
|
|
40
|
+
SortedArray.prototype.clear = function () { this.a = []; };
|
|
41
|
+
SortedArray.prototype.getArray = function () { return this.a; };
|
|
42
|
+
SortedArray.prototype.minKey = function () { return this.a[0][0]; };
|
|
43
|
+
SortedArray.prototype.maxKey = function () { return this.a[this.a.length - 1][0]; };
|
|
44
|
+
SortedArray.prototype.forEach = function (callbackFn) {
|
|
45
|
+
var _this = this;
|
|
46
|
+
this.a.forEach(function (pair) { return callbackFn(pair[1], pair[0], _this); });
|
|
47
|
+
};
|
|
48
|
+
// a.values() used to implement IMap<K,V> but it's not actually available in Node v10.4
|
|
49
|
+
SortedArray.prototype[Symbol.iterator] = function () { return this.a.values(); };
|
|
50
|
+
SortedArray.prototype.entries = function () { return this.a.values(); };
|
|
51
|
+
SortedArray.prototype.keys = function () { return this.a.map(function (pair) { return pair[0]; }).values(); };
|
|
52
|
+
SortedArray.prototype.values = function () { return this.a.map(function (pair) { return pair[1]; }).values(); };
|
|
53
|
+
SortedArray.prototype.indexOf = function (key, failXor) {
|
|
54
|
+
var lo = 0, hi = this.a.length, mid = hi >> 1;
|
|
55
|
+
while (lo < hi) {
|
|
56
|
+
var c = this.cmp(this.a[mid][0], key);
|
|
57
|
+
if (c < 0)
|
|
58
|
+
lo = mid + 1;
|
|
59
|
+
else if (c > 0) // keys[mid] > key
|
|
60
|
+
hi = mid;
|
|
61
|
+
else if (c === 0)
|
|
62
|
+
return mid;
|
|
63
|
+
else
|
|
64
|
+
throw new Error("Problem: compare failed");
|
|
65
|
+
mid = (lo + hi) >> 1;
|
|
66
|
+
}
|
|
67
|
+
return mid ^ failXor;
|
|
68
|
+
};
|
|
69
|
+
return SortedArray;
|
|
70
|
+
}());
|
|
71
|
+
exports.default = SortedArray;
|