solve-engine 1.0.0-beta.2 → 1.0.0-beta.4
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/dist/{Lexer-D9l4Yrk2.d.ts → Lexer-Cfm79Dak.d.cts} +18 -2
- package/dist/{Lexer-BJdhlnej.d.cts → Lexer-W9MBOP0V.d.ts} +18 -2
- package/dist/{PackageRegistry-DaH4aIKP.d.ts → PackageRegistry-CjDt-Jy_.d.ts} +60 -4
- package/dist/{PackageRegistry-D-Tv_7ca.d.cts → PackageRegistry-pHtKythi.d.cts} +60 -4
- package/dist/{Parselet-CK8cQu2a.d.cts → Parselet-Cu0bLSis.d.cts} +1 -1
- package/dist/{Parselet-ConOIdRO.d.ts → Parselet-DEdF9I7n.d.ts} +1 -1
- package/dist/{Token-0jpvUdPY.d.cts → Token-BzG5G4ja.d.cts} +44 -0
- package/dist/{Token-0jpvUdPY.d.ts → Token-BzG5G4ja.d.ts} +44 -0
- package/dist/TokenNormalizer-DGVa24Q-.d.cts +377 -0
- package/dist/TokenNormalizer-t_GotBxr.d.ts +377 -0
- package/dist/{chunk-HWSZJQCI.js → chunk-2CS6OMZK.js} +37 -15
- package/dist/chunk-2CS6OMZK.js.map +1 -0
- package/dist/{chunk-XJCMXB2E.cjs → chunk-2MV4HBKC.cjs} +187 -61
- package/dist/chunk-2MV4HBKC.cjs.map +1 -0
- package/dist/{chunk-J73SJHR3.cjs → chunk-2NPS5DQ3.cjs} +558 -341
- package/dist/chunk-2NPS5DQ3.cjs.map +1 -0
- package/dist/{chunk-QWY3VEZN.js → chunk-3MNKQZ77.js} +65 -12
- package/dist/chunk-3MNKQZ77.js.map +1 -0
- package/dist/{chunk-RZCWSXTA.cjs → chunk-43G3JT2E.cjs} +1491 -218
- package/dist/chunk-43G3JT2E.cjs.map +1 -0
- package/dist/{chunk-WQTTOGXC.cjs → chunk-4AVD7NZW.cjs} +4 -4
- package/dist/{chunk-WQTTOGXC.cjs.map → chunk-4AVD7NZW.cjs.map} +1 -1
- package/dist/{chunk-HTXVVJRA.cjs → chunk-4CVLFLOB.cjs} +112 -2
- package/dist/chunk-4CVLFLOB.cjs.map +1 -0
- package/dist/{chunk-5YEMOYSE.js → chunk-6GCKCWLB.js} +9 -3
- package/dist/chunk-6GCKCWLB.js.map +1 -0
- package/dist/{chunk-EBSPLUW4.cjs → chunk-AHCLWAM5.cjs} +28 -10
- package/dist/chunk-AHCLWAM5.cjs.map +1 -0
- package/dist/{chunk-KVILKGMS.js → chunk-AJA6LUI7.js} +36 -2
- package/dist/chunk-AJA6LUI7.js.map +1 -0
- package/dist/{chunk-EHAHVROS.cjs → chunk-CLVQBF5C.cjs} +5 -5
- package/dist/{chunk-EHAHVROS.cjs.map → chunk-CLVQBF5C.cjs.map} +1 -1
- package/dist/{chunk-34RRD7PC.js → chunk-CYFK5SY2.js} +111 -3
- package/dist/chunk-CYFK5SY2.js.map +1 -0
- package/dist/{chunk-M5LX5AOO.js → chunk-DDQVZGLO.js} +25 -12
- package/dist/chunk-DDQVZGLO.js.map +1 -0
- package/dist/{chunk-LR7YASZF.cjs → chunk-EAAHVJ4P.cjs} +3 -3
- package/dist/chunk-EAAHVJ4P.cjs.map +1 -0
- package/dist/{chunk-3PPFLFH4.js → chunk-FIFQPKBA.js} +1417 -144
- package/dist/chunk-FIFQPKBA.js.map +1 -0
- package/dist/{chunk-RIN643A3.js → chunk-GPPLSM2Z.js} +61 -2
- package/dist/chunk-GPPLSM2Z.js.map +1 -0
- package/dist/{chunk-4QADQTWS.js → chunk-KHJUSHFU.js} +231 -14
- package/dist/chunk-KHJUSHFU.js.map +1 -0
- package/dist/{chunk-NMD5VRN4.cjs → chunk-M4F66R4O.cjs} +74 -73
- package/dist/chunk-M4F66R4O.cjs.map +1 -0
- package/dist/{chunk-6NTVRDQV.cjs → chunk-M4Q47KHF.cjs} +126 -73
- package/dist/chunk-M4Q47KHF.cjs.map +1 -0
- package/dist/{chunk-LIPPNDBE.js → chunk-M5E34VG5.js} +3 -3
- package/dist/{chunk-LIPPNDBE.js.map → chunk-M5E34VG5.js.map} +1 -1
- package/dist/{chunk-53B6KDDJ.cjs → chunk-MBNQVDVC.cjs} +38 -3
- package/dist/{chunk-53B6KDDJ.cjs.map → chunk-MBNQVDVC.cjs.map} +1 -1
- package/dist/{chunk-SDGRK7EP.js → chunk-MEOHSQEH.js} +6 -5
- package/dist/chunk-MEOHSQEH.js.map +1 -0
- package/dist/{chunk-NMCRQP3Z.cjs → chunk-MTX2KVU7.cjs} +71 -70
- package/dist/chunk-MTX2KVU7.cjs.map +1 -0
- package/dist/{chunk-QNJ4ACRT.cjs → chunk-NJTXJ5AG.cjs} +37 -15
- package/dist/chunk-NJTXJ5AG.cjs.map +1 -0
- package/dist/{chunk-C4XZV6E7.cjs → chunk-NZFKROS7.cjs} +26 -20
- package/dist/chunk-NZFKROS7.cjs.map +1 -0
- package/dist/{chunk-64W6GLLZ.js → chunk-OFXOTECC.js} +24 -6
- package/dist/chunk-OFXOTECC.js.map +1 -0
- package/dist/{chunk-3YNVWKR2.cjs → chunk-OUHT5Z36.cjs} +28 -5
- package/dist/chunk-OUHT5Z36.cjs.map +1 -0
- package/dist/{chunk-EIGTWK5N.js → chunk-OWRHDUJD.js} +3 -3
- package/dist/chunk-OWRHDUJD.js.map +1 -0
- package/dist/{chunk-4MG4XKO2.js → chunk-PCPX42KL.js} +38 -3
- package/dist/{chunk-4MG4XKO2.js.map → chunk-PCPX42KL.js.map} +1 -1
- package/dist/{chunk-GW32KPCU.cjs → chunk-R24DI24X.cjs} +61 -2
- package/dist/chunk-R24DI24X.cjs.map +1 -0
- package/dist/{chunk-XVWCOTR6.js → chunk-SFQWJMKT.js} +7 -6
- package/dist/chunk-SFQWJMKT.js.map +1 -0
- package/dist/{chunk-6BKTCEUP.cjs → chunk-TY3TLZAW.cjs} +36 -2
- package/dist/chunk-TY3TLZAW.cjs.map +1 -0
- package/dist/{chunk-DM3LMRBC.js → chunk-UKPGSAZW.js} +187 -61
- package/dist/chunk-UKPGSAZW.js.map +1 -0
- package/dist/{chunk-NH2O2AUR.js → chunk-WC5FFSHB.js} +26 -4
- package/dist/chunk-WC5FFSHB.js.map +1 -0
- package/dist/{chunk-CLL7RUQV.cjs → chunk-WWOLFXTX.cjs} +40 -18
- package/dist/chunk-WWOLFXTX.cjs.map +1 -0
- package/dist/{chunk-JBSYC7BB.cjs → chunk-X2BWAZAU.cjs} +66 -53
- package/dist/chunk-X2BWAZAU.cjs.map +1 -0
- package/dist/{chunk-GOLDJNMZ.js → chunk-XBTEO4OB.js} +28 -5
- package/dist/chunk-XBTEO4OB.js.map +1 -0
- package/dist/{chunk-EPOXXJBK.js → chunk-YU2CUNFO.js} +3 -3
- package/dist/{chunk-EPOXXJBK.js.map → chunk-YU2CUNFO.js.map} +1 -1
- package/dist/constants.cjs +4 -4
- package/dist/constants.js +1 -1
- package/dist/engine.cjs +29 -30
- package/dist/engine.d.cts +6 -6
- package/dist/engine.d.ts +6 -6
- package/dist/engine.js +19 -20
- package/dist/format.cjs +7 -8
- package/dist/format.cjs.map +1 -1
- package/dist/format.js +2 -3
- package/dist/format.js.map +1 -1
- package/dist/index.cjs +28 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +20 -21
- package/dist/index.js.map +1 -1
- package/dist/language.cjs +74 -12
- package/dist/language.cjs.map +1 -1
- package/dist/language.d.cts +6 -6
- package/dist/language.d.ts +6 -6
- package/dist/language.js +68 -6
- package/dist/language.js.map +1 -1
- package/dist/lexer.cjs +19 -19
- package/dist/lexer.d.cts +3 -3
- package/dist/lexer.d.ts +3 -3
- package/dist/lexer.js +7 -7
- package/dist/normalizer.cjs +12 -12
- package/dist/normalizer.d.cts +4 -210
- package/dist/normalizer.d.ts +4 -210
- package/dist/normalizer.js +6 -6
- package/dist/packages.cjs +36 -37
- package/dist/packages.d.cts +5 -47
- package/dist/packages.d.ts +5 -47
- package/dist/packages.js +13 -14
- package/dist/parser.cjs +12 -12
- package/dist/parser.d.cts +3 -2
- package/dist/parser.d.ts +3 -2
- package/dist/parser.js +4 -4
- package/dist/resolvers.d.cts +1 -1
- package/dist/resolvers.d.ts +1 -1
- package/dist/uom.cjs +14 -14
- package/dist/uom.d.cts +12 -4
- package/dist/uom.d.ts +12 -4
- package/dist/uom.js +4 -4
- package/dist/vm.cjs +17 -17
- package/dist/vm.js +6 -6
- package/package.json +2 -1
- package/dist/NormalizerRule-BrVoVjmP.d.cts +0 -163
- package/dist/NormalizerRule-CEjf1FyD.d.ts +0 -163
- package/dist/chunk-34RRD7PC.js.map +0 -1
- package/dist/chunk-3PPFLFH4.js.map +0 -1
- package/dist/chunk-3YNVWKR2.cjs.map +0 -1
- package/dist/chunk-4QADQTWS.js.map +0 -1
- package/dist/chunk-5YEMOYSE.js.map +0 -1
- package/dist/chunk-64W6GLLZ.js.map +0 -1
- package/dist/chunk-6BKTCEUP.cjs.map +0 -1
- package/dist/chunk-6NTVRDQV.cjs.map +0 -1
- package/dist/chunk-C4XZV6E7.cjs.map +0 -1
- package/dist/chunk-CLL7RUQV.cjs.map +0 -1
- package/dist/chunk-DM3LMRBC.js.map +0 -1
- package/dist/chunk-EBSPLUW4.cjs.map +0 -1
- package/dist/chunk-EIGTWK5N.js.map +0 -1
- package/dist/chunk-GOLDJNMZ.js.map +0 -1
- package/dist/chunk-GW32KPCU.cjs.map +0 -1
- package/dist/chunk-HTXVVJRA.cjs.map +0 -1
- package/dist/chunk-HWSZJQCI.js.map +0 -1
- package/dist/chunk-J73SJHR3.cjs.map +0 -1
- package/dist/chunk-JBSYC7BB.cjs.map +0 -1
- package/dist/chunk-KVILKGMS.js.map +0 -1
- package/dist/chunk-LR7YASZF.cjs.map +0 -1
- package/dist/chunk-M5LX5AOO.js.map +0 -1
- package/dist/chunk-NH2O2AUR.js.map +0 -1
- package/dist/chunk-NMCRQP3Z.cjs.map +0 -1
- package/dist/chunk-NMD5VRN4.cjs.map +0 -1
- package/dist/chunk-OT6OJY7C.cjs +0 -114
- package/dist/chunk-OT6OJY7C.cjs.map +0 -1
- package/dist/chunk-QNJ4ACRT.cjs.map +0 -1
- package/dist/chunk-QWY3VEZN.js.map +0 -1
- package/dist/chunk-RFYD5TJE.js +0 -111
- package/dist/chunk-RFYD5TJE.js.map +0 -1
- package/dist/chunk-RIN643A3.js.map +0 -1
- package/dist/chunk-RZCWSXTA.cjs.map +0 -1
- package/dist/chunk-SDGRK7EP.js.map +0 -1
- package/dist/chunk-XJCMXB2E.cjs.map +0 -1
- package/dist/chunk-XVWCOTR6.js.map +0 -1
|
@@ -1,62 +1,63 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkFEAIOR7N_cjs = require('./chunk-FEAIOR7N.cjs');
|
|
4
|
-
var
|
|
5
|
-
var
|
|
4
|
+
var chunk2MV4HBKC_cjs = require('./chunk-2MV4HBKC.cjs');
|
|
5
|
+
var chunk4CVLFLOB_cjs = require('./chunk-4CVLFLOB.cjs');
|
|
6
6
|
var chunkOC6LTXYS_cjs = require('./chunk-OC6LTXYS.cjs');
|
|
7
|
-
var
|
|
7
|
+
var chunkNJTXJ5AG_cjs = require('./chunk-NJTXJ5AG.cjs');
|
|
8
|
+
var chunkMBNQVDVC_cjs = require('./chunk-MBNQVDVC.cjs');
|
|
8
9
|
var chunkM4N5GA5Z_cjs = require('./chunk-M4N5GA5Z.cjs');
|
|
9
10
|
|
|
10
11
|
// src/symbolic/MultivariateFactor.ts
|
|
11
12
|
function exactRoot(value, degree) {
|
|
12
|
-
const rootOf = degree === 2 ?
|
|
13
|
+
const rootOf = degree === 2 ? chunk4CVLFLOB_cjs.exactIntegerSqrt : chunk4CVLFLOB_cjs.exactIntegerCbrt;
|
|
13
14
|
const numerator = rootOf(value.n);
|
|
14
15
|
const denominator = rootOf(value.d);
|
|
15
16
|
return numerator === null || denominator === null ? null : { n: numerator, d: denominator };
|
|
16
17
|
}
|
|
17
18
|
function monomialRoot(key, degree) {
|
|
18
|
-
const monomial =
|
|
19
|
+
const monomial = chunk4CVLFLOB_cjs.monomialFromKey(key);
|
|
19
20
|
const root = /* @__PURE__ */ new Map();
|
|
20
21
|
for (const [name, exponent] of monomial) {
|
|
21
22
|
if (exponent % degree !== 0) return null;
|
|
22
23
|
root.set(name, exponent / degree);
|
|
23
24
|
}
|
|
24
|
-
return
|
|
25
|
+
return chunk4CVLFLOB_cjs.monomialToKey(root);
|
|
25
26
|
}
|
|
26
27
|
function monomialMul(a, b) {
|
|
27
|
-
const product2 =
|
|
28
|
-
for (const [name, exponent] of
|
|
28
|
+
const product2 = chunk4CVLFLOB_cjs.monomialFromKey(a);
|
|
29
|
+
for (const [name, exponent] of chunk4CVLFLOB_cjs.monomialFromKey(b)) {
|
|
29
30
|
product2.set(name, (product2.get(name) ?? 0) + exponent);
|
|
30
31
|
}
|
|
31
|
-
return
|
|
32
|
+
return chunk4CVLFLOB_cjs.monomialToKey(product2);
|
|
32
33
|
}
|
|
33
34
|
function monomialDiv(a, b) {
|
|
34
|
-
const quotient =
|
|
35
|
-
for (const [name, exponent] of
|
|
35
|
+
const quotient = chunk4CVLFLOB_cjs.monomialFromKey(a);
|
|
36
|
+
for (const [name, exponent] of chunk4CVLFLOB_cjs.monomialFromKey(b)) {
|
|
36
37
|
const remaining = (quotient.get(name) ?? 0) - exponent;
|
|
37
38
|
if (remaining <= 0) quotient.delete(name);
|
|
38
39
|
else quotient.set(name, remaining);
|
|
39
40
|
}
|
|
40
|
-
return
|
|
41
|
+
return chunk4CVLFLOB_cjs.monomialToKey(quotient);
|
|
41
42
|
}
|
|
42
43
|
function monomialGcd(a, b) {
|
|
43
|
-
const left =
|
|
44
|
+
const left = chunk4CVLFLOB_cjs.monomialFromKey(a);
|
|
44
45
|
const shared = /* @__PURE__ */ new Map();
|
|
45
|
-
for (const [name, exponent] of
|
|
46
|
+
for (const [name, exponent] of chunk4CVLFLOB_cjs.monomialFromKey(b)) {
|
|
46
47
|
const other = left.get(name);
|
|
47
48
|
if (other !== void 0) shared.set(name, Math.min(other, exponent));
|
|
48
49
|
}
|
|
49
|
-
return
|
|
50
|
+
return chunk4CVLFLOB_cjs.monomialToKey(shared);
|
|
50
51
|
}
|
|
51
52
|
function namesOf(keys) {
|
|
52
53
|
const names = /* @__PURE__ */ new Set();
|
|
53
|
-
for (const key of keys) for (const name of
|
|
54
|
+
for (const key of keys) for (const name of chunk4CVLFLOB_cjs.monomialFromKey(key).keys()) names.add(name);
|
|
54
55
|
return [...names].sort();
|
|
55
56
|
}
|
|
56
57
|
function termsToNode(terms) {
|
|
57
58
|
const map = /* @__PURE__ */ new Map();
|
|
58
59
|
for (const term of terms) map.set(term.key, term.coefficient);
|
|
59
|
-
return
|
|
60
|
+
return chunk4CVLFLOB_cjs.fromPolynomial({ terms: map, vars: namesOf(terms.map((term) => term.key)) });
|
|
60
61
|
}
|
|
61
62
|
function product(factors) {
|
|
62
63
|
let result = factors[0];
|
|
@@ -65,7 +66,7 @@ function product(factors) {
|
|
|
65
66
|
}
|
|
66
67
|
function orderedTerms(p) {
|
|
67
68
|
const terms = [...p.terms].map(([key, coefficient]) => ({ key, coefficient }));
|
|
68
|
-
return terms.sort((a, b) =>
|
|
69
|
+
return terms.sort((a, b) => chunk4CVLFLOB_cjs.compareMonomials(a.key, b.key, p.vars));
|
|
69
70
|
}
|
|
70
71
|
function factorMultivariate(p) {
|
|
71
72
|
if (p.vars.length < 2) return null;
|
|
@@ -93,7 +94,7 @@ function factorBinomial(first, second) {
|
|
|
93
94
|
return product([linear, termsToNode([squareOf(cubes.a), middle, squareOf(cubes.b)])]);
|
|
94
95
|
}
|
|
95
96
|
function asPowerPair(first, second, degree) {
|
|
96
|
-
const magnitude = second.coefficient.n < 0n ?
|
|
97
|
+
const magnitude = second.coefficient.n < 0n ? chunk4CVLFLOB_cjs.rationalNeg(second.coefficient) : second.coefficient;
|
|
97
98
|
const firstRoot = exactRoot(first.coefficient, degree);
|
|
98
99
|
const secondRoot = exactRoot(magnitude, degree);
|
|
99
100
|
if (firstRoot === null || secondRoot === null) return null;
|
|
@@ -103,10 +104,10 @@ function asPowerPair(first, second, degree) {
|
|
|
103
104
|
return { a: { key: firstKey, coefficient: firstRoot }, b: { key: secondKey, coefficient: secondRoot } };
|
|
104
105
|
}
|
|
105
106
|
function negated(term) {
|
|
106
|
-
return { key: term.key, coefficient:
|
|
107
|
+
return { key: term.key, coefficient: chunk4CVLFLOB_cjs.rationalNeg(term.coefficient) };
|
|
107
108
|
}
|
|
108
109
|
function multiplyTerms(a, b) {
|
|
109
|
-
return { key: monomialMul(a.key, b.key), coefficient:
|
|
110
|
+
return { key: monomialMul(a.key, b.key), coefficient: chunk4CVLFLOB_cjs.rationalMul(a.coefficient, b.coefficient) };
|
|
110
111
|
}
|
|
111
112
|
function squareOf(term) {
|
|
112
113
|
return multiplyTerms(term, term);
|
|
@@ -118,12 +119,12 @@ function factorPerfectSquare(terms) {
|
|
|
118
119
|
if (roots === null) return null;
|
|
119
120
|
const cross = multiplyTerms(roots.a, roots.b);
|
|
120
121
|
if (cross.key !== middle.key) return null;
|
|
121
|
-
const twice =
|
|
122
|
+
const twice = chunk4CVLFLOB_cjs.rationalMul(cross.coefficient, { n: 2n, d: 1n });
|
|
122
123
|
const negative = middle.coefficient.n < 0n;
|
|
123
|
-
const magnitude = negative ?
|
|
124
|
-
if (!
|
|
124
|
+
const magnitude = negative ? chunk4CVLFLOB_cjs.rationalNeg(middle.coefficient) : middle.coefficient;
|
|
125
|
+
if (!chunk4CVLFLOB_cjs.isRationalOne(chunk4CVLFLOB_cjs.rationalDiv(magnitude, twice))) return null;
|
|
125
126
|
const base = termsToNode([roots.a, negative ? negated(roots.b) : roots.b]);
|
|
126
|
-
return { kind: "pow", base, exponent:
|
|
127
|
+
return { kind: "pow", base, exponent: chunk4CVLFLOB_cjs.constNode(2) };
|
|
127
128
|
}
|
|
128
129
|
function factorByGrouping(terms) {
|
|
129
130
|
const pairings = [
|
|
@@ -148,7 +149,7 @@ function splitPair(first, second) {
|
|
|
148
149
|
const common = { key: shared, coefficient: first.coefficient };
|
|
149
150
|
const cofactor = [
|
|
150
151
|
{ key: monomialDiv(first.key, shared), coefficient: { n: 1n, d: 1n } },
|
|
151
|
-
{ key: monomialDiv(second.key, shared), coefficient:
|
|
152
|
+
{ key: monomialDiv(second.key, shared), coefficient: chunk4CVLFLOB_cjs.rationalDiv(second.coefficient, first.coefficient) }
|
|
152
153
|
];
|
|
153
154
|
return cofactor[0].key === cofactor[1].key ? null : { common, cofactor };
|
|
154
155
|
}
|
|
@@ -188,14 +189,14 @@ function divisors(value) {
|
|
|
188
189
|
return found;
|
|
189
190
|
}
|
|
190
191
|
function evaluateAt(descending, x) {
|
|
191
|
-
let total =
|
|
192
|
-
for (const coeff of descending) total =
|
|
192
|
+
let total = chunk4CVLFLOB_cjs.RATIONAL_ZERO;
|
|
193
|
+
for (const coeff of descending) total = chunk4CVLFLOB_cjs.rationalAdd(chunk4CVLFLOB_cjs.rationalMul(total, x), coeff);
|
|
193
194
|
return total;
|
|
194
195
|
}
|
|
195
196
|
function divideByRoot(descending, root) {
|
|
196
197
|
const quotient = [descending[0]];
|
|
197
198
|
for (let i = 1; i < descending.length - 1; i++) {
|
|
198
|
-
quotient.push(
|
|
199
|
+
quotient.push(chunk4CVLFLOB_cjs.rationalAdd(descending[i], chunk4CVLFLOB_cjs.rationalMul(quotient[i - 1], root)));
|
|
199
200
|
}
|
|
200
201
|
return quotient;
|
|
201
202
|
}
|
|
@@ -232,25 +233,25 @@ function rationalRoots(descending) {
|
|
|
232
233
|
const key = `${candidate.n}/${candidate.d}`;
|
|
233
234
|
if (seen.has(key)) continue;
|
|
234
235
|
seen.add(key);
|
|
235
|
-
if (
|
|
236
|
+
if (chunk4CVLFLOB_cjs.isRationalZero(evaluateAt(descending, candidate))) roots.push(candidate);
|
|
236
237
|
}
|
|
237
238
|
}
|
|
238
239
|
}
|
|
239
240
|
return roots;
|
|
240
241
|
}
|
|
241
242
|
function linearFactorNode(variable, root) {
|
|
242
|
-
if (
|
|
243
|
-
return root.n > 0n ? { kind: "sub", left:
|
|
243
|
+
if (chunk4CVLFLOB_cjs.isRationalZero(root)) return chunk4CVLFLOB_cjs.varNode(variable);
|
|
244
|
+
return root.n > 0n ? { kind: "sub", left: chunk4CVLFLOB_cjs.varNode(variable), right: chunk4CVLFLOB_cjs.constNode(root) } : { kind: "add", left: chunk4CVLFLOB_cjs.varNode(variable), right: chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.rationalNeg(root)) };
|
|
244
245
|
}
|
|
245
246
|
function coefficientsToNode(descending, variable) {
|
|
246
247
|
const degree = descending.length - 1;
|
|
247
248
|
const terms = /* @__PURE__ */ new Map();
|
|
248
249
|
descending.forEach((coeff, index) => {
|
|
249
|
-
if (
|
|
250
|
+
if (chunk4CVLFLOB_cjs.isRationalZero(coeff)) return;
|
|
250
251
|
const power2 = degree - index;
|
|
251
252
|
terms.set(power2 === 0 ? "" : power2 === 1 ? variable : `${variable}^${power2}`, coeff);
|
|
252
253
|
});
|
|
253
|
-
return
|
|
254
|
+
return chunk4CVLFLOB_cjs.fromPolynomial({ terms, vars: terms.size > 0 ? [variable] : [] });
|
|
254
255
|
}
|
|
255
256
|
function factorUnivariate(descending, variable) {
|
|
256
257
|
const factors = [];
|
|
@@ -259,7 +260,7 @@ function factorUnivariate(descending, variable) {
|
|
|
259
260
|
while (roots.length > 0 && remaining.length > 2) {
|
|
260
261
|
for (const root of roots) {
|
|
261
262
|
let multiplicity = 0;
|
|
262
|
-
while (remaining.length > 1 &&
|
|
263
|
+
while (remaining.length > 1 && chunk4CVLFLOB_cjs.isRationalZero(evaluateAt(remaining, root))) {
|
|
263
264
|
remaining = divideByRoot(remaining, root);
|
|
264
265
|
multiplicity++;
|
|
265
266
|
}
|
|
@@ -270,17 +271,17 @@ function factorUnivariate(descending, variable) {
|
|
|
270
271
|
const leftoverDegree = remaining.length - 1;
|
|
271
272
|
if (leftoverDegree >= 1) {
|
|
272
273
|
factors.push({ base: coefficientsToNode(remaining, variable), power: 1 });
|
|
273
|
-
return { content:
|
|
274
|
+
return { content: chunk4CVLFLOB_cjs.RATIONAL_ONE, factors };
|
|
274
275
|
}
|
|
275
|
-
return { content: remaining.length === 1 ? remaining[0] :
|
|
276
|
+
return { content: remaining.length === 1 ? remaining[0] : chunk4CVLFLOB_cjs.RATIONAL_ONE, factors };
|
|
276
277
|
}
|
|
277
278
|
function factorizationToNode(factorization) {
|
|
278
279
|
const pieces = [];
|
|
279
|
-
if (!
|
|
280
|
+
if (!chunk4CVLFLOB_cjs.isRationalOne(factorization.content)) pieces.push(chunk4CVLFLOB_cjs.constNode(factorization.content));
|
|
280
281
|
for (const factor of factorization.factors) {
|
|
281
|
-
pieces.push(factor.power === 1 ? factor.base :
|
|
282
|
+
pieces.push(factor.power === 1 ? factor.base : chunk4CVLFLOB_cjs.powNode(factor.base, chunk4CVLFLOB_cjs.constNode({ n: BigInt(factor.power), d: 1n })));
|
|
282
283
|
}
|
|
283
|
-
if (pieces.length === 0) return
|
|
284
|
+
if (pieces.length === 0) return chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.RATIONAL_ONE);
|
|
284
285
|
let result = pieces[0];
|
|
285
286
|
for (let i = 1; i < pieces.length; i++) result = { kind: "mul", left: result, right: pieces[i] };
|
|
286
287
|
return result;
|
|
@@ -292,7 +293,7 @@ function contentOf(p) {
|
|
|
292
293
|
numeratorGcd = gcd(numeratorGcd, coeff.n);
|
|
293
294
|
denominatorLcm = lcm(denominatorLcm, coeff.d);
|
|
294
295
|
}
|
|
295
|
-
if (numeratorGcd === 0n) return
|
|
296
|
+
if (numeratorGcd === 0n) return chunk4CVLFLOB_cjs.RATIONAL_ONE;
|
|
296
297
|
return { n: numeratorGcd, d: denominatorLcm };
|
|
297
298
|
}
|
|
298
299
|
function extractCommonMonomial(p) {
|
|
@@ -338,48 +339,48 @@ function monomialNode(monomial) {
|
|
|
338
339
|
let result = null;
|
|
339
340
|
for (const name of names) {
|
|
340
341
|
const exponent = monomial.get(name);
|
|
341
|
-
const factor = exponent === 1 ?
|
|
342
|
+
const factor = exponent === 1 ? chunk4CVLFLOB_cjs.varNode(name) : chunk4CVLFLOB_cjs.powNode(chunk4CVLFLOB_cjs.varNode(name), chunk4CVLFLOB_cjs.constNode({ n: BigInt(exponent), d: 1n }));
|
|
342
343
|
result = result === null ? factor : { kind: "mul", left: result, right: factor };
|
|
343
344
|
}
|
|
344
345
|
return result;
|
|
345
346
|
}
|
|
346
347
|
function factorSymbolic(node) {
|
|
347
|
-
const polynomial =
|
|
348
|
+
const polynomial = chunk4CVLFLOB_cjs.toPolynomial(node);
|
|
348
349
|
if (polynomial === null || polynomial.terms.size === 0) return node;
|
|
349
|
-
if (
|
|
350
|
+
if (chunk4CVLFLOB_cjs.polyDegree(polynomial) > FACTOR_MAX_DEGREE) return node;
|
|
350
351
|
if (polynomial.vars.length === 0) return node;
|
|
351
352
|
const content = contentOf(polynomial);
|
|
352
|
-
const primitive =
|
|
353
|
+
const primitive = chunk4CVLFLOB_cjs.isRationalOne(content) ? polynomial : scaleTerms(polynomial, chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.RATIONAL_ONE, content));
|
|
353
354
|
const { monomial, reduced } = extractCommonMonomial(primitive);
|
|
354
355
|
const monomialFactor = monomialNode(monomial);
|
|
355
|
-
const variable =
|
|
356
|
+
const variable = chunk4CVLFLOB_cjs.polyUnivariateVar(reduced);
|
|
356
357
|
if (variable === null) {
|
|
357
358
|
const patterned = factorMultivariate(reduced);
|
|
358
359
|
if (patterned !== null) return assemble(content, monomialFactor, patterned);
|
|
359
360
|
const pieces2 = buildPieces(content, monomialFactor, reduced);
|
|
360
361
|
return pieces2 ?? node;
|
|
361
362
|
}
|
|
362
|
-
const descending = [...
|
|
363
|
+
const descending = [...chunk4CVLFLOB_cjs.polyCoefficients(reduced, variable)].reverse();
|
|
363
364
|
const factorization = factorUnivariate(descending, variable);
|
|
364
|
-
const combinedContent =
|
|
365
|
-
const isUnchanged = factorization.factors.length <= 1 && (factorization.factors[0]?.power ?? 1) === 1 && monomialFactor === null &&
|
|
365
|
+
const combinedContent = chunk4CVLFLOB_cjs.rationalMul(content, factorization.content);
|
|
366
|
+
const isUnchanged = factorization.factors.length <= 1 && (factorization.factors[0]?.power ?? 1) === 1 && monomialFactor === null && chunk4CVLFLOB_cjs.isRationalOne(combinedContent);
|
|
366
367
|
if (isUnchanged) return node;
|
|
367
368
|
const pieces = [];
|
|
368
|
-
if (!
|
|
369
|
+
if (!chunk4CVLFLOB_cjs.isRationalOne(combinedContent)) pieces.push(chunk4CVLFLOB_cjs.constNode(combinedContent));
|
|
369
370
|
if (monomialFactor !== null) pieces.push(monomialFactor);
|
|
370
|
-
pieces.push(factorizationToNode({ content:
|
|
371
|
+
pieces.push(factorizationToNode({ content: chunk4CVLFLOB_cjs.RATIONAL_ONE, factors: factorization.factors }));
|
|
371
372
|
let result = pieces[0];
|
|
372
373
|
for (let i = 1; i < pieces.length; i++) result = { kind: "mul", left: result, right: pieces[i] };
|
|
373
374
|
return result;
|
|
374
375
|
}
|
|
375
376
|
function scaleTerms(p, k) {
|
|
376
377
|
const terms = /* @__PURE__ */ new Map();
|
|
377
|
-
for (const [key, coeff] of p.terms) terms.set(key,
|
|
378
|
+
for (const [key, coeff] of p.terms) terms.set(key, chunk4CVLFLOB_cjs.rationalMul(coeff, k));
|
|
378
379
|
return { terms, vars: p.vars };
|
|
379
380
|
}
|
|
380
381
|
function assemble(content, monomialFactor, factored) {
|
|
381
382
|
const pieces = [];
|
|
382
|
-
if (!
|
|
383
|
+
if (!chunk4CVLFLOB_cjs.isRationalOne(content)) pieces.push(chunk4CVLFLOB_cjs.constNode(content));
|
|
383
384
|
if (monomialFactor !== null) pieces.push(monomialFactor);
|
|
384
385
|
pieces.push(factored);
|
|
385
386
|
let result = pieces[0];
|
|
@@ -387,11 +388,11 @@ function assemble(content, monomialFactor, factored) {
|
|
|
387
388
|
return result;
|
|
388
389
|
}
|
|
389
390
|
function buildPieces(content, monomialFactor, reduced) {
|
|
390
|
-
if (monomialFactor === null &&
|
|
391
|
+
if (monomialFactor === null && chunk4CVLFLOB_cjs.isRationalOne(content)) return null;
|
|
391
392
|
const pieces = [];
|
|
392
|
-
if (!
|
|
393
|
+
if (!chunk4CVLFLOB_cjs.isRationalOne(content)) pieces.push(chunk4CVLFLOB_cjs.constNode(content));
|
|
393
394
|
if (monomialFactor !== null) pieces.push(monomialFactor);
|
|
394
|
-
pieces.push(
|
|
395
|
+
pieces.push(chunk4CVLFLOB_cjs.fromPolynomial(reduced));
|
|
395
396
|
let result = pieces[0];
|
|
396
397
|
for (let i = 1; i < pieces.length; i++) result = { kind: "mul", left: result, right: pieces[i] };
|
|
397
398
|
return result;
|
|
@@ -402,103 +403,103 @@ var TWO = { n: 2n, d: 1n };
|
|
|
402
403
|
var THREE = { n: 3n, d: 1n };
|
|
403
404
|
var FOUR = { n: 4n, d: 1n };
|
|
404
405
|
function depressCubic(a, b, c, d) {
|
|
405
|
-
const shift =
|
|
406
|
-
const p =
|
|
407
|
-
|
|
408
|
-
|
|
406
|
+
const shift = chunk4CVLFLOB_cjs.rationalNeg(chunk4CVLFLOB_cjs.rationalDiv(b, chunk4CVLFLOB_cjs.rationalMul(THREE, a)));
|
|
407
|
+
const p = chunk4CVLFLOB_cjs.rationalDiv(
|
|
408
|
+
chunk4CVLFLOB_cjs.rationalSub(chunk4CVLFLOB_cjs.rationalMul(THREE, chunk4CVLFLOB_cjs.rationalMul(a, c)), chunk4CVLFLOB_cjs.rationalMul(b, b)),
|
|
409
|
+
chunk4CVLFLOB_cjs.rationalMul(THREE, chunk4CVLFLOB_cjs.rationalMul(a, a))
|
|
409
410
|
);
|
|
410
|
-
const twoBCubed =
|
|
411
|
-
const nineABC =
|
|
412
|
-
const twentySevenAAD =
|
|
413
|
-
const q =
|
|
414
|
-
|
|
415
|
-
|
|
411
|
+
const twoBCubed = chunk4CVLFLOB_cjs.rationalMul(TWO, chunk4CVLFLOB_cjs.rationalMul(b, chunk4CVLFLOB_cjs.rationalMul(b, b)));
|
|
412
|
+
const nineABC = chunk4CVLFLOB_cjs.rationalMul({ n: 9n, d: 1n }, chunk4CVLFLOB_cjs.rationalMul(a, chunk4CVLFLOB_cjs.rationalMul(b, c)));
|
|
413
|
+
const twentySevenAAD = chunk4CVLFLOB_cjs.rationalMul({ n: 27n, d: 1n }, chunk4CVLFLOB_cjs.rationalMul(chunk4CVLFLOB_cjs.rationalMul(a, a), d));
|
|
414
|
+
const q = chunk4CVLFLOB_cjs.rationalDiv(
|
|
415
|
+
chunk4CVLFLOB_cjs.rationalAdd(chunk4CVLFLOB_cjs.rationalSub(twoBCubed, nineABC), twentySevenAAD),
|
|
416
|
+
chunk4CVLFLOB_cjs.rationalMul({ n: 27n, d: 1n }, chunk4CVLFLOB_cjs.rationalMul(a, chunk4CVLFLOB_cjs.rationalMul(a, a)))
|
|
416
417
|
);
|
|
417
418
|
return { p, q, shift };
|
|
418
419
|
}
|
|
419
420
|
function solveCubic(a, b, c, d) {
|
|
420
421
|
const { p, q, shift } = depressCubic(a, b, c, d);
|
|
421
|
-
const discriminant =
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
422
|
+
const discriminant = chunk4CVLFLOB_cjs.rationalNeg(
|
|
423
|
+
chunk4CVLFLOB_cjs.rationalAdd(
|
|
424
|
+
chunk4CVLFLOB_cjs.rationalMul(FOUR, chunk4CVLFLOB_cjs.rationalMul(p, chunk4CVLFLOB_cjs.rationalMul(p, p))),
|
|
425
|
+
chunk4CVLFLOB_cjs.rationalMul({ n: 27n, d: 1n }, chunk4CVLFLOB_cjs.rationalMul(q, q))
|
|
425
426
|
)
|
|
426
427
|
);
|
|
427
|
-
if (
|
|
428
|
+
if (chunk4CVLFLOB_cjs.rationalCompare(discriminant, chunk4CVLFLOB_cjs.RATIONAL_ZERO) > 0) {
|
|
428
429
|
return { exact: [], approximate: trigonometricRoots(p, q, shift) };
|
|
429
430
|
}
|
|
430
|
-
if (
|
|
431
|
+
if (chunk4CVLFLOB_cjs.isRationalZero(discriminant)) return { exact: repeatedCubicRoots(p, q, shift), approximate: [] };
|
|
431
432
|
return { exact: cardanoRoots(p, q, shift), approximate: [] };
|
|
432
433
|
}
|
|
433
434
|
function repeatedCubicRoots(p, q, shift) {
|
|
434
|
-
if (
|
|
435
|
-
const simple =
|
|
436
|
-
const repeated =
|
|
437
|
-
const ordered = [simple, repeated].sort(
|
|
438
|
-
return ordered.map(
|
|
435
|
+
if (chunk4CVLFLOB_cjs.isRationalZero(p)) return [chunk4CVLFLOB_cjs.constNode(shift)];
|
|
436
|
+
const simple = chunk4CVLFLOB_cjs.rationalAdd(chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalMul(THREE, q), p), shift);
|
|
437
|
+
const repeated = chunk4CVLFLOB_cjs.rationalAdd(chunk4CVLFLOB_cjs.rationalNeg(chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalMul(THREE, q), chunk4CVLFLOB_cjs.rationalMul(TWO, p))), shift);
|
|
438
|
+
const ordered = [simple, repeated].sort(chunk4CVLFLOB_cjs.rationalCompare);
|
|
439
|
+
return ordered.map(chunk4CVLFLOB_cjs.constNode);
|
|
439
440
|
}
|
|
440
441
|
function cardanoRoots(p, q, shift) {
|
|
441
|
-
const half =
|
|
442
|
-
const radicand =
|
|
443
|
-
|
|
444
|
-
|
|
442
|
+
const half = chunk4CVLFLOB_cjs.rationalNeg(chunk4CVLFLOB_cjs.rationalDiv(q, TWO));
|
|
443
|
+
const radicand = chunk4CVLFLOB_cjs.rationalAdd(
|
|
444
|
+
chunk4CVLFLOB_cjs.rationalMul(chunk4CVLFLOB_cjs.rationalDiv(q, TWO), chunk4CVLFLOB_cjs.rationalDiv(q, TWO)),
|
|
445
|
+
chunk4CVLFLOB_cjs.rationalMul(chunk4CVLFLOB_cjs.rationalDiv(p, THREE), chunk4CVLFLOB_cjs.rationalMul(chunk4CVLFLOB_cjs.rationalDiv(p, THREE), chunk4CVLFLOB_cjs.rationalDiv(p, THREE)))
|
|
445
446
|
);
|
|
446
|
-
const inner =
|
|
447
|
-
const u = { kind: "call", name: "cbrt", args: [{ kind: "add", left:
|
|
448
|
-
const v = { kind: "call", name: "cbrt", args: [{ kind: "sub", left:
|
|
447
|
+
const inner = chunk4CVLFLOB_cjs.surdNode(radicand);
|
|
448
|
+
const u = { kind: "call", name: "cbrt", args: [{ kind: "add", left: chunk4CVLFLOB_cjs.constNode(half), right: inner }] };
|
|
449
|
+
const v = { kind: "call", name: "cbrt", args: [{ kind: "sub", left: chunk4CVLFLOB_cjs.constNode(half), right: inner }] };
|
|
449
450
|
const sum = { kind: "add", left: u, right: v };
|
|
450
451
|
const difference = { kind: "sub", left: u, right: v };
|
|
451
|
-
const real = { kind: "add", left:
|
|
452
|
+
const real = { kind: "add", left: chunk4CVLFLOB_cjs.constNode(shift), right: { kind: "div", left: { kind: "neg", operand: sum }, right: chunk4CVLFLOB_cjs.constNode(TWO) } };
|
|
452
453
|
const imaginary = {
|
|
453
454
|
kind: "mul",
|
|
454
|
-
left: { kind: "div", left: { kind: "mul", left: difference, right:
|
|
455
|
-
right:
|
|
455
|
+
left: { kind: "div", left: { kind: "mul", left: difference, right: chunk4CVLFLOB_cjs.surdNode(THREE) }, right: chunk4CVLFLOB_cjs.constNode(TWO) },
|
|
456
|
+
right: chunk4CVLFLOB_cjs.complexNode(chunk4CVLFLOB_cjs.COMPLEX_I)
|
|
456
457
|
};
|
|
457
458
|
return [
|
|
458
|
-
{ kind: "add", left:
|
|
459
|
+
{ kind: "add", left: chunk4CVLFLOB_cjs.constNode(shift), right: sum },
|
|
459
460
|
{ kind: "sub", left: real, right: imaginary },
|
|
460
461
|
{ kind: "add", left: real, right: imaginary }
|
|
461
462
|
];
|
|
462
463
|
}
|
|
463
464
|
function trigonometricRoots(p, q, shift) {
|
|
464
|
-
const pNumber =
|
|
465
|
-
const qNumber =
|
|
466
|
-
const shiftNumber =
|
|
465
|
+
const pNumber = chunk4CVLFLOB_cjs.rationalToNumber(p);
|
|
466
|
+
const qNumber = chunk4CVLFLOB_cjs.rationalToNumber(q);
|
|
467
|
+
const shiftNumber = chunk4CVLFLOB_cjs.rationalToNumber(shift);
|
|
467
468
|
const magnitude = 2 * Math.sqrt(-pNumber / 3);
|
|
468
469
|
const ratio = 3 * qNumber / (2 * pNumber) * Math.sqrt(-3 / pNumber);
|
|
469
470
|
const angle = Math.acos(Math.min(1, Math.max(-1, ratio))) / 3;
|
|
470
471
|
return [0, 1, 2].map((k) => magnitude * Math.cos(angle - 2 * Math.PI * k / 3) + shiftNumber).sort((left, right) => left - right);
|
|
471
472
|
}
|
|
472
473
|
function depressQuartic(b, c, d, e) {
|
|
473
|
-
const shift =
|
|
474
|
-
const bb =
|
|
475
|
-
const p =
|
|
476
|
-
const q =
|
|
477
|
-
|
|
478
|
-
|
|
474
|
+
const shift = chunk4CVLFLOB_cjs.rationalNeg(chunk4CVLFLOB_cjs.rationalDiv(b, FOUR));
|
|
475
|
+
const bb = chunk4CVLFLOB_cjs.rationalMul(b, b);
|
|
476
|
+
const p = chunk4CVLFLOB_cjs.rationalSub(c, chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalMul(THREE, bb), { n: 8n, d: 1n }));
|
|
477
|
+
const q = chunk4CVLFLOB_cjs.rationalAdd(
|
|
478
|
+
chunk4CVLFLOB_cjs.rationalSub(d, chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalMul(b, c), TWO)),
|
|
479
|
+
chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalMul(bb, b), { n: 8n, d: 1n })
|
|
479
480
|
);
|
|
480
|
-
const r =
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
481
|
+
const r = chunk4CVLFLOB_cjs.rationalSub(
|
|
482
|
+
chunk4CVLFLOB_cjs.rationalAdd(
|
|
483
|
+
chunk4CVLFLOB_cjs.rationalSub(e, chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalMul(b, d), FOUR)),
|
|
484
|
+
chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalMul(bb, c), { n: 16n, d: 1n })
|
|
484
485
|
),
|
|
485
|
-
|
|
486
|
+
chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalMul(THREE, chunk4CVLFLOB_cjs.rationalMul(bb, bb)), { n: 256n, d: 1n })
|
|
486
487
|
);
|
|
487
488
|
return { p, q, r, shift };
|
|
488
489
|
}
|
|
489
490
|
function solveQuartic(a, b, c, d, e, solveQuadratic2) {
|
|
490
|
-
const monic = (value) =>
|
|
491
|
+
const monic = (value) => chunk4CVLFLOB_cjs.rationalDiv(value, a);
|
|
491
492
|
const { p, q, r, shift } = depressQuartic(monic(b), monic(c), monic(d), monic(e));
|
|
492
|
-
const roots =
|
|
493
|
+
const roots = chunk4CVLFLOB_cjs.isRationalZero(q) ? biquadraticRoots(p, r) : splitQuarticRoots(p, q, r, solveQuadratic2);
|
|
493
494
|
if (roots === null) return null;
|
|
494
|
-
const shifted =
|
|
495
|
+
const shifted = chunk4CVLFLOB_cjs.isRationalZero(shift) ? roots : roots.map((root) => ({ kind: "add", left: chunk4CVLFLOB_cjs.constNode(shift), right: root }));
|
|
495
496
|
return { exact: distinct(shifted), approximate: [] };
|
|
496
497
|
}
|
|
497
498
|
function distinct(roots) {
|
|
498
499
|
const seen = /* @__PURE__ */ new Set();
|
|
499
500
|
const unique = [];
|
|
500
501
|
for (const root of roots) {
|
|
501
|
-
const key =
|
|
502
|
+
const key = chunk4CVLFLOB_cjs.symbolicKey(chunk4CVLFLOB_cjs.simplifySymbolic(root));
|
|
502
503
|
if (seen.has(key)) continue;
|
|
503
504
|
seen.add(key);
|
|
504
505
|
unique.push(root);
|
|
@@ -506,53 +507,53 @@ function distinct(roots) {
|
|
|
506
507
|
return unique;
|
|
507
508
|
}
|
|
508
509
|
function biquadraticRoots(p, r) {
|
|
509
|
-
const discriminant =
|
|
510
|
-
if (
|
|
511
|
-
const root =
|
|
512
|
-
if (root !== null) return rationalSquareRoots(
|
|
510
|
+
const discriminant = chunk4CVLFLOB_cjs.rationalSub(chunk4CVLFLOB_cjs.rationalMul(p, p), chunk4CVLFLOB_cjs.rationalMul(FOUR, r));
|
|
511
|
+
if (chunk4CVLFLOB_cjs.rationalCompare(discriminant, chunk4CVLFLOB_cjs.RATIONAL_ZERO) < 0) return complexBiquadraticRoots(p, r);
|
|
512
|
+
const root = chunk4CVLFLOB_cjs.exactRationalSqrt(discriminant);
|
|
513
|
+
if (root !== null) return rationalSquareRoots(chunk4CVLFLOB_cjs.rationalNeg(p), root, chunk4CVLFLOB_cjs.isRationalZero(discriminant));
|
|
513
514
|
return nestedSquareRoots(p, r, discriminant);
|
|
514
515
|
}
|
|
515
516
|
function rationalSquareRoots(negatedP, root, repeated) {
|
|
516
|
-
const values = repeated ? [
|
|
517
|
+
const values = repeated ? [chunk4CVLFLOB_cjs.rationalDiv(negatedP, TWO)] : [chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalAdd(negatedP, root), TWO), chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalSub(negatedP, root), TWO)];
|
|
517
518
|
const roots = [];
|
|
518
519
|
for (const value of values) {
|
|
519
|
-
if (
|
|
520
|
-
roots.push(
|
|
520
|
+
if (chunk4CVLFLOB_cjs.isRationalZero(value)) {
|
|
521
|
+
roots.push(chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.RATIONAL_ZERO));
|
|
521
522
|
continue;
|
|
522
523
|
}
|
|
523
|
-
const square =
|
|
524
|
+
const square = chunk4CVLFLOB_cjs.signedSurdNode(value);
|
|
524
525
|
roots.push({ kind: "neg", operand: square }, square);
|
|
525
526
|
}
|
|
526
527
|
return roots;
|
|
527
528
|
}
|
|
528
529
|
function nestedSquareRoots(p, r, discriminant) {
|
|
529
|
-
const negatedP =
|
|
530
|
-
const surd =
|
|
531
|
-
const negativeP =
|
|
530
|
+
const negatedP = chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.rationalNeg(p));
|
|
531
|
+
const surd = chunk4CVLFLOB_cjs.surdNode(discriminant);
|
|
532
|
+
const negativeP = chunk4CVLFLOB_cjs.rationalCompare(p, chunk4CVLFLOB_cjs.RATIONAL_ZERO) <= 0;
|
|
532
533
|
const solutions = [
|
|
533
|
-
{ node: halved({ kind: "add", left: negatedP, right: surd }), positive: negativeP ||
|
|
534
|
-
{ node: halved({ kind: "sub", left: negatedP, right: surd }), positive: negativeP &&
|
|
534
|
+
{ node: halved({ kind: "add", left: negatedP, right: surd }), positive: negativeP || chunk4CVLFLOB_cjs.rationalCompare(r, chunk4CVLFLOB_cjs.RATIONAL_ZERO) <= 0 },
|
|
535
|
+
{ node: halved({ kind: "sub", left: negatedP, right: surd }), positive: negativeP && chunk4CVLFLOB_cjs.rationalCompare(r, chunk4CVLFLOB_cjs.RATIONAL_ZERO) >= 0 }
|
|
535
536
|
];
|
|
536
537
|
const roots = [];
|
|
537
538
|
for (const { node, positive } of solutions) {
|
|
538
539
|
const radicand = positive ? node : { kind: "neg", operand: node };
|
|
539
540
|
const magnitude = { kind: "call", name: "sqrt", args: [radicand] };
|
|
540
|
-
const square = positive ? magnitude : { kind: "mul", left: magnitude, right:
|
|
541
|
+
const square = positive ? magnitude : { kind: "mul", left: magnitude, right: chunk4CVLFLOB_cjs.complexNode(chunk4CVLFLOB_cjs.COMPLEX_I) };
|
|
541
542
|
roots.push({ kind: "neg", operand: square }, square);
|
|
542
543
|
}
|
|
543
544
|
return roots;
|
|
544
545
|
}
|
|
545
546
|
function halved(node) {
|
|
546
|
-
return { kind: "div", left: node, right:
|
|
547
|
+
return { kind: "div", left: node, right: chunk4CVLFLOB_cjs.constNode(TWO) };
|
|
547
548
|
}
|
|
548
549
|
function complexBiquadraticRoots(p, r) {
|
|
549
|
-
const modulus =
|
|
550
|
+
const modulus = chunk4CVLFLOB_cjs.exactRationalSqrt(r);
|
|
550
551
|
if (modulus === null) return null;
|
|
551
|
-
const realPart =
|
|
552
|
-
const imaginaryPart =
|
|
553
|
-
if (
|
|
554
|
-
const re =
|
|
555
|
-
const im = { kind: "mul", left:
|
|
552
|
+
const realPart = chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalAdd(modulus, chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalNeg(p), TWO)), TWO);
|
|
553
|
+
const imaginaryPart = chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalSub(modulus, chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalNeg(p), TWO)), TWO);
|
|
554
|
+
if (chunk4CVLFLOB_cjs.rationalCompare(realPart, chunk4CVLFLOB_cjs.RATIONAL_ZERO) < 0 || chunk4CVLFLOB_cjs.rationalCompare(imaginaryPart, chunk4CVLFLOB_cjs.RATIONAL_ZERO) < 0) return null;
|
|
555
|
+
const re = chunk4CVLFLOB_cjs.surdNode(realPart);
|
|
556
|
+
const im = { kind: "mul", left: chunk4CVLFLOB_cjs.surdNode(imaginaryPart), right: chunk4CVLFLOB_cjs.complexNode(chunk4CVLFLOB_cjs.COMPLEX_I) };
|
|
556
557
|
const first = { kind: "add", left: re, right: im };
|
|
557
558
|
const second = { kind: "sub", left: re, right: im };
|
|
558
559
|
return [
|
|
@@ -565,22 +566,22 @@ function complexBiquadraticRoots(p, r) {
|
|
|
565
566
|
function splitQuarticRoots(p, q, r, solveQuadratic2) {
|
|
566
567
|
const resolvent = [
|
|
567
568
|
{ n: 1n, d: 1n },
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
569
|
+
chunk4CVLFLOB_cjs.rationalMul(TWO, p),
|
|
570
|
+
chunk4CVLFLOB_cjs.rationalSub(chunk4CVLFLOB_cjs.rationalMul(p, p), chunk4CVLFLOB_cjs.rationalMul(FOUR, r)),
|
|
571
|
+
chunk4CVLFLOB_cjs.rationalNeg(chunk4CVLFLOB_cjs.rationalMul(q, q))
|
|
571
572
|
];
|
|
572
573
|
for (const z of rationalRoots(resolvent)) {
|
|
573
|
-
if (
|
|
574
|
-
const alpha =
|
|
574
|
+
if (chunk4CVLFLOB_cjs.rationalCompare(z, chunk4CVLFLOB_cjs.RATIONAL_ZERO) <= 0) continue;
|
|
575
|
+
const alpha = chunk4CVLFLOB_cjs.exactRationalSqrt(z);
|
|
575
576
|
if (alpha === null) continue;
|
|
576
|
-
const sum =
|
|
577
|
-
const difference =
|
|
578
|
-
const beta =
|
|
579
|
-
const gamma =
|
|
577
|
+
const sum = chunk4CVLFLOB_cjs.rationalAdd(p, z);
|
|
578
|
+
const difference = chunk4CVLFLOB_cjs.rationalDiv(q, alpha);
|
|
579
|
+
const beta = chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalSub(sum, difference), TWO);
|
|
580
|
+
const gamma = chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalAdd(sum, difference), TWO);
|
|
580
581
|
const one2 = { n: 1n, d: 1n };
|
|
581
582
|
return [
|
|
582
583
|
...solveQuadratic2(one2, alpha, beta),
|
|
583
|
-
...solveQuadratic2(one2,
|
|
584
|
+
...solveQuadratic2(one2, chunk4CVLFLOB_cjs.rationalNeg(alpha), gamma)
|
|
584
585
|
];
|
|
585
586
|
}
|
|
586
587
|
return null;
|
|
@@ -592,64 +593,64 @@ var NEWTON_MAX_ITERATIONS = 100;
|
|
|
592
593
|
var NEWTON_TOLERANCE = 1e-12;
|
|
593
594
|
var NUMERIC_SCAN_STEPS = 2e3;
|
|
594
595
|
function evaluateRational(descending, x) {
|
|
595
|
-
let total =
|
|
596
|
-
for (const coeff of descending) total =
|
|
596
|
+
let total = chunk4CVLFLOB_cjs.RATIONAL_ZERO;
|
|
597
|
+
for (const coeff of descending) total = chunk4CVLFLOB_cjs.rationalAdd(chunk4CVLFLOB_cjs.rationalMul(total, x), coeff);
|
|
597
598
|
return total;
|
|
598
599
|
}
|
|
599
600
|
function evaluateNumeric(descending, x) {
|
|
600
601
|
let total = 0;
|
|
601
|
-
for (const coeff of descending) total = total * x +
|
|
602
|
+
for (const coeff of descending) total = total * x + chunk4CVLFLOB_cjs.rationalToNumber(coeff);
|
|
602
603
|
return total;
|
|
603
604
|
}
|
|
604
605
|
function divideByRoot2(descending, root) {
|
|
605
606
|
const quotient = [descending[0]];
|
|
606
607
|
for (let i = 1; i < descending.length - 1; i++) {
|
|
607
|
-
quotient.push(
|
|
608
|
+
quotient.push(chunk4CVLFLOB_cjs.rationalAdd(descending[i], chunk4CVLFLOB_cjs.rationalMul(quotient[i - 1], root)));
|
|
608
609
|
}
|
|
609
610
|
return quotient;
|
|
610
611
|
}
|
|
611
612
|
function solveQuadratic(a, b, c) {
|
|
612
|
-
const discriminant =
|
|
613
|
-
const twoA =
|
|
614
|
-
if (
|
|
615
|
-
return complexQuadraticRoots(
|
|
616
|
-
}
|
|
617
|
-
if (
|
|
618
|
-
const rootN =
|
|
619
|
-
const rootD =
|
|
613
|
+
const discriminant = chunk4CVLFLOB_cjs.rationalSub(chunk4CVLFLOB_cjs.rationalMul(b, b), chunk4CVLFLOB_cjs.rationalMul(rational4(), chunk4CVLFLOB_cjs.rationalMul(a, c)));
|
|
614
|
+
const twoA = chunk4CVLFLOB_cjs.rationalMul(rational2(), a);
|
|
615
|
+
if (chunk4CVLFLOB_cjs.rationalCompare(discriminant, chunk4CVLFLOB_cjs.RATIONAL_ZERO) < 0) {
|
|
616
|
+
return complexQuadraticRoots(chunk4CVLFLOB_cjs.rationalNeg(b), discriminant, twoA);
|
|
617
|
+
}
|
|
618
|
+
if (chunk4CVLFLOB_cjs.isRationalZero(discriminant)) return [chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalNeg(b), twoA))];
|
|
619
|
+
const rootN = chunk4CVLFLOB_cjs.exactIntegerSqrt(discriminant.n);
|
|
620
|
+
const rootD = chunk4CVLFLOB_cjs.exactIntegerSqrt(discriminant.d);
|
|
620
621
|
if (rootN !== null && rootD !== null) {
|
|
621
622
|
const root = { n: rootN, d: rootD };
|
|
622
|
-
const plus =
|
|
623
|
-
const minus =
|
|
624
|
-
return
|
|
625
|
-
}
|
|
626
|
-
const surd =
|
|
627
|
-
const ascending =
|
|
628
|
-
const lower = { kind: "div", left: { kind: "sub", left:
|
|
629
|
-
const upper = { kind: "div", left: { kind: "add", left:
|
|
623
|
+
const plus = chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalAdd(chunk4CVLFLOB_cjs.rationalNeg(b), root), twoA);
|
|
624
|
+
const minus = chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalSub(chunk4CVLFLOB_cjs.rationalNeg(b), root), twoA);
|
|
625
|
+
return chunk4CVLFLOB_cjs.rationalCompare(minus, plus) <= 0 ? [chunk4CVLFLOB_cjs.constNode(minus), chunk4CVLFLOB_cjs.constNode(plus)] : [chunk4CVLFLOB_cjs.constNode(plus), chunk4CVLFLOB_cjs.constNode(minus)];
|
|
626
|
+
}
|
|
627
|
+
const surd = chunk4CVLFLOB_cjs.surdNode(discriminant);
|
|
628
|
+
const ascending = chunk4CVLFLOB_cjs.rationalCompare(twoA, chunk4CVLFLOB_cjs.RATIONAL_ZERO) > 0;
|
|
629
|
+
const lower = { kind: "div", left: { kind: "sub", left: chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.rationalNeg(b)), right: surd }, right: chunk4CVLFLOB_cjs.constNode(twoA) };
|
|
630
|
+
const upper = { kind: "div", left: { kind: "add", left: chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.rationalNeg(b)), right: surd }, right: chunk4CVLFLOB_cjs.constNode(twoA) };
|
|
630
631
|
return ascending ? [lower, upper] : [upper, lower];
|
|
631
632
|
}
|
|
632
633
|
function complexQuadraticRoots(negatedB, discriminant, twoA) {
|
|
633
|
-
const magnitude =
|
|
634
|
-
const rootN =
|
|
635
|
-
const rootD =
|
|
634
|
+
const magnitude = chunk4CVLFLOB_cjs.rationalNeg(discriminant);
|
|
635
|
+
const rootN = chunk4CVLFLOB_cjs.exactIntegerSqrt(magnitude.n);
|
|
636
|
+
const rootD = chunk4CVLFLOB_cjs.exactIntegerSqrt(magnitude.d);
|
|
636
637
|
if (rootN !== null && rootD !== null) {
|
|
637
|
-
const imaginary2 =
|
|
638
|
-
const real2 =
|
|
638
|
+
const imaginary2 = chunk4CVLFLOB_cjs.rationalDiv({ n: rootN, d: rootD }, twoA);
|
|
639
|
+
const real2 = chunk4CVLFLOB_cjs.rationalDiv(negatedB, twoA);
|
|
639
640
|
return [
|
|
640
|
-
|
|
641
|
-
|
|
641
|
+
chunk4CVLFLOB_cjs.complexNode(chunk4CVLFLOB_cjs.complex(real2, chunk4CVLFLOB_cjs.rationalNeg(imaginary2))),
|
|
642
|
+
chunk4CVLFLOB_cjs.complexNode(chunk4CVLFLOB_cjs.complex(real2, imaginary2))
|
|
642
643
|
];
|
|
643
644
|
}
|
|
644
|
-
const real =
|
|
645
|
-
const scaledRadicand =
|
|
646
|
-
const imaginary = { kind: "mul", left:
|
|
647
|
-
if (
|
|
645
|
+
const real = chunk4CVLFLOB_cjs.rationalDiv(negatedB, twoA);
|
|
646
|
+
const scaledRadicand = chunk4CVLFLOB_cjs.rationalDiv(magnitude, chunk4CVLFLOB_cjs.rationalMul(twoA, twoA));
|
|
647
|
+
const imaginary = { kind: "mul", left: chunk4CVLFLOB_cjs.surdNode(scaledRadicand), right: chunk4CVLFLOB_cjs.complexNode(chunk4CVLFLOB_cjs.COMPLEX_I) };
|
|
648
|
+
if (chunk4CVLFLOB_cjs.isRationalZero(real)) {
|
|
648
649
|
return [{ kind: "neg", operand: imaginary }, imaginary];
|
|
649
650
|
}
|
|
650
651
|
return [
|
|
651
|
-
{ kind: "sub", left:
|
|
652
|
-
{ kind: "add", left:
|
|
652
|
+
{ kind: "sub", left: chunk4CVLFLOB_cjs.constNode(real), right: imaginary },
|
|
653
|
+
{ kind: "add", left: chunk4CVLFLOB_cjs.constNode(real), right: imaginary }
|
|
653
654
|
];
|
|
654
655
|
}
|
|
655
656
|
function rational2() {
|
|
@@ -659,11 +660,11 @@ function rational4() {
|
|
|
659
660
|
return { n: 4n, d: 1n };
|
|
660
661
|
}
|
|
661
662
|
function numericRoots(descending) {
|
|
662
|
-
const leading =
|
|
663
|
+
const leading = chunk4CVLFLOB_cjs.rationalToNumber(descending[0]);
|
|
663
664
|
if (leading === 0) return [];
|
|
664
665
|
let bound = 0;
|
|
665
666
|
for (let i = 1; i < descending.length; i++) {
|
|
666
|
-
const ratio = Math.abs(
|
|
667
|
+
const ratio = Math.abs(chunk4CVLFLOB_cjs.rationalToNumber(descending[i]) / leading);
|
|
667
668
|
if (ratio > bound) bound = ratio;
|
|
668
669
|
}
|
|
669
670
|
bound += 1;
|
|
@@ -698,7 +699,7 @@ function bisect(descending, low, high) {
|
|
|
698
699
|
return (left + right) / 2;
|
|
699
700
|
}
|
|
700
701
|
function solveForVariable(lhs, rhs, variable) {
|
|
701
|
-
const polynomial =
|
|
702
|
+
const polynomial = chunk4CVLFLOB_cjs.toPolynomial({ kind: "sub", left: lhs, right: rhs });
|
|
702
703
|
if (polynomial === null) {
|
|
703
704
|
return {
|
|
704
705
|
kind: "unsupported",
|
|
@@ -706,7 +707,7 @@ function solveForVariable(lhs, rhs, variable) {
|
|
|
706
707
|
};
|
|
707
708
|
}
|
|
708
709
|
const others = polynomial.vars.filter((name) => name !== variable);
|
|
709
|
-
const degree =
|
|
710
|
+
const degree = chunk4CVLFLOB_cjs.polyDegree(polynomial, variable);
|
|
710
711
|
if (others.length > 0) {
|
|
711
712
|
if (degree !== 1) {
|
|
712
713
|
return {
|
|
@@ -722,7 +723,7 @@ function solveForVariable(lhs, rhs, variable) {
|
|
|
722
723
|
if (degree > SOLVE_MAX_DEGREE) {
|
|
723
724
|
return { kind: "unsupported", reason: `degree ${degree} is above the supported maximum of ${SOLVE_MAX_DEGREE}` };
|
|
724
725
|
}
|
|
725
|
-
const descending = [...
|
|
726
|
+
const descending = [...chunk4CVLFLOB_cjs.polyCoefficients(polynomial, variable)].reverse();
|
|
726
727
|
return solveUnivariate(descending);
|
|
727
728
|
}
|
|
728
729
|
function solveLinearWithOtherUnknowns(polynomial, variable) {
|
|
@@ -747,8 +748,8 @@ function solveLinearWithOtherUnknowns(polynomial, variable) {
|
|
|
747
748
|
}
|
|
748
749
|
return [...names].sort();
|
|
749
750
|
};
|
|
750
|
-
const coefficient =
|
|
751
|
-
const constant =
|
|
751
|
+
const coefficient = chunk4CVLFLOB_cjs.fromPolynomial({ terms: coefficientTerms, vars: namesOf2(coefficientTerms) });
|
|
752
|
+
const constant = chunk4CVLFLOB_cjs.fromPolynomial({ terms: constantTerms, vars: namesOf2(constantTerms) });
|
|
752
753
|
return {
|
|
753
754
|
kind: "roots",
|
|
754
755
|
exact: [{ kind: "div", left: { kind: "neg", operand: constant }, right: coefficient }],
|
|
@@ -767,19 +768,19 @@ function closedFormRoots(descending) {
|
|
|
767
768
|
function solveUnivariate(descending) {
|
|
768
769
|
const exact = [];
|
|
769
770
|
let remaining = [...descending];
|
|
770
|
-
let roots = [...rationalRoots(remaining)].sort(
|
|
771
|
+
let roots = [...rationalRoots(remaining)].sort(chunk4CVLFLOB_cjs.rationalCompare);
|
|
771
772
|
while (roots.length > 0 && remaining.length > 1) {
|
|
772
773
|
for (const root of roots) {
|
|
773
|
-
while (remaining.length > 1 &&
|
|
774
|
+
while (remaining.length > 1 && chunk4CVLFLOB_cjs.isRationalZero(evaluateRational(remaining, root))) {
|
|
774
775
|
remaining = divideByRoot2(remaining, root);
|
|
775
776
|
}
|
|
776
|
-
exact.push(
|
|
777
|
+
exact.push(chunk4CVLFLOB_cjs.constNode(root));
|
|
777
778
|
}
|
|
778
|
-
roots = remaining.length > 1 ? [...rationalRoots(remaining)].sort(
|
|
779
|
+
roots = remaining.length > 1 ? [...rationalRoots(remaining)].sort(chunk4CVLFLOB_cjs.rationalCompare) : [];
|
|
779
780
|
}
|
|
780
781
|
const leftoverDegree = remaining.length - 1;
|
|
781
782
|
if (leftoverDegree === 1) {
|
|
782
|
-
exact.push(
|
|
783
|
+
exact.push(chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.rationalDiv(chunk4CVLFLOB_cjs.rationalNeg(remaining[1]), remaining[0])));
|
|
783
784
|
return { kind: "roots", exact, approximate: [] };
|
|
784
785
|
}
|
|
785
786
|
if (leftoverDegree === 2) {
|
|
@@ -845,11 +846,11 @@ function valueToSymbolic(v) {
|
|
|
845
846
|
if (v.type === 13 /* Error */ || v.type === 12 /* Pending */) return null;
|
|
846
847
|
const numeric = v.toNumber();
|
|
847
848
|
if (!Number.isFinite(numeric)) return null;
|
|
848
|
-
return
|
|
849
|
+
return chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.rationalFromNumber(numeric));
|
|
849
850
|
}
|
|
850
851
|
function symbolicToValue(node) {
|
|
851
|
-
const simplified =
|
|
852
|
-
if (simplified.kind === "const") return chunkOC6LTXYS_cjs.numberValue(
|
|
852
|
+
const simplified = chunk4CVLFLOB_cjs.simplifySymbolic(node);
|
|
853
|
+
if (simplified.kind === "const") return chunkOC6LTXYS_cjs.numberValue(chunk4CVLFLOB_cjs.rationalToNumber(simplified.value));
|
|
853
854
|
return chunkOC6LTXYS_cjs.symbolicValue(simplified);
|
|
854
855
|
}
|
|
855
856
|
function unsupported(what) {
|
|
@@ -862,7 +863,7 @@ function symbolicPow(l, r) {
|
|
|
862
863
|
const base = valueToSymbolic(l);
|
|
863
864
|
const exponent = valueToSymbolic(r);
|
|
864
865
|
if (base === null || exponent === null) return unsupported("^");
|
|
865
|
-
return symbolicToValue(
|
|
866
|
+
return symbolicToValue(chunk4CVLFLOB_cjs.powNode(base, exponent));
|
|
866
867
|
}
|
|
867
868
|
function symbolicNeg(v) {
|
|
868
869
|
const operand = valueToSymbolic(v);
|
|
@@ -878,11 +879,11 @@ function symbolicBuiltin(index, args) {
|
|
|
878
879
|
nodes.push(node);
|
|
879
880
|
}
|
|
880
881
|
if (index === POW_BUILTIN_INDEX && nodes.length === 2) {
|
|
881
|
-
return symbolicToValue(
|
|
882
|
+
return symbolicToValue(chunk4CVLFLOB_cjs.powNode(nodes[0], nodes[1]));
|
|
882
883
|
}
|
|
883
884
|
const name = SYMBOLIC_BUILTIN_NAMES[index];
|
|
884
885
|
if (name === void 0) return unsupported(`builtin ${index}`);
|
|
885
|
-
return symbolicToValue(
|
|
886
|
+
return symbolicToValue(chunk4CVLFLOB_cjs.callNode(name, nodes));
|
|
886
887
|
}
|
|
887
888
|
function rootToValue(root) {
|
|
888
889
|
const value = symbolicToValue(root);
|
|
@@ -923,15 +924,15 @@ function unifyUom(l, r) {
|
|
|
923
924
|
if (l.unit === r.unit) {
|
|
924
925
|
return { lv: l.toNumber(), rv: r.toNumber(), unit: l.unit, sameMeasure: true };
|
|
925
926
|
}
|
|
926
|
-
const lMeasure =
|
|
927
|
-
const rMeasure =
|
|
928
|
-
const isCurrency =
|
|
927
|
+
const lMeasure = chunkNJTXJ5AG_cjs.getMeasure(l.unit);
|
|
928
|
+
const rMeasure = chunkNJTXJ5AG_cjs.getMeasure(r.unit);
|
|
929
|
+
const isCurrency = chunk2MV4HBKC_cjs.sharedCurrencyExchange.isCurrency(l.unit) && chunk2MV4HBKC_cjs.sharedCurrencyExchange.isCurrency(r.unit);
|
|
929
930
|
if (lMeasure && lMeasure === rMeasure) {
|
|
930
|
-
const rvConverted =
|
|
931
|
+
const rvConverted = chunkNJTXJ5AG_cjs.convertUnit(r.toNumber(), r.unit, l.unit);
|
|
931
932
|
return { lv: l.toNumber(), rv: rvConverted, unit: l.unit, sameMeasure: true };
|
|
932
933
|
}
|
|
933
934
|
if (isCurrency) {
|
|
934
|
-
const rvConverted =
|
|
935
|
+
const rvConverted = chunk2MV4HBKC_cjs.sharedCurrencyExchange.convertSync(r.toNumber(), r.unit, l.unit);
|
|
935
936
|
if (rvConverted !== null) {
|
|
936
937
|
return { lv: l.toNumber(), rv: rvConverted, unit: l.unit, sameMeasure: true };
|
|
937
938
|
}
|
|
@@ -961,7 +962,7 @@ function binaryOp(l, r, op, bigOp, symbolicOp) {
|
|
|
961
962
|
);
|
|
962
963
|
}
|
|
963
964
|
const node = { kind: symbolicOp, left, right };
|
|
964
|
-
return chunkOC6LTXYS_cjs.symbolicValue(
|
|
965
|
+
return chunkOC6LTXYS_cjs.symbolicValue(chunk4CVLFLOB_cjs.simplifySymbolic(node));
|
|
965
966
|
}
|
|
966
967
|
if (l.type === 0 /* Number */ && r.type === 0 /* Number */) {
|
|
967
968
|
return chunkOC6LTXYS_cjs.numberValue(op(l.value, r.value));
|
|
@@ -985,7 +986,7 @@ function binaryOp(l, r, op, bigOp, symbolicOp) {
|
|
|
985
986
|
if (l.type === 7 /* Matrix */ && r.type === 7 /* Matrix */) {
|
|
986
987
|
const lm = l.value;
|
|
987
988
|
const rm = r.value;
|
|
988
|
-
if (!
|
|
989
|
+
if (!chunk4CVLFLOB_cjs.sameShape(lm, rm)) {
|
|
989
990
|
return chunkOC6LTXYS_cjs.errorValue("DIMENSION_MISMATCH", `Cannot combine matrices of different shapes: ${lm.rows}x${lm.cols} and ${rm.rows}x${rm.cols}`);
|
|
990
991
|
}
|
|
991
992
|
const result = new Array(lm.data.length);
|
|
@@ -1060,34 +1061,34 @@ var sharedOpRegistry = new OpRegistry();
|
|
|
1060
1061
|
var APART_MAX_DEGREE = 12;
|
|
1061
1062
|
function multiply(a, b) {
|
|
1062
1063
|
if (a.length === 0 || b.length === 0) return [];
|
|
1063
|
-
const product2 = new Array(a.length + b.length - 1).fill(
|
|
1064
|
+
const product2 = new Array(a.length + b.length - 1).fill(chunk4CVLFLOB_cjs.RATIONAL_ZERO);
|
|
1064
1065
|
a.forEach((left, i) => {
|
|
1065
1066
|
b.forEach((right, j) => {
|
|
1066
|
-
product2[i + j] =
|
|
1067
|
+
product2[i + j] = chunk4CVLFLOB_cjs.rationalAdd(product2[i + j], chunk4CVLFLOB_cjs.rationalMul(left, right));
|
|
1067
1068
|
});
|
|
1068
1069
|
});
|
|
1069
1070
|
return product2;
|
|
1070
1071
|
}
|
|
1071
1072
|
function power(base, exponent) {
|
|
1072
|
-
let result = [
|
|
1073
|
+
let result = [chunk4CVLFLOB_cjs.RATIONAL_ONE];
|
|
1073
1074
|
for (let i = 0; i < exponent; i++) result = multiply(result, base);
|
|
1074
1075
|
return result;
|
|
1075
1076
|
}
|
|
1076
1077
|
function scale(coefficients, factor) {
|
|
1077
|
-
return coefficients.map((coefficient) =>
|
|
1078
|
+
return coefficients.map((coefficient) => chunk4CVLFLOB_cjs.rationalDiv(coefficient, factor));
|
|
1078
1079
|
}
|
|
1079
1080
|
function denominatorFactors(ascending, variable) {
|
|
1080
1081
|
const factors = [];
|
|
1081
1082
|
let lowest = 0;
|
|
1082
|
-
while (lowest < ascending.length &&
|
|
1083
|
-
if (lowest > 0) factors.push({ base: [
|
|
1083
|
+
while (lowest < ascending.length && chunk4CVLFLOB_cjs.isRationalZero(ascending[lowest])) lowest++;
|
|
1084
|
+
if (lowest > 0) factors.push({ base: [chunk4CVLFLOB_cjs.RATIONAL_ZERO, chunk4CVLFLOB_cjs.RATIONAL_ONE], power: lowest });
|
|
1084
1085
|
const remaining = ascending.slice(lowest);
|
|
1085
1086
|
if (remaining.length > 1) {
|
|
1086
1087
|
const factorization = factorUnivariate([...remaining].reverse(), variable);
|
|
1087
1088
|
for (const factor of factorization.factors) {
|
|
1088
|
-
const polynomial =
|
|
1089
|
+
const polynomial = chunk4CVLFLOB_cjs.toPolynomial(factor.base);
|
|
1089
1090
|
if (polynomial === null) return null;
|
|
1090
|
-
factors.push({ base: [...
|
|
1091
|
+
factors.push({ base: [...chunk4CVLFLOB_cjs.polyCoefficients(polynomial, variable)], power: factor.power });
|
|
1091
1092
|
}
|
|
1092
1093
|
}
|
|
1093
1094
|
return factors.length > 0 ? factors : null;
|
|
@@ -1106,10 +1107,10 @@ function enumerateUnknowns(factors) {
|
|
|
1106
1107
|
}
|
|
1107
1108
|
function unknownColumn(unknown, factors, denominator) {
|
|
1108
1109
|
const divisor = power(factors[unknown.factor].base, unknown.power);
|
|
1109
|
-
const { quotient, remainder } =
|
|
1110
|
-
if (!
|
|
1111
|
-
const shift = new Array(unknown.degree).fill(
|
|
1112
|
-
shift.push(
|
|
1110
|
+
const { quotient, remainder } = chunk4CVLFLOB_cjs.polynomialDivide(denominator, divisor);
|
|
1111
|
+
if (!chunk4CVLFLOB_cjs.isZeroPolynomial(remainder)) return null;
|
|
1112
|
+
const shift = new Array(unknown.degree).fill(chunk4CVLFLOB_cjs.RATIONAL_ZERO);
|
|
1113
|
+
shift.push(chunk4CVLFLOB_cjs.RATIONAL_ONE);
|
|
1113
1114
|
return multiply(quotient, shift);
|
|
1114
1115
|
}
|
|
1115
1116
|
function solveLinearSystem(matrix, target) {
|
|
@@ -1117,7 +1118,7 @@ function solveLinearSystem(matrix, target) {
|
|
|
1117
1118
|
for (let column = 0; column < size; column++) {
|
|
1118
1119
|
let pivot = -1;
|
|
1119
1120
|
for (let row = column; row < size; row++) {
|
|
1120
|
-
if (!
|
|
1121
|
+
if (!chunk4CVLFLOB_cjs.isRationalZero(matrix[row][column])) {
|
|
1121
1122
|
pivot = row;
|
|
1122
1123
|
break;
|
|
1123
1124
|
}
|
|
@@ -1126,21 +1127,21 @@ function solveLinearSystem(matrix, target) {
|
|
|
1126
1127
|
[matrix[column], matrix[pivot]] = [matrix[pivot], matrix[column]];
|
|
1127
1128
|
[target[column], target[pivot]] = [target[pivot], target[column]];
|
|
1128
1129
|
for (let row = 0; row < size; row++) {
|
|
1129
|
-
if (row === column ||
|
|
1130
|
-
const factor =
|
|
1130
|
+
if (row === column || chunk4CVLFLOB_cjs.isRationalZero(matrix[row][column])) continue;
|
|
1131
|
+
const factor = chunk4CVLFLOB_cjs.rationalDiv(matrix[row][column], matrix[column][column]);
|
|
1131
1132
|
for (let k = column; k < size; k++) {
|
|
1132
|
-
matrix[row][k] =
|
|
1133
|
+
matrix[row][k] = chunk4CVLFLOB_cjs.rationalSub(matrix[row][k], chunk4CVLFLOB_cjs.rationalMul(factor, matrix[column][k]));
|
|
1133
1134
|
}
|
|
1134
|
-
target[row] =
|
|
1135
|
+
target[row] = chunk4CVLFLOB_cjs.rationalSub(target[row], chunk4CVLFLOB_cjs.rationalMul(factor, target[column]));
|
|
1135
1136
|
}
|
|
1136
1137
|
}
|
|
1137
|
-
return target.map((value, index) =>
|
|
1138
|
+
return target.map((value, index) => chunk4CVLFLOB_cjs.rationalDiv(value, matrix[index][index]));
|
|
1138
1139
|
}
|
|
1139
1140
|
function partialFractions(numerator, denominator, variable) {
|
|
1140
1141
|
if (denominator.length < 2 || denominator.length - 1 > APART_MAX_DEGREE) return null;
|
|
1141
|
-
const shared =
|
|
1142
|
-
const reducedNumerator = shared.length > 1 ?
|
|
1143
|
-
const reducedDenominator = shared.length > 1 ?
|
|
1142
|
+
const shared = chunk4CVLFLOB_cjs.coefficientGcd(numerator, denominator);
|
|
1143
|
+
const reducedNumerator = shared.length > 1 ? chunk4CVLFLOB_cjs.polynomialDivide(numerator, shared).quotient : [...numerator];
|
|
1144
|
+
const reducedDenominator = shared.length > 1 ? chunk4CVLFLOB_cjs.polynomialDivide(denominator, shared).quotient : [...denominator];
|
|
1144
1145
|
if (reducedDenominator.length === 1) {
|
|
1145
1146
|
return { polynomial: scale(reducedNumerator, reducedDenominator[0]), terms: [] };
|
|
1146
1147
|
}
|
|
@@ -1148,8 +1149,8 @@ function partialFractions(numerator, denominator, variable) {
|
|
|
1148
1149
|
const leading = reducedDenominator[reducedDenominator.length - 1];
|
|
1149
1150
|
const monicDenominator = scale(reducedDenominator, leading);
|
|
1150
1151
|
const scaledNumerator = scale(reducedNumerator, leading);
|
|
1151
|
-
const { quotient, remainder } =
|
|
1152
|
-
if (
|
|
1152
|
+
const { quotient, remainder } = chunk4CVLFLOB_cjs.polynomialDivide(scaledNumerator, monicDenominator);
|
|
1153
|
+
if (chunk4CVLFLOB_cjs.isZeroPolynomial(remainder)) return { polynomial: quotient, terms: [] };
|
|
1153
1154
|
const factors = denominatorFactors(monicDenominator, variable);
|
|
1154
1155
|
if (factors === null) return null;
|
|
1155
1156
|
const terms = solveForNumerators(factors, monicDenominator, remainder);
|
|
@@ -1167,10 +1168,10 @@ function solveForNumerators(factors, denominator, remainder) {
|
|
|
1167
1168
|
}
|
|
1168
1169
|
const matrix = [];
|
|
1169
1170
|
for (let row = 0; row < size; row++) {
|
|
1170
|
-
matrix.push(columns.map((column) => column[row] ??
|
|
1171
|
+
matrix.push(columns.map((column) => column[row] ?? chunk4CVLFLOB_cjs.RATIONAL_ZERO));
|
|
1171
1172
|
}
|
|
1172
1173
|
const target = [];
|
|
1173
|
-
for (let row = 0; row < size; row++) target.push(remainder[row] ??
|
|
1174
|
+
for (let row = 0; row < size; row++) target.push(remainder[row] ?? chunk4CVLFLOB_cjs.RATIONAL_ZERO);
|
|
1174
1175
|
const solution = solveLinearSystem(matrix, target);
|
|
1175
1176
|
if (solution === null) return null;
|
|
1176
1177
|
return groupSolution(unknowns, solution, factors);
|
|
@@ -1186,8 +1187,8 @@ function groupSolution(unknowns, solution, factors) {
|
|
|
1186
1187
|
const terms = [];
|
|
1187
1188
|
for (const [key, coefficients] of grouped) {
|
|
1188
1189
|
const [factorIndex, termPower] = key.split(":").map(Number);
|
|
1189
|
-
const filled = [...coefficients].map((value) => value ??
|
|
1190
|
-
if (filled.every(
|
|
1190
|
+
const filled = [...coefficients].map((value) => value ?? chunk4CVLFLOB_cjs.RATIONAL_ZERO);
|
|
1191
|
+
if (filled.every(chunk4CVLFLOB_cjs.isRationalZero)) continue;
|
|
1191
1192
|
terms.push({ numerator: filled, base: factors[factorIndex].base, power: termPower });
|
|
1192
1193
|
}
|
|
1193
1194
|
return terms;
|
|
@@ -1195,11 +1196,11 @@ function groupSolution(unknowns, solution, factors) {
|
|
|
1195
1196
|
function coefficientsToNode2(coefficients, variable) {
|
|
1196
1197
|
const terms = /* @__PURE__ */ new Map();
|
|
1197
1198
|
coefficients.forEach((coefficient, exponent) => {
|
|
1198
|
-
if (
|
|
1199
|
+
if (chunk4CVLFLOB_cjs.isRationalZero(coefficient)) return;
|
|
1199
1200
|
terms.set(exponent === 0 ? "" : exponent === 1 ? variable : `${variable}^${exponent}`, coefficient);
|
|
1200
1201
|
});
|
|
1201
|
-
if (terms.size === 0) return
|
|
1202
|
-
return
|
|
1202
|
+
if (terms.size === 0) return chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.RATIONAL_ZERO);
|
|
1203
|
+
return chunk4CVLFLOB_cjs.fromPolynomial({ terms, vars: coefficients.length > 1 ? [variable] : [] });
|
|
1203
1204
|
}
|
|
1204
1205
|
function apartSymbolic(node) {
|
|
1205
1206
|
const parts = asRationalFunction(node);
|
|
@@ -1209,9 +1210,9 @@ function apartSymbolic(node) {
|
|
|
1209
1210
|
let result = decomposition.polynomial.length > 0 ? coefficientsToNode2(decomposition.polynomial, parts.variable) : null;
|
|
1210
1211
|
for (const term of decomposition.terms) {
|
|
1211
1212
|
const base = coefficientsToNode2(term.base, parts.variable);
|
|
1212
|
-
const denominator = term.power === 1 ? base :
|
|
1213
|
+
const denominator = term.power === 1 ? base : chunk4CVLFLOB_cjs.powNode(base, chunk4CVLFLOB_cjs.constNode({ n: BigInt(term.power), d: 1n }));
|
|
1213
1214
|
const negative = isNegativeNumerator(term.numerator);
|
|
1214
|
-
const numerator = negative ? term.numerator.map((coefficient) =>
|
|
1215
|
+
const numerator = negative ? term.numerator.map((coefficient) => chunk4CVLFLOB_cjs.rationalNeg(coefficient)) : term.numerator;
|
|
1215
1216
|
const piece = {
|
|
1216
1217
|
kind: "div",
|
|
1217
1218
|
left: coefficientsToNode2(numerator, parts.variable),
|
|
@@ -1220,22 +1221,22 @@ function apartSymbolic(node) {
|
|
|
1220
1221
|
if (result === null) result = negative ? { kind: "neg", operand: piece } : piece;
|
|
1221
1222
|
else result = { kind: negative ? "sub" : "add", left: result, right: piece };
|
|
1222
1223
|
}
|
|
1223
|
-
return result === null ? node :
|
|
1224
|
+
return result === null ? node : chunk4CVLFLOB_cjs.simplifySymbolic(result);
|
|
1224
1225
|
}
|
|
1225
1226
|
function isNegativeNumerator(coefficients) {
|
|
1226
1227
|
return coefficients.some((coefficient) => coefficient.n < 0n) && coefficients.every((coefficient) => coefficient.n <= 0n);
|
|
1227
1228
|
}
|
|
1228
1229
|
function asRationalFunction(node) {
|
|
1229
1230
|
if (node.kind !== "div") return null;
|
|
1230
|
-
const numerator =
|
|
1231
|
-
const denominator =
|
|
1231
|
+
const numerator = chunk4CVLFLOB_cjs.toPolynomial(node.left);
|
|
1232
|
+
const denominator = chunk4CVLFLOB_cjs.toPolynomial(node.right);
|
|
1232
1233
|
if (numerator === null || denominator === null) return null;
|
|
1233
|
-
const variable =
|
|
1234
|
+
const variable = chunk4CVLFLOB_cjs.polyUnivariateVar(denominator);
|
|
1234
1235
|
if (variable === null) return null;
|
|
1235
1236
|
if (numerator.vars.some((name) => name !== variable)) return null;
|
|
1236
1237
|
return {
|
|
1237
|
-
numerator:
|
|
1238
|
-
denominator:
|
|
1238
|
+
numerator: chunk4CVLFLOB_cjs.polyCoefficients(numerator, variable),
|
|
1239
|
+
denominator: chunk4CVLFLOB_cjs.polyCoefficients(denominator, variable),
|
|
1239
1240
|
variable
|
|
1240
1241
|
};
|
|
1241
1242
|
}
|
|
@@ -1243,52 +1244,52 @@ function asRationalFunction(node) {
|
|
|
1243
1244
|
// src/symbolic/Derivative.ts
|
|
1244
1245
|
var DERIVATIVE_MAX_ORDER = 16;
|
|
1245
1246
|
function zero() {
|
|
1246
|
-
return
|
|
1247
|
+
return chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.RATIONAL_ZERO);
|
|
1247
1248
|
}
|
|
1248
1249
|
function one() {
|
|
1249
|
-
return
|
|
1250
|
+
return chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.RATIONAL_ONE);
|
|
1250
1251
|
}
|
|
1251
1252
|
function functionDerivative(name, argument) {
|
|
1252
1253
|
switch (name) {
|
|
1253
1254
|
case "sin":
|
|
1254
|
-
return
|
|
1255
|
+
return chunk4CVLFLOB_cjs.callNode("cos", [argument]);
|
|
1255
1256
|
case "cos":
|
|
1256
|
-
return { kind: "neg", operand:
|
|
1257
|
+
return { kind: "neg", operand: chunk4CVLFLOB_cjs.callNode("sin", [argument]) };
|
|
1257
1258
|
case "tan":
|
|
1258
|
-
return { kind: "div", left: one(), right:
|
|
1259
|
+
return { kind: "div", left: one(), right: chunk4CVLFLOB_cjs.powNode(chunk4CVLFLOB_cjs.callNode("cos", [argument]), chunk4CVLFLOB_cjs.constNode(2)) };
|
|
1259
1260
|
case "exp":
|
|
1260
|
-
return
|
|
1261
|
+
return chunk4CVLFLOB_cjs.callNode("exp", [argument]);
|
|
1261
1262
|
case "log":
|
|
1262
1263
|
return { kind: "div", left: one(), right: argument };
|
|
1263
1264
|
case "sqrt":
|
|
1264
1265
|
return {
|
|
1265
1266
|
kind: "div",
|
|
1266
1267
|
left: one(),
|
|
1267
|
-
right: { kind: "mul", left:
|
|
1268
|
+
right: { kind: "mul", left: chunk4CVLFLOB_cjs.constNode(2), right: chunk4CVLFLOB_cjs.callNode("sqrt", [argument]) }
|
|
1268
1269
|
};
|
|
1269
1270
|
case "asin":
|
|
1270
|
-
return { kind: "div", left: one(), right:
|
|
1271
|
+
return { kind: "div", left: one(), right: chunk4CVLFLOB_cjs.callNode("sqrt", [oneMinusSquare(argument)]) };
|
|
1271
1272
|
case "acos":
|
|
1272
|
-
return { kind: "neg", operand: { kind: "div", left: one(), right:
|
|
1273
|
+
return { kind: "neg", operand: { kind: "div", left: one(), right: chunk4CVLFLOB_cjs.callNode("sqrt", [oneMinusSquare(argument)]) } };
|
|
1273
1274
|
case "atan":
|
|
1274
1275
|
return { kind: "div", left: one(), right: onePlusSquare(argument) };
|
|
1275
1276
|
case "sinh":
|
|
1276
|
-
return
|
|
1277
|
+
return chunk4CVLFLOB_cjs.callNode("cosh", [argument]);
|
|
1277
1278
|
case "cosh":
|
|
1278
|
-
return
|
|
1279
|
+
return chunk4CVLFLOB_cjs.callNode("sinh", [argument]);
|
|
1279
1280
|
case "tanh":
|
|
1280
|
-
return { kind: "div", left: one(), right:
|
|
1281
|
+
return { kind: "div", left: one(), right: chunk4CVLFLOB_cjs.powNode(chunk4CVLFLOB_cjs.callNode("cosh", [argument]), chunk4CVLFLOB_cjs.constNode(2)) };
|
|
1281
1282
|
case "abs":
|
|
1282
|
-
return
|
|
1283
|
+
return chunk4CVLFLOB_cjs.callNode("sign", [argument]);
|
|
1283
1284
|
default:
|
|
1284
1285
|
return null;
|
|
1285
1286
|
}
|
|
1286
1287
|
}
|
|
1287
1288
|
function oneMinusSquare(argument) {
|
|
1288
|
-
return { kind: "sub", left: one(), right:
|
|
1289
|
+
return { kind: "sub", left: one(), right: chunk4CVLFLOB_cjs.powNode(argument, chunk4CVLFLOB_cjs.constNode(2)) };
|
|
1289
1290
|
}
|
|
1290
1291
|
function onePlusSquare(argument) {
|
|
1291
|
-
return { kind: "add", left: one(), right:
|
|
1292
|
+
return { kind: "add", left: one(), right: chunk4CVLFLOB_cjs.powNode(argument, chunk4CVLFLOB_cjs.constNode(2)) };
|
|
1292
1293
|
}
|
|
1293
1294
|
function differentiate(node, variable, order = 1) {
|
|
1294
1295
|
if (order < 0 || !Number.isInteger(order)) {
|
|
@@ -1301,8 +1302,8 @@ function differentiate(node, variable, order = 1) {
|
|
|
1301
1302
|
{ limit: DERIVATIVE_MAX_ORDER }
|
|
1302
1303
|
);
|
|
1303
1304
|
}
|
|
1304
|
-
let result =
|
|
1305
|
-
for (let i = 0; i < order; i++) result =
|
|
1305
|
+
let result = chunk4CVLFLOB_cjs.simplifySymbolic(node);
|
|
1306
|
+
for (let i = 0; i < order; i++) result = chunk4CVLFLOB_cjs.simplifySymbolic(derive(result, variable));
|
|
1306
1307
|
return result;
|
|
1307
1308
|
}
|
|
1308
1309
|
function derive(node, variable) {
|
|
@@ -1332,7 +1333,7 @@ function derive(node, variable) {
|
|
|
1332
1333
|
left: { kind: "mul", left: derive(node.left, variable), right: node.right },
|
|
1333
1334
|
right: { kind: "mul", left: node.left, right: derive(node.right, variable) }
|
|
1334
1335
|
},
|
|
1335
|
-
right:
|
|
1336
|
+
right: chunk4CVLFLOB_cjs.powNode(node.right, chunk4CVLFLOB_cjs.constNode(2))
|
|
1336
1337
|
};
|
|
1337
1338
|
case "pow":
|
|
1338
1339
|
return derivePow(node, variable);
|
|
@@ -1346,79 +1347,79 @@ function derive(node, variable) {
|
|
|
1346
1347
|
}
|
|
1347
1348
|
function derivePow(node, variable) {
|
|
1348
1349
|
if (node.exponent.kind === "const") {
|
|
1349
|
-
const reduced =
|
|
1350
|
+
const reduced = chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.rationalSub(node.exponent.value, chunk4CVLFLOB_cjs.RATIONAL_ONE));
|
|
1350
1351
|
return {
|
|
1351
1352
|
kind: "mul",
|
|
1352
|
-
left: { kind: "mul", left: node.exponent, right:
|
|
1353
|
+
left: { kind: "mul", left: node.exponent, right: chunk4CVLFLOB_cjs.powNode(node.base, reduced) },
|
|
1353
1354
|
right: derive(node.base, variable)
|
|
1354
1355
|
};
|
|
1355
1356
|
}
|
|
1356
1357
|
if (node.base.kind === "const" && node.base.value.n > 0n) {
|
|
1357
1358
|
return {
|
|
1358
1359
|
kind: "mul",
|
|
1359
|
-
left: { kind: "mul", left: node, right:
|
|
1360
|
+
left: { kind: "mul", left: node, right: chunk4CVLFLOB_cjs.callNode("log", [node.base]) },
|
|
1360
1361
|
right: derive(node.exponent, variable)
|
|
1361
1362
|
};
|
|
1362
1363
|
}
|
|
1363
1364
|
return unevaluated(node, variable);
|
|
1364
1365
|
}
|
|
1365
1366
|
function unevaluated(node, variable) {
|
|
1366
|
-
return
|
|
1367
|
+
return chunk4CVLFLOB_cjs.callNode("der", [node, chunk4CVLFLOB_cjs.varNode(variable)]);
|
|
1367
1368
|
}
|
|
1368
1369
|
|
|
1369
1370
|
// src/symbolic/Integral.ts
|
|
1370
1371
|
function asLinear(node, variable) {
|
|
1371
|
-
const polynomial =
|
|
1372
|
+
const polynomial = chunk4CVLFLOB_cjs.toPolynomial(node);
|
|
1372
1373
|
if (polynomial === null) return null;
|
|
1373
1374
|
const others = polynomial.vars.filter((name) => name !== variable);
|
|
1374
1375
|
if (others.length > 0) return null;
|
|
1375
|
-
if (
|
|
1376
|
-
const ascending =
|
|
1376
|
+
if (chunk4CVLFLOB_cjs.polyDegree(polynomial, variable) > 1) return null;
|
|
1377
|
+
const ascending = chunk4CVLFLOB_cjs.polyCoefficients(polynomial, variable);
|
|
1377
1378
|
const intercept = ascending[0] ?? { n: 0n, d: 1n };
|
|
1378
1379
|
const slope = ascending[1] ?? { n: 0n, d: 1n };
|
|
1379
|
-
return
|
|
1380
|
+
return chunk4CVLFLOB_cjs.isRationalZero(slope) ? null : { slope, intercept };
|
|
1380
1381
|
}
|
|
1381
1382
|
function integratePolynomial(node, variable) {
|
|
1382
|
-
const polynomial =
|
|
1383
|
+
const polynomial = chunk4CVLFLOB_cjs.toPolynomial(node);
|
|
1383
1384
|
if (polynomial === null) return null;
|
|
1384
1385
|
const others = polynomial.vars.filter((name) => name !== variable);
|
|
1385
1386
|
if (others.length > 0) {
|
|
1386
1387
|
return { ok: false, reason: `it involves more than one unknown (${others.join(", ")})` };
|
|
1387
1388
|
}
|
|
1388
|
-
const ascending =
|
|
1389
|
-
let result =
|
|
1389
|
+
const ascending = chunk4CVLFLOB_cjs.polyCoefficients(polynomial, variable);
|
|
1390
|
+
let result = chunk4CVLFLOB_cjs.constNode(0);
|
|
1390
1391
|
ascending.forEach((coeff, power2) => {
|
|
1391
|
-
if (
|
|
1392
|
+
if (chunk4CVLFLOB_cjs.isRationalZero(coeff)) return;
|
|
1392
1393
|
const nextPower = power2 + 1;
|
|
1393
|
-
const scaled =
|
|
1394
|
+
const scaled = chunk4CVLFLOB_cjs.rationalDiv(coeff, { n: BigInt(nextPower), d: 1n });
|
|
1394
1395
|
const term = {
|
|
1395
1396
|
kind: "mul",
|
|
1396
|
-
left:
|
|
1397
|
-
right: nextPower === 1 ?
|
|
1397
|
+
left: chunk4CVLFLOB_cjs.constNode(scaled),
|
|
1398
|
+
right: nextPower === 1 ? chunk4CVLFLOB_cjs.varNode(variable) : chunk4CVLFLOB_cjs.powNode(chunk4CVLFLOB_cjs.varNode(variable), chunk4CVLFLOB_cjs.constNode(nextPower))
|
|
1398
1399
|
};
|
|
1399
1400
|
result = { kind: "add", left: result, right: term };
|
|
1400
1401
|
});
|
|
1401
|
-
return { ok: true, value:
|
|
1402
|
+
return { ok: true, value: chunk4CVLFLOB_cjs.simplifySymbolic(result) };
|
|
1402
1403
|
}
|
|
1403
1404
|
function integrateStandardForm(node, variable) {
|
|
1404
1405
|
if (node.kind !== "call" || node.args.length !== 1) return null;
|
|
1405
1406
|
const linear = asLinear(node.args[0], variable);
|
|
1406
1407
|
if (linear === null) return null;
|
|
1407
1408
|
const inner = node.args[0];
|
|
1408
|
-
const divideBySlope = (value) =>
|
|
1409
|
+
const divideBySlope = (value) => chunk4CVLFLOB_cjs.simplifySymbolic({ kind: "div", left: value, right: chunk4CVLFLOB_cjs.constNode(linear.slope) });
|
|
1409
1410
|
switch (node.name) {
|
|
1410
1411
|
case "exp":
|
|
1411
|
-
return { ok: true, value: divideBySlope(
|
|
1412
|
+
return { ok: true, value: divideBySlope(chunk4CVLFLOB_cjs.callNode("exp", [inner])) };
|
|
1412
1413
|
case "sin":
|
|
1413
|
-
return { ok: true, value: divideBySlope({ kind: "neg", operand:
|
|
1414
|
+
return { ok: true, value: divideBySlope({ kind: "neg", operand: chunk4CVLFLOB_cjs.callNode("cos", [inner]) }) };
|
|
1414
1415
|
case "cos":
|
|
1415
|
-
return { ok: true, value: divideBySlope(
|
|
1416
|
+
return { ok: true, value: divideBySlope(chunk4CVLFLOB_cjs.callNode("sin", [inner])) };
|
|
1416
1417
|
case "log":
|
|
1417
1418
|
return {
|
|
1418
1419
|
ok: true,
|
|
1419
1420
|
value: divideBySlope({
|
|
1420
1421
|
kind: "sub",
|
|
1421
|
-
left: { kind: "mul", left: inner, right:
|
|
1422
|
+
left: { kind: "mul", left: inner, right: chunk4CVLFLOB_cjs.callNode("log", [inner]) },
|
|
1422
1423
|
right: inner
|
|
1423
1424
|
})
|
|
1424
1425
|
};
|
|
@@ -1433,18 +1434,18 @@ function integrateReciprocalForms(node, variable) {
|
|
|
1433
1434
|
if (linear !== null) {
|
|
1434
1435
|
return {
|
|
1435
1436
|
ok: true,
|
|
1436
|
-
value:
|
|
1437
|
+
value: chunk4CVLFLOB_cjs.simplifySymbolic({
|
|
1437
1438
|
kind: "div",
|
|
1438
|
-
left:
|
|
1439
|
-
right:
|
|
1439
|
+
left: chunk4CVLFLOB_cjs.callNode("log", [node.right]),
|
|
1440
|
+
right: chunk4CVLFLOB_cjs.constNode(linear.slope)
|
|
1440
1441
|
})
|
|
1441
1442
|
};
|
|
1442
1443
|
}
|
|
1443
|
-
const denominator =
|
|
1444
|
+
const denominator = chunk4CVLFLOB_cjs.toPolynomial(node.right);
|
|
1444
1445
|
if (denominator !== null && denominator.vars.length === 1 && denominator.vars[0] === variable) {
|
|
1445
|
-
const ascending =
|
|
1446
|
-
const isOnePlusSquare = ascending.length === 3 && isRationalOneNode(ascending[0]) &&
|
|
1447
|
-
if (isOnePlusSquare) return { ok: true, value:
|
|
1446
|
+
const ascending = chunk4CVLFLOB_cjs.polyCoefficients(denominator, variable);
|
|
1447
|
+
const isOnePlusSquare = ascending.length === 3 && isRationalOneNode(ascending[0]) && chunk4CVLFLOB_cjs.isRationalZero(ascending[1]) && isRationalOneNode(ascending[2]);
|
|
1448
|
+
if (isOnePlusSquare) return { ok: true, value: chunk4CVLFLOB_cjs.callNode("atan", [chunk4CVLFLOB_cjs.varNode(variable)]) };
|
|
1448
1449
|
}
|
|
1449
1450
|
return null;
|
|
1450
1451
|
}
|
|
@@ -1456,7 +1457,7 @@ function integrateRationalFunction(node, variable) {
|
|
|
1456
1457
|
if (parts === null || parts.variable !== variable) return null;
|
|
1457
1458
|
const decomposition = partialFractions(parts.numerator, parts.denominator, variable);
|
|
1458
1459
|
if (decomposition === null) return null;
|
|
1459
|
-
let result = decomposition.polynomial.length > 0 ? polynomialAntiderivative(decomposition.polynomial, variable) :
|
|
1460
|
+
let result = decomposition.polynomial.length > 0 ? polynomialAntiderivative(decomposition.polynomial, variable) : chunk4CVLFLOB_cjs.constNode(0);
|
|
1460
1461
|
for (const term of decomposition.terms) {
|
|
1461
1462
|
const piece = integrateTerm(term, variable);
|
|
1462
1463
|
if (piece === null) {
|
|
@@ -1467,72 +1468,72 @@ function integrateRationalFunction(node, variable) {
|
|
|
1467
1468
|
}
|
|
1468
1469
|
result = { kind: "add", left: result, right: piece };
|
|
1469
1470
|
}
|
|
1470
|
-
return { ok: true, value:
|
|
1471
|
+
return { ok: true, value: chunk4CVLFLOB_cjs.simplifySymbolic(result) };
|
|
1471
1472
|
}
|
|
1472
1473
|
function integrateTerm(term, variable) {
|
|
1473
1474
|
const baseDegree = term.base.length - 1;
|
|
1474
1475
|
const base = coefficientsToNode2(term.base, variable);
|
|
1475
1476
|
if (baseDegree === 1) {
|
|
1476
|
-
const coefficient = term.numerator[0] ??
|
|
1477
|
+
const coefficient = term.numerator[0] ?? chunk4CVLFLOB_cjs.RATIONAL_ZERO;
|
|
1477
1478
|
if (term.power === 1) {
|
|
1478
|
-
return { kind: "mul", left:
|
|
1479
|
+
return { kind: "mul", left: chunk4CVLFLOB_cjs.constNode(coefficient), right: chunk4CVLFLOB_cjs.callNode("log", [base]) };
|
|
1479
1480
|
}
|
|
1480
1481
|
const reduced = term.power - 1;
|
|
1481
|
-
const scaled =
|
|
1482
|
+
const scaled = chunk4CVLFLOB_cjs.rationalDiv(coefficient, { n: BigInt(-reduced), d: 1n });
|
|
1482
1483
|
return {
|
|
1483
1484
|
kind: "div",
|
|
1484
|
-
left:
|
|
1485
|
-
right:
|
|
1485
|
+
left: chunk4CVLFLOB_cjs.constNode(scaled),
|
|
1486
|
+
right: chunk4CVLFLOB_cjs.powNode(base, chunk4CVLFLOB_cjs.constNode({ n: BigInt(reduced), d: 1n }))
|
|
1486
1487
|
};
|
|
1487
1488
|
}
|
|
1488
1489
|
if (baseDegree !== 2 || term.power !== 1) return null;
|
|
1489
1490
|
return integrateQuadraticTerm(term, variable, base);
|
|
1490
1491
|
}
|
|
1491
1492
|
function integrateQuadraticTerm(term, variable, base) {
|
|
1492
|
-
const constant = term.numerator[0] ??
|
|
1493
|
-
const linear = term.numerator[1] ??
|
|
1493
|
+
const constant = term.numerator[0] ?? chunk4CVLFLOB_cjs.RATIONAL_ZERO;
|
|
1494
|
+
const linear = term.numerator[1] ?? chunk4CVLFLOB_cjs.RATIONAL_ZERO;
|
|
1494
1495
|
const [q, p] = term.base;
|
|
1495
1496
|
const half = { n: 1n, d: 2n };
|
|
1496
|
-
const halfP =
|
|
1497
|
+
const halfP = chunk4CVLFLOB_cjs.rationalMul(p, half);
|
|
1497
1498
|
const logarithm = {
|
|
1498
1499
|
kind: "mul",
|
|
1499
|
-
left:
|
|
1500
|
-
right:
|
|
1500
|
+
left: chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.rationalMul(linear, half)),
|
|
1501
|
+
right: chunk4CVLFLOB_cjs.callNode("log", [base])
|
|
1501
1502
|
};
|
|
1502
|
-
const leftover =
|
|
1503
|
-
if (
|
|
1504
|
-
const width =
|
|
1503
|
+
const leftover = chunk4CVLFLOB_cjs.rationalSub(constant, chunk4CVLFLOB_cjs.rationalMul(linear, halfP));
|
|
1504
|
+
if (chunk4CVLFLOB_cjs.isRationalZero(leftover)) return logarithm;
|
|
1505
|
+
const width = chunk4CVLFLOB_cjs.surdNode(chunk4CVLFLOB_cjs.rationalSub(q, chunk4CVLFLOB_cjs.rationalMul(halfP, halfP)));
|
|
1505
1506
|
const shifted = {
|
|
1506
1507
|
kind: "add",
|
|
1507
|
-
left:
|
|
1508
|
-
right:
|
|
1508
|
+
left: chunk4CVLFLOB_cjs.varNode(variable),
|
|
1509
|
+
right: chunk4CVLFLOB_cjs.constNode(halfP)
|
|
1509
1510
|
};
|
|
1510
1511
|
const arctangent = {
|
|
1511
1512
|
kind: "mul",
|
|
1512
|
-
left: { kind: "div", left:
|
|
1513
|
-
right:
|
|
1513
|
+
left: { kind: "div", left: chunk4CVLFLOB_cjs.constNode(leftover), right: width },
|
|
1514
|
+
right: chunk4CVLFLOB_cjs.callNode("atan", [{ kind: "div", left: shifted, right: width }])
|
|
1514
1515
|
};
|
|
1515
|
-
return
|
|
1516
|
+
return chunk4CVLFLOB_cjs.isRationalZero(linear) ? arctangent : { kind: "add", left: logarithm, right: arctangent };
|
|
1516
1517
|
}
|
|
1517
1518
|
function polynomialAntiderivative(ascending, variable) {
|
|
1518
|
-
let result =
|
|
1519
|
+
let result = chunk4CVLFLOB_cjs.constNode(0);
|
|
1519
1520
|
ascending.forEach((coeff, exponent) => {
|
|
1520
|
-
if (
|
|
1521
|
+
if (chunk4CVLFLOB_cjs.isRationalZero(coeff)) return;
|
|
1521
1522
|
const nextPower = exponent + 1;
|
|
1522
|
-
const scaled =
|
|
1523
|
+
const scaled = chunk4CVLFLOB_cjs.rationalDiv(coeff, { n: BigInt(nextPower), d: 1n });
|
|
1523
1524
|
const term = {
|
|
1524
1525
|
kind: "mul",
|
|
1525
|
-
left:
|
|
1526
|
-
right: nextPower === 1 ?
|
|
1526
|
+
left: chunk4CVLFLOB_cjs.constNode(scaled),
|
|
1527
|
+
right: nextPower === 1 ? chunk4CVLFLOB_cjs.varNode(variable) : chunk4CVLFLOB_cjs.powNode(chunk4CVLFLOB_cjs.varNode(variable), chunk4CVLFLOB_cjs.constNode(nextPower))
|
|
1527
1528
|
};
|
|
1528
1529
|
result = { kind: "add", left: result, right: term };
|
|
1529
1530
|
});
|
|
1530
1531
|
return result;
|
|
1531
1532
|
}
|
|
1532
1533
|
function integrate(node, variable) {
|
|
1533
|
-
const simplified =
|
|
1534
|
-
if (!
|
|
1535
|
-
return { ok: true, value:
|
|
1534
|
+
const simplified = chunk4CVLFLOB_cjs.simplifySymbolic(node);
|
|
1535
|
+
if (!chunk4CVLFLOB_cjs.freeVariables(simplified).has(variable)) {
|
|
1536
|
+
return { ok: true, value: chunk4CVLFLOB_cjs.simplifySymbolic({ kind: "mul", left: simplified, right: chunk4CVLFLOB_cjs.varNode(variable) }) };
|
|
1536
1537
|
}
|
|
1537
1538
|
const polynomial = integratePolynomial(simplified, variable);
|
|
1538
1539
|
if (polynomial !== null) return polynomial;
|
|
@@ -1549,13 +1550,13 @@ function integrate(node, variable) {
|
|
|
1549
1550
|
if (!right.ok) return right;
|
|
1550
1551
|
return {
|
|
1551
1552
|
ok: true,
|
|
1552
|
-
value:
|
|
1553
|
+
value: chunk4CVLFLOB_cjs.simplifySymbolic({ kind: simplified.kind, left: left.value, right: right.value })
|
|
1553
1554
|
};
|
|
1554
1555
|
}
|
|
1555
1556
|
if (simplified.kind === "mul" && simplified.left.kind === "const") {
|
|
1556
1557
|
const inner = integrate(simplified.right, variable);
|
|
1557
1558
|
if (!inner.ok) return inner;
|
|
1558
|
-
return { ok: true, value:
|
|
1559
|
+
return { ok: true, value: chunk4CVLFLOB_cjs.simplifySymbolic({ kind: "mul", left: simplified.left, right: inner.value }) };
|
|
1559
1560
|
}
|
|
1560
1561
|
return {
|
|
1561
1562
|
ok: false,
|
|
@@ -1573,13 +1574,13 @@ function taylorSeries(node, variable, point, degree) {
|
|
|
1573
1574
|
{ limit: TAYLOR_MAX_DEGREE }
|
|
1574
1575
|
);
|
|
1575
1576
|
}
|
|
1576
|
-
const pointNode =
|
|
1577
|
+
const pointNode = chunk4CVLFLOB_cjs.constNode(point);
|
|
1577
1578
|
let factorial = 1n;
|
|
1578
|
-
let result =
|
|
1579
|
+
let result = chunk4CVLFLOB_cjs.constNode(chunk4CVLFLOB_cjs.RATIONAL_ZERO);
|
|
1579
1580
|
for (let order = 0; order <= degree; order++) {
|
|
1580
1581
|
if (order > 0) factorial *= BigInt(order);
|
|
1581
1582
|
const derivative = differentiate(node, variable, order);
|
|
1582
|
-
const atPoint =
|
|
1583
|
+
const atPoint = chunk4CVLFLOB_cjs.simplifySymbolic(chunk4CVLFLOB_cjs.substitute(derivative, variable, pointNode));
|
|
1583
1584
|
if (atPoint.kind !== "const") {
|
|
1584
1585
|
throw chunkM4N5GA5Z_cjs.ErrorFactory.execution(
|
|
1585
1586
|
"SYMBOLIC_TAYLOR_INEXACT",
|
|
@@ -1587,13 +1588,13 @@ function taylorSeries(node, variable, point, degree) {
|
|
|
1587
1588
|
{ order }
|
|
1588
1589
|
);
|
|
1589
1590
|
}
|
|
1590
|
-
const coefficient =
|
|
1591
|
-
if (
|
|
1592
|
-
const shifted =
|
|
1593
|
-
const power2 = order === 0 ?
|
|
1594
|
-
result = { kind: "add", left: result, right: { kind: "mul", left:
|
|
1591
|
+
const coefficient = chunk4CVLFLOB_cjs.rationalDiv(atPoint.value, { n: factorial, d: 1n });
|
|
1592
|
+
if (chunk4CVLFLOB_cjs.isRationalZero(coefficient)) continue;
|
|
1593
|
+
const shifted = chunk4CVLFLOB_cjs.isRationalZero(point) ? chunk4CVLFLOB_cjs.varNode(variable) : { kind: "sub", left: chunk4CVLFLOB_cjs.varNode(variable), right: pointNode };
|
|
1594
|
+
const power2 = order === 0 ? chunk4CVLFLOB_cjs.constNode(1) : order === 1 ? shifted : chunk4CVLFLOB_cjs.powNode(shifted, chunk4CVLFLOB_cjs.constNode(order));
|
|
1595
|
+
result = { kind: "add", left: result, right: { kind: "mul", left: chunk4CVLFLOB_cjs.constNode(coefficient), right: power2 } };
|
|
1595
1596
|
}
|
|
1596
|
-
return
|
|
1597
|
+
return chunk4CVLFLOB_cjs.simplifySymbolic(result);
|
|
1597
1598
|
}
|
|
1598
1599
|
function jacobian(functions, variables) {
|
|
1599
1600
|
return functions.map((fn) => variables.map((variable) => differentiate(fn, variable)));
|
|
@@ -1689,6 +1690,19 @@ function adjustForInflation(amount, fromYear, toYear) {
|
|
|
1689
1690
|
}
|
|
1690
1691
|
|
|
1691
1692
|
// src/vm/VMBuiltins.ts
|
|
1693
|
+
var ANGLE_KIND = 0;
|
|
1694
|
+
function angleInRadians(value) {
|
|
1695
|
+
if (value.type === 6 /* Uom */ && value.unit !== void 0) {
|
|
1696
|
+
const entry = chunkMBNQVDVC_cjs.UNIT_TABLE[value.unit.toLowerCase()];
|
|
1697
|
+
if (entry !== void 0 && entry[0] === ANGLE_KIND) return value.toNumber() * entry[1];
|
|
1698
|
+
}
|
|
1699
|
+
return value.toNumber();
|
|
1700
|
+
}
|
|
1701
|
+
function pluraliseUnit(unit, count) {
|
|
1702
|
+
if (count === 1) return unit;
|
|
1703
|
+
const plural = `${unit}s`;
|
|
1704
|
+
return chunkMBNQVDVC_cjs.UNIT_TABLE[plural.toLowerCase()] === void 0 ? unit : plural;
|
|
1705
|
+
}
|
|
1692
1706
|
var builtinFunctions = {
|
|
1693
1707
|
// ── Populated below ──
|
|
1694
1708
|
// sqrt: a negative argument has a complex answer now that there is a complex
|
|
@@ -1697,15 +1711,16 @@ var builtinFunctions = {
|
|
|
1697
1711
|
0: (args) => {
|
|
1698
1712
|
const value = args[0].toNumber();
|
|
1699
1713
|
if (value >= 0) return chunkOC6LTXYS_cjs.numberValue(Math.sqrt(value));
|
|
1700
|
-
return symbolicToValue(
|
|
1714
|
+
return symbolicToValue(chunk4CVLFLOB_cjs.callNode("sqrt", [chunk4CVLFLOB_cjs.constNode(value)]));
|
|
1701
1715
|
},
|
|
1702
1716
|
// abs(a): for a Matrix, "|a|" (Calca's determinant-pipe notation) is a
|
|
1703
1717
|
// valid alias for det(a) (index 64), reusing the SAME implementation
|
|
1704
1718
|
// not a separate one. Plain-number abs is unaffected.
|
|
1705
|
-
1: (args) => args[0].type === 7 /* Matrix */ ?
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1719
|
+
1: (args) => args[0].type === 7 /* Matrix */ ? chunk4CVLFLOB_cjs.determinant(args[0].value) : chunkOC6LTXYS_cjs.numberValue(Math.abs(args[0].toNumber())),
|
|
1720
|
+
// sin/cos/tan accept an angle with a unit; see angleInRadians().
|
|
1721
|
+
2: (args) => chunkOC6LTXYS_cjs.numberValue(Math.sin(angleInRadians(args[0]))),
|
|
1722
|
+
3: (args) => chunkOC6LTXYS_cjs.numberValue(Math.cos(angleInRadians(args[0]))),
|
|
1723
|
+
4: (args) => chunkOC6LTXYS_cjs.numberValue(Math.tan(angleInRadians(args[0]))),
|
|
1709
1724
|
5: (args) => chunkOC6LTXYS_cjs.numberValue(Math.log(args[0].toNumber())),
|
|
1710
1725
|
6: (args) => chunkOC6LTXYS_cjs.numberValue(Math.ceil(args[0].toNumber())),
|
|
1711
1726
|
7: (args) => chunkOC6LTXYS_cjs.numberValue(Math.floor(args[0].toNumber())),
|
|
@@ -2019,11 +2034,13 @@ var builtinFunctions = {
|
|
|
2019
2034
|
const { monthlyPayment } = amortizeLoan(principal, rate, years);
|
|
2020
2035
|
return args[0].type === 6 /* Uom */ ? chunkOC6LTXYS_cjs.uomValue(monthlyPayment, args[0].unit) : chunkOC6LTXYS_cjs.numberValue(monthlyPayment);
|
|
2021
2036
|
},
|
|
2022
|
-
// taxAdd(amount, rate) -> amount * (1 + rate)
|
|
2023
|
-
//
|
|
2024
|
-
//
|
|
2025
|
-
//
|
|
2026
|
-
//
|
|
2037
|
+
// taxAdd(amount, rate) -> amount * (1 + rate), the tax-inclusive total.
|
|
2038
|
+
// Backs the taxAdd() function-call form, whose name promises exactly this.
|
|
2039
|
+
// The "tax on $X at R%" PHRASE does NOT use it, see index 86.
|
|
2040
|
+
//
|
|
2041
|
+
// No default rate is baked in anywhere, the caller always supplies one
|
|
2042
|
+
// explicitly, since tax rates vary by region and change over time; this
|
|
2043
|
+
// package makes no assumption about which rate applies.
|
|
2027
2044
|
58: (args) => {
|
|
2028
2045
|
const amount = args[0].toNumber();
|
|
2029
2046
|
const rate = args[1].toNumber();
|
|
@@ -2107,16 +2124,16 @@ var builtinFunctions = {
|
|
|
2107
2124
|
// own transpose (a 1x1 "matrix" transposed is itself), matches this
|
|
2108
2125
|
// engine's existing convention of treating a scalar as a trivial 1x1
|
|
2109
2126
|
// matrix (see Value.ts's toNumber()/isNaN() 1x1 special case).
|
|
2110
|
-
63: (args) => args[0].type === 7 /* Matrix */ ?
|
|
2127
|
+
63: (args) => args[0].type === 7 /* Matrix */ ? chunk4CVLFLOB_cjs.transpose(args[0].value) : args[0],
|
|
2111
2128
|
// det(a), determinant. A plain Number's "determinant" is itself (the
|
|
2112
2129
|
// determinant of a 1x1 matrix [x] is x).
|
|
2113
|
-
64: (args) => args[0].type === 7 /* Matrix */ ?
|
|
2130
|
+
64: (args) => args[0].type === 7 /* Matrix */ ? chunk4CVLFLOB_cjs.determinant(args[0].value) : chunkOC6LTXYS_cjs.numberValue(args[0].toNumber()),
|
|
2114
2131
|
// inv(a), matrix inverse for a Matrix; for a plain Number, `1/x`
|
|
2115
2132
|
// (byte-identical to `Math.pow(x, -1)`, which is what `x^-1` computed
|
|
2116
2133
|
// before this feature existed. See PrecedenceParser.ts's `^-1`
|
|
2117
2134
|
// special-case doc comment for why this must stay exact).
|
|
2118
2135
|
65: (args) => {
|
|
2119
|
-
if (args[0].type === 7 /* Matrix */) return
|
|
2136
|
+
if (args[0].type === 7 /* Matrix */) return chunk4CVLFLOB_cjs.inverse(args[0].value);
|
|
2120
2137
|
return chunkOC6LTXYS_cjs.numberValue(1 / args[0].toNumber());
|
|
2121
2138
|
},
|
|
2122
2139
|
// dot(a, b), matrix product / scalar-broadcast, the SAME dispatch as
|
|
@@ -2130,7 +2147,7 @@ var builtinFunctions = {
|
|
|
2130
2147
|
return chunkOC6LTXYS_cjs.numberValue(a.toNumber() * b.toNumber());
|
|
2131
2148
|
}
|
|
2132
2149
|
const toMatrix = (v) => v.type === 7 /* Matrix */ ? v.value : { rows: 1, cols: 1, data: [v.toNumber()], hasSymbolic: false };
|
|
2133
|
-
return
|
|
2150
|
+
return chunk4CVLFLOB_cjs.matrixMultiply(toMatrix(a), toMatrix(b));
|
|
2134
2151
|
},
|
|
2135
2152
|
// ── Symbolic algebra (packages/symbolic/) ──
|
|
2136
2153
|
// expand(expr), multiplying out every product and power. Reached only
|
|
@@ -2144,7 +2161,7 @@ var builtinFunctions = {
|
|
|
2144
2161
|
67: (args) => {
|
|
2145
2162
|
const [value] = args;
|
|
2146
2163
|
if (value.type !== 9 /* Symbolic */) return value;
|
|
2147
|
-
return symbolicToValue(
|
|
2164
|
+
return symbolicToValue(chunk4CVLFLOB_cjs.expandSymbolic(value.value));
|
|
2148
2165
|
},
|
|
2149
2166
|
// factor(expr), writing a polynomial as a product of irreducible factors
|
|
2150
2167
|
// over the RATIONALS. x^2-2 and x^2+1 come back unchanged, which is the
|
|
@@ -2210,19 +2227,19 @@ var builtinFunctions = {
|
|
|
2210
2227
|
functions.push(node);
|
|
2211
2228
|
}
|
|
2212
2229
|
const variables = /* @__PURE__ */ new Set();
|
|
2213
|
-
for (const fn of functions) for (const name of
|
|
2230
|
+
for (const fn of functions) for (const name of chunk4CVLFLOB_cjs.freeVariables(fn)) variables.add(name);
|
|
2214
2231
|
const sorted = [...variables].sort();
|
|
2215
2232
|
if (sorted.length === 0) return chunkOC6LTXYS_cjs.errorValue("SYMBOLIC_JACOBIAN_NO_VARIABLES", "jacobian needs at least one unknown to differentiate against.");
|
|
2216
2233
|
const rows = jacobian(functions, sorted);
|
|
2217
2234
|
const rowMajor = [];
|
|
2218
2235
|
for (const row of rows) {
|
|
2219
|
-
for (const cell of row) rowMajor.push(
|
|
2236
|
+
for (const cell of row) rowMajor.push(chunk4CVLFLOB_cjs.symbolicToEntry(cell));
|
|
2220
2237
|
}
|
|
2221
|
-
return chunkOC6LTXYS_cjs.matrixValue(rows.length, sorted.length,
|
|
2238
|
+
return chunkOC6LTXYS_cjs.matrixValue(rows.length, sorted.length, chunk4CVLFLOB_cjs.rowMajorToColumnMajor(rows.length, sorted.length, rowMajor));
|
|
2222
2239
|
},
|
|
2223
2240
|
// An imaginary literal, 3i. The parselet pushes the numeric part and this
|
|
2224
2241
|
// turns it into an exact imaginary value.
|
|
2225
|
-
74: (args) => symbolicToValue(
|
|
2242
|
+
74: (args) => symbolicToValue(chunk4CVLFLOB_cjs.complexNode(chunk4CVLFLOB_cjs.complex(chunk4CVLFLOB_cjs.RATIONAL_ZERO, chunk4CVLFLOB_cjs.rationalFromNumber(args[0].toNumber())))),
|
|
2226
2243
|
// conj(z), re(z) and im(z). Each folds immediately for a literal and stays
|
|
2227
2244
|
// symbolic for anything still carrying an unknown.
|
|
2228
2245
|
75: (args) => applyComplexAccessor("conj", args[0]),
|
|
@@ -2232,19 +2249,219 @@ var builtinFunctions = {
|
|
|
2232
2249
|
78: (args) => {
|
|
2233
2250
|
const value = args[0];
|
|
2234
2251
|
if (value.type !== 9 /* Symbolic */) return value;
|
|
2235
|
-
return symbolicToValue(
|
|
2252
|
+
return symbolicToValue(chunk4CVLFLOB_cjs.cancelSymbolic(value.value));
|
|
2236
2253
|
},
|
|
2237
2254
|
// apart(expr), the partial-fraction decomposition of a rational function.
|
|
2238
2255
|
79: (args) => {
|
|
2239
2256
|
const value = args[0];
|
|
2240
2257
|
if (value.type !== 9 /* Symbolic */) return value;
|
|
2241
2258
|
return symbolicToValue(apartSymbolic(value.value));
|
|
2259
|
+
},
|
|
2260
|
+
// taxIn(amount, rate) -> amount - amount/(1 + rate), the tax already
|
|
2261
|
+
// contained in a tax-INCLUSIVE total. Backs "tax in/of/from $X at R%".
|
|
2262
|
+
// The complement of taxRemove (index 59): the two sum to the gross amount.
|
|
2263
|
+
85: (args) => {
|
|
2264
|
+
const amount = args[0].toNumber();
|
|
2265
|
+
const rate = args[1].toNumber();
|
|
2266
|
+
if (1 + rate <= 0) {
|
|
2267
|
+
return chunkOC6LTXYS_cjs.errorValue("INVALID_RATE", `taxIn: rate ${rate} makes (1 + rate) non-positive`);
|
|
2268
|
+
}
|
|
2269
|
+
const tax = amount - amount / (1 + rate);
|
|
2270
|
+
return args[0].type === 6 /* Uom */ ? chunkOC6LTXYS_cjs.uomValue(tax, args[0].unit) : chunkOC6LTXYS_cjs.numberValue(tax);
|
|
2271
|
+
},
|
|
2272
|
+
// taxOn(amount, rate) -> amount * rate, the tax itself.
|
|
2273
|
+
//
|
|
2274
|
+
// The "tax on $X at R%" phrase used to compile to taxAdd (index 58) and
|
|
2275
|
+
// answer $345.00 for "tax on $300 at 15%". Soulver answers $45.00, and
|
|
2276
|
+
// "the tax on $300" is the tax, not the bill. The total is "$300 + 15%",
|
|
2277
|
+
// which reads as a relative increase (see PercentParselet.ts), or
|
|
2278
|
+
// taxAdd(300, 0.15) for the function form.
|
|
2279
|
+
86: (args) => {
|
|
2280
|
+
const amount = args[0].toNumber();
|
|
2281
|
+
const rate = args[1].toNumber();
|
|
2282
|
+
const tax = amount * rate;
|
|
2283
|
+
return args[0].type === 6 /* Uom */ ? chunkOC6LTXYS_cjs.uomValue(tax, args[0].unit) : chunkOC6LTXYS_cjs.numberValue(tax);
|
|
2284
|
+
},
|
|
2285
|
+
// ── Degree-taking trig (sind/cosd/tand and the inverses) ──────────────
|
|
2286
|
+
// The "d" spellings take and return degrees rather than radians, which is
|
|
2287
|
+
// the convention every scientific calculator uses. sin(90 degrees) is the
|
|
2288
|
+
// other way to say the same thing; both exist because both get typed.
|
|
2289
|
+
87: (args) => chunkOC6LTXYS_cjs.numberValue(Math.sin(args[0].toNumber() * Math.PI / 180)),
|
|
2290
|
+
88: (args) => chunkOC6LTXYS_cjs.numberValue(Math.cos(args[0].toNumber() * Math.PI / 180)),
|
|
2291
|
+
89: (args) => chunkOC6LTXYS_cjs.numberValue(Math.tan(args[0].toNumber() * Math.PI / 180)),
|
|
2292
|
+
90: (args) => chunkOC6LTXYS_cjs.numberValue(Math.asin(args[0].toNumber()) * 180 / Math.PI),
|
|
2293
|
+
91: (args) => chunkOC6LTXYS_cjs.numberValue(Math.acos(args[0].toNumber()) * 180 / Math.PI),
|
|
2294
|
+
92: (args) => chunkOC6LTXYS_cjs.numberValue(Math.atan(args[0].toNumber()) * 180 / Math.PI),
|
|
2295
|
+
// daysCount(n) -> n labelled as days. "days in Q3" is a count of days
|
|
2296
|
+
// and should say so; a bare 92 loses what was being counted.
|
|
2297
|
+
93: (args) => chunkOC6LTXYS_cjs.uomValue(args[0].toNumber(), "days"),
|
|
2298
|
+
// asTwoUnits(value, majorUnit, minorUnit) -> "12 min 30 s".
|
|
2299
|
+
//
|
|
2300
|
+
// "12.5 minutes in minutes and seconds" asks for one quantity split
|
|
2301
|
+
// across two units, which every other conversion path cannot express:
|
|
2302
|
+
// they each produce a single number in a single unit.
|
|
2303
|
+
//
|
|
2304
|
+
// The whole part goes to the major unit and the remainder to the minor,
|
|
2305
|
+
// so nothing is lost. A pair that is not ordered major-then-minor, or
|
|
2306
|
+
// that spans two different measures, reports rather than guessing.
|
|
2307
|
+
94: (args) => {
|
|
2308
|
+
const major = args[1].value;
|
|
2309
|
+
const minor = args[2].value;
|
|
2310
|
+
const majorEntry = chunkMBNQVDVC_cjs.UNIT_TABLE[major.toLowerCase()];
|
|
2311
|
+
const minorEntry = chunkMBNQVDVC_cjs.UNIT_TABLE[minor.toLowerCase()];
|
|
2312
|
+
if (majorEntry === void 0 || minorEntry === void 0) {
|
|
2313
|
+
return chunkOC6LTXYS_cjs.errorValue("UNKNOWN_UNIT", `${major} and ${minor}: one of these is not a unit`);
|
|
2314
|
+
}
|
|
2315
|
+
if (majorEntry[0] !== minorEntry[0]) {
|
|
2316
|
+
return chunkOC6LTXYS_cjs.errorValue("INCOMPATIBLE_UNITS", `${major} and ${minor} measure different things`);
|
|
2317
|
+
}
|
|
2318
|
+
if (minorEntry[1] >= majorEntry[1]) {
|
|
2319
|
+
return chunkOC6LTXYS_cjs.errorValue("INCOMPATIBLE_UNITS", `${major} and ${minor}: name the larger unit first`);
|
|
2320
|
+
}
|
|
2321
|
+
const source = args[0];
|
|
2322
|
+
const sourceEntry = source.type === 6 /* Uom */ && source.unit !== void 0 ? chunkMBNQVDVC_cjs.UNIT_TABLE[source.unit.toLowerCase()] : void 0;
|
|
2323
|
+
const inBase = source.toNumber() * (sourceEntry?.[1] ?? majorEntry[1]);
|
|
2324
|
+
const majorCount = Math.floor(inBase / majorEntry[1]);
|
|
2325
|
+
const minorCount = Math.round((inBase - majorCount * majorEntry[1]) / minorEntry[1] * 1e3) / 1e3;
|
|
2326
|
+
return chunkOC6LTXYS_cjs.stringValue(`${majorCount} ${major} ${minorCount} ${minor}`);
|
|
2327
|
+
},
|
|
2328
|
+
// makeRate(value, denominatorUnit) -> value per that unit.
|
|
2329
|
+
//
|
|
2330
|
+
// `3 hours / day` is a rate, `3 hours / 3 days` is a division. The
|
|
2331
|
+
// difference is whether a number was written in the denominator, which
|
|
2332
|
+
// is decided at parse time, so this only ever receives the rate case.
|
|
2333
|
+
//
|
|
2334
|
+
// Building the rate directly rather than dividing by an implied 1 is the
|
|
2335
|
+
// whole point: a division makes same-measure units cancel, which turned
|
|
2336
|
+
// `3 hours / day` into 0.125 when that shortcut was tried.
|
|
2337
|
+
95: (args) => {
|
|
2338
|
+
const source = args[0];
|
|
2339
|
+
const denominator = String(args[1].value);
|
|
2340
|
+
const numerator = source.type === 6 /* Uom */ && source.unit !== void 0 ? source.unit : "";
|
|
2341
|
+
if (numerator.includes("/")) {
|
|
2342
|
+
return chunkOC6LTXYS_cjs.errorValue("INVALID_RATE_UNIT", `${numerator}/${denominator}: that is already a rate`);
|
|
2343
|
+
}
|
|
2344
|
+
return chunkOC6LTXYS_cjs.uomValue(source.toNumber(), `${numerator}/${denominator}`);
|
|
2345
|
+
},
|
|
2346
|
+
// atRate(quantity, rate) -> whichever of the two the question implies.
|
|
2347
|
+
//
|
|
2348
|
+
// 30 hours at $30/hour $900 a duration at a price per duration
|
|
2349
|
+
// $500 at $20/hour 25 hours money at a price per duration
|
|
2350
|
+
//
|
|
2351
|
+
// Both are written with the same word and mean opposite operations. Which
|
|
2352
|
+
// one applies is decided by which half of the rate the left side matches:
|
|
2353
|
+
// match the denominator and you are buying that many, match the numerator
|
|
2354
|
+
// and you are asking how many it buys.
|
|
2355
|
+
96: (args) => {
|
|
2356
|
+
const left = args[0];
|
|
2357
|
+
const rate = args[1];
|
|
2358
|
+
if (rate.type !== 6 /* Uom */ || rate.unit === void 0 || !rate.unit.includes("/")) {
|
|
2359
|
+
return chunkOC6LTXYS_cjs.errorValue("INVALID_RATE", 'at: the right-hand side has to be a rate, as in "$30/hour"');
|
|
2360
|
+
}
|
|
2361
|
+
const slash = rate.unit.indexOf("/");
|
|
2362
|
+
const numerator = rate.unit.slice(0, slash);
|
|
2363
|
+
const denominator = rate.unit.slice(slash + 1);
|
|
2364
|
+
const leftUnit = left.type === 6 /* Uom */ ? left.unit : void 0;
|
|
2365
|
+
const denominatorEntry = chunkMBNQVDVC_cjs.UNIT_TABLE[denominator.toLowerCase()];
|
|
2366
|
+
const leftEntry = leftUnit === void 0 ? void 0 : chunkMBNQVDVC_cjs.UNIT_TABLE[leftUnit.toLowerCase()];
|
|
2367
|
+
if (leftEntry !== void 0 && denominatorEntry !== void 0 && leftEntry[0] === denominatorEntry[0]) {
|
|
2368
|
+
const inDenominator = left.toNumber() * leftEntry[1] / denominatorEntry[1];
|
|
2369
|
+
const total = inDenominator * rate.toNumber();
|
|
2370
|
+
return numerator === "" ? chunkOC6LTXYS_cjs.numberValue(total) : chunkOC6LTXYS_cjs.uomValue(total, numerator);
|
|
2371
|
+
}
|
|
2372
|
+
if (leftUnit !== void 0 && leftUnit === numerator) {
|
|
2373
|
+
const count = left.toNumber() / rate.toNumber();
|
|
2374
|
+
return chunkOC6LTXYS_cjs.uomValue(count, pluraliseUnit(denominator, count));
|
|
2375
|
+
}
|
|
2376
|
+
if (leftUnit === void 0) {
|
|
2377
|
+
const total = left.toNumber() * rate.toNumber();
|
|
2378
|
+
return numerator === "" ? chunkOC6LTXYS_cjs.numberValue(total) : chunkOC6LTXYS_cjs.uomValue(total, numerator);
|
|
2379
|
+
}
|
|
2380
|
+
return chunkOC6LTXYS_cjs.errorValue("INCOMPATIBLE_UNITS", `at: ${leftUnit} matches neither side of ${rate.unit}`);
|
|
2381
|
+
},
|
|
2382
|
+
// ── Investments (packages/finance/) ────────────────────────────────────
|
|
2383
|
+
// compoundFutureValueEvery(principal, rate, years, periodsPerYear)
|
|
2384
|
+
// FV = P(1 + r/n)^(n·y). Index 51 is the same formula with n fixed at 1;
|
|
2385
|
+
// this one backs "compounding monthly"/"quarterly"/"daily"/"weekly".
|
|
2386
|
+
// Kept separate rather than widening 51, because 51 is also the public
|
|
2387
|
+
// compoundInterest(principal, rate, years) call and its arity is part of
|
|
2388
|
+
// that contract.
|
|
2389
|
+
80: (args) => {
|
|
2390
|
+
const principal = args[0].toNumber();
|
|
2391
|
+
const rate = args[1].toNumber();
|
|
2392
|
+
const years = args[2].toNumber();
|
|
2393
|
+
const perYear = args[3].toNumber();
|
|
2394
|
+
if (perYear <= 0) {
|
|
2395
|
+
return chunkOC6LTXYS_cjs.errorValue("INVALID_RATE", `compounding: ${perYear} periods per year is not a period`);
|
|
2396
|
+
}
|
|
2397
|
+
if (1 + rate / perYear <= 0) {
|
|
2398
|
+
return chunkOC6LTXYS_cjs.errorValue("INVALID_RATE", `compounding: rate ${rate} makes each period non-positive`);
|
|
2399
|
+
}
|
|
2400
|
+
const fv = principal * Math.pow(1 + rate / perYear, perYear * years);
|
|
2401
|
+
return args[0].type === 6 /* Uom */ ? chunkOC6LTXYS_cjs.uomValue(fv, args[0].unit) : chunkOC6LTXYS_cjs.numberValue(fv);
|
|
2402
|
+
},
|
|
2403
|
+
// compoundInterestEarnedEvery(principal, rate, years, periodsPerYear)
|
|
2404
|
+
// The interest-only portion of index 80, i.e. FV - P.
|
|
2405
|
+
81: (args) => {
|
|
2406
|
+
const principal = args[0].toNumber();
|
|
2407
|
+
const rate = args[1].toNumber();
|
|
2408
|
+
const years = args[2].toNumber();
|
|
2409
|
+
const perYear = args[3].toNumber();
|
|
2410
|
+
if (perYear <= 0 || 1 + rate / perYear <= 0) {
|
|
2411
|
+
return chunkOC6LTXYS_cjs.errorValue("INVALID_RATE", `compounding: rate ${rate} over ${perYear} periods per year is not usable`);
|
|
2412
|
+
}
|
|
2413
|
+
const interest = principal * (Math.pow(1 + rate / perYear, perYear * years) - 1);
|
|
2414
|
+
return args[0].type === 6 /* Uom */ ? chunkOC6LTXYS_cjs.uomValue(interest, args[0].unit) : chunkOC6LTXYS_cjs.numberValue(interest);
|
|
2415
|
+
},
|
|
2416
|
+
// presentValue(futureValue, rate, years) -> FV / (1 + r)^y, what a sum
|
|
2417
|
+
// promised in the future is worth today. The inverse of index 51.
|
|
2418
|
+
82: (args) => {
|
|
2419
|
+
const future = args[0].toNumber();
|
|
2420
|
+
const rate = args[1].toNumber();
|
|
2421
|
+
const years = args[2].toNumber();
|
|
2422
|
+
if (1 + rate <= 0) {
|
|
2423
|
+
return chunkOC6LTXYS_cjs.errorValue("INVALID_RATE", `presentValue: rate ${rate} makes (1 + rate) non-positive`);
|
|
2424
|
+
}
|
|
2425
|
+
const pv = future / Math.pow(1 + rate, years);
|
|
2426
|
+
return args[0].type === 6 /* Uom */ ? chunkOC6LTXYS_cjs.uomValue(pv, args[0].unit) : chunkOC6LTXYS_cjs.numberValue(pv);
|
|
2427
|
+
},
|
|
2428
|
+
// returnOnInvestment(invested, returned) -> (returned - invested) /
|
|
2429
|
+
// invested, the gain as a multiple of what was put in. $500 in and $1,500
|
|
2430
|
+
// out is 2x, not 3x: ROI conventionally measures the profit against the
|
|
2431
|
+
// cost, so doubling your money is 1x return and tripling it is 2x. The
|
|
2432
|
+
// money multiple (3x here) is a different figure; `$1,500 / $500` gives it.
|
|
2433
|
+
83: (args) => {
|
|
2434
|
+
const invested = args[0].toNumber();
|
|
2435
|
+
const returned = args[1].toNumber();
|
|
2436
|
+
if (invested === 0) {
|
|
2437
|
+
return chunkOC6LTXYS_cjs.errorValue("INVALID_RATE", "roi: nothing was invested, so there is no return on it");
|
|
2438
|
+
}
|
|
2439
|
+
return chunkOC6LTXYS_cjs.numberValue((returned - invested) / invested);
|
|
2440
|
+
},
|
|
2441
|
+
// annualisedReturn(invested, returned, years) -> CAGR, the constant
|
|
2442
|
+
// yearly rate that turns `invested` into `returned` over `years`:
|
|
2443
|
+
// (returned/invested)^(1/years) - 1. Returned as a Percentage so it
|
|
2444
|
+
// renders "13.99%" rather than 0.1399.
|
|
2445
|
+
84: (args) => {
|
|
2446
|
+
const invested = args[0].toNumber();
|
|
2447
|
+
const returned = args[1].toNumber();
|
|
2448
|
+
const years = args[2].toNumber();
|
|
2449
|
+
if (invested <= 0) {
|
|
2450
|
+
return chunkOC6LTXYS_cjs.errorValue("INVALID_RATE", "annual return: the amount invested must be positive");
|
|
2451
|
+
}
|
|
2452
|
+
if (years <= 0) {
|
|
2453
|
+
return chunkOC6LTXYS_cjs.errorValue("INVALID_RATE", "annual return: the period must be longer than zero");
|
|
2454
|
+
}
|
|
2455
|
+
if (returned <= 0) {
|
|
2456
|
+
return chunkOC6LTXYS_cjs.errorValue("INVALID_RATE", "annual return: nothing was returned, so there is no annual rate");
|
|
2457
|
+
}
|
|
2458
|
+
return chunkOC6LTXYS_cjs.percentageValue(Math.pow(returned / invested, 1 / years) - 1);
|
|
2242
2459
|
}
|
|
2243
2460
|
};
|
|
2244
2461
|
function applyComplexAccessor(name, value) {
|
|
2245
2462
|
const node = valueToSymbolic(value);
|
|
2246
2463
|
if (node === null) return chunkOC6LTXYS_cjs.errorValue("SYMBOLIC_NONFINITE_OPERAND", name + " needs a value with an exact number.");
|
|
2247
|
-
return symbolicToValue(
|
|
2464
|
+
return symbolicToValue(chunk4CVLFLOB_cjs.callNode(name, [node]));
|
|
2248
2465
|
}
|
|
2249
2466
|
function symbolicVariableName(value, verb) {
|
|
2250
2467
|
if (value?.type !== 3 /* String */) {
|
|
@@ -2411,5 +2628,5 @@ exports.symbolicNeg = symbolicNeg;
|
|
|
2411
2628
|
exports.symbolicPow = symbolicPow;
|
|
2412
2629
|
exports.unifyUom = unifyUom;
|
|
2413
2630
|
exports.unregisterAsConverter = unregisterAsConverter;
|
|
2414
|
-
//# sourceMappingURL=chunk-
|
|
2415
|
-
//# sourceMappingURL=chunk-
|
|
2631
|
+
//# sourceMappingURL=chunk-2NPS5DQ3.cjs.map
|
|
2632
|
+
//# sourceMappingURL=chunk-2NPS5DQ3.cjs.map
|