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