@calcit/ternary-tree 0.0.18 → 0.0.19-a1
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/lib/{hash.d.ts → hash.d.mts} +0 -0
- package/lib/{hash.js → hash.mjs} +0 -0
- package/lib/index.d.mts +4 -0
- package/lib/index.mjs +4 -0
- package/lib/{list.d.ts → list.d.mts} +1 -1
- package/lib/{list.js → list.mjs} +3 -3
- package/lib/main.d.mts +2 -0
- package/lib/{main.js → main.mjs} +6 -6
- package/lib/{map.d.ts → map.d.mts} +1 -1
- package/lib/{map.js → map.mjs} +2 -2
- package/lib/{test-list.d.ts → test-list.d.mts} +0 -0
- package/lib/{test-list.js → test-list.mjs} +18 -2
- package/lib/{test-map.d.ts → test-map.d.mts} +0 -0
- package/lib/{test-map.js → test-map.mjs} +3 -3
- package/lib/{types.d.ts → types.d.mts} +0 -0
- package/lib/{types.js → types.mjs} +0 -0
- package/lib/{utils.d.ts → utils.d.mts} +1 -1
- package/lib/{utils.js → utils.mjs} +2 -2
- package/package.json +9 -7
- package/assets/index.html +0 -2
- package/lib/bundle.js +0 -3022
- package/lib/bundle.js.map +0 -1
- package/lib/index.d.ts +0 -4
- package/lib/index.js +0 -4
- package/lib/main.d.ts +0 -2
- package/src/costs.nim +0 -62
- package/src/hash.ts +0 -78
- package/src/index.ts +0 -5
- package/src/list.ts +0 -996
- package/src/main.ts +0 -20
- package/src/map.ts +0 -1341
- package/src/shape.nim +0 -62
- package/src/test-list.ts +0 -271
- package/src/test-map.ts +0 -288
- package/src/types.ts +0 -87
- package/src/utils.ts +0 -124
package/src/map.ts
DELETED
@@ -1,1341 +0,0 @@
|
|
1
|
-
import { TernaryTreeMap, TernaryTreeKind, TernaryTreeMapTheLeaf, TernaryTreeMapTheBranch, RefInt, Hash, hashGenerator, TernaryTreeMapHashEntry } from "./types";
|
2
|
-
import { divideTernarySizes, roughIntPow, cmp, dataEqual } from "./utils";
|
3
|
-
|
4
|
-
let emptyBranch: TernaryTreeMap<any, any> = null as any;
|
5
|
-
let nilResult = null as any;
|
6
|
-
|
7
|
-
function getMax<K, V>(tree: TernaryTreeMap<K, V>): Hash {
|
8
|
-
if (tree == null) {
|
9
|
-
throw new Error("Cannot find max hash of nil");
|
10
|
-
}
|
11
|
-
switch (tree.kind) {
|
12
|
-
case TernaryTreeKind.ternaryTreeLeaf:
|
13
|
-
return tree.hash;
|
14
|
-
case TernaryTreeKind.ternaryTreeBranch:
|
15
|
-
return tree.maxHash;
|
16
|
-
default:
|
17
|
-
throw new Error("Unknown");
|
18
|
-
}
|
19
|
-
}
|
20
|
-
|
21
|
-
function getMin<K, V>(tree: TernaryTreeMap<K, V>): Hash {
|
22
|
-
if (tree == null) {
|
23
|
-
throw new Error("Cannot find min hash of nil");
|
24
|
-
}
|
25
|
-
switch (tree.kind) {
|
26
|
-
case TernaryTreeKind.ternaryTreeLeaf:
|
27
|
-
return tree.hash;
|
28
|
-
case TernaryTreeKind.ternaryTreeBranch:
|
29
|
-
return tree.minHash;
|
30
|
-
default:
|
31
|
-
throw new Error("Unknown");
|
32
|
-
}
|
33
|
-
}
|
34
|
-
|
35
|
-
export function getMapDepth<K, V>(tree: TernaryTreeMap<K, V>): number {
|
36
|
-
// console.log( "calling...", tree)
|
37
|
-
if (tree == null) {
|
38
|
-
return 0;
|
39
|
-
}
|
40
|
-
switch (tree.kind) {
|
41
|
-
case TernaryTreeKind.ternaryTreeLeaf:
|
42
|
-
return 1;
|
43
|
-
case TernaryTreeKind.ternaryTreeBranch:
|
44
|
-
return Math.max(getMapDepth(tree.left), getMapDepth(tree.middle), getMapDepth(tree.right)) + 1;
|
45
|
-
default:
|
46
|
-
throw new Error("Unknown");
|
47
|
-
}
|
48
|
-
}
|
49
|
-
|
50
|
-
function createLeaf<K, T>(k: K, v: T): TernaryTreeMap<K, T> {
|
51
|
-
let result: TernaryTreeMapTheLeaf<K, T> = {
|
52
|
-
kind: TernaryTreeKind.ternaryTreeLeaf,
|
53
|
-
hash: hashGenerator(k),
|
54
|
-
elements: [[k, v]],
|
55
|
-
};
|
56
|
-
return result;
|
57
|
-
}
|
58
|
-
|
59
|
-
function createLeafFromHashEntry<K, T>(item: TernaryTreeMapHashEntry<K, T>): TernaryTreeMap<K, T> {
|
60
|
-
let result: TernaryTreeMap<K, T> = {
|
61
|
-
kind: TernaryTreeKind.ternaryTreeLeaf,
|
62
|
-
hash: item.hash,
|
63
|
-
elements: item.pairs,
|
64
|
-
};
|
65
|
-
return result;
|
66
|
-
}
|
67
|
-
|
68
|
-
// this proc is not exported, pick up next proc as the entry.
|
69
|
-
// pairs must be sorted before passing to proc.
|
70
|
-
function makeTernaryTreeMap<K, T>(size: number, offset: number, xs: /* var */ Array<TernaryTreeMapHashEntry<K, T>>): TernaryTreeMap<K, T> {
|
71
|
-
switch (size) {
|
72
|
-
case 0: {
|
73
|
-
let result: TernaryTreeMap<K, T> = emptyBranch;
|
74
|
-
return result;
|
75
|
-
}
|
76
|
-
case 1: {
|
77
|
-
let leftPair = xs[offset];
|
78
|
-
let result: TernaryTreeMap<K, T> = createLeafFromHashEntry(leftPair);
|
79
|
-
return result;
|
80
|
-
}
|
81
|
-
case 2: {
|
82
|
-
let leftPair = xs[offset];
|
83
|
-
let middlePair = xs[offset + 1];
|
84
|
-
let result: TernaryTreeMap<K, T> = {
|
85
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
86
|
-
maxHash: middlePair.hash,
|
87
|
-
minHash: leftPair.hash,
|
88
|
-
left: createLeafFromHashEntry(leftPair),
|
89
|
-
middle: createLeafFromHashEntry(middlePair),
|
90
|
-
right: emptyBranch,
|
91
|
-
depth: 1,
|
92
|
-
};
|
93
|
-
return result;
|
94
|
-
}
|
95
|
-
case 3: {
|
96
|
-
let leftPair = xs[offset];
|
97
|
-
let middlePair = xs[offset + 1];
|
98
|
-
let rightPair = xs[offset + 2];
|
99
|
-
let result: TernaryTreeMap<K, T> = {
|
100
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
101
|
-
maxHash: rightPair.hash,
|
102
|
-
minHash: leftPair.hash,
|
103
|
-
left: createLeafFromHashEntry(leftPair),
|
104
|
-
middle: createLeafFromHashEntry(middlePair),
|
105
|
-
right: createLeafFromHashEntry(rightPair),
|
106
|
-
depth: 1,
|
107
|
-
};
|
108
|
-
return result;
|
109
|
-
}
|
110
|
-
default: {
|
111
|
-
let divided = divideTernarySizes(size);
|
112
|
-
|
113
|
-
let left = makeTernaryTreeMap(divided.left, offset, xs);
|
114
|
-
let middle = makeTernaryTreeMap(divided.middle, offset + divided.left, xs);
|
115
|
-
let right = makeTernaryTreeMap(divided.right, offset + divided.left + divided.middle, xs);
|
116
|
-
|
117
|
-
let result: TernaryTreeMap<K, T> = {
|
118
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
119
|
-
maxHash: getMax(right),
|
120
|
-
minHash: getMin(left),
|
121
|
-
left: left,
|
122
|
-
middle: middle,
|
123
|
-
right: right,
|
124
|
-
depth: Math.max(getMapDepth(left), getMapDepth(middle), getMapDepth(right)) + 1,
|
125
|
-
};
|
126
|
-
return result;
|
127
|
-
}
|
128
|
-
}
|
129
|
-
}
|
130
|
-
|
131
|
-
export function initTernaryTreeMapFromHashEntries<K, T>(xs: Array<TernaryTreeMapHashEntry<K, T>>): TernaryTreeMap<K, T> {
|
132
|
-
return makeTernaryTreeMap(xs.length, 0, xs);
|
133
|
-
}
|
134
|
-
|
135
|
-
export function initTernaryTreeMap<K, T>(t: Map<K, T>): TernaryTreeMap<K, T> {
|
136
|
-
let groupBuffers: Map<number, Array<[K, T]>> = new Map();
|
137
|
-
let xs: Array<TernaryTreeMapHashEntry<K, T>> = [];
|
138
|
-
for (let [k, v] of t) {
|
139
|
-
let h = hashGenerator(k);
|
140
|
-
if (groupBuffers.has(h)) {
|
141
|
-
let branch = groupBuffers.get(h);
|
142
|
-
if (branch != null) {
|
143
|
-
branch.push([k, v]);
|
144
|
-
} else {
|
145
|
-
throw new Error("Expected referece to pairs");
|
146
|
-
}
|
147
|
-
} else {
|
148
|
-
let pairs: [K, T][] = [[k, v]];
|
149
|
-
groupBuffers.set(h, pairs);
|
150
|
-
xs.push({
|
151
|
-
hash: h,
|
152
|
-
pairs,
|
153
|
-
});
|
154
|
-
}
|
155
|
-
}
|
156
|
-
|
157
|
-
for (let [k, v] of groupBuffers) {
|
158
|
-
if (v != null) {
|
159
|
-
} else {
|
160
|
-
throw new Error("Expected reference to paris");
|
161
|
-
}
|
162
|
-
}
|
163
|
-
|
164
|
-
// MUTABLE in-place sort
|
165
|
-
xs.sort((a, b) => cmp(a.hash, b.hash));
|
166
|
-
|
167
|
-
let result = initTernaryTreeMapFromHashEntries(xs);
|
168
|
-
// checkMapStructure(result);
|
169
|
-
return result;
|
170
|
-
}
|
171
|
-
|
172
|
-
// use for..in for performance
|
173
|
-
export function initTernaryTreeMapFromArray<K, T>(t: Array<[K, T]>): TernaryTreeMap<K, T> {
|
174
|
-
let groupBuffers: Record<number, Array<[K, T]>> = {};
|
175
|
-
let xs: Array<TernaryTreeMapHashEntry<K, T>> = [];
|
176
|
-
for (let idx = 0; idx < t.length; idx++) {
|
177
|
-
let k = t[idx][0];
|
178
|
-
let v = t[idx][1];
|
179
|
-
let h = hashGenerator(k);
|
180
|
-
if (groupBuffers[h] != null) {
|
181
|
-
let branch = groupBuffers[h];
|
182
|
-
if (branch != null) {
|
183
|
-
branch.push([k, v]);
|
184
|
-
} else {
|
185
|
-
throw new Error("Expected referece to pairs");
|
186
|
-
}
|
187
|
-
} else {
|
188
|
-
let pairs: [K, T][] = [[k, v]];
|
189
|
-
groupBuffers[h] = pairs;
|
190
|
-
xs.push({
|
191
|
-
hash: h,
|
192
|
-
pairs: pairs,
|
193
|
-
});
|
194
|
-
}
|
195
|
-
}
|
196
|
-
|
197
|
-
// MUTABLE in-place sort
|
198
|
-
xs.sort((a, b) => cmp(a.hash, b.hash));
|
199
|
-
|
200
|
-
let result = initTernaryTreeMapFromHashEntries(xs);
|
201
|
-
// checkMapStructure(result);
|
202
|
-
return result;
|
203
|
-
}
|
204
|
-
|
205
|
-
// for empty map
|
206
|
-
export function initEmptyTernaryTreeMap<K, T>(): TernaryTreeMap<K, T> {
|
207
|
-
let result: TernaryTreeMap<K, T> = emptyBranch;
|
208
|
-
return result;
|
209
|
-
}
|
210
|
-
|
211
|
-
export function mapToString<K, V>(tree: TernaryTreeMap<K, V>): string {
|
212
|
-
return `TernaryTreeMap[${mapLen(tree)}, ...]`;
|
213
|
-
}
|
214
|
-
|
215
|
-
export function mapLen<K, V>(tree: TernaryTreeMap<K, V>): number {
|
216
|
-
if (tree == null) {
|
217
|
-
return 0;
|
218
|
-
}
|
219
|
-
switch (tree.kind) {
|
220
|
-
case TernaryTreeKind.ternaryTreeLeaf:
|
221
|
-
return tree.elements.length;
|
222
|
-
case TernaryTreeKind.ternaryTreeBranch:
|
223
|
-
return mapLen(tree.left) + mapLen(tree.middle) + mapLen(tree.right); // TODO
|
224
|
-
default:
|
225
|
-
throw new Error("Unknown");
|
226
|
-
}
|
227
|
-
}
|
228
|
-
|
229
|
-
// when size succeeds bound, no longer counting, faster than traversing whole tree
|
230
|
-
export function mapLenBound<K, V>(tree: TernaryTreeMap<K, V>, bound: number): number {
|
231
|
-
if (tree == null) {
|
232
|
-
return 0;
|
233
|
-
}
|
234
|
-
switch (tree.kind) {
|
235
|
-
case TernaryTreeKind.ternaryTreeLeaf:
|
236
|
-
return tree.elements.length;
|
237
|
-
case TernaryTreeKind.ternaryTreeBranch:
|
238
|
-
let ret = mapLenBound(tree.left, bound);
|
239
|
-
if (ret > bound) {
|
240
|
-
return ret;
|
241
|
-
}
|
242
|
-
ret = ret + mapLenBound(tree.middle, bound);
|
243
|
-
if (ret > bound) {
|
244
|
-
return ret;
|
245
|
-
}
|
246
|
-
ret = ret + mapLenBound(tree.right, bound);
|
247
|
-
return ret;
|
248
|
-
default:
|
249
|
-
throw new Error("Unknown");
|
250
|
-
}
|
251
|
-
}
|
252
|
-
|
253
|
-
export function formatMapInline<K, V>(tree: TernaryTreeMap<K, V>, withHash: boolean = false): string {
|
254
|
-
if (tree == null) {
|
255
|
-
return "_";
|
256
|
-
}
|
257
|
-
switch (tree.kind) {
|
258
|
-
case TernaryTreeKind.ternaryTreeLeaf:
|
259
|
-
if (withHash) {
|
260
|
-
return `${tree.hash}->${tree.elements[0][0]}:${tree.elements[0][1]}`; // TODO show whole list
|
261
|
-
} else {
|
262
|
-
return `${tree.elements[0][0]}:${tree.elements[0][1]}`;
|
263
|
-
}
|
264
|
-
case TernaryTreeKind.ternaryTreeBranch: {
|
265
|
-
return "(" + formatMapInline(tree.left, withHash) + " " + formatMapInline(tree.middle, withHash) + " " + formatMapInline(tree.right, withHash) + ")";
|
266
|
-
}
|
267
|
-
|
268
|
-
default:
|
269
|
-
throw new Error("Unknown");
|
270
|
-
}
|
271
|
-
}
|
272
|
-
|
273
|
-
export function isMapEmpty<K, V>(tree: TernaryTreeMap<K, V>): boolean {
|
274
|
-
if (tree == null) {
|
275
|
-
return true;
|
276
|
-
}
|
277
|
-
switch (tree.kind) {
|
278
|
-
case TernaryTreeKind.ternaryTreeLeaf:
|
279
|
-
return false;
|
280
|
-
case TernaryTreeKind.ternaryTreeBranch:
|
281
|
-
return tree.left == null && tree.middle == null && tree.right == null;
|
282
|
-
default:
|
283
|
-
throw new Error("Unknown");
|
284
|
-
}
|
285
|
-
}
|
286
|
-
|
287
|
-
export function isMapOfOne<K, V>(tree: TernaryTreeMap<K, V>, counted: number = 0): boolean {
|
288
|
-
if (tree == null) {
|
289
|
-
return true;
|
290
|
-
}
|
291
|
-
switch (tree.kind) {
|
292
|
-
case TernaryTreeKind.ternaryTreeLeaf:
|
293
|
-
return false;
|
294
|
-
case TernaryTreeKind.ternaryTreeBranch:
|
295
|
-
return tree.left == null && tree.middle == null && tree.right == null;
|
296
|
-
default:
|
297
|
-
throw new Error("Unknown");
|
298
|
-
}
|
299
|
-
}
|
300
|
-
|
301
|
-
function collectHashSortedArray<K, T>(tree: TernaryTreeMap<K, T>, acc: /* var */ Array<[K, T]>, idx: RefInt): void {
|
302
|
-
if (tree == null || isMapEmpty(tree)) {
|
303
|
-
// discard
|
304
|
-
} else {
|
305
|
-
switch (tree.kind) {
|
306
|
-
case TernaryTreeKind.ternaryTreeLeaf: {
|
307
|
-
for (let i = 0; i < tree.elements.length; i++) {
|
308
|
-
let item = tree.elements[i];
|
309
|
-
acc[idx.value] = item;
|
310
|
-
idx.value = idx.value + 1;
|
311
|
-
}
|
312
|
-
break;
|
313
|
-
}
|
314
|
-
case TernaryTreeKind.ternaryTreeBranch: {
|
315
|
-
collectHashSortedArray(tree.left, acc, idx);
|
316
|
-
collectHashSortedArray(tree.middle, acc, idx);
|
317
|
-
collectHashSortedArray(tree.right, acc, idx);
|
318
|
-
break;
|
319
|
-
}
|
320
|
-
default:
|
321
|
-
throw new Error("Unknown");
|
322
|
-
}
|
323
|
-
}
|
324
|
-
}
|
325
|
-
|
326
|
-
// sorted by hash(tree.key)
|
327
|
-
export function toHashSortedPairs<K, T>(tree: TernaryTreeMap<K, T>): Array<[K, T]> {
|
328
|
-
let acc = new Array<[K, T]>(mapLen(tree));
|
329
|
-
let idx: RefInt = { value: 0 };
|
330
|
-
collectHashSortedArray(tree, acc, idx);
|
331
|
-
return acc;
|
332
|
-
}
|
333
|
-
|
334
|
-
function collectOrderedHashEntries<K, T>(tree: TernaryTreeMap<K, T>, acc: /* var */ Array<TernaryTreeMapHashEntry<K, T>>, idx: RefInt): void {
|
335
|
-
if (tree == null || isMapEmpty(tree)) {
|
336
|
-
// discard
|
337
|
-
} else {
|
338
|
-
switch (tree.kind) {
|
339
|
-
case TernaryTreeKind.ternaryTreeLeaf: {
|
340
|
-
acc[idx.value] = { hash: tree.hash, pairs: tree.elements };
|
341
|
-
idx.value = idx.value + 1;
|
342
|
-
break;
|
343
|
-
}
|
344
|
-
case TernaryTreeKind.ternaryTreeBranch: {
|
345
|
-
collectOrderedHashEntries(tree.left, acc, idx);
|
346
|
-
collectOrderedHashEntries(tree.middle, acc, idx);
|
347
|
-
collectOrderedHashEntries(tree.right, acc, idx);
|
348
|
-
break;
|
349
|
-
}
|
350
|
-
default: {
|
351
|
-
throw new Error("Unknown");
|
352
|
-
}
|
353
|
-
}
|
354
|
-
}
|
355
|
-
}
|
356
|
-
|
357
|
-
// for reusing leaves during rebalancing
|
358
|
-
function toOrderedHashEntries<K, T>(tree: TernaryTreeMap<K, T>): Array<TernaryTreeMapHashEntry<K, T>> {
|
359
|
-
let acc = new Array<TernaryTreeMapHashEntry<K, T>>(mapLen(tree));
|
360
|
-
let idx: RefInt = { value: 0 };
|
361
|
-
collectOrderedHashEntries(tree, acc, idx);
|
362
|
-
return acc;
|
363
|
-
}
|
364
|
-
|
365
|
-
export function contains<K, T>(originalTree: TernaryTreeMap<K, T>, item: K): boolean {
|
366
|
-
if (originalTree == null) {
|
367
|
-
return false;
|
368
|
-
}
|
369
|
-
|
370
|
-
// TODO
|
371
|
-
|
372
|
-
// reduce redundant computation by reusing hash result
|
373
|
-
let hx = hashGenerator(item);
|
374
|
-
|
375
|
-
let tree = originalTree;
|
376
|
-
|
377
|
-
whileLoop: while (tree != null) {
|
378
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
379
|
-
if (hx === tree.hash) {
|
380
|
-
let size = tree.elements.length;
|
381
|
-
for (let idx = 0; idx < size; idx++) {
|
382
|
-
let pair = tree.elements[idx];
|
383
|
-
if (dataEqual(pair[0], item)) {
|
384
|
-
return true;
|
385
|
-
}
|
386
|
-
}
|
387
|
-
}
|
388
|
-
return false;
|
389
|
-
}
|
390
|
-
|
391
|
-
// echo "looking for: ", hx, " ", item, " in ", tree.formatInline(true)
|
392
|
-
if (tree.left == null) {
|
393
|
-
return false;
|
394
|
-
}
|
395
|
-
if (tree.left.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
396
|
-
if (hx < tree.left.hash) {
|
397
|
-
return false;
|
398
|
-
}
|
399
|
-
if (tree.left.hash === hx) {
|
400
|
-
tree = tree.left;
|
401
|
-
continue whileLoop; // notice, it jumps to while loop
|
402
|
-
}
|
403
|
-
} else {
|
404
|
-
if (hx < tree.left.minHash) {
|
405
|
-
return false;
|
406
|
-
}
|
407
|
-
if (hx <= tree.left.maxHash) {
|
408
|
-
tree = tree.left;
|
409
|
-
continue whileLoop; // notice, it jumps to while loop
|
410
|
-
}
|
411
|
-
}
|
412
|
-
|
413
|
-
if (tree.middle == null) {
|
414
|
-
return false;
|
415
|
-
}
|
416
|
-
if (tree.middle.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
417
|
-
if (hx < tree.middle.hash) {
|
418
|
-
return false;
|
419
|
-
}
|
420
|
-
if (tree.middle.hash === hx) {
|
421
|
-
tree = tree.middle;
|
422
|
-
continue whileLoop; // notice, it jumps to while loop
|
423
|
-
}
|
424
|
-
} else {
|
425
|
-
if (hx < tree.middle.minHash) {
|
426
|
-
return false;
|
427
|
-
}
|
428
|
-
if (hx <= tree.middle.maxHash) {
|
429
|
-
tree = tree.middle;
|
430
|
-
continue whileLoop; // notice, it jumps to while loop
|
431
|
-
}
|
432
|
-
}
|
433
|
-
|
434
|
-
if (tree.right == null) {
|
435
|
-
return false;
|
436
|
-
}
|
437
|
-
if (tree.right.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
438
|
-
if (hx < tree.right.hash) {
|
439
|
-
return false;
|
440
|
-
}
|
441
|
-
if (tree.right.hash === hx) {
|
442
|
-
tree = tree.right;
|
443
|
-
continue whileLoop; // notice, it jumps to while loop
|
444
|
-
}
|
445
|
-
} else {
|
446
|
-
if (hx < tree.right.minHash) {
|
447
|
-
return false;
|
448
|
-
}
|
449
|
-
if (hx <= tree.right.maxHash) {
|
450
|
-
tree = tree.right;
|
451
|
-
continue whileLoop; // notice, it jumps to while loop
|
452
|
-
}
|
453
|
-
}
|
454
|
-
return false;
|
455
|
-
}
|
456
|
-
|
457
|
-
return false;
|
458
|
-
}
|
459
|
-
|
460
|
-
export function mapGetDefault<K, T>(originalTree: TernaryTreeMap<K, T>, item: K, v0: T): T {
|
461
|
-
let hx = hashGenerator(item);
|
462
|
-
|
463
|
-
let tree = originalTree;
|
464
|
-
|
465
|
-
whileLoop: while (tree != null) {
|
466
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
467
|
-
let size = tree.elements.length;
|
468
|
-
for (let i = 0; i < size; i++) {
|
469
|
-
let pair = tree.elements[i];
|
470
|
-
if (dataEqual(pair[0], item)) {
|
471
|
-
return pair[1];
|
472
|
-
}
|
473
|
-
}
|
474
|
-
return v0;
|
475
|
-
}
|
476
|
-
|
477
|
-
// echo "looking for: ", hx, " ", item, " in ", tree.formatInline
|
478
|
-
|
479
|
-
if (tree.left == null) {
|
480
|
-
return v0;
|
481
|
-
}
|
482
|
-
if (tree.left.kind == TernaryTreeKind.ternaryTreeLeaf) {
|
483
|
-
if (hx < tree.left.hash) {
|
484
|
-
return v0;
|
485
|
-
}
|
486
|
-
if (tree.left.hash === hx) {
|
487
|
-
tree = tree.left;
|
488
|
-
continue whileLoop; // notice, it jumps to while loop
|
489
|
-
}
|
490
|
-
} else {
|
491
|
-
if (hx < tree.left.minHash) {
|
492
|
-
return v0;
|
493
|
-
}
|
494
|
-
if (hx <= tree.left.maxHash) {
|
495
|
-
tree = tree.left;
|
496
|
-
continue whileLoop; // notice, it jumps to while loop
|
497
|
-
}
|
498
|
-
}
|
499
|
-
|
500
|
-
if (tree.middle == null) {
|
501
|
-
return v0;
|
502
|
-
}
|
503
|
-
if (tree.middle.kind == TernaryTreeKind.ternaryTreeLeaf) {
|
504
|
-
if (hx < tree.middle.hash) {
|
505
|
-
return v0;
|
506
|
-
}
|
507
|
-
if (tree.middle.hash === hx) {
|
508
|
-
tree = tree.middle;
|
509
|
-
continue whileLoop; // notice, it jumps to while loop
|
510
|
-
}
|
511
|
-
} else {
|
512
|
-
if (hx < tree.middle.minHash) {
|
513
|
-
return v0;
|
514
|
-
}
|
515
|
-
if (hx <= tree.middle.maxHash) {
|
516
|
-
tree = tree.middle;
|
517
|
-
continue whileLoop; // notice, it jumps to while loop
|
518
|
-
}
|
519
|
-
}
|
520
|
-
|
521
|
-
if (tree.right == null) {
|
522
|
-
return v0;
|
523
|
-
}
|
524
|
-
if (tree.right.kind == TernaryTreeKind.ternaryTreeLeaf) {
|
525
|
-
if (hx < tree.right.hash) {
|
526
|
-
return v0;
|
527
|
-
}
|
528
|
-
if (tree.right.hash === hx) {
|
529
|
-
tree = tree.right;
|
530
|
-
continue whileLoop; // notice, it jumps to while loop
|
531
|
-
}
|
532
|
-
} else {
|
533
|
-
if (hx < tree.right.minHash) {
|
534
|
-
return v0;
|
535
|
-
}
|
536
|
-
if (hx <= tree.right.maxHash) {
|
537
|
-
tree = tree.right;
|
538
|
-
continue whileLoop; // notice, it jumps to while loop
|
539
|
-
}
|
540
|
-
}
|
541
|
-
|
542
|
-
return v0;
|
543
|
-
}
|
544
|
-
|
545
|
-
return v0;
|
546
|
-
}
|
547
|
-
|
548
|
-
// leaves on the left has smaller hashes
|
549
|
-
// TODO check sizes, hashes
|
550
|
-
export function checkMapStructure<K, V>(tree: TernaryTreeMap<K, V>): boolean {
|
551
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
552
|
-
for (let i = 0; i < tree.elements.length; i++) {
|
553
|
-
let pair = tree.elements[i];
|
554
|
-
if (pair.length !== 2) {
|
555
|
-
throw new Error("Expected pair to br [k,v] :" + pair);
|
556
|
-
}
|
557
|
-
if (tree.hash !== hashGenerator(pair[0])) {
|
558
|
-
throw new Error(`Bad hash at leaf node ${tree}`);
|
559
|
-
}
|
560
|
-
}
|
561
|
-
|
562
|
-
if (mapLenBound(tree, 2) !== 1) {
|
563
|
-
throw new Error(`Bad len at leaf node ${tree}`);
|
564
|
-
}
|
565
|
-
} else {
|
566
|
-
if (tree.left == null) {
|
567
|
-
if (tree.middle != null) {
|
568
|
-
throw new Error("Layout is not compact");
|
569
|
-
}
|
570
|
-
if (tree.middle != null) {
|
571
|
-
throw new Error("Layout is not compact");
|
572
|
-
}
|
573
|
-
}
|
574
|
-
if (tree.middle == null) {
|
575
|
-
if (tree.right != null) {
|
576
|
-
throw new Error("Layout is not compact");
|
577
|
-
}
|
578
|
-
}
|
579
|
-
if (tree.left != null && tree.middle != null) {
|
580
|
-
if (getMax(tree.left) >= getMin(tree.middle)) {
|
581
|
-
throw new Error(`Wrong hash order at left/middle branches ${formatMapInline(tree, true)}`);
|
582
|
-
}
|
583
|
-
}
|
584
|
-
|
585
|
-
if (tree.left != null && tree.right != null) {
|
586
|
-
if (getMax(tree.left) >= getMin(tree.right)) {
|
587
|
-
console.log(getMax(tree.left), getMin(tree.right));
|
588
|
-
throw new Error(`Wrong hash order at left/right branches ${formatMapInline(tree, true)}`);
|
589
|
-
}
|
590
|
-
}
|
591
|
-
if (tree.middle != null && tree.right != null) {
|
592
|
-
if (getMax(tree.middle) >= getMin(tree.right)) {
|
593
|
-
throw new Error(`Wrong hash order at middle/right branches ${formatMapInline(tree, true)}`);
|
594
|
-
}
|
595
|
-
}
|
596
|
-
|
597
|
-
if (tree.left != null) {
|
598
|
-
checkMapStructure(tree.left);
|
599
|
-
}
|
600
|
-
if (tree.middle != null) {
|
601
|
-
checkMapStructure(tree.middle);
|
602
|
-
}
|
603
|
-
if (tree.right != null) {
|
604
|
-
checkMapStructure(tree.right);
|
605
|
-
}
|
606
|
-
}
|
607
|
-
|
608
|
-
return true;
|
609
|
-
}
|
610
|
-
|
611
|
-
function rangeContainsHash<K, T>(tree: TernaryTreeMap<K, T>, thisHash: Hash): boolean {
|
612
|
-
if (tree == null) {
|
613
|
-
return false;
|
614
|
-
} else if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
615
|
-
return tree.hash === thisHash;
|
616
|
-
} else {
|
617
|
-
return thisHash >= tree.minHash && thisHash <= tree.maxHash;
|
618
|
-
}
|
619
|
-
}
|
620
|
-
|
621
|
-
function assocExisted<K, T>(tree: TernaryTreeMap<K, T>, key: K, item: T, thisHash: Hash = null as any): TernaryTreeMap<K, T> {
|
622
|
-
if (tree == null || isMapEmpty(tree)) {
|
623
|
-
throw new Error("Cannot call assoc on nil");
|
624
|
-
}
|
625
|
-
|
626
|
-
thisHash = thisHash ?? hashGenerator(key);
|
627
|
-
|
628
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
629
|
-
if (tree.hash !== thisHash) {
|
630
|
-
throw new Error("Expected hashes to be identical, otherwise element is missing");
|
631
|
-
}
|
632
|
-
let newPairs = new Array<[K, T]>(tree.elements.length);
|
633
|
-
let replaced = false;
|
634
|
-
let size = tree.elements.length;
|
635
|
-
for (let idx = 0; idx < size; idx++) {
|
636
|
-
let pair = tree.elements[idx];
|
637
|
-
if (dataEqual(pair[0], key)) {
|
638
|
-
newPairs[idx] = [key, item];
|
639
|
-
replaced = true;
|
640
|
-
} else {
|
641
|
-
newPairs[idx] = pair;
|
642
|
-
}
|
643
|
-
}
|
644
|
-
if (replaced) {
|
645
|
-
let result: TernaryTreeMap<K, T> = { kind: TernaryTreeKind.ternaryTreeLeaf, hash: thisHash, elements: newPairs };
|
646
|
-
return result;
|
647
|
-
} else {
|
648
|
-
throw new Error("Unexpected missing hash in assoc, invalid branch");
|
649
|
-
}
|
650
|
-
}
|
651
|
-
|
652
|
-
if (thisHash < tree.minHash) throw new Error("Unexpected missing hash in assoc, hash too small");
|
653
|
-
else if (thisHash > tree.maxHash) throw new Error("Unexpected missing hash in assoc, hash too large");
|
654
|
-
|
655
|
-
if (tree.left == null) {
|
656
|
-
throw new Error("Unexpected missing hash in assoc, found not branch");
|
657
|
-
}
|
658
|
-
if (rangeContainsHash(tree.left, thisHash)) {
|
659
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
660
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
661
|
-
maxHash: tree.maxHash,
|
662
|
-
minHash: tree.minHash,
|
663
|
-
left: assocExisted(tree.left, key, item, thisHash),
|
664
|
-
middle: tree.middle,
|
665
|
-
right: tree.right,
|
666
|
-
depth: 0, // TODO
|
667
|
-
};
|
668
|
-
return result;
|
669
|
-
}
|
670
|
-
|
671
|
-
if (tree.middle == null) {
|
672
|
-
throw new Error("Unexpected missing hash in assoc, found not branch");
|
673
|
-
}
|
674
|
-
if (rangeContainsHash(tree.middle, thisHash)) {
|
675
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
676
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
677
|
-
maxHash: tree.maxHash,
|
678
|
-
minHash: tree.minHash,
|
679
|
-
left: tree.left,
|
680
|
-
middle: assocExisted(tree.middle, key, item, thisHash),
|
681
|
-
right: tree.right,
|
682
|
-
depth: 0, // TODO
|
683
|
-
};
|
684
|
-
return result;
|
685
|
-
}
|
686
|
-
|
687
|
-
if (tree.right == null) {
|
688
|
-
throw new Error("Unexpected missing hash in assoc, found not branch");
|
689
|
-
}
|
690
|
-
if (rangeContainsHash(tree.right, thisHash)) {
|
691
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
692
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
693
|
-
maxHash: tree.maxHash,
|
694
|
-
minHash: tree.minHash,
|
695
|
-
left: tree.left,
|
696
|
-
middle: tree.middle,
|
697
|
-
right: assocExisted(tree.right, key, item, thisHash),
|
698
|
-
depth: 0, // TODO
|
699
|
-
};
|
700
|
-
return result;
|
701
|
-
}
|
702
|
-
throw new Error("Unexpected missing hash in assoc, found not branch");
|
703
|
-
}
|
704
|
-
|
705
|
-
function assocNew<K, T>(tree: TernaryTreeMap<K, T>, key: K, item: T, thisHash: Hash = null as any): TernaryTreeMap<K, T> {
|
706
|
-
// echo fmt"assoc new: {key} to {tree.formatInline}"
|
707
|
-
if (tree == null || isMapEmpty(tree)) {
|
708
|
-
return createLeaf(key, item);
|
709
|
-
}
|
710
|
-
|
711
|
-
thisHash = thisHash ?? hashGenerator(key);
|
712
|
-
|
713
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
714
|
-
if (thisHash > tree.hash) {
|
715
|
-
let childBranch: TernaryTreeMapTheLeaf<K, T> = {
|
716
|
-
kind: TernaryTreeKind.ternaryTreeLeaf,
|
717
|
-
hash: thisHash,
|
718
|
-
elements: [[key, item]],
|
719
|
-
};
|
720
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
721
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
722
|
-
maxHash: thisHash,
|
723
|
-
minHash: tree.hash,
|
724
|
-
left: tree,
|
725
|
-
middle: childBranch,
|
726
|
-
right: emptyBranch,
|
727
|
-
depth: 0, // TODO
|
728
|
-
};
|
729
|
-
return result;
|
730
|
-
} else if (thisHash < tree.hash) {
|
731
|
-
let childBranch: TernaryTreeMapTheLeaf<K, T> = {
|
732
|
-
kind: TernaryTreeKind.ternaryTreeLeaf,
|
733
|
-
hash: thisHash,
|
734
|
-
elements: [[key, item]],
|
735
|
-
};
|
736
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
737
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
738
|
-
maxHash: tree.hash,
|
739
|
-
minHash: thisHash,
|
740
|
-
left: childBranch,
|
741
|
-
middle: tree,
|
742
|
-
right: emptyBranch,
|
743
|
-
depth: 0, // TODO
|
744
|
-
};
|
745
|
-
return result;
|
746
|
-
} else {
|
747
|
-
let size = tree.elements.length;
|
748
|
-
for (let i = 0; i < size; i++) {
|
749
|
-
let pair = tree.elements[i];
|
750
|
-
if (dataEqual(pair[0], key)) {
|
751
|
-
throw new Error("Unexpected existed key in assoc");
|
752
|
-
}
|
753
|
-
}
|
754
|
-
let newPairs = new Array<[K, T]>(tree.elements.length + 1);
|
755
|
-
for (let idx = 0; idx < size; idx++) {
|
756
|
-
let pair = tree.elements[idx];
|
757
|
-
newPairs[idx] = pair;
|
758
|
-
}
|
759
|
-
newPairs[tree.elements.length] = [key, item];
|
760
|
-
let result: TernaryTreeMapTheLeaf<K, T> = {
|
761
|
-
kind: TernaryTreeKind.ternaryTreeLeaf,
|
762
|
-
hash: tree.hash,
|
763
|
-
elements: newPairs,
|
764
|
-
};
|
765
|
-
return result;
|
766
|
-
}
|
767
|
-
} else {
|
768
|
-
if (thisHash < tree.minHash) {
|
769
|
-
if (tree.right == null) {
|
770
|
-
let childBranch: TernaryTreeMapTheLeaf<K, T> = {
|
771
|
-
kind: TernaryTreeKind.ternaryTreeLeaf,
|
772
|
-
hash: thisHash,
|
773
|
-
elements: [[key, item]],
|
774
|
-
};
|
775
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
776
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
777
|
-
maxHash: tree.maxHash,
|
778
|
-
minHash: thisHash,
|
779
|
-
left: childBranch,
|
780
|
-
middle: tree.left,
|
781
|
-
right: tree.middle,
|
782
|
-
depth: 0, // TODO
|
783
|
-
};
|
784
|
-
return result;
|
785
|
-
} else {
|
786
|
-
let childBranch: TernaryTreeMapTheLeaf<K, T> = {
|
787
|
-
kind: TernaryTreeKind.ternaryTreeLeaf,
|
788
|
-
hash: thisHash,
|
789
|
-
elements: [[key, item]],
|
790
|
-
};
|
791
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
792
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
793
|
-
maxHash: tree.maxHash,
|
794
|
-
minHash: thisHash,
|
795
|
-
left: childBranch,
|
796
|
-
middle: tree,
|
797
|
-
right: emptyBranch,
|
798
|
-
depth: 0, // TODO
|
799
|
-
};
|
800
|
-
return result;
|
801
|
-
}
|
802
|
-
}
|
803
|
-
|
804
|
-
if (thisHash > tree.maxHash) {
|
805
|
-
// in compact layout, left arm must be existed
|
806
|
-
if (tree.middle == null) {
|
807
|
-
let childBranch: TernaryTreeMapTheLeaf<K, T> = {
|
808
|
-
kind: TernaryTreeKind.ternaryTreeLeaf,
|
809
|
-
hash: thisHash,
|
810
|
-
elements: [[key, item]],
|
811
|
-
};
|
812
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
813
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
814
|
-
maxHash: thisHash,
|
815
|
-
minHash: tree.minHash,
|
816
|
-
left: tree.left,
|
817
|
-
middle: childBranch,
|
818
|
-
right: emptyBranch,
|
819
|
-
depth: 0, // TODO
|
820
|
-
};
|
821
|
-
return result;
|
822
|
-
} else if (tree.right == null) {
|
823
|
-
let childBranch: TernaryTreeMapTheLeaf<K, T> = {
|
824
|
-
kind: TernaryTreeKind.ternaryTreeLeaf,
|
825
|
-
hash: thisHash,
|
826
|
-
elements: [[key, item]],
|
827
|
-
};
|
828
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
829
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
830
|
-
maxHash: thisHash,
|
831
|
-
minHash: tree.minHash,
|
832
|
-
left: tree.left,
|
833
|
-
middle: tree.middle,
|
834
|
-
right: childBranch,
|
835
|
-
depth: 0, // TODO
|
836
|
-
};
|
837
|
-
return result;
|
838
|
-
} else {
|
839
|
-
let childBranch: TernaryTreeMapTheLeaf<K, T> = {
|
840
|
-
kind: TernaryTreeKind.ternaryTreeLeaf,
|
841
|
-
hash: thisHash,
|
842
|
-
elements: [[key, item]],
|
843
|
-
};
|
844
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
845
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
846
|
-
maxHash: thisHash,
|
847
|
-
minHash: tree.minHash,
|
848
|
-
left: tree,
|
849
|
-
middle: childBranch,
|
850
|
-
right: emptyBranch,
|
851
|
-
depth: 0, // TODO
|
852
|
-
};
|
853
|
-
|
854
|
-
return result;
|
855
|
-
}
|
856
|
-
}
|
857
|
-
|
858
|
-
if (rangeContainsHash(tree.left, thisHash)) {
|
859
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
860
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
861
|
-
maxHash: tree.maxHash,
|
862
|
-
minHash: tree.minHash,
|
863
|
-
left: assocNew(tree.left, key, item, thisHash),
|
864
|
-
middle: tree.middle,
|
865
|
-
right: tree.right,
|
866
|
-
depth: 0, // TODO
|
867
|
-
};
|
868
|
-
return result;
|
869
|
-
}
|
870
|
-
if (rangeContainsHash(tree.middle, thisHash)) {
|
871
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
872
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
873
|
-
maxHash: tree.maxHash,
|
874
|
-
minHash: tree.minHash,
|
875
|
-
left: tree.left,
|
876
|
-
middle: assocNew(tree.middle, key, item, thisHash),
|
877
|
-
right: tree.right,
|
878
|
-
depth: 0, // TODO
|
879
|
-
};
|
880
|
-
return result;
|
881
|
-
}
|
882
|
-
if (rangeContainsHash(tree.right, thisHash)) {
|
883
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
884
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
885
|
-
maxHash: tree.maxHash,
|
886
|
-
minHash: tree.minHash,
|
887
|
-
left: tree.left,
|
888
|
-
middle: tree.middle,
|
889
|
-
right: assocNew(tree.right, key, item, thisHash),
|
890
|
-
depth: 0, // TODO
|
891
|
-
};
|
892
|
-
return result;
|
893
|
-
}
|
894
|
-
|
895
|
-
if (tree.middle == null) {
|
896
|
-
throw new Error("unreachable. if inside range, then middle should be here");
|
897
|
-
}
|
898
|
-
if (thisHash < getMin(tree.middle)) {
|
899
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
900
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
901
|
-
maxHash: tree.maxHash,
|
902
|
-
minHash: tree.minHash,
|
903
|
-
left: assocNew(tree.left, key, item, thisHash),
|
904
|
-
middle: tree.middle,
|
905
|
-
right: tree.right,
|
906
|
-
depth: 0, // TODO
|
907
|
-
};
|
908
|
-
return result;
|
909
|
-
} else {
|
910
|
-
let result: TernaryTreeMap<K, T> = {
|
911
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
912
|
-
maxHash: tree.maxHash,
|
913
|
-
minHash: tree.minHash,
|
914
|
-
left: tree.left,
|
915
|
-
middle: tree.middle,
|
916
|
-
right: assocNew(tree.right, key, item, thisHash),
|
917
|
-
depth: 0, // TODO
|
918
|
-
};
|
919
|
-
return result;
|
920
|
-
}
|
921
|
-
}
|
922
|
-
}
|
923
|
-
|
924
|
-
export function assocMap<K, T>(tree: TernaryTreeMap<K, T>, key: K, item: T, disableBalancing: boolean = false): TernaryTreeMap<K, T> {
|
925
|
-
if (tree == null || isMapEmpty(tree)) {
|
926
|
-
return createLeaf(key, item);
|
927
|
-
}
|
928
|
-
|
929
|
-
if (contains(tree, key)) {
|
930
|
-
return assocExisted(tree, key, item);
|
931
|
-
} else {
|
932
|
-
return assocNew(tree, key, item);
|
933
|
-
}
|
934
|
-
}
|
935
|
-
|
936
|
-
function dissocExisted<K, T>(tree: TernaryTreeMap<K, T>, key: K): TernaryTreeMap<K, T> {
|
937
|
-
if (tree == null) {
|
938
|
-
throw new Error("Unexpected missing key in dissoc");
|
939
|
-
}
|
940
|
-
|
941
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
942
|
-
if (tree.hash === hashGenerator(key)) {
|
943
|
-
let size = tree.elements.length;
|
944
|
-
if (size === 1 && dataEqual(key, tree.elements[0][0])) {
|
945
|
-
return emptyBranch;
|
946
|
-
} else {
|
947
|
-
let newPairs: Array<[K, T]> = [];
|
948
|
-
for (let i = 0; i < size; i++) {
|
949
|
-
let pair = tree.elements[i];
|
950
|
-
if (!dataEqual(pair[0], key)) {
|
951
|
-
newPairs.push(pair);
|
952
|
-
}
|
953
|
-
}
|
954
|
-
let result: TernaryTreeMapTheLeaf<K, T> = { kind: TernaryTreeKind.ternaryTreeLeaf, hash: tree.hash, elements: newPairs };
|
955
|
-
return result;
|
956
|
-
}
|
957
|
-
} else {
|
958
|
-
throw new Error("Unexpected missing key in dissoc on leaf");
|
959
|
-
}
|
960
|
-
}
|
961
|
-
|
962
|
-
if (mapLenBound(tree, 2) === 1) {
|
963
|
-
if (!contains(tree, key)) {
|
964
|
-
throw new Error("Unexpected missing key in dissoc single branch");
|
965
|
-
}
|
966
|
-
return emptyBranch;
|
967
|
-
}
|
968
|
-
|
969
|
-
let thisHash = hashGenerator(key);
|
970
|
-
|
971
|
-
if (rangeContainsHash(tree.left, thisHash)) {
|
972
|
-
let changedBranch = dissocExisted(tree.left, key);
|
973
|
-
|
974
|
-
if (isMapEmpty(changedBranch)) {
|
975
|
-
if (isMapEmpty(tree.right)) {
|
976
|
-
return tree.middle;
|
977
|
-
}
|
978
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
979
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
980
|
-
maxHash: tree.maxHash,
|
981
|
-
minHash: getMin(tree.middle),
|
982
|
-
left: tree.middle,
|
983
|
-
middle: tree.right,
|
984
|
-
right: emptyBranch,
|
985
|
-
depth: 0, // TODO
|
986
|
-
};
|
987
|
-
return result;
|
988
|
-
} else {
|
989
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
990
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
991
|
-
maxHash: tree.maxHash,
|
992
|
-
minHash: getMin(changedBranch),
|
993
|
-
left: changedBranch,
|
994
|
-
middle: tree.middle,
|
995
|
-
right: tree.right,
|
996
|
-
depth: 0, // TODO
|
997
|
-
};
|
998
|
-
return result;
|
999
|
-
}
|
1000
|
-
}
|
1001
|
-
|
1002
|
-
if (rangeContainsHash(tree.middle, thisHash)) {
|
1003
|
-
let changedBranch = dissocExisted(tree.middle, key);
|
1004
|
-
|
1005
|
-
if (isMapEmpty(changedBranch)) {
|
1006
|
-
if (isMapEmpty(tree.right)) {
|
1007
|
-
return tree.left;
|
1008
|
-
}
|
1009
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
1010
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
1011
|
-
maxHash: tree.maxHash,
|
1012
|
-
minHash: tree.minHash,
|
1013
|
-
left: tree.left,
|
1014
|
-
middle: tree.right,
|
1015
|
-
right: emptyBranch,
|
1016
|
-
depth: 0, // TODO
|
1017
|
-
};
|
1018
|
-
return result;
|
1019
|
-
} else {
|
1020
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
1021
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
1022
|
-
maxHash: tree.maxHash,
|
1023
|
-
minHash: tree.minHash,
|
1024
|
-
left: tree.left,
|
1025
|
-
middle: changedBranch,
|
1026
|
-
right: tree.right,
|
1027
|
-
depth: 0, // TODO
|
1028
|
-
};
|
1029
|
-
return result;
|
1030
|
-
}
|
1031
|
-
}
|
1032
|
-
|
1033
|
-
if (rangeContainsHash(tree.right, thisHash)) {
|
1034
|
-
let changedBranch = dissocExisted(tree.right, key);
|
1035
|
-
|
1036
|
-
if (changedBranch == null) {
|
1037
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
1038
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
1039
|
-
maxHash: getMax(tree.middle),
|
1040
|
-
minHash: tree.minHash,
|
1041
|
-
left: tree.left,
|
1042
|
-
middle: tree.middle,
|
1043
|
-
right: emptyBranch,
|
1044
|
-
depth: 0, // TODO
|
1045
|
-
};
|
1046
|
-
return result;
|
1047
|
-
} else {
|
1048
|
-
let result: TernaryTreeMapTheBranch<K, T> = {
|
1049
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
1050
|
-
maxHash: getMax(changedBranch),
|
1051
|
-
minHash: tree.minHash,
|
1052
|
-
left: tree.left,
|
1053
|
-
middle: tree.middle,
|
1054
|
-
right: changedBranch,
|
1055
|
-
depth: 0, // TODO
|
1056
|
-
};
|
1057
|
-
return result;
|
1058
|
-
}
|
1059
|
-
}
|
1060
|
-
|
1061
|
-
throw new Error("Cannot find branch in dissoc");
|
1062
|
-
}
|
1063
|
-
|
1064
|
-
export function dissocMap<K, T>(tree: TernaryTreeMap<K, T>, key: K): TernaryTreeMap<K, T> {
|
1065
|
-
if (contains(tree, key)) {
|
1066
|
-
return dissocExisted(tree, key);
|
1067
|
-
} else {
|
1068
|
-
return tree;
|
1069
|
-
}
|
1070
|
-
}
|
1071
|
-
|
1072
|
-
function collectToPairsArray<K, T>(acc: Array<[K, T]>, tree: TernaryTreeMap<K, T>): void {
|
1073
|
-
if (tree != null) {
|
1074
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
1075
|
-
for (let i = 0; i < tree.elements.length; i++) {
|
1076
|
-
let pair = tree.elements[i];
|
1077
|
-
acc.push(pair);
|
1078
|
-
}
|
1079
|
-
} else {
|
1080
|
-
if (tree.left != null) {
|
1081
|
-
collectToPairsArray(acc, tree.left);
|
1082
|
-
}
|
1083
|
-
if (tree.middle != null) {
|
1084
|
-
collectToPairsArray(acc, tree.middle);
|
1085
|
-
}
|
1086
|
-
if (tree.right != null) {
|
1087
|
-
collectToPairsArray(acc, tree.right);
|
1088
|
-
}
|
1089
|
-
}
|
1090
|
-
}
|
1091
|
-
}
|
1092
|
-
|
1093
|
-
/** similar to `toPairs`, but using Array.push directly */
|
1094
|
-
export function toPairsArray<K, T>(tree: TernaryTreeMap<K, T>): Array<[K, T]> {
|
1095
|
-
let result: Array<[K, T]> = [];
|
1096
|
-
collectToPairsArray(result, tree);
|
1097
|
-
return result;
|
1098
|
-
}
|
1099
|
-
|
1100
|
-
export function* toPairs<K, T>(tree: TernaryTreeMap<K, T>): Generator<[K, T]> {
|
1101
|
-
if (tree != null) {
|
1102
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
1103
|
-
for (let pair of tree.elements) {
|
1104
|
-
yield pair;
|
1105
|
-
}
|
1106
|
-
} else {
|
1107
|
-
if (tree.left != null) {
|
1108
|
-
for (let item of toPairs(tree.left)) {
|
1109
|
-
yield item;
|
1110
|
-
}
|
1111
|
-
}
|
1112
|
-
if (tree.middle != null) {
|
1113
|
-
for (let item of toPairs(tree.middle)) {
|
1114
|
-
yield item;
|
1115
|
-
}
|
1116
|
-
}
|
1117
|
-
if (tree.right != null) {
|
1118
|
-
for (let item of toPairs(tree.right)) {
|
1119
|
-
yield item;
|
1120
|
-
}
|
1121
|
-
}
|
1122
|
-
}
|
1123
|
-
}
|
1124
|
-
}
|
1125
|
-
|
1126
|
-
export function* toKeys<K, V>(tree: TernaryTreeMap<K, V>): Generator<K> {
|
1127
|
-
if (tree != null) {
|
1128
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
1129
|
-
for (let i = 0; i < tree.elements.length; i++) {
|
1130
|
-
let pair = tree.elements[i];
|
1131
|
-
yield pair[0];
|
1132
|
-
}
|
1133
|
-
} else {
|
1134
|
-
if (tree.left != null) {
|
1135
|
-
for (let item of toKeys(tree.left)) {
|
1136
|
-
yield item;
|
1137
|
-
}
|
1138
|
-
}
|
1139
|
-
if (tree.middle != null) {
|
1140
|
-
for (let item of toKeys(tree.middle)) {
|
1141
|
-
yield item;
|
1142
|
-
}
|
1143
|
-
}
|
1144
|
-
if (tree.right != null) {
|
1145
|
-
for (let item of toKeys(tree.right)) {
|
1146
|
-
yield item;
|
1147
|
-
}
|
1148
|
-
}
|
1149
|
-
}
|
1150
|
-
}
|
1151
|
-
}
|
1152
|
-
|
1153
|
-
export function* toValues<K, V>(tree: TernaryTreeMap<K, V>): Generator<V> {
|
1154
|
-
if (tree != null) {
|
1155
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
1156
|
-
for (let i = 0; i < tree.elements.length; i++) {
|
1157
|
-
let pair = tree.elements[i];
|
1158
|
-
yield pair[1];
|
1159
|
-
}
|
1160
|
-
} else {
|
1161
|
-
if (tree.left != null) {
|
1162
|
-
for (let item of toValues(tree.left)) {
|
1163
|
-
yield item;
|
1164
|
-
}
|
1165
|
-
}
|
1166
|
-
if (tree.middle != null) {
|
1167
|
-
for (let item of toValues(tree.middle)) {
|
1168
|
-
yield item;
|
1169
|
-
}
|
1170
|
-
}
|
1171
|
-
if (tree.right != null) {
|
1172
|
-
for (let item of toValues(tree.right)) {
|
1173
|
-
yield item;
|
1174
|
-
}
|
1175
|
-
}
|
1176
|
-
}
|
1177
|
-
}
|
1178
|
-
}
|
1179
|
-
|
1180
|
-
export function mapEqual<K, V>(xs: TernaryTreeMap<K, V>, ys: TernaryTreeMap<K, V>): boolean {
|
1181
|
-
if (xs === ys) {
|
1182
|
-
return true;
|
1183
|
-
}
|
1184
|
-
if (mapLen(xs) !== mapLen(ys)) {
|
1185
|
-
return false;
|
1186
|
-
}
|
1187
|
-
|
1188
|
-
if (isMapEmpty(xs)) {
|
1189
|
-
return true;
|
1190
|
-
}
|
1191
|
-
|
1192
|
-
for (let pair of toPairsArray(xs)) {
|
1193
|
-
let key = pair[0];
|
1194
|
-
let vx = pair[1];
|
1195
|
-
|
1196
|
-
if (!contains(ys, key)) {
|
1197
|
-
return false;
|
1198
|
-
}
|
1199
|
-
let vy = mapGetDefault(ys, key, null);
|
1200
|
-
|
1201
|
-
// TODO compare deep structures
|
1202
|
-
if (!dataEqual(vx, vy)) {
|
1203
|
-
return false;
|
1204
|
-
}
|
1205
|
-
}
|
1206
|
-
|
1207
|
-
return true;
|
1208
|
-
}
|
1209
|
-
|
1210
|
-
export function merge<K, T>(xs: TernaryTreeMap<K, T>, ys: TernaryTreeMap<K, T>): TernaryTreeMap<K, T> {
|
1211
|
-
let ret = xs;
|
1212
|
-
let counted = 0;
|
1213
|
-
for (let [key, item] of toPairs(ys)) {
|
1214
|
-
ret = assocMap(ret, key, item);
|
1215
|
-
// # TODO pickd loop by experience
|
1216
|
-
if (counted > 700) {
|
1217
|
-
forceMapInplaceBalancing(ret);
|
1218
|
-
counted = 0;
|
1219
|
-
} else {
|
1220
|
-
counted = counted + 1;
|
1221
|
-
}
|
1222
|
-
}
|
1223
|
-
return ret;
|
1224
|
-
}
|
1225
|
-
|
1226
|
-
// # skip a value, mostly for nil
|
1227
|
-
export function mergeSkip<K, T>(xs: TernaryTreeMap<K, T>, ys: TernaryTreeMap<K, T>, skipped: T): TernaryTreeMap<K, T> {
|
1228
|
-
let ret = xs;
|
1229
|
-
let counted = 0;
|
1230
|
-
for (let [key, item] of toPairs(ys)) {
|
1231
|
-
if (dataEqual(item, skipped)) {
|
1232
|
-
continue;
|
1233
|
-
}
|
1234
|
-
ret = assocMap(ret, key, item);
|
1235
|
-
// # TODO pickd loop by experience
|
1236
|
-
if (counted > 700) {
|
1237
|
-
forceMapInplaceBalancing(ret);
|
1238
|
-
counted = 0;
|
1239
|
-
} else {
|
1240
|
-
counted = counted + 1;
|
1241
|
-
}
|
1242
|
-
}
|
1243
|
-
return ret;
|
1244
|
-
}
|
1245
|
-
|
1246
|
-
// this function mutates original tree to make it more balanced
|
1247
|
-
export function forceMapInplaceBalancing<K, T>(tree: TernaryTreeMap<K, T>): void {
|
1248
|
-
// echo "Force inplace balancing of list"
|
1249
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeBranch) {
|
1250
|
-
let xs = toOrderedHashEntries(tree);
|
1251
|
-
let newTree = makeTernaryTreeMap(xs.length, 0, xs) as TernaryTreeMapTheBranch<K, T>;
|
1252
|
-
tree.left = newTree.left;
|
1253
|
-
tree.middle = newTree.middle;
|
1254
|
-
tree.right = newTree.right;
|
1255
|
-
} else {
|
1256
|
-
// discard
|
1257
|
-
}
|
1258
|
-
}
|
1259
|
-
|
1260
|
-
export function sameMapShape<K, T>(xs: TernaryTreeMap<K, T>, ys: TernaryTreeMap<K, T>): boolean {
|
1261
|
-
if (xs == null) {
|
1262
|
-
if (ys == null) {
|
1263
|
-
return true;
|
1264
|
-
} else {
|
1265
|
-
return false;
|
1266
|
-
}
|
1267
|
-
}
|
1268
|
-
if (ys == null) {
|
1269
|
-
return false;
|
1270
|
-
}
|
1271
|
-
|
1272
|
-
if (mapLen(xs) !== mapLen(ys)) {
|
1273
|
-
return false;
|
1274
|
-
}
|
1275
|
-
|
1276
|
-
if (xs.kind !== ys.kind) {
|
1277
|
-
return false;
|
1278
|
-
}
|
1279
|
-
|
1280
|
-
if (xs.kind === TernaryTreeKind.ternaryTreeLeaf && ys.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
1281
|
-
if (xs.elements.length !== ys.elements.length) {
|
1282
|
-
return false;
|
1283
|
-
}
|
1284
|
-
for (let idx = 0; idx < xs.elements.length; idx++) {
|
1285
|
-
if (!dataEqual(xs.elements[idx], ys.elements[idx])) {
|
1286
|
-
return false;
|
1287
|
-
}
|
1288
|
-
}
|
1289
|
-
return true;
|
1290
|
-
} else if (xs.kind === TernaryTreeKind.ternaryTreeBranch && ys.kind === TernaryTreeKind.ternaryTreeBranch) {
|
1291
|
-
if (!sameMapShape(xs.left, ys.left)) {
|
1292
|
-
return false;
|
1293
|
-
}
|
1294
|
-
|
1295
|
-
if (!sameMapShape(xs.middle, ys.middle)) {
|
1296
|
-
return false;
|
1297
|
-
}
|
1298
|
-
|
1299
|
-
if (!sameMapShape(xs.right, ys.right)) {
|
1300
|
-
return false;
|
1301
|
-
}
|
1302
|
-
|
1303
|
-
return true;
|
1304
|
-
} else {
|
1305
|
-
throw new Error("Unknown");
|
1306
|
-
}
|
1307
|
-
}
|
1308
|
-
|
1309
|
-
export function mapMapValues<K, T, V>(tree: TernaryTreeMap<K, T>, f: (x: T) => V): TernaryTreeMap<K, V> {
|
1310
|
-
if (tree == null) {
|
1311
|
-
return tree;
|
1312
|
-
}
|
1313
|
-
|
1314
|
-
switch (tree.kind) {
|
1315
|
-
case TernaryTreeKind.ternaryTreeLeaf: {
|
1316
|
-
let newElements = new Array<[K, V]>(tree.elements.length);
|
1317
|
-
let size = tree.elements.length;
|
1318
|
-
for (let idx = 0; idx < size; idx++) {
|
1319
|
-
newElements[idx] = [tree.elements[idx][0], f(tree.elements[idx][1])];
|
1320
|
-
}
|
1321
|
-
let result: TernaryTreeMap<K, V> = {
|
1322
|
-
kind: TernaryTreeKind.ternaryTreeLeaf,
|
1323
|
-
hash: tree.hash,
|
1324
|
-
elements: newElements,
|
1325
|
-
};
|
1326
|
-
return result;
|
1327
|
-
}
|
1328
|
-
case TernaryTreeKind.ternaryTreeBranch: {
|
1329
|
-
let result: TernaryTreeMap<K, V> = {
|
1330
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
1331
|
-
depth: tree.depth,
|
1332
|
-
minHash: tree.minHash,
|
1333
|
-
maxHash: tree.maxHash,
|
1334
|
-
left: mapMapValues(tree.left, f),
|
1335
|
-
middle: mapMapValues(tree.middle, f),
|
1336
|
-
right: mapMapValues(tree.right, f),
|
1337
|
-
};
|
1338
|
-
return result;
|
1339
|
-
}
|
1340
|
-
}
|
1341
|
-
}
|