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
|
@@ -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;
|