@obinexusmk2/hypernum 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +355 -256
- package/dist/index.cjs +4 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -7
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +2 -2
- package/dist/index.umd.js.map +1 -1
- package/dist/types/{config → src/config}/config-loader.d.ts +0 -0
- package/dist/types/src/config/config-loader.d.ts.map +1 -0
- package/dist/types/{config → src/config}/config-parser.d.ts +0 -0
- package/dist/types/src/config/config-parser.d.ts.map +1 -0
- package/dist/types/{config → src/config}/config-resolver.d.ts +0 -0
- package/dist/types/src/config/config-resolver.d.ts.map +1 -0
- package/dist/types/{config → src/config}/config-source.d.ts +0 -0
- package/dist/types/src/config/config-source.d.ts.map +1 -0
- package/dist/types/{config → src/config}/index.d.ts +0 -0
- package/dist/types/src/config/index.d.ts.map +1 -0
- package/dist/types/{core → src/core}/common.d.ts +0 -0
- package/dist/types/src/core/common.d.ts.map +1 -0
- package/dist/types/{core → src/core}/config.d.ts +0 -0
- package/dist/types/src/core/config.d.ts.map +1 -0
- package/dist/types/{core → src/core}/constants.d.ts +0 -0
- package/dist/types/src/core/constants.d.ts.map +1 -0
- package/dist/types/{core → src/core}/errors.d.ts +0 -0
- package/dist/types/src/core/errors.d.ts.map +1 -0
- package/dist/types/{core → src/core}/hypernum.d.ts +0 -0
- package/dist/types/src/core/hypernum.d.ts.map +1 -0
- package/dist/types/{core → src/core}/index.d.ts +0 -0
- package/dist/types/src/core/index.d.ts.map +1 -0
- package/dist/types/{index.d.ts → src/index.d.ts} +1 -1
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/arithmetic.d.ts +0 -0
- package/dist/types/src/operations/arithmetic.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/bitwise.d.ts +0 -0
- package/dist/types/src/operations/bitwise.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/comparison.d.ts +0 -0
- package/dist/types/src/operations/comparison.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/conversion.d.ts +0 -0
- package/dist/types/src/operations/conversion.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/factorial.d.ts +0 -0
- package/dist/types/src/operations/factorial.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/index.d.ts +0 -0
- package/dist/types/src/operations/index.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/power.d.ts +0 -0
- package/dist/types/src/operations/power.d.ts.map +1 -0
- package/dist/types/{storage → src/storage}/Heap.d.ts +0 -0
- package/dist/types/src/storage/Heap.d.ts.map +1 -0
- package/dist/types/{storage → src/storage}/index.d.ts +0 -0
- package/dist/types/src/storage/index.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/ackermann.d.ts +0 -0
- package/dist/types/src/structures/ackermann.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/big-array.d.ts +0 -0
- package/dist/types/src/structures/big-array.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/index.d.ts +0 -0
- package/dist/types/src/structures/index.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/number-tree.d.ts +0 -0
- package/dist/types/src/structures/number-tree.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/power-tower.d.ts +0 -0
- package/dist/types/src/structures/power-tower.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/formatting.d.ts +0 -0
- package/dist/types/src/utils/formatting.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/index.d.ts +0 -0
- package/dist/types/src/utils/index.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/parser.d.ts +0 -0
- package/dist/types/src/utils/parser.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/precision.d.ts +0 -0
- package/dist/types/src/utils/precision.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/validation.d.ts +0 -0
- package/dist/types/src/utils/validation.d.ts.map +1 -0
- package/package.json +169 -164
- package/rollup.config.js +163 -161
- package/src/cli/hypernum.js +272 -0
- package/src/config/config-loader.ts +0 -0
- package/src/config/config-parser.ts +160 -160
- package/src/config/config-resolver.ts +0 -0
- package/src/config/config-source.ts +0 -0
- package/src/config/index.ts +0 -0
- package/src/core/common.ts +184 -184
- package/src/core/config.ts +392 -392
- package/src/core/constants.ts +101 -101
- package/src/core/errors.ts +202 -202
- package/src/core/hypernum.ts +240 -240
- package/src/core/index.ts +4 -4
- package/src/index.ts +179 -182
- package/src/operations/arithmetic.ts +332 -332
- package/src/operations/bitwise.ts +366 -366
- package/src/operations/comparison.ts +271 -271
- package/src/operations/conversion.ts +399 -399
- package/src/operations/factorial.ts +278 -278
- package/src/operations/index.ts +4 -4
- package/src/operations/power.ts +315 -315
- package/src/storage/Heap.ts +237 -237
- package/src/storage/index.ts +0 -0
- package/src/structures/ackermann.ts +232 -232
- package/src/structures/big-array.ts +305 -305
- package/src/structures/index.ts +3 -3
- package/src/structures/number-tree.ts +403 -403
- package/src/structures/power-tower.ts +277 -277
- package/src/types/common.d.ts +356 -356
- package/src/types/core.d.ts +160 -160
- package/src/types/index.d.ts +1 -1
- package/src/utils/formatting.ts +245 -245
- package/src/utils/index.ts +4 -4
- package/src/utils/parser.ts +244 -244
- package/src/utils/precision.ts +216 -216
- package/src/utils/validation.ts +182 -182
- package/tsconfig.json +83 -83
- package/dist/types/config/config-loader.d.ts.map +0 -1
- package/dist/types/config/config-parser.d.ts.map +0 -1
- package/dist/types/config/config-resolver.d.ts.map +0 -1
- package/dist/types/config/config-source.d.ts.map +0 -1
- package/dist/types/config/index.d.ts.map +0 -1
- package/dist/types/core/common.d.ts.map +0 -1
- package/dist/types/core/config.d.ts.map +0 -1
- package/dist/types/core/constants.d.ts.map +0 -1
- package/dist/types/core/errors.d.ts.map +0 -1
- package/dist/types/core/hypernum.d.ts.map +0 -1
- package/dist/types/core/index.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/operations/arithmetic.d.ts.map +0 -1
- package/dist/types/operations/bitwise.d.ts.map +0 -1
- package/dist/types/operations/comparison.d.ts.map +0 -1
- package/dist/types/operations/conversion.d.ts.map +0 -1
- package/dist/types/operations/factorial.d.ts.map +0 -1
- package/dist/types/operations/index.d.ts.map +0 -1
- package/dist/types/operations/power.d.ts.map +0 -1
- package/dist/types/storage/Heap.d.ts.map +0 -1
- package/dist/types/storage/index.d.ts.map +0 -1
- package/dist/types/structures/ackermann.d.ts.map +0 -1
- package/dist/types/structures/big-array.d.ts.map +0 -1
- package/dist/types/structures/index.d.ts.map +0 -1
- package/dist/types/structures/number-tree.d.ts.map +0 -1
- package/dist/types/structures/power-tower.d.ts.map +0 -1
- package/dist/types/utils/formatting.d.ts.map +0 -1
- package/dist/types/utils/index.d.ts.map +0 -1
- package/dist/types/utils/parser.d.ts.map +0 -1
- package/dist/types/utils/precision.d.ts.map +0 -1
- package/dist/types/utils/validation.d.ts.map +0 -1
|
@@ -1,279 +1,279 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Factorial operations module for Hypernum library
|
|
3
|
-
* Provides efficient implementations for factorial and related computations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
toBigInt,
|
|
8
|
-
ValidationError,
|
|
9
|
-
OverflowError,
|
|
10
|
-
validateNonNegative
|
|
11
|
-
} from '../utils/validation';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Options for factorial operations
|
|
15
|
-
*/
|
|
16
|
-
export interface FactorialOptions {
|
|
17
|
-
/** Maximum allowed computation value */
|
|
18
|
-
maxValue?: number;
|
|
19
|
-
/** Whether to check for overflow */
|
|
20
|
-
checkOverflow?: boolean;
|
|
21
|
-
/** Cache computed values */
|
|
22
|
-
useCache?: boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const DEFAULT_OPTIONS: Required<FactorialOptions> = {
|
|
26
|
-
maxValue: 1000,
|
|
27
|
-
checkOverflow: true,
|
|
28
|
-
useCache: true
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// Cache for factorial values
|
|
32
|
-
const factorialCache = new Map<bigint, bigint>();
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Calculates factorial of a number (n!)
|
|
36
|
-
*/
|
|
37
|
-
export function factorial(
|
|
38
|
-
value: bigint | string | number,
|
|
39
|
-
options: FactorialOptions = {}
|
|
40
|
-
): bigint {
|
|
41
|
-
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
42
|
-
const n = toBigInt(value);
|
|
43
|
-
|
|
44
|
-
validateNonNegative(n);
|
|
45
|
-
|
|
46
|
-
if (opts.checkOverflow && n > BigInt(opts.maxValue)) {
|
|
47
|
-
throw new OverflowError(`Factorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Handle base cases
|
|
51
|
-
if (n <= 1n) {
|
|
52
|
-
return 1n;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Check cache
|
|
56
|
-
if (opts.useCache && factorialCache.has(n)) {
|
|
57
|
-
return factorialCache.get(n)!;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Calculate factorial
|
|
61
|
-
let result = 1n;
|
|
62
|
-
for (let i = 2n; i <= n; i++) {
|
|
63
|
-
result *= i;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Cache result
|
|
67
|
-
if (opts.useCache) {
|
|
68
|
-
factorialCache.set(n, result);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return result;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Calculates binomial coefficient (n choose k)
|
|
76
|
-
*/
|
|
77
|
-
export function binomial(
|
|
78
|
-
n: bigint | string | number,
|
|
79
|
-
k: bigint | string | number,
|
|
80
|
-
options: FactorialOptions = {}
|
|
81
|
-
): bigint {
|
|
82
|
-
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
83
|
-
const bigN = toBigInt(n);
|
|
84
|
-
const bigK = toBigInt(k);
|
|
85
|
-
|
|
86
|
-
validateNonNegative(bigN);
|
|
87
|
-
validateNonNegative(bigK);
|
|
88
|
-
|
|
89
|
-
if (bigK > bigN) {
|
|
90
|
-
throw new ValidationError('K cannot be greater than N in binomial coefficient');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Optimize for k > n/2 by using symmetry
|
|
94
|
-
if (bigK > bigN / 2n) {
|
|
95
|
-
return binomial(bigN, bigN - bigK, opts);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Use multiplicative formula instead of factorial for efficiency
|
|
99
|
-
let result = 1n;
|
|
100
|
-
for (let i = 0n; i < bigK; i++) {
|
|
101
|
-
result = (result * (bigN - i)) / (i + 1n);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return result;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Calculates subfactorial (derangement number)
|
|
109
|
-
* Number of permutations of n elements with no fixed points
|
|
110
|
-
*/
|
|
111
|
-
export function subfactorial(
|
|
112
|
-
value: bigint | string | number,
|
|
113
|
-
options: FactorialOptions = {}
|
|
114
|
-
): bigint {
|
|
115
|
-
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
116
|
-
const n = toBigInt(value);
|
|
117
|
-
|
|
118
|
-
validateNonNegative(n);
|
|
119
|
-
|
|
120
|
-
if (opts.checkOverflow && n > BigInt(opts.maxValue)) {
|
|
121
|
-
throw new OverflowError(`Subfactorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Handle base cases
|
|
125
|
-
if (n === 0n) return 1n;
|
|
126
|
-
if (n === 1n) return 0n;
|
|
127
|
-
|
|
128
|
-
// Use recursive formula !n = n * !(n-1) + (-1)^n
|
|
129
|
-
let result = 0n;
|
|
130
|
-
const nFact = factorial(n, opts);
|
|
131
|
-
|
|
132
|
-
for (let k = 0n; k <= n; k++) {
|
|
133
|
-
const term = factorial(n - k, opts) * (k % 2n === 0n ? 1n : -1n);
|
|
134
|
-
result += term;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return nFact - result;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Calculates rising factorial (Pochhammer symbol)
|
|
142
|
-
* x^(n) = x(x+1)(x+2)...(x+n-1)
|
|
143
|
-
*/
|
|
144
|
-
export function risingFactorial(
|
|
145
|
-
x: bigint | string | number,
|
|
146
|
-
n: bigint | string | number,
|
|
147
|
-
options: FactorialOptions = {}
|
|
148
|
-
): bigint {
|
|
149
|
-
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
150
|
-
const bigX = toBigInt(x);
|
|
151
|
-
const bigN = toBigInt(n);
|
|
152
|
-
|
|
153
|
-
validateNonNegative(bigN);
|
|
154
|
-
|
|
155
|
-
if (opts.checkOverflow && bigN > BigInt(opts.maxValue)) {
|
|
156
|
-
throw new OverflowError(`Rising factorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
let result = 1n;
|
|
160
|
-
for (let i = 0n; i < bigN; i++) {
|
|
161
|
-
result *= (bigX + i);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return result;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Calculates falling factorial
|
|
169
|
-
* x_(n) = x(x-1)(x-2)...(x-n+1)
|
|
170
|
-
*/
|
|
171
|
-
export function fallingFactorial(
|
|
172
|
-
x: bigint | string | number,
|
|
173
|
-
n: bigint | string | number,
|
|
174
|
-
options: FactorialOptions = {}
|
|
175
|
-
): bigint {
|
|
176
|
-
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
177
|
-
const bigX = toBigInt(x);
|
|
178
|
-
const bigN = toBigInt(n);
|
|
179
|
-
|
|
180
|
-
validateNonNegative(bigN);
|
|
181
|
-
|
|
182
|
-
if (opts.checkOverflow && bigN > BigInt(opts.maxValue)) {
|
|
183
|
-
throw new OverflowError(`Falling factorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
let result = 1n;
|
|
187
|
-
for (let i = 0n; i < bigN; i++) {
|
|
188
|
-
result *= (bigX - i);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return result;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Calculates multifactorial (n!!)
|
|
196
|
-
* Product of numbers from 1 to n that leave the same remainder as n when divided by k
|
|
197
|
-
*/
|
|
198
|
-
export function multiFactorial(
|
|
199
|
-
value: bigint | string | number,
|
|
200
|
-
k: bigint | string | number = 2n,
|
|
201
|
-
options: FactorialOptions = {}
|
|
202
|
-
): bigint {
|
|
203
|
-
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
204
|
-
const n = toBigInt(value);
|
|
205
|
-
const bigK = toBigInt(k);
|
|
206
|
-
|
|
207
|
-
validateNonNegative(n);
|
|
208
|
-
if (bigK <= 0n) {
|
|
209
|
-
throw new ValidationError('K must be positive in multifactorial');
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (opts.checkOverflow && n > BigInt(opts.maxValue)) {
|
|
213
|
-
throw new OverflowError(`Multifactorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
let result = 1n;
|
|
217
|
-
let current = n;
|
|
218
|
-
|
|
219
|
-
while (current > 0n) {
|
|
220
|
-
result *= current;
|
|
221
|
-
current -= bigK;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
return result;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Calculates primorial (product of primes up to n)
|
|
229
|
-
*/
|
|
230
|
-
export function primorial(
|
|
231
|
-
value: bigint | string | number,
|
|
232
|
-
options: FactorialOptions = {}
|
|
233
|
-
): bigint {
|
|
234
|
-
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
235
|
-
const n = toBigInt(value);
|
|
236
|
-
|
|
237
|
-
validateNonNegative(n);
|
|
238
|
-
|
|
239
|
-
if (opts.checkOverflow && n > BigInt(opts.maxValue)) {
|
|
240
|
-
throw new OverflowError(`Primorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (n <= 1n) return 1n;
|
|
244
|
-
|
|
245
|
-
// Generate primes up to n using Sieve of Eratosthenes
|
|
246
|
-
const num = Number(n);
|
|
247
|
-
const sieve = new Array(num + 1).fill(true);
|
|
248
|
-
sieve[0] = sieve[1] = false;
|
|
249
|
-
|
|
250
|
-
for (let i = 2; i * i <= num; i++) {
|
|
251
|
-
if (sieve[i]) {
|
|
252
|
-
for (let j = i * i; j <= num; j += i) {
|
|
253
|
-
sieve[j] = false;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Calculate product of all primes up to n
|
|
259
|
-
let result = 1n;
|
|
260
|
-
for (let i = 2; i <= num; i++) {
|
|
261
|
-
if (sieve[i]) {
|
|
262
|
-
result *= BigInt(i);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
return result;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
export default {
|
|
272
|
-
factorial,
|
|
273
|
-
binomial,
|
|
274
|
-
subfactorial,
|
|
275
|
-
risingFactorial,
|
|
276
|
-
fallingFactorial,
|
|
277
|
-
multiFactorial,
|
|
278
|
-
primorial
|
|
1
|
+
/**
|
|
2
|
+
* Factorial operations module for Hypernum library
|
|
3
|
+
* Provides efficient implementations for factorial and related computations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
toBigInt,
|
|
8
|
+
ValidationError,
|
|
9
|
+
OverflowError,
|
|
10
|
+
validateNonNegative
|
|
11
|
+
} from '../utils/validation';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Options for factorial operations
|
|
15
|
+
*/
|
|
16
|
+
export interface FactorialOptions {
|
|
17
|
+
/** Maximum allowed computation value */
|
|
18
|
+
maxValue?: number;
|
|
19
|
+
/** Whether to check for overflow */
|
|
20
|
+
checkOverflow?: boolean;
|
|
21
|
+
/** Cache computed values */
|
|
22
|
+
useCache?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const DEFAULT_OPTIONS: Required<FactorialOptions> = {
|
|
26
|
+
maxValue: 1000,
|
|
27
|
+
checkOverflow: true,
|
|
28
|
+
useCache: true
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Cache for factorial values
|
|
32
|
+
const factorialCache = new Map<bigint, bigint>();
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Calculates factorial of a number (n!)
|
|
36
|
+
*/
|
|
37
|
+
export function factorial(
|
|
38
|
+
value: bigint | string | number,
|
|
39
|
+
options: FactorialOptions = {}
|
|
40
|
+
): bigint {
|
|
41
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
42
|
+
const n = toBigInt(value);
|
|
43
|
+
|
|
44
|
+
validateNonNegative(n);
|
|
45
|
+
|
|
46
|
+
if (opts.checkOverflow && n > BigInt(opts.maxValue)) {
|
|
47
|
+
throw new OverflowError(`Factorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Handle base cases
|
|
51
|
+
if (n <= 1n) {
|
|
52
|
+
return 1n;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Check cache
|
|
56
|
+
if (opts.useCache && factorialCache.has(n)) {
|
|
57
|
+
return factorialCache.get(n)!;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Calculate factorial
|
|
61
|
+
let result = 1n;
|
|
62
|
+
for (let i = 2n; i <= n; i++) {
|
|
63
|
+
result *= i;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Cache result
|
|
67
|
+
if (opts.useCache) {
|
|
68
|
+
factorialCache.set(n, result);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Calculates binomial coefficient (n choose k)
|
|
76
|
+
*/
|
|
77
|
+
export function binomial(
|
|
78
|
+
n: bigint | string | number,
|
|
79
|
+
k: bigint | string | number,
|
|
80
|
+
options: FactorialOptions = {}
|
|
81
|
+
): bigint {
|
|
82
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
83
|
+
const bigN = toBigInt(n);
|
|
84
|
+
const bigK = toBigInt(k);
|
|
85
|
+
|
|
86
|
+
validateNonNegative(bigN);
|
|
87
|
+
validateNonNegative(bigK);
|
|
88
|
+
|
|
89
|
+
if (bigK > bigN) {
|
|
90
|
+
throw new ValidationError('K cannot be greater than N in binomial coefficient');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Optimize for k > n/2 by using symmetry
|
|
94
|
+
if (bigK > bigN / 2n) {
|
|
95
|
+
return binomial(bigN, bigN - bigK, opts);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Use multiplicative formula instead of factorial for efficiency
|
|
99
|
+
let result = 1n;
|
|
100
|
+
for (let i = 0n; i < bigK; i++) {
|
|
101
|
+
result = (result * (bigN - i)) / (i + 1n);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Calculates subfactorial (derangement number)
|
|
109
|
+
* Number of permutations of n elements with no fixed points
|
|
110
|
+
*/
|
|
111
|
+
export function subfactorial(
|
|
112
|
+
value: bigint | string | number,
|
|
113
|
+
options: FactorialOptions = {}
|
|
114
|
+
): bigint {
|
|
115
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
116
|
+
const n = toBigInt(value);
|
|
117
|
+
|
|
118
|
+
validateNonNegative(n);
|
|
119
|
+
|
|
120
|
+
if (opts.checkOverflow && n > BigInt(opts.maxValue)) {
|
|
121
|
+
throw new OverflowError(`Subfactorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Handle base cases
|
|
125
|
+
if (n === 0n) return 1n;
|
|
126
|
+
if (n === 1n) return 0n;
|
|
127
|
+
|
|
128
|
+
// Use recursive formula !n = n * !(n-1) + (-1)^n
|
|
129
|
+
let result = 0n;
|
|
130
|
+
const nFact = factorial(n, opts);
|
|
131
|
+
|
|
132
|
+
for (let k = 0n; k <= n; k++) {
|
|
133
|
+
const term = factorial(n - k, opts) * (k % 2n === 0n ? 1n : -1n);
|
|
134
|
+
result += term;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return nFact - result;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Calculates rising factorial (Pochhammer symbol)
|
|
142
|
+
* x^(n) = x(x+1)(x+2)...(x+n-1)
|
|
143
|
+
*/
|
|
144
|
+
export function risingFactorial(
|
|
145
|
+
x: bigint | string | number,
|
|
146
|
+
n: bigint | string | number,
|
|
147
|
+
options: FactorialOptions = {}
|
|
148
|
+
): bigint {
|
|
149
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
150
|
+
const bigX = toBigInt(x);
|
|
151
|
+
const bigN = toBigInt(n);
|
|
152
|
+
|
|
153
|
+
validateNonNegative(bigN);
|
|
154
|
+
|
|
155
|
+
if (opts.checkOverflow && bigN > BigInt(opts.maxValue)) {
|
|
156
|
+
throw new OverflowError(`Rising factorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
let result = 1n;
|
|
160
|
+
for (let i = 0n; i < bigN; i++) {
|
|
161
|
+
result *= (bigX + i);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Calculates falling factorial
|
|
169
|
+
* x_(n) = x(x-1)(x-2)...(x-n+1)
|
|
170
|
+
*/
|
|
171
|
+
export function fallingFactorial(
|
|
172
|
+
x: bigint | string | number,
|
|
173
|
+
n: bigint | string | number,
|
|
174
|
+
options: FactorialOptions = {}
|
|
175
|
+
): bigint {
|
|
176
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
177
|
+
const bigX = toBigInt(x);
|
|
178
|
+
const bigN = toBigInt(n);
|
|
179
|
+
|
|
180
|
+
validateNonNegative(bigN);
|
|
181
|
+
|
|
182
|
+
if (opts.checkOverflow && bigN > BigInt(opts.maxValue)) {
|
|
183
|
+
throw new OverflowError(`Falling factorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
let result = 1n;
|
|
187
|
+
for (let i = 0n; i < bigN; i++) {
|
|
188
|
+
result *= (bigX - i);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return result;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Calculates multifactorial (n!!)
|
|
196
|
+
* Product of numbers from 1 to n that leave the same remainder as n when divided by k
|
|
197
|
+
*/
|
|
198
|
+
export function multiFactorial(
|
|
199
|
+
value: bigint | string | number,
|
|
200
|
+
k: bigint | string | number = 2n,
|
|
201
|
+
options: FactorialOptions = {}
|
|
202
|
+
): bigint {
|
|
203
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
204
|
+
const n = toBigInt(value);
|
|
205
|
+
const bigK = toBigInt(k);
|
|
206
|
+
|
|
207
|
+
validateNonNegative(n);
|
|
208
|
+
if (bigK <= 0n) {
|
|
209
|
+
throw new ValidationError('K must be positive in multifactorial');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (opts.checkOverflow && n > BigInt(opts.maxValue)) {
|
|
213
|
+
throw new OverflowError(`Multifactorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
let result = 1n;
|
|
217
|
+
let current = n;
|
|
218
|
+
|
|
219
|
+
while (current > 0n) {
|
|
220
|
+
result *= current;
|
|
221
|
+
current -= bigK;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Calculates primorial (product of primes up to n)
|
|
229
|
+
*/
|
|
230
|
+
export function primorial(
|
|
231
|
+
value: bigint | string | number,
|
|
232
|
+
options: FactorialOptions = {}
|
|
233
|
+
): bigint {
|
|
234
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
235
|
+
const n = toBigInt(value);
|
|
236
|
+
|
|
237
|
+
validateNonNegative(n);
|
|
238
|
+
|
|
239
|
+
if (opts.checkOverflow && n > BigInt(opts.maxValue)) {
|
|
240
|
+
throw new OverflowError(`Primorial input too large: maximum allowed is ${opts.maxValue}`);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (n <= 1n) return 1n;
|
|
244
|
+
|
|
245
|
+
// Generate primes up to n using Sieve of Eratosthenes
|
|
246
|
+
const num = Number(n);
|
|
247
|
+
const sieve = new Array(num + 1).fill(true);
|
|
248
|
+
sieve[0] = sieve[1] = false;
|
|
249
|
+
|
|
250
|
+
for (let i = 2; i * i <= num; i++) {
|
|
251
|
+
if (sieve[i]) {
|
|
252
|
+
for (let j = i * i; j <= num; j += i) {
|
|
253
|
+
sieve[j] = false;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Calculate product of all primes up to n
|
|
259
|
+
let result = 1n;
|
|
260
|
+
for (let i = 2; i <= num; i++) {
|
|
261
|
+
if (sieve[i]) {
|
|
262
|
+
result *= BigInt(i);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return result;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
export default {
|
|
272
|
+
factorial,
|
|
273
|
+
binomial,
|
|
274
|
+
subfactorial,
|
|
275
|
+
risingFactorial,
|
|
276
|
+
fallingFactorial,
|
|
277
|
+
multiFactorial,
|
|
278
|
+
primorial
|
|
279
279
|
};
|
package/src/operations/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export * from './arithmetic';
|
|
2
|
-
export * from './comparison';
|
|
3
|
-
export * from './conversion';
|
|
4
|
-
export * from './bitwise';
|
|
1
|
+
export * from './arithmetic';
|
|
2
|
+
export * from './comparison';
|
|
3
|
+
export * from './conversion';
|
|
4
|
+
export * from './bitwise';
|
|
5
5
|
export * from './factorial'
|