continuedfraction.js 0.0.2 → 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.
@@ -1,177 +1,960 @@
1
- 'use strict';
2
- import Fraction from 'fraction.js';
3
-
4
-
5
-
6
- /**
7
- * Utility class for generating continued-fraction expansions of various constants.
8
- */
9
- const ContinuedFraction = {
10
-
11
- /**
12
- * Infinite generator for the continued-fraction terms of sqrt(N).
13
- * √N = [a0; (a1, a2, ..., a_p)], where the period ends when ak = 2*a0.
14
- * For perfect squares, yields only a0 = floor(sqrt(N)) and then returns.
15
- *
16
- * @param {number} N - Integer whose square root CF expansion is desired (N ≥ 0).
17
- * @yields {number} - Next continued-fraction term of √N.
18
- */
19
- "sqrt": function* (N) {
20
-
21
- const a0 = Math.floor(Math.sqrt(N));
22
- yield a0;
23
- if (a0 * a0 === N) return; // perfect square: single-term CF
24
-
25
- //while (true) {
26
- let nk = 0;
27
- let dk = 1;
28
- let ak = a0;
29
-
30
- do {
31
- nk = ak * dk - nk;
32
- dk = (N - nk * nk) / dk; // remains integer by construction
33
- ak = Math.floor((a0 + nk) / dk);
34
- yield ak;
35
- } while (/* 2 * a0 !== ak */ true);
36
- //}
37
- },
38
-
39
- /**
40
- * Generator for continued-fraction terms of any real number via Fraction.js.
41
- *
42
- * @exports
43
- * @param {number|string|BigInt} n - The real number to convert (as number or string).
44
- * @yields {number} - Next continued-fraction term of n.
45
- */
46
- "fromNumber": function* (n) {
47
-
48
- yield* Fraction(n)['toContinued']();
49
- },
50
-
51
- /**
52
- * Generator for continued-fraction terms of a rational a/b via Fraction.js.
53
- *
54
- * @param {number|string|BigInt|Fraction} a - Numerator.
55
- * @param {number|string|BigInt} b - Denominator.
56
- * @yields {number} - Next continued-fraction term of a/b.
57
- */
58
- "fromFraction": function* (a, b) {
59
-
60
- yield* Fraction(a, b)['toContinued']();
61
- },
62
-
63
- /**
64
- * Infinite generator of the golden ratio φ = [1; 1, 1, 1, …].
65
- *
66
- * @yields {number} - Always 1.
67
- */
68
- "PHI": function* () {
69
-
70
- while (true) {
71
- yield 1;
72
- }
73
- },
74
-
75
- /**
76
- * Infinite generator for Continued‐fraction terms of 4/π:
77
- * 4/π = 1 + 1²/(3 + 2²/(5 + 3²/(7 + …)))
78
- * @yields {{a:number,b:number}} - Term pair (aₙ, bₙ) of the generalized continued fraction.
79
- * - first: a₀ = 1
80
- * - then: aₙ = 2n+1, bₙ = n² (n ≥ 1)
81
- */
82
- "FOUR_OVER_PI": function* () {
83
-
84
- yield { "a": 1, "b": 0 }; // a₀ = 1
85
-
86
- for (let n = 0; true; n++) {
87
- yield { "a": 2, "b": (n * 2 + 1) ** 2 };
88
- }
89
- },
90
-
91
- /**
92
- * Infinite generator for Continued‐fraction terms of π:
93
- * π = 3 + 1²/(6 + 3²/(6 + 5²/(6 + …)))
94
- * @yields {{a:number,b:number}} - Term pair (aₙ, bₙ) of the generalized continued fraction.
95
- * - first: a₀ = 3
96
- * - then: aₙ = 6, bₙ = (2n-1)² (n ≥ 1)
97
- */
98
- "PI": function* () {
99
-
100
- yield { "a": 3, "b": 0 }; // a₀ = 3
101
-
102
- for (let n = 1; true; n++) {
103
- yield { "a": 6, "b": (n * 2 - 1) ** 2 };
104
- }
105
- },
106
-
107
- /**
108
- * Infinite generator of e = [2; 1, 2, 1, 1, 4, 1, …].
109
- * Terms follow the pattern [2; (1,2m,1) for m = 1,2,3,…].
110
- *
111
- * @yields {number} - Next continued-fraction term of e.
112
- */
113
- "E": function* () {
114
-
115
- yield 2; // a₀ = 2
116
-
117
- for (let m = 1; ; m++) {
118
- yield 1;
119
- yield 2 * m;
120
- yield 1;
121
- }
122
-
123
- /* Alternative:
124
- yield { a: 2, b: 0 }; // a₀ = 2
125
- yield { a: 1, b: 1 }; // a₁ = 1
126
-
127
- for (let m = 2; ; m++) {
128
- yield { a: n, b: m - 1 };
129
- }
130
- */
131
- },
132
-
133
- /**
134
- * Evaluate a (simple or generalized) continued fraction generator.
135
- * For generalized: terms are objects { a, b }, else regular numbers.
136
- *
137
- * @param {Generator|Function} generator - Continued fraction term generator.
138
- * @param {number} steps - Number of terms to evaluate.
139
- * @returns {Fraction} - Rational approximation as Fraction.
140
- */
141
- "eval": function (generator, steps = 10) {
142
-
143
- if (typeof generator === "function") {
144
- generator = generator();
1
+ // node_modules/fraction.js/dist/fraction.mjs
2
+ if (typeof BigInt === "undefined") BigInt = function(n) {
3
+ if (isNaN(n)) throw new Error("");
4
+ return n;
5
+ };
6
+ var C_ZERO = BigInt(0);
7
+ var C_ONE = BigInt(1);
8
+ var C_TWO = BigInt(2);
9
+ var C_FIVE = BigInt(5);
10
+ var C_TEN = BigInt(10);
11
+ var MAX_CYCLE_LEN = 2e3;
12
+ var P = {
13
+ "s": C_ONE,
14
+ "n": C_ZERO,
15
+ "d": C_ONE
16
+ };
17
+ function assign(n, s) {
18
+ try {
19
+ n = BigInt(n);
20
+ } catch (e) {
21
+ throw InvalidParameter();
22
+ }
23
+ return n * s;
24
+ }
25
+ function trunc(x) {
26
+ return typeof x === "bigint" ? x : Math.floor(x);
27
+ }
28
+ function newFraction(n, d) {
29
+ if (d === C_ZERO) {
30
+ throw DivisionByZero();
31
+ }
32
+ const f = Object.create(Fraction.prototype);
33
+ f["s"] = n < C_ZERO ? -C_ONE : C_ONE;
34
+ n = n < C_ZERO ? -n : n;
35
+ const a = gcd(n, d);
36
+ f["n"] = n / a;
37
+ f["d"] = d / a;
38
+ return f;
39
+ }
40
+ function factorize(num) {
41
+ const factors = {};
42
+ let n = num;
43
+ let i = C_TWO;
44
+ let s = C_FIVE - C_ONE;
45
+ while (s <= n) {
46
+ while (n % i === C_ZERO) {
47
+ n /= i;
48
+ factors[i] = (factors[i] || C_ZERO) + C_ONE;
49
+ }
50
+ s += C_ONE + C_TWO * i++;
51
+ }
52
+ if (n !== num) {
53
+ if (n > 1)
54
+ factors[n] = (factors[n] || C_ZERO) + C_ONE;
55
+ } else {
56
+ factors[num] = (factors[num] || C_ZERO) + C_ONE;
57
+ }
58
+ return factors;
59
+ }
60
+ var parse = function(p1, p2) {
61
+ let n = C_ZERO, d = C_ONE, s = C_ONE;
62
+ if (p1 === void 0 || p1 === null) {
63
+ } else if (p2 !== void 0) {
64
+ if (typeof p1 === "bigint") {
65
+ n = p1;
66
+ } else if (isNaN(p1)) {
67
+ throw InvalidParameter();
68
+ } else if (p1 % 1 !== 0) {
69
+ throw NonIntegerParameter();
70
+ } else {
71
+ n = BigInt(p1);
72
+ }
73
+ if (typeof p2 === "bigint") {
74
+ d = p2;
75
+ } else if (isNaN(p2)) {
76
+ throw InvalidParameter();
77
+ } else if (p2 % 1 !== 0) {
78
+ throw NonIntegerParameter();
79
+ } else {
80
+ d = BigInt(p2);
81
+ }
82
+ s = n * d;
83
+ } else if (typeof p1 === "object") {
84
+ if ("d" in p1 && "n" in p1) {
85
+ n = BigInt(p1["n"]);
86
+ d = BigInt(p1["d"]);
87
+ if ("s" in p1)
88
+ n *= BigInt(p1["s"]);
89
+ } else if (0 in p1) {
90
+ n = BigInt(p1[0]);
91
+ if (1 in p1)
92
+ d = BigInt(p1[1]);
93
+ } else if (typeof p1 === "bigint") {
94
+ n = p1;
95
+ } else {
96
+ throw InvalidParameter();
97
+ }
98
+ s = n * d;
99
+ } else if (typeof p1 === "number") {
100
+ if (isNaN(p1)) {
101
+ throw InvalidParameter();
102
+ }
103
+ if (p1 < 0) {
104
+ s = -C_ONE;
105
+ p1 = -p1;
106
+ }
107
+ if (p1 % 1 === 0) {
108
+ n = BigInt(p1);
109
+ } else {
110
+ let z = 1;
111
+ let A = 0, B = 1;
112
+ let C = 1, D = 1;
113
+ let N = 1e7;
114
+ if (p1 >= 1) {
115
+ z = 10 ** Math.floor(1 + Math.log10(p1));
116
+ p1 /= z;
117
+ }
118
+ while (B <= N && D <= N) {
119
+ let M = (A + C) / (B + D);
120
+ if (p1 === M) {
121
+ if (B + D <= N) {
122
+ n = A + C;
123
+ d = B + D;
124
+ } else if (D > B) {
125
+ n = C;
126
+ d = D;
127
+ } else {
128
+ n = A;
129
+ d = B;
130
+ }
131
+ break;
132
+ } else {
133
+ if (p1 > M) {
134
+ A += C;
135
+ B += D;
136
+ } else {
137
+ C += A;
138
+ D += B;
139
+ }
140
+ if (B > N) {
141
+ n = C;
142
+ d = D;
143
+ } else {
144
+ n = A;
145
+ d = B;
146
+ }
145
147
  }
146
-
147
- // pull off a₀ (with its b₀)
148
- const first = generator['next']();
149
- if (first['done']) return Fraction(0);
150
-
151
- const a0 = Fraction(first['value']['a'] ?? first['value']);
152
-
153
- // initialize convergents p₋₁/q₋₁ = 1/0, p₀/q₀ = a₀/1
154
- let pCurr = a0, qCurr = Fraction(1);
155
- let pPrev = Fraction(1), qPrev = Fraction(0);
156
-
157
- // run through a₁… up to `steps-1` more
158
- for (let k = 1; k < steps; k++) {
159
- const { value, done } = generator['next']();
160
- if (done) break;
161
-
162
- const ak = Fraction(value['a'] ?? value),
163
- bk = Fraction(value['b'] ?? 1);
164
-
165
- // pₖ = aₖ·pₖ₋₁ + bₖ·pₖ₋₂
166
- // qₖ = aₖ·qₖ₋₁ + bₖ·qₖ₋₂
167
- [pPrev, pCurr] = [pCurr, ak['mul'](pCurr)['add'](bk['mul'](pPrev))];
168
- [qPrev, qCurr] = [qCurr, ak['mul'](qCurr)['add'](bk['mul'](qPrev))];
148
+ }
149
+ n = BigInt(n) * BigInt(z);
150
+ d = BigInt(d);
151
+ }
152
+ } else if (typeof p1 === "string") {
153
+ let ndx = 0;
154
+ let v = C_ZERO, w = C_ZERO, x = C_ZERO, y = C_ONE, z = C_ONE;
155
+ let match = p1.replace(/_/g, "").match(/\d+|./g);
156
+ if (match === null)
157
+ throw InvalidParameter();
158
+ if (match[ndx] === "-") {
159
+ s = -C_ONE;
160
+ ndx++;
161
+ } else if (match[ndx] === "+") {
162
+ ndx++;
163
+ }
164
+ if (match.length === ndx + 1) {
165
+ w = assign(match[ndx++], s);
166
+ } else if (match[ndx + 1] === "." || match[ndx] === ".") {
167
+ if (match[ndx] !== ".") {
168
+ v = assign(match[ndx++], s);
169
+ }
170
+ ndx++;
171
+ if (ndx + 1 === match.length || match[ndx + 1] === "(" && match[ndx + 3] === ")" || match[ndx + 1] === "'" && match[ndx + 3] === "'") {
172
+ w = assign(match[ndx], s);
173
+ y = C_TEN ** BigInt(match[ndx].length);
174
+ ndx++;
175
+ }
176
+ if (match[ndx] === "(" && match[ndx + 2] === ")" || match[ndx] === "'" && match[ndx + 2] === "'") {
177
+ x = assign(match[ndx + 1], s);
178
+ z = C_TEN ** BigInt(match[ndx + 1].length) - C_ONE;
179
+ ndx += 3;
180
+ }
181
+ } else if (match[ndx + 1] === "/" || match[ndx + 1] === ":") {
182
+ w = assign(match[ndx], s);
183
+ y = assign(match[ndx + 2], C_ONE);
184
+ ndx += 3;
185
+ } else if (match[ndx + 3] === "/" && match[ndx + 1] === " ") {
186
+ v = assign(match[ndx], s);
187
+ w = assign(match[ndx + 2], s);
188
+ y = assign(match[ndx + 4], C_ONE);
189
+ ndx += 5;
190
+ }
191
+ if (match.length <= ndx) {
192
+ d = y * z;
193
+ s = /* void */
194
+ n = x + d * v + z * w;
195
+ } else {
196
+ throw InvalidParameter();
197
+ }
198
+ } else if (typeof p1 === "bigint") {
199
+ n = p1;
200
+ s = p1;
201
+ d = C_ONE;
202
+ } else {
203
+ throw InvalidParameter();
204
+ }
205
+ if (d === C_ZERO) {
206
+ throw DivisionByZero();
207
+ }
208
+ P["s"] = s < C_ZERO ? -C_ONE : C_ONE;
209
+ P["n"] = n < C_ZERO ? -n : n;
210
+ P["d"] = d < C_ZERO ? -d : d;
211
+ };
212
+ function modpow(b, e, m) {
213
+ let r = C_ONE;
214
+ for (; e > C_ZERO; b = b * b % m, e >>= C_ONE) {
215
+ if (e & C_ONE) {
216
+ r = r * b % m;
217
+ }
218
+ }
219
+ return r;
220
+ }
221
+ function cycleLen(n, d) {
222
+ for (; d % C_TWO === C_ZERO; d /= C_TWO) {
223
+ }
224
+ for (; d % C_FIVE === C_ZERO; d /= C_FIVE) {
225
+ }
226
+ if (d === C_ONE)
227
+ return C_ZERO;
228
+ let rem = C_TEN % d;
229
+ let t = 1;
230
+ for (; rem !== C_ONE; t++) {
231
+ rem = rem * C_TEN % d;
232
+ if (t > MAX_CYCLE_LEN)
233
+ return C_ZERO;
234
+ }
235
+ return BigInt(t);
236
+ }
237
+ function cycleStart(n, d, len) {
238
+ let rem1 = C_ONE;
239
+ let rem2 = modpow(C_TEN, len, d);
240
+ for (let t = 0; t < 300; t++) {
241
+ if (rem1 === rem2)
242
+ return BigInt(t);
243
+ rem1 = rem1 * C_TEN % d;
244
+ rem2 = rem2 * C_TEN % d;
245
+ }
246
+ return 0;
247
+ }
248
+ function gcd(a, b) {
249
+ if (!a)
250
+ return b;
251
+ if (!b)
252
+ return a;
253
+ while (1) {
254
+ a %= b;
255
+ if (!a)
256
+ return b;
257
+ b %= a;
258
+ if (!b)
259
+ return a;
260
+ }
261
+ }
262
+ function Fraction(a, b) {
263
+ parse(a, b);
264
+ if (this instanceof Fraction) {
265
+ a = gcd(P["d"], P["n"]);
266
+ this["s"] = P["s"];
267
+ this["n"] = P["n"] / a;
268
+ this["d"] = P["d"] / a;
269
+ } else {
270
+ return newFraction(P["s"] * P["n"], P["d"]);
271
+ }
272
+ }
273
+ var DivisionByZero = function() {
274
+ return new Error("Division by Zero");
275
+ };
276
+ var InvalidParameter = function() {
277
+ return new Error("Invalid argument");
278
+ };
279
+ var NonIntegerParameter = function() {
280
+ return new Error("Parameters must be integer");
281
+ };
282
+ Fraction.prototype = {
283
+ "s": C_ONE,
284
+ "n": C_ZERO,
285
+ "d": C_ONE,
286
+ /**
287
+ * Calculates the absolute value
288
+ *
289
+ * Ex: new Fraction(-4).abs() => 4
290
+ **/
291
+ "abs": function() {
292
+ return newFraction(this["n"], this["d"]);
293
+ },
294
+ /**
295
+ * Inverts the sign of the current fraction
296
+ *
297
+ * Ex: new Fraction(-4).neg() => 4
298
+ **/
299
+ "neg": function() {
300
+ return newFraction(-this["s"] * this["n"], this["d"]);
301
+ },
302
+ /**
303
+ * Adds two rational numbers
304
+ *
305
+ * Ex: new Fraction({n: 2, d: 3}).add("14.9") => 467 / 30
306
+ **/
307
+ "add": function(a, b) {
308
+ parse(a, b);
309
+ return newFraction(
310
+ this["s"] * this["n"] * P["d"] + P["s"] * this["d"] * P["n"],
311
+ this["d"] * P["d"]
312
+ );
313
+ },
314
+ /**
315
+ * Subtracts two rational numbers
316
+ *
317
+ * Ex: new Fraction({n: 2, d: 3}).add("14.9") => -427 / 30
318
+ **/
319
+ "sub": function(a, b) {
320
+ parse(a, b);
321
+ return newFraction(
322
+ this["s"] * this["n"] * P["d"] - P["s"] * this["d"] * P["n"],
323
+ this["d"] * P["d"]
324
+ );
325
+ },
326
+ /**
327
+ * Multiplies two rational numbers
328
+ *
329
+ * Ex: new Fraction("-17.(345)").mul(3) => 5776 / 111
330
+ **/
331
+ "mul": function(a, b) {
332
+ parse(a, b);
333
+ return newFraction(
334
+ this["s"] * P["s"] * this["n"] * P["n"],
335
+ this["d"] * P["d"]
336
+ );
337
+ },
338
+ /**
339
+ * Divides two rational numbers
340
+ *
341
+ * Ex: new Fraction("-17.(345)").inverse().div(3)
342
+ **/
343
+ "div": function(a, b) {
344
+ parse(a, b);
345
+ return newFraction(
346
+ this["s"] * P["s"] * this["n"] * P["d"],
347
+ this["d"] * P["n"]
348
+ );
349
+ },
350
+ /**
351
+ * Clones the actual object
352
+ *
353
+ * Ex: new Fraction("-17.(345)").clone()
354
+ **/
355
+ "clone": function() {
356
+ return newFraction(this["s"] * this["n"], this["d"]);
357
+ },
358
+ /**
359
+ * Calculates the modulo of two rational numbers - a more precise fmod
360
+ *
361
+ * Ex: new Fraction('4.(3)').mod([7, 8]) => (13/3) % (7/8) = (5/6)
362
+ * Ex: new Fraction(20, 10).mod().equals(0) ? "is Integer"
363
+ **/
364
+ "mod": function(a, b) {
365
+ if (a === void 0) {
366
+ return newFraction(this["s"] * this["n"] % this["d"], C_ONE);
367
+ }
368
+ parse(a, b);
369
+ if (C_ZERO === P["n"] * this["d"]) {
370
+ throw DivisionByZero();
371
+ }
372
+ return newFraction(
373
+ this["s"] * (P["d"] * this["n"]) % (P["n"] * this["d"]),
374
+ P["d"] * this["d"]
375
+ );
376
+ },
377
+ /**
378
+ * Calculates the fractional gcd of two rational numbers
379
+ *
380
+ * Ex: new Fraction(5,8).gcd(3,7) => 1/56
381
+ */
382
+ "gcd": function(a, b) {
383
+ parse(a, b);
384
+ return newFraction(gcd(P["n"], this["n"]) * gcd(P["d"], this["d"]), P["d"] * this["d"]);
385
+ },
386
+ /**
387
+ * Calculates the fractional lcm of two rational numbers
388
+ *
389
+ * Ex: new Fraction(5,8).lcm(3,7) => 15
390
+ */
391
+ "lcm": function(a, b) {
392
+ parse(a, b);
393
+ if (P["n"] === C_ZERO && this["n"] === C_ZERO) {
394
+ return newFraction(C_ZERO, C_ONE);
395
+ }
396
+ return newFraction(P["n"] * this["n"], gcd(P["n"], this["n"]) * gcd(P["d"], this["d"]));
397
+ },
398
+ /**
399
+ * Gets the inverse of the fraction, means numerator and denominator are exchanged
400
+ *
401
+ * Ex: new Fraction([-3, 4]).inverse() => -4 / 3
402
+ **/
403
+ "inverse": function() {
404
+ return newFraction(this["s"] * this["d"], this["n"]);
405
+ },
406
+ /**
407
+ * Calculates the fraction to some integer exponent
408
+ *
409
+ * Ex: new Fraction(-1,2).pow(-3) => -8
410
+ */
411
+ "pow": function(a, b) {
412
+ parse(a, b);
413
+ if (P["d"] === C_ONE) {
414
+ if (P["s"] < C_ZERO) {
415
+ return newFraction((this["s"] * this["d"]) ** P["n"], this["n"] ** P["n"]);
416
+ } else {
417
+ return newFraction((this["s"] * this["n"]) ** P["n"], this["d"] ** P["n"]);
418
+ }
419
+ }
420
+ if (this["s"] < C_ZERO) return null;
421
+ let N = factorize(this["n"]);
422
+ let D = factorize(this["d"]);
423
+ let n = C_ONE;
424
+ let d = C_ONE;
425
+ for (let k in N) {
426
+ if (k === "1") continue;
427
+ if (k === "0") {
428
+ n = C_ZERO;
429
+ break;
430
+ }
431
+ N[k] *= P["n"];
432
+ if (N[k] % P["d"] === C_ZERO) {
433
+ N[k] /= P["d"];
434
+ } else return null;
435
+ n *= BigInt(k) ** N[k];
436
+ }
437
+ for (let k in D) {
438
+ if (k === "1") continue;
439
+ D[k] *= P["n"];
440
+ if (D[k] % P["d"] === C_ZERO) {
441
+ D[k] /= P["d"];
442
+ } else return null;
443
+ d *= BigInt(k) ** D[k];
444
+ }
445
+ if (P["s"] < C_ZERO) {
446
+ return newFraction(d, n);
447
+ }
448
+ return newFraction(n, d);
449
+ },
450
+ /**
451
+ * Calculates the logarithm of a fraction to a given rational base
452
+ *
453
+ * Ex: new Fraction(27, 8).log(9, 4) => 3/2
454
+ */
455
+ "log": function(a, b) {
456
+ parse(a, b);
457
+ if (this["s"] <= C_ZERO || P["s"] <= C_ZERO) return null;
458
+ const allPrimes = {};
459
+ const baseFactors = factorize(P["n"]);
460
+ const T1 = factorize(P["d"]);
461
+ const numberFactors = factorize(this["n"]);
462
+ const T2 = factorize(this["d"]);
463
+ for (const prime in T1) {
464
+ baseFactors[prime] = (baseFactors[prime] || C_ZERO) - T1[prime];
465
+ }
466
+ for (const prime in T2) {
467
+ numberFactors[prime] = (numberFactors[prime] || C_ZERO) - T2[prime];
468
+ }
469
+ for (const prime in baseFactors) {
470
+ if (prime === "1") continue;
471
+ allPrimes[prime] = true;
472
+ }
473
+ for (const prime in numberFactors) {
474
+ if (prime === "1") continue;
475
+ allPrimes[prime] = true;
476
+ }
477
+ let retN = null;
478
+ let retD = null;
479
+ for (const prime in allPrimes) {
480
+ const baseExponent = baseFactors[prime] || C_ZERO;
481
+ const numberExponent = numberFactors[prime] || C_ZERO;
482
+ if (baseExponent === C_ZERO) {
483
+ if (numberExponent !== C_ZERO) {
484
+ return null;
169
485
  }
170
-
171
- // final convergent = pCurr/qCurr
172
- return pCurr['div'](qCurr);
486
+ continue;
487
+ }
488
+ let curN = numberExponent;
489
+ let curD = baseExponent;
490
+ const gcdValue = gcd(curN, curD);
491
+ curN /= gcdValue;
492
+ curD /= gcdValue;
493
+ if (retN === null && retD === null) {
494
+ retN = curN;
495
+ retD = curD;
496
+ } else if (curN * retD !== retN * curD) {
497
+ return null;
498
+ }
499
+ }
500
+ return retN !== null && retD !== null ? newFraction(retN, retD) : null;
501
+ },
502
+ /**
503
+ * Check if two rational numbers are the same
504
+ *
505
+ * Ex: new Fraction(19.6).equals([98, 5]);
506
+ **/
507
+ "equals": function(a, b) {
508
+ parse(a, b);
509
+ return this["s"] * this["n"] * P["d"] === P["s"] * P["n"] * this["d"];
510
+ },
511
+ /**
512
+ * Check if this rational number is less than another
513
+ *
514
+ * Ex: new Fraction(19.6).lt([98, 5]);
515
+ **/
516
+ "lt": function(a, b) {
517
+ parse(a, b);
518
+ return this["s"] * this["n"] * P["d"] < P["s"] * P["n"] * this["d"];
519
+ },
520
+ /**
521
+ * Check if this rational number is less than or equal another
522
+ *
523
+ * Ex: new Fraction(19.6).lt([98, 5]);
524
+ **/
525
+ "lte": function(a, b) {
526
+ parse(a, b);
527
+ return this["s"] * this["n"] * P["d"] <= P["s"] * P["n"] * this["d"];
528
+ },
529
+ /**
530
+ * Check if this rational number is greater than another
531
+ *
532
+ * Ex: new Fraction(19.6).lt([98, 5]);
533
+ **/
534
+ "gt": function(a, b) {
535
+ parse(a, b);
536
+ return this["s"] * this["n"] * P["d"] > P["s"] * P["n"] * this["d"];
537
+ },
538
+ /**
539
+ * Check if this rational number is greater than or equal another
540
+ *
541
+ * Ex: new Fraction(19.6).lt([98, 5]);
542
+ **/
543
+ "gte": function(a, b) {
544
+ parse(a, b);
545
+ return this["s"] * this["n"] * P["d"] >= P["s"] * P["n"] * this["d"];
546
+ },
547
+ /**
548
+ * Compare two rational numbers
549
+ * < 0 iff this < that
550
+ * > 0 iff this > that
551
+ * = 0 iff this = that
552
+ *
553
+ * Ex: new Fraction(19.6).compare([98, 5]);
554
+ **/
555
+ "compare": function(a, b) {
556
+ parse(a, b);
557
+ let t = this["s"] * this["n"] * P["d"] - P["s"] * P["n"] * this["d"];
558
+ return (C_ZERO < t) - (t < C_ZERO);
559
+ },
560
+ /**
561
+ * Calculates the ceil of a rational number
562
+ *
563
+ * Ex: new Fraction('4.(3)').ceil() => (5 / 1)
564
+ **/
565
+ "ceil": function(places) {
566
+ places = C_TEN ** BigInt(places || 0);
567
+ return newFraction(
568
+ trunc(this["s"] * places * this["n"] / this["d"]) + (places * this["n"] % this["d"] > C_ZERO && this["s"] >= C_ZERO ? C_ONE : C_ZERO),
569
+ places
570
+ );
571
+ },
572
+ /**
573
+ * Calculates the floor of a rational number
574
+ *
575
+ * Ex: new Fraction('4.(3)').floor() => (4 / 1)
576
+ **/
577
+ "floor": function(places) {
578
+ places = C_TEN ** BigInt(places || 0);
579
+ return newFraction(
580
+ trunc(this["s"] * places * this["n"] / this["d"]) - (places * this["n"] % this["d"] > C_ZERO && this["s"] < C_ZERO ? C_ONE : C_ZERO),
581
+ places
582
+ );
583
+ },
584
+ /**
585
+ * Rounds a rational numbers
586
+ *
587
+ * Ex: new Fraction('4.(3)').round() => (4 / 1)
588
+ **/
589
+ "round": function(places) {
590
+ places = C_TEN ** BigInt(places || 0);
591
+ return newFraction(
592
+ trunc(this["s"] * places * this["n"] / this["d"]) + this["s"] * ((this["s"] >= C_ZERO ? C_ONE : C_ZERO) + C_TWO * (places * this["n"] % this["d"]) > this["d"] ? C_ONE : C_ZERO),
593
+ places
594
+ );
595
+ },
596
+ /**
597
+ * Rounds a rational number to a multiple of another rational number
598
+ *
599
+ * Ex: new Fraction('0.9').roundTo("1/8") => 7 / 8
600
+ **/
601
+ "roundTo": function(a, b) {
602
+ parse(a, b);
603
+ const n = this["n"] * P["d"];
604
+ const d = this["d"] * P["n"];
605
+ const r = n % d;
606
+ let k = trunc(n / d);
607
+ if (r + r >= d) {
608
+ k++;
609
+ }
610
+ return newFraction(this["s"] * k * P["n"], P["d"]);
611
+ },
612
+ /**
613
+ * Check if two rational numbers are divisible
614
+ *
615
+ * Ex: new Fraction(19.6).divisible(1.5);
616
+ */
617
+ "divisible": function(a, b) {
618
+ parse(a, b);
619
+ return !(!(P["n"] * this["d"]) || this["n"] * P["d"] % (P["n"] * this["d"]));
620
+ },
621
+ /**
622
+ * Returns a decimal representation of the fraction
623
+ *
624
+ * Ex: new Fraction("100.'91823'").valueOf() => 100.91823918239183
625
+ **/
626
+ "valueOf": function() {
627
+ return Number(this["s"] * this["n"]) / Number(this["d"]);
628
+ },
629
+ /**
630
+ * Creates a string representation of a fraction with all digits
631
+ *
632
+ * Ex: new Fraction("100.'91823'").toString() => "100.(91823)"
633
+ **/
634
+ "toString": function(dec) {
635
+ let N = this["n"];
636
+ let D = this["d"];
637
+ dec = dec || 15;
638
+ let cycLen = cycleLen(N, D);
639
+ let cycOff = cycleStart(N, D, cycLen);
640
+ let str = this["s"] < C_ZERO ? "-" : "";
641
+ str += trunc(N / D);
642
+ N %= D;
643
+ N *= C_TEN;
644
+ if (N)
645
+ str += ".";
646
+ if (cycLen) {
647
+ for (let i = cycOff; i--; ) {
648
+ str += trunc(N / D);
649
+ N %= D;
650
+ N *= C_TEN;
651
+ }
652
+ str += "(";
653
+ for (let i = cycLen; i--; ) {
654
+ str += trunc(N / D);
655
+ N %= D;
656
+ N *= C_TEN;
657
+ }
658
+ str += ")";
659
+ } else {
660
+ for (let i = dec; N && i--; ) {
661
+ str += trunc(N / D);
662
+ N %= D;
663
+ N *= C_TEN;
664
+ }
665
+ }
666
+ return str;
667
+ },
668
+ /**
669
+ * Returns a string-fraction representation of a Fraction object
670
+ *
671
+ * Ex: new Fraction("1.'3'").toFraction() => "4 1/3"
672
+ **/
673
+ "toFraction": function(showMixed) {
674
+ let n = this["n"];
675
+ let d = this["d"];
676
+ let str = this["s"] < C_ZERO ? "-" : "";
677
+ if (d === C_ONE) {
678
+ str += n;
679
+ } else {
680
+ let whole = trunc(n / d);
681
+ if (showMixed && whole > C_ZERO) {
682
+ str += whole;
683
+ str += " ";
684
+ n %= d;
685
+ }
686
+ str += n;
687
+ str += "/";
688
+ str += d;
173
689
  }
690
+ return str;
691
+ },
692
+ /**
693
+ * Returns a latex representation of a Fraction object
694
+ *
695
+ * Ex: new Fraction("1.'3'").toLatex() => "\frac{4}{3}"
696
+ **/
697
+ "toLatex": function(showMixed) {
698
+ let n = this["n"];
699
+ let d = this["d"];
700
+ let str = this["s"] < C_ZERO ? "-" : "";
701
+ if (d === C_ONE) {
702
+ str += n;
703
+ } else {
704
+ let whole = trunc(n / d);
705
+ if (showMixed && whole > C_ZERO) {
706
+ str += whole;
707
+ n %= d;
708
+ }
709
+ str += "\\frac{";
710
+ str += n;
711
+ str += "}{";
712
+ str += d;
713
+ str += "}";
714
+ }
715
+ return str;
716
+ },
717
+ /**
718
+ * Returns an array of continued fraction elements
719
+ *
720
+ * Ex: new Fraction("7/8").toContinued() => [0,1,7]
721
+ */
722
+ "toContinued": function() {
723
+ let a = this["n"];
724
+ let b = this["d"];
725
+ let res = [];
726
+ do {
727
+ res.push(trunc(a / b));
728
+ let t = a % b;
729
+ a = b;
730
+ b = t;
731
+ } while (a !== C_ONE);
732
+ return res;
733
+ },
734
+ "simplify": function(eps) {
735
+ const ieps = BigInt(1 / (eps || 1e-3) | 0);
736
+ const thisABS = this["abs"]();
737
+ const cont = thisABS["toContinued"]();
738
+ for (let i = 1; i < cont.length; i++) {
739
+ let s = newFraction(cont[i - 1], C_ONE);
740
+ for (let k = i - 2; k >= 0; k--) {
741
+ s = s["inverse"]()["add"](cont[k]);
742
+ }
743
+ let t = s["sub"](thisABS);
744
+ if (t["n"] * ieps < t["d"]) {
745
+ return s["mul"](this["s"]);
746
+ }
747
+ }
748
+ return this;
749
+ }
750
+ };
751
+
752
+ // src/continuedfraction.ts
753
+ /**
754
+ * @license ContinuedFraction.js v0.1.0
755
+ * https://github.com/rawify/ContinuedFraction.js
756
+ *
757
+ * Copyright (c) 2026, Robert Eisele (https://raw.org/)
758
+ * Licensed under the MIT license.
759
+ **/
760
+ var Fraction2 = Fraction;
761
+ function iteratorFrom(source) {
762
+ return typeof source === "function" ? source() : source;
763
+ }
764
+ function coefficientOf(term) {
765
+ return typeof term === "object" && term !== null && "a" in term ? term.a : term;
174
766
  }
767
+ function numeratorOf(term) {
768
+ return typeof term === "object" && term !== null && "b" in term ? term.b : 1;
769
+ }
770
+ function validateSteps(steps) {
771
+ if (!Number.isSafeInteger(steps) || steps < 0) {
772
+ throw new RangeError("steps must be a non-negative safe integer");
773
+ }
774
+ }
775
+ var ContinuedFraction = class _ContinuedFraction {
776
+ constructor() {
777
+ throw new TypeError("ContinuedFraction is a static class");
778
+ }
779
+ /**
780
+ * Infinite generator for the continued-fraction terms of sqrt(N).
781
+ * sqrt(N) = [a0; (a1, a2, ..., a_p)], with a period boundary at ak = 2*a0.
782
+ * For perfect squares, yields only a0 = floor(sqrt(N)) and then returns.
783
+ *
784
+ * @param N Integer whose square-root CF expansion is desired (N >= 0).
785
+ * @yields Next continued-fraction term of sqrt(N).
786
+ */
787
+ static *sqrt(N) {
788
+ if (!Number.isSafeInteger(N) || N < 0) {
789
+ throw new RangeError("N must be a non-negative safe integer");
790
+ }
791
+ const a0 = Math.floor(Math.sqrt(N));
792
+ yield a0;
793
+ if (a0 * a0 === N) return;
794
+ let nk = 0;
795
+ let dk = 1;
796
+ let ak = a0;
797
+ while (true) {
798
+ nk = ak * dk - nk;
799
+ dk = (N - nk * nk) / dk;
800
+ ak = Math.floor((a0 + nk) / dk);
801
+ yield ak;
802
+ }
803
+ }
804
+ /**
805
+ * Generator for continued-fraction terms of any real number via Fraction.js.
806
+ *
807
+ * @param n The real number to convert (as number, string, or bigint).
808
+ * @yields Next continued-fraction term of n.
809
+ */
810
+ static *fromNumber(n) {
811
+ yield* Fraction2(n).toContinued();
812
+ }
813
+ /**
814
+ * Generator for continued-fraction terms of a rational a/b via Fraction.js.
815
+ *
816
+ * @param a Numerator, Fraction, or complete fraction string.
817
+ * @param b Optional denominator.
818
+ * @yields Next continued-fraction term of a/b.
819
+ */
820
+ static *fromFraction(a, b) {
821
+ const fraction = b === void 0 ? Fraction2(a) : Fraction2(a).div(Fraction2(b));
822
+ yield* fraction.toContinued();
823
+ }
824
+ /**
825
+ * Yields a finite sequence of simple or generalized terms unchanged.
826
+ *
827
+ * @param terms Continued-fraction terms.
828
+ * @yields Each supplied term in order.
829
+ */
830
+ static *fromTerms(terms) {
831
+ yield* terms;
832
+ }
833
+ /**
834
+ * Infinite generator of the golden ratio phi = [1; 1, 1, 1, ...].
835
+ *
836
+ * @yields Always 1.
837
+ */
838
+ static *PHI() {
839
+ while (true) {
840
+ yield 1;
841
+ }
842
+ }
843
+ /**
844
+ * Infinite generator for Brouncker's generalized continued fraction of 4/pi:
845
+ * 4/pi = 1 + 1^2/(2 + 3^2/(2 + 5^2/(2 + ...)))
846
+ *
847
+ * @yields Term pair (a_n, b_n) of the generalized continued fraction.
848
+ * - first: a_0 = 1
849
+ * - then: a_n = 2, b_n = (2n-1)^2 (n >= 1)
850
+ */
851
+ static *FOUR_OVER_PI() {
852
+ yield { a: 1, b: 0 };
853
+ for (let n = 1; true; n++) {
854
+ yield { a: 2, b: (n * 2 - 1) ** 2 };
855
+ }
856
+ }
857
+ /**
858
+ * Infinite generator for a generalized continued fraction of pi:
859
+ * pi = 3 + 1^2/(6 + 3^2/(6 + 5^2/(6 + ...)))
860
+ *
861
+ * @yields Term pair (a_n, b_n) of the generalized continued fraction.
862
+ * - first: a_0 = 3
863
+ * - then: a_n = 6, b_n = (2n-1)^2 (n >= 1)
864
+ */
865
+ static *PI() {
866
+ yield { a: 3, b: 0 };
867
+ for (let n = 1; true; n++) {
868
+ yield { a: 6, b: (n * 2 - 1) ** 2 };
869
+ }
870
+ }
871
+ /**
872
+ * Infinite generator of e = [2; 1, 2, 1, 1, 4, 1, ...].
873
+ * Terms follow the pattern [2; (1, 2m, 1) for m = 1, 2, 3, ...].
874
+ *
875
+ * @yields Next continued-fraction term of e.
876
+ */
877
+ static *E() {
878
+ yield 2;
879
+ for (let m = 1; true; m++) {
880
+ yield 1;
881
+ yield 2 * m;
882
+ yield 1;
883
+ }
884
+ }
885
+ /**
886
+ * Collects at most `steps` terms from a continued fraction.
887
+ *
888
+ * @param source Continued-fraction term iterator or a function returning one.
889
+ * @param steps Maximum number of terms to collect.
890
+ * @returns Collected terms in source order.
891
+ */
892
+ static toArray(source, steps = 10) {
893
+ validateSteps(steps);
894
+ const iterator = iteratorFrom(source);
895
+ const terms = [];
896
+ while (terms.length < steps) {
897
+ const result = iterator.next();
898
+ if (result.done) break;
899
+ terms.push(result.value);
900
+ }
901
+ return terms;
902
+ }
903
+ /**
904
+ * Generates every convergent of a simple or generalized continued fraction.
905
+ *
906
+ * @param source Continued-fraction term iterator or a function returning one.
907
+ * @yields Exact convergents as Fraction instances.
908
+ */
909
+ static *convergents(source) {
910
+ const iterator = iteratorFrom(source);
911
+ const first = iterator.next();
912
+ if (first.done) return;
913
+ let currentNumerator = Fraction2(coefficientOf(first.value));
914
+ let currentDenominator = Fraction2(1);
915
+ let previousNumerator = Fraction2(1);
916
+ let previousDenominator = Fraction2(0);
917
+ yield currentNumerator.div(currentDenominator);
918
+ while (true) {
919
+ const result = iterator.next();
920
+ if (result.done) return;
921
+ const coefficient = Fraction2(coefficientOf(result.value));
922
+ const numerator = Fraction2(numeratorOf(result.value));
923
+ [previousNumerator, currentNumerator] = [
924
+ currentNumerator,
925
+ coefficient.mul(currentNumerator).add(numerator.mul(previousNumerator))
926
+ ];
927
+ [previousDenominator, currentDenominator] = [
928
+ currentDenominator,
929
+ coefficient.mul(currentDenominator).add(numerator.mul(previousDenominator))
930
+ ];
931
+ yield currentNumerator.div(currentDenominator);
932
+ }
933
+ }
934
+ /**
935
+ * Evaluates a simple or generalized continued fraction generator.
936
+ * For generalized fractions terms are objects `{ a, b }`; otherwise they are coefficients.
937
+ *
938
+ * @param source Continued-fraction term iterator or a function returning one.
939
+ * @param steps Number of terms to evaluate.
940
+ * @returns Rational approximation as Fraction.
941
+ */
942
+ static eval(source, steps = 10) {
943
+ validateSteps(steps);
944
+ if (steps === 0) return Fraction2(0);
945
+ let approximation = Fraction2(0);
946
+ let count = 0;
947
+ for (const convergent of _ContinuedFraction.convergents(source)) {
948
+ approximation = convergent;
949
+ count++;
950
+ if (count === steps) break;
951
+ }
952
+ return approximation;
953
+ }
954
+ };
955
+ var continuedfraction_default = ContinuedFraction;
175
956
  export {
176
- ContinuedFraction as default, ContinuedFraction
957
+ ContinuedFraction,
958
+ continuedfraction_default as default
177
959
  };
960
+ //# sourceMappingURL=continuedfraction.mjs.map