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.
- package/LICENSE +1 -1
- package/README.md +130 -29
- package/dist/continuedfraction.d.mts +115 -0
- package/dist/continuedfraction.d.ts +16 -0
- package/dist/continuedfraction.js +248 -177
- package/dist/continuedfraction.js.map +7 -0
- package/dist/continuedfraction.min.js +8 -10
- package/dist/continuedfraction.mjs +954 -171
- package/dist/continuedfraction.mjs.map +7 -0
- package/package.json +31 -30
- package/continuedfraction.d.mts +0 -69
- package/continuedfraction.d.ts +0 -62
- package/src/continuedfraction.js +0 -179
- package/tests/continued.js +0 -50
|
@@ -1,177 +1,960 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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
|
-
|
|
172
|
-
|
|
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
|
|
957
|
+
ContinuedFraction,
|
|
958
|
+
continuedfraction_default as default
|
|
177
959
|
};
|
|
960
|
+
//# sourceMappingURL=continuedfraction.mjs.map
|