@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
package/dist/index.js
ADDED
|
@@ -0,0 +1,3284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @obinexusmk2/hypernum v0.1.0
|
|
3
|
+
* Precison at Scale
|
|
4
|
+
*A high-precision mathematics library for large number operations with BigInt support, custom data structures, and comprehensive type safety
|
|
5
|
+
* @license ISC
|
|
6
|
+
*/
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Validation utilities for Hypernum library
|
|
13
|
+
* Provides type checking and validation functions for large number operations
|
|
14
|
+
*/
|
|
15
|
+
// Custom error types for validation
|
|
16
|
+
let ValidationError$1 = class ValidationError extends Error {
|
|
17
|
+
constructor(message) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = 'ValidationError';
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
class OverflowError extends Error {
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = 'OverflowError';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Type guards
|
|
29
|
+
const isBigInt = (value) => {
|
|
30
|
+
return typeof value === 'bigint';
|
|
31
|
+
};
|
|
32
|
+
const isValidNumberString = (value) => {
|
|
33
|
+
return /^-?\d+$/.test(value);
|
|
34
|
+
};
|
|
35
|
+
const isValidNumber = (value) => {
|
|
36
|
+
return typeof value === 'number' && !isNaN(value) && isFinite(value);
|
|
37
|
+
};
|
|
38
|
+
// Type conversions with validation
|
|
39
|
+
const toBigInt = (value) => {
|
|
40
|
+
if (isBigInt(value)) {
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
if (typeof value === 'string') {
|
|
44
|
+
if (!isValidNumberString(value)) {
|
|
45
|
+
throw new ValidationError$1(`Invalid number string: ${value}`);
|
|
46
|
+
}
|
|
47
|
+
return BigInt(value);
|
|
48
|
+
}
|
|
49
|
+
if (isValidNumber(value)) {
|
|
50
|
+
if (!Number.isInteger(value)) {
|
|
51
|
+
throw new ValidationError$1('Cannot convert non-integer number to BigInt');
|
|
52
|
+
}
|
|
53
|
+
return BigInt(value);
|
|
54
|
+
}
|
|
55
|
+
throw new ValidationError$1(`Cannot convert ${typeof value} to BigInt`);
|
|
56
|
+
};
|
|
57
|
+
// Operation safety checks
|
|
58
|
+
const checkAdditionOverflow = (a, b) => {
|
|
59
|
+
// Check if addition would overflow
|
|
60
|
+
if (b > 0 && a > BigInt(Number.MAX_SAFE_INTEGER) - b) {
|
|
61
|
+
throw new OverflowError('Addition would overflow');
|
|
62
|
+
}
|
|
63
|
+
if (b < 0 && a < BigInt(Number.MIN_SAFE_INTEGER) - b) {
|
|
64
|
+
throw new OverflowError('Addition would underflow');
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const checkMultiplicationOverflow = (a, b) => {
|
|
68
|
+
// Check if multiplication would overflow
|
|
69
|
+
if (a !== BigInt(0) && b !== BigInt(0)) {
|
|
70
|
+
const maxValue = BigInt(Number.MAX_SAFE_INTEGER);
|
|
71
|
+
const minValue = BigInt(Number.MIN_SAFE_INTEGER);
|
|
72
|
+
if (a > maxValue / b || a < minValue / b) {
|
|
73
|
+
throw new OverflowError('Multiplication would overflow');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
const checkPowerOverflow = (base, exponent) => {
|
|
78
|
+
// Basic overflow checks for exponentiation
|
|
79
|
+
if (exponent < BigInt(0)) {
|
|
80
|
+
throw new ValidationError$1('Negative exponents not supported for integers');
|
|
81
|
+
}
|
|
82
|
+
if (base === BigInt(0) && exponent === BigInt(0)) {
|
|
83
|
+
throw new ValidationError$1('Zero raised to zero is undefined');
|
|
84
|
+
}
|
|
85
|
+
if (exponent > BigInt(1000)) {
|
|
86
|
+
throw new OverflowError('Exponent too large, computation would overflow');
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const validatePositive = (value) => {
|
|
90
|
+
if (value <= BigInt(0)) {
|
|
91
|
+
throw new ValidationError$1('Value must be positive');
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const validateNonNegative = (value) => {
|
|
95
|
+
if (value < BigInt(0)) {
|
|
96
|
+
throw new ValidationError$1('Value must be non-negative');
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Precision utilities for Hypernum library
|
|
102
|
+
* Provides functions for handling decimal precision and rounding operations
|
|
103
|
+
*/
|
|
104
|
+
/**
|
|
105
|
+
* Rounding modes for decimal operations
|
|
106
|
+
*/
|
|
107
|
+
var RoundingMode;
|
|
108
|
+
(function (RoundingMode) {
|
|
109
|
+
RoundingMode["FLOOR"] = "FLOOR";
|
|
110
|
+
RoundingMode["CEIL"] = "CEIL";
|
|
111
|
+
RoundingMode["DOWN"] = "DOWN";
|
|
112
|
+
RoundingMode["UP"] = "UP";
|
|
113
|
+
RoundingMode["HALF_EVEN"] = "HALF_EVEN";
|
|
114
|
+
RoundingMode["HALF_UP"] = "HALF_UP";
|
|
115
|
+
RoundingMode["HALF_DOWN"] = "HALF_DOWN";
|
|
116
|
+
})(RoundingMode || (RoundingMode = {}));
|
|
117
|
+
/**
|
|
118
|
+
* Scale a bigint by a power of 10
|
|
119
|
+
*/
|
|
120
|
+
const scaleByPowerOfTen = (value, power) => {
|
|
121
|
+
if (power === 0)
|
|
122
|
+
return value;
|
|
123
|
+
if (power > 0) {
|
|
124
|
+
return value * (BigInt(10) ** BigInt(power));
|
|
125
|
+
}
|
|
126
|
+
return value / (BigInt(10) ** BigInt(-power));
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Round a number according to specified mode and precision
|
|
130
|
+
*/
|
|
131
|
+
const round = (value, precision = 0, mode = RoundingMode.HALF_EVEN) => {
|
|
132
|
+
if (precision < 0) {
|
|
133
|
+
throw new ValidationError$1('Precision must be non-negative');
|
|
134
|
+
}
|
|
135
|
+
if (precision === 0) {
|
|
136
|
+
return value;
|
|
137
|
+
}
|
|
138
|
+
const scale = BigInt(10) ** BigInt(precision);
|
|
139
|
+
const scaled = value / scale;
|
|
140
|
+
const remainder = value % scale;
|
|
141
|
+
switch (mode) {
|
|
142
|
+
case RoundingMode.FLOOR:
|
|
143
|
+
return scaled * scale;
|
|
144
|
+
case RoundingMode.CEIL:
|
|
145
|
+
return remainder > 0n ? (scaled + 1n) * scale : scaled * scale;
|
|
146
|
+
case RoundingMode.DOWN:
|
|
147
|
+
return value >= 0n ? scaled * scale : (scaled - 1n) * scale;
|
|
148
|
+
case RoundingMode.UP:
|
|
149
|
+
return value >= 0n ? (scaled + 1n) * scale : scaled * scale;
|
|
150
|
+
case RoundingMode.HALF_UP:
|
|
151
|
+
return remainder >= scale / 2n ? (scaled + 1n) * scale : scaled * scale;
|
|
152
|
+
case RoundingMode.HALF_DOWN:
|
|
153
|
+
return remainder > scale / 2n ? (scaled + 1n) * scale : scaled * scale;
|
|
154
|
+
case RoundingMode.HALF_EVEN:
|
|
155
|
+
if (remainder === scale / 2n) {
|
|
156
|
+
return scaled % 2n === 0n ? scaled * scale : (scaled + 1n) * scale;
|
|
157
|
+
}
|
|
158
|
+
return remainder > scale / 2n ? (scaled + 1n) * scale : scaled * scale;
|
|
159
|
+
default:
|
|
160
|
+
throw new ValidationError$1('Invalid rounding mode');
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Normalize two numbers to the same precision
|
|
165
|
+
*/
|
|
166
|
+
const normalizePrecision = (a, b, precisionA, precisionB) => {
|
|
167
|
+
const targetPrecision = Math.max(precisionA, precisionB);
|
|
168
|
+
const scaledA = scaleByPowerOfTen(a, targetPrecision - precisionA);
|
|
169
|
+
const scaledB = scaleByPowerOfTen(b, targetPrecision - precisionB);
|
|
170
|
+
return [scaledA, scaledB];
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Scale a division operation to achieve desired precision
|
|
174
|
+
*/
|
|
175
|
+
const scaledDivision = (numerator, denominator, precision, roundingMode = RoundingMode.HALF_EVEN) => {
|
|
176
|
+
if (denominator === 0n) {
|
|
177
|
+
throw new ValidationError$1('Division by zero');
|
|
178
|
+
}
|
|
179
|
+
if (precision < 0) {
|
|
180
|
+
throw new ValidationError$1('Precision must be non-negative');
|
|
181
|
+
}
|
|
182
|
+
// Scale up numerator to handle desired precision
|
|
183
|
+
const scaledNumerator = scaleByPowerOfTen(numerator, precision);
|
|
184
|
+
const quotient = scaledNumerator / denominator;
|
|
185
|
+
return round(quotient, 0, roundingMode);
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Configuration type definitions for Hypernum library
|
|
190
|
+
* Defines all configuration options and their default values
|
|
191
|
+
*/
|
|
192
|
+
/**
|
|
193
|
+
* Converts FullConfig to BasicConfig if necessary
|
|
194
|
+
*/
|
|
195
|
+
function convertToBasicConfig(config) {
|
|
196
|
+
if (isBasicConfig(config)) {
|
|
197
|
+
return config;
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
precision: config.arithmetic.defaultPrecision,
|
|
201
|
+
roundingMode: config.arithmetic.defaultRoundingMode,
|
|
202
|
+
checkOverflow: config.arithmetic.checkOverflow,
|
|
203
|
+
maxSteps: config.arithmetic.maxComputationSteps,
|
|
204
|
+
debug: config.debug.verbose
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Default configuration values for basic config
|
|
209
|
+
*/
|
|
210
|
+
const DEFAULT_BASIC_CONFIG = {
|
|
211
|
+
precision: 0,
|
|
212
|
+
roundingMode: RoundingMode.HALF_EVEN,
|
|
213
|
+
checkOverflow: true,
|
|
214
|
+
maxSteps: 1000,
|
|
215
|
+
debug: false
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* Full default configuration values
|
|
219
|
+
*/
|
|
220
|
+
const DEFAULT_FULL_CONFIG = {
|
|
221
|
+
arithmetic: {
|
|
222
|
+
defaultPrecision: 0,
|
|
223
|
+
defaultRoundingMode: RoundingMode.HALF_EVEN,
|
|
224
|
+
checkOverflow: true,
|
|
225
|
+
maxComputationSteps: 1000,
|
|
226
|
+
autoPrecision: {
|
|
227
|
+
enabled: true,
|
|
228
|
+
maxPrecision: 100,
|
|
229
|
+
minPrecision: 0
|
|
230
|
+
},
|
|
231
|
+
constants: {
|
|
232
|
+
precision: 50,
|
|
233
|
+
cache: true,
|
|
234
|
+
algorithm: 'series'
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
dataStructures: {
|
|
238
|
+
array: {
|
|
239
|
+
initialCapacity: 16,
|
|
240
|
+
growthFactor: 2,
|
|
241
|
+
maxSize: 1000000
|
|
242
|
+
},
|
|
243
|
+
tree: {
|
|
244
|
+
maxDepth: 1000,
|
|
245
|
+
autoBalance: true,
|
|
246
|
+
nodeLimit: 1000000
|
|
247
|
+
},
|
|
248
|
+
heap: {
|
|
249
|
+
initialCapacity: 16,
|
|
250
|
+
growthPolicy: 'double',
|
|
251
|
+
validatePropertyOnOperation: true
|
|
252
|
+
},
|
|
253
|
+
cache: {
|
|
254
|
+
enabled: true,
|
|
255
|
+
maxSize: 1000,
|
|
256
|
+
ttl: 3600000, // 1 hour
|
|
257
|
+
evictionPolicy: 'LRU',
|
|
258
|
+
persistToDisk: false,
|
|
259
|
+
compressionEnabled: false
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
formatting: {
|
|
263
|
+
notation: 'standard',
|
|
264
|
+
precision: 0,
|
|
265
|
+
grouping: true,
|
|
266
|
+
groupSize: 3,
|
|
267
|
+
decimalSeparator: '.',
|
|
268
|
+
groupSeparator: ',',
|
|
269
|
+
uppercase: false,
|
|
270
|
+
scientific: {
|
|
271
|
+
minExponent: 6,
|
|
272
|
+
maxSignificantDigits: 6,
|
|
273
|
+
exponentSeparator: 'e'
|
|
274
|
+
},
|
|
275
|
+
engineering: {
|
|
276
|
+
useSIPrefixes: true
|
|
277
|
+
},
|
|
278
|
+
localization: {
|
|
279
|
+
locale: 'en-US',
|
|
280
|
+
useLocaleGrouping: false
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
performance: {
|
|
284
|
+
enableTracking: false,
|
|
285
|
+
samplingRate: 0.1,
|
|
286
|
+
thresholds: {
|
|
287
|
+
warnThresholdMs: 100,
|
|
288
|
+
errorThresholdMs: 1000,
|
|
289
|
+
maxMemoryBytes: 1024 * 1024 * 1024 // 1GB
|
|
290
|
+
},
|
|
291
|
+
metrics: {
|
|
292
|
+
timing: true,
|
|
293
|
+
memory: true,
|
|
294
|
+
cache: true
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
debug: {
|
|
298
|
+
verbose: false,
|
|
299
|
+
trackPerformance: false,
|
|
300
|
+
logLevel: 'error'
|
|
301
|
+
},
|
|
302
|
+
features: {
|
|
303
|
+
experimentalFeatures: false,
|
|
304
|
+
useWasm: false,
|
|
305
|
+
workerThreads: false,
|
|
306
|
+
sharedArrayBuffer: false,
|
|
307
|
+
bigIntTypedArrays: true
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
/**
|
|
311
|
+
* Type guard to check if config is a full configuration
|
|
312
|
+
*/
|
|
313
|
+
function isFullConfig(config) {
|
|
314
|
+
return 'arithmetic' in config && 'dataStructures' in config;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Type guard to check if config is a basic configuration
|
|
318
|
+
*/
|
|
319
|
+
function isBasicConfig(config) {
|
|
320
|
+
return !isFullConfig(config);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Validates configuration values
|
|
324
|
+
*/
|
|
325
|
+
function validateConfig(config) {
|
|
326
|
+
if (isFullConfig(config)) {
|
|
327
|
+
validateFullConfig(config);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
validateBasicConfig(config);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Validates basic configuration values
|
|
335
|
+
*/
|
|
336
|
+
function validateBasicConfig(config) {
|
|
337
|
+
if (config.precision !== undefined && config.precision < 0) {
|
|
338
|
+
throw new Error('Precision cannot be negative');
|
|
339
|
+
}
|
|
340
|
+
if (config.maxSteps !== undefined && config.maxSteps <= 0) {
|
|
341
|
+
throw new Error('Maximum steps must be positive');
|
|
342
|
+
}
|
|
343
|
+
if (config.debug !== undefined && typeof config.debug !== 'boolean') {
|
|
344
|
+
throw new Error('Debug flag must be a boolean');
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Validates full configuration values
|
|
349
|
+
*/
|
|
350
|
+
function validateFullConfig(config) {
|
|
351
|
+
if (config.arithmetic.defaultPrecision < 0) {
|
|
352
|
+
throw new Error('Default precision cannot be negative');
|
|
353
|
+
}
|
|
354
|
+
if (config.arithmetic.maxComputationSteps <= 0) {
|
|
355
|
+
throw new Error('Max computation steps must be positive');
|
|
356
|
+
}
|
|
357
|
+
if (config.dataStructures.array.initialCapacity <= 0) {
|
|
358
|
+
throw new Error('Initial capacity must be positive');
|
|
359
|
+
}
|
|
360
|
+
if (config.dataStructures.array.growthFactor <= 1) {
|
|
361
|
+
throw new Error('Growth factor must be greater than 1');
|
|
362
|
+
}
|
|
363
|
+
if (config.performance.samplingRate < 0 || config.performance.samplingRate > 1) {
|
|
364
|
+
throw new Error('Sampling rate must be between 0 and 1');
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Merges configuration with appropriate defaults
|
|
369
|
+
*/
|
|
370
|
+
function mergeConfig(custom = {}) {
|
|
371
|
+
if (isFullConfig(custom)) {
|
|
372
|
+
const fullConfig = custom;
|
|
373
|
+
return {
|
|
374
|
+
...DEFAULT_FULL_CONFIG,
|
|
375
|
+
...fullConfig,
|
|
376
|
+
arithmetic: { ...DEFAULT_FULL_CONFIG.arithmetic, ...fullConfig.arithmetic },
|
|
377
|
+
dataStructures: { ...DEFAULT_FULL_CONFIG.dataStructures, ...fullConfig.dataStructures },
|
|
378
|
+
formatting: { ...DEFAULT_FULL_CONFIG.formatting, ...fullConfig.formatting },
|
|
379
|
+
performance: { ...DEFAULT_FULL_CONFIG.performance, ...fullConfig.performance },
|
|
380
|
+
debug: { ...DEFAULT_FULL_CONFIG.debug, ...fullConfig.debug },
|
|
381
|
+
features: { ...DEFAULT_FULL_CONFIG.features, ...fullConfig.features }
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
const basicConfig = {
|
|
385
|
+
precision: custom.precision ?? DEFAULT_BASIC_CONFIG.precision,
|
|
386
|
+
roundingMode: custom.roundingMode ?? DEFAULT_BASIC_CONFIG.roundingMode,
|
|
387
|
+
checkOverflow: custom.checkOverflow ?? DEFAULT_BASIC_CONFIG.checkOverflow,
|
|
388
|
+
maxSteps: custom.maxSteps ?? DEFAULT_BASIC_CONFIG.maxSteps,
|
|
389
|
+
debug: custom.debug ?? DEFAULT_BASIC_CONFIG.debug
|
|
390
|
+
};
|
|
391
|
+
return basicConfig;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Core constants for Hypernum library
|
|
396
|
+
* Defines fundamental values and limits used across the library
|
|
397
|
+
*/
|
|
398
|
+
// Numerical limits
|
|
399
|
+
const MAX_SAFE_INTEGER = BigInt(Number.MAX_SAFE_INTEGER);
|
|
400
|
+
const MIN_SAFE_INTEGER = BigInt(Number.MIN_SAFE_INTEGER);
|
|
401
|
+
const MAX_PRECISION = 100;
|
|
402
|
+
const MAX_COMPUTATION_STEPS = 1000;
|
|
403
|
+
const MAX_BITS = 1024;
|
|
404
|
+
// Commonly used values
|
|
405
|
+
const ZERO = BigInt(0);
|
|
406
|
+
const ONE = BigInt(1);
|
|
407
|
+
const TWO = BigInt(2);
|
|
408
|
+
const TEN = BigInt(10);
|
|
409
|
+
const NEGATIVE_ONE = BigInt(-1);
|
|
410
|
+
// Power operation limits
|
|
411
|
+
const MAX_POWER_BASE = BigInt(2) ** BigInt(53);
|
|
412
|
+
const MAX_POWER_EXPONENT = BigInt(1000);
|
|
413
|
+
const MAX_TETRATION_HEIGHT = BigInt(4);
|
|
414
|
+
const MAX_FACTORIAL_INPUT = BigInt(1000);
|
|
415
|
+
// Tree and heap configuration
|
|
416
|
+
const DEFAULT_TREE_MAX_DEPTH = 1000;
|
|
417
|
+
const DEFAULT_HEAP_INITIAL_CAPACITY = 16;
|
|
418
|
+
const DEFAULT_ARRAY_GROWTH_FACTOR = 2;
|
|
419
|
+
const MIN_ARRAY_CAPACITY = 16;
|
|
420
|
+
// Formatting configuration
|
|
421
|
+
const DEFAULT_DECIMAL_SEPARATOR = '.';
|
|
422
|
+
const DEFAULT_GROUP_SEPARATOR = ',';
|
|
423
|
+
const DEFAULT_GROUP_SIZE = 3;
|
|
424
|
+
const MAX_GROUP_SIZE = 10;
|
|
425
|
+
// Roman numeral limits
|
|
426
|
+
const MIN_ROMAN_VALUE = 1;
|
|
427
|
+
const MAX_ROMAN_VALUE = 3999;
|
|
428
|
+
// Ackermann function limits
|
|
429
|
+
const MAX_ACKERMANN_M = 4;
|
|
430
|
+
const MAX_ACKERMANN_N = 1000;
|
|
431
|
+
// Cache configuration
|
|
432
|
+
const DEFAULT_CACHE_SIZE = 1000;
|
|
433
|
+
const MAX_CACHE_SIZE = 10000;
|
|
434
|
+
// Error messages
|
|
435
|
+
const ERROR_MESSAGES = {
|
|
436
|
+
OVERFLOW: 'Operation would result in overflow',
|
|
437
|
+
UNDERFLOW: 'Operation would result in underflow',
|
|
438
|
+
NEGATIVE_ROOT: 'Cannot compute root of negative number',
|
|
439
|
+
NEGATIVE_EXPONENT: 'Negative exponents not supported for integers',
|
|
440
|
+
DIVISION_BY_ZERO: 'Division by zero',
|
|
441
|
+
INVALID_PRECISION: 'Precision must be non-negative and not exceed MAX_PRECISION',
|
|
442
|
+
INVALID_BASE: 'Base must be a positive integer',
|
|
443
|
+
INVALID_ROMAN: 'Invalid Roman numeral',
|
|
444
|
+
COMPUTATION_LIMIT: 'Computation exceeded maximum allowed steps',
|
|
445
|
+
NEGATIVE_INDEX: 'Array index cannot be negative',
|
|
446
|
+
TREE_DEPTH_EXCEEDED: 'Maximum tree depth exceeded',
|
|
447
|
+
INVALID_HEAP_PROPERTY: 'Heap property violation detected'
|
|
448
|
+
};
|
|
449
|
+
// Feature flags for optional functionality
|
|
450
|
+
const FEATURES = {
|
|
451
|
+
OVERFLOW_CHECKING: true,
|
|
452
|
+
AUTOMATIC_PRECISION: true,
|
|
453
|
+
MEMOIZATION: true,
|
|
454
|
+
TREE_BALANCING: true,
|
|
455
|
+
DEBUG_MODE: false
|
|
456
|
+
};
|
|
457
|
+
// Default options for various operations
|
|
458
|
+
const DEFAULT_OPTIONS$8 = {
|
|
459
|
+
precision: 0,
|
|
460
|
+
roundingMode: 'HALF_EVEN',
|
|
461
|
+
checkOverflow: true,
|
|
462
|
+
maxSteps: MAX_COMPUTATION_STEPS,
|
|
463
|
+
grouping: true,
|
|
464
|
+
uppercase: false,
|
|
465
|
+
cache: true
|
|
466
|
+
};
|
|
467
|
+
// Units for number formatting (powers of 1000)
|
|
468
|
+
const NUMBER_UNITS = [
|
|
469
|
+
{ value: 1n, symbol: '' },
|
|
470
|
+
{ value: 1000n, symbol: 'K' },
|
|
471
|
+
{ value: 1000000n, symbol: 'M' },
|
|
472
|
+
{ value: 1000000000n, symbol: 'B' },
|
|
473
|
+
{ value: 1000000000000n, symbol: 'T' },
|
|
474
|
+
{ value: 1000000000000000n, symbol: 'Q' }
|
|
475
|
+
];
|
|
476
|
+
// Performance monitoring thresholds
|
|
477
|
+
const PERFORMANCE = {
|
|
478
|
+
WARN_THRESHOLD_MS: 100,
|
|
479
|
+
ERROR_THRESHOLD_MS: 1000,
|
|
480
|
+
MAX_ARRAY_SIZE: 1000000,
|
|
481
|
+
MAX_TREE_SIZE: 1000000
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Custom error types for Hypernum library
|
|
486
|
+
* Provides specific error classes for different types of errors that can occur
|
|
487
|
+
* during mathematical operations and data structure manipulations
|
|
488
|
+
*/
|
|
489
|
+
/**
|
|
490
|
+
* Base error class for Hypernum library
|
|
491
|
+
* All other error classes inherit from this
|
|
492
|
+
*/
|
|
493
|
+
class HypernumError extends Error {
|
|
494
|
+
constructor(message) {
|
|
495
|
+
super(message);
|
|
496
|
+
this.name = 'HypernumError';
|
|
497
|
+
Object.setPrototypeOf(this, HypernumError.prototype);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Error for validation failures
|
|
502
|
+
*/
|
|
503
|
+
class ValidationError extends HypernumError {
|
|
504
|
+
constructor(message) {
|
|
505
|
+
super(message);
|
|
506
|
+
this.name = 'ValidationError';
|
|
507
|
+
Object.setPrototypeOf(this, ValidationError.prototype);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Error for arithmetic underflow conditions
|
|
512
|
+
*/
|
|
513
|
+
class UnderflowError extends HypernumError {
|
|
514
|
+
constructor(message = ERROR_MESSAGES.UNDERFLOW) {
|
|
515
|
+
super(message);
|
|
516
|
+
this.name = 'UnderflowError';
|
|
517
|
+
Object.setPrototypeOf(this, UnderflowError.prototype);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Error for division by zero
|
|
522
|
+
*/
|
|
523
|
+
class DivisionByZeroError extends HypernumError {
|
|
524
|
+
constructor(message = ERROR_MESSAGES.DIVISION_BY_ZERO) {
|
|
525
|
+
super(message);
|
|
526
|
+
this.name = 'DivisionByZeroError';
|
|
527
|
+
Object.setPrototypeOf(this, DivisionByZeroError.prototype);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Error for precision-related issues
|
|
532
|
+
*/
|
|
533
|
+
class PrecisionError extends HypernumError {
|
|
534
|
+
constructor(message = ERROR_MESSAGES.INVALID_PRECISION) {
|
|
535
|
+
super(message);
|
|
536
|
+
this.name = 'PrecisionError';
|
|
537
|
+
Object.setPrototypeOf(this, PrecisionError.prototype);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Error for computation limits exceeded
|
|
542
|
+
*/
|
|
543
|
+
class ComputationLimitError extends HypernumError {
|
|
544
|
+
constructor(message = ERROR_MESSAGES.COMPUTATION_LIMIT) {
|
|
545
|
+
super(message);
|
|
546
|
+
this.name = 'ComputationLimitError';
|
|
547
|
+
Object.setPrototypeOf(this, ComputationLimitError.prototype);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Error for invalid operations on data structures
|
|
552
|
+
*/
|
|
553
|
+
class DataStructureError extends HypernumError {
|
|
554
|
+
constructor(message) {
|
|
555
|
+
super(message);
|
|
556
|
+
this.name = 'DataStructureError';
|
|
557
|
+
Object.setPrototypeOf(this, DataStructureError.prototype);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Error for heap property violations
|
|
562
|
+
*/
|
|
563
|
+
class HeapPropertyError extends DataStructureError {
|
|
564
|
+
constructor(message = ERROR_MESSAGES.INVALID_HEAP_PROPERTY) {
|
|
565
|
+
super(message);
|
|
566
|
+
this.name = 'HeapPropertyError';
|
|
567
|
+
Object.setPrototypeOf(this, HeapPropertyError.prototype);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Error for tree-related issues
|
|
572
|
+
*/
|
|
573
|
+
class TreeError extends DataStructureError {
|
|
574
|
+
constructor(message = ERROR_MESSAGES.TREE_DEPTH_EXCEEDED) {
|
|
575
|
+
super(message);
|
|
576
|
+
this.name = 'TreeError';
|
|
577
|
+
Object.setPrototypeOf(this, TreeError.prototype);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Error for array index out of bounds
|
|
582
|
+
*/
|
|
583
|
+
class IndexError extends DataStructureError {
|
|
584
|
+
constructor(message = ERROR_MESSAGES.NEGATIVE_INDEX) {
|
|
585
|
+
super(message);
|
|
586
|
+
this.name = 'IndexError';
|
|
587
|
+
Object.setPrototypeOf(this, IndexError.prototype);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Error for invalid number format or conversion
|
|
592
|
+
*/
|
|
593
|
+
class FormatError extends HypernumError {
|
|
594
|
+
constructor(message) {
|
|
595
|
+
super(message);
|
|
596
|
+
this.name = 'FormatError';
|
|
597
|
+
Object.setPrototypeOf(this, FormatError.prototype);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Error for invalid Roman numeral operations
|
|
602
|
+
*/
|
|
603
|
+
class RomanNumeralError extends FormatError {
|
|
604
|
+
constructor(message = ERROR_MESSAGES.INVALID_ROMAN) {
|
|
605
|
+
super(message);
|
|
606
|
+
this.name = 'RomanNumeralError';
|
|
607
|
+
Object.setPrototypeOf(this, RomanNumeralError.prototype);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Arithmetic operations module for Hypernum library
|
|
613
|
+
* Provides high-precision arithmetic operations with BigInt support
|
|
614
|
+
*/
|
|
615
|
+
const DEFAULT_OPTIONS$7 = {
|
|
616
|
+
precision: 0,
|
|
617
|
+
roundingMode: RoundingMode.HALF_EVEN,
|
|
618
|
+
checkOverflow: true
|
|
619
|
+
};
|
|
620
|
+
/**
|
|
621
|
+
* Adds two numbers with optional precision and overflow checking
|
|
622
|
+
*/
|
|
623
|
+
function add(a, b, options = {}) {
|
|
624
|
+
const opts = { ...DEFAULT_OPTIONS$7, ...options };
|
|
625
|
+
const bigA = toBigInt(a);
|
|
626
|
+
const bigB = toBigInt(b);
|
|
627
|
+
if (opts.checkOverflow) {
|
|
628
|
+
checkAdditionOverflow(bigA, bigB);
|
|
629
|
+
}
|
|
630
|
+
if (opts.precision === 0) {
|
|
631
|
+
return bigA + bigB;
|
|
632
|
+
}
|
|
633
|
+
const [scaledA, scaledB] = normalizePrecision(bigA, bigB, opts.precision, opts.precision);
|
|
634
|
+
const result = scaledA + scaledB;
|
|
635
|
+
return round(result, opts.precision, opts.roundingMode);
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Subtracts two numbers with optional precision and overflow checking
|
|
639
|
+
*/
|
|
640
|
+
function subtract(a, b, options = {}) {
|
|
641
|
+
const opts = { ...DEFAULT_OPTIONS$7, ...options };
|
|
642
|
+
const bigA = toBigInt(a);
|
|
643
|
+
const bigB = toBigInt(b);
|
|
644
|
+
if (opts.checkOverflow) {
|
|
645
|
+
checkAdditionOverflow(bigA, -bigB);
|
|
646
|
+
}
|
|
647
|
+
if (opts.precision === 0) {
|
|
648
|
+
return bigA - bigB;
|
|
649
|
+
}
|
|
650
|
+
const [scaledA, scaledB] = normalizePrecision(bigA, bigB, opts.precision, opts.precision);
|
|
651
|
+
const result = scaledA - scaledB;
|
|
652
|
+
return round(result, opts.precision, opts.roundingMode);
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Multiplies two numbers with optional precision and overflow checking
|
|
656
|
+
*/
|
|
657
|
+
function multiply(a, b, options = {}) {
|
|
658
|
+
const opts = { ...DEFAULT_OPTIONS$7, ...options };
|
|
659
|
+
const bigA = toBigInt(a);
|
|
660
|
+
const bigB = toBigInt(b);
|
|
661
|
+
if (opts.checkOverflow) {
|
|
662
|
+
checkMultiplicationOverflow(bigA, bigB);
|
|
663
|
+
}
|
|
664
|
+
const result = bigA * bigB;
|
|
665
|
+
if (opts.precision === 0) {
|
|
666
|
+
return result;
|
|
667
|
+
}
|
|
668
|
+
return round(result, opts.precision, opts.roundingMode);
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Divides two numbers with specified precision and rounding
|
|
672
|
+
*/
|
|
673
|
+
function divide(numerator, denominator, options = {}) {
|
|
674
|
+
const opts = { ...DEFAULT_OPTIONS$7, ...options };
|
|
675
|
+
const bigNumerator = toBigInt(numerator);
|
|
676
|
+
const bigDenominator = toBigInt(denominator);
|
|
677
|
+
if (bigDenominator === BigInt(0)) {
|
|
678
|
+
throw new ValidationError$1('Division by zero');
|
|
679
|
+
}
|
|
680
|
+
return scaledDivision(bigNumerator, bigDenominator, opts.precision, opts.roundingMode);
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Calculates remainder with optional precision
|
|
684
|
+
*/
|
|
685
|
+
function remainder(a, b, options = {}) {
|
|
686
|
+
const opts = { ...DEFAULT_OPTIONS$7, ...options };
|
|
687
|
+
const bigA = toBigInt(a);
|
|
688
|
+
const bigB = toBigInt(b);
|
|
689
|
+
if (bigB === BigInt(0)) {
|
|
690
|
+
throw new ValidationError$1('Division by zero in remainder operation');
|
|
691
|
+
}
|
|
692
|
+
if (opts.precision === 0) {
|
|
693
|
+
return bigA % bigB;
|
|
694
|
+
}
|
|
695
|
+
const [scaledA, scaledB] = normalizePrecision(bigA, bigB, opts.precision, opts.precision);
|
|
696
|
+
const result = scaledA % scaledB;
|
|
697
|
+
return round(result, opts.precision, opts.roundingMode);
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Calculates the absolute value
|
|
701
|
+
*/
|
|
702
|
+
function abs(value) {
|
|
703
|
+
const bigValue = toBigInt(value);
|
|
704
|
+
return bigValue < BigInt(0) ? -bigValue : bigValue;
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Returns the sign of a number (-1, 0, or 1)
|
|
708
|
+
*/
|
|
709
|
+
function sign(value) {
|
|
710
|
+
const bigValue = toBigInt(value);
|
|
711
|
+
if (bigValue < BigInt(0))
|
|
712
|
+
return BigInt(-1);
|
|
713
|
+
if (bigValue > BigInt(0))
|
|
714
|
+
return BigInt(1);
|
|
715
|
+
return BigInt(0);
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Calculates the greatest common divisor of two numbers
|
|
719
|
+
*/
|
|
720
|
+
function gcd(a, b) {
|
|
721
|
+
let bigA = abs(toBigInt(a));
|
|
722
|
+
let bigB = abs(toBigInt(b));
|
|
723
|
+
while (bigB !== BigInt(0)) {
|
|
724
|
+
const temp = bigB;
|
|
725
|
+
bigB = bigA % bigB;
|
|
726
|
+
bigA = temp;
|
|
727
|
+
}
|
|
728
|
+
return bigA;
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Calculates the least common multiple of two numbers
|
|
732
|
+
*/
|
|
733
|
+
function lcm(a, b) {
|
|
734
|
+
const bigA = abs(toBigInt(a));
|
|
735
|
+
const bigB = abs(toBigInt(b));
|
|
736
|
+
if (bigA === BigInt(0) || bigB === BigInt(0)) {
|
|
737
|
+
return BigInt(0);
|
|
738
|
+
}
|
|
739
|
+
return abs(bigA * bigB) / gcd(bigA, bigB);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* Bitwise operations module for Hypernum library
|
|
744
|
+
* Provides functions for bit-level manipulations of large numbers
|
|
745
|
+
*/
|
|
746
|
+
const DEFAULT_OPTIONS$6 = {
|
|
747
|
+
maxBits: 1024,
|
|
748
|
+
strict: true
|
|
749
|
+
};
|
|
750
|
+
/**
|
|
751
|
+
* Validates shift amount is within reasonable bounds
|
|
752
|
+
*/
|
|
753
|
+
function validateShift(shift, options) {
|
|
754
|
+
if (shift < 0n) {
|
|
755
|
+
throw new ValidationError$1('Shift amount cannot be negative');
|
|
756
|
+
}
|
|
757
|
+
if (options.strict && shift >= BigInt(options.maxBits)) {
|
|
758
|
+
throw new ValidationError$1(`Shift amount exceeds maximum of ${options.maxBits} bits`);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Performs bitwise AND operation
|
|
763
|
+
*/
|
|
764
|
+
function and(a, b) {
|
|
765
|
+
const bigA = toBigInt(a);
|
|
766
|
+
const bigB = toBigInt(b);
|
|
767
|
+
return bigA & bigB;
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Performs bitwise OR operation
|
|
771
|
+
*/
|
|
772
|
+
function or(a, b) {
|
|
773
|
+
const bigA = toBigInt(a);
|
|
774
|
+
const bigB = toBigInt(b);
|
|
775
|
+
return bigA | bigB;
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Performs bitwise XOR operation
|
|
779
|
+
*/
|
|
780
|
+
function xor(a, b) {
|
|
781
|
+
const bigA = toBigInt(a);
|
|
782
|
+
const bigB = toBigInt(b);
|
|
783
|
+
return bigA ^ bigB;
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Performs bitwise NOT operation
|
|
787
|
+
*/
|
|
788
|
+
function not(value) {
|
|
789
|
+
const bigValue = toBigInt(value);
|
|
790
|
+
return ~bigValue;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Performs left shift operation
|
|
794
|
+
*/
|
|
795
|
+
function leftShift(value, shift, options = {}) {
|
|
796
|
+
const opts = { ...DEFAULT_OPTIONS$6, ...options };
|
|
797
|
+
const bigValue = toBigInt(value);
|
|
798
|
+
const bigShift = toBigInt(shift);
|
|
799
|
+
validateShift(bigShift, opts);
|
|
800
|
+
return bigValue << bigShift;
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Performs right shift operation
|
|
804
|
+
*/
|
|
805
|
+
function rightShift(value, shift, options = {}) {
|
|
806
|
+
const opts = { ...DEFAULT_OPTIONS$6, ...options };
|
|
807
|
+
const bigValue = toBigInt(value);
|
|
808
|
+
const bigShift = toBigInt(shift);
|
|
809
|
+
validateShift(bigShift, opts);
|
|
810
|
+
return bigValue >> bigShift;
|
|
811
|
+
}
|
|
812
|
+
/**
|
|
813
|
+
* Performs unsigned right shift operation
|
|
814
|
+
* Note: BigInt doesn't have >>> operator, so we implement it manually
|
|
815
|
+
*/
|
|
816
|
+
function unsignedRightShift(value, shift, options = {}) {
|
|
817
|
+
const opts = { ...DEFAULT_OPTIONS$6, ...options };
|
|
818
|
+
const bigValue = toBigInt(value);
|
|
819
|
+
const bigShift = toBigInt(shift);
|
|
820
|
+
validateShift(bigShift, opts);
|
|
821
|
+
if (bigValue >= 0n) {
|
|
822
|
+
return bigValue >> bigShift;
|
|
823
|
+
}
|
|
824
|
+
// Handle negative numbers by first converting to positive
|
|
825
|
+
const mask = (1n << BigInt(opts.maxBits)) - 1n;
|
|
826
|
+
return (bigValue & mask) >> bigShift;
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Rotates bits left by specified amount
|
|
830
|
+
*/
|
|
831
|
+
function rotateLeft(value, rotation, options = {}) {
|
|
832
|
+
const opts = { ...DEFAULT_OPTIONS$6, ...options };
|
|
833
|
+
const bigValue = toBigInt(value);
|
|
834
|
+
let bigRotation = toBigInt(rotation);
|
|
835
|
+
validateNonNegative(bigRotation);
|
|
836
|
+
// Normalize rotation to be within maxBits
|
|
837
|
+
if (bigRotation >= BigInt(opts.maxBits)) {
|
|
838
|
+
bigRotation = bigRotation % BigInt(opts.maxBits);
|
|
839
|
+
}
|
|
840
|
+
if (bigRotation === 0n) {
|
|
841
|
+
return bigValue;
|
|
842
|
+
}
|
|
843
|
+
const leftPart = leftShift(bigValue, bigRotation, opts);
|
|
844
|
+
const rightPart = unsignedRightShift(bigValue, BigInt(opts.maxBits) - bigRotation, opts);
|
|
845
|
+
return leftPart | rightPart;
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Rotates bits right by specified amount
|
|
849
|
+
*/
|
|
850
|
+
function rotateRight(value, rotation, options = {}) {
|
|
851
|
+
const opts = { ...DEFAULT_OPTIONS$6, ...options };
|
|
852
|
+
const bigValue = toBigInt(value);
|
|
853
|
+
let bigRotation = toBigInt(rotation);
|
|
854
|
+
validateNonNegative(bigRotation);
|
|
855
|
+
// Normalize rotation to be within maxBits
|
|
856
|
+
if (bigRotation >= BigInt(opts.maxBits)) {
|
|
857
|
+
bigRotation = bigRotation % BigInt(opts.maxBits);
|
|
858
|
+
}
|
|
859
|
+
if (bigRotation === 0n) {
|
|
860
|
+
return bigValue;
|
|
861
|
+
}
|
|
862
|
+
const rightPart = unsignedRightShift(bigValue, bigRotation, opts);
|
|
863
|
+
const leftPart = leftShift(bigValue, BigInt(opts.maxBits) - bigRotation, opts);
|
|
864
|
+
return leftPart | rightPart;
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Counts number of set bits (1s)
|
|
868
|
+
*/
|
|
869
|
+
function popCount(value, options = {}) {
|
|
870
|
+
const opts = { ...DEFAULT_OPTIONS$6, ...options };
|
|
871
|
+
let bigValue = toBigInt(value);
|
|
872
|
+
let count = 0n;
|
|
873
|
+
while (bigValue !== 0n) {
|
|
874
|
+
count += bigValue & 1n;
|
|
875
|
+
bigValue = unsignedRightShift(bigValue, 1n, opts);
|
|
876
|
+
}
|
|
877
|
+
return count;
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* Returns number of trailing zero bits
|
|
881
|
+
*/
|
|
882
|
+
function trailingZeros(value, options = {}) {
|
|
883
|
+
const opts = { ...DEFAULT_OPTIONS$6, ...options };
|
|
884
|
+
let bigValue = toBigInt(value);
|
|
885
|
+
if (bigValue === 0n) {
|
|
886
|
+
return BigInt(opts.maxBits);
|
|
887
|
+
}
|
|
888
|
+
let count = 0n;
|
|
889
|
+
while ((bigValue & 1n) === 0n) {
|
|
890
|
+
count++;
|
|
891
|
+
bigValue = unsignedRightShift(bigValue, 1n, opts);
|
|
892
|
+
}
|
|
893
|
+
return count;
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Returns number of leading zero bits
|
|
897
|
+
*/
|
|
898
|
+
function leadingZeros(value, options = {}) {
|
|
899
|
+
const opts = { ...DEFAULT_OPTIONS$6, ...options };
|
|
900
|
+
let bigValue = toBigInt(value);
|
|
901
|
+
if (bigValue === 0n) {
|
|
902
|
+
return BigInt(opts.maxBits);
|
|
903
|
+
}
|
|
904
|
+
let count = 0n;
|
|
905
|
+
const msb = 1n << BigInt(opts.maxBits - 1);
|
|
906
|
+
while ((bigValue & msb) === 0n && count < BigInt(opts.maxBits)) {
|
|
907
|
+
count++;
|
|
908
|
+
bigValue = leftShift(bigValue, 1n, opts);
|
|
909
|
+
}
|
|
910
|
+
return count;
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Returns bit at specified position
|
|
914
|
+
*/
|
|
915
|
+
function getBit(value, position, options = {}) {
|
|
916
|
+
const opts = { ...DEFAULT_OPTIONS$6, ...options };
|
|
917
|
+
const bigValue = toBigInt(value);
|
|
918
|
+
const bigPosition = toBigInt(position);
|
|
919
|
+
validateNonNegative(bigPosition);
|
|
920
|
+
if (opts.strict && bigPosition >= BigInt(opts.maxBits)) {
|
|
921
|
+
throw new ValidationError$1(`Bit position exceeds maximum of ${opts.maxBits} bits`);
|
|
922
|
+
}
|
|
923
|
+
return (bigValue & (1n << bigPosition)) !== 0n;
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* Sets bit at specified position
|
|
927
|
+
*/
|
|
928
|
+
function setBit(value, position, options = {}) {
|
|
929
|
+
const opts = { ...DEFAULT_OPTIONS$6, ...options };
|
|
930
|
+
const bigValue = toBigInt(value);
|
|
931
|
+
const bigPosition = toBigInt(position);
|
|
932
|
+
validateNonNegative(bigPosition);
|
|
933
|
+
if (opts.strict && bigPosition >= BigInt(opts.maxBits)) {
|
|
934
|
+
throw new ValidationError$1(`Bit position exceeds maximum of ${opts.maxBits} bits`);
|
|
935
|
+
}
|
|
936
|
+
return bigValue | (1n << bigPosition);
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* Clears bit at specified position
|
|
940
|
+
*/
|
|
941
|
+
function clearBit(value, position, options = {}) {
|
|
942
|
+
const opts = { ...DEFAULT_OPTIONS$6, ...options };
|
|
943
|
+
const bigValue = toBigInt(value);
|
|
944
|
+
const bigPosition = toBigInt(position);
|
|
945
|
+
validateNonNegative(bigPosition);
|
|
946
|
+
if (opts.strict && bigPosition >= BigInt(opts.maxBits)) {
|
|
947
|
+
throw new ValidationError$1(`Bit position exceeds maximum of ${opts.maxBits} bits`);
|
|
948
|
+
}
|
|
949
|
+
return bigValue & ~(1n << bigPosition);
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Toggles bit at specified position
|
|
953
|
+
*/
|
|
954
|
+
function toggleBit(value, position, options = {}) {
|
|
955
|
+
const opts = { ...DEFAULT_OPTIONS$6, ...options };
|
|
956
|
+
const bigValue = toBigInt(value);
|
|
957
|
+
const bigPosition = toBigInt(position);
|
|
958
|
+
validateNonNegative(bigPosition);
|
|
959
|
+
if (opts.strict && bigPosition >= BigInt(opts.maxBits)) {
|
|
960
|
+
throw new ValidationError$1(`Bit position exceeds maximum of ${opts.maxBits} bits`);
|
|
961
|
+
}
|
|
962
|
+
return bigValue ^ (1n << bigPosition);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* Power operations module for Hypernum library
|
|
967
|
+
* Provides efficient implementations for exponentiation and related operations
|
|
968
|
+
*/
|
|
969
|
+
const DEFAULT_OPTIONS$5 = {
|
|
970
|
+
precision: 0,
|
|
971
|
+
roundingMode: RoundingMode.HALF_EVEN,
|
|
972
|
+
checkOverflow: true,
|
|
973
|
+
maxSteps: 1000
|
|
974
|
+
};
|
|
975
|
+
/**
|
|
976
|
+
* Raises a number to an integer power using binary exponentiation
|
|
977
|
+
*/
|
|
978
|
+
function power(baseValue, exponentValue, options = {}) {
|
|
979
|
+
const opts = { ...DEFAULT_OPTIONS$5, ...options };
|
|
980
|
+
const bigBase = toBigInt(baseValue);
|
|
981
|
+
const bigExponent = toBigInt(exponentValue);
|
|
982
|
+
// Handle special cases
|
|
983
|
+
if (bigExponent === 0n) {
|
|
984
|
+
return 1n;
|
|
985
|
+
}
|
|
986
|
+
if (bigExponent === 1n) {
|
|
987
|
+
return bigBase;
|
|
988
|
+
}
|
|
989
|
+
if (bigBase === 0n && bigExponent < 0n) {
|
|
990
|
+
throw new ValidationError$1('Zero cannot be raised to a negative power');
|
|
991
|
+
}
|
|
992
|
+
if (bigBase === 0n) {
|
|
993
|
+
return 0n;
|
|
994
|
+
}
|
|
995
|
+
if (bigBase === 1n) {
|
|
996
|
+
return 1n;
|
|
997
|
+
}
|
|
998
|
+
if (bigBase === -1n) {
|
|
999
|
+
return bigExponent % 2n === 0n ? 1n : -1n;
|
|
1000
|
+
}
|
|
1001
|
+
// Validate inputs
|
|
1002
|
+
if (bigExponent < 0n) {
|
|
1003
|
+
throw new ValidationError$1('Negative exponents not supported for integer power');
|
|
1004
|
+
}
|
|
1005
|
+
if (opts.checkOverflow) {
|
|
1006
|
+
checkPowerOverflow(bigBase, bigExponent);
|
|
1007
|
+
}
|
|
1008
|
+
// Binary exponentiation algorithm
|
|
1009
|
+
let result = 1n;
|
|
1010
|
+
let base = bigBase;
|
|
1011
|
+
let exponent = bigExponent;
|
|
1012
|
+
let steps = 0;
|
|
1013
|
+
while (exponent > 0n) {
|
|
1014
|
+
if (steps++ > opts.maxSteps) {
|
|
1015
|
+
throw new OverflowError('Power operation exceeded maximum computation steps');
|
|
1016
|
+
}
|
|
1017
|
+
if (exponent & 1n) {
|
|
1018
|
+
result *= base;
|
|
1019
|
+
}
|
|
1020
|
+
base *= base;
|
|
1021
|
+
exponent >>= 1n;
|
|
1022
|
+
}
|
|
1023
|
+
if (opts.precision > 0) {
|
|
1024
|
+
return round(result, opts.precision, opts.roundingMode);
|
|
1025
|
+
}
|
|
1026
|
+
return result;
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Calculates square root using Newton's method
|
|
1030
|
+
*/
|
|
1031
|
+
function sqrt(value, options = {}) {
|
|
1032
|
+
const opts = { ...DEFAULT_OPTIONS$5, ...options };
|
|
1033
|
+
const bigValue = toBigInt(value);
|
|
1034
|
+
validateNonNegative(bigValue);
|
|
1035
|
+
if (bigValue === 0n) {
|
|
1036
|
+
return 0n;
|
|
1037
|
+
}
|
|
1038
|
+
if (bigValue === 1n) {
|
|
1039
|
+
return 1n;
|
|
1040
|
+
}
|
|
1041
|
+
// Newton's method for square root
|
|
1042
|
+
let guess = bigValue >> 1n;
|
|
1043
|
+
let lastGuess;
|
|
1044
|
+
let steps = 0;
|
|
1045
|
+
do {
|
|
1046
|
+
if (steps++ > opts.maxSteps) {
|
|
1047
|
+
throw new OverflowError('Square root operation exceeded maximum computation steps');
|
|
1048
|
+
}
|
|
1049
|
+
lastGuess = guess;
|
|
1050
|
+
guess = (guess + bigValue / guess) >> 1n;
|
|
1051
|
+
} while (guess < lastGuess);
|
|
1052
|
+
if (opts.precision > 0) {
|
|
1053
|
+
return round(lastGuess, opts.precision, opts.roundingMode);
|
|
1054
|
+
}
|
|
1055
|
+
return lastGuess;
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* Calculates nth root using Newton's method
|
|
1059
|
+
*/
|
|
1060
|
+
function nthRoot(value, n, options = {}) {
|
|
1061
|
+
const opts = { ...DEFAULT_OPTIONS$5, ...options };
|
|
1062
|
+
const bigValue = toBigInt(value);
|
|
1063
|
+
const bigN = toBigInt(n);
|
|
1064
|
+
validateNonNegative(bigValue);
|
|
1065
|
+
if (bigN <= 0n) {
|
|
1066
|
+
throw new ValidationError$1('Root index must be positive');
|
|
1067
|
+
}
|
|
1068
|
+
if (bigValue === 0n) {
|
|
1069
|
+
return 0n;
|
|
1070
|
+
}
|
|
1071
|
+
if (bigValue === 1n) {
|
|
1072
|
+
return 1n;
|
|
1073
|
+
}
|
|
1074
|
+
if (bigN === 1n) {
|
|
1075
|
+
return bigValue;
|
|
1076
|
+
}
|
|
1077
|
+
if (bigN === 2n) {
|
|
1078
|
+
return sqrt(bigValue, opts);
|
|
1079
|
+
}
|
|
1080
|
+
// Newton's method for nth root
|
|
1081
|
+
let guess = bigValue >> 1n;
|
|
1082
|
+
let lastGuess;
|
|
1083
|
+
let steps = 0;
|
|
1084
|
+
const nMinus1 = bigN - 1n;
|
|
1085
|
+
do {
|
|
1086
|
+
if (steps++ > opts.maxSteps) {
|
|
1087
|
+
throw new OverflowError('Nth root operation exceeded maximum computation steps');
|
|
1088
|
+
}
|
|
1089
|
+
lastGuess = guess;
|
|
1090
|
+
const powered = power(guess, nMinus1, opts);
|
|
1091
|
+
guess = ((nMinus1 * guess) + (bigValue / powered)) / bigN;
|
|
1092
|
+
} while (guess < lastGuess);
|
|
1093
|
+
if (opts.precision > 0) {
|
|
1094
|
+
return round(lastGuess, opts.precision, opts.roundingMode);
|
|
1095
|
+
}
|
|
1096
|
+
return lastGuess;
|
|
1097
|
+
}
|
|
1098
|
+
/**
|
|
1099
|
+
* Calculates tetration (repeated exponentiation)
|
|
1100
|
+
* a↑↑n = a^(a^(a^...)) (n times)
|
|
1101
|
+
*/
|
|
1102
|
+
function tetration(base, height, options = {}) {
|
|
1103
|
+
const opts = { ...DEFAULT_OPTIONS$5, ...options };
|
|
1104
|
+
const bigBase = toBigInt(base);
|
|
1105
|
+
const bigHeight = toBigInt(height);
|
|
1106
|
+
validateNonNegative(bigHeight);
|
|
1107
|
+
if (bigHeight === 0n) {
|
|
1108
|
+
return 1n;
|
|
1109
|
+
}
|
|
1110
|
+
if (bigHeight === 1n) {
|
|
1111
|
+
return bigBase;
|
|
1112
|
+
}
|
|
1113
|
+
if (bigBase === 0n) {
|
|
1114
|
+
return bigHeight % 2n === 0n ? 1n : 0n;
|
|
1115
|
+
}
|
|
1116
|
+
if (bigBase === 1n) {
|
|
1117
|
+
return 1n;
|
|
1118
|
+
}
|
|
1119
|
+
if (bigBase === 2n && bigHeight > 4n) {
|
|
1120
|
+
throw new OverflowError('Tetration would overflow for base 2 and height > 4');
|
|
1121
|
+
}
|
|
1122
|
+
let result = bigBase;
|
|
1123
|
+
let steps = 0;
|
|
1124
|
+
for (let i = 1n; i < bigHeight; i++) {
|
|
1125
|
+
if (steps++ > opts.maxSteps) {
|
|
1126
|
+
throw new OverflowError('Tetration operation exceeded maximum computation steps');
|
|
1127
|
+
}
|
|
1128
|
+
result = power(bigBase, result, opts);
|
|
1129
|
+
}
|
|
1130
|
+
if (opts.precision > 0) {
|
|
1131
|
+
return round(result, opts.precision, opts.roundingMode);
|
|
1132
|
+
}
|
|
1133
|
+
return result;
|
|
1134
|
+
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Calculates super-root (inverse tetration)
|
|
1137
|
+
* Finds x where x↑↑n = value
|
|
1138
|
+
*/
|
|
1139
|
+
function superRoot(value, height, options = {}) {
|
|
1140
|
+
const opts = { ...DEFAULT_OPTIONS$5, ...options };
|
|
1141
|
+
const bigValue = toBigInt(value);
|
|
1142
|
+
const bigHeight = toBigInt(height);
|
|
1143
|
+
validateNonNegative(bigHeight);
|
|
1144
|
+
if (bigHeight === 0n) {
|
|
1145
|
+
throw new ValidationError$1('Height cannot be zero for super-root');
|
|
1146
|
+
}
|
|
1147
|
+
if (bigValue < 1n) {
|
|
1148
|
+
throw new ValidationError$1('Value must be at least 1 for super-root');
|
|
1149
|
+
}
|
|
1150
|
+
if (bigValue === 1n) {
|
|
1151
|
+
return 1n;
|
|
1152
|
+
}
|
|
1153
|
+
if (bigHeight === 1n) {
|
|
1154
|
+
return bigValue;
|
|
1155
|
+
}
|
|
1156
|
+
// Binary search for super-root
|
|
1157
|
+
let left = 1n;
|
|
1158
|
+
let right = bigValue;
|
|
1159
|
+
let steps = 0;
|
|
1160
|
+
while (left <= right) {
|
|
1161
|
+
if (steps++ > opts.maxSteps) {
|
|
1162
|
+
throw new OverflowError('Super-root operation exceeded maximum computation steps');
|
|
1163
|
+
}
|
|
1164
|
+
const mid = (left + right) >> 1n;
|
|
1165
|
+
try {
|
|
1166
|
+
const test = tetration(mid, bigHeight, opts);
|
|
1167
|
+
if (test === bigValue) {
|
|
1168
|
+
return mid;
|
|
1169
|
+
}
|
|
1170
|
+
if (test < bigValue) {
|
|
1171
|
+
left = mid + 1n;
|
|
1172
|
+
}
|
|
1173
|
+
else {
|
|
1174
|
+
right = mid - 1n;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
catch (error) {
|
|
1178
|
+
right = mid - 1n;
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
if (opts.precision > 0) {
|
|
1182
|
+
return round(right, opts.precision, opts.roundingMode);
|
|
1183
|
+
}
|
|
1184
|
+
return right;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
/**
|
|
1188
|
+
* Abstract base heap class implementing common heap operations
|
|
1189
|
+
*/
|
|
1190
|
+
class Heap {
|
|
1191
|
+
constructor(comparator) {
|
|
1192
|
+
this.heap = [];
|
|
1193
|
+
this.compare = comparator;
|
|
1194
|
+
}
|
|
1195
|
+
/**
|
|
1196
|
+
* Gets the size of the heap
|
|
1197
|
+
*/
|
|
1198
|
+
size() {
|
|
1199
|
+
return this.heap.length;
|
|
1200
|
+
}
|
|
1201
|
+
/**
|
|
1202
|
+
* Checks if the heap is empty
|
|
1203
|
+
*/
|
|
1204
|
+
isEmpty() {
|
|
1205
|
+
return this.heap.length === 0;
|
|
1206
|
+
}
|
|
1207
|
+
/**
|
|
1208
|
+
* Peeks at the root element without removing it
|
|
1209
|
+
*/
|
|
1210
|
+
peek() {
|
|
1211
|
+
return this.heap[0];
|
|
1212
|
+
}
|
|
1213
|
+
/**
|
|
1214
|
+
* Inserts a new element into the heap
|
|
1215
|
+
*/
|
|
1216
|
+
push(value) {
|
|
1217
|
+
this.heap.push(value);
|
|
1218
|
+
this.siftUp(this.heap.length - 1);
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* Removes and returns the root element
|
|
1222
|
+
*/
|
|
1223
|
+
pop() {
|
|
1224
|
+
if (this.isEmpty()) {
|
|
1225
|
+
return undefined;
|
|
1226
|
+
}
|
|
1227
|
+
const root = this.heap[0];
|
|
1228
|
+
const last = this.heap.pop();
|
|
1229
|
+
if (!this.isEmpty()) {
|
|
1230
|
+
this.heap[0] = last;
|
|
1231
|
+
this.siftDown(0);
|
|
1232
|
+
}
|
|
1233
|
+
return root;
|
|
1234
|
+
}
|
|
1235
|
+
/**
|
|
1236
|
+
* Removes all elements from the heap
|
|
1237
|
+
*/
|
|
1238
|
+
clear() {
|
|
1239
|
+
this.heap = [];
|
|
1240
|
+
}
|
|
1241
|
+
/**
|
|
1242
|
+
* Creates a heap from an array of elements
|
|
1243
|
+
*/
|
|
1244
|
+
static heapify(array, comparator) {
|
|
1245
|
+
const heap = this instanceof MinHeap ? new MinHeap(comparator) : new MaxHeap(comparator);
|
|
1246
|
+
array.forEach(item => heap.push(item));
|
|
1247
|
+
return heap;
|
|
1248
|
+
}
|
|
1249
|
+
/**
|
|
1250
|
+
* Gets the parent index of a node
|
|
1251
|
+
*/
|
|
1252
|
+
getParentIndex(index) {
|
|
1253
|
+
return Math.floor((index - 1) / 2);
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Gets the left child index of a node
|
|
1257
|
+
*/
|
|
1258
|
+
getLeftChildIndex(index) {
|
|
1259
|
+
return 2 * index + 1;
|
|
1260
|
+
}
|
|
1261
|
+
/**
|
|
1262
|
+
* Gets the right child index of a node
|
|
1263
|
+
*/
|
|
1264
|
+
getRightChildIndex(index) {
|
|
1265
|
+
return 2 * index + 2;
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Swaps two elements in the heap
|
|
1269
|
+
*/
|
|
1270
|
+
swap(i, j) {
|
|
1271
|
+
const temp = this.heap[i];
|
|
1272
|
+
this.heap[i] = this.heap[j];
|
|
1273
|
+
this.heap[j] = temp;
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
/**
|
|
1277
|
+
* MinHeap implementation where the root is the smallest element
|
|
1278
|
+
*/
|
|
1279
|
+
class MinHeap extends Heap {
|
|
1280
|
+
constructor(comparator) {
|
|
1281
|
+
super(comparator);
|
|
1282
|
+
}
|
|
1283
|
+
siftUp(index) {
|
|
1284
|
+
while (index > 0) {
|
|
1285
|
+
const parentIndex = this.getParentIndex(index);
|
|
1286
|
+
if (this.compare(this.heap[index], this.heap[parentIndex]) >= 0) {
|
|
1287
|
+
break;
|
|
1288
|
+
}
|
|
1289
|
+
this.swap(index, parentIndex);
|
|
1290
|
+
index = parentIndex;
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
siftDown(index) {
|
|
1294
|
+
const size = this.heap.length;
|
|
1295
|
+
while (true) {
|
|
1296
|
+
let smallest = index;
|
|
1297
|
+
const left = this.getLeftChildIndex(index);
|
|
1298
|
+
const right = this.getRightChildIndex(index);
|
|
1299
|
+
if (left < size && this.compare(this.heap[left], this.heap[smallest]) < 0) {
|
|
1300
|
+
smallest = left;
|
|
1301
|
+
}
|
|
1302
|
+
if (right < size && this.heap[right] !== undefined && this.compare(this.heap[right], this.heap[smallest]) < 0) {
|
|
1303
|
+
smallest = right;
|
|
1304
|
+
}
|
|
1305
|
+
if (smallest === index) {
|
|
1306
|
+
break;
|
|
1307
|
+
}
|
|
1308
|
+
this.swap(index, smallest);
|
|
1309
|
+
index = smallest;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
/**
|
|
1314
|
+
* MaxHeap implementation where the root is the largest element
|
|
1315
|
+
*/
|
|
1316
|
+
class MaxHeap extends Heap {
|
|
1317
|
+
constructor(comparator) {
|
|
1318
|
+
super(comparator);
|
|
1319
|
+
}
|
|
1320
|
+
siftUp(index) {
|
|
1321
|
+
while (index > 0) {
|
|
1322
|
+
const parentIndex = this.getParentIndex(index);
|
|
1323
|
+
if (this.compare(this.heap[index], this.heap[parentIndex]) <= 0) {
|
|
1324
|
+
break;
|
|
1325
|
+
}
|
|
1326
|
+
this.swap(index, parentIndex);
|
|
1327
|
+
index = parentIndex;
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
siftDown(index) {
|
|
1331
|
+
const size = this.heap.length;
|
|
1332
|
+
while (true) {
|
|
1333
|
+
let largest = index;
|
|
1334
|
+
const left = this.getLeftChildIndex(index);
|
|
1335
|
+
const right = this.getRightChildIndex(index);
|
|
1336
|
+
if (left < size && this.heap[left] !== undefined && this.compare(this.heap[left], this.heap[largest]) > 0) {
|
|
1337
|
+
largest = left;
|
|
1338
|
+
}
|
|
1339
|
+
if (right < size && this.heap[right] !== undefined && this.compare(this.heap[right], this.heap[largest]) > 0) {
|
|
1340
|
+
largest = right;
|
|
1341
|
+
}
|
|
1342
|
+
if (largest === index) {
|
|
1343
|
+
break;
|
|
1344
|
+
}
|
|
1345
|
+
this.swap(index, largest);
|
|
1346
|
+
index = largest;
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
/**
|
|
1351
|
+
* Custom comparator for large numbers
|
|
1352
|
+
*/
|
|
1353
|
+
function createLargeNumberComparator() {
|
|
1354
|
+
return (a, b) => {
|
|
1355
|
+
return a > b ? 1 : a < b ? -1 : 0;
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
/**
|
|
1360
|
+
* Class representing the Ackermann function computation structure
|
|
1361
|
+
* Implements caching and relationship tracking between values
|
|
1362
|
+
*/
|
|
1363
|
+
class AckermannStructure {
|
|
1364
|
+
constructor() {
|
|
1365
|
+
this.nodes = new Map();
|
|
1366
|
+
this.maxComputedM = -1;
|
|
1367
|
+
this.maxComputedN = -1;
|
|
1368
|
+
this.heap = new MaxHeap(createLargeNumberComparator());
|
|
1369
|
+
}
|
|
1370
|
+
/**
|
|
1371
|
+
* Generates a unique key for node storage
|
|
1372
|
+
*/
|
|
1373
|
+
static getNodeKey(m, n) {
|
|
1374
|
+
return `${m},${n}`;
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* Computes the Ackermann function value
|
|
1378
|
+
* Uses recursion with memoization
|
|
1379
|
+
*/
|
|
1380
|
+
computeAckermann(m, n) {
|
|
1381
|
+
// Handle invalid inputs
|
|
1382
|
+
if (m < 0 || n < 0) {
|
|
1383
|
+
throw new Error('Ackermann function undefined for negative numbers');
|
|
1384
|
+
}
|
|
1385
|
+
// Check if already computed
|
|
1386
|
+
const key = AckermannStructure.getNodeKey(m, n);
|
|
1387
|
+
const existing = this.nodes.get(key);
|
|
1388
|
+
if (existing) {
|
|
1389
|
+
return existing.value;
|
|
1390
|
+
}
|
|
1391
|
+
// Compute based on Ackermann function definition
|
|
1392
|
+
let value;
|
|
1393
|
+
try {
|
|
1394
|
+
if (m === 0) {
|
|
1395
|
+
value = BigInt(n + 1);
|
|
1396
|
+
}
|
|
1397
|
+
else if (n === 0) {
|
|
1398
|
+
value = this.computeAckermann(m - 1, 1);
|
|
1399
|
+
}
|
|
1400
|
+
else {
|
|
1401
|
+
const inner = this.computeAckermann(m, n - 1);
|
|
1402
|
+
// Convert bigint to number for recursion, being careful about size
|
|
1403
|
+
const innerNum = inner <= BigInt(Number.MAX_SAFE_INTEGER)
|
|
1404
|
+
? Number(inner)
|
|
1405
|
+
: Number.MAX_SAFE_INTEGER;
|
|
1406
|
+
value = this.computeAckermann(m - 1, innerNum);
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
catch (error) {
|
|
1410
|
+
// Handle stack overflow or computation limits
|
|
1411
|
+
if (error instanceof RangeError) {
|
|
1412
|
+
return BigInt(Number.MAX_SAFE_INTEGER);
|
|
1413
|
+
}
|
|
1414
|
+
throw error;
|
|
1415
|
+
}
|
|
1416
|
+
return value;
|
|
1417
|
+
}
|
|
1418
|
+
/**
|
|
1419
|
+
* Adds a new node to the structure
|
|
1420
|
+
*/
|
|
1421
|
+
addNode(m, n) {
|
|
1422
|
+
const key = AckermannStructure.getNodeKey(m, n);
|
|
1423
|
+
if (this.nodes.has(key)) {
|
|
1424
|
+
return this.nodes.get(key);
|
|
1425
|
+
}
|
|
1426
|
+
// Create new node
|
|
1427
|
+
const value = this.computeAckermann(m, n);
|
|
1428
|
+
const node = { m, n, value };
|
|
1429
|
+
this.nodes.set(key, node);
|
|
1430
|
+
// Link to existing nodes
|
|
1431
|
+
const prevMKey = AckermannStructure.getNodeKey(m - 1, n);
|
|
1432
|
+
const prevNKey = AckermannStructure.getNodeKey(m, n - 1);
|
|
1433
|
+
if (this.nodes.has(prevMKey)) {
|
|
1434
|
+
const prevM = this.nodes.get(prevMKey);
|
|
1435
|
+
node.prevM = prevM;
|
|
1436
|
+
prevM.nextM = node;
|
|
1437
|
+
}
|
|
1438
|
+
if (this.nodes.has(prevNKey)) {
|
|
1439
|
+
const prevN = this.nodes.get(prevNKey);
|
|
1440
|
+
node.prevN = prevN;
|
|
1441
|
+
prevN.nextN = node;
|
|
1442
|
+
}
|
|
1443
|
+
// Update tracking
|
|
1444
|
+
this.maxComputedM = Math.max(this.maxComputedM, m);
|
|
1445
|
+
this.maxComputedN = Math.max(this.maxComputedN, n);
|
|
1446
|
+
this.heap.push(value);
|
|
1447
|
+
return node;
|
|
1448
|
+
}
|
|
1449
|
+
/**
|
|
1450
|
+
* Builds nodes for a range of m and n values
|
|
1451
|
+
*/
|
|
1452
|
+
buildRange(mRange, nRange) {
|
|
1453
|
+
for (let m = 0; m <= mRange; m++) {
|
|
1454
|
+
for (let n = 0; n <= nRange; n++) {
|
|
1455
|
+
this.addNode(m, n);
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
/**
|
|
1460
|
+
* Gets the computation path to reach A(m,n)
|
|
1461
|
+
*/
|
|
1462
|
+
getComputationPath(m, n) {
|
|
1463
|
+
const path = [];
|
|
1464
|
+
const key = AckermannStructure.getNodeKey(m, n);
|
|
1465
|
+
let current = this.nodes.get(key);
|
|
1466
|
+
while (current) {
|
|
1467
|
+
path.push({
|
|
1468
|
+
m: current.m,
|
|
1469
|
+
n: current.n,
|
|
1470
|
+
value: current.value
|
|
1471
|
+
});
|
|
1472
|
+
// Follow computation path backwards
|
|
1473
|
+
if (current.m === 0) {
|
|
1474
|
+
break;
|
|
1475
|
+
}
|
|
1476
|
+
else if (current.n === 0) {
|
|
1477
|
+
current = this.nodes.get(AckermannStructure.getNodeKey(current.m - 1, 1));
|
|
1478
|
+
}
|
|
1479
|
+
else {
|
|
1480
|
+
const prevN = this.nodes.get(AckermannStructure.getNodeKey(current.m, current.n - 1));
|
|
1481
|
+
if (prevN) {
|
|
1482
|
+
path.push({
|
|
1483
|
+
m: prevN.m,
|
|
1484
|
+
n: prevN.n,
|
|
1485
|
+
value: prevN.value
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
// Convert bigint to number safely for the next lookup
|
|
1489
|
+
const nextValue = prevN?.value ?? BigInt(0);
|
|
1490
|
+
const safeNextValue = nextValue <= BigInt(Number.MAX_SAFE_INTEGER)
|
|
1491
|
+
? Number(nextValue)
|
|
1492
|
+
: Number.MAX_SAFE_INTEGER;
|
|
1493
|
+
current = this.nodes.get(AckermannStructure.getNodeKey(current.m - 1, safeNextValue));
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
return path.reverse();
|
|
1497
|
+
}
|
|
1498
|
+
/**
|
|
1499
|
+
* Analyzes growth rate for a fixed m value
|
|
1500
|
+
*/
|
|
1501
|
+
analyzeGrowthRate(m) {
|
|
1502
|
+
const growth = new Map();
|
|
1503
|
+
let prevValue = BigInt(1);
|
|
1504
|
+
for (let n = 0; n <= this.maxComputedN; n++) {
|
|
1505
|
+
const key = AckermannStructure.getNodeKey(m, n);
|
|
1506
|
+
const node = this.nodes.get(key);
|
|
1507
|
+
if (!node || node.value >= BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
1508
|
+
break;
|
|
1509
|
+
}
|
|
1510
|
+
growth.set(n, {
|
|
1511
|
+
value: node.value,
|
|
1512
|
+
increase: node.value - prevValue,
|
|
1513
|
+
multiplier: prevValue === BigInt(0) ? BigInt(0) : node.value / prevValue
|
|
1514
|
+
});
|
|
1515
|
+
prevValue = node.value;
|
|
1516
|
+
}
|
|
1517
|
+
return growth;
|
|
1518
|
+
}
|
|
1519
|
+
/**
|
|
1520
|
+
* Gets the largest computed value
|
|
1521
|
+
*/
|
|
1522
|
+
getLargestValue() {
|
|
1523
|
+
return this.heap.peek() ?? BigInt(0);
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* Gets a specific Ackermann value if it exists
|
|
1527
|
+
*/
|
|
1528
|
+
getValue(m, n) {
|
|
1529
|
+
return this.nodes.get(AckermannStructure.getNodeKey(m, n))?.value;
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
/**
|
|
1534
|
+
* A specialized array implementation for handling large numbers and providing
|
|
1535
|
+
* efficient operations with segment tree support
|
|
1536
|
+
*/
|
|
1537
|
+
class BigArray {
|
|
1538
|
+
constructor(options = {}) {
|
|
1539
|
+
const { initialCapacity = 16, growthFactor = 2, comparator = ((a, b) => {
|
|
1540
|
+
if (a < b)
|
|
1541
|
+
return -1;
|
|
1542
|
+
if (a > b)
|
|
1543
|
+
return 1;
|
|
1544
|
+
return 0;
|
|
1545
|
+
}) } = options;
|
|
1546
|
+
this.capacity = initialCapacity;
|
|
1547
|
+
this.growthFactor = growthFactor;
|
|
1548
|
+
this.comparator = comparator;
|
|
1549
|
+
this.size = 0;
|
|
1550
|
+
this.data = new Array(this.capacity);
|
|
1551
|
+
this.segmentTree = new Array(4 * this.capacity).fill(null);
|
|
1552
|
+
}
|
|
1553
|
+
/**
|
|
1554
|
+
* Gets the current size of the array
|
|
1555
|
+
*/
|
|
1556
|
+
getSize() {
|
|
1557
|
+
return this.size;
|
|
1558
|
+
}
|
|
1559
|
+
/**
|
|
1560
|
+
* Gets the current capacity of the array
|
|
1561
|
+
*/
|
|
1562
|
+
getCapacity() {
|
|
1563
|
+
return this.capacity;
|
|
1564
|
+
}
|
|
1565
|
+
/**
|
|
1566
|
+
* Resizes the internal array when needed
|
|
1567
|
+
*/
|
|
1568
|
+
resize(newCapacity) {
|
|
1569
|
+
const newData = new Array(newCapacity);
|
|
1570
|
+
for (let i = 0; i < this.size; i++) {
|
|
1571
|
+
newData[i] = this.data[i];
|
|
1572
|
+
}
|
|
1573
|
+
this.data = newData;
|
|
1574
|
+
this.capacity = newCapacity;
|
|
1575
|
+
this.rebuildSegmentTree();
|
|
1576
|
+
}
|
|
1577
|
+
/**
|
|
1578
|
+
* Appends an element to the end of the array
|
|
1579
|
+
*/
|
|
1580
|
+
push(value) {
|
|
1581
|
+
try {
|
|
1582
|
+
if (this.size >= this.capacity) {
|
|
1583
|
+
this.resize(this.capacity * this.growthFactor);
|
|
1584
|
+
}
|
|
1585
|
+
this.data[this.size] = value;
|
|
1586
|
+
this.updateSegmentTree(0, this.size, value);
|
|
1587
|
+
this.size++;
|
|
1588
|
+
return { success: true, value: this.size - 1 };
|
|
1589
|
+
}
|
|
1590
|
+
catch (error) {
|
|
1591
|
+
return {
|
|
1592
|
+
success: false,
|
|
1593
|
+
error: error instanceof Error ? error.message : 'Unknown error during push'
|
|
1594
|
+
};
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
/**
|
|
1598
|
+
* Removes and returns the last element
|
|
1599
|
+
*/
|
|
1600
|
+
pop() {
|
|
1601
|
+
if (this.size === 0) {
|
|
1602
|
+
return { success: false, error: 'Array is empty' };
|
|
1603
|
+
}
|
|
1604
|
+
const value = this.data[this.size - 1];
|
|
1605
|
+
this.size--;
|
|
1606
|
+
// Shrink array if it's too sparse
|
|
1607
|
+
if (this.size < this.capacity / (this.growthFactor * 2)) {
|
|
1608
|
+
this.resize(Math.max(16, Math.floor(this.capacity / this.growthFactor)));
|
|
1609
|
+
}
|
|
1610
|
+
return { success: true, value };
|
|
1611
|
+
}
|
|
1612
|
+
/**
|
|
1613
|
+
* Gets element at specified index
|
|
1614
|
+
*/
|
|
1615
|
+
get(index) {
|
|
1616
|
+
if (index < 0 || index >= this.size) {
|
|
1617
|
+
return { success: false, error: 'Index out of bounds' };
|
|
1618
|
+
}
|
|
1619
|
+
return { success: true, value: this.data[index] };
|
|
1620
|
+
}
|
|
1621
|
+
/**
|
|
1622
|
+
* Sets element at specified index
|
|
1623
|
+
*/
|
|
1624
|
+
set(index, value) {
|
|
1625
|
+
if (index < 0 || index >= this.size) {
|
|
1626
|
+
return { success: false, error: 'Index out of bounds' };
|
|
1627
|
+
}
|
|
1628
|
+
const oldValue = this.data[index];
|
|
1629
|
+
this.data[index] = value;
|
|
1630
|
+
this.updateSegmentTree(0, index, value);
|
|
1631
|
+
return { success: true, value: oldValue };
|
|
1632
|
+
}
|
|
1633
|
+
/**
|
|
1634
|
+
* Rebuilds the segment tree after major changes
|
|
1635
|
+
*/
|
|
1636
|
+
rebuildSegmentTree() {
|
|
1637
|
+
this.segmentTree = new Array(4 * this.capacity).fill(null);
|
|
1638
|
+
if (this.size > 0) {
|
|
1639
|
+
this.buildSegmentTree(0, 0, this.size - 1);
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
/**
|
|
1643
|
+
* Builds a segment tree node recursively
|
|
1644
|
+
*/
|
|
1645
|
+
buildSegmentTree(node, start, end) {
|
|
1646
|
+
if (start === end) {
|
|
1647
|
+
this.segmentTree[node] = {
|
|
1648
|
+
value: this.data[start],
|
|
1649
|
+
start,
|
|
1650
|
+
end
|
|
1651
|
+
};
|
|
1652
|
+
return;
|
|
1653
|
+
}
|
|
1654
|
+
const mid = Math.floor((start + end) / 2);
|
|
1655
|
+
this.buildSegmentTree(2 * node + 1, start, mid);
|
|
1656
|
+
this.buildSegmentTree(2 * node + 2, mid + 1, end);
|
|
1657
|
+
const leftNode = this.segmentTree[2 * node + 1];
|
|
1658
|
+
const rightNode = this.segmentTree[2 * node + 2];
|
|
1659
|
+
if (leftNode && rightNode) {
|
|
1660
|
+
this.segmentTree[node] = {
|
|
1661
|
+
value: this.comparator(leftNode.value, rightNode.value) >= 0
|
|
1662
|
+
? leftNode.value
|
|
1663
|
+
: rightNode.value,
|
|
1664
|
+
start,
|
|
1665
|
+
end
|
|
1666
|
+
};
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
/**
|
|
1670
|
+
* Updates the segment tree after a value change
|
|
1671
|
+
*/
|
|
1672
|
+
updateSegmentTree(node, index, value) {
|
|
1673
|
+
if (!this.segmentTree[node]) {
|
|
1674
|
+
return;
|
|
1675
|
+
}
|
|
1676
|
+
const currentNode = this.segmentTree[node];
|
|
1677
|
+
if (currentNode.start === currentNode.end) {
|
|
1678
|
+
currentNode.value = value;
|
|
1679
|
+
return;
|
|
1680
|
+
}
|
|
1681
|
+
const mid = Math.floor((currentNode.start + currentNode.end) / 2);
|
|
1682
|
+
if (index <= mid) {
|
|
1683
|
+
this.updateSegmentTree(2 * node + 1, index, value);
|
|
1684
|
+
}
|
|
1685
|
+
else {
|
|
1686
|
+
this.updateSegmentTree(2 * node + 2, index, value);
|
|
1687
|
+
}
|
|
1688
|
+
const leftNode = this.segmentTree[2 * node + 1];
|
|
1689
|
+
const rightNode = this.segmentTree[2 * node + 2];
|
|
1690
|
+
if (leftNode && rightNode) {
|
|
1691
|
+
currentNode.value = this.comparator(leftNode.value, rightNode.value) >= 0
|
|
1692
|
+
? leftNode.value
|
|
1693
|
+
: rightNode.value;
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
/**
|
|
1697
|
+
* Queries the maximum value in a range
|
|
1698
|
+
*/
|
|
1699
|
+
queryRange(start, end) {
|
|
1700
|
+
if (start < 0 || end >= this.size || start > end) {
|
|
1701
|
+
return { success: false, error: 'Invalid range' };
|
|
1702
|
+
}
|
|
1703
|
+
const result = this.querySegmentTree(0, start, end);
|
|
1704
|
+
return result
|
|
1705
|
+
? { success: true, value: result }
|
|
1706
|
+
: { success: false, error: 'Range query failed' };
|
|
1707
|
+
}
|
|
1708
|
+
/**
|
|
1709
|
+
* Recursively queries the segment tree
|
|
1710
|
+
*/
|
|
1711
|
+
querySegmentTree(node, queryStart, queryEnd) {
|
|
1712
|
+
const currentNode = this.segmentTree[node];
|
|
1713
|
+
if (!currentNode) {
|
|
1714
|
+
return null;
|
|
1715
|
+
}
|
|
1716
|
+
if (queryStart <= currentNode.start && queryEnd >= currentNode.end) {
|
|
1717
|
+
return currentNode.value;
|
|
1718
|
+
}
|
|
1719
|
+
if (queryEnd < currentNode.start || queryStart > currentNode.end) {
|
|
1720
|
+
return null;
|
|
1721
|
+
}
|
|
1722
|
+
const leftResult = this.querySegmentTree(2 * node + 1, queryStart, queryEnd);
|
|
1723
|
+
const rightResult = this.querySegmentTree(2 * node + 2, queryStart, queryEnd);
|
|
1724
|
+
if (leftResult === null)
|
|
1725
|
+
return rightResult;
|
|
1726
|
+
if (rightResult === null)
|
|
1727
|
+
return leftResult;
|
|
1728
|
+
return this.comparator(leftResult, rightResult) >= 0 ? leftResult : rightResult;
|
|
1729
|
+
}
|
|
1730
|
+
/**
|
|
1731
|
+
* Creates a heap from the current array
|
|
1732
|
+
*/
|
|
1733
|
+
toHeap(isMin = true) {
|
|
1734
|
+
const heap = isMin
|
|
1735
|
+
? new MinHeap(this.comparator)
|
|
1736
|
+
: new MaxHeap(this.comparator);
|
|
1737
|
+
for (let i = 0; i < this.size; i++) {
|
|
1738
|
+
if (this.data[i] !== undefined) {
|
|
1739
|
+
if (this.data[i] !== undefined) {
|
|
1740
|
+
heap.push(this.data[i]);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
return heap;
|
|
1745
|
+
}
|
|
1746
|
+
/**
|
|
1747
|
+
* Sorts the array in-place
|
|
1748
|
+
*/
|
|
1749
|
+
sort(ascending = true) {
|
|
1750
|
+
const heap = this.toHeap(!ascending);
|
|
1751
|
+
for (let i = this.size - 1; i >= 0; i--) {
|
|
1752
|
+
const value = heap.pop();
|
|
1753
|
+
if (value !== undefined) {
|
|
1754
|
+
this.data[i] = value;
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
this.rebuildSegmentTree();
|
|
1758
|
+
}
|
|
1759
|
+
/**
|
|
1760
|
+
* Returns array as native array
|
|
1761
|
+
*/
|
|
1762
|
+
toArray() {
|
|
1763
|
+
return this.data.slice(0, this.size);
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
/**
|
|
1768
|
+
* Class representing a node in the number tree
|
|
1769
|
+
*/
|
|
1770
|
+
class NumberNode {
|
|
1771
|
+
constructor(value) {
|
|
1772
|
+
this.value = typeof value === 'bigint' ? value : BigInt(value);
|
|
1773
|
+
this.left = null;
|
|
1774
|
+
this.right = null;
|
|
1775
|
+
this.parent = null;
|
|
1776
|
+
this.height = 1;
|
|
1777
|
+
this.size = 1;
|
|
1778
|
+
this.sum = this.value;
|
|
1779
|
+
}
|
|
1780
|
+
/**
|
|
1781
|
+
* Updates node statistics based on children
|
|
1782
|
+
*/
|
|
1783
|
+
updateStats() {
|
|
1784
|
+
this.height = 1 + Math.max(this.left?.height ?? 0, this.right?.height ?? 0);
|
|
1785
|
+
this.size = 1 + (this.left?.size ?? 0) + (this.right?.size ?? 0);
|
|
1786
|
+
this.sum = this.value +
|
|
1787
|
+
(this.left?.sum ?? BigInt(0)) +
|
|
1788
|
+
(this.right?.sum ?? BigInt(0));
|
|
1789
|
+
}
|
|
1790
|
+
/**
|
|
1791
|
+
* Gets balance factor of the node
|
|
1792
|
+
*/
|
|
1793
|
+
getBalance() {
|
|
1794
|
+
return (this.left?.height ?? 0) - (this.right?.height ?? 0);
|
|
1795
|
+
}
|
|
1796
|
+
/**
|
|
1797
|
+
* Gets complete statistics for the node and its subtree
|
|
1798
|
+
*/
|
|
1799
|
+
getStats() {
|
|
1800
|
+
return {
|
|
1801
|
+
height: this.height,
|
|
1802
|
+
size: this.size,
|
|
1803
|
+
sum: this.sum,
|
|
1804
|
+
min: this.findMin().value,
|
|
1805
|
+
max: this.findMax().value
|
|
1806
|
+
};
|
|
1807
|
+
}
|
|
1808
|
+
/**
|
|
1809
|
+
* Finds minimum value node in the subtree
|
|
1810
|
+
*/
|
|
1811
|
+
findMin() {
|
|
1812
|
+
let current = this;
|
|
1813
|
+
while (current.left) {
|
|
1814
|
+
current = current.left;
|
|
1815
|
+
}
|
|
1816
|
+
return current;
|
|
1817
|
+
}
|
|
1818
|
+
/**
|
|
1819
|
+
* Finds maximum value node in the subtree
|
|
1820
|
+
*/
|
|
1821
|
+
findMax() {
|
|
1822
|
+
let current = this;
|
|
1823
|
+
while (current.right) {
|
|
1824
|
+
current = current.right;
|
|
1825
|
+
}
|
|
1826
|
+
return current;
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
/**
|
|
1830
|
+
* AVL Tree implementation specialized for handling large numbers
|
|
1831
|
+
*/
|
|
1832
|
+
class NumberTree {
|
|
1833
|
+
constructor(comparator) {
|
|
1834
|
+
this.root = null;
|
|
1835
|
+
this.comparator = comparator ?? ((a, b) => {
|
|
1836
|
+
if (a < b)
|
|
1837
|
+
return -1;
|
|
1838
|
+
if (a > b)
|
|
1839
|
+
return 1;
|
|
1840
|
+
return 0;
|
|
1841
|
+
});
|
|
1842
|
+
}
|
|
1843
|
+
/**
|
|
1844
|
+
* Gets the root node if it exists
|
|
1845
|
+
*/
|
|
1846
|
+
getRoot() {
|
|
1847
|
+
return this.root;
|
|
1848
|
+
}
|
|
1849
|
+
/**
|
|
1850
|
+
* Inserts a new value into the tree
|
|
1851
|
+
*/
|
|
1852
|
+
insert(value) {
|
|
1853
|
+
const newValue = typeof value === 'bigint' ? value : BigInt(value);
|
|
1854
|
+
this.root = this.insertNode(this.root, newValue);
|
|
1855
|
+
return this.find(newValue);
|
|
1856
|
+
}
|
|
1857
|
+
/**
|
|
1858
|
+
* Recursively inserts a new node
|
|
1859
|
+
*/
|
|
1860
|
+
insertNode(node, value) {
|
|
1861
|
+
if (!node) {
|
|
1862
|
+
return new NumberNode(value);
|
|
1863
|
+
}
|
|
1864
|
+
const compareResult = this.comparator(value, node.value);
|
|
1865
|
+
if (compareResult < 0) {
|
|
1866
|
+
node.left = this.insertNode(node.left, value);
|
|
1867
|
+
node.left.parent = node;
|
|
1868
|
+
}
|
|
1869
|
+
else if (compareResult > 0) {
|
|
1870
|
+
node.right = this.insertNode(node.right, value);
|
|
1871
|
+
node.right.parent = node;
|
|
1872
|
+
}
|
|
1873
|
+
else {
|
|
1874
|
+
return node; // Duplicate value, return existing node
|
|
1875
|
+
}
|
|
1876
|
+
node.updateStats();
|
|
1877
|
+
return this.balance(node);
|
|
1878
|
+
}
|
|
1879
|
+
/**
|
|
1880
|
+
* Balances a node using AVL rotations
|
|
1881
|
+
*/
|
|
1882
|
+
balance(node) {
|
|
1883
|
+
const balance = node.getBalance();
|
|
1884
|
+
// Left heavy
|
|
1885
|
+
if (balance > 1) {
|
|
1886
|
+
if (node.left && node.left.getBalance() < 0) {
|
|
1887
|
+
node.left = this.rotateLeft(node.left);
|
|
1888
|
+
}
|
|
1889
|
+
return this.rotateRight(node);
|
|
1890
|
+
}
|
|
1891
|
+
// Right heavy
|
|
1892
|
+
if (balance < -1) {
|
|
1893
|
+
if (node.right && node.right.getBalance() > 0) {
|
|
1894
|
+
node.right = this.rotateRight(node.right);
|
|
1895
|
+
}
|
|
1896
|
+
return this.rotateLeft(node);
|
|
1897
|
+
}
|
|
1898
|
+
return node;
|
|
1899
|
+
}
|
|
1900
|
+
/**
|
|
1901
|
+
* Performs left rotation
|
|
1902
|
+
*/
|
|
1903
|
+
rotateLeft(node) {
|
|
1904
|
+
const rightChild = node.right;
|
|
1905
|
+
const rightLeftChild = rightChild.left;
|
|
1906
|
+
rightChild.left = node;
|
|
1907
|
+
node.right = rightLeftChild;
|
|
1908
|
+
if (rightLeftChild) {
|
|
1909
|
+
rightLeftChild.parent = node;
|
|
1910
|
+
}
|
|
1911
|
+
rightChild.parent = node.parent;
|
|
1912
|
+
node.parent = rightChild;
|
|
1913
|
+
node.updateStats();
|
|
1914
|
+
rightChild.updateStats();
|
|
1915
|
+
return rightChild;
|
|
1916
|
+
}
|
|
1917
|
+
/**
|
|
1918
|
+
* Performs right rotation
|
|
1919
|
+
*/
|
|
1920
|
+
rotateRight(node) {
|
|
1921
|
+
const leftChild = node.left;
|
|
1922
|
+
const leftRightChild = leftChild.right;
|
|
1923
|
+
leftChild.right = node;
|
|
1924
|
+
node.left = leftRightChild;
|
|
1925
|
+
if (leftRightChild) {
|
|
1926
|
+
leftRightChild.parent = node;
|
|
1927
|
+
}
|
|
1928
|
+
leftChild.parent = node.parent;
|
|
1929
|
+
node.parent = leftChild;
|
|
1930
|
+
node.updateStats();
|
|
1931
|
+
leftChild.updateStats();
|
|
1932
|
+
return leftChild;
|
|
1933
|
+
}
|
|
1934
|
+
/**
|
|
1935
|
+
* Removes a value from the tree
|
|
1936
|
+
*/
|
|
1937
|
+
remove(value) {
|
|
1938
|
+
const searchValue = typeof value === 'bigint' ? value : BigInt(value);
|
|
1939
|
+
const nodeToRemove = this.find(searchValue);
|
|
1940
|
+
if (!nodeToRemove) {
|
|
1941
|
+
return false;
|
|
1942
|
+
}
|
|
1943
|
+
this.root = this.removeNode(this.root, searchValue);
|
|
1944
|
+
return true;
|
|
1945
|
+
}
|
|
1946
|
+
/**
|
|
1947
|
+
* Recursively removes a node
|
|
1948
|
+
*/
|
|
1949
|
+
removeNode(node, value) {
|
|
1950
|
+
if (!node) {
|
|
1951
|
+
return null;
|
|
1952
|
+
}
|
|
1953
|
+
const compareResult = this.comparator(value, node.value);
|
|
1954
|
+
if (compareResult < 0) {
|
|
1955
|
+
node.left = this.removeNode(node.left, value);
|
|
1956
|
+
if (node.left) {
|
|
1957
|
+
node.left.parent = node;
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
else if (compareResult > 0) {
|
|
1961
|
+
node.right = this.removeNode(node.right, value);
|
|
1962
|
+
if (node.right) {
|
|
1963
|
+
node.right.parent = node;
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
else {
|
|
1967
|
+
// Node to delete found
|
|
1968
|
+
if (!node.left) {
|
|
1969
|
+
return node.right;
|
|
1970
|
+
}
|
|
1971
|
+
if (!node.right) {
|
|
1972
|
+
return node.left;
|
|
1973
|
+
}
|
|
1974
|
+
// Node has two children
|
|
1975
|
+
const successor = node.right.findMin();
|
|
1976
|
+
node.value = successor.value;
|
|
1977
|
+
node.right = this.removeNode(node.right, successor.value);
|
|
1978
|
+
if (node.right) {
|
|
1979
|
+
node.right.parent = node;
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
node.updateStats();
|
|
1983
|
+
return this.balance(node);
|
|
1984
|
+
}
|
|
1985
|
+
/**
|
|
1986
|
+
* Finds a node by value
|
|
1987
|
+
*/
|
|
1988
|
+
find(value) {
|
|
1989
|
+
const searchValue = typeof value === 'bigint' ? value : BigInt(value);
|
|
1990
|
+
let current = this.root;
|
|
1991
|
+
while (current) {
|
|
1992
|
+
const compareResult = this.comparator(searchValue, current.value);
|
|
1993
|
+
if (compareResult === 0) {
|
|
1994
|
+
return current;
|
|
1995
|
+
}
|
|
1996
|
+
current = compareResult < 0 ? current.left : current.right;
|
|
1997
|
+
}
|
|
1998
|
+
return null;
|
|
1999
|
+
}
|
|
2000
|
+
/**
|
|
2001
|
+
* Traverses the tree in specified order and returns values
|
|
2002
|
+
*/
|
|
2003
|
+
traverse(order = 'inOrder', config = {}) {
|
|
2004
|
+
const result = [];
|
|
2005
|
+
const traverse = (node, depth = 0) => {
|
|
2006
|
+
if (!node || (config.maxDepth !== undefined && depth >= config.maxDepth)) {
|
|
2007
|
+
return;
|
|
2008
|
+
}
|
|
2009
|
+
if (order === 'preOrder') {
|
|
2010
|
+
result.push(node.value);
|
|
2011
|
+
}
|
|
2012
|
+
if (!config.skipSubtrees) {
|
|
2013
|
+
traverse(node.left, depth + 1);
|
|
2014
|
+
}
|
|
2015
|
+
if (order === 'inOrder') {
|
|
2016
|
+
result.push(node.value);
|
|
2017
|
+
}
|
|
2018
|
+
if (!config.skipSubtrees) {
|
|
2019
|
+
traverse(node.right, depth + 1);
|
|
2020
|
+
}
|
|
2021
|
+
if (order === 'postOrder') {
|
|
2022
|
+
result.push(node.value);
|
|
2023
|
+
}
|
|
2024
|
+
};
|
|
2025
|
+
traverse(this.root);
|
|
2026
|
+
return result;
|
|
2027
|
+
}
|
|
2028
|
+
/**
|
|
2029
|
+
* Gets overall tree statistics
|
|
2030
|
+
*/
|
|
2031
|
+
getTreeStats() {
|
|
2032
|
+
return this.root?.getStats() ?? null;
|
|
2033
|
+
}
|
|
2034
|
+
/**
|
|
2035
|
+
* Gets the nth smallest value in the tree
|
|
2036
|
+
*/
|
|
2037
|
+
getNthValue(n) {
|
|
2038
|
+
if (!this.root || n < 1 || n > this.root.size) {
|
|
2039
|
+
return null;
|
|
2040
|
+
}
|
|
2041
|
+
const findNth = (node, position) => {
|
|
2042
|
+
if (!node) {
|
|
2043
|
+
return null;
|
|
2044
|
+
}
|
|
2045
|
+
const leftSize = node.left?.size ?? 0;
|
|
2046
|
+
if (position === leftSize + 1) {
|
|
2047
|
+
return node.value;
|
|
2048
|
+
}
|
|
2049
|
+
if (position <= leftSize) {
|
|
2050
|
+
return findNth(node.left, position);
|
|
2051
|
+
}
|
|
2052
|
+
return findNth(node.right, position - leftSize - 1);
|
|
2053
|
+
};
|
|
2054
|
+
return findNth(this.root, n);
|
|
2055
|
+
}
|
|
2056
|
+
/**
|
|
2057
|
+
* Gets a range of values between start and end (inclusive)
|
|
2058
|
+
*/
|
|
2059
|
+
getRange(start, end) {
|
|
2060
|
+
const startValue = typeof start === 'bigint' ? start : BigInt(start);
|
|
2061
|
+
const endValue = typeof end === 'bigint' ? end : BigInt(end);
|
|
2062
|
+
const result = [];
|
|
2063
|
+
const collectRange = (node) => {
|
|
2064
|
+
if (!node) {
|
|
2065
|
+
return;
|
|
2066
|
+
}
|
|
2067
|
+
if (this.comparator(node.value, startValue) >= 0 &&
|
|
2068
|
+
this.comparator(node.value, endValue) <= 0) {
|
|
2069
|
+
collectRange(node.left);
|
|
2070
|
+
result.push(node.value);
|
|
2071
|
+
collectRange(node.right);
|
|
2072
|
+
}
|
|
2073
|
+
else if (this.comparator(node.value, startValue) > 0) {
|
|
2074
|
+
collectRange(node.left);
|
|
2075
|
+
}
|
|
2076
|
+
else {
|
|
2077
|
+
collectRange(node.right);
|
|
2078
|
+
}
|
|
2079
|
+
};
|
|
2080
|
+
collectRange(this.root);
|
|
2081
|
+
return result;
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
|
|
2085
|
+
/**
|
|
2086
|
+
* Default options for power tower computations
|
|
2087
|
+
*/
|
|
2088
|
+
const DEFAULT_OPTIONS$4 = {
|
|
2089
|
+
maxHeight: 100,
|
|
2090
|
+
maxValue: BigInt(Number.MAX_SAFE_INTEGER),
|
|
2091
|
+
checkOverflow: true,
|
|
2092
|
+
precision: 0
|
|
2093
|
+
};
|
|
2094
|
+
/**
|
|
2095
|
+
* Class representing a power tower (tetration) computation structure
|
|
2096
|
+
* Handles expressions of the form: a↑↑b = a^(a^(a^...)) (b times)
|
|
2097
|
+
*/
|
|
2098
|
+
class PowerTower {
|
|
2099
|
+
constructor(options = {}) {
|
|
2100
|
+
this.options = { ...DEFAULT_OPTIONS$4, ...options };
|
|
2101
|
+
this.head = null;
|
|
2102
|
+
this.tail = null;
|
|
2103
|
+
this.size = 0;
|
|
2104
|
+
}
|
|
2105
|
+
/**
|
|
2106
|
+
* Creates a new power tower node
|
|
2107
|
+
*/
|
|
2108
|
+
createNode(value, height) {
|
|
2109
|
+
return {
|
|
2110
|
+
value,
|
|
2111
|
+
height,
|
|
2112
|
+
evaluated: false,
|
|
2113
|
+
previous: null,
|
|
2114
|
+
next: null
|
|
2115
|
+
};
|
|
2116
|
+
}
|
|
2117
|
+
/**
|
|
2118
|
+
* Validates power tower height
|
|
2119
|
+
*/
|
|
2120
|
+
validateHeight(height) {
|
|
2121
|
+
if (height < 0) {
|
|
2122
|
+
throw new ValidationError$1('Height cannot be negative');
|
|
2123
|
+
}
|
|
2124
|
+
if (height > this.options.maxHeight) {
|
|
2125
|
+
throw new ValidationError$1(`Height exceeds maximum of ${this.options.maxHeight}`);
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
/**
|
|
2129
|
+
* Validates value for computation
|
|
2130
|
+
*/
|
|
2131
|
+
validateValue(value) {
|
|
2132
|
+
validateNonNegative(value);
|
|
2133
|
+
if (this.options.checkOverflow && value > this.options.maxValue) {
|
|
2134
|
+
throw new OverflowError(`Value exceeds maximum of ${this.options.maxValue}`);
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
/**
|
|
2138
|
+
* Computes power with overflow checking
|
|
2139
|
+
*/
|
|
2140
|
+
computePower(base, exponent) {
|
|
2141
|
+
if (exponent === BigInt(0)) {
|
|
2142
|
+
return BigInt(1);
|
|
2143
|
+
}
|
|
2144
|
+
if (exponent === BigInt(1)) {
|
|
2145
|
+
return base;
|
|
2146
|
+
}
|
|
2147
|
+
let result = base;
|
|
2148
|
+
for (let i = BigInt(1); i < exponent; i++) {
|
|
2149
|
+
if (this.options.checkOverflow) {
|
|
2150
|
+
// Check if next multiplication would overflow
|
|
2151
|
+
const next = result * base;
|
|
2152
|
+
if (next > this.options.maxValue) {
|
|
2153
|
+
throw new OverflowError('Power computation would overflow');
|
|
2154
|
+
}
|
|
2155
|
+
result = next;
|
|
2156
|
+
}
|
|
2157
|
+
else {
|
|
2158
|
+
result *= base;
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
return result;
|
|
2162
|
+
}
|
|
2163
|
+
/**
|
|
2164
|
+
* Builds a power tower of specified height with given base
|
|
2165
|
+
*/
|
|
2166
|
+
build(base, height) {
|
|
2167
|
+
this.validateHeight(height);
|
|
2168
|
+
const baseValue = typeof base === 'bigint' ? base : BigInt(base);
|
|
2169
|
+
this.validateValue(baseValue);
|
|
2170
|
+
this.clear(); // Clear existing tower
|
|
2171
|
+
for (let i = 0; i < height; i++) {
|
|
2172
|
+
const node = this.createNode(baseValue, i + 1);
|
|
2173
|
+
if (!this.head) {
|
|
2174
|
+
this.head = node;
|
|
2175
|
+
this.tail = node;
|
|
2176
|
+
}
|
|
2177
|
+
else {
|
|
2178
|
+
node.previous = this.tail;
|
|
2179
|
+
this.tail.next = node;
|
|
2180
|
+
this.tail = node;
|
|
2181
|
+
}
|
|
2182
|
+
this.size++;
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
/**
|
|
2186
|
+
* Evaluates the power tower up to specified height
|
|
2187
|
+
*/
|
|
2188
|
+
evaluate(height) {
|
|
2189
|
+
if (!this.head) {
|
|
2190
|
+
return BigInt(1); // Empty tower evaluates to 1
|
|
2191
|
+
}
|
|
2192
|
+
const targetHeight = height ?? this.size;
|
|
2193
|
+
this.validateHeight(targetHeight);
|
|
2194
|
+
let current = this.head;
|
|
2195
|
+
let result = current.value;
|
|
2196
|
+
let currentHeight = 1;
|
|
2197
|
+
try {
|
|
2198
|
+
while (current.next && currentHeight < targetHeight) {
|
|
2199
|
+
result = this.computePower(current.next.value, result);
|
|
2200
|
+
current.evaluated = true;
|
|
2201
|
+
current = current.next;
|
|
2202
|
+
currentHeight++;
|
|
2203
|
+
}
|
|
2204
|
+
current.evaluated = true;
|
|
2205
|
+
return result;
|
|
2206
|
+
}
|
|
2207
|
+
catch (error) {
|
|
2208
|
+
if (error instanceof OverflowError) {
|
|
2209
|
+
// Mark nodes up to current height as evaluated
|
|
2210
|
+
let node = this.head;
|
|
2211
|
+
while (node !== current) {
|
|
2212
|
+
node.evaluated = true;
|
|
2213
|
+
node = node.next;
|
|
2214
|
+
}
|
|
2215
|
+
throw error;
|
|
2216
|
+
}
|
|
2217
|
+
throw error;
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
/**
|
|
2221
|
+
* Gets the current height of the power tower
|
|
2222
|
+
*/
|
|
2223
|
+
getHeight() {
|
|
2224
|
+
return this.size;
|
|
2225
|
+
}
|
|
2226
|
+
/**
|
|
2227
|
+
* Checks if the tower can be evaluated to a given height
|
|
2228
|
+
*/
|
|
2229
|
+
isComputable(height) {
|
|
2230
|
+
try {
|
|
2231
|
+
const targetHeight = height ?? this.size;
|
|
2232
|
+
this.validateHeight(targetHeight);
|
|
2233
|
+
// Check first few levels without full computation
|
|
2234
|
+
let current = this.head;
|
|
2235
|
+
let currentHeight = 0;
|
|
2236
|
+
while (current && currentHeight < targetHeight) {
|
|
2237
|
+
// Quick check for obvious overflow conditions
|
|
2238
|
+
if (current.value > BigInt(4) && currentHeight > 3) {
|
|
2239
|
+
return false;
|
|
2240
|
+
}
|
|
2241
|
+
current = current.next;
|
|
2242
|
+
currentHeight++;
|
|
2243
|
+
}
|
|
2244
|
+
// Try actual computation with a lower overflow threshold
|
|
2245
|
+
const safeOptions = { ...this.options, maxValue: this.options.maxValue >> BigInt(1) };
|
|
2246
|
+
const safeTower = new PowerTower(safeOptions);
|
|
2247
|
+
safeTower.build(this.head.value, targetHeight);
|
|
2248
|
+
safeTower.evaluate();
|
|
2249
|
+
return true;
|
|
2250
|
+
}
|
|
2251
|
+
catch {
|
|
2252
|
+
return false;
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
/**
|
|
2256
|
+
* Gets the computation state at each level
|
|
2257
|
+
*/
|
|
2258
|
+
getState() {
|
|
2259
|
+
const state = [];
|
|
2260
|
+
let current = this.head;
|
|
2261
|
+
while (current) {
|
|
2262
|
+
state.push({
|
|
2263
|
+
height: current.height,
|
|
2264
|
+
value: current.value,
|
|
2265
|
+
evaluated: current.evaluated
|
|
2266
|
+
});
|
|
2267
|
+
current = current.next;
|
|
2268
|
+
}
|
|
2269
|
+
return state;
|
|
2270
|
+
}
|
|
2271
|
+
/**
|
|
2272
|
+
* Clears the power tower
|
|
2273
|
+
*/
|
|
2274
|
+
clear() {
|
|
2275
|
+
this.head = null;
|
|
2276
|
+
this.tail = null;
|
|
2277
|
+
this.size = 0;
|
|
2278
|
+
}
|
|
2279
|
+
/**
|
|
2280
|
+
* Gets the maximum computationally feasible height for a given base
|
|
2281
|
+
*/
|
|
2282
|
+
static getMaxFeasibleHeight(base) {
|
|
2283
|
+
const baseValue = typeof base === 'bigint' ? base : BigInt(base);
|
|
2284
|
+
validateNonNegative(baseValue);
|
|
2285
|
+
if (baseValue === BigInt(0))
|
|
2286
|
+
return 0;
|
|
2287
|
+
if (baseValue === BigInt(1))
|
|
2288
|
+
return Infinity;
|
|
2289
|
+
if (baseValue === BigInt(2))
|
|
2290
|
+
return 4; // 2↑↑4 is already enormous
|
|
2291
|
+
if (baseValue === BigInt(3))
|
|
2292
|
+
return 3; // 3↑↑3 is already astronomical
|
|
2293
|
+
if (baseValue === BigInt(4))
|
|
2294
|
+
return 2;
|
|
2295
|
+
return 1; // For bases > 4, only height 1 is reliably computable
|
|
2296
|
+
}
|
|
2297
|
+
/**
|
|
2298
|
+
* Creates a string representation of the power tower
|
|
2299
|
+
*/
|
|
2300
|
+
toString() {
|
|
2301
|
+
if (!this.head) {
|
|
2302
|
+
return "Empty Tower";
|
|
2303
|
+
}
|
|
2304
|
+
let result = this.head.value.toString();
|
|
2305
|
+
let current = this.head;
|
|
2306
|
+
while (current.next) {
|
|
2307
|
+
result = `${current.next.value}^(${result})`;
|
|
2308
|
+
current = current.next;
|
|
2309
|
+
}
|
|
2310
|
+
return result;
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
/**
|
|
2315
|
+
* Formatting utilities for Hypernum library
|
|
2316
|
+
* Provides functions for formatting large numbers and converting between different representations
|
|
2317
|
+
*/
|
|
2318
|
+
// Default formatting options
|
|
2319
|
+
const DEFAULT_OPTIONS$3 = {
|
|
2320
|
+
notation: 'standard',
|
|
2321
|
+
precision: 0,
|
|
2322
|
+
grouping: true,
|
|
2323
|
+
groupSize: 3,
|
|
2324
|
+
decimalSeparator: '.',
|
|
2325
|
+
groupSeparator: ',',
|
|
2326
|
+
};
|
|
2327
|
+
/**
|
|
2328
|
+
* Formats a BigInt value according to specified options
|
|
2329
|
+
*/
|
|
2330
|
+
const formatBigInt = (value, options = {}) => {
|
|
2331
|
+
const opts = { ...DEFAULT_OPTIONS$3, ...options };
|
|
2332
|
+
// Handle negative numbers
|
|
2333
|
+
const isNegative = value < BigInt(0);
|
|
2334
|
+
const absValue = isNegative ? -value : value;
|
|
2335
|
+
let result;
|
|
2336
|
+
switch (opts.notation) {
|
|
2337
|
+
case 'scientific':
|
|
2338
|
+
result = formatScientific(absValue, opts).coefficient + 'e' +
|
|
2339
|
+
formatScientific(absValue, opts).exponent;
|
|
2340
|
+
break;
|
|
2341
|
+
case 'engineering':
|
|
2342
|
+
result = formatEngineering(absValue, opts);
|
|
2343
|
+
break;
|
|
2344
|
+
case 'compact':
|
|
2345
|
+
result = formatCompact(absValue, opts);
|
|
2346
|
+
break;
|
|
2347
|
+
default:
|
|
2348
|
+
result = formatStandard(absValue, opts);
|
|
2349
|
+
}
|
|
2350
|
+
return isNegative ? '-' + result : result;
|
|
2351
|
+
};
|
|
2352
|
+
/**
|
|
2353
|
+
* Formats a number in standard notation with grouping
|
|
2354
|
+
*/
|
|
2355
|
+
const formatStandard = (value, options) => {
|
|
2356
|
+
let str = value.toString();
|
|
2357
|
+
if (!options.grouping) {
|
|
2358
|
+
return str;
|
|
2359
|
+
}
|
|
2360
|
+
// Apply grouping from the right
|
|
2361
|
+
const result = [];
|
|
2362
|
+
let position = str.length;
|
|
2363
|
+
while (position > 0) {
|
|
2364
|
+
const start = Math.max(0, position - options.groupSize);
|
|
2365
|
+
result.unshift(str.slice(start, position));
|
|
2366
|
+
position = start;
|
|
2367
|
+
}
|
|
2368
|
+
return result.join(options.groupSeparator);
|
|
2369
|
+
};
|
|
2370
|
+
/**
|
|
2371
|
+
* Converts a number to scientific notation
|
|
2372
|
+
*/
|
|
2373
|
+
const formatScientific = (value, options) => {
|
|
2374
|
+
if (value === BigInt(0)) {
|
|
2375
|
+
return { coefficient: '0', exponent: 0 };
|
|
2376
|
+
}
|
|
2377
|
+
const str = value.toString();
|
|
2378
|
+
const exponent = str.length - 1;
|
|
2379
|
+
let coefficient = str[0] || '';
|
|
2380
|
+
coefficient += options.decimalSeparator + str.slice(1, options.precision + 1);
|
|
2381
|
+
return {
|
|
2382
|
+
coefficient: coefficient,
|
|
2383
|
+
exponent: exponent,
|
|
2384
|
+
};
|
|
2385
|
+
};
|
|
2386
|
+
/**
|
|
2387
|
+
* Formats a number in engineering notation (exponents divisible by 3)
|
|
2388
|
+
*/
|
|
2389
|
+
const formatEngineering = (value, options) => {
|
|
2390
|
+
if (value === BigInt(0)) {
|
|
2391
|
+
return '0';
|
|
2392
|
+
}
|
|
2393
|
+
const str = value.toString();
|
|
2394
|
+
const len = str.length;
|
|
2395
|
+
const exponent = Math.floor((len - 1) / 3) * 3;
|
|
2396
|
+
let coefficient = '';
|
|
2397
|
+
const digitsBeforePoint = len - exponent;
|
|
2398
|
+
for (let i = 0; i < Math.min(len, digitsBeforePoint + options.precision); i++) {
|
|
2399
|
+
if (i === digitsBeforePoint && i < len) {
|
|
2400
|
+
coefficient += options.decimalSeparator;
|
|
2401
|
+
}
|
|
2402
|
+
coefficient += str[i];
|
|
2403
|
+
}
|
|
2404
|
+
return `${coefficient}e${exponent}`;
|
|
2405
|
+
};
|
|
2406
|
+
/**
|
|
2407
|
+
* Formats a number in compact notation (K, M, B, T)
|
|
2408
|
+
*/
|
|
2409
|
+
const formatCompact = (value, options) => {
|
|
2410
|
+
const suffixes = ['', 'K', 'M', 'B', 'T', 'Q'];
|
|
2411
|
+
const str = value.toString();
|
|
2412
|
+
const len = str.length;
|
|
2413
|
+
if (len <= 3) {
|
|
2414
|
+
return formatStandard(value, options);
|
|
2415
|
+
}
|
|
2416
|
+
const suffixIndex = Math.min(Math.floor((len - 1) / 3), suffixes.length - 1);
|
|
2417
|
+
const suffix = suffixes[suffixIndex];
|
|
2418
|
+
const scale = BigInt(10) ** BigInt(suffixIndex * 3);
|
|
2419
|
+
const scaledValue = value / scale;
|
|
2420
|
+
let result = scaledValue.toString();
|
|
2421
|
+
if (options.precision > 0) {
|
|
2422
|
+
const remainder = value % scale;
|
|
2423
|
+
if (remainder > BigInt(0)) {
|
|
2424
|
+
const decimalPart = remainder.toString().padStart(3, '0').slice(0, options.precision);
|
|
2425
|
+
result += options.decimalSeparator + decimalPart;
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
return result + suffix;
|
|
2429
|
+
};
|
|
2430
|
+
/**
|
|
2431
|
+
* Parses a formatted string back to BigInt
|
|
2432
|
+
*/
|
|
2433
|
+
const parseBigIntString = (str, options = {}) => {
|
|
2434
|
+
const opts = { ...DEFAULT_OPTIONS$3, ...options };
|
|
2435
|
+
// Remove grouping separators
|
|
2436
|
+
let cleanStr = str.replace(new RegExp(`\\${opts.groupSeparator}`, 'g'), '');
|
|
2437
|
+
// Handle scientific notation
|
|
2438
|
+
if (cleanStr.toLowerCase().includes('e')) {
|
|
2439
|
+
const [coefficient, exponent] = cleanStr.toLowerCase().split('e');
|
|
2440
|
+
const base = BigInt(10);
|
|
2441
|
+
const exp = BigInt(exponent || '0');
|
|
2442
|
+
return BigInt(Math.floor(Number(coefficient))) * (base ** exp);
|
|
2443
|
+
}
|
|
2444
|
+
// Handle suffixes
|
|
2445
|
+
const suffixMap = new Map([
|
|
2446
|
+
['k', BigInt(1000)],
|
|
2447
|
+
['m', BigInt(1000000)],
|
|
2448
|
+
['b', BigInt(1000000000)],
|
|
2449
|
+
['t', BigInt(1000000000000)],
|
|
2450
|
+
['q', BigInt(1000000000000000)],
|
|
2451
|
+
]);
|
|
2452
|
+
const suffix = cleanStr.slice(-1).toLowerCase();
|
|
2453
|
+
const multiplier = suffixMap.get(suffix);
|
|
2454
|
+
if (multiplier) {
|
|
2455
|
+
cleanStr = cleanStr.slice(0, -1);
|
|
2456
|
+
const value = BigInt(Math.floor(Number(cleanStr)));
|
|
2457
|
+
return value * multiplier;
|
|
2458
|
+
}
|
|
2459
|
+
// Handle regular numbers
|
|
2460
|
+
return BigInt(cleanStr);
|
|
2461
|
+
};
|
|
2462
|
+
/**
|
|
2463
|
+
* Normalizes a string representation for comparison
|
|
2464
|
+
*/
|
|
2465
|
+
const normalizeNumberString = (str) => {
|
|
2466
|
+
// Remove all spaces and separators
|
|
2467
|
+
str = str.replace(/[\s,]/g, '');
|
|
2468
|
+
// Handle scientific notation
|
|
2469
|
+
if (str.toLowerCase().includes('e')) {
|
|
2470
|
+
const [coefficient, exponent] = str.toLowerCase().split('e');
|
|
2471
|
+
const exp = parseInt(exponent || '0');
|
|
2472
|
+
const coef = parseFloat(coefficient || '0');
|
|
2473
|
+
return (coef * Math.pow(10, exp)).toString();
|
|
2474
|
+
}
|
|
2475
|
+
return str;
|
|
2476
|
+
};
|
|
2477
|
+
|
|
2478
|
+
/**
|
|
2479
|
+
* Main Hypernum class that provides a high-level interface to all library functionality
|
|
2480
|
+
*/
|
|
2481
|
+
class Hypernum {
|
|
2482
|
+
constructor(config = {}) {
|
|
2483
|
+
this.config = {
|
|
2484
|
+
precision: config.precision ?? DEFAULT_OPTIONS$8.precision,
|
|
2485
|
+
roundingMode: config.roundingMode ?? DEFAULT_OPTIONS$8.roundingMode,
|
|
2486
|
+
checkOverflow: config.checkOverflow ?? DEFAULT_OPTIONS$8.checkOverflow,
|
|
2487
|
+
maxSteps: config.maxSteps ?? DEFAULT_OPTIONS$8.maxSteps,
|
|
2488
|
+
debug: config.debug ?? FEATURES.DEBUG_MODE
|
|
2489
|
+
};
|
|
2490
|
+
// Validate configuration
|
|
2491
|
+
if (this.config.precision < 0 || this.config.precision > MAX_PRECISION) {
|
|
2492
|
+
throw new ValidationError(`Precision must be between 0 and ${MAX_PRECISION}`);
|
|
2493
|
+
}
|
|
2494
|
+
if (this.config.maxSteps < 1 || this.config.maxSteps > MAX_COMPUTATION_STEPS) {
|
|
2495
|
+
throw new ValidationError(`Max steps must be between 1 and ${MAX_COMPUTATION_STEPS}`);
|
|
2496
|
+
}
|
|
2497
|
+
// Initialize data structure storage
|
|
2498
|
+
this.structures = {
|
|
2499
|
+
arrays: new Map(),
|
|
2500
|
+
trees: new Map(),
|
|
2501
|
+
heaps: new Map()
|
|
2502
|
+
};
|
|
2503
|
+
}
|
|
2504
|
+
// Arithmetic Operations
|
|
2505
|
+
add(a, b) {
|
|
2506
|
+
return add(a, b, this.config);
|
|
2507
|
+
}
|
|
2508
|
+
subtract(a, b) {
|
|
2509
|
+
return subtract(a, b, this.config);
|
|
2510
|
+
}
|
|
2511
|
+
multiply(a, b) {
|
|
2512
|
+
return multiply(a, b, this.config);
|
|
2513
|
+
}
|
|
2514
|
+
divide(a, b) {
|
|
2515
|
+
return divide(a, b, this.config);
|
|
2516
|
+
}
|
|
2517
|
+
mod(a, b) {
|
|
2518
|
+
return remainder(a, b, this.config);
|
|
2519
|
+
}
|
|
2520
|
+
// Power Operations
|
|
2521
|
+
power(base, exponent) {
|
|
2522
|
+
return power(base, exponent, this.config);
|
|
2523
|
+
}
|
|
2524
|
+
sqrt(value) {
|
|
2525
|
+
return sqrt(value, this.config);
|
|
2526
|
+
}
|
|
2527
|
+
nthRoot(value, n) {
|
|
2528
|
+
return nthRoot(value, n, this.config);
|
|
2529
|
+
}
|
|
2530
|
+
// Bitwise Operations
|
|
2531
|
+
and(a, b) {
|
|
2532
|
+
return and(a, b);
|
|
2533
|
+
}
|
|
2534
|
+
or(a, b) {
|
|
2535
|
+
return or(a, b);
|
|
2536
|
+
}
|
|
2537
|
+
xor(a, b) {
|
|
2538
|
+
return xor(a, b);
|
|
2539
|
+
}
|
|
2540
|
+
not(value) {
|
|
2541
|
+
return not(value);
|
|
2542
|
+
}
|
|
2543
|
+
/**
|
|
2544
|
+
* Calculates the greatest common divisor of two numbers
|
|
2545
|
+
*/
|
|
2546
|
+
gcd(a, b) {
|
|
2547
|
+
return gcd(a, b);
|
|
2548
|
+
}
|
|
2549
|
+
/**
|
|
2550
|
+
* Calculates the least common multiple of two numbers
|
|
2551
|
+
*/
|
|
2552
|
+
lcm(a, b) {
|
|
2553
|
+
return lcm(a, b);
|
|
2554
|
+
}
|
|
2555
|
+
// Data Structure Management
|
|
2556
|
+
createArray(id) {
|
|
2557
|
+
if (this.structures.arrays.has(id)) {
|
|
2558
|
+
throw new ValidationError(`Array with id '${id}' already exists`);
|
|
2559
|
+
}
|
|
2560
|
+
const array = new BigArray();
|
|
2561
|
+
this.structures.arrays.set(id, array);
|
|
2562
|
+
return array;
|
|
2563
|
+
}
|
|
2564
|
+
getArray(id) {
|
|
2565
|
+
const array = this.structures.arrays.get(id);
|
|
2566
|
+
if (!array) {
|
|
2567
|
+
throw new ValidationError(`Array with id '${id}' not found`);
|
|
2568
|
+
}
|
|
2569
|
+
return array;
|
|
2570
|
+
}
|
|
2571
|
+
createTree(id) {
|
|
2572
|
+
if (this.structures.trees.has(id)) {
|
|
2573
|
+
throw new ValidationError(`Tree with id '${id}' already exists`);
|
|
2574
|
+
}
|
|
2575
|
+
const tree = new NumberTree();
|
|
2576
|
+
this.structures.trees.set(id, tree);
|
|
2577
|
+
return tree;
|
|
2578
|
+
}
|
|
2579
|
+
getTree(id) {
|
|
2580
|
+
const tree = this.structures.trees.get(id);
|
|
2581
|
+
if (!tree) {
|
|
2582
|
+
throw new ValidationError(`Tree with id '${id}' not found`);
|
|
2583
|
+
}
|
|
2584
|
+
return tree;
|
|
2585
|
+
}
|
|
2586
|
+
createHeap(id, isMinHeap = true) {
|
|
2587
|
+
if (this.structures.heaps.has(id)) {
|
|
2588
|
+
throw new ValidationError(`Heap with id '${id}' already exists`);
|
|
2589
|
+
}
|
|
2590
|
+
const heap = isMinHeap ? new MinHeap(this.compareValues) : new MaxHeap(this.compareValues);
|
|
2591
|
+
this.structures.heaps.set(id, heap);
|
|
2592
|
+
return heap;
|
|
2593
|
+
}
|
|
2594
|
+
getHeap(id) {
|
|
2595
|
+
const heap = this.structures.heaps.get(id);
|
|
2596
|
+
if (!heap) {
|
|
2597
|
+
throw new ValidationError(`Heap with id '${id}' not found`);
|
|
2598
|
+
}
|
|
2599
|
+
return heap;
|
|
2600
|
+
}
|
|
2601
|
+
// Special Functions
|
|
2602
|
+
createAckermannStructure() {
|
|
2603
|
+
return new AckermannStructure();
|
|
2604
|
+
}
|
|
2605
|
+
// Formatting and Validation
|
|
2606
|
+
format(value, options) {
|
|
2607
|
+
const bigValue = toBigInt(value);
|
|
2608
|
+
return formatBigInt(bigValue, options);
|
|
2609
|
+
}
|
|
2610
|
+
validate(value) {
|
|
2611
|
+
try {
|
|
2612
|
+
toBigInt(value);
|
|
2613
|
+
return true;
|
|
2614
|
+
}
|
|
2615
|
+
catch {
|
|
2616
|
+
return false;
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
// Configuration Management
|
|
2620
|
+
updateConfig(newConfig) {
|
|
2621
|
+
Object.assign(this.config, newConfig);
|
|
2622
|
+
}
|
|
2623
|
+
getConfig() {
|
|
2624
|
+
return { ...this.config };
|
|
2625
|
+
}
|
|
2626
|
+
// Utility Functions
|
|
2627
|
+
compareValues(a, b) {
|
|
2628
|
+
if (a < b)
|
|
2629
|
+
return -1;
|
|
2630
|
+
if (a > b)
|
|
2631
|
+
return 1;
|
|
2632
|
+
return 0;
|
|
2633
|
+
}
|
|
2634
|
+
// Cleanup
|
|
2635
|
+
dispose() {
|
|
2636
|
+
this.structures.arrays.clear();
|
|
2637
|
+
this.structures.trees.clear();
|
|
2638
|
+
this.structures.heaps.clear();
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
|
|
2642
|
+
/**
|
|
2643
|
+
* Comparison operations module for Hypernum library
|
|
2644
|
+
* Provides functions for comparing large numbers with precision support
|
|
2645
|
+
*/
|
|
2646
|
+
const DEFAULT_OPTIONS$2 = {
|
|
2647
|
+
precision: 0,
|
|
2648
|
+
roundingMode: RoundingMode.HALF_EVEN,
|
|
2649
|
+
tolerance: 0
|
|
2650
|
+
};
|
|
2651
|
+
/**
|
|
2652
|
+
* Compares two numbers with optional precision
|
|
2653
|
+
*/
|
|
2654
|
+
function compare(a, b, options = {}) {
|
|
2655
|
+
const opts = { ...DEFAULT_OPTIONS$2, ...options };
|
|
2656
|
+
const bigA = toBigInt(a);
|
|
2657
|
+
const bigB = toBigInt(b);
|
|
2658
|
+
if (opts.precision === 0 && opts.tolerance === 0) {
|
|
2659
|
+
if (bigA < bigB)
|
|
2660
|
+
return -1;
|
|
2661
|
+
if (bigA > bigB)
|
|
2662
|
+
return 1;
|
|
2663
|
+
return 0;
|
|
2664
|
+
}
|
|
2665
|
+
const [scaledA, scaledB] = normalizePrecision(bigA, bigB, opts.precision, opts.precision);
|
|
2666
|
+
if (opts.tolerance > 0) {
|
|
2667
|
+
const diff = scaledA - scaledB;
|
|
2668
|
+
const toleranceValue = BigInt(10) ** BigInt(opts.tolerance);
|
|
2669
|
+
if (diff < -toleranceValue)
|
|
2670
|
+
return -1;
|
|
2671
|
+
if (diff > toleranceValue)
|
|
2672
|
+
return 1;
|
|
2673
|
+
return 0;
|
|
2674
|
+
}
|
|
2675
|
+
if (scaledA < scaledB)
|
|
2676
|
+
return -1;
|
|
2677
|
+
if (scaledA > scaledB)
|
|
2678
|
+
return 1;
|
|
2679
|
+
return 0;
|
|
2680
|
+
}
|
|
2681
|
+
/**
|
|
2682
|
+
* Checks if two numbers are equal
|
|
2683
|
+
*/
|
|
2684
|
+
function equals(a, b, options = {}) {
|
|
2685
|
+
return compare(a, b, options) === 0;
|
|
2686
|
+
}
|
|
2687
|
+
/**
|
|
2688
|
+
* Checks if first number is less than second
|
|
2689
|
+
*/
|
|
2690
|
+
function lessThan(a, b, options = {}) {
|
|
2691
|
+
return compare(a, b, options) === -1;
|
|
2692
|
+
}
|
|
2693
|
+
/**
|
|
2694
|
+
* Checks if first number is less than or equal to second
|
|
2695
|
+
*/
|
|
2696
|
+
function lessThanOrEqual(a, b, options = {}) {
|
|
2697
|
+
const result = compare(a, b, options);
|
|
2698
|
+
return result === -1 || result === 0;
|
|
2699
|
+
}
|
|
2700
|
+
/**
|
|
2701
|
+
* Checks if first number is greater than second
|
|
2702
|
+
*/
|
|
2703
|
+
function greaterThan(a, b, options = {}) {
|
|
2704
|
+
return compare(a, b, options) === 1;
|
|
2705
|
+
}
|
|
2706
|
+
/**
|
|
2707
|
+
* Checks if first number is greater than or equal to second
|
|
2708
|
+
*/
|
|
2709
|
+
function greaterThanOrEqual(a, b, options = {}) {
|
|
2710
|
+
const result = compare(a, b, options);
|
|
2711
|
+
return result === 1 || result === 0;
|
|
2712
|
+
}
|
|
2713
|
+
/**
|
|
2714
|
+
* Checks if a number is between two others (inclusive)
|
|
2715
|
+
*/
|
|
2716
|
+
function between(value, min, max, options = {}) {
|
|
2717
|
+
return greaterThanOrEqual(value, min, options) && lessThanOrEqual(value, max, options);
|
|
2718
|
+
}
|
|
2719
|
+
/**
|
|
2720
|
+
* Finds the maximum value in an array of numbers
|
|
2721
|
+
*/
|
|
2722
|
+
function max(values, options = {}) {
|
|
2723
|
+
if (values.length === 0) {
|
|
2724
|
+
throw new ValidationError$1('Cannot find maximum of empty array');
|
|
2725
|
+
}
|
|
2726
|
+
return values.reduce((max, current) => {
|
|
2727
|
+
const bigMax = toBigInt(max);
|
|
2728
|
+
const bigCurrent = toBigInt(current);
|
|
2729
|
+
return greaterThan(bigCurrent, bigMax, options) ? bigCurrent : bigMax;
|
|
2730
|
+
}, toBigInt(values[0]));
|
|
2731
|
+
}
|
|
2732
|
+
/**
|
|
2733
|
+
* Finds the minimum value in an array of numbers
|
|
2734
|
+
*/
|
|
2735
|
+
function min(values, options = {}) {
|
|
2736
|
+
if (values.length === 0) {
|
|
2737
|
+
throw new ValidationError$1('Cannot find minimum of empty array');
|
|
2738
|
+
}
|
|
2739
|
+
return values.reduce((min, current) => {
|
|
2740
|
+
const bigMin = toBigInt(min);
|
|
2741
|
+
const bigCurrent = toBigInt(current);
|
|
2742
|
+
return lessThan(bigCurrent, bigMin, options) ? bigCurrent : bigMin;
|
|
2743
|
+
}, toBigInt(values[0]));
|
|
2744
|
+
}
|
|
2745
|
+
/**
|
|
2746
|
+
* Clamps a value between minimum and maximum bounds
|
|
2747
|
+
*/
|
|
2748
|
+
function clamp(value, min, max, options = {}) {
|
|
2749
|
+
const bigValue = toBigInt(value);
|
|
2750
|
+
const bigMin = toBigInt(min);
|
|
2751
|
+
const bigMax = toBigInt(max);
|
|
2752
|
+
if (lessThan(bigMax, bigMin, options)) {
|
|
2753
|
+
throw new ValidationError$1('Maximum bound must be greater than or equal to minimum bound');
|
|
2754
|
+
}
|
|
2755
|
+
if (lessThan(bigValue, bigMin, options))
|
|
2756
|
+
return bigMin;
|
|
2757
|
+
if (greaterThan(bigValue, bigMax, options))
|
|
2758
|
+
return bigMax;
|
|
2759
|
+
return bigValue;
|
|
2760
|
+
}
|
|
2761
|
+
/**
|
|
2762
|
+
* Checks if all values in array are equal within tolerance
|
|
2763
|
+
*/
|
|
2764
|
+
function allEqual(values, options = {}) {
|
|
2765
|
+
if (values.length <= 1)
|
|
2766
|
+
return true;
|
|
2767
|
+
const first = toBigInt(values[0]);
|
|
2768
|
+
return values.every(value => equals(value, first, options));
|
|
2769
|
+
}
|
|
2770
|
+
/**
|
|
2771
|
+
* Checks if values are in ascending order
|
|
2772
|
+
*/
|
|
2773
|
+
function isAscending(values, options = {}) {
|
|
2774
|
+
if (values.length <= 1)
|
|
2775
|
+
return true;
|
|
2776
|
+
for (let i = 1; i < values.length; i++) {
|
|
2777
|
+
if (values[i] === undefined || values[i - 1] === undefined || !greaterThanOrEqual(values[i], values[i - 1], options)) {
|
|
2778
|
+
return false;
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
return true;
|
|
2782
|
+
}
|
|
2783
|
+
/**
|
|
2784
|
+
* Checks if values are in descending order
|
|
2785
|
+
*/
|
|
2786
|
+
function isDescending(values, options = {}) {
|
|
2787
|
+
if (values.length <= 1)
|
|
2788
|
+
return true;
|
|
2789
|
+
for (let i = 1; i < values.length; i++) {
|
|
2790
|
+
if (values[i] === undefined || values[i - 1] === undefined || !lessThanOrEqual(values[i], values[i - 1], options)) {
|
|
2791
|
+
return false;
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2794
|
+
return true;
|
|
2795
|
+
}
|
|
2796
|
+
/**
|
|
2797
|
+
* Creates a comparator function for sorting
|
|
2798
|
+
*/
|
|
2799
|
+
function createComparator(options = {}) {
|
|
2800
|
+
return (a, b) => compare(a, b, options);
|
|
2801
|
+
}
|
|
2802
|
+
|
|
2803
|
+
/**
|
|
2804
|
+
* Conversion operations module for Hypernum library
|
|
2805
|
+
* Provides functions for converting numbers between different formats and bases
|
|
2806
|
+
*/
|
|
2807
|
+
const DEFAULT_OPTIONS$1 = {
|
|
2808
|
+
precision: 0,
|
|
2809
|
+
roundingMode: RoundingMode.HALF_EVEN,
|
|
2810
|
+
uppercase: false,
|
|
2811
|
+
prefix: false,
|
|
2812
|
+
minDigits: 1
|
|
2813
|
+
};
|
|
2814
|
+
/**
|
|
2815
|
+
* Converts number to binary string representation
|
|
2816
|
+
*/
|
|
2817
|
+
function toBinary(value, options = {}) {
|
|
2818
|
+
const opts = { ...DEFAULT_OPTIONS$1, ...options };
|
|
2819
|
+
const bigValue = toBigInt(value);
|
|
2820
|
+
let binary = bigValue.toString(2);
|
|
2821
|
+
// Pad with zeros if needed
|
|
2822
|
+
while (binary.length < opts.minDigits) {
|
|
2823
|
+
binary = '0' + binary;
|
|
2824
|
+
}
|
|
2825
|
+
return opts.prefix ? '0b' + binary : binary;
|
|
2826
|
+
}
|
|
2827
|
+
/**
|
|
2828
|
+
* Converts number to octal string representation
|
|
2829
|
+
*/
|
|
2830
|
+
function toOctal(value, options = {}) {
|
|
2831
|
+
const opts = { ...DEFAULT_OPTIONS$1, ...options };
|
|
2832
|
+
const bigValue = toBigInt(value);
|
|
2833
|
+
let octal = bigValue.toString(8);
|
|
2834
|
+
while (octal.length < opts.minDigits) {
|
|
2835
|
+
octal = '0' + octal;
|
|
2836
|
+
}
|
|
2837
|
+
return opts.prefix ? '0o' + octal : octal;
|
|
2838
|
+
}
|
|
2839
|
+
/**
|
|
2840
|
+
* Converts number to hexadecimal string representation
|
|
2841
|
+
*/
|
|
2842
|
+
function toHexadecimal(value, options = {}) {
|
|
2843
|
+
const opts = { ...DEFAULT_OPTIONS$1, ...options };
|
|
2844
|
+
const bigValue = toBigInt(value);
|
|
2845
|
+
let hex = bigValue.toString(16);
|
|
2846
|
+
if (opts.uppercase) {
|
|
2847
|
+
hex = hex.toUpperCase();
|
|
2848
|
+
}
|
|
2849
|
+
while (hex.length < opts.minDigits) {
|
|
2850
|
+
hex = '0' + hex;
|
|
2851
|
+
}
|
|
2852
|
+
return opts.prefix ? '0x' + hex : hex;
|
|
2853
|
+
}
|
|
2854
|
+
/**
|
|
2855
|
+
* Converts number to string in specified base
|
|
2856
|
+
*/
|
|
2857
|
+
function toBase(value, base, options = {}) {
|
|
2858
|
+
if (base < 2 || base > 36) {
|
|
2859
|
+
throw new ValidationError$1('Base must be between 2 and 36');
|
|
2860
|
+
}
|
|
2861
|
+
const opts = { ...DEFAULT_OPTIONS$1, ...options };
|
|
2862
|
+
const bigValue = toBigInt(value);
|
|
2863
|
+
let result = bigValue.toString(base);
|
|
2864
|
+
if (opts.uppercase) {
|
|
2865
|
+
result = result.toUpperCase();
|
|
2866
|
+
}
|
|
2867
|
+
while (result.length < opts.minDigits) {
|
|
2868
|
+
result = '0' + result;
|
|
2869
|
+
}
|
|
2870
|
+
return result;
|
|
2871
|
+
}
|
|
2872
|
+
/**
|
|
2873
|
+
* Converts string from specified base to bigint
|
|
2874
|
+
*/
|
|
2875
|
+
function fromBase(value, base) {
|
|
2876
|
+
if (base < 2 || base > 36) {
|
|
2877
|
+
throw new ValidationError$1('Base must be between 2 and 36');
|
|
2878
|
+
}
|
|
2879
|
+
// Remove base prefixes if present
|
|
2880
|
+
const cleanValue = value.toLowerCase()
|
|
2881
|
+
.replace(/^0x/, '') // hex
|
|
2882
|
+
.replace(/^0b/, '') // binary
|
|
2883
|
+
.replace(/^0o/, ''); // octal
|
|
2884
|
+
try {
|
|
2885
|
+
return BigInt(`${base}n${cleanValue}`);
|
|
2886
|
+
}
|
|
2887
|
+
catch (error) {
|
|
2888
|
+
throw new ValidationError$1(`Invalid number format for base ${base}: ${value}`);
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2891
|
+
/**
|
|
2892
|
+
* Converts decimal string to fraction representation
|
|
2893
|
+
*/
|
|
2894
|
+
function toFraction(value) {
|
|
2895
|
+
// Split into integer and decimal parts
|
|
2896
|
+
const [intPart, decPart = ''] = value.split('.');
|
|
2897
|
+
if (!decPart) {
|
|
2898
|
+
return [toBigInt(intPart), 1n];
|
|
2899
|
+
}
|
|
2900
|
+
// Convert decimal to fraction
|
|
2901
|
+
const numerator = toBigInt(intPart + decPart);
|
|
2902
|
+
const denominator = 10n ** BigInt(decPart.length);
|
|
2903
|
+
// Simplify fraction
|
|
2904
|
+
const gcd = calculateGCD(numerator, denominator);
|
|
2905
|
+
return [numerator / gcd, denominator / gcd];
|
|
2906
|
+
}
|
|
2907
|
+
/**
|
|
2908
|
+
* Converts fraction to decimal string with specified precision
|
|
2909
|
+
*/
|
|
2910
|
+
function fromFraction(numerator, denominator, options = {}) {
|
|
2911
|
+
const opts = { ...DEFAULT_OPTIONS$1, ...options };
|
|
2912
|
+
const bigNumerator = toBigInt(numerator);
|
|
2913
|
+
const bigDenominator = toBigInt(denominator);
|
|
2914
|
+
if (bigDenominator === 0n) {
|
|
2915
|
+
throw new ValidationError$1('Denominator cannot be zero');
|
|
2916
|
+
}
|
|
2917
|
+
const quotient = bigNumerator / bigDenominator;
|
|
2918
|
+
const remainder = bigNumerator % bigDenominator;
|
|
2919
|
+
if (remainder === 0n || opts.precision === 0) {
|
|
2920
|
+
return quotient.toString();
|
|
2921
|
+
}
|
|
2922
|
+
// Calculate decimal part
|
|
2923
|
+
const scaleFactor = 10n ** BigInt(opts.precision);
|
|
2924
|
+
const scaledRemainder = (remainder * scaleFactor) / bigDenominator;
|
|
2925
|
+
return `${quotient}.${scaledRemainder.toString().padStart(opts.precision, '0')}`;
|
|
2926
|
+
}
|
|
2927
|
+
/**
|
|
2928
|
+
* Converts scientific notation to decimal string
|
|
2929
|
+
*/
|
|
2930
|
+
function fromScientific(value) {
|
|
2931
|
+
// Parse scientific notation format
|
|
2932
|
+
const match = value.match(/^(-?\d+\.?\d*)[eE]([+-]?\d+)$/);
|
|
2933
|
+
if (!match) {
|
|
2934
|
+
throw new ValidationError$1('Invalid scientific notation format');
|
|
2935
|
+
}
|
|
2936
|
+
const [, significand, exponent] = match;
|
|
2937
|
+
const exp = parseInt(exponent || '0', 10);
|
|
2938
|
+
// Convert to regular decimal
|
|
2939
|
+
if (exp >= 0) {
|
|
2940
|
+
if (significand === undefined) {
|
|
2941
|
+
throw new ValidationError$1('Invalid scientific notation format');
|
|
2942
|
+
}
|
|
2943
|
+
return (BigInt(significand.replace('.', '')) * (10n ** BigInt(exp))).toString();
|
|
2944
|
+
}
|
|
2945
|
+
else {
|
|
2946
|
+
const absExp = Math.abs(exp);
|
|
2947
|
+
if (significand === undefined) {
|
|
2948
|
+
throw new ValidationError$1('Invalid scientific notation format');
|
|
2949
|
+
}
|
|
2950
|
+
const scaledValue = BigInt(significand.replace('.', ''));
|
|
2951
|
+
return (scaledValue / (10n ** BigInt(absExp))).toString();
|
|
2952
|
+
}
|
|
2953
|
+
}
|
|
2954
|
+
/**
|
|
2955
|
+
* Converts decimal to scientific notation
|
|
2956
|
+
*/
|
|
2957
|
+
function toScientific(value, options = {}) {
|
|
2958
|
+
const opts = { ...DEFAULT_OPTIONS$1, ...options };
|
|
2959
|
+
const bigValue = toBigInt(value);
|
|
2960
|
+
if (bigValue === 0n) {
|
|
2961
|
+
return '0e0';
|
|
2962
|
+
}
|
|
2963
|
+
const str = bigValue.toString();
|
|
2964
|
+
const firstDigit = str[0] === '-' ? str[1] : str[0];
|
|
2965
|
+
const exponent = str.length - (str[0] === '-' ? 2 : 1);
|
|
2966
|
+
let result = firstDigit;
|
|
2967
|
+
if (str.length > 1) {
|
|
2968
|
+
const restDigits = str.slice(str[0] === '-' ? 2 : 1);
|
|
2969
|
+
if (opts.precision > 0) {
|
|
2970
|
+
result += '.' + restDigits.slice(0, opts.precision);
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
if (str[0] === '-') {
|
|
2974
|
+
result = '-' + result;
|
|
2975
|
+
}
|
|
2976
|
+
return `${result}e${exponent}`;
|
|
2977
|
+
}
|
|
2978
|
+
/**
|
|
2979
|
+
* Calculates Greatest Common Divisor (helper function)
|
|
2980
|
+
*/
|
|
2981
|
+
function calculateGCD(a, b) {
|
|
2982
|
+
a = a < 0n ? -a : a;
|
|
2983
|
+
b = b < 0n ? -b : b;
|
|
2984
|
+
while (b !== 0n) {
|
|
2985
|
+
const temp = b;
|
|
2986
|
+
b = a % b;
|
|
2987
|
+
a = temp;
|
|
2988
|
+
}
|
|
2989
|
+
return a;
|
|
2990
|
+
}
|
|
2991
|
+
/**
|
|
2992
|
+
* Converts Roman numeral to number
|
|
2993
|
+
*/
|
|
2994
|
+
function fromRoman(value) {
|
|
2995
|
+
const romanValues = new Map([
|
|
2996
|
+
['I', 1],
|
|
2997
|
+
['V', 5],
|
|
2998
|
+
['X', 10],
|
|
2999
|
+
['L', 50],
|
|
3000
|
+
['C', 100],
|
|
3001
|
+
['D', 500],
|
|
3002
|
+
['M', 1000]
|
|
3003
|
+
]);
|
|
3004
|
+
let result = 0;
|
|
3005
|
+
let prevValue = 0;
|
|
3006
|
+
// Process from right to left
|
|
3007
|
+
for (let i = value.length - 1; i >= 0; i--) {
|
|
3008
|
+
const char = value[i]?.toUpperCase() ?? '';
|
|
3009
|
+
const current = romanValues.get(char);
|
|
3010
|
+
if (current === undefined) {
|
|
3011
|
+
throw new ValidationError$1(`Invalid Roman numeral character: ${char}`);
|
|
3012
|
+
}
|
|
3013
|
+
if (current >= prevValue) {
|
|
3014
|
+
result += current;
|
|
3015
|
+
}
|
|
3016
|
+
else {
|
|
3017
|
+
result -= current;
|
|
3018
|
+
}
|
|
3019
|
+
prevValue = current;
|
|
3020
|
+
}
|
|
3021
|
+
return BigInt(result);
|
|
3022
|
+
}
|
|
3023
|
+
/**
|
|
3024
|
+
* Converts number to Roman numeral
|
|
3025
|
+
*/
|
|
3026
|
+
function toRoman(value, options = {}) {
|
|
3027
|
+
const opts = { ...DEFAULT_OPTIONS$1, ...options };
|
|
3028
|
+
const num = Number(toBigInt(value));
|
|
3029
|
+
if (num <= 0 || num > 3999) {
|
|
3030
|
+
throw new ValidationError$1('Number must be between 1 and 3999 for Roman numerals');
|
|
3031
|
+
}
|
|
3032
|
+
const romanSymbols = [
|
|
3033
|
+
['I', 'V'], // ones
|
|
3034
|
+
['X', 'L'], // tens
|
|
3035
|
+
['C', 'D'], // hundreds
|
|
3036
|
+
['M'] // thousands
|
|
3037
|
+
];
|
|
3038
|
+
let result = '';
|
|
3039
|
+
let position = 0;
|
|
3040
|
+
let remaining = num;
|
|
3041
|
+
while (remaining > 0) {
|
|
3042
|
+
const digit = remaining % 10;
|
|
3043
|
+
const symbols = romanSymbols[position];
|
|
3044
|
+
if (!symbols) {
|
|
3045
|
+
break; // Safety check for position overflow
|
|
3046
|
+
}
|
|
3047
|
+
const unit = symbols[0];
|
|
3048
|
+
const five = symbols[1] ?? '';
|
|
3049
|
+
const next = position < 3 ? romanSymbols[position + 1]?.[0] ?? '' : '';
|
|
3050
|
+
let digitStr = '';
|
|
3051
|
+
if (digit === 9 && next) {
|
|
3052
|
+
digitStr = unit + next;
|
|
3053
|
+
}
|
|
3054
|
+
else if (digit >= 5 && five) {
|
|
3055
|
+
digitStr = five + unit.repeat(digit - 5);
|
|
3056
|
+
}
|
|
3057
|
+
else if (digit === 4 && five) {
|
|
3058
|
+
digitStr = unit + five;
|
|
3059
|
+
}
|
|
3060
|
+
else {
|
|
3061
|
+
digitStr = unit.repeat(digit);
|
|
3062
|
+
}
|
|
3063
|
+
result = digitStr + result;
|
|
3064
|
+
remaining = Math.floor(remaining / 10);
|
|
3065
|
+
position++;
|
|
3066
|
+
}
|
|
3067
|
+
return opts.uppercase ? result : result.toLowerCase();
|
|
3068
|
+
}
|
|
3069
|
+
|
|
3070
|
+
/**
|
|
3071
|
+
* Factorial operations module for Hypernum library
|
|
3072
|
+
* Provides efficient implementations for factorial and related computations
|
|
3073
|
+
*/
|
|
3074
|
+
const DEFAULT_OPTIONS = {
|
|
3075
|
+
maxValue: 1000,
|
|
3076
|
+
checkOverflow: true,
|
|
3077
|
+
useCache: true
|
|
3078
|
+
};
|
|
3079
|
+
// Cache for factorial values
|
|
3080
|
+
const factorialCache = new Map();
|
|
3081
|
+
/**
|
|
3082
|
+
* Calculates factorial of a number (n!)
|
|
3083
|
+
*/
|
|
3084
|
+
function factorial(value, options = {}) {
|
|
3085
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
3086
|
+
const n = toBigInt(value);
|
|
3087
|
+
validateNonNegative(n);
|
|
3088
|
+
if (opts.checkOverflow && n > BigInt(opts.maxValue)) {
|
|
3089
|
+
throw new OverflowError(`Factorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
3090
|
+
}
|
|
3091
|
+
// Handle base cases
|
|
3092
|
+
if (n <= 1n) {
|
|
3093
|
+
return 1n;
|
|
3094
|
+
}
|
|
3095
|
+
// Check cache
|
|
3096
|
+
if (opts.useCache && factorialCache.has(n)) {
|
|
3097
|
+
return factorialCache.get(n);
|
|
3098
|
+
}
|
|
3099
|
+
// Calculate factorial
|
|
3100
|
+
let result = 1n;
|
|
3101
|
+
for (let i = 2n; i <= n; i++) {
|
|
3102
|
+
result *= i;
|
|
3103
|
+
}
|
|
3104
|
+
// Cache result
|
|
3105
|
+
if (opts.useCache) {
|
|
3106
|
+
factorialCache.set(n, result);
|
|
3107
|
+
}
|
|
3108
|
+
return result;
|
|
3109
|
+
}
|
|
3110
|
+
/**
|
|
3111
|
+
* Calculates binomial coefficient (n choose k)
|
|
3112
|
+
*/
|
|
3113
|
+
function binomial(n, k, options = {}) {
|
|
3114
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
3115
|
+
const bigN = toBigInt(n);
|
|
3116
|
+
const bigK = toBigInt(k);
|
|
3117
|
+
validateNonNegative(bigN);
|
|
3118
|
+
validateNonNegative(bigK);
|
|
3119
|
+
if (bigK > bigN) {
|
|
3120
|
+
throw new ValidationError$1('K cannot be greater than N in binomial coefficient');
|
|
3121
|
+
}
|
|
3122
|
+
// Optimize for k > n/2 by using symmetry
|
|
3123
|
+
if (bigK > bigN / 2n) {
|
|
3124
|
+
return binomial(bigN, bigN - bigK, opts);
|
|
3125
|
+
}
|
|
3126
|
+
// Use multiplicative formula instead of factorial for efficiency
|
|
3127
|
+
let result = 1n;
|
|
3128
|
+
for (let i = 0n; i < bigK; i++) {
|
|
3129
|
+
result = (result * (bigN - i)) / (i + 1n);
|
|
3130
|
+
}
|
|
3131
|
+
return result;
|
|
3132
|
+
}
|
|
3133
|
+
/**
|
|
3134
|
+
* Calculates subfactorial (derangement number)
|
|
3135
|
+
* Number of permutations of n elements with no fixed points
|
|
3136
|
+
*/
|
|
3137
|
+
function subfactorial(value, options = {}) {
|
|
3138
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
3139
|
+
const n = toBigInt(value);
|
|
3140
|
+
validateNonNegative(n);
|
|
3141
|
+
if (opts.checkOverflow && n > BigInt(opts.maxValue)) {
|
|
3142
|
+
throw new OverflowError(`Subfactorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
3143
|
+
}
|
|
3144
|
+
// Handle base cases
|
|
3145
|
+
if (n === 0n)
|
|
3146
|
+
return 1n;
|
|
3147
|
+
if (n === 1n)
|
|
3148
|
+
return 0n;
|
|
3149
|
+
// Use recursive formula !n = n * !(n-1) + (-1)^n
|
|
3150
|
+
let result = 0n;
|
|
3151
|
+
const nFact = factorial(n, opts);
|
|
3152
|
+
for (let k = 0n; k <= n; k++) {
|
|
3153
|
+
const term = factorial(n - k, opts) * (k % 2n === 0n ? 1n : -1n);
|
|
3154
|
+
result += term;
|
|
3155
|
+
}
|
|
3156
|
+
return nFact - result;
|
|
3157
|
+
}
|
|
3158
|
+
/**
|
|
3159
|
+
* Calculates rising factorial (Pochhammer symbol)
|
|
3160
|
+
* x^(n) = x(x+1)(x+2)...(x+n-1)
|
|
3161
|
+
*/
|
|
3162
|
+
function risingFactorial(x, n, options = {}) {
|
|
3163
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
3164
|
+
const bigX = toBigInt(x);
|
|
3165
|
+
const bigN = toBigInt(n);
|
|
3166
|
+
validateNonNegative(bigN);
|
|
3167
|
+
if (opts.checkOverflow && bigN > BigInt(opts.maxValue)) {
|
|
3168
|
+
throw new OverflowError(`Rising factorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
3169
|
+
}
|
|
3170
|
+
let result = 1n;
|
|
3171
|
+
for (let i = 0n; i < bigN; i++) {
|
|
3172
|
+
result *= (bigX + i);
|
|
3173
|
+
}
|
|
3174
|
+
return result;
|
|
3175
|
+
}
|
|
3176
|
+
/**
|
|
3177
|
+
* Calculates falling factorial
|
|
3178
|
+
* x_(n) = x(x-1)(x-2)...(x-n+1)
|
|
3179
|
+
*/
|
|
3180
|
+
function fallingFactorial(x, n, options = {}) {
|
|
3181
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
3182
|
+
const bigX = toBigInt(x);
|
|
3183
|
+
const bigN = toBigInt(n);
|
|
3184
|
+
validateNonNegative(bigN);
|
|
3185
|
+
if (opts.checkOverflow && bigN > BigInt(opts.maxValue)) {
|
|
3186
|
+
throw new OverflowError(`Falling factorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
3187
|
+
}
|
|
3188
|
+
let result = 1n;
|
|
3189
|
+
for (let i = 0n; i < bigN; i++) {
|
|
3190
|
+
result *= (bigX - i);
|
|
3191
|
+
}
|
|
3192
|
+
return result;
|
|
3193
|
+
}
|
|
3194
|
+
/**
|
|
3195
|
+
* Calculates multifactorial (n!!)
|
|
3196
|
+
* Product of numbers from 1 to n that leave the same remainder as n when divided by k
|
|
3197
|
+
*/
|
|
3198
|
+
function multiFactorial(value, k = 2n, options = {}) {
|
|
3199
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
3200
|
+
const n = toBigInt(value);
|
|
3201
|
+
const bigK = toBigInt(k);
|
|
3202
|
+
validateNonNegative(n);
|
|
3203
|
+
if (bigK <= 0n) {
|
|
3204
|
+
throw new ValidationError$1('K must be positive in multifactorial');
|
|
3205
|
+
}
|
|
3206
|
+
if (opts.checkOverflow && n > BigInt(opts.maxValue)) {
|
|
3207
|
+
throw new OverflowError(`Multifactorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
3208
|
+
}
|
|
3209
|
+
let result = 1n;
|
|
3210
|
+
let current = n;
|
|
3211
|
+
while (current > 0n) {
|
|
3212
|
+
result *= current;
|
|
3213
|
+
current -= bigK;
|
|
3214
|
+
}
|
|
3215
|
+
return result;
|
|
3216
|
+
}
|
|
3217
|
+
/**
|
|
3218
|
+
* Calculates primorial (product of primes up to n)
|
|
3219
|
+
*/
|
|
3220
|
+
function primorial(value, options = {}) {
|
|
3221
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
3222
|
+
const n = toBigInt(value);
|
|
3223
|
+
validateNonNegative(n);
|
|
3224
|
+
if (opts.checkOverflow && n > BigInt(opts.maxValue)) {
|
|
3225
|
+
throw new OverflowError(`Primorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
3226
|
+
}
|
|
3227
|
+
if (n <= 1n)
|
|
3228
|
+
return 1n;
|
|
3229
|
+
// Generate primes up to n using Sieve of Eratosthenes
|
|
3230
|
+
const num = Number(n);
|
|
3231
|
+
const sieve = new Array(num + 1).fill(true);
|
|
3232
|
+
sieve[0] = sieve[1] = false;
|
|
3233
|
+
for (let i = 2; i * i <= num; i++) {
|
|
3234
|
+
if (sieve[i]) {
|
|
3235
|
+
for (let j = i * i; j <= num; j += i) {
|
|
3236
|
+
sieve[j] = false;
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
// Calculate product of all primes up to n
|
|
3241
|
+
let result = 1n;
|
|
3242
|
+
for (let i = 2; i <= num; i++) {
|
|
3243
|
+
if (sieve[i]) {
|
|
3244
|
+
result *= BigInt(i);
|
|
3245
|
+
}
|
|
3246
|
+
}
|
|
3247
|
+
return result;
|
|
3248
|
+
}
|
|
3249
|
+
|
|
3250
|
+
/**
|
|
3251
|
+
* Hypernum - A TypeScript/JavaScript library for large number operations
|
|
3252
|
+
*/
|
|
3253
|
+
const packagePath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../package.json');
|
|
3254
|
+
const { version: VERSION } = JSON.parse(fs.readFileSync(packagePath, 'utf-8'));
|
|
3255
|
+
/**
|
|
3256
|
+
* Creates a new Hypernum instance with custom configuration
|
|
3257
|
+
*/
|
|
3258
|
+
function createHypernum(config) {
|
|
3259
|
+
const mergedConfig = mergeConfig(config || {});
|
|
3260
|
+
validateConfig(mergedConfig);
|
|
3261
|
+
const instanceConfig = {
|
|
3262
|
+
precision: 'arithmetic' in mergedConfig
|
|
3263
|
+
? mergedConfig.arithmetic.defaultPrecision
|
|
3264
|
+
: mergedConfig.precision ?? 0,
|
|
3265
|
+
roundingMode: 'arithmetic' in mergedConfig
|
|
3266
|
+
? mergedConfig.arithmetic.defaultRoundingMode
|
|
3267
|
+
: mergedConfig.roundingMode ?? RoundingMode.HALF_EVEN,
|
|
3268
|
+
checkOverflow: 'arithmetic' in mergedConfig
|
|
3269
|
+
? mergedConfig.arithmetic.checkOverflow
|
|
3270
|
+
: mergedConfig.checkOverflow ?? true,
|
|
3271
|
+
maxSteps: 'arithmetic' in mergedConfig
|
|
3272
|
+
? mergedConfig.arithmetic.maxComputationSteps
|
|
3273
|
+
: mergedConfig.maxSteps ?? 1000,
|
|
3274
|
+
debug: 'debug' in mergedConfig && typeof mergedConfig.debug === 'object'
|
|
3275
|
+
? mergedConfig.debug.verbose
|
|
3276
|
+
: false
|
|
3277
|
+
};
|
|
3278
|
+
return new Hypernum(instanceConfig);
|
|
3279
|
+
}
|
|
3280
|
+
// Default instance
|
|
3281
|
+
const defaultHypernum = createHypernum();
|
|
3282
|
+
|
|
3283
|
+
export { AckermannStructure, BigArray, ComputationLimitError, DEFAULT_ARRAY_GROWTH_FACTOR, DEFAULT_BASIC_CONFIG, DEFAULT_CACHE_SIZE, DEFAULT_DECIMAL_SEPARATOR, DEFAULT_FULL_CONFIG, DEFAULT_GROUP_SEPARATOR, DEFAULT_GROUP_SIZE, DEFAULT_HEAP_INITIAL_CAPACITY, DEFAULT_OPTIONS$8 as DEFAULT_OPTIONS, DEFAULT_TREE_MAX_DEPTH, DataStructureError, DivisionByZeroError, ERROR_MESSAGES, FEATURES, FormatError, HeapPropertyError, Hypernum, HypernumError, IndexError, MAX_ACKERMANN_M, MAX_ACKERMANN_N, MAX_BITS, MAX_CACHE_SIZE, MAX_COMPUTATION_STEPS, MAX_FACTORIAL_INPUT, MAX_GROUP_SIZE, MAX_POWER_BASE, MAX_POWER_EXPONENT, MAX_PRECISION, MAX_ROMAN_VALUE, MAX_SAFE_INTEGER, MAX_TETRATION_HEIGHT, MIN_ARRAY_CAPACITY, MIN_ROMAN_VALUE, MIN_SAFE_INTEGER, MaxHeap, MinHeap, NEGATIVE_ONE, NUMBER_UNITS, NumberTree, ONE, PERFORMANCE, PowerTower, PrecisionError, RomanNumeralError, RoundingMode, TEN, TWO, TreeError, UnderflowError, VERSION, ZERO, abs, add, allEqual, and, between, binomial, checkAdditionOverflow, checkMultiplicationOverflow, checkPowerOverflow, clamp, clearBit, compare, convertToBasicConfig, createComparator, createHypernum, Hypernum as default, defaultHypernum, divide, equals, factorial, fallingFactorial, formatBigInt, fromBase, fromFraction, fromRoman, fromScientific, gcd, getBit, greaterThan, greaterThanOrEqual, isAscending, isBasicConfig, isDescending, isFullConfig, lcm, leadingZeros, leftShift, lessThan, lessThanOrEqual, max, mergeConfig, min, multiFactorial, multiply, normalizeNumberString, normalizePrecision, not, nthRoot, or, parseBigIntString, popCount, power, primorial, remainder, rightShift, risingFactorial, rotateLeft, rotateRight, round, scaleByPowerOfTen, scaledDivision, setBit, sign, sqrt, subfactorial, subtract, superRoot, tetration, toBase, toBigInt, toBinary, toFraction, toHexadecimal, toOctal, toRoman, toScientific, toggleBit, trailingZeros, unsignedRightShift, validateConfig, validateNonNegative, validatePositive, xor };
|
|
3284
|
+
//# sourceMappingURL=index.js.map
|