@obinexusmk2/hypernum 0.1.0
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 -0
- package/README.md +256 -0
- package/dist/index.cjs +3425 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +1449 -0
- package/dist/index.js +3284 -0
- package/dist/index.js.map +1 -0
- package/dist/index.umd.js +8 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/types/config/config-loader.d.ts +56 -0
- package/dist/types/config/config-loader.d.ts.map +1 -0
- package/dist/types/config/config-parser.d.ts +28 -0
- package/dist/types/config/config-parser.d.ts.map +1 -0
- package/dist/types/config/config-resolver.d.ts +21 -0
- package/dist/types/config/config-resolver.d.ts.map +1 -0
- package/dist/types/config/config-source.d.ts +27 -0
- package/dist/types/config/config-source.d.ts.map +1 -0
- package/dist/types/config/index.d.ts +68 -0
- package/dist/types/config/index.d.ts.map +1 -0
- package/dist/types/core/common.d.ts +169 -0
- package/dist/types/core/common.d.ts.map +1 -0
- package/dist/types/core/config.d.ts +197 -0
- package/dist/types/core/config.d.ts.map +1 -0
- package/dist/types/core/constants.d.ts +88 -0
- package/dist/types/core/constants.d.ts.map +1 -0
- package/dist/types/core/errors.d.ts +97 -0
- package/dist/types/core/errors.d.ts.map +1 -0
- package/dist/types/core/hypernum.d.ts +60 -0
- package/dist/types/core/hypernum.d.ts.map +1 -0
- package/dist/types/core/index.d.ts +6 -0
- package/dist/types/core/index.d.ts.map +1 -0
- package/dist/types/index.d.ts +33 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/operations/arithmetic.d.ts +72 -0
- package/dist/types/operations/arithmetic.d.ts.map +1 -0
- package/dist/types/operations/bitwise.d.ts +98 -0
- package/dist/types/operations/bitwise.d.ts.map +1 -0
- package/dist/types/operations/comparison.d.ts +94 -0
- package/dist/types/operations/comparison.d.ts.map +1 -0
- package/dist/types/operations/conversion.d.ts +79 -0
- package/dist/types/operations/conversion.d.ts.map +1 -0
- package/dist/types/operations/factorial.d.ts +58 -0
- package/dist/types/operations/factorial.d.ts.map +1 -0
- package/dist/types/operations/index.d.ts +6 -0
- package/dist/types/operations/index.d.ts.map +1 -0
- package/dist/types/operations/power.d.ts +49 -0
- package/dist/types/operations/power.d.ts.map +1 -0
- package/dist/types/storage/Heap.d.ts +95 -0
- package/dist/types/storage/Heap.d.ts.map +1 -0
- package/dist/types/storage/index.d.ts +2 -0
- package/dist/types/storage/index.d.ts.map +1 -0
- package/dist/types/structures/ackermann.d.ts +74 -0
- package/dist/types/structures/ackermann.d.ts.map +1 -0
- package/dist/types/structures/big-array.d.ts +102 -0
- package/dist/types/structures/big-array.d.ts.map +1 -0
- package/dist/types/structures/index.d.ts +5 -0
- package/dist/types/structures/index.d.ts.map +1 -0
- package/dist/types/structures/number-tree.d.ts +114 -0
- package/dist/types/structures/number-tree.d.ts.map +1 -0
- package/dist/types/structures/power-tower.d.ts +74 -0
- package/dist/types/structures/power-tower.d.ts.map +1 -0
- package/dist/types/utils/formatting.d.ts +45 -0
- package/dist/types/utils/formatting.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +5 -0
- package/dist/types/utils/index.d.ts.map +1 -0
- package/dist/types/utils/parser.d.ts +39 -0
- package/dist/types/utils/parser.d.ts.map +1 -0
- package/dist/types/utils/precision.d.ts +57 -0
- package/dist/types/utils/precision.d.ts.map +1 -0
- package/dist/types/utils/validation.d.ts +28 -0
- package/dist/types/utils/validation.d.ts.map +1 -0
- package/package.json +164 -0
- package/rollup.config.js +162 -0
- package/src/config/config-loader.ts +226 -0
- package/src/config/config-parser.ts +161 -0
- package/src/config/config-resolver.ts +52 -0
- package/src/config/config-source.ts +32 -0
- package/src/config/index.ts +159 -0
- package/src/core/common.ts +185 -0
- package/src/core/config.ts +393 -0
- package/src/core/constants.ts +102 -0
- package/src/core/errors.ts +203 -0
- package/src/core/hypernum.ts +241 -0
- package/src/core/index.ts +5 -0
- package/src/index.ts +183 -0
- package/src/operations/arithmetic.ts +333 -0
- package/src/operations/bitwise.ts +367 -0
- package/src/operations/comparison.ts +272 -0
- package/src/operations/conversion.ts +400 -0
- package/src/operations/factorial.ts +279 -0
- package/src/operations/index.ts +5 -0
- package/src/operations/power.ts +316 -0
- package/src/storage/Heap.ts +238 -0
- package/src/storage/index.ts +1 -0
- package/src/structures/ackermann.ts +233 -0
- package/src/structures/big-array.ts +306 -0
- package/src/structures/index.ts +4 -0
- package/src/structures/number-tree.ts +404 -0
- package/src/structures/power-tower.ts +278 -0
- package/src/types/common.d.ts +357 -0
- package/src/types/core.d.ts +161 -0
- package/src/types/index.d.ts +2 -0
- package/src/utils/formatting.ts +246 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/parser.ts +245 -0
- package/src/utils/precision.ts +217 -0
- package/src/utils/validation.ts +183 -0
- package/tsconfig.json +84 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* Represents the result of a comparison operation
|
|
4
|
+
* -1: first value is less than second value
|
|
5
|
+
* 0: values are equal
|
|
6
|
+
* 1: first value is greater than second value
|
|
7
|
+
*/
|
|
8
|
+
export type ComparisonResult = -1 | 0 | 1;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generic comparator function type for heap elements
|
|
12
|
+
*/
|
|
13
|
+
export type Comparator<T> = (a: T, b: T) => ComparisonResult;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Abstract base heap class implementing common heap operations
|
|
17
|
+
*/
|
|
18
|
+
abstract class Heap<T> {
|
|
19
|
+
protected heap: T[];
|
|
20
|
+
protected readonly compare: Comparator<T>;
|
|
21
|
+
|
|
22
|
+
constructor(comparator: Comparator<T>) {
|
|
23
|
+
this.heap = [];
|
|
24
|
+
this.compare = comparator;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Gets the size of the heap
|
|
29
|
+
*/
|
|
30
|
+
public size(): number {
|
|
31
|
+
return this.heap.length;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Checks if the heap is empty
|
|
36
|
+
*/
|
|
37
|
+
public isEmpty(): boolean {
|
|
38
|
+
return this.heap.length === 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Peeks at the root element without removing it
|
|
43
|
+
*/
|
|
44
|
+
public peek(): T | undefined {
|
|
45
|
+
return this.heap[0];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Inserts a new element into the heap
|
|
50
|
+
*/
|
|
51
|
+
public push(value: T): void {
|
|
52
|
+
this.heap.push(value);
|
|
53
|
+
this.siftUp(this.heap.length - 1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Removes and returns the root element
|
|
58
|
+
*/
|
|
59
|
+
public pop(): T | undefined {
|
|
60
|
+
if (this.isEmpty()) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const root = this.heap[0];
|
|
65
|
+
const last = this.heap.pop()!;
|
|
66
|
+
|
|
67
|
+
if (!this.isEmpty()) {
|
|
68
|
+
this.heap[0] = last;
|
|
69
|
+
this.siftDown(0);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return root;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Removes all elements from the heap
|
|
77
|
+
*/
|
|
78
|
+
public clear(): void {
|
|
79
|
+
this.heap = [];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Creates a heap from an array of elements
|
|
84
|
+
*/
|
|
85
|
+
public static heapify<T extends {}>(array: T[], comparator: Comparator<T>): Heap<T> {
|
|
86
|
+
const heap = this instanceof MinHeap ? new MinHeap(comparator) : new MaxHeap(comparator);
|
|
87
|
+
array.forEach(item => heap.push(item));
|
|
88
|
+
return heap;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Gets the parent index of a node
|
|
93
|
+
*/
|
|
94
|
+
protected getParentIndex(index: number): number {
|
|
95
|
+
return Math.floor((index - 1) / 2);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Gets the left child index of a node
|
|
100
|
+
*/
|
|
101
|
+
protected getLeftChildIndex(index: number): number {
|
|
102
|
+
return 2 * index + 1;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Gets the right child index of a node
|
|
107
|
+
*/
|
|
108
|
+
protected getRightChildIndex(index: number): number {
|
|
109
|
+
return 2 * index + 2;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Swaps two elements in the heap
|
|
114
|
+
*/
|
|
115
|
+
protected swap(i: number, j: number): void {
|
|
116
|
+
const temp = this.heap[i]!;
|
|
117
|
+
this.heap[i] = this.heap[j]!;
|
|
118
|
+
this.heap[j] = temp;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Moves an element up the heap until heap property is satisfied
|
|
123
|
+
*/
|
|
124
|
+
protected abstract siftUp(index: number): void;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Moves an element down the heap until heap property is satisfied
|
|
128
|
+
*/
|
|
129
|
+
protected abstract siftDown(index: number): void;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* MinHeap implementation where the root is the smallest element
|
|
134
|
+
*/
|
|
135
|
+
export class MinHeap<T> extends Heap<T> {
|
|
136
|
+
constructor(comparator: Comparator<T>) {
|
|
137
|
+
super(comparator);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
protected siftUp(index: number): void {
|
|
141
|
+
while (index > 0) {
|
|
142
|
+
const parentIndex = this.getParentIndex(index);
|
|
143
|
+
if (this.compare(this.heap[index]!, this.heap[parentIndex]!) >= 0) {
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
this.swap(index, parentIndex);
|
|
147
|
+
index = parentIndex;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
protected siftDown(index: number): void {
|
|
152
|
+
const size = this.heap.length;
|
|
153
|
+
|
|
154
|
+
while (true) {
|
|
155
|
+
let smallest = index;
|
|
156
|
+
const left = this.getLeftChildIndex(index);
|
|
157
|
+
const right = this.getRightChildIndex(index);
|
|
158
|
+
|
|
159
|
+
if (left < size && this.compare(this.heap[left]!, this.heap[smallest]!) < 0) {
|
|
160
|
+
smallest = left;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (right < size && this.heap[right] !== undefined && this.compare(this.heap[right] as T, this.heap[smallest] as T) < 0) {
|
|
164
|
+
smallest = right;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (smallest === index) {
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
this.swap(index, smallest);
|
|
172
|
+
index = smallest;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* MaxHeap implementation where the root is the largest element
|
|
179
|
+
*/
|
|
180
|
+
export class MaxHeap<T> extends Heap<T> {
|
|
181
|
+
constructor(comparator: Comparator<T>) {
|
|
182
|
+
super(comparator);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
protected siftUp(index: number): void {
|
|
186
|
+
while (index > 0) {
|
|
187
|
+
const parentIndex = this.getParentIndex(index);
|
|
188
|
+
if (this.compare(this.heap[index]!, this.heap[parentIndex]!) <= 0) {
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
this.swap(index, parentIndex);
|
|
192
|
+
index = parentIndex;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
protected siftDown(index: number): void {
|
|
197
|
+
const size = this.heap.length;
|
|
198
|
+
|
|
199
|
+
while (true) {
|
|
200
|
+
let largest = index;
|
|
201
|
+
const left = this.getLeftChildIndex(index);
|
|
202
|
+
const right = this.getRightChildIndex(index);
|
|
203
|
+
|
|
204
|
+
if (left < size && this.heap[left] !== undefined && this.compare(this.heap[left]!, this.heap[largest]!) > 0) {
|
|
205
|
+
largest = left;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (right < size && this.heap[right] !== undefined && this.compare(this.heap[right]!, this.heap[largest]!) > 0) {
|
|
209
|
+
largest = right;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (largest === index) {
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
this.swap(index, largest);
|
|
217
|
+
index = largest;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Type Guards
|
|
223
|
+
export const isMinHeap = <T>(heap: Heap<T>): heap is MinHeap<T> => {
|
|
224
|
+
return heap instanceof MinHeap;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
export const isMaxHeap = <T>(heap: Heap<T>): heap is MaxHeap<T> => {
|
|
228
|
+
return heap instanceof MaxHeap;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Custom comparator for large numbers
|
|
233
|
+
*/
|
|
234
|
+
export function createLargeNumberComparator(): (a: bigint, b: bigint) => number {
|
|
235
|
+
return (a, b) => {
|
|
236
|
+
return a > b ? 1 : a < b ? -1 : 0;
|
|
237
|
+
};
|
|
238
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Heap';
|
|
@@ -0,0 +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
|
+
|
|
233
|
+
export default AckermannStructure;
|