@obinexusmk2/hypernum 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +355 -256
- package/dist/index.cjs +4 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -7
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +2 -2
- package/dist/index.umd.js.map +1 -1
- package/dist/types/{config → src/config}/config-loader.d.ts +0 -0
- package/dist/types/src/config/config-loader.d.ts.map +1 -0
- package/dist/types/{config → src/config}/config-parser.d.ts +0 -0
- package/dist/types/src/config/config-parser.d.ts.map +1 -0
- package/dist/types/{config → src/config}/config-resolver.d.ts +0 -0
- package/dist/types/src/config/config-resolver.d.ts.map +1 -0
- package/dist/types/{config → src/config}/config-source.d.ts +0 -0
- package/dist/types/src/config/config-source.d.ts.map +1 -0
- package/dist/types/{config → src/config}/index.d.ts +0 -0
- package/dist/types/src/config/index.d.ts.map +1 -0
- package/dist/types/{core → src/core}/common.d.ts +0 -0
- package/dist/types/src/core/common.d.ts.map +1 -0
- package/dist/types/{core → src/core}/config.d.ts +0 -0
- package/dist/types/src/core/config.d.ts.map +1 -0
- package/dist/types/{core → src/core}/constants.d.ts +0 -0
- package/dist/types/src/core/constants.d.ts.map +1 -0
- package/dist/types/{core → src/core}/errors.d.ts +0 -0
- package/dist/types/src/core/errors.d.ts.map +1 -0
- package/dist/types/{core → src/core}/hypernum.d.ts +0 -0
- package/dist/types/src/core/hypernum.d.ts.map +1 -0
- package/dist/types/{core → src/core}/index.d.ts +0 -0
- package/dist/types/src/core/index.d.ts.map +1 -0
- package/dist/types/{index.d.ts → src/index.d.ts} +1 -1
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/arithmetic.d.ts +0 -0
- package/dist/types/src/operations/arithmetic.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/bitwise.d.ts +0 -0
- package/dist/types/src/operations/bitwise.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/comparison.d.ts +0 -0
- package/dist/types/src/operations/comparison.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/conversion.d.ts +0 -0
- package/dist/types/src/operations/conversion.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/factorial.d.ts +0 -0
- package/dist/types/src/operations/factorial.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/index.d.ts +0 -0
- package/dist/types/src/operations/index.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/power.d.ts +0 -0
- package/dist/types/src/operations/power.d.ts.map +1 -0
- package/dist/types/{storage → src/storage}/Heap.d.ts +0 -0
- package/dist/types/src/storage/Heap.d.ts.map +1 -0
- package/dist/types/{storage → src/storage}/index.d.ts +0 -0
- package/dist/types/src/storage/index.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/ackermann.d.ts +0 -0
- package/dist/types/src/structures/ackermann.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/big-array.d.ts +0 -0
- package/dist/types/src/structures/big-array.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/index.d.ts +0 -0
- package/dist/types/src/structures/index.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/number-tree.d.ts +0 -0
- package/dist/types/src/structures/number-tree.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/power-tower.d.ts +0 -0
- package/dist/types/src/structures/power-tower.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/formatting.d.ts +0 -0
- package/dist/types/src/utils/formatting.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/index.d.ts +0 -0
- package/dist/types/src/utils/index.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/parser.d.ts +0 -0
- package/dist/types/src/utils/parser.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/precision.d.ts +0 -0
- package/dist/types/src/utils/precision.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/validation.d.ts +0 -0
- package/dist/types/src/utils/validation.d.ts.map +1 -0
- package/package.json +169 -164
- package/rollup.config.js +163 -161
- package/src/cli/hypernum.js +272 -0
- package/src/config/config-loader.ts +0 -0
- package/src/config/config-parser.ts +160 -160
- package/src/config/config-resolver.ts +0 -0
- package/src/config/config-source.ts +0 -0
- package/src/config/index.ts +0 -0
- package/src/core/common.ts +184 -184
- package/src/core/config.ts +392 -392
- package/src/core/constants.ts +101 -101
- package/src/core/errors.ts +202 -202
- package/src/core/hypernum.ts +240 -240
- package/src/core/index.ts +4 -4
- package/src/index.ts +179 -182
- package/src/operations/arithmetic.ts +332 -332
- package/src/operations/bitwise.ts +366 -366
- package/src/operations/comparison.ts +271 -271
- package/src/operations/conversion.ts +399 -399
- package/src/operations/factorial.ts +278 -278
- package/src/operations/index.ts +4 -4
- package/src/operations/power.ts +315 -315
- package/src/storage/Heap.ts +237 -237
- package/src/storage/index.ts +0 -0
- package/src/structures/ackermann.ts +232 -232
- package/src/structures/big-array.ts +305 -305
- package/src/structures/index.ts +3 -3
- package/src/structures/number-tree.ts +403 -403
- package/src/structures/power-tower.ts +277 -277
- package/src/types/common.d.ts +356 -356
- package/src/types/core.d.ts +160 -160
- package/src/types/index.d.ts +1 -1
- package/src/utils/formatting.ts +245 -245
- package/src/utils/index.ts +4 -4
- package/src/utils/parser.ts +244 -244
- package/src/utils/precision.ts +216 -216
- package/src/utils/validation.ts +182 -182
- package/tsconfig.json +83 -83
- package/dist/types/config/config-loader.d.ts.map +0 -1
- package/dist/types/config/config-parser.d.ts.map +0 -1
- package/dist/types/config/config-resolver.d.ts.map +0 -1
- package/dist/types/config/config-source.d.ts.map +0 -1
- package/dist/types/config/index.d.ts.map +0 -1
- package/dist/types/core/common.d.ts.map +0 -1
- package/dist/types/core/config.d.ts.map +0 -1
- package/dist/types/core/constants.d.ts.map +0 -1
- package/dist/types/core/errors.d.ts.map +0 -1
- package/dist/types/core/hypernum.d.ts.map +0 -1
- package/dist/types/core/index.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/operations/arithmetic.d.ts.map +0 -1
- package/dist/types/operations/bitwise.d.ts.map +0 -1
- package/dist/types/operations/comparison.d.ts.map +0 -1
- package/dist/types/operations/conversion.d.ts.map +0 -1
- package/dist/types/operations/factorial.d.ts.map +0 -1
- package/dist/types/operations/index.d.ts.map +0 -1
- package/dist/types/operations/power.d.ts.map +0 -1
- package/dist/types/storage/Heap.d.ts.map +0 -1
- package/dist/types/storage/index.d.ts.map +0 -1
- package/dist/types/structures/ackermann.d.ts.map +0 -1
- package/dist/types/structures/big-array.d.ts.map +0 -1
- package/dist/types/structures/index.d.ts.map +0 -1
- package/dist/types/structures/number-tree.d.ts.map +0 -1
- package/dist/types/structures/power-tower.d.ts.map +0 -1
- package/dist/types/utils/formatting.d.ts.map +0 -1
- package/dist/types/utils/index.d.ts.map +0 -1
- package/dist/types/utils/parser.d.ts.map +0 -1
- package/dist/types/utils/precision.d.ts.map +0 -1
- package/dist/types/utils/validation.d.ts.map +0 -1
|
@@ -1,233 +1,233 @@
|
|
|
1
|
-
import { Comparator } from "..";
|
|
2
|
-
import { MaxHeap, createLargeNumberComparator } from "../storage/Heap";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Interface representing an Ackermann node in the computation structure
|
|
6
|
-
*/
|
|
7
|
-
interface IAckermannNode {
|
|
8
|
-
m: number;
|
|
9
|
-
n: number;
|
|
10
|
-
value: bigint;
|
|
11
|
-
prevM?: IAckermannNode; // Link to A(m-1, n)
|
|
12
|
-
prevN?: IAckermannNode; // Link to A(m, n-1)
|
|
13
|
-
nextM?: IAckermannNode; // Link to A(m+1, n)
|
|
14
|
-
nextN?: IAckermannNode; // Link to A(m, n+1)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Type for Ackermann computation path step
|
|
19
|
-
*/
|
|
20
|
-
type ComputationStep = {
|
|
21
|
-
m: number;
|
|
22
|
-
n: number;
|
|
23
|
-
value: bigint;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Type for growth rate analysis
|
|
28
|
-
*/
|
|
29
|
-
type GrowthAnalysis = {
|
|
30
|
-
value: bigint;
|
|
31
|
-
increase: bigint;
|
|
32
|
-
multiplier: bigint;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Class representing the Ackermann function computation structure
|
|
37
|
-
* Implements caching and relationship tracking between values
|
|
38
|
-
*/
|
|
39
|
-
export class AckermannStructure {
|
|
40
|
-
private nodes: Map<string, IAckermannNode>;
|
|
41
|
-
private maxComputedM: number;
|
|
42
|
-
private maxComputedN: number;
|
|
43
|
-
private heap: MaxHeap<bigint>;
|
|
44
|
-
|
|
45
|
-
constructor() {
|
|
46
|
-
this.nodes = new Map();
|
|
47
|
-
this.maxComputedM = -1;
|
|
48
|
-
this.maxComputedN = -1;
|
|
49
|
-
this.heap = new MaxHeap<bigint>(createLargeNumberComparator() as Comparator<bigint>);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Generates a unique key for node storage
|
|
54
|
-
*/
|
|
55
|
-
private static getNodeKey(m: number, n: number): string {
|
|
56
|
-
return `${m},${n}`;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Computes the Ackermann function value
|
|
61
|
-
* Uses recursion with memoization
|
|
62
|
-
*/
|
|
63
|
-
private computeAckermann(m: number, n: number): bigint {
|
|
64
|
-
// Handle invalid inputs
|
|
65
|
-
if (m < 0 || n < 0) {
|
|
66
|
-
throw new Error('Ackermann function undefined for negative numbers');
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Check if already computed
|
|
70
|
-
const key = AckermannStructure.getNodeKey(m, n);
|
|
71
|
-
const existing = this.nodes.get(key);
|
|
72
|
-
if (existing) {
|
|
73
|
-
return existing.value;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Compute based on Ackermann function definition
|
|
77
|
-
let value: bigint;
|
|
78
|
-
try {
|
|
79
|
-
if (m === 0) {
|
|
80
|
-
value = BigInt(n + 1);
|
|
81
|
-
} else if (n === 0) {
|
|
82
|
-
value = this.computeAckermann(m - 1, 1);
|
|
83
|
-
} else {
|
|
84
|
-
const inner = this.computeAckermann(m, n - 1);
|
|
85
|
-
// Convert bigint to number for recursion, being careful about size
|
|
86
|
-
const innerNum = inner <= BigInt(Number.MAX_SAFE_INTEGER)
|
|
87
|
-
? Number(inner)
|
|
88
|
-
: Number.MAX_SAFE_INTEGER;
|
|
89
|
-
value = this.computeAckermann(m - 1, innerNum);
|
|
90
|
-
}
|
|
91
|
-
} catch (error) {
|
|
92
|
-
// Handle stack overflow or computation limits
|
|
93
|
-
if (error instanceof RangeError) {
|
|
94
|
-
return BigInt(Number.MAX_SAFE_INTEGER);
|
|
95
|
-
}
|
|
96
|
-
throw error;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return value;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Adds a new node to the structure
|
|
104
|
-
*/
|
|
105
|
-
public addNode(m: number, n: number): IAckermannNode {
|
|
106
|
-
const key = AckermannStructure.getNodeKey(m, n);
|
|
107
|
-
if (this.nodes.has(key)) {
|
|
108
|
-
return this.nodes.get(key)!;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Create new node
|
|
112
|
-
const value = this.computeAckermann(m, n);
|
|
113
|
-
const node: IAckermannNode = { m, n, value };
|
|
114
|
-
this.nodes.set(key, node);
|
|
115
|
-
|
|
116
|
-
// Link to existing nodes
|
|
117
|
-
const prevMKey = AckermannStructure.getNodeKey(m - 1, n);
|
|
118
|
-
const prevNKey = AckermannStructure.getNodeKey(m, n - 1);
|
|
119
|
-
|
|
120
|
-
if (this.nodes.has(prevMKey)) {
|
|
121
|
-
const prevM = this.nodes.get(prevMKey)!;
|
|
122
|
-
node.prevM = prevM;
|
|
123
|
-
prevM.nextM = node;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (this.nodes.has(prevNKey)) {
|
|
127
|
-
const prevN = this.nodes.get(prevNKey)!;
|
|
128
|
-
node.prevN = prevN;
|
|
129
|
-
prevN.nextN = node;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Update tracking
|
|
133
|
-
this.maxComputedM = Math.max(this.maxComputedM, m);
|
|
134
|
-
this.maxComputedN = Math.max(this.maxComputedN, n);
|
|
135
|
-
this.heap.push(value);
|
|
136
|
-
|
|
137
|
-
return node;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Builds nodes for a range of m and n values
|
|
142
|
-
*/
|
|
143
|
-
public buildRange(mRange: number, nRange: number): void {
|
|
144
|
-
for (let m = 0; m <= mRange; m++) {
|
|
145
|
-
for (let n = 0; n <= nRange; n++) {
|
|
146
|
-
this.addNode(m, n);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Gets the computation path to reach A(m,n)
|
|
153
|
-
*/
|
|
154
|
-
public getComputationPath(m: number, n: number): ComputationStep[] {
|
|
155
|
-
const path: ComputationStep[] = [];
|
|
156
|
-
const key = AckermannStructure.getNodeKey(m, n);
|
|
157
|
-
let current = this.nodes.get(key);
|
|
158
|
-
|
|
159
|
-
while (current) {
|
|
160
|
-
path.push({
|
|
161
|
-
m: current.m,
|
|
162
|
-
n: current.n,
|
|
163
|
-
value: current.value
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// Follow computation path backwards
|
|
167
|
-
if (current.m === 0) {
|
|
168
|
-
break;
|
|
169
|
-
} else if (current.n === 0) {
|
|
170
|
-
current = this.nodes.get(AckermannStructure.getNodeKey(current.m - 1, 1));
|
|
171
|
-
} else {
|
|
172
|
-
const prevN = this.nodes.get(AckermannStructure.getNodeKey(current.m, current.n - 1));
|
|
173
|
-
if (prevN) {
|
|
174
|
-
path.push({
|
|
175
|
-
m: prevN.m,
|
|
176
|
-
n: prevN.n,
|
|
177
|
-
value: prevN.value
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
// Convert bigint to number safely for the next lookup
|
|
181
|
-
const nextValue = prevN?.value ?? BigInt(0);
|
|
182
|
-
const safeNextValue = nextValue <= BigInt(Number.MAX_SAFE_INTEGER)
|
|
183
|
-
? Number(nextValue)
|
|
184
|
-
: Number.MAX_SAFE_INTEGER;
|
|
185
|
-
current = this.nodes.get(AckermannStructure.getNodeKey(current.m - 1, safeNextValue));
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return path.reverse();
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Analyzes growth rate for a fixed m value
|
|
194
|
-
*/
|
|
195
|
-
public analyzeGrowthRate(m: number): Map<number, GrowthAnalysis> {
|
|
196
|
-
const growth = new Map<number, GrowthAnalysis>();
|
|
197
|
-
let prevValue = BigInt(1);
|
|
198
|
-
|
|
199
|
-
for (let n = 0; n <= this.maxComputedN; n++) {
|
|
200
|
-
const key = AckermannStructure.getNodeKey(m, n);
|
|
201
|
-
const node = this.nodes.get(key);
|
|
202
|
-
if (!node || node.value >= BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
growth.set(n, {
|
|
207
|
-
value: node.value,
|
|
208
|
-
increase: node.value - prevValue,
|
|
209
|
-
multiplier: prevValue === BigInt(0) ? BigInt(0) : node.value / prevValue
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
prevValue = node.value;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return growth;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Gets the largest computed value
|
|
220
|
-
*/
|
|
221
|
-
public getLargestValue(): bigint {
|
|
222
|
-
return this.heap.peek() ?? BigInt(0);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Gets a specific Ackermann value if it exists
|
|
227
|
-
*/
|
|
228
|
-
public getValue(m: number, n: number): bigint | undefined {
|
|
229
|
-
return this.nodes.get(AckermannStructure.getNodeKey(m, n))?.value;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
1
|
+
import { Comparator } from "..";
|
|
2
|
+
import { MaxHeap, createLargeNumberComparator } from "../storage/Heap";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Interface representing an Ackermann node in the computation structure
|
|
6
|
+
*/
|
|
7
|
+
interface IAckermannNode {
|
|
8
|
+
m: number;
|
|
9
|
+
n: number;
|
|
10
|
+
value: bigint;
|
|
11
|
+
prevM?: IAckermannNode; // Link to A(m-1, n)
|
|
12
|
+
prevN?: IAckermannNode; // Link to A(m, n-1)
|
|
13
|
+
nextM?: IAckermannNode; // Link to A(m+1, n)
|
|
14
|
+
nextN?: IAckermannNode; // Link to A(m, n+1)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Type for Ackermann computation path step
|
|
19
|
+
*/
|
|
20
|
+
type ComputationStep = {
|
|
21
|
+
m: number;
|
|
22
|
+
n: number;
|
|
23
|
+
value: bigint;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Type for growth rate analysis
|
|
28
|
+
*/
|
|
29
|
+
type GrowthAnalysis = {
|
|
30
|
+
value: bigint;
|
|
31
|
+
increase: bigint;
|
|
32
|
+
multiplier: bigint;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Class representing the Ackermann function computation structure
|
|
37
|
+
* Implements caching and relationship tracking between values
|
|
38
|
+
*/
|
|
39
|
+
export class AckermannStructure {
|
|
40
|
+
private nodes: Map<string, IAckermannNode>;
|
|
41
|
+
private maxComputedM: number;
|
|
42
|
+
private maxComputedN: number;
|
|
43
|
+
private heap: MaxHeap<bigint>;
|
|
44
|
+
|
|
45
|
+
constructor() {
|
|
46
|
+
this.nodes = new Map();
|
|
47
|
+
this.maxComputedM = -1;
|
|
48
|
+
this.maxComputedN = -1;
|
|
49
|
+
this.heap = new MaxHeap<bigint>(createLargeNumberComparator() as Comparator<bigint>);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Generates a unique key for node storage
|
|
54
|
+
*/
|
|
55
|
+
private static getNodeKey(m: number, n: number): string {
|
|
56
|
+
return `${m},${n}`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Computes the Ackermann function value
|
|
61
|
+
* Uses recursion with memoization
|
|
62
|
+
*/
|
|
63
|
+
private computeAckermann(m: number, n: number): bigint {
|
|
64
|
+
// Handle invalid inputs
|
|
65
|
+
if (m < 0 || n < 0) {
|
|
66
|
+
throw new Error('Ackermann function undefined for negative numbers');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Check if already computed
|
|
70
|
+
const key = AckermannStructure.getNodeKey(m, n);
|
|
71
|
+
const existing = this.nodes.get(key);
|
|
72
|
+
if (existing) {
|
|
73
|
+
return existing.value;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Compute based on Ackermann function definition
|
|
77
|
+
let value: bigint;
|
|
78
|
+
try {
|
|
79
|
+
if (m === 0) {
|
|
80
|
+
value = BigInt(n + 1);
|
|
81
|
+
} else if (n === 0) {
|
|
82
|
+
value = this.computeAckermann(m - 1, 1);
|
|
83
|
+
} else {
|
|
84
|
+
const inner = this.computeAckermann(m, n - 1);
|
|
85
|
+
// Convert bigint to number for recursion, being careful about size
|
|
86
|
+
const innerNum = inner <= BigInt(Number.MAX_SAFE_INTEGER)
|
|
87
|
+
? Number(inner)
|
|
88
|
+
: Number.MAX_SAFE_INTEGER;
|
|
89
|
+
value = this.computeAckermann(m - 1, innerNum);
|
|
90
|
+
}
|
|
91
|
+
} catch (error) {
|
|
92
|
+
// Handle stack overflow or computation limits
|
|
93
|
+
if (error instanceof RangeError) {
|
|
94
|
+
return BigInt(Number.MAX_SAFE_INTEGER);
|
|
95
|
+
}
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Adds a new node to the structure
|
|
104
|
+
*/
|
|
105
|
+
public addNode(m: number, n: number): IAckermannNode {
|
|
106
|
+
const key = AckermannStructure.getNodeKey(m, n);
|
|
107
|
+
if (this.nodes.has(key)) {
|
|
108
|
+
return this.nodes.get(key)!;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Create new node
|
|
112
|
+
const value = this.computeAckermann(m, n);
|
|
113
|
+
const node: IAckermannNode = { m, n, value };
|
|
114
|
+
this.nodes.set(key, node);
|
|
115
|
+
|
|
116
|
+
// Link to existing nodes
|
|
117
|
+
const prevMKey = AckermannStructure.getNodeKey(m - 1, n);
|
|
118
|
+
const prevNKey = AckermannStructure.getNodeKey(m, n - 1);
|
|
119
|
+
|
|
120
|
+
if (this.nodes.has(prevMKey)) {
|
|
121
|
+
const prevM = this.nodes.get(prevMKey)!;
|
|
122
|
+
node.prevM = prevM;
|
|
123
|
+
prevM.nextM = node;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (this.nodes.has(prevNKey)) {
|
|
127
|
+
const prevN = this.nodes.get(prevNKey)!;
|
|
128
|
+
node.prevN = prevN;
|
|
129
|
+
prevN.nextN = node;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Update tracking
|
|
133
|
+
this.maxComputedM = Math.max(this.maxComputedM, m);
|
|
134
|
+
this.maxComputedN = Math.max(this.maxComputedN, n);
|
|
135
|
+
this.heap.push(value);
|
|
136
|
+
|
|
137
|
+
return node;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Builds nodes for a range of m and n values
|
|
142
|
+
*/
|
|
143
|
+
public buildRange(mRange: number, nRange: number): void {
|
|
144
|
+
for (let m = 0; m <= mRange; m++) {
|
|
145
|
+
for (let n = 0; n <= nRange; n++) {
|
|
146
|
+
this.addNode(m, n);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Gets the computation path to reach A(m,n)
|
|
153
|
+
*/
|
|
154
|
+
public getComputationPath(m: number, n: number): ComputationStep[] {
|
|
155
|
+
const path: ComputationStep[] = [];
|
|
156
|
+
const key = AckermannStructure.getNodeKey(m, n);
|
|
157
|
+
let current = this.nodes.get(key);
|
|
158
|
+
|
|
159
|
+
while (current) {
|
|
160
|
+
path.push({
|
|
161
|
+
m: current.m,
|
|
162
|
+
n: current.n,
|
|
163
|
+
value: current.value
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Follow computation path backwards
|
|
167
|
+
if (current.m === 0) {
|
|
168
|
+
break;
|
|
169
|
+
} else if (current.n === 0) {
|
|
170
|
+
current = this.nodes.get(AckermannStructure.getNodeKey(current.m - 1, 1));
|
|
171
|
+
} else {
|
|
172
|
+
const prevN = this.nodes.get(AckermannStructure.getNodeKey(current.m, current.n - 1));
|
|
173
|
+
if (prevN) {
|
|
174
|
+
path.push({
|
|
175
|
+
m: prevN.m,
|
|
176
|
+
n: prevN.n,
|
|
177
|
+
value: prevN.value
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
// Convert bigint to number safely for the next lookup
|
|
181
|
+
const nextValue = prevN?.value ?? BigInt(0);
|
|
182
|
+
const safeNextValue = nextValue <= BigInt(Number.MAX_SAFE_INTEGER)
|
|
183
|
+
? Number(nextValue)
|
|
184
|
+
: Number.MAX_SAFE_INTEGER;
|
|
185
|
+
current = this.nodes.get(AckermannStructure.getNodeKey(current.m - 1, safeNextValue));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return path.reverse();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Analyzes growth rate for a fixed m value
|
|
194
|
+
*/
|
|
195
|
+
public analyzeGrowthRate(m: number): Map<number, GrowthAnalysis> {
|
|
196
|
+
const growth = new Map<number, GrowthAnalysis>();
|
|
197
|
+
let prevValue = BigInt(1);
|
|
198
|
+
|
|
199
|
+
for (let n = 0; n <= this.maxComputedN; n++) {
|
|
200
|
+
const key = AckermannStructure.getNodeKey(m, n);
|
|
201
|
+
const node = this.nodes.get(key);
|
|
202
|
+
if (!node || node.value >= BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
growth.set(n, {
|
|
207
|
+
value: node.value,
|
|
208
|
+
increase: node.value - prevValue,
|
|
209
|
+
multiplier: prevValue === BigInt(0) ? BigInt(0) : node.value / prevValue
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
prevValue = node.value;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return growth;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Gets the largest computed value
|
|
220
|
+
*/
|
|
221
|
+
public getLargestValue(): bigint {
|
|
222
|
+
return this.heap.peek() ?? BigInt(0);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Gets a specific Ackermann value if it exists
|
|
227
|
+
*/
|
|
228
|
+
public getValue(m: number, n: number): bigint | undefined {
|
|
229
|
+
return this.nodes.get(AckermannStructure.getNodeKey(m, n))?.value;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
233
|
export default AckermannStructure;
|