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.
Files changed (42) hide show
  1. package/LICENSE +23 -0
  2. package/b+tree.d.ts +429 -0
  3. package/b+tree.js +1545 -0
  4. package/b+tree.min.js +1 -0
  5. package/extended/bulkLoad.d.ts +14 -0
  6. package/extended/bulkLoad.js +113 -0
  7. package/extended/bulkLoad.min.js +1 -0
  8. package/extended/decompose.d.ts +1 -0
  9. package/extended/decompose.js +680 -0
  10. package/extended/decompose.min.js +1 -0
  11. package/extended/diffAgainst.d.ts +23 -0
  12. package/extended/diffAgainst.js +254 -0
  13. package/extended/diffAgainst.min.js +1 -0
  14. package/extended/forEachKeyInBoth.d.ts +19 -0
  15. package/extended/forEachKeyInBoth.js +73 -0
  16. package/extended/forEachKeyInBoth.min.js +1 -0
  17. package/extended/forEachKeyNotIn.d.ts +18 -0
  18. package/extended/forEachKeyNotIn.js +87 -0
  19. package/extended/forEachKeyNotIn.min.js +1 -0
  20. package/extended/index.d.ts +133 -0
  21. package/extended/index.js +200 -0
  22. package/extended/index.min.js +1 -0
  23. package/extended/intersect.d.ts +16 -0
  24. package/extended/intersect.js +44 -0
  25. package/extended/intersect.min.js +1 -0
  26. package/extended/parallelWalk.d.ts +1 -0
  27. package/extended/parallelWalk.js +188 -0
  28. package/extended/parallelWalk.min.js +1 -0
  29. package/extended/shared.d.ts +1 -0
  30. package/extended/shared.js +64 -0
  31. package/extended/shared.min.js +1 -0
  32. package/extended/subtract.d.ts +16 -0
  33. package/extended/subtract.js +35 -0
  34. package/extended/subtract.min.js +1 -0
  35. package/extended/union.d.ts +16 -0
  36. package/extended/union.js +36 -0
  37. package/extended/union.min.js +1 -0
  38. package/interfaces.d.ts +307 -0
  39. package/package.json +122 -0
  40. package/readme.md +420 -0
  41. package/sorted-array.d.ts +22 -0
  42. package/sorted-array.js +71 -0
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ var desc = Object.getOwnPropertyDescriptor(m, k);
20
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
+ desc = { enumerable: true, get: function() { return m[k]; } };
22
+ }
23
+ Object.defineProperty(o, k2, desc);
24
+ }) : (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ o[k2] = m[k];
27
+ }));
28
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
30
+ }) : function(o, v) {
31
+ o["default"] = v;
32
+ });
33
+ var __importStar = (this && this.__importStar) || function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ var __importDefault = (this && this.__importDefault) || function (mod) {
41
+ return (mod && mod.__esModule) ? mod : { "default": mod };
42
+ };
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.BTreeEx = void 0;
45
+ var b_tree_1 = __importStar(require("../b+tree"));
46
+ var diffAgainst_1 = __importDefault(require("./diffAgainst"));
47
+ var forEachKeyInBoth_1 = __importDefault(require("./forEachKeyInBoth"));
48
+ var forEachKeyNotIn_1 = __importDefault(require("./forEachKeyNotIn"));
49
+ var intersect_1 = __importDefault(require("./intersect"));
50
+ var subtract_1 = __importDefault(require("./subtract"));
51
+ var union_1 = __importDefault(require("./union"));
52
+ var bulkLoad_1 = require("./bulkLoad");
53
+ /**
54
+ * An extended version of the `BTree` class that includes additional functionality
55
+ * such as bulk loading, set operations, and diffing.
56
+ * It is separated to keep the core BTree class small from a bundle size perspective.
57
+ * Note: each additional functionality piece is available as a standalone function from the extended folder.
58
+ * @extends BTree
59
+ */
60
+ var BTreeEx = /** @class */ (function (_super) {
61
+ __extends(BTreeEx, _super);
62
+ function BTreeEx() {
63
+ return _super !== null && _super.apply(this, arguments) || this;
64
+ }
65
+ /**
66
+ * Bulk loads a new `BTreeEx` from parallel arrays of sorted entries.
67
+ * This reuses the same algorithm as `extended/bulkLoad`, but produces a `BTreeEx`.
68
+ * Time and space complexity are O(n).
69
+ * @param keys Keys to load, sorted by key in strictly ascending order.
70
+ * @param values Values aligned with the supplied keys.
71
+ * @param maxNodeSize The branching factor (maximum number of children per node).
72
+ * @param compare Comparator to use. Defaults to the standard comparator if omitted.
73
+ * @returns A fully built tree containing the supplied entries.
74
+ * @throws Error if the entries are not strictly sorted or contain duplicate keys.
75
+ */
76
+ BTreeEx.bulkLoad = function (keys, values, maxNodeSize, compare) {
77
+ var cmp = compare !== null && compare !== void 0 ? compare : b_tree_1.defaultComparator;
78
+ var root = (0, bulkLoad_1.bulkLoadRoot)(keys, values, maxNodeSize, cmp);
79
+ var tree = new BTreeEx(undefined, cmp, maxNodeSize);
80
+ var target = tree;
81
+ target._root = root;
82
+ return tree;
83
+ };
84
+ /** See {@link BTree.clone}. */
85
+ BTreeEx.prototype.clone = function () {
86
+ var source = this;
87
+ source._root.isShared = true;
88
+ var result = new BTreeEx(undefined, this._compare, this._maxNodeSize);
89
+ var target = result;
90
+ target._root = source._root;
91
+ return result;
92
+ };
93
+ /** See {@link BTree.greedyClone}. */
94
+ BTreeEx.prototype.greedyClone = function (force) {
95
+ var source = this;
96
+ var result = new BTreeEx(undefined, this._compare, this._maxNodeSize);
97
+ var target = result;
98
+ target._root = source._root.greedyClone(force);
99
+ return result;
100
+ };
101
+ /**
102
+ * Computes the differences between `this` and `other`.
103
+ * For efficiency, the diff is returned via invocations of supplied handlers.
104
+ * The computation is optimized for the case in which the two trees have large amounts of shared data
105
+ * (obtained by calling the `clone` or `with` APIs) and will avoid any iteration of shared state.
106
+ * The handlers can cause computation to early exit by returning `{ break: R }`.
107
+ * Neither collection should be mutated during the comparison (inside your callbacks), as this method assumes they remain stable.
108
+ * @param other The tree to compute a diff against.
109
+ * @param onlyThis Callback invoked for all keys only present in `this`.
110
+ * @param onlyOther Callback invoked for all keys only present in `other`.
111
+ * @param different Callback invoked for all keys with differing values.
112
+ * @returns The first `break` payload returned by a handler, or `undefined` if no handler breaks.
113
+ * @throws Error if the supplied trees were created with different comparators.
114
+ */
115
+ BTreeEx.prototype.diffAgainst = function (other, onlyThis, onlyOther, different) {
116
+ return (0, diffAgainst_1.default)(this, other, onlyThis, onlyOther, different);
117
+ };
118
+ /**
119
+ * Calls the supplied `callback` for each key/value pair shared by this tree and `other`, in sorted key order.
120
+ * Neither tree is modified.
121
+ *
122
+ * Complexity is O(N + M) when the trees overlap heavily, and additionally bounded by O(log(N + M) * D)
123
+ * where `D` is the number of disjoint key ranges between the trees, because disjoint subtrees are skipped.
124
+ * In practice, that means for keys of random distribution the performance is linear and for keys with significant
125
+ * numbers of non-overlapping key ranges it is much faster.
126
+ * @param other The other tree to compare with this one.
127
+ * @param callback Called for keys that appear in both trees. It can cause iteration to early exit by returning `{ break: R }`.
128
+ * @returns The first `break` payload returned by the callback, or `undefined` if the walk finishes.
129
+ * @throws Error if the two trees were created with different comparators.
130
+ */
131
+ BTreeEx.prototype.forEachKeyInBoth = function (other, callback) {
132
+ return (0, forEachKeyInBoth_1.default)(this, other, callback);
133
+ };
134
+ /**
135
+ * Calls the supplied `callback` for each key/value pair that exists in this tree but not in `other`
136
+ * (set subtraction). The callback runs in sorted key order and neither tree is modified.
137
+ *
138
+ * Complexity is O(N + M) when the key ranges overlap heavily, and additionally bounded by O(log(N + M) * D)
139
+ * where `D` is the number of disjoint ranges between the trees, because non-overlapping subtrees are skipped.
140
+ * In practice, that means for keys of random distribution the performance is linear and for keys with significant
141
+ * numbers of non-overlapping key ranges it is much faster.
142
+ * @param other Keys present in this tree will be omitted from the callback.
143
+ * @param callback Invoked for keys unique to `this`. It can cause iteration to early exit by returning `{ break: R }`.
144
+ * @returns The first `break` payload returned by the callback, or `undefined` if all qualifying keys are visited.
145
+ * @throws Error if the trees were created with different comparators.
146
+ */
147
+ BTreeEx.prototype.forEachKeyNotIn = function (other, callback) {
148
+ return (0, forEachKeyNotIn_1.default)(this, other, callback);
149
+ };
150
+ /**
151
+ * Returns a new tree containing only keys present in both trees.
152
+ * Neither tree is modified.
153
+ *
154
+ * Complexity is O(N + M) in the fully overlapping case and additionally bounded by O(log(N + M) * D),
155
+ * where `D` is the number of disjoint key ranges, because disjoint subtrees are skipped entirely.
156
+ * In practice, that means for keys of random distribution the performance is linear and for keys with significant
157
+ * numbers of non-overlapping key ranges it is much faster.
158
+ * @param other The other tree to intersect with this one.
159
+ * @param combineFn Called for keys that appear in both trees. Return the desired value.
160
+ * @returns A new `BTreeEx` populated with the intersection.
161
+ * @throws Error if the trees were created with different comparators.
162
+ */
163
+ BTreeEx.prototype.intersect = function (other, combineFn) {
164
+ return (0, intersect_1.default)(this, other, combineFn);
165
+ };
166
+ /**
167
+ * Efficiently unions this tree with `other`, reusing subtrees wherever possible without modifying either input.
168
+ *
169
+ * Complexity is O(N + M) in the fully overlapping case, and additionally bounded by O(log(N + M) * D)
170
+ * where `D` is the number of disjoint key ranges, because disjoint subtrees are skipped entirely.
171
+ * In practice, that means for keys of random distribution the performance is linear and for keys with significant
172
+ * numbers of non-overlapping key ranges it is much faster.
173
+ * @param other The other tree to union with this one.
174
+ * @param combineFn Called for keys that appear in both trees. Return the desired value, or `undefined` to omit the key.
175
+ * @returns A new `BTreeEx` that contains the unioned key/value pairs.
176
+ * @throws Error if the trees were created with different comparators or max node sizes.
177
+ */
178
+ BTreeEx.prototype.union = function (other, combineFn) {
179
+ return (0, union_1.default)(this, other, combineFn);
180
+ };
181
+ /**
182
+ * Returns a new tree containing only the keys that are present in this tree but not `other` (set subtraction).
183
+ * Neither input tree is modified.
184
+ *
185
+ * Complexity is O(N + M) for time and O(N) for allocations in the worst case. Additionally, time is bounded by
186
+ * O(log(N + M) * D1) and space by O(log N * D2) where `D1` is the number of disjoint key ranges between the trees
187
+ * and `D2` is the number of disjoint ranges inside this tree.
188
+ * In practice, that means for keys of random distribution the performance is linear and for keys with significant
189
+ * numbers of non-overlapping key ranges it is much faster.
190
+ * @param other The tree whose keys will be removed from the result.
191
+ * @returns A new `BTreeEx` representing `this \ other`.
192
+ * @throws Error if the trees were created with different comparators or max node sizes.
193
+ */
194
+ BTreeEx.prototype.subtract = function (other) {
195
+ return (0, subtract_1.default)(this, other);
196
+ };
197
+ return BTreeEx;
198
+ }(b_tree_1.default));
199
+ exports.BTreeEx = BTreeEx;
200
+ exports.default = BTreeEx;
@@ -0,0 +1 @@
1
+ "use strict";var __extends=this&&this.__extends||function(){var o=function(t,e){return(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])})(t,e)};return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function r(){this.constructor=t}o(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}}(),__createBinding=this&&this.__createBinding||(Object.create?function(t,e,r,o){void 0===o&&(o=r);var n=Object.getOwnPropertyDescriptor(e,r);n&&("get"in n?e.__esModule:!n.writable&&!n.configurable)||(n={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,o,n)}:function(t,e,r,o){void 0===o&&(o=r),t[o]=e[r]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),__importStar=this&&this.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)"default"!==r&&Object.prototype.hasOwnProperty.call(t,r)&&__createBinding(e,t,r);return __setModuleDefault(e,t),e},__importDefault=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.BTreeEx=void 0;var b_tree_1=__importStar(require("../b+tree")),diffAgainst_1=__importDefault(require("./diffAgainst")),forEachKeyInBoth_1=__importDefault(require("./forEachKeyInBoth")),forEachKeyNotIn_1=__importDefault(require("./forEachKeyNotIn")),intersect_1=__importDefault(require("./intersect")),subtract_1=__importDefault(require("./subtract")),union_1=__importDefault(require("./union")),bulkLoad_1=require("./bulkLoad"),BTreeEx=function(t){function n(){return null!==t&&t.apply(this,arguments)||this}return __extends(n,t),n.bulkLoad=function(t,e,r,o){o=null!=o?o:b_tree_1.defaultComparator,e=(0,bulkLoad_1.bulkLoadRoot)(t,e,r,o),r=new n(void 0,o,r);return r._root=e,r},n.prototype.clone=function(){this._root.isShared=!0;var t=new n(void 0,this._compare,this._maxNodeSize);return t._root=this._root,t},n.prototype.greedyClone=function(t){var e=new n(void 0,this._compare,this._maxNodeSize);return e._root=this._root.greedyClone(t),e},n.prototype.diffAgainst=function(t,e,r,o){return(0,diffAgainst_1.default)(this,t,e,r,o)},n.prototype.forEachKeyInBoth=function(t,e){return(0,forEachKeyInBoth_1.default)(this,t,e)},n.prototype.forEachKeyNotIn=function(t,e){return(0,forEachKeyNotIn_1.default)(this,t,e)},n.prototype.intersect=function(t,e){return(0,intersect_1.default)(this,t,e)},n.prototype.union=function(t,e){return(0,union_1.default)(this,t,e)},n.prototype.subtract=function(t){return(0,subtract_1.default)(this,t)},n}(b_tree_1.default);exports.BTreeEx=BTreeEx,exports.default=BTreeEx;
@@ -0,0 +1,16 @@
1
+ import BTree from '../b+tree';
2
+ /**
3
+ * Returns a new tree containing only keys present in both input trees.
4
+ * Neither tree is modified.
5
+ *
6
+ * Complexity is O(N + M) in the fully overlapping case and additionally bounded by O(log(N + M) * D),
7
+ * where `D` is the number of disjoint key ranges, because disjoint subtrees are skipped entirely.
8
+ * In practice, that means for keys of random distribution the performance is linear and for keys with significant
9
+ * numbers of non-overlapping key ranges it is much faster.
10
+ * @param treeA First tree to intersect.
11
+ * @param treeB Second tree to intersect.
12
+ * @param combineFn Called for keys that appear in both trees. Return the desired value.
13
+ * @returns A new tree populated with the intersection.
14
+ * @throws Error if the trees were created with different comparators.
15
+ */
16
+ export default function intersect<TBTree extends BTree<K, V>, K, V>(treeA: TBTree, treeB: TBTree, combineFn: (key: K, leftValue: V, rightValue: V) => V): TBTree;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ var shared_1 = require("./shared");
7
+ var forEachKeyInBoth_1 = __importDefault(require("./forEachKeyInBoth"));
8
+ var bulkLoad_1 = require("./bulkLoad");
9
+ /**
10
+ * Returns a new tree containing only keys present in both input trees.
11
+ * Neither tree is modified.
12
+ *
13
+ * Complexity is O(N + M) in the fully overlapping case and additionally bounded by O(log(N + M) * D),
14
+ * where `D` is the number of disjoint key ranges, because disjoint subtrees are skipped entirely.
15
+ * In practice, that means for keys of random distribution the performance is linear and for keys with significant
16
+ * numbers of non-overlapping key ranges it is much faster.
17
+ * @param treeA First tree to intersect.
18
+ * @param treeB Second tree to intersect.
19
+ * @param combineFn Called for keys that appear in both trees. Return the desired value.
20
+ * @returns A new tree populated with the intersection.
21
+ * @throws Error if the trees were created with different comparators.
22
+ */
23
+ function intersect(treeA, treeB, combineFn) {
24
+ var _treeA = treeA;
25
+ var _treeB = treeB;
26
+ var branchingFactor = (0, shared_1.checkCanDoSetOperation)(_treeA, _treeB, true);
27
+ if (_treeA._root.size() === 0)
28
+ return treeA.clone();
29
+ if (_treeB._root.size() === 0)
30
+ return treeB.clone();
31
+ var intersectedKeys = [];
32
+ var intersectedValues = [];
33
+ (0, forEachKeyInBoth_1.default)(treeA, treeB, function (key, leftValue, rightValue) {
34
+ var mergedValue = combineFn(key, leftValue, rightValue);
35
+ intersectedKeys.push(key);
36
+ intersectedValues.push(mergedValue);
37
+ });
38
+ // Intersected keys are guaranteed to be in order, so we can bulk load
39
+ var constructor = treeA.constructor;
40
+ var resultTree = new constructor(undefined, treeA._compare, branchingFactor);
41
+ resultTree._root = (0, bulkLoad_1.bulkLoadRoot)(intersectedKeys, intersectedValues, branchingFactor, treeA._compare);
42
+ return resultTree;
43
+ }
44
+ exports.default = intersect;
@@ -0,0 +1 @@
1
+ "use strict";var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});var shared_1=require("./shared"),forEachKeyInBoth_1=__importDefault(require("./forEachKeyInBoth")),bulkLoad_1=require("./bulkLoad");function intersect(e,r,o){var t=e,u=r,a=(0,shared_1.checkCanDoSetOperation)(t,u,!0);if(0===t._root.size())return e.clone();if(0===u._root.size())return r.clone();var n=[],i=[];(0,forEachKeyInBoth_1.default)(e,r,function(e,r,t){t=o(e,r,t);n.push(e),i.push(t)});r=new e.constructor(void 0,e._compare,a);return r._root=(0,bulkLoad_1.bulkLoadRoot)(n,i,a,e._compare),r}exports.default=intersect;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,188 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.noop = exports.moveTo = exports.getKey = exports.createCursor = exports.moveForwardOne = void 0;
4
+ /**
5
+ * Walks the cursor forward by one key.
6
+ * Returns true if end-of-tree was reached (cursor not structurally mutated).
7
+ * Optimized for this case over the more general `moveTo` function.
8
+ * @internal
9
+ */
10
+ function moveForwardOne(cur, other) {
11
+ var leaf = cur.leaf;
12
+ var nextIndex = cur.leafIndex + 1;
13
+ if (nextIndex < leaf.keys.length) {
14
+ // Still within current leaf
15
+ cur.onMoveInLeaf(leaf, cur.leafPayload, cur.leafIndex, nextIndex, true);
16
+ cur.leafIndex = nextIndex;
17
+ return false;
18
+ }
19
+ // If our optimized step within leaf failed, use full moveTo logic
20
+ // Pass isInclusive=false to ensure we walk forward to the key exactly after the current
21
+ return moveTo(cur, other, getKey(cur), false, true)[0];
22
+ }
23
+ exports.moveForwardOne = moveForwardOne;
24
+ /**
25
+ * Create a cursor pointing to the leftmost key of the supplied tree.
26
+ * @internal
27
+ */
28
+ function createCursor(tree, makePayload, onEnterLeaf, onMoveInLeaf, onExitLeaf, onStepUp, onStepDown) {
29
+ var spine = [];
30
+ var n = tree._root;
31
+ while (!n.isLeaf) {
32
+ var ni = n;
33
+ var payload = makePayload();
34
+ spine.push({ node: ni, childIndex: 0, payload: payload });
35
+ n = ni.children[0];
36
+ }
37
+ var leafPayload = makePayload();
38
+ var cur = {
39
+ tree: tree,
40
+ leaf: n, leafIndex: 0,
41
+ spine: spine,
42
+ leafPayload: leafPayload,
43
+ makePayload: makePayload,
44
+ onEnterLeaf: onEnterLeaf,
45
+ onMoveInLeaf: onMoveInLeaf,
46
+ onExitLeaf: onExitLeaf,
47
+ onStepUp: onStepUp,
48
+ onStepDown: onStepDown
49
+ };
50
+ return cur;
51
+ }
52
+ exports.createCursor = createCursor;
53
+ /**
54
+ * Gets the key at the current cursor position.
55
+ * @internal
56
+ */
57
+ function getKey(c) {
58
+ return c.leaf.keys[c.leafIndex];
59
+ }
60
+ exports.getKey = getKey;
61
+ /**
62
+ * Move cursor strictly forward to the first key >= (inclusive) or > (exclusive) target.
63
+ * Returns a boolean indicating if end-of-tree was reached (cursor not structurally mutated).
64
+ * Also returns a boolean indicating if the target key was landed on exactly.
65
+ * @internal
66
+ */
67
+ function moveTo(cur, other, targetKey, isInclusive, startedEqual) {
68
+ // Cache for perf
69
+ var cmp = cur.tree._compare;
70
+ var onMoveInLeaf = cur.onMoveInLeaf;
71
+ // Fast path: destination within current leaf
72
+ var leaf = cur.leaf;
73
+ var leafPayload = cur.leafPayload;
74
+ var i = leaf.indexOf(targetKey, -1, cmp);
75
+ var destInLeaf;
76
+ var targetExactlyReached;
77
+ if (i < 0) {
78
+ destInLeaf = ~i;
79
+ targetExactlyReached = false;
80
+ }
81
+ else {
82
+ if (isInclusive) {
83
+ destInLeaf = i;
84
+ targetExactlyReached = true;
85
+ }
86
+ else {
87
+ destInLeaf = i + 1;
88
+ targetExactlyReached = false;
89
+ }
90
+ }
91
+ var leafKeyCount = leaf.keys.length;
92
+ if (destInLeaf < leafKeyCount) {
93
+ onMoveInLeaf(leaf, leafPayload, cur.leafIndex, destInLeaf, startedEqual);
94
+ cur.leafIndex = destInLeaf;
95
+ return [false, targetExactlyReached];
96
+ }
97
+ // Find first ancestor with a viable right step
98
+ var spine = cur.spine;
99
+ var initialSpineLength = spine.length;
100
+ var descentLevel = -1;
101
+ var descentIndex = -1;
102
+ for (var s = initialSpineLength - 1; s >= 0; s--) {
103
+ var parent = spine[s].node;
104
+ var indexOf = parent.indexOf(targetKey, -1, cmp);
105
+ var stepDownIndex = void 0;
106
+ if (indexOf < 0) {
107
+ stepDownIndex = ~indexOf;
108
+ }
109
+ else {
110
+ stepDownIndex = isInclusive ? indexOf : indexOf + 1;
111
+ }
112
+ // Note: when key not found, indexOf with failXor=0 already returns insertion index
113
+ if (stepDownIndex < parent.keys.length) {
114
+ descentLevel = s;
115
+ descentIndex = stepDownIndex;
116
+ break;
117
+ }
118
+ }
119
+ // Exit leaf; even if no spine, we did walk out of it conceptually
120
+ var startIndex = cur.leafIndex;
121
+ cur.onExitLeaf(leaf, leafPayload, startIndex, startedEqual, cur);
122
+ var onStepUp = cur.onStepUp;
123
+ if (descentLevel < 0) {
124
+ // No descent point; step up all the way; last callback gets infinity
125
+ for (var depth = initialSpineLength - 1; depth >= 0; depth--) {
126
+ var entry_1 = spine[depth];
127
+ var sd = depth === 0 ? Number.POSITIVE_INFINITY : Number.NaN;
128
+ onStepUp(entry_1.node, initialSpineLength - depth, entry_1.payload, entry_1.childIndex, depth, sd, cur, other);
129
+ }
130
+ return [true, false];
131
+ }
132
+ // Step up through ancestors above the descentLevel
133
+ for (var depth = initialSpineLength - 1; depth > descentLevel; depth--) {
134
+ var entry_2 = spine[depth];
135
+ onStepUp(entry_2.node, initialSpineLength - depth, entry_2.payload, entry_2.childIndex, depth, Number.NaN, cur, other);
136
+ }
137
+ var entry = spine[descentLevel];
138
+ onStepUp(entry.node, initialSpineLength - descentLevel, entry.payload, entry.childIndex, descentLevel, descentIndex, cur, other);
139
+ entry.childIndex = descentIndex;
140
+ var onStepDown = cur.onStepDown;
141
+ var makePayload = cur.makePayload;
142
+ // Descend, invoking onStepDown and creating payloads
143
+ var height = initialSpineLength - descentLevel - 1; // calculate height before changing length
144
+ spine.length = descentLevel + 1;
145
+ var node = spine[descentLevel].node.children[descentIndex];
146
+ while (!node.isLeaf) {
147
+ var ni = node;
148
+ var keys = ni.keys;
149
+ var stepDownIndex = ni.indexOf(targetKey, 0, cmp);
150
+ if (!isInclusive && stepDownIndex < keys.length && cmp(keys[stepDownIndex], targetKey) === 0)
151
+ stepDownIndex++;
152
+ var payload = makePayload();
153
+ var spineIndex = spine.length;
154
+ spine.push({ node: ni, childIndex: stepDownIndex, payload: payload });
155
+ onStepDown(ni, height, spineIndex, stepDownIndex, cur, other);
156
+ node = ni.children[stepDownIndex];
157
+ height -= 1;
158
+ }
159
+ // Enter destination leaf
160
+ var idx = node.indexOf(targetKey, -1, cmp);
161
+ var destIndex;
162
+ if (idx < 0) {
163
+ destIndex = ~idx;
164
+ targetExactlyReached = false;
165
+ }
166
+ else {
167
+ if (isInclusive) {
168
+ destIndex = idx;
169
+ targetExactlyReached = true;
170
+ }
171
+ else {
172
+ destIndex = idx + 1;
173
+ targetExactlyReached = false;
174
+ }
175
+ }
176
+ cur.leaf = node;
177
+ cur.leafPayload = makePayload();
178
+ cur.leafIndex = destIndex;
179
+ cur.onEnterLeaf(node, destIndex, cur, other);
180
+ return [false, targetExactlyReached];
181
+ }
182
+ exports.moveTo = moveTo;
183
+ /**
184
+ * A no-operation function.
185
+ * @internal
186
+ */
187
+ function noop() { }
188
+ exports.noop = noop;
@@ -0,0 +1 @@
1
+ "use strict";function moveForwardOne(e,o){var n=e.leaf,a=e.leafIndex+1;return a<n.keys.length?(e.onMoveInLeaf(n,e.leafPayload,e.leafIndex,a,!0),e.leafIndex=a,!1):moveTo(e,o,getKey(e),!1,!0)[0]}function createCursor(e,o,n,a,r,d,t){for(var l=[],f=e._root;!f.isLeaf;){var p=f,x=o();l.push({node:p,childIndex:0,payload:x}),f=p.children[0]}return{tree:e,leaf:f,leafIndex:0,spine:l,leafPayload:o(),makePayload:o,onEnterLeaf:n,onMoveInLeaf:a,onExitLeaf:r,onStepUp:d,onStepDown:t}}function getKey(e){return e.leaf.keys[e.leafIndex]}function moveTo(e,o,n,a,r){var d=e.tree._compare,t=e.onMoveInLeaf,l=e.leaf,f=e.leafPayload,p=l.indexOf(n,-1,d),p=p<0?(h=~p,!1):a?(h=p,!0):(h=p+1,!1);if(h<l.keys.length)return t(l,f,e.leafIndex,h,r),e.leafIndex=h,[!1,p];for(var x=e.spine,i=x.length,v=-1,s=-1,u=i-1;0<=u;u--){var I=x[u].node,y=I.indexOf(n,-1,d),c=void 0;if((c=y<0?~y:a?y:y+1)<I.keys.length){v=u,s=c;break}}var h=e.leafIndex;e.onExitLeaf(l,f,h,r,e);var m=e.onStepUp;if(v<0){for(var g=i-1;0<=g;g--){var O=x[g],L=0===g?Number.POSITIVE_INFINITY:Number.NaN;m(O.node,i-g,O.payload,O.childIndex,g,L,e,o)}return[!0,!1]}for(g=i-1;v<g;g--){var N=x[g];m(N.node,i-g,N.payload,N.childIndex,g,Number.NaN,e,o)}r=x[v];m(r.node,i-v,r.payload,r.childIndex,v,s,e,o),r.childIndex=s;var k=e.onStepDown,P=e.makePayload,T=i-v-1;x.length=v+1;for(var w=x[v].node.children[s];!w.isLeaf;){var b=w,E=b.keys,c=b.indexOf(n,0,d);!a&&c<E.length&&0===d(E[c],n)&&c++;var F=P(),E=x.length;x.push({node:b,childIndex:c,payload:F}),k(b,T,E,c,e,o),w=b.children[c],--T}var K,r=w.indexOf(n,-1,d);return p=r<0?(K=~r,!1):a?(K=r,!0):(K=r+1,!1),e.leaf=w,e.leafPayload=P(),e.leafIndex=K,e.onEnterLeaf(w,K,e,o),[!1,p]}function noop(){}Object.defineProperty(exports,"__esModule",{value:!0}),exports.noop=exports.moveTo=exports.getKey=exports.createCursor=exports.moveForwardOne=void 0,exports.moveForwardOne=moveForwardOne,exports.createCursor=createCursor,exports.getKey=getKey,exports.moveTo=moveTo,exports.noop=noop;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkCanDoSetOperation = exports.branchingFactorErrorMsg = exports.comparatorErrorMsg = exports.makeLeavesFrom = void 0;
4
+ var b_tree_1 = require("../b+tree");
5
+ /**
6
+ * Builds leaves from the given parallel arrays of entries.
7
+ * The supplied load factor will be respected if possible, but may be exceeded
8
+ * to ensure the 50% full rule is maintained.
9
+ * Note: if < maxNodeSize entries are provided, only one leaf will be created, which may be underfilled.
10
+ * @param keys The list of keys to build leaves from.
11
+ * @param values The list of values to build leaves from.
12
+ * @param maxNodeSize The maximum node size (branching factor) for the resulting leaves.
13
+ * @param onLeafCreation Called when a new leaf is created.
14
+ * @param loadFactor Desired load factor for created leaves. Must be between 0.5 and 1.0.
15
+ * @internal
16
+ */
17
+ function makeLeavesFrom(keys, values, maxNodeSize, loadFactor, onLeafCreation) {
18
+ if (keys.length !== values.length)
19
+ throw new Error("makeLeavesFrom: keys and values arrays must be the same length");
20
+ var totalPairs = keys.length;
21
+ if (totalPairs === 0)
22
+ return 0;
23
+ var targetSize = Math.ceil(maxNodeSize * loadFactor);
24
+ // This method creates as many evenly filled leaves as possible from
25
+ // the pending entries. All will be > 50% full if we are creating more than one leaf.
26
+ var remaining = totalPairs;
27
+ var pairIndex = 0;
28
+ var remainingLeaves = totalPairs <= maxNodeSize ? 1 : Math.ceil(totalPairs / targetSize);
29
+ for (; remainingLeaves > 0; remainingLeaves--) {
30
+ var chunkSize = Math.ceil(remaining / remainingLeaves);
31
+ var nextIndex = pairIndex + chunkSize;
32
+ var chunkKeys = keys.slice(pairIndex, nextIndex);
33
+ var chunkVals = values.slice(pairIndex, nextIndex);
34
+ pairIndex = nextIndex;
35
+ remaining -= chunkSize;
36
+ var leaf = new b_tree_1.BNode(chunkKeys, chunkVals);
37
+ onLeafCreation(leaf);
38
+ }
39
+ }
40
+ exports.makeLeavesFrom = makeLeavesFrom;
41
+ ;
42
+ /**
43
+ * Error message used when comparators differ between trees.
44
+ * @internal
45
+ */
46
+ exports.comparatorErrorMsg = "Cannot perform set operations on BTrees with different comparators.";
47
+ /**
48
+ * Error message used when branching factors differ between trees.
49
+ * @internal
50
+ */
51
+ exports.branchingFactorErrorMsg = "Cannot perform set operations on BTrees with different max node sizes.";
52
+ /**
53
+ * Checks that two trees can be used together in a set operation.
54
+ * @internal
55
+ */
56
+ function checkCanDoSetOperation(treeA, treeB, supportsDifferentBranchingFactors) {
57
+ if (treeA._compare !== treeB._compare)
58
+ throw new Error(exports.comparatorErrorMsg);
59
+ var branchingFactor = treeA._maxNodeSize;
60
+ if (!supportsDifferentBranchingFactors && branchingFactor !== treeB._maxNodeSize)
61
+ throw new Error(exports.branchingFactorErrorMsg);
62
+ return branchingFactor;
63
+ }
64
+ exports.checkCanDoSetOperation = checkCanDoSetOperation;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.checkCanDoSetOperation=exports.branchingFactorErrorMsg=exports.comparatorErrorMsg=exports.makeLeavesFrom=void 0;var b_tree_1=require("../b+tree");function makeLeavesFrom(e,r,o,t,a){if(e.length!==r.length)throw new Error("makeLeavesFrom: keys and values arrays must be the same length");var n=e.length;if(0===n)return 0;for(var t=Math.ceil(o*t),s=n,i=0,c=n<=o?1:Math.ceil(n/t);0<c;c--){var p=Math.ceil(s/c),m=i+p,h=e.slice(i,m),f=r.slice(i,m),i=m;s-=p,a(new b_tree_1.BNode(h,f))}}function checkCanDoSetOperation(e,r,o){if(e._compare!==r._compare)throw new Error(exports.comparatorErrorMsg);e=e._maxNodeSize;if(!o&&e!==r._maxNodeSize)throw new Error(exports.branchingFactorErrorMsg);return e}exports.makeLeavesFrom=makeLeavesFrom,exports.comparatorErrorMsg="Cannot perform set operations on BTrees with different comparators.",exports.branchingFactorErrorMsg="Cannot perform set operations on BTrees with different max node sizes.",exports.checkCanDoSetOperation=checkCanDoSetOperation;
@@ -0,0 +1,16 @@
1
+ import BTree from '../b+tree';
2
+ /**
3
+ * Returns a new tree containing only the keys that are present in `targetTree` but not `subtractTree` (set subtraction).
4
+ * Neither tree is modified.
5
+ *
6
+ * Complexity is O(N + M) for time and O(N) for allocations in the worst case. Additionally, time is bounded by
7
+ * O(log(N + M) * D1) and space by O(log N * D2), where `D1` is the number of disjoint key ranges between the trees
8
+ * and `D2` is the number of disjoint ranges inside `targetTree`, because disjoint subtrees are skipped entirely.
9
+ * In practice, that means for keys of random distribution the performance is linear and for keys with significant
10
+ * numbers of non-overlapping key ranges it is much faster.
11
+ * @param targetTree The tree to subtract from.
12
+ * @param subtractTree The tree whose keys will be removed from the result.
13
+ * @returns A new tree that contains the subtraction result.
14
+ * @throws Error if the trees were created with different comparators or max node sizes.
15
+ */
16
+ export default function subtract<TBTree extends BTree<K, V>, K, V>(targetTree: TBTree, subtractTree: TBTree): TBTree;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var shared_1 = require("./shared");
4
+ var decompose_1 = require("./decompose");
5
+ /**
6
+ * Returns a new tree containing only the keys that are present in `targetTree` but not `subtractTree` (set subtraction).
7
+ * Neither tree is modified.
8
+ *
9
+ * Complexity is O(N + M) for time and O(N) for allocations in the worst case. Additionally, time is bounded by
10
+ * O(log(N + M) * D1) and space by O(log N * D2), where `D1` is the number of disjoint key ranges between the trees
11
+ * and `D2` is the number of disjoint ranges inside `targetTree`, because disjoint subtrees are skipped entirely.
12
+ * In practice, that means for keys of random distribution the performance is linear and for keys with significant
13
+ * numbers of non-overlapping key ranges it is much faster.
14
+ * @param targetTree The tree to subtract from.
15
+ * @param subtractTree The tree whose keys will be removed from the result.
16
+ * @returns A new tree that contains the subtraction result.
17
+ * @throws Error if the trees were created with different comparators or max node sizes.
18
+ */
19
+ function subtract(targetTree, subtractTree) {
20
+ var _targetTree = targetTree;
21
+ var _subtractTree = subtractTree;
22
+ var branchingFactor = (0, shared_1.checkCanDoSetOperation)(_targetTree, _subtractTree, false);
23
+ if (_targetTree._root.size() === 0 || _subtractTree._root.size() === 0)
24
+ return targetTree.clone();
25
+ // Decompose target tree into disjoint subtrees leaves.
26
+ // As many of these as possible will be reused from the original trees, and the remaining
27
+ // will be leaves that are exploded (and filtered) due to intersecting leaves in subtractTree.
28
+ var decomposed = (0, decompose_1.decompose)(_targetTree, _subtractTree, function () { return undefined; }, true);
29
+ var constructor = targetTree.constructor;
30
+ if (decomposed.heights.length === 0) {
31
+ return new constructor(undefined, targetTree._compare, targetTree._maxNodeSize);
32
+ }
33
+ return (0, decompose_1.buildFromDecomposition)(constructor, branchingFactor, decomposed, targetTree._compare, targetTree._maxNodeSize);
34
+ }
35
+ exports.default = subtract;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var shared_1=require("./shared"),decompose_1=require("./decompose");function subtract(e,o){var r=e,t=o,o=(0,shared_1.checkCanDoSetOperation)(r,t,!1);if(0===r._root.size()||0===t._root.size())return e.clone();r=(0,decompose_1.decompose)(r,t,function(){},!0),t=e.constructor;return 0===r.heights.length?new t(void 0,e._compare,e._maxNodeSize):(0,decompose_1.buildFromDecomposition)(t,o,r,e._compare,e._maxNodeSize)}exports.default=subtract;
@@ -0,0 +1,16 @@
1
+ import BTree from '../b+tree';
2
+ /**
3
+ * Efficiently unions two trees, reusing subtrees wherever possible without mutating either input.
4
+ *
5
+ * Complexity is O(N + M) when the trees overlap heavily, and additionally bounded by O(log(N + M) * D)
6
+ * where `D` is the number of disjoint key ranges, because disjoint subtrees are skipped entirely.
7
+ * In practice, that means for keys of random distribution the performance is linear and for keys with significant
8
+ * numbers of non-overlapping key ranges it is much faster.
9
+ * @param treeA First tree to union.
10
+ * @param treeB Second tree to union.
11
+ * @param combineFn Called for keys that appear in both trees. Return the desired value, or
12
+ * `undefined` to omit the key from the result. Note: symmetric difference can be achieved by always returning `undefined`.
13
+ * @returns A new BTree that contains the unioned key/value pairs.
14
+ * @throws Error if the trees were created with different comparators or max node sizes.
15
+ */
16
+ export default function union<TBTree extends BTree<K, V>, K, V>(treeA: TBTree, treeB: TBTree, combineFn: (key: K, leftValue: V, rightValue: V) => V | undefined): TBTree;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var shared_1 = require("./shared");
4
+ var decompose_1 = require("./decompose");
5
+ /**
6
+ * Efficiently unions two trees, reusing subtrees wherever possible without mutating either input.
7
+ *
8
+ * Complexity is O(N + M) when the trees overlap heavily, and additionally bounded by O(log(N + M) * D)
9
+ * where `D` is the number of disjoint key ranges, because disjoint subtrees are skipped entirely.
10
+ * In practice, that means for keys of random distribution the performance is linear and for keys with significant
11
+ * numbers of non-overlapping key ranges it is much faster.
12
+ * @param treeA First tree to union.
13
+ * @param treeB Second tree to union.
14
+ * @param combineFn Called for keys that appear in both trees. Return the desired value, or
15
+ * `undefined` to omit the key from the result. Note: symmetric difference can be achieved by always returning `undefined`.
16
+ * @returns A new BTree that contains the unioned key/value pairs.
17
+ * @throws Error if the trees were created with different comparators or max node sizes.
18
+ */
19
+ function union(treeA, treeB, combineFn) {
20
+ if (treeA === treeB)
21
+ return treeA.clone();
22
+ var _treeA = treeA;
23
+ var _treeB = treeB;
24
+ var branchingFactor = (0, shared_1.checkCanDoSetOperation)(_treeA, _treeB, false);
25
+ if (_treeA._root.size() === 0)
26
+ return treeB.clone();
27
+ if (_treeB._root.size() === 0)
28
+ return treeA.clone();
29
+ // Decompose both trees into disjoint subtrees leaves.
30
+ // As many of these as possible will be reused from the original trees, and the remaining
31
+ // will be leaves that are the result of merging intersecting leaves.
32
+ var decomposed = (0, decompose_1.decompose)(_treeA, _treeB, combineFn);
33
+ var constructor = treeA.constructor;
34
+ return (0, decompose_1.buildFromDecomposition)(constructor, branchingFactor, decomposed, _treeA._compare, _treeA._maxNodeSize);
35
+ }
36
+ exports.default = union;