@calcit/ternary-tree 0.0.23 → 0.0.25

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.
@@ -0,0 +1,153 @@
1
+ import { initTernaryTreeList, initTernaryTreeListFromRange, listGet, assocList, insert, listLen, indexOf, listToItems, prepend, append, concat, slice, reverse, listMapValues, } from "./list.mjs";
2
+ function createTestListData(size) {
3
+ const data = [];
4
+ for (let i = 0; i < size; i++) {
5
+ data.push(i);
6
+ }
7
+ return data;
8
+ }
9
+ function measureTime(name, fn) {
10
+ const start = performance.now();
11
+ const result = fn();
12
+ const end = performance.now();
13
+ console.log(`${name}: ${(end - start).toFixed(2)}ms`);
14
+ return result;
15
+ }
16
+ export function runListPerformanceTests() {
17
+ console.log("\n=== List Performance Tests ===");
18
+ const sizes = [100, 1000, 5000, 10000];
19
+ for (const size of sizes) {
20
+ console.log(`\n--- Testing with ${size} elements ---`);
21
+ const testData = createTestListData(size);
22
+ // Test list creation
23
+ const treeList = measureTime(`initTernaryTreeList(${size})`, () => {
24
+ return initTernaryTreeList(testData);
25
+ });
26
+ // Test range creation
27
+ measureTime(`initTernaryTreeListFromRange(${size})`, () => {
28
+ return initTernaryTreeListFromRange(testData, 0, size);
29
+ });
30
+ // Test random access (listGet)
31
+ const indices = Array.from({ length: Math.min(100, size) }, (_, i) => Math.floor(Math.random() * size));
32
+ measureTime(`Random access(${indices.length})`, () => {
33
+ for (const idx of indices) {
34
+ listGet(treeList, idx);
35
+ }
36
+ });
37
+ // Test sequential access
38
+ measureTime(`Sequential access(${size})`, () => {
39
+ for (let i = 0; i < size; i++) {
40
+ listGet(treeList, i);
41
+ }
42
+ });
43
+ // Test prepend operations
44
+ measureTime(`Prepend operations(100)`, () => {
45
+ let list = treeList;
46
+ for (let i = 0; i < 100; i++) {
47
+ list = prepend(list, i + size);
48
+ }
49
+ return list;
50
+ });
51
+ // Test append operations
52
+ measureTime(`Append operations(100)`, () => {
53
+ let list = treeList;
54
+ for (let i = 0; i < 100; i++) {
55
+ list = append(list, i + size);
56
+ }
57
+ return list;
58
+ });
59
+ // Test assoc operations
60
+ const assocIndices = Array.from({ length: Math.min(50, size) }, (_, i) => Math.floor(Math.random() * size));
61
+ measureTime(`Assoc operations(${assocIndices.length})`, () => {
62
+ let list = treeList;
63
+ for (const idx of assocIndices) {
64
+ list = assocList(list, idx, idx * 2);
65
+ }
66
+ return list;
67
+ });
68
+ // Test insert operations
69
+ const insertIndices = Array.from({ length: Math.min(25, size) }, (_, i) => Math.floor(Math.random() * (size + i)));
70
+ measureTime(`Insert operations(${insertIndices.length})`, () => {
71
+ let list = treeList;
72
+ for (let i = 0; i < insertIndices.length; i++) {
73
+ const idx = Math.min(insertIndices[i], listLen(list));
74
+ list = insert(list, idx, i + size);
75
+ }
76
+ return list;
77
+ });
78
+ // Test search operations
79
+ const searchValues = testData.slice(0, Math.min(50, size));
80
+ measureTime(`Search operations(${searchValues.length})`, () => {
81
+ for (const value of searchValues) {
82
+ indexOf(treeList, value);
83
+ }
84
+ });
85
+ // Test iteration
86
+ measureTime(`Iterator traversal(${size})`, () => {
87
+ let count = 0;
88
+ for (const item of listToItems(treeList)) {
89
+ count++;
90
+ }
91
+ return count;
92
+ });
93
+ // Test slice operations
94
+ const sliceCount = Math.min(10, size / 10);
95
+ measureTime(`Slice operations(${sliceCount})`, () => {
96
+ for (let i = 0; i < sliceCount; i++) {
97
+ const start = Math.floor((Math.random() * size) / 2);
98
+ const end = start + Math.floor((Math.random() * size) / 4);
99
+ slice(treeList, start, end);
100
+ }
101
+ });
102
+ // Test reverse operation
103
+ if (size <= 5000) {
104
+ // Only test reverse for smaller sizes as it can be expensive
105
+ measureTime(`Reverse(${size})`, () => {
106
+ return reverse(treeList);
107
+ });
108
+ }
109
+ // Test map operation
110
+ measureTime(`Map operation(${size})`, () => {
111
+ return listMapValues(treeList, (x) => x * 2);
112
+ });
113
+ }
114
+ // Concat performance test
115
+ console.log("\n=== Concat Performance Test ===");
116
+ const list1 = initTernaryTreeList(createTestListData(1000));
117
+ const list2 = initTernaryTreeList(createTestListData(1000));
118
+ const list3 = initTernaryTreeList(createTestListData(1000));
119
+ measureTime("Concat two lists(1000 each)", () => {
120
+ return concat(list1, list2);
121
+ });
122
+ measureTime("Concat three lists(1000 each)", () => {
123
+ return concat(concat(list1, list2), list3);
124
+ });
125
+ // Memory stress test
126
+ console.log("\n=== Memory Usage Test ===");
127
+ const largeData = createTestListData(25000);
128
+ measureTime("Large list creation(25k)", () => {
129
+ return initTernaryTreeList(largeData);
130
+ });
131
+ // Cascading operations test
132
+ console.log("\n=== Cascading Operations Test ===");
133
+ measureTime("Complex operations chain", () => {
134
+ let list = initTernaryTreeList(createTestListData(1000));
135
+ // Chain multiple operations
136
+ list = prepend(list, -1);
137
+ list = append(list, 1001);
138
+ list = assocList(list, 500, 9999);
139
+ list = insert(list, 250, 8888);
140
+ // Access and search
141
+ listGet(list, 100);
142
+ indexOf(list, 9999);
143
+ // Slice and iterate
144
+ const sliced = slice(list, 100, 200);
145
+ for (const item of listToItems(sliced)) {
146
+ // consume iterator
147
+ }
148
+ return list;
149
+ });
150
+ }
151
+ if (import.meta.url === `file://${process.argv[1]}`) {
152
+ runListPerformanceTests();
153
+ }
package/lib/test-list.mjs CHANGED
@@ -1,208 +1,207 @@
1
1
  import { listToString, initTernaryTreeList, initTernaryTreeListFromRange, indexOf, findIndex, reverse, checkListStructure, slice, listToPairs, listToItems, formatListInline, sameListShape, assocBefore, concat, assocAfter, prepend, append, rest, butlast, first, assocList, dissocList, listGet, insert, initEmptyTernaryTreeList, last, listLen, forceListInplaceBalancing, listEqual, indexToItems, listMapValues, concat2, } from "./list.mjs";
2
- import { test, check, arrayEqual, checkEqual } from "./test-utils.mjs";
2
+ import { describe, test, check, checkEqual, checkArrayEqual } from "./test-utils.mjs";
3
3
  export let runListTests = () => {
4
- test("init list", () => {
5
- check(listToString(initTernaryTreeList([1, 2, 3, 4])) === "TernaryTreeList[4, ...]");
6
- let origin11 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
7
- let data11 = initTernaryTreeList(origin11);
8
- check(checkListStructure(data11));
9
- checkEqual(formatListInline(data11), "((1 (2 3 _) 4) (5 6 7) (8 (9 10 _) 11))");
10
- check(arrayEqual(origin11, [...listToItems(data11)]));
11
- check(arrayEqual([...listToItems(data11)], [...indexToItems(data11)]));
12
- let emptyXs = new Array(0);
13
- check(listEqual(initEmptyTernaryTreeList(), initTernaryTreeList(emptyXs)));
14
- });
15
- test("list operations", () => {
16
- let origin11 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
17
- let data11 = initTernaryTreeList(origin11);
18
- // get
19
- for (let idx = 0; idx < origin11.length; idx++) {
20
- check(origin11[idx] === listGet(data11, idx));
21
- }
22
- check(first(data11) === 1);
23
- check(last(data11) === 11);
24
- // assoc
25
- let origin5 = [1, 2, 3, 4, 5];
26
- let data5 = initTernaryTreeList(origin5);
27
- let updated = assocList(data5, 3, 10);
28
- check(listGet(updated, 3) === 10);
29
- check(listGet(data5, 3) === 4);
30
- check(listLen(updated) === listLen(data5));
31
- for (let idx = 0; idx < listLen(data5); idx++) {
32
- // echo data5.dissoc(idx).formatInline
33
- check(listLen(dissocList(data5, idx)) === listLen(data5) - 1);
34
- }
35
- checkEqual(formatListInline(data5), "((1 2 _) 3 (4 5 _))");
36
- checkEqual(formatListInline(dissocList(data5, 0)), "(2 3 (4 5 _))");
37
- checkEqual(formatListInline(dissocList(data5, 1)), "(1 3 (4 5 _))");
38
- checkEqual(formatListInline(dissocList(data5, 2)), "((1 2 _) (4 5 _) _)");
39
- checkEqual(formatListInline(dissocList(data5, 3)), "((1 2 _) 3 5)");
40
- checkEqual(formatListInline(dissocList(data5, 4)), "((1 2 _) 3 4)");
41
- checkEqual(formatListInline(rest(initTernaryTreeList([1]))), "_");
42
- checkEqual(formatListInline(rest(initTernaryTreeList([1, 2]))), "2");
43
- checkEqual(formatListInline(rest(initTernaryTreeList([1, 2, 3]))), "(2 3 _)");
44
- checkEqual(formatListInline(rest(initTernaryTreeList([1, 2, 3, 4]))), "((2 3 _) 4 _)");
45
- checkEqual(formatListInline(rest(initTernaryTreeList([1, 2, 3, 4, 5]))), "(2 3 (4 5 _))");
46
- checkEqual(formatListInline(butlast(initTernaryTreeList([1]))), "_");
47
- checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2]))), "1");
48
- checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2, 3]))), "(1 2 _)");
49
- checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2, 3, 4]))), "(1 (2 3 _) _)");
50
- checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2, 3, 4, 5]))), "((1 2 _) 3 4)");
51
- });
52
- test("list insertions", () => {
53
- let origin5 = [1, 2, 3, 4, 5];
54
- let data5 = initTernaryTreeList(origin5);
55
- checkEqual(formatListInline(data5), "((1 2 _) 3 (4 5 _))");
56
- checkEqual(formatListInline(insert(data5, 0, 10, false)), "(10 ((1 2 _) 3 (4 5 _)) _)");
57
- checkEqual(formatListInline(insert(data5, 0, 10, true)), "((1 10 2) 3 (4 5 _))");
58
- checkEqual(formatListInline(insert(data5, 1, 10, false)), "((1 10 2) 3 (4 5 _))");
59
- checkEqual(formatListInline(insert(data5, 1, 10, true)), "((1 2 10) 3 (4 5 _))");
60
- checkEqual(formatListInline(insert(data5, 2, 10, false)), "((1 2 _) (10 3 _) (4 5 _))");
61
- checkEqual(formatListInline(insert(data5, 2, 10, true)), "((1 2 _) (3 10 _) (4 5 _))");
62
- checkEqual(formatListInline(insert(data5, 3, 10, false)), "((1 2 _) 3 (10 4 5))");
63
- checkEqual(formatListInline(insert(data5, 3, 10, true)), "((1 2 _) 3 (4 10 5))");
64
- checkEqual(formatListInline(insert(data5, 4, 10, false)), "((1 2 _) 3 (4 10 5))");
65
- checkEqual(formatListInline(insert(data5, 4, 10, true)), "(((1 2 _) 3 (4 5 _)) 10 _)");
66
- let origin4 = [1, 2, 3, 4];
67
- let data4 = initTernaryTreeList(origin4);
68
- checkEqual(formatListInline(assocBefore(data4, 3, 10)), "(1 (2 3 _) (10 4 _))");
69
- checkEqual(formatListInline(assocAfter(data4, 3, 10)), "(1 (2 3 _) (4 10 _))");
70
- checkEqual(formatListInline(prepend(data4, 10)), "((10 1 _) (2 3 _) 4)");
71
- checkEqual(formatListInline(append(data4, 10)), "(1 (2 3 _) (4 10 _))");
72
- });
73
- test("concat", () => {
74
- let data1 = initTernaryTreeList([1, 2]);
75
- let data2 = initTernaryTreeList([3, 4]);
76
- let data3 = initTernaryTreeList([5, 6]);
77
- let data4 = initTernaryTreeList([7, 8]);
78
- check(formatListInline(concat(data1, data2)) === "(1 2 (3 4 _))");
79
- check(formatListInline(concat(initTernaryTreeList([]), data1)) === "(1 2 _)");
80
- check(formatListInline(concat(data1, data2, data3)) === "((1 2 _) (3 4 _) (5 6 _))");
81
- check(formatListInline(concat(data1, data2, data3, data4)) === "((1 2 _) ((3 4 _) (5 6 _) _) (7 8 _))");
82
- checkListStructure(concat(data1, data2));
83
- checkListStructure(concat(data1, data2, data3));
84
- checkListStructure(concat(data1, data2, data3, data4));
85
- check(listLen(concat(data1, data2, data3, data4)) === 8);
86
- });
87
- test("check(equality", () => {
88
- let origin4 = [1, 2, 3, 4];
89
- let data4 = initTernaryTreeList(origin4);
90
- let data4n = initTernaryTreeList(origin4);
91
- let data4Made = prepend(initTernaryTreeList([2, 3, 4]), 1);
92
- checkListStructure(data4);
93
- checkListStructure(data4n);
94
- checkListStructure(data4Made);
95
- check(sameListShape(data4, data4) === true);
96
- check(sameListShape(data4, data4n) === true);
97
- check(sameListShape(data4, data4Made) === false);
98
- check(listEqual(data4, data4n));
99
- check(listEqual(data4, data4Made));
100
- check(listEqual(data4n, data4Made));
101
- check(data4 !== data4Made); // identical false
102
- });
103
- test("force balancing", () => {
104
- var data = initTernaryTreeList([]);
105
- for (let idx = 0; idx < 20; idx++) {
106
- data = append(data, idx, true);
107
- checkListStructure(data);
108
- }
109
- // echo data.formatInline
110
- check(formatListInline(data) === "(((0 1 2) (3 4 5) (6 7 8)) ((9 10 11) (12 13 14) (15 16 17)) (18 19 _))");
111
- forceListInplaceBalancing(data);
112
- check(formatListInline(data) === "(((0 1 _) (2 3 4) (5 6 _)) ((7 8 _) (9 10 _) (11 12 _)) ((13 14 _) (15 16 17) (18 19 _)))");
113
- // echo data.formatInline
114
- });
115
- test("iterator", () => {
116
- let origin4 = [1, 2, 3, 4];
117
- let data4 = initTernaryTreeList(origin4);
118
- checkListStructure(data4);
119
- var i = 0;
120
- for (let item of listToItems(data4)) {
121
- i = i + 1;
122
- }
123
- check(i === 4);
124
- i = 0;
125
- for (let [idx, item] of listToPairs(data4)) {
126
- i = i + idx;
127
- }
128
- check(i === 6);
129
- });
130
- test("check structure", () => {
131
- var data = initTernaryTreeList([]);
132
- for (let idx = 0; idx < 20; idx++) {
133
- data = append(data, idx, true);
134
- checkListStructure(data);
135
- }
136
- check(checkListStructure(data));
137
- for (let idx = 0; idx < 20; idx++) {
138
- data = rest(data);
139
- checkListStructure(data);
140
- }
141
- let origin11 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
142
- let data11 = initTernaryTreeList(origin11);
143
- check(checkListStructure(data11));
144
- checkListStructure(prepend(initEmptyTernaryTreeList(), 1));
145
- checkListStructure(prepend(null, 1));
146
- });
147
- test("slices", () => {
148
- var data = initTernaryTreeList([]);
149
- for (let idx = 0; idx < 40; idx++) {
150
- data = append(data, idx, true);
151
- }
152
- var list40 = [];
153
- for (let idx = 0; idx < 40; idx++) {
154
- list40.push(idx);
155
- }
156
- for (let i = 0; i < 40; i++) {
157
- for (let j = i; j < 40; j++) {
158
- check(arrayEqual([...listToItems(slice(data, i, j))], list40.slice(i, j)));
159
- checkListStructure(slice(data, i, j));
4
+ describe("TernaryTreeList Tests", () => {
5
+ test("should initialize list correctly", () => {
6
+ check(listToString(initTernaryTreeList([1, 2, 3, 4])) === "TernaryTreeList[4, ...]");
7
+ let origin11 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
8
+ let data11 = initTernaryTreeList(origin11);
9
+ check(checkListStructure(data11));
10
+ checkEqual(formatListInline(data11), "((1 (2 3 _) 4) (5 6 7) (8 (9 10 _) 11))");
11
+ checkArrayEqual([...listToItems(data11)], origin11);
12
+ checkArrayEqual([...listToItems(data11)], [...indexToItems(data11)]);
13
+ let emptyXs = new Array(0);
14
+ check(listEqual(initEmptyTernaryTreeList(), initTernaryTreeList(emptyXs)));
15
+ });
16
+ test("should perform basic list operations", () => {
17
+ let origin11 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
18
+ let data11 = initTernaryTreeList(origin11);
19
+ // get
20
+ for (let idx = 0; idx < origin11.length; idx++) {
21
+ check(origin11[idx] === listGet(data11, idx));
160
22
  }
161
- }
162
- });
163
- test("reverse", () => {
164
- let data = initTernaryTreeList([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
165
- let reversedData = reverse(data);
166
- check(arrayEqual([...listToItems(data)].reverse(), [...listToItems(reversedData)]));
167
- check(checkListStructure(reversedData));
168
- });
169
- test("list traverse", () => {
170
- var i = 0;
171
- let data = initTernaryTreeList([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
172
- checkListStructure(data);
173
- for (let x of listToItems(data)) {
174
- i = i + 1;
175
- }
176
- check(i === 10);
177
- });
178
- test("index of", () => {
179
- let data = initTernaryTreeList([1, 2, 3, 4, 5, 6, 7, 8]);
180
- check(indexOf(data, 2) === 1);
181
- check(findIndex(data, (x) => x === 2) === 1);
182
- check(indexOf(data, 9) === -1);
183
- check(findIndex(data, (x) => x === 9) === -1);
184
- });
185
- test("map values", () => {
186
- let data = initTernaryTreeList([1, 2, 3, 4]);
187
- let data2 = initTernaryTreeList([1, 4, 9, 16]);
188
- let data3 = listMapValues(data, (x) => x * x);
189
- checkListStructure(data3);
190
- check(listEqual(data2, data3));
191
- check(formatListInline(data2) === formatListInline(data3));
192
- });
193
- test("concat", () => {
194
- let data1 = initTernaryTreeList([3, 4]);
195
- let data2 = initTernaryTreeListFromRange([1, 2, 3, 4, 5, 6], 2, 4);
196
- check(listEqual(data1, data2));
197
- checkListStructure(data1);
198
- checkListStructure(data2);
199
- });
200
- test("concat loop", () => {
201
- let data1 = initTernaryTreeList([3, 4]);
202
- let data2 = initTernaryTreeList([5]);
203
- for (let i = 0; i < 100; i++) {
204
- data1 = concat2(data1, data2);
205
- }
206
- console.log("concat into depth", formatListInline(data1));
23
+ check(first(data11) === 1);
24
+ check(last(data11) === 11);
25
+ // assoc
26
+ let origin5 = [1, 2, 3, 4, 5];
27
+ let data5 = initTernaryTreeList(origin5);
28
+ let updated = assocList(data5, 3, 10);
29
+ check(listGet(updated, 3) === 10);
30
+ check(listGet(data5, 3) === 4);
31
+ check(listLen(updated) === listLen(data5));
32
+ for (let idx = 0; idx < listLen(data5); idx++) {
33
+ check(listLen(dissocList(data5, idx)) === listLen(data5) - 1);
34
+ }
35
+ checkEqual(formatListInline(data5), "((1 2 _) 3 (4 5 _))");
36
+ checkEqual(formatListInline(dissocList(data5, 0)), "(2 3 (4 5 _))");
37
+ checkEqual(formatListInline(dissocList(data5, 1)), "(1 3 (4 5 _))");
38
+ checkEqual(formatListInline(dissocList(data5, 2)), "((1 2 _) (4 5 _) _)");
39
+ checkEqual(formatListInline(dissocList(data5, 3)), "((1 2 _) 3 5)");
40
+ checkEqual(formatListInline(dissocList(data5, 4)), "((1 2 _) 3 4)");
41
+ checkEqual(formatListInline(rest(initTernaryTreeList([1]))), "_");
42
+ checkEqual(formatListInline(rest(initTernaryTreeList([1, 2]))), "2");
43
+ checkEqual(formatListInline(rest(initTernaryTreeList([1, 2, 3]))), "(2 3 _)");
44
+ checkEqual(formatListInline(rest(initTernaryTreeList([1, 2, 3, 4]))), "((2 3 _) 4 _)");
45
+ checkEqual(formatListInline(rest(initTernaryTreeList([1, 2, 3, 4, 5]))), "(2 3 (4 5 _))");
46
+ checkEqual(formatListInline(butlast(initTernaryTreeList([1]))), "_");
47
+ checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2]))), "1");
48
+ checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2, 3]))), "(1 2 _)");
49
+ checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2, 3, 4]))), "(1 (2 3 _) _)");
50
+ checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2, 3, 4, 5]))), "((1 2 _) 3 4)");
51
+ });
52
+ test("should handle list insertions", () => {
53
+ let origin5 = [1, 2, 3, 4, 5];
54
+ let data5 = initTernaryTreeList(origin5);
55
+ checkEqual(formatListInline(data5), "((1 2 _) 3 (4 5 _))");
56
+ checkEqual(formatListInline(insert(data5, 0, 10, false)), "(10 ((1 2 _) 3 (4 5 _)) _)");
57
+ checkEqual(formatListInline(insert(data5, 0, 10, true)), "((1 10 2) 3 (4 5 _))");
58
+ checkEqual(formatListInline(insert(data5, 1, 10, false)), "((1 10 2) 3 (4 5 _))");
59
+ checkEqual(formatListInline(insert(data5, 1, 10, true)), "((1 2 10) 3 (4 5 _))");
60
+ checkEqual(formatListInline(insert(data5, 2, 10, false)), "((1 2 _) (10 3 _) (4 5 _))");
61
+ checkEqual(formatListInline(insert(data5, 2, 10, true)), "((1 2 _) (3 10 _) (4 5 _))");
62
+ checkEqual(formatListInline(insert(data5, 3, 10, false)), "((1 2 _) 3 (10 4 5))");
63
+ checkEqual(formatListInline(insert(data5, 3, 10, true)), "((1 2 _) 3 (4 10 5))");
64
+ checkEqual(formatListInline(insert(data5, 4, 10, false)), "((1 2 _) 3 (4 10 5))");
65
+ checkEqual(formatListInline(insert(data5, 4, 10, true)), "(((1 2 _) 3 (4 5 _)) 10 _)");
66
+ let origin4 = [1, 2, 3, 4];
67
+ let data4 = initTernaryTreeList(origin4);
68
+ checkEqual(formatListInline(assocBefore(data4, 3, 10)), "(1 (2 3 _) (10 4 _))");
69
+ checkEqual(formatListInline(assocAfter(data4, 3, 10)), "(1 (2 3 _) (4 10 _))");
70
+ checkEqual(formatListInline(prepend(data4, 10)), "((10 1 _) (2 3 _) 4)");
71
+ checkEqual(formatListInline(append(data4, 10)), "(1 (2 3 _) (4 10 _))");
72
+ });
73
+ test("should handle list concatenation", () => {
74
+ let data1 = initTernaryTreeList([1, 2]);
75
+ let data2 = initTernaryTreeList([3, 4]);
76
+ let data3 = initTernaryTreeList([5, 6]);
77
+ let data4 = initTernaryTreeList([7, 8]);
78
+ check(formatListInline(concat(data1, data2)) === "(1 2 (3 4 _))");
79
+ check(formatListInline(concat(initTernaryTreeList([]), data1)) === "(1 2 _)");
80
+ check(formatListInline(concat(data1, data2, data3)) === "((1 2 _) (3 4 _) (5 6 _))");
81
+ check(formatListInline(concat(data1, data2, data3, data4)) === "((1 2 _) ((3 4 _) (5 6 _) _) (7 8 _))");
82
+ check(checkListStructure(concat(data1, data2)));
83
+ check(checkListStructure(concat(data1, data2, data3)));
84
+ check(checkListStructure(concat(data1, data2, data3, data4)));
85
+ check(listLen(concat(data1, data2, data3, data4)) === 8);
86
+ });
87
+ test("should check equality correctly", () => {
88
+ let origin4 = [1, 2, 3, 4];
89
+ let data4 = initTernaryTreeList(origin4);
90
+ let data4n = initTernaryTreeList(origin4);
91
+ let data4Made = prepend(initTernaryTreeList([2, 3, 4]), 1);
92
+ check(checkListStructure(data4));
93
+ check(checkListStructure(data4n));
94
+ check(checkListStructure(data4Made));
95
+ check(sameListShape(data4, data4) === true);
96
+ check(sameListShape(data4, data4n) === true);
97
+ check(sameListShape(data4, data4Made) === false);
98
+ check(listEqual(data4, data4n));
99
+ check(listEqual(data4, data4Made));
100
+ check(listEqual(data4n, data4Made));
101
+ check(data4 !== data4Made); // identical false
102
+ });
103
+ test("should force balancing correctly", () => {
104
+ var data = initTernaryTreeList([]);
105
+ for (let idx = 0; idx < 20; idx++) {
106
+ data = append(data, idx, true);
107
+ check(checkListStructure(data));
108
+ }
109
+ check(formatListInline(data) === "(((0 1 2) (3 4 5) (6 7 8)) ((9 10 11) (12 13 14) (15 16 17)) (18 19 _))");
110
+ forceListInplaceBalancing(data);
111
+ check(formatListInline(data) === "(((0 1 _) (2 3 4) (5 6 _)) ((7 8 _) (9 10 _) (11 12 _)) ((13 14 _) (15 16 17) (18 19 _)))");
112
+ });
113
+ test("should handle iteration correctly", () => {
114
+ let origin4 = [1, 2, 3, 4];
115
+ let data4 = initTernaryTreeList(origin4);
116
+ check(checkListStructure(data4));
117
+ var count = 0;
118
+ for (let item of listToItems(data4)) {
119
+ count = count + 1;
120
+ }
121
+ check(count === 4);
122
+ var indexSum = 0;
123
+ for (let [idx, item] of listToPairs(data4)) {
124
+ indexSum = indexSum + idx;
125
+ }
126
+ check(indexSum === 6);
127
+ });
128
+ test("should maintain structure integrity", () => {
129
+ var data = initTernaryTreeList([]);
130
+ for (let idx = 0; idx < 20; idx++) {
131
+ data = append(data, idx, true);
132
+ check(checkListStructure(data));
133
+ }
134
+ check(checkListStructure(data));
135
+ for (let idx = 0; idx < 20; idx++) {
136
+ data = rest(data);
137
+ check(checkListStructure(data));
138
+ }
139
+ let origin11 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
140
+ let data11 = initTernaryTreeList(origin11);
141
+ check(checkListStructure(data11));
142
+ check(checkListStructure(prepend(initEmptyTernaryTreeList(), 1)));
143
+ check(checkListStructure(prepend(null, 1)));
144
+ });
145
+ test("should handle slicing correctly", () => {
146
+ var data = initTernaryTreeList([]);
147
+ for (let idx = 0; idx < 40; idx++) {
148
+ data = append(data, idx, true);
149
+ }
150
+ var list40 = [];
151
+ for (let idx = 0; idx < 40; idx++) {
152
+ list40.push(idx);
153
+ }
154
+ for (let i = 0; i < 40; i++) {
155
+ for (let j = i; j < 40; j++) {
156
+ checkArrayEqual([...listToItems(slice(data, i, j))], list40.slice(i, j));
157
+ check(checkListStructure(slice(data, i, j)));
158
+ }
159
+ }
160
+ });
161
+ test("should reverse lists correctly", () => {
162
+ let data = initTernaryTreeList([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
163
+ let reversedData = reverse(data);
164
+ checkArrayEqual([...listToItems(reversedData)], [...listToItems(data)].reverse());
165
+ check(checkListStructure(reversedData));
166
+ });
167
+ test("should traverse lists correctly", () => {
168
+ var count = 0;
169
+ let data = initTernaryTreeList([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
170
+ check(checkListStructure(data));
171
+ for (let x of listToItems(data)) {
172
+ count = count + 1;
173
+ }
174
+ check(count === 10);
175
+ });
176
+ test("should find index correctly", () => {
177
+ let data = initTernaryTreeList([1, 2, 3, 4, 5, 6, 7, 8]);
178
+ check(indexOf(data, 2) === 1);
179
+ check(findIndex(data, (x) => x === 2) === 1);
180
+ check(indexOf(data, 9) === -1);
181
+ check(findIndex(data, (x) => x === 9) === -1);
182
+ });
183
+ test("should map values correctly", () => {
184
+ let data = initTernaryTreeList([1, 2, 3, 4]);
185
+ let data2 = initTernaryTreeList([1, 4, 9, 16]);
186
+ let data3 = listMapValues(data, (x) => x * x);
187
+ check(checkListStructure(data3));
188
+ check(listEqual(data2, data3));
189
+ check(formatListInline(data2) === formatListInline(data3));
190
+ });
191
+ test("should handle range initialization", () => {
192
+ let data1 = initTernaryTreeList([3, 4]);
193
+ let data2 = initTernaryTreeListFromRange([1, 2, 3, 4, 5, 6], 2, 4);
194
+ check(listEqual(data1, data2));
195
+ check(checkListStructure(data1));
196
+ check(checkListStructure(data2));
197
+ });
198
+ test("should handle concat loop stress test", () => {
199
+ let data1 = initTernaryTreeList([3, 4]);
200
+ let data2 = initTernaryTreeList([5]);
201
+ for (let i = 0; i < 100; i++) {
202
+ data1 = concat2(data1, data2);
203
+ }
204
+ console.log("concat into depth", formatListInline(data1));
205
+ });
207
206
  });
208
207
  };
@@ -0,0 +1 @@
1
+ export declare function runPerformanceTests(): void;
@@ -0,0 +1,70 @@
1
+ import { initTernaryTreeMap, initTernaryTreeMapFromArray, assocMap, contains, mapGetDefault, dissocMap, toPairsArray, initEmptyTernaryTreeMap, } from "./map.mjs";
2
+ function createTestData(size) {
3
+ const data = [];
4
+ for (let i = 0; i < size; i++) {
5
+ data.push([i, `value_${i}`]);
6
+ }
7
+ return data;
8
+ }
9
+ function measureTime(name, fn) {
10
+ const start = performance.now();
11
+ const result = fn();
12
+ const end = performance.now();
13
+ console.log(`${name}: ${(end - start).toFixed(2)}ms`);
14
+ return result;
15
+ }
16
+ export function runPerformanceTests() {
17
+ console.log("\n=== Performance Tests ===");
18
+ const sizes = [100, 1000, 5000, 10000];
19
+ for (const size of sizes) {
20
+ console.log(`\n--- Testing with ${size} elements ---`);
21
+ const testData = createTestData(size);
22
+ const mapData = new Map(testData);
23
+ // Test initTernaryTreeMapFromArray
24
+ const treeFromArray = measureTime(`initTernaryTreeMapFromArray(${size})`, () => {
25
+ return initTernaryTreeMapFromArray(testData);
26
+ });
27
+ // Test initTernaryTreeMap
28
+ const treeFromMap = measureTime(`initTernaryTreeMap(${size})`, () => {
29
+ return initTernaryTreeMap(mapData);
30
+ });
31
+ // Test sequential assoc operations
32
+ measureTime(`Sequential assoc(${size})`, () => {
33
+ let tree = initEmptyTernaryTreeMap();
34
+ for (const [k, v] of testData) {
35
+ tree = assocMap(tree, k, v);
36
+ }
37
+ return tree;
38
+ });
39
+ // Test lookups
40
+ const lookupKeys = testData.slice(0, Math.min(100, size)).map(([k]) => k);
41
+ measureTime(`Lookups(${lookupKeys.length})`, () => {
42
+ for (const key of lookupKeys) {
43
+ contains(treeFromArray, key);
44
+ mapGetDefault(treeFromArray, key, "default");
45
+ }
46
+ });
47
+ // Test dissoc operations
48
+ const dissocKeys = testData.slice(0, Math.min(50, size)).map(([k]) => k);
49
+ measureTime(`Dissoc(${dissocKeys.length})`, () => {
50
+ let tree = treeFromArray;
51
+ for (const key of dissocKeys) {
52
+ tree = dissocMap(tree, key);
53
+ }
54
+ return tree;
55
+ });
56
+ // Test toPairsArray
57
+ measureTime(`toPairsArray(${size})`, () => {
58
+ return toPairsArray(treeFromArray);
59
+ });
60
+ }
61
+ console.log("\n=== Memory usage test ===");
62
+ const largeData = createTestData(50000);
63
+ console.log(`Testing with ${largeData.length} elements for memory efficiency`);
64
+ measureTime("Large dataset creation", () => {
65
+ return initTernaryTreeMapFromArray(largeData);
66
+ });
67
+ }
68
+ if (import.meta.url === `file://${process.argv[1]}`) {
69
+ runPerformanceTests();
70
+ }