solve-engine 1.0.0-beta.7 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{BytecodeBuilder-3egMyuDi.d.cts → BytecodeBuilder-B0xskcv5.d.cts} +2 -1
- package/dist/{BytecodeBuilder-3egMyuDi.d.ts → BytecodeBuilder-B0xskcv5.d.ts} +2 -1
- package/dist/{Configuration-fVpd-HC-.d.cts → Configuration-B-G5gTRn.d.cts} +107 -29
- package/dist/{Configuration-fVpd-HC-.d.ts → Configuration-B-G5gTRn.d.ts} +107 -29
- package/dist/{EngineError-DvPSnhZi.d.cts → EngineError-LU7W7AgI.d.cts} +96 -16
- package/dist/{EngineError-DvPSnhZi.d.ts → EngineError-LU7W7AgI.d.ts} +96 -16
- package/dist/{Lexer-W9MBOP0V.d.ts → Lexer-BN5mt30n.d.ts} +16 -0
- package/dist/{Lexer-Cfm79Dak.d.cts → Lexer-D78E2yDW.d.cts} +16 -0
- package/dist/{PackageRegistry-CjDt-Jy_.d.ts → PackageRegistry-DFeINv2O.d.ts} +54 -13
- package/dist/{PackageRegistry-pHtKythi.d.cts → PackageRegistry-u2zdfFaj.d.cts} +54 -13
- package/dist/{Parselet-DEdF9I7n.d.ts → Parselet-BaySkMV3.d.ts} +37 -5
- package/dist/{Parselet-Cu0bLSis.d.cts → Parselet-DuI1Pjiq.d.cts} +37 -5
- package/dist/{ScopeManager-CKfQtl7l.d.cts → ScopeManager-B6GzdhVG.d.cts} +75 -6
- package/dist/{ScopeManager-B5k0nk05.d.ts → ScopeManager-udv4Twwq.d.ts} +75 -6
- package/dist/{VMCheckpoints-BmDwIXgK.d.ts → VMCheckpoints-BiaIlOOY.d.ts} +4 -4
- package/dist/{VMCheckpoints-CqFuLwrT.d.cts → VMCheckpoints-DwLjivM7.d.cts} +4 -4
- package/dist/{Value-KtAQNHur.d.cts → Value-CXJqDH9J.d.cts} +5 -2
- package/dist/{Value-KtAQNHur.d.ts → Value-CXJqDH9J.d.ts} +5 -2
- package/dist/{chunk-CSG5XVNJ.cjs → chunk-3AFRJYP4.cjs} +556 -414
- package/dist/chunk-3AFRJYP4.cjs.map +1 -0
- package/dist/chunk-3BOK2LDK.js +17 -0
- package/dist/chunk-3BOK2LDK.js.map +1 -0
- package/dist/{chunk-6RDSQURE.js → chunk-3D7V24DG.js} +57 -6
- package/dist/chunk-3D7V24DG.js.map +1 -0
- package/dist/{chunk-MEOHSQEH.js → chunk-3LAEG75D.js} +47 -15
- package/dist/chunk-3LAEG75D.js.map +1 -0
- package/dist/{chunk-P75775WC.js → chunk-3VNGREMU.js} +118 -41
- package/dist/chunk-3VNGREMU.js.map +1 -0
- package/dist/{chunk-4AVD7NZW.cjs → chunk-4B2CNWQU.cjs} +13 -7
- package/dist/chunk-4B2CNWQU.cjs.map +1 -0
- package/dist/{chunk-6GCKCWLB.js → chunk-526PMQOA.js} +126 -69
- package/dist/chunk-526PMQOA.js.map +1 -0
- package/dist/{chunk-2CS6OMZK.js → chunk-5F4C26RU.js} +8 -5
- package/dist/chunk-5F4C26RU.js.map +1 -0
- package/dist/{chunk-M4N5GA5Z.cjs → chunk-5KMIY374.cjs} +57 -6
- package/dist/chunk-5KMIY374.cjs.map +1 -0
- package/dist/{chunk-R24DI24X.cjs → chunk-5LI5EPGJ.cjs} +6 -5
- package/dist/chunk-5LI5EPGJ.cjs.map +1 -0
- package/dist/{chunk-BAMZT3GL.js → chunk-5WVP4YHP.js} +939 -134
- package/dist/chunk-5WVP4YHP.js.map +1 -0
- package/dist/{chunk-MZOVP3WI.cjs → chunk-6KFYJ6TD.cjs} +3 -2
- package/dist/chunk-6KFYJ6TD.cjs.map +1 -0
- package/dist/{chunk-BXKJLM5R.cjs → chunk-6WFMPTGB.cjs} +972 -636
- package/dist/chunk-6WFMPTGB.cjs.map +1 -0
- package/dist/{chunk-2MV4HBKC.cjs → chunk-A2N2GFCG.cjs} +10 -10
- package/dist/{chunk-2MV4HBKC.cjs.map → chunk-A2N2GFCG.cjs.map} +1 -1
- package/dist/chunk-ADBA3XBE.cjs +20 -0
- package/dist/chunk-ADBA3XBE.cjs.map +1 -0
- package/dist/{chunk-MBNQVDVC.cjs → chunk-AMOJYLG2.cjs} +16 -10
- package/dist/chunk-AMOJYLG2.cjs.map +1 -0
- package/dist/{chunk-CLVQBF5C.cjs → chunk-AQNHHJMJ.cjs} +5 -5
- package/dist/{chunk-CLVQBF5C.cjs.map → chunk-AQNHHJMJ.cjs.map} +1 -1
- package/dist/{chunk-AHCLWAM5.cjs → chunk-BHTNFEGZ.cjs} +13 -13
- package/dist/chunk-BHTNFEGZ.cjs.map +1 -0
- package/dist/{chunk-35IWNZPJ.cjs → chunk-E4NUZXVK.cjs} +58 -27
- package/dist/chunk-E4NUZXVK.cjs.map +1 -0
- package/dist/{chunk-P33SBYGG.js → chunk-GLG5ZMX7.js} +54 -23
- package/dist/chunk-GLG5ZMX7.js.map +1 -0
- package/dist/{chunk-BVAR5J2F.js → chunk-GQCOSXMG.js} +117 -6
- package/dist/chunk-GQCOSXMG.js.map +1 -0
- package/dist/{chunk-QDMPOAI7.cjs → chunk-HDP7VK3C.cjs} +1118 -313
- package/dist/chunk-HDP7VK3C.cjs.map +1 -0
- package/dist/{chunk-GVWHCL2N.js → chunk-HMOISHXR.js} +217 -75
- package/dist/chunk-HMOISHXR.js.map +1 -0
- package/dist/{chunk-MTX2KVU7.cjs → chunk-HVQFNJKE.cjs} +122 -90
- package/dist/chunk-HVQFNJKE.cjs.map +1 -0
- package/dist/{chunk-OC6LTXYS.cjs → chunk-JMXUNXQS.cjs} +126 -7
- package/dist/chunk-JMXUNXQS.cjs.map +1 -0
- package/dist/{chunk-WWOLFXTX.cjs → chunk-KBSXGXPM.cjs} +10 -7
- package/dist/chunk-KBSXGXPM.cjs.map +1 -0
- package/dist/{chunk-YU2CUNFO.js → chunk-KV7UW6T6.js} +11 -5
- package/dist/chunk-KV7UW6T6.js.map +1 -0
- package/dist/{chunk-CCJPSHGI.cjs → chunk-N7FNVFXW.cjs} +4 -12
- package/dist/chunk-N7FNVFXW.cjs.map +1 -0
- package/dist/{chunk-CYFK5SY2.js → chunk-O3ANBHSA.js} +169 -39
- package/dist/chunk-O3ANBHSA.js.map +1 -0
- package/dist/{chunk-NZFKROS7.cjs → chunk-PA4VC73I.cjs} +130 -72
- package/dist/chunk-PA4VC73I.cjs.map +1 -0
- package/dist/{chunk-NJTXJ5AG.cjs → chunk-PFUESQTW.cjs} +18 -18
- package/dist/{chunk-NJTXJ5AG.cjs.map → chunk-PFUESQTW.cjs.map} +1 -1
- package/dist/{chunk-SFQWJMKT.js → chunk-QY25VWBF.js} +51 -12
- package/dist/chunk-QY25VWBF.js.map +1 -0
- package/dist/{chunk-WC5FFSHB.js → chunk-R3PY4G7J.js} +3 -3
- package/dist/{chunk-WC5FFSHB.js.map → chunk-R3PY4G7J.js.map} +1 -1
- package/dist/{chunk-M5E34VG5.js → chunk-SBUFNJVE.js} +3 -3
- package/dist/{chunk-M5E34VG5.js.map → chunk-SBUFNJVE.js.map} +1 -1
- package/dist/{chunk-UKPGSAZW.js → chunk-TMA4RCEN.js} +3 -3
- package/dist/{chunk-UKPGSAZW.js.map → chunk-TMA4RCEN.js.map} +1 -1
- package/dist/{chunk-V6HA6JJZ.cjs → chunk-U5VAY32K.cjs} +215 -138
- package/dist/chunk-U5VAY32K.cjs.map +1 -0
- package/dist/{chunk-DUEZFTK2.js → chunk-UKQHXPGW.js} +4 -12
- package/dist/chunk-UKQHXPGW.js.map +1 -0
- package/dist/{chunk-4CVLFLOB.cjs → chunk-UM6BVY2S.cjs} +201 -69
- package/dist/chunk-UM6BVY2S.cjs.map +1 -0
- package/dist/{chunk-75JP4BZX.js → chunk-UQ3UIZJC.js} +3 -2
- package/dist/chunk-UQ3UIZJC.js.map +1 -0
- package/dist/{chunk-PCPX42KL.js → chunk-V4XG5QF6.js} +16 -10
- package/dist/chunk-V4XG5QF6.js.map +1 -0
- package/dist/{chunk-GPPLSM2Z.js → chunk-VB37OC6I.js} +6 -5
- package/dist/chunk-VB37OC6I.js.map +1 -0
- package/dist/{chunk-MVBEL57Q.js → chunk-Y7FT4IQT.js} +500 -170
- package/dist/chunk-Y7FT4IQT.js.map +1 -0
- package/dist/{chunk-OFXOTECC.js → chunk-YPPPYLSR.js} +7 -7
- package/dist/chunk-YPPPYLSR.js.map +1 -0
- package/dist/{chunk-M4F66R4O.cjs → chunk-YWQ6V4ZN.cjs} +121 -82
- package/dist/chunk-YWQ6V4ZN.cjs.map +1 -0
- package/dist/constants.cjs +5 -5
- package/dist/constants.d.cts +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +2 -2
- package/dist/engine.cjs +31 -31
- package/dist/engine.d.cts +11 -11
- package/dist/engine.d.ts +11 -11
- package/dist/engine.js +21 -21
- package/dist/errors.cjs +19 -19
- package/dist/errors.d.cts +2 -2
- package/dist/errors.d.ts +2 -2
- package/dist/errors.js +1 -1
- package/dist/format.cjs +29 -22
- package/dist/format.cjs.map +1 -1
- package/dist/format.d.cts +1 -2
- package/dist/format.d.ts +1 -2
- package/dist/format.js +23 -16
- package/dist/format.js.map +1 -1
- package/dist/index.cjs +31 -31
- package/dist/index.d.cts +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.js +22 -22
- package/dist/language.cjs +8 -8
- package/dist/language.cjs.map +1 -1
- package/dist/language.d.cts +10 -10
- package/dist/language.d.ts +10 -10
- package/dist/language.js +6 -6
- package/dist/language.js.map +1 -1
- package/dist/lexer.cjs +18 -18
- package/dist/lexer.d.cts +2 -2
- package/dist/lexer.d.ts +2 -2
- package/dist/lexer.js +6 -6
- package/dist/normalizer.cjs +12 -12
- package/dist/normalizer.js +6 -6
- package/dist/packages.cjs +39 -39
- package/dist/packages.d.cts +9 -9
- package/dist/packages.d.ts +9 -9
- package/dist/packages.js +16 -16
- package/dist/parser.cjs +15 -15
- package/dist/parser.d.cts +23 -9
- package/dist/parser.d.ts +23 -9
- package/dist/parser.js +5 -5
- package/dist/{pipeline-CrsRPmsv.d.ts → pipeline-B6k5lCB7.d.ts} +1 -1
- package/dist/{pipeline-DPUQt7yL.d.cts → pipeline-BEb3hujr.d.cts} +1 -1
- package/dist/resolvers.d.cts +2 -2
- package/dist/resolvers.d.ts +2 -2
- package/dist/uom.cjs +17 -17
- package/dist/uom.d.cts +2 -2
- package/dist/uom.d.ts +2 -2
- package/dist/uom.js +7 -7
- package/dist/utilities.cjs +8 -4
- package/dist/utilities.d.cts +19 -3
- package/dist/utilities.d.ts +19 -3
- package/dist/utilities.js +2 -2
- package/dist/vm.cjs +43 -31
- package/dist/vm.d.cts +105 -9
- package/dist/vm.d.ts +105 -9
- package/dist/vm.js +9 -9
- package/package.json +1 -1
- package/dist/chunk-2CS6OMZK.js.map +0 -1
- package/dist/chunk-35IWNZPJ.cjs.map +0 -1
- package/dist/chunk-4AVD7NZW.cjs.map +0 -1
- package/dist/chunk-4CVLFLOB.cjs.map +0 -1
- package/dist/chunk-6GCKCWLB.js.map +0 -1
- package/dist/chunk-6RDSQURE.js.map +0 -1
- package/dist/chunk-75JP4BZX.js.map +0 -1
- package/dist/chunk-AHCLWAM5.cjs.map +0 -1
- package/dist/chunk-BAMZT3GL.js.map +0 -1
- package/dist/chunk-BVAR5J2F.js.map +0 -1
- package/dist/chunk-BXKJLM5R.cjs.map +0 -1
- package/dist/chunk-CCJPSHGI.cjs.map +0 -1
- package/dist/chunk-CSG5XVNJ.cjs.map +0 -1
- package/dist/chunk-CYFK5SY2.js.map +0 -1
- package/dist/chunk-DUEZFTK2.js.map +0 -1
- package/dist/chunk-GPPLSM2Z.js.map +0 -1
- package/dist/chunk-GVWHCL2N.js.map +0 -1
- package/dist/chunk-M4F66R4O.cjs.map +0 -1
- package/dist/chunk-M4N5GA5Z.cjs.map +0 -1
- package/dist/chunk-MBNQVDVC.cjs.map +0 -1
- package/dist/chunk-MEOHSQEH.js.map +0 -1
- package/dist/chunk-MTX2KVU7.cjs.map +0 -1
- package/dist/chunk-MVBEL57Q.js.map +0 -1
- package/dist/chunk-MZOVP3WI.cjs.map +0 -1
- package/dist/chunk-N5YFR4UP.cjs +0 -10
- package/dist/chunk-N5YFR4UP.cjs.map +0 -1
- package/dist/chunk-NZFKROS7.cjs.map +0 -1
- package/dist/chunk-OC6LTXYS.cjs.map +0 -1
- package/dist/chunk-OFXOTECC.js.map +0 -1
- package/dist/chunk-P33SBYGG.js.map +0 -1
- package/dist/chunk-P75775WC.js.map +0 -1
- package/dist/chunk-PCPX42KL.js.map +0 -1
- package/dist/chunk-PFSDGGYL.js +0 -8
- package/dist/chunk-PFSDGGYL.js.map +0 -1
- package/dist/chunk-QDMPOAI7.cjs.map +0 -1
- package/dist/chunk-R24DI24X.cjs.map +0 -1
- package/dist/chunk-SFQWJMKT.js.map +0 -1
- package/dist/chunk-V6HA6JJZ.cjs.map +0 -1
- package/dist/chunk-WWOLFXTX.cjs.map +0 -1
- package/dist/chunk-YU2CUNFO.js.map +0 -1
|
@@ -1,63 +1,63 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkFEAIOR7N_cjs = require('./chunk-FEAIOR7N.cjs');
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
4
|
+
var chunkA2N2GFCG_cjs = require('./chunk-A2N2GFCG.cjs');
|
|
5
|
+
var chunkUM6BVY2S_cjs = require('./chunk-UM6BVY2S.cjs');
|
|
6
|
+
var chunkJMXUNXQS_cjs = require('./chunk-JMXUNXQS.cjs');
|
|
7
|
+
var chunkPFUESQTW_cjs = require('./chunk-PFUESQTW.cjs');
|
|
8
|
+
var chunkAMOJYLG2_cjs = require('./chunk-AMOJYLG2.cjs');
|
|
9
|
+
var chunk5KMIY374_cjs = require('./chunk-5KMIY374.cjs');
|
|
10
10
|
|
|
11
11
|
// src/symbolic/MultivariateFactor.ts
|
|
12
12
|
function exactRoot(value, degree) {
|
|
13
|
-
const rootOf = degree === 2 ?
|
|
13
|
+
const rootOf = degree === 2 ? chunkUM6BVY2S_cjs.exactIntegerSqrt : chunkUM6BVY2S_cjs.exactIntegerCbrt;
|
|
14
14
|
const numerator = rootOf(value.n);
|
|
15
15
|
const denominator = rootOf(value.d);
|
|
16
16
|
return numerator === null || denominator === null ? null : { n: numerator, d: denominator };
|
|
17
17
|
}
|
|
18
18
|
function monomialRoot(key, degree) {
|
|
19
|
-
const monomial =
|
|
19
|
+
const monomial = chunkUM6BVY2S_cjs.monomialFromKey(key);
|
|
20
20
|
const root = /* @__PURE__ */ new Map();
|
|
21
21
|
for (const [name, exponent] of monomial) {
|
|
22
22
|
if (exponent % degree !== 0) return null;
|
|
23
23
|
root.set(name, exponent / degree);
|
|
24
24
|
}
|
|
25
|
-
return
|
|
25
|
+
return chunkUM6BVY2S_cjs.monomialToKey(root);
|
|
26
26
|
}
|
|
27
27
|
function monomialMul(a, b) {
|
|
28
|
-
const product2 =
|
|
29
|
-
for (const [name, exponent] of
|
|
28
|
+
const product2 = chunkUM6BVY2S_cjs.monomialFromKey(a);
|
|
29
|
+
for (const [name, exponent] of chunkUM6BVY2S_cjs.monomialFromKey(b)) {
|
|
30
30
|
product2.set(name, (product2.get(name) ?? 0) + exponent);
|
|
31
31
|
}
|
|
32
|
-
return
|
|
32
|
+
return chunkUM6BVY2S_cjs.monomialToKey(product2);
|
|
33
33
|
}
|
|
34
34
|
function monomialDiv(a, b) {
|
|
35
|
-
const quotient =
|
|
36
|
-
for (const [name, exponent] of
|
|
35
|
+
const quotient = chunkUM6BVY2S_cjs.monomialFromKey(a);
|
|
36
|
+
for (const [name, exponent] of chunkUM6BVY2S_cjs.monomialFromKey(b)) {
|
|
37
37
|
const remaining = (quotient.get(name) ?? 0) - exponent;
|
|
38
38
|
if (remaining <= 0) quotient.delete(name);
|
|
39
39
|
else quotient.set(name, remaining);
|
|
40
40
|
}
|
|
41
|
-
return
|
|
41
|
+
return chunkUM6BVY2S_cjs.monomialToKey(quotient);
|
|
42
42
|
}
|
|
43
43
|
function monomialGcd(a, b) {
|
|
44
|
-
const left =
|
|
44
|
+
const left = chunkUM6BVY2S_cjs.monomialFromKey(a);
|
|
45
45
|
const shared = /* @__PURE__ */ new Map();
|
|
46
|
-
for (const [name, exponent] of
|
|
46
|
+
for (const [name, exponent] of chunkUM6BVY2S_cjs.monomialFromKey(b)) {
|
|
47
47
|
const other = left.get(name);
|
|
48
48
|
if (other !== void 0) shared.set(name, Math.min(other, exponent));
|
|
49
49
|
}
|
|
50
|
-
return
|
|
50
|
+
return chunkUM6BVY2S_cjs.monomialToKey(shared);
|
|
51
51
|
}
|
|
52
52
|
function namesOf(keys) {
|
|
53
53
|
const names = /* @__PURE__ */ new Set();
|
|
54
|
-
for (const key of keys) for (const name of
|
|
54
|
+
for (const key of keys) for (const name of chunkUM6BVY2S_cjs.monomialFromKey(key).keys()) names.add(name);
|
|
55
55
|
return [...names].sort();
|
|
56
56
|
}
|
|
57
57
|
function termsToNode(terms) {
|
|
58
58
|
const map = /* @__PURE__ */ new Map();
|
|
59
59
|
for (const term of terms) map.set(term.key, term.coefficient);
|
|
60
|
-
return
|
|
60
|
+
return chunkUM6BVY2S_cjs.fromPolynomial({ terms: map, vars: namesOf(terms.map((term) => term.key)) });
|
|
61
61
|
}
|
|
62
62
|
function product(factors) {
|
|
63
63
|
let result = factors[0];
|
|
@@ -66,7 +66,7 @@ function product(factors) {
|
|
|
66
66
|
}
|
|
67
67
|
function orderedTerms(p) {
|
|
68
68
|
const terms = [...p.terms].map(([key, coefficient]) => ({ key, coefficient }));
|
|
69
|
-
return terms.sort((a, b) =>
|
|
69
|
+
return terms.sort((a, b) => chunkUM6BVY2S_cjs.compareMonomials(a.key, b.key, p.vars));
|
|
70
70
|
}
|
|
71
71
|
function factorMultivariate(p) {
|
|
72
72
|
if (p.vars.length < 2) return null;
|
|
@@ -94,9 +94,9 @@ function factorBinomial(first, second) {
|
|
|
94
94
|
return product([linear, termsToNode([squareOf(cubes.a), middle, squareOf(cubes.b)])]);
|
|
95
95
|
}
|
|
96
96
|
function asPowerPair(first, second, degree) {
|
|
97
|
-
const
|
|
97
|
+
const magnitude2 = second.coefficient.n < 0n ? chunkUM6BVY2S_cjs.rationalNeg(second.coefficient) : second.coefficient;
|
|
98
98
|
const firstRoot = exactRoot(first.coefficient, degree);
|
|
99
|
-
const secondRoot = exactRoot(
|
|
99
|
+
const secondRoot = exactRoot(magnitude2, degree);
|
|
100
100
|
if (firstRoot === null || secondRoot === null) return null;
|
|
101
101
|
const firstKey = monomialRoot(first.key, degree);
|
|
102
102
|
const secondKey = monomialRoot(second.key, degree);
|
|
@@ -104,10 +104,10 @@ function asPowerPair(first, second, degree) {
|
|
|
104
104
|
return { a: { key: firstKey, coefficient: firstRoot }, b: { key: secondKey, coefficient: secondRoot } };
|
|
105
105
|
}
|
|
106
106
|
function negated(term) {
|
|
107
|
-
return { key: term.key, coefficient:
|
|
107
|
+
return { key: term.key, coefficient: chunkUM6BVY2S_cjs.rationalNeg(term.coefficient) };
|
|
108
108
|
}
|
|
109
109
|
function multiplyTerms(a, b) {
|
|
110
|
-
return { key: monomialMul(a.key, b.key), coefficient:
|
|
110
|
+
return { key: monomialMul(a.key, b.key), coefficient: chunkUM6BVY2S_cjs.rationalMul(a.coefficient, b.coefficient) };
|
|
111
111
|
}
|
|
112
112
|
function squareOf(term) {
|
|
113
113
|
return multiplyTerms(term, term);
|
|
@@ -119,12 +119,12 @@ function factorPerfectSquare(terms) {
|
|
|
119
119
|
if (roots === null) return null;
|
|
120
120
|
const cross = multiplyTerms(roots.a, roots.b);
|
|
121
121
|
if (cross.key !== middle.key) return null;
|
|
122
|
-
const twice =
|
|
122
|
+
const twice = chunkUM6BVY2S_cjs.rationalMul(cross.coefficient, { n: 2n, d: 1n });
|
|
123
123
|
const negative = middle.coefficient.n < 0n;
|
|
124
|
-
const
|
|
125
|
-
if (!
|
|
124
|
+
const magnitude2 = negative ? chunkUM6BVY2S_cjs.rationalNeg(middle.coefficient) : middle.coefficient;
|
|
125
|
+
if (!chunkUM6BVY2S_cjs.isRationalOne(chunkUM6BVY2S_cjs.rationalDiv(magnitude2, twice))) return null;
|
|
126
126
|
const base = termsToNode([roots.a, negative ? negated(roots.b) : roots.b]);
|
|
127
|
-
return { kind: "pow", base, exponent:
|
|
127
|
+
return { kind: "pow", base, exponent: chunkUM6BVY2S_cjs.constNode(2) };
|
|
128
128
|
}
|
|
129
129
|
function factorByGrouping(terms) {
|
|
130
130
|
const pairings = [
|
|
@@ -149,7 +149,7 @@ function splitPair(first, second) {
|
|
|
149
149
|
const common = { key: shared, coefficient: first.coefficient };
|
|
150
150
|
const cofactor = [
|
|
151
151
|
{ key: monomialDiv(first.key, shared), coefficient: { n: 1n, d: 1n } },
|
|
152
|
-
{ key: monomialDiv(second.key, shared), coefficient:
|
|
152
|
+
{ key: monomialDiv(second.key, shared), coefficient: chunkUM6BVY2S_cjs.rationalDiv(second.coefficient, first.coefficient) }
|
|
153
153
|
];
|
|
154
154
|
return cofactor[0].key === cofactor[1].key ? null : { common, cofactor };
|
|
155
155
|
}
|
|
@@ -176,27 +176,27 @@ function lcm(a, b) {
|
|
|
176
176
|
return a / gcd(a, b) * b;
|
|
177
177
|
}
|
|
178
178
|
function divisors(value) {
|
|
179
|
-
const
|
|
180
|
-
if (
|
|
179
|
+
const magnitude2 = value < 0n ? -value : value;
|
|
180
|
+
if (magnitude2 === 0n) return null;
|
|
181
181
|
const found = [];
|
|
182
|
-
for (let candidate = 1n; candidate * candidate <=
|
|
183
|
-
if (
|
|
182
|
+
for (let candidate = 1n; candidate * candidate <= magnitude2; candidate++) {
|
|
183
|
+
if (magnitude2 % candidate !== 0n) continue;
|
|
184
184
|
found.push(candidate);
|
|
185
|
-
const paired =
|
|
185
|
+
const paired = magnitude2 / candidate;
|
|
186
186
|
if (paired !== candidate) found.push(paired);
|
|
187
187
|
if (found.length > FACTOR_MAX_ROOT_CANDIDATES) return null;
|
|
188
188
|
}
|
|
189
189
|
return found;
|
|
190
190
|
}
|
|
191
191
|
function evaluateAt(descending, x) {
|
|
192
|
-
let total =
|
|
193
|
-
for (const coeff of descending) total =
|
|
192
|
+
let total = chunkUM6BVY2S_cjs.RATIONAL_ZERO;
|
|
193
|
+
for (const coeff of descending) total = chunkUM6BVY2S_cjs.rationalAdd(chunkUM6BVY2S_cjs.rationalMul(total, x), coeff);
|
|
194
194
|
return total;
|
|
195
195
|
}
|
|
196
196
|
function divideByRoot(descending, root) {
|
|
197
197
|
const quotient = [descending[0]];
|
|
198
198
|
for (let i = 1; i < descending.length - 1; i++) {
|
|
199
|
-
quotient.push(
|
|
199
|
+
quotient.push(chunkUM6BVY2S_cjs.rationalAdd(descending[i], chunkUM6BVY2S_cjs.rationalMul(quotient[i - 1], root)));
|
|
200
200
|
}
|
|
201
201
|
return quotient;
|
|
202
202
|
}
|
|
@@ -211,14 +211,14 @@ function rationalRoots(descending) {
|
|
|
211
211
|
const numeratorDivisors = divisors(trailing);
|
|
212
212
|
const denominatorDivisors = divisors(leading);
|
|
213
213
|
if (numeratorDivisors === null || denominatorDivisors === null) {
|
|
214
|
-
throw
|
|
214
|
+
throw chunk5KMIY374_cjs.ErrorFactory.execution(
|
|
215
215
|
"SYMBOLIC_FACTOR_LIMIT_EXCEEDED",
|
|
216
216
|
"This polynomial's coefficients have too many divisors to search for rational roots.",
|
|
217
217
|
{ limit: FACTOR_MAX_ROOT_CANDIDATES }
|
|
218
218
|
);
|
|
219
219
|
}
|
|
220
220
|
if (numeratorDivisors.length * denominatorDivisors.length > FACTOR_MAX_ROOT_CANDIDATES) {
|
|
221
|
-
throw
|
|
221
|
+
throw chunk5KMIY374_cjs.ErrorFactory.execution(
|
|
222
222
|
"SYMBOLIC_FACTOR_LIMIT_EXCEEDED",
|
|
223
223
|
"This polynomial has too many candidate rational roots to test.",
|
|
224
224
|
{ limit: FACTOR_MAX_ROOT_CANDIDATES }
|
|
@@ -233,25 +233,25 @@ function rationalRoots(descending) {
|
|
|
233
233
|
const key = `${candidate.n}/${candidate.d}`;
|
|
234
234
|
if (seen.has(key)) continue;
|
|
235
235
|
seen.add(key);
|
|
236
|
-
if (
|
|
236
|
+
if (chunkUM6BVY2S_cjs.isRationalZero(evaluateAt(descending, candidate))) roots.push(candidate);
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
return roots;
|
|
241
241
|
}
|
|
242
242
|
function linearFactorNode(variable, root) {
|
|
243
|
-
if (
|
|
244
|
-
return root.n > 0n ? { kind: "sub", left:
|
|
243
|
+
if (chunkUM6BVY2S_cjs.isRationalZero(root)) return chunkUM6BVY2S_cjs.varNode(variable);
|
|
244
|
+
return root.n > 0n ? { kind: "sub", left: chunkUM6BVY2S_cjs.varNode(variable), right: chunkUM6BVY2S_cjs.constNode(root) } : { kind: "add", left: chunkUM6BVY2S_cjs.varNode(variable), right: chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.rationalNeg(root)) };
|
|
245
245
|
}
|
|
246
246
|
function coefficientsToNode(descending, variable) {
|
|
247
247
|
const degree = descending.length - 1;
|
|
248
248
|
const terms = /* @__PURE__ */ new Map();
|
|
249
249
|
descending.forEach((coeff, index) => {
|
|
250
|
-
if (
|
|
251
|
-
const
|
|
252
|
-
terms.set(
|
|
250
|
+
if (chunkUM6BVY2S_cjs.isRationalZero(coeff)) return;
|
|
251
|
+
const power3 = degree - index;
|
|
252
|
+
terms.set(power3 === 0 ? "" : power3 === 1 ? variable : `${variable}^${power3}`, coeff);
|
|
253
253
|
});
|
|
254
|
-
return
|
|
254
|
+
return chunkUM6BVY2S_cjs.fromPolynomial({ terms, vars: terms.size > 0 ? [variable] : [] });
|
|
255
255
|
}
|
|
256
256
|
function factorUnivariate(descending, variable) {
|
|
257
257
|
const factors = [];
|
|
@@ -260,7 +260,7 @@ function factorUnivariate(descending, variable) {
|
|
|
260
260
|
while (roots.length > 0 && remaining.length > 2) {
|
|
261
261
|
for (const root of roots) {
|
|
262
262
|
let multiplicity = 0;
|
|
263
|
-
while (remaining.length > 1 &&
|
|
263
|
+
while (remaining.length > 1 && chunkUM6BVY2S_cjs.isRationalZero(evaluateAt(remaining, root))) {
|
|
264
264
|
remaining = divideByRoot(remaining, root);
|
|
265
265
|
multiplicity++;
|
|
266
266
|
}
|
|
@@ -271,17 +271,17 @@ function factorUnivariate(descending, variable) {
|
|
|
271
271
|
const leftoverDegree = remaining.length - 1;
|
|
272
272
|
if (leftoverDegree >= 1) {
|
|
273
273
|
factors.push({ base: coefficientsToNode(remaining, variable), power: 1 });
|
|
274
|
-
return { content:
|
|
274
|
+
return { content: chunkUM6BVY2S_cjs.RATIONAL_ONE, factors };
|
|
275
275
|
}
|
|
276
|
-
return { content: remaining.length === 1 ? remaining[0] :
|
|
276
|
+
return { content: remaining.length === 1 ? remaining[0] : chunkUM6BVY2S_cjs.RATIONAL_ONE, factors };
|
|
277
277
|
}
|
|
278
278
|
function factorizationToNode(factorization) {
|
|
279
279
|
const pieces = [];
|
|
280
|
-
if (!
|
|
280
|
+
if (!chunkUM6BVY2S_cjs.isRationalOne(factorization.content)) pieces.push(chunkUM6BVY2S_cjs.constNode(factorization.content));
|
|
281
281
|
for (const factor of factorization.factors) {
|
|
282
|
-
pieces.push(factor.power === 1 ? factor.base :
|
|
282
|
+
pieces.push(factor.power === 1 ? factor.base : chunkUM6BVY2S_cjs.powNode(factor.base, chunkUM6BVY2S_cjs.constNode({ n: BigInt(factor.power), d: 1n })));
|
|
283
283
|
}
|
|
284
|
-
if (pieces.length === 0) return
|
|
284
|
+
if (pieces.length === 0) return chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.RATIONAL_ONE);
|
|
285
285
|
let result = pieces[0];
|
|
286
286
|
for (let i = 1; i < pieces.length; i++) result = { kind: "mul", left: result, right: pieces[i] };
|
|
287
287
|
return result;
|
|
@@ -293,7 +293,7 @@ function contentOf(p) {
|
|
|
293
293
|
numeratorGcd = gcd(numeratorGcd, coeff.n);
|
|
294
294
|
denominatorLcm = lcm(denominatorLcm, coeff.d);
|
|
295
295
|
}
|
|
296
|
-
if (numeratorGcd === 0n) return
|
|
296
|
+
if (numeratorGcd === 0n) return chunkUM6BVY2S_cjs.RATIONAL_ONE;
|
|
297
297
|
return { n: numeratorGcd, d: denominatorLcm };
|
|
298
298
|
}
|
|
299
299
|
function extractCommonMonomial(p) {
|
|
@@ -339,48 +339,48 @@ function monomialNode(monomial) {
|
|
|
339
339
|
let result = null;
|
|
340
340
|
for (const name of names) {
|
|
341
341
|
const exponent = monomial.get(name);
|
|
342
|
-
const factor = exponent === 1 ?
|
|
342
|
+
const factor = exponent === 1 ? chunkUM6BVY2S_cjs.varNode(name) : chunkUM6BVY2S_cjs.powNode(chunkUM6BVY2S_cjs.varNode(name), chunkUM6BVY2S_cjs.constNode({ n: BigInt(exponent), d: 1n }));
|
|
343
343
|
result = result === null ? factor : { kind: "mul", left: result, right: factor };
|
|
344
344
|
}
|
|
345
345
|
return result;
|
|
346
346
|
}
|
|
347
347
|
function factorSymbolic(node) {
|
|
348
|
-
const polynomial =
|
|
348
|
+
const polynomial = chunkUM6BVY2S_cjs.toPolynomial(node);
|
|
349
349
|
if (polynomial === null || polynomial.terms.size === 0) return node;
|
|
350
|
-
if (
|
|
350
|
+
if (chunkUM6BVY2S_cjs.polyDegree(polynomial) > FACTOR_MAX_DEGREE) return node;
|
|
351
351
|
if (polynomial.vars.length === 0) return node;
|
|
352
352
|
const content = contentOf(polynomial);
|
|
353
|
-
const primitive =
|
|
353
|
+
const primitive = chunkUM6BVY2S_cjs.isRationalOne(content) ? polynomial : scaleTerms(polynomial, chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.RATIONAL_ONE, content));
|
|
354
354
|
const { monomial, reduced } = extractCommonMonomial(primitive);
|
|
355
355
|
const monomialFactor = monomialNode(monomial);
|
|
356
|
-
const variable =
|
|
356
|
+
const variable = chunkUM6BVY2S_cjs.polyUnivariateVar(reduced);
|
|
357
357
|
if (variable === null) {
|
|
358
358
|
const patterned = factorMultivariate(reduced);
|
|
359
359
|
if (patterned !== null) return assemble(content, monomialFactor, patterned);
|
|
360
360
|
const pieces2 = buildPieces(content, monomialFactor, reduced);
|
|
361
361
|
return pieces2 ?? node;
|
|
362
362
|
}
|
|
363
|
-
const descending = [...
|
|
363
|
+
const descending = [...chunkUM6BVY2S_cjs.polyCoefficients(reduced, variable)].reverse();
|
|
364
364
|
const factorization = factorUnivariate(descending, variable);
|
|
365
|
-
const combinedContent =
|
|
366
|
-
const isUnchanged = factorization.factors.length <= 1 && (factorization.factors[0]?.power ?? 1) === 1 && monomialFactor === null &&
|
|
365
|
+
const combinedContent = chunkUM6BVY2S_cjs.rationalMul(content, factorization.content);
|
|
366
|
+
const isUnchanged = factorization.factors.length <= 1 && (factorization.factors[0]?.power ?? 1) === 1 && monomialFactor === null && chunkUM6BVY2S_cjs.isRationalOne(combinedContent);
|
|
367
367
|
if (isUnchanged) return node;
|
|
368
368
|
const pieces = [];
|
|
369
|
-
if (!
|
|
369
|
+
if (!chunkUM6BVY2S_cjs.isRationalOne(combinedContent)) pieces.push(chunkUM6BVY2S_cjs.constNode(combinedContent));
|
|
370
370
|
if (monomialFactor !== null) pieces.push(monomialFactor);
|
|
371
|
-
pieces.push(factorizationToNode({ content:
|
|
371
|
+
pieces.push(factorizationToNode({ content: chunkUM6BVY2S_cjs.RATIONAL_ONE, factors: factorization.factors }));
|
|
372
372
|
let result = pieces[0];
|
|
373
373
|
for (let i = 1; i < pieces.length; i++) result = { kind: "mul", left: result, right: pieces[i] };
|
|
374
374
|
return result;
|
|
375
375
|
}
|
|
376
376
|
function scaleTerms(p, k) {
|
|
377
377
|
const terms = /* @__PURE__ */ new Map();
|
|
378
|
-
for (const [key, coeff] of p.terms) terms.set(key,
|
|
378
|
+
for (const [key, coeff] of p.terms) terms.set(key, chunkUM6BVY2S_cjs.rationalMul(coeff, k));
|
|
379
379
|
return { terms, vars: p.vars };
|
|
380
380
|
}
|
|
381
381
|
function assemble(content, monomialFactor, factored) {
|
|
382
382
|
const pieces = [];
|
|
383
|
-
if (!
|
|
383
|
+
if (!chunkUM6BVY2S_cjs.isRationalOne(content)) pieces.push(chunkUM6BVY2S_cjs.constNode(content));
|
|
384
384
|
if (monomialFactor !== null) pieces.push(monomialFactor);
|
|
385
385
|
pieces.push(factored);
|
|
386
386
|
let result = pieces[0];
|
|
@@ -388,11 +388,11 @@ function assemble(content, monomialFactor, factored) {
|
|
|
388
388
|
return result;
|
|
389
389
|
}
|
|
390
390
|
function buildPieces(content, monomialFactor, reduced) {
|
|
391
|
-
if (monomialFactor === null &&
|
|
391
|
+
if (monomialFactor === null && chunkUM6BVY2S_cjs.isRationalOne(content)) return null;
|
|
392
392
|
const pieces = [];
|
|
393
|
-
if (!
|
|
393
|
+
if (!chunkUM6BVY2S_cjs.isRationalOne(content)) pieces.push(chunkUM6BVY2S_cjs.constNode(content));
|
|
394
394
|
if (monomialFactor !== null) pieces.push(monomialFactor);
|
|
395
|
-
pieces.push(
|
|
395
|
+
pieces.push(chunkUM6BVY2S_cjs.fromPolynomial(reduced));
|
|
396
396
|
let result = pieces[0];
|
|
397
397
|
for (let i = 1; i < pieces.length; i++) result = { kind: "mul", left: result, right: pieces[i] };
|
|
398
398
|
return result;
|
|
@@ -403,103 +403,103 @@ var TWO = { n: 2n, d: 1n };
|
|
|
403
403
|
var THREE = { n: 3n, d: 1n };
|
|
404
404
|
var FOUR = { n: 4n, d: 1n };
|
|
405
405
|
function depressCubic(a, b, c, d) {
|
|
406
|
-
const shift =
|
|
407
|
-
const p =
|
|
408
|
-
|
|
409
|
-
|
|
406
|
+
const shift = chunkUM6BVY2S_cjs.rationalNeg(chunkUM6BVY2S_cjs.rationalDiv(b, chunkUM6BVY2S_cjs.rationalMul(THREE, a)));
|
|
407
|
+
const p = chunkUM6BVY2S_cjs.rationalDiv(
|
|
408
|
+
chunkUM6BVY2S_cjs.rationalSub(chunkUM6BVY2S_cjs.rationalMul(THREE, chunkUM6BVY2S_cjs.rationalMul(a, c)), chunkUM6BVY2S_cjs.rationalMul(b, b)),
|
|
409
|
+
chunkUM6BVY2S_cjs.rationalMul(THREE, chunkUM6BVY2S_cjs.rationalMul(a, a))
|
|
410
410
|
);
|
|
411
|
-
const twoBCubed =
|
|
412
|
-
const nineABC =
|
|
413
|
-
const twentySevenAAD =
|
|
414
|
-
const q =
|
|
415
|
-
|
|
416
|
-
|
|
411
|
+
const twoBCubed = chunkUM6BVY2S_cjs.rationalMul(TWO, chunkUM6BVY2S_cjs.rationalMul(b, chunkUM6BVY2S_cjs.rationalMul(b, b)));
|
|
412
|
+
const nineABC = chunkUM6BVY2S_cjs.rationalMul({ n: 9n, d: 1n }, chunkUM6BVY2S_cjs.rationalMul(a, chunkUM6BVY2S_cjs.rationalMul(b, c)));
|
|
413
|
+
const twentySevenAAD = chunkUM6BVY2S_cjs.rationalMul({ n: 27n, d: 1n }, chunkUM6BVY2S_cjs.rationalMul(chunkUM6BVY2S_cjs.rationalMul(a, a), d));
|
|
414
|
+
const q = chunkUM6BVY2S_cjs.rationalDiv(
|
|
415
|
+
chunkUM6BVY2S_cjs.rationalAdd(chunkUM6BVY2S_cjs.rationalSub(twoBCubed, nineABC), twentySevenAAD),
|
|
416
|
+
chunkUM6BVY2S_cjs.rationalMul({ n: 27n, d: 1n }, chunkUM6BVY2S_cjs.rationalMul(a, chunkUM6BVY2S_cjs.rationalMul(a, a)))
|
|
417
417
|
);
|
|
418
418
|
return { p, q, shift };
|
|
419
419
|
}
|
|
420
420
|
function solveCubic(a, b, c, d) {
|
|
421
421
|
const { p, q, shift } = depressCubic(a, b, c, d);
|
|
422
|
-
const discriminant =
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
422
|
+
const discriminant = chunkUM6BVY2S_cjs.rationalNeg(
|
|
423
|
+
chunkUM6BVY2S_cjs.rationalAdd(
|
|
424
|
+
chunkUM6BVY2S_cjs.rationalMul(FOUR, chunkUM6BVY2S_cjs.rationalMul(p, chunkUM6BVY2S_cjs.rationalMul(p, p))),
|
|
425
|
+
chunkUM6BVY2S_cjs.rationalMul({ n: 27n, d: 1n }, chunkUM6BVY2S_cjs.rationalMul(q, q))
|
|
426
426
|
)
|
|
427
427
|
);
|
|
428
|
-
if (
|
|
428
|
+
if (chunkUM6BVY2S_cjs.rationalCompare(discriminant, chunkUM6BVY2S_cjs.RATIONAL_ZERO) > 0) {
|
|
429
429
|
return { exact: [], approximate: trigonometricRoots(p, q, shift) };
|
|
430
430
|
}
|
|
431
|
-
if (
|
|
431
|
+
if (chunkUM6BVY2S_cjs.isRationalZero(discriminant)) return { exact: repeatedCubicRoots(p, q, shift), approximate: [] };
|
|
432
432
|
return { exact: cardanoRoots(p, q, shift), approximate: [] };
|
|
433
433
|
}
|
|
434
434
|
function repeatedCubicRoots(p, q, shift) {
|
|
435
|
-
if (
|
|
436
|
-
const simple =
|
|
437
|
-
const repeated =
|
|
438
|
-
const ordered = [simple, repeated].sort(
|
|
439
|
-
return ordered.map(
|
|
435
|
+
if (chunkUM6BVY2S_cjs.isRationalZero(p)) return [chunkUM6BVY2S_cjs.constNode(shift)];
|
|
436
|
+
const simple = chunkUM6BVY2S_cjs.rationalAdd(chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalMul(THREE, q), p), shift);
|
|
437
|
+
const repeated = chunkUM6BVY2S_cjs.rationalAdd(chunkUM6BVY2S_cjs.rationalNeg(chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalMul(THREE, q), chunkUM6BVY2S_cjs.rationalMul(TWO, p))), shift);
|
|
438
|
+
const ordered = [simple, repeated].sort(chunkUM6BVY2S_cjs.rationalCompare);
|
|
439
|
+
return ordered.map(chunkUM6BVY2S_cjs.constNode);
|
|
440
440
|
}
|
|
441
441
|
function cardanoRoots(p, q, shift) {
|
|
442
|
-
const half =
|
|
443
|
-
const radicand =
|
|
444
|
-
|
|
445
|
-
|
|
442
|
+
const half = chunkUM6BVY2S_cjs.rationalNeg(chunkUM6BVY2S_cjs.rationalDiv(q, TWO));
|
|
443
|
+
const radicand = chunkUM6BVY2S_cjs.rationalAdd(
|
|
444
|
+
chunkUM6BVY2S_cjs.rationalMul(chunkUM6BVY2S_cjs.rationalDiv(q, TWO), chunkUM6BVY2S_cjs.rationalDiv(q, TWO)),
|
|
445
|
+
chunkUM6BVY2S_cjs.rationalMul(chunkUM6BVY2S_cjs.rationalDiv(p, THREE), chunkUM6BVY2S_cjs.rationalMul(chunkUM6BVY2S_cjs.rationalDiv(p, THREE), chunkUM6BVY2S_cjs.rationalDiv(p, THREE)))
|
|
446
446
|
);
|
|
447
|
-
const inner =
|
|
448
|
-
const u = { kind: "call", name: "cbrt", args: [{ kind: "add", left:
|
|
449
|
-
const v = { kind: "call", name: "cbrt", args: [{ kind: "sub", left:
|
|
447
|
+
const inner = chunkUM6BVY2S_cjs.surdNode(radicand);
|
|
448
|
+
const u = { kind: "call", name: "cbrt", args: [{ kind: "add", left: chunkUM6BVY2S_cjs.constNode(half), right: inner }] };
|
|
449
|
+
const v = { kind: "call", name: "cbrt", args: [{ kind: "sub", left: chunkUM6BVY2S_cjs.constNode(half), right: inner }] };
|
|
450
450
|
const sum = { kind: "add", left: u, right: v };
|
|
451
451
|
const difference = { kind: "sub", left: u, right: v };
|
|
452
|
-
const real = { kind: "add", left:
|
|
452
|
+
const real = { kind: "add", left: chunkUM6BVY2S_cjs.constNode(shift), right: { kind: "div", left: { kind: "neg", operand: sum }, right: chunkUM6BVY2S_cjs.constNode(TWO) } };
|
|
453
453
|
const imaginary = {
|
|
454
454
|
kind: "mul",
|
|
455
|
-
left: { kind: "div", left: { kind: "mul", left: difference, right:
|
|
456
|
-
right:
|
|
455
|
+
left: { kind: "div", left: { kind: "mul", left: difference, right: chunkUM6BVY2S_cjs.surdNode(THREE) }, right: chunkUM6BVY2S_cjs.constNode(TWO) },
|
|
456
|
+
right: chunkUM6BVY2S_cjs.complexNode(chunkUM6BVY2S_cjs.COMPLEX_I)
|
|
457
457
|
};
|
|
458
458
|
return [
|
|
459
|
-
{ kind: "add", left:
|
|
459
|
+
{ kind: "add", left: chunkUM6BVY2S_cjs.constNode(shift), right: sum },
|
|
460
460
|
{ kind: "sub", left: real, right: imaginary },
|
|
461
461
|
{ kind: "add", left: real, right: imaginary }
|
|
462
462
|
];
|
|
463
463
|
}
|
|
464
464
|
function trigonometricRoots(p, q, shift) {
|
|
465
|
-
const pNumber =
|
|
466
|
-
const qNumber =
|
|
467
|
-
const shiftNumber =
|
|
468
|
-
const
|
|
465
|
+
const pNumber = chunkUM6BVY2S_cjs.rationalToNumber(p);
|
|
466
|
+
const qNumber = chunkUM6BVY2S_cjs.rationalToNumber(q);
|
|
467
|
+
const shiftNumber = chunkUM6BVY2S_cjs.rationalToNumber(shift);
|
|
468
|
+
const magnitude2 = 2 * Math.sqrt(-pNumber / 3);
|
|
469
469
|
const ratio = 3 * qNumber / (2 * pNumber) * Math.sqrt(-3 / pNumber);
|
|
470
470
|
const angle = Math.acos(Math.min(1, Math.max(-1, ratio))) / 3;
|
|
471
|
-
return [0, 1, 2].map((k) =>
|
|
471
|
+
return [0, 1, 2].map((k) => magnitude2 * Math.cos(angle - 2 * Math.PI * k / 3) + shiftNumber).sort((left, right) => left - right);
|
|
472
472
|
}
|
|
473
473
|
function depressQuartic(b, c, d, e) {
|
|
474
|
-
const shift =
|
|
475
|
-
const bb =
|
|
476
|
-
const p =
|
|
477
|
-
const q =
|
|
478
|
-
|
|
479
|
-
|
|
474
|
+
const shift = chunkUM6BVY2S_cjs.rationalNeg(chunkUM6BVY2S_cjs.rationalDiv(b, FOUR));
|
|
475
|
+
const bb = chunkUM6BVY2S_cjs.rationalMul(b, b);
|
|
476
|
+
const p = chunkUM6BVY2S_cjs.rationalSub(c, chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalMul(THREE, bb), { n: 8n, d: 1n }));
|
|
477
|
+
const q = chunkUM6BVY2S_cjs.rationalAdd(
|
|
478
|
+
chunkUM6BVY2S_cjs.rationalSub(d, chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalMul(b, c), TWO)),
|
|
479
|
+
chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalMul(bb, b), { n: 8n, d: 1n })
|
|
480
480
|
);
|
|
481
|
-
const r =
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
481
|
+
const r = chunkUM6BVY2S_cjs.rationalSub(
|
|
482
|
+
chunkUM6BVY2S_cjs.rationalAdd(
|
|
483
|
+
chunkUM6BVY2S_cjs.rationalSub(e, chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalMul(b, d), FOUR)),
|
|
484
|
+
chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalMul(bb, c), { n: 16n, d: 1n })
|
|
485
485
|
),
|
|
486
|
-
|
|
486
|
+
chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalMul(THREE, chunkUM6BVY2S_cjs.rationalMul(bb, bb)), { n: 256n, d: 1n })
|
|
487
487
|
);
|
|
488
488
|
return { p, q, r, shift };
|
|
489
489
|
}
|
|
490
490
|
function solveQuartic(a, b, c, d, e, solveQuadratic2) {
|
|
491
|
-
const monic = (value) =>
|
|
491
|
+
const monic = (value) => chunkUM6BVY2S_cjs.rationalDiv(value, a);
|
|
492
492
|
const { p, q, r, shift } = depressQuartic(monic(b), monic(c), monic(d), monic(e));
|
|
493
|
-
const roots =
|
|
493
|
+
const roots = chunkUM6BVY2S_cjs.isRationalZero(q) ? biquadraticRoots(p, r) : splitQuarticRoots(p, q, r, solveQuadratic2);
|
|
494
494
|
if (roots === null) return null;
|
|
495
|
-
const shifted =
|
|
495
|
+
const shifted = chunkUM6BVY2S_cjs.isRationalZero(shift) ? roots : roots.map((root) => ({ kind: "add", left: chunkUM6BVY2S_cjs.constNode(shift), right: root }));
|
|
496
496
|
return { exact: distinct(shifted), approximate: [] };
|
|
497
497
|
}
|
|
498
498
|
function distinct(roots) {
|
|
499
499
|
const seen = /* @__PURE__ */ new Set();
|
|
500
500
|
const unique = [];
|
|
501
501
|
for (const root of roots) {
|
|
502
|
-
const key =
|
|
502
|
+
const key = chunkUM6BVY2S_cjs.symbolicKey(chunkUM6BVY2S_cjs.simplifySymbolic(root));
|
|
503
503
|
if (seen.has(key)) continue;
|
|
504
504
|
seen.add(key);
|
|
505
505
|
unique.push(root);
|
|
@@ -507,53 +507,51 @@ function distinct(roots) {
|
|
|
507
507
|
return unique;
|
|
508
508
|
}
|
|
509
509
|
function biquadraticRoots(p, r) {
|
|
510
|
-
const discriminant =
|
|
511
|
-
if (
|
|
512
|
-
const root =
|
|
513
|
-
if (root !== null) return rationalSquareRoots(
|
|
510
|
+
const discriminant = chunkUM6BVY2S_cjs.rationalSub(chunkUM6BVY2S_cjs.rationalMul(p, p), chunkUM6BVY2S_cjs.rationalMul(FOUR, r));
|
|
511
|
+
if (chunkUM6BVY2S_cjs.rationalCompare(discriminant, chunkUM6BVY2S_cjs.RATIONAL_ZERO) < 0) return complexBiquadraticRoots(p, r);
|
|
512
|
+
const root = chunkUM6BVY2S_cjs.exactRationalSqrt(discriminant);
|
|
513
|
+
if (root !== null) return rationalSquareRoots(chunkUM6BVY2S_cjs.rationalNeg(p), root, chunkUM6BVY2S_cjs.isRationalZero(discriminant));
|
|
514
514
|
return nestedSquareRoots(p, r, discriminant);
|
|
515
515
|
}
|
|
516
516
|
function rationalSquareRoots(negatedP, root, repeated) {
|
|
517
|
-
const values = repeated ? [
|
|
517
|
+
const values = repeated ? [chunkUM6BVY2S_cjs.rationalDiv(negatedP, TWO)] : [chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalAdd(negatedP, root), TWO), chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalSub(negatedP, root), TWO)];
|
|
518
518
|
const roots = [];
|
|
519
519
|
for (const value of values) {
|
|
520
|
-
if (
|
|
521
|
-
roots.push(
|
|
520
|
+
if (chunkUM6BVY2S_cjs.isRationalZero(value)) {
|
|
521
|
+
roots.push(chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.RATIONAL_ZERO));
|
|
522
522
|
continue;
|
|
523
523
|
}
|
|
524
|
-
const square =
|
|
524
|
+
const square = chunkUM6BVY2S_cjs.signedSurdNode(value);
|
|
525
525
|
roots.push({ kind: "neg", operand: square }, square);
|
|
526
526
|
}
|
|
527
527
|
return roots;
|
|
528
528
|
}
|
|
529
529
|
function nestedSquareRoots(p, r, discriminant) {
|
|
530
|
-
const negatedP =
|
|
531
|
-
const surd =
|
|
532
|
-
const negativeP =
|
|
530
|
+
const negatedP = chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.rationalNeg(p));
|
|
531
|
+
const surd = chunkUM6BVY2S_cjs.surdNode(discriminant);
|
|
532
|
+
const negativeP = chunkUM6BVY2S_cjs.rationalCompare(p, chunkUM6BVY2S_cjs.RATIONAL_ZERO) <= 0;
|
|
533
533
|
const solutions = [
|
|
534
|
-
{ node: halved({ kind: "add", left: negatedP, right: surd }), positive: negativeP ||
|
|
535
|
-
{ node: halved({ kind: "sub", left: negatedP, right: surd }), positive: negativeP &&
|
|
534
|
+
{ node: halved({ kind: "add", left: negatedP, right: surd }), positive: negativeP || chunkUM6BVY2S_cjs.rationalCompare(r, chunkUM6BVY2S_cjs.RATIONAL_ZERO) <= 0 },
|
|
535
|
+
{ node: halved({ kind: "sub", left: negatedP, right: surd }), positive: negativeP && chunkUM6BVY2S_cjs.rationalCompare(r, chunkUM6BVY2S_cjs.RATIONAL_ZERO) >= 0 }
|
|
536
536
|
];
|
|
537
537
|
const roots = [];
|
|
538
538
|
for (const { node, positive } of solutions) {
|
|
539
539
|
const radicand = positive ? node : { kind: "neg", operand: node };
|
|
540
|
-
const
|
|
541
|
-
const square = positive ?
|
|
540
|
+
const magnitude2 = { kind: "call", name: "sqrt", args: [radicand] };
|
|
541
|
+
const square = positive ? magnitude2 : { kind: "mul", left: magnitude2, right: chunkUM6BVY2S_cjs.complexNode(chunkUM6BVY2S_cjs.COMPLEX_I) };
|
|
542
542
|
roots.push({ kind: "neg", operand: square }, square);
|
|
543
543
|
}
|
|
544
544
|
return roots;
|
|
545
545
|
}
|
|
546
546
|
function halved(node) {
|
|
547
|
-
return { kind: "div", left: node, right:
|
|
547
|
+
return { kind: "div", left: node, right: chunkUM6BVY2S_cjs.constNode(TWO) };
|
|
548
548
|
}
|
|
549
549
|
function complexBiquadraticRoots(p, r) {
|
|
550
|
-
const
|
|
551
|
-
|
|
552
|
-
const
|
|
553
|
-
const
|
|
554
|
-
|
|
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) };
|
|
550
|
+
const centre = chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalNeg(p), TWO);
|
|
551
|
+
const modulus = chunkUM6BVY2S_cjs.exactRationalSqrt(r);
|
|
552
|
+
const re = modulus === null ? nestedSurd(chunkUM6BVY2S_cjs.surdNode(r), centre) : chunkUM6BVY2S_cjs.surdNode(chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalAdd(modulus, centre), TWO));
|
|
553
|
+
const imaginaryMagnitude = modulus === null ? nestedSurd(chunkUM6BVY2S_cjs.surdNode(r), chunkUM6BVY2S_cjs.rationalNeg(centre)) : chunkUM6BVY2S_cjs.surdNode(chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalSub(modulus, centre), TWO));
|
|
554
|
+
const im = { kind: "mul", left: imaginaryMagnitude, right: chunkUM6BVY2S_cjs.complexNode(chunkUM6BVY2S_cjs.COMPLEX_I) };
|
|
557
555
|
const first = { kind: "add", left: re, right: im };
|
|
558
556
|
const second = { kind: "sub", left: re, right: im };
|
|
559
557
|
return [
|
|
@@ -563,94 +561,262 @@ function complexBiquadraticRoots(p, r) {
|
|
|
563
561
|
first
|
|
564
562
|
];
|
|
565
563
|
}
|
|
564
|
+
function nestedSurd(surd, offset) {
|
|
565
|
+
const shifted = offset.n >= 0n ? { kind: "add", left: surd, right: chunkUM6BVY2S_cjs.constNode(offset) } : { kind: "sub", left: surd, right: chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.rationalNeg(offset)) };
|
|
566
|
+
return { kind: "call", name: "sqrt", args: [halved(shifted)] };
|
|
567
|
+
}
|
|
566
568
|
function splitQuarticRoots(p, q, r, solveQuadratic2) {
|
|
567
569
|
const resolvent = [
|
|
568
570
|
{ n: 1n, d: 1n },
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
571
|
+
chunkUM6BVY2S_cjs.rationalMul(TWO, p),
|
|
572
|
+
chunkUM6BVY2S_cjs.rationalSub(chunkUM6BVY2S_cjs.rationalMul(p, p), chunkUM6BVY2S_cjs.rationalMul(FOUR, r)),
|
|
573
|
+
chunkUM6BVY2S_cjs.rationalNeg(chunkUM6BVY2S_cjs.rationalMul(q, q))
|
|
572
574
|
];
|
|
573
575
|
for (const z of rationalRoots(resolvent)) {
|
|
574
|
-
if (
|
|
575
|
-
const alpha =
|
|
576
|
+
if (chunkUM6BVY2S_cjs.rationalCompare(z, chunkUM6BVY2S_cjs.RATIONAL_ZERO) <= 0) continue;
|
|
577
|
+
const alpha = chunkUM6BVY2S_cjs.exactRationalSqrt(z);
|
|
576
578
|
if (alpha === null) continue;
|
|
577
|
-
const sum =
|
|
578
|
-
const difference =
|
|
579
|
-
const beta =
|
|
580
|
-
const gamma =
|
|
579
|
+
const sum = chunkUM6BVY2S_cjs.rationalAdd(p, z);
|
|
580
|
+
const difference = chunkUM6BVY2S_cjs.rationalDiv(q, alpha);
|
|
581
|
+
const beta = chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalSub(sum, difference), TWO);
|
|
582
|
+
const gamma = chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalAdd(sum, difference), TWO);
|
|
581
583
|
const one2 = { n: 1n, d: 1n };
|
|
582
584
|
return [
|
|
583
585
|
...solveQuadratic2(one2, alpha, beta),
|
|
584
|
-
...solveQuadratic2(one2,
|
|
586
|
+
...solveQuadratic2(one2, chunkUM6BVY2S_cjs.rationalNeg(alpha), gamma)
|
|
585
587
|
];
|
|
586
588
|
}
|
|
587
589
|
return null;
|
|
588
590
|
}
|
|
589
591
|
|
|
592
|
+
// src/symbolic/NumericRoots.ts
|
|
593
|
+
var DURAND_KERNER_MAX_ITERATIONS = 200;
|
|
594
|
+
var DURAND_KERNER_TOLERANCE = 1e-14;
|
|
595
|
+
var ROOT_RESIDUAL_TOLERANCE = 1e-10;
|
|
596
|
+
var ROOT_SEPARATION_TOLERANCE = 1e-10;
|
|
597
|
+
var AXIS_SNAP_TOLERANCE = 1e-9;
|
|
598
|
+
var CONJUGATE_PAIR_TOLERANCE = 1e-8;
|
|
599
|
+
var NEWTON_POLISH_STEPS = 4;
|
|
600
|
+
function subtract(a, b) {
|
|
601
|
+
return { re: a.re - b.re, im: a.im - b.im };
|
|
602
|
+
}
|
|
603
|
+
function multiply(a, b) {
|
|
604
|
+
return { re: a.re * b.re - a.im * b.im, im: a.re * b.im + a.im * b.re };
|
|
605
|
+
}
|
|
606
|
+
function divide(a, b) {
|
|
607
|
+
if (Math.abs(b.re) >= Math.abs(b.im)) {
|
|
608
|
+
const ratio2 = b.im / b.re;
|
|
609
|
+
const denominator2 = b.re + b.im * ratio2;
|
|
610
|
+
return { re: (a.re + a.im * ratio2) / denominator2, im: (a.im - a.re * ratio2) / denominator2 };
|
|
611
|
+
}
|
|
612
|
+
const ratio = b.re / b.im;
|
|
613
|
+
const denominator = b.re * ratio + b.im;
|
|
614
|
+
return { re: (a.re * ratio + a.im) / denominator, im: (a.im * ratio - a.re) / denominator };
|
|
615
|
+
}
|
|
616
|
+
function magnitude(z) {
|
|
617
|
+
return Math.hypot(z.re, z.im);
|
|
618
|
+
}
|
|
619
|
+
function evaluateAt2(descending, z) {
|
|
620
|
+
let re = 0;
|
|
621
|
+
let im = 0;
|
|
622
|
+
for (const coefficient of descending) {
|
|
623
|
+
const nextRe = re * z.re - im * z.im + coefficient;
|
|
624
|
+
im = re * z.im + im * z.re;
|
|
625
|
+
re = nextRe;
|
|
626
|
+
}
|
|
627
|
+
return { re, im };
|
|
628
|
+
}
|
|
629
|
+
function evaluationScale(descending, z) {
|
|
630
|
+
const radius = magnitude(z);
|
|
631
|
+
let total = 0;
|
|
632
|
+
for (const coefficient of descending) total = total * radius + Math.abs(coefficient);
|
|
633
|
+
return total;
|
|
634
|
+
}
|
|
635
|
+
function differentiate(descending) {
|
|
636
|
+
const degree = descending.length - 1;
|
|
637
|
+
const derivative = [];
|
|
638
|
+
for (let i = 0; i < degree; i++) derivative.push(descending[i] * (degree - i));
|
|
639
|
+
return derivative;
|
|
640
|
+
}
|
|
641
|
+
function squareFreeDoubles(descending) {
|
|
642
|
+
const ascending = [...descending].reverse();
|
|
643
|
+
const squareFree = [...chunkUM6BVY2S_cjs.squareFreePart(ascending)].reverse();
|
|
644
|
+
const doubles = squareFree.map(chunkUM6BVY2S_cjs.rationalToNumber);
|
|
645
|
+
if (doubles.some((value) => !Number.isFinite(value))) return null;
|
|
646
|
+
return doubles;
|
|
647
|
+
}
|
|
648
|
+
function initialEstimates(monic) {
|
|
649
|
+
const degree = monic.length - 1;
|
|
650
|
+
let largest = 0;
|
|
651
|
+
for (let i = 1; i < monic.length; i++) largest = Math.max(largest, Math.abs(monic[i]));
|
|
652
|
+
const radius = 1 + largest;
|
|
653
|
+
const centre = -monic[1] / degree;
|
|
654
|
+
const estimates = [];
|
|
655
|
+
for (let k = 0; k < degree; k++) {
|
|
656
|
+
const angle = 2 * Math.PI * k / degree + Math.PI / (2 * degree);
|
|
657
|
+
estimates.push({ re: centre + radius * Math.cos(angle), im: radius * Math.sin(angle) });
|
|
658
|
+
}
|
|
659
|
+
return estimates;
|
|
660
|
+
}
|
|
661
|
+
function durandKerner(monic) {
|
|
662
|
+
const degree = monic.length - 1;
|
|
663
|
+
const estimates = initialEstimates(monic);
|
|
664
|
+
for (let iteration = 0; iteration < DURAND_KERNER_MAX_ITERATIONS; iteration++) {
|
|
665
|
+
let largestStep = 0;
|
|
666
|
+
let largestRoot = 1;
|
|
667
|
+
for (let i = 0; i < degree; i++) {
|
|
668
|
+
let denominator = { re: 1, im: 0 };
|
|
669
|
+
for (let j = 0; j < degree; j++) {
|
|
670
|
+
if (i !== j) denominator = multiply(denominator, subtract(estimates[i], estimates[j]));
|
|
671
|
+
}
|
|
672
|
+
if (denominator.re === 0 && denominator.im === 0) {
|
|
673
|
+
estimates[i] = { re: estimates[i].re + 1e-6 * (i + 1), im: estimates[i].im + 1e-6 };
|
|
674
|
+
continue;
|
|
675
|
+
}
|
|
676
|
+
const step = divide(evaluateAt2(monic, estimates[i]), denominator);
|
|
677
|
+
if (!Number.isFinite(step.re) || !Number.isFinite(step.im)) return null;
|
|
678
|
+
estimates[i] = subtract(estimates[i], step);
|
|
679
|
+
largestStep = Math.max(largestStep, magnitude(step));
|
|
680
|
+
largestRoot = Math.max(largestRoot, magnitude(estimates[i]));
|
|
681
|
+
}
|
|
682
|
+
if (largestStep <= DURAND_KERNER_TOLERANCE * largestRoot) return estimates;
|
|
683
|
+
}
|
|
684
|
+
return null;
|
|
685
|
+
}
|
|
686
|
+
function polish(monic, derivative, start) {
|
|
687
|
+
let candidate = start;
|
|
688
|
+
for (let step = 0; step < NEWTON_POLISH_STEPS; step++) {
|
|
689
|
+
const slope = evaluateAt2(derivative, candidate);
|
|
690
|
+
if (slope.re === 0 && slope.im === 0) break;
|
|
691
|
+
const next = subtract(candidate, divide(evaluateAt2(monic, candidate), slope));
|
|
692
|
+
if (!Number.isFinite(next.re) || !Number.isFinite(next.im)) break;
|
|
693
|
+
candidate = next;
|
|
694
|
+
}
|
|
695
|
+
return candidate;
|
|
696
|
+
}
|
|
697
|
+
function snapToAxes(monic, derivative, z) {
|
|
698
|
+
const scale2 = Math.max(1, magnitude(z));
|
|
699
|
+
if (z.im !== 0 && Math.abs(z.im) <= AXIS_SNAP_TOLERANCE * scale2) {
|
|
700
|
+
const candidate = polish(monic, derivative, { re: z.re, im: 0 });
|
|
701
|
+
if (isRootWithinTolerance(monic, candidate)) return { re: candidate.re, im: 0 };
|
|
702
|
+
}
|
|
703
|
+
if (z.re !== 0 && Math.abs(z.re) <= AXIS_SNAP_TOLERANCE * scale2) {
|
|
704
|
+
const candidate = polish(monic, derivative, { re: 0, im: z.im });
|
|
705
|
+
if (isRootWithinTolerance(monic, candidate)) return { re: 0, im: candidate.im };
|
|
706
|
+
}
|
|
707
|
+
return z;
|
|
708
|
+
}
|
|
709
|
+
function isRootWithinTolerance(monic, z) {
|
|
710
|
+
if (!Number.isFinite(z.re) || !Number.isFinite(z.im)) return false;
|
|
711
|
+
return magnitude(evaluateAt2(monic, z)) <= ROOT_RESIDUAL_TOLERANCE * evaluationScale(monic, z);
|
|
712
|
+
}
|
|
713
|
+
function pairConjugates(roots) {
|
|
714
|
+
const result = [...roots];
|
|
715
|
+
const paired = result.map((root) => root.im === 0);
|
|
716
|
+
for (let i = 0; i < result.length; i++) {
|
|
717
|
+
if (paired[i]) continue;
|
|
718
|
+
const wanted = { re: result[i].re, im: -result[i].im };
|
|
719
|
+
let partner = -1;
|
|
720
|
+
let closest = Number.POSITIVE_INFINITY;
|
|
721
|
+
for (let j = i + 1; j < result.length; j++) {
|
|
722
|
+
if (paired[j]) continue;
|
|
723
|
+
const distance = magnitude(subtract(result[j], wanted));
|
|
724
|
+
if (distance < closest) {
|
|
725
|
+
closest = distance;
|
|
726
|
+
partner = j;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
if (partner === -1 || closest > CONJUGATE_PAIR_TOLERANCE * Math.max(1, magnitude(result[i]))) continue;
|
|
730
|
+
const re = (result[i].re + result[partner].re) / 2;
|
|
731
|
+
const im = (Math.abs(result[i].im) + Math.abs(result[partner].im)) / 2;
|
|
732
|
+
const sign = result[i].im < 0 ? -1 : 1;
|
|
733
|
+
result[i] = { re, im: sign * im };
|
|
734
|
+
result[partner] = { re, im: -sign * im };
|
|
735
|
+
paired[i] = true;
|
|
736
|
+
paired[partner] = true;
|
|
737
|
+
}
|
|
738
|
+
return result;
|
|
739
|
+
}
|
|
740
|
+
function allSeparated(roots) {
|
|
741
|
+
for (let i = 0; i < roots.length; i++) {
|
|
742
|
+
for (let j = i + 1; j < roots.length; j++) {
|
|
743
|
+
const scale2 = Math.max(1, magnitude(roots[i]), magnitude(roots[j]));
|
|
744
|
+
if (magnitude(subtract(roots[i], roots[j])) <= ROOT_SEPARATION_TOLERANCE * scale2) return false;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
return true;
|
|
748
|
+
}
|
|
749
|
+
function approximateRoots(descending) {
|
|
750
|
+
const monic = squareFreeDoubles(descending);
|
|
751
|
+
if (monic === null) return null;
|
|
752
|
+
if (monic.length < 2) return [];
|
|
753
|
+
const converged = durandKerner(monic);
|
|
754
|
+
if (converged === null) return null;
|
|
755
|
+
const derivative = differentiate(monic);
|
|
756
|
+
const roots = pairConjugates(converged).map((root) => snapToAxes(monic, derivative, root));
|
|
757
|
+
for (const root of roots) {
|
|
758
|
+
if (!isRootWithinTolerance(monic, root)) return null;
|
|
759
|
+
}
|
|
760
|
+
if (!allSeparated(roots)) return null;
|
|
761
|
+
return [...roots].sort((a, b) => a.re - b.re || a.im - b.im);
|
|
762
|
+
}
|
|
763
|
+
|
|
590
764
|
// src/symbolic/Solve.ts
|
|
591
765
|
var SOLVE_MAX_DEGREE = 8;
|
|
592
|
-
var NEWTON_MAX_ITERATIONS = 100;
|
|
593
|
-
var NEWTON_TOLERANCE = 1e-12;
|
|
594
|
-
var NUMERIC_SCAN_STEPS = 2e3;
|
|
595
766
|
function evaluateRational(descending, x) {
|
|
596
|
-
let total =
|
|
597
|
-
for (const coeff of descending) total =
|
|
598
|
-
return total;
|
|
599
|
-
}
|
|
600
|
-
function evaluateNumeric(descending, x) {
|
|
601
|
-
let total = 0;
|
|
602
|
-
for (const coeff of descending) total = total * x + chunk4CVLFLOB_cjs.rationalToNumber(coeff);
|
|
767
|
+
let total = chunkUM6BVY2S_cjs.RATIONAL_ZERO;
|
|
768
|
+
for (const coeff of descending) total = chunkUM6BVY2S_cjs.rationalAdd(chunkUM6BVY2S_cjs.rationalMul(total, x), coeff);
|
|
603
769
|
return total;
|
|
604
770
|
}
|
|
605
771
|
function divideByRoot2(descending, root) {
|
|
606
772
|
const quotient = [descending[0]];
|
|
607
773
|
for (let i = 1; i < descending.length - 1; i++) {
|
|
608
|
-
quotient.push(
|
|
774
|
+
quotient.push(chunkUM6BVY2S_cjs.rationalAdd(descending[i], chunkUM6BVY2S_cjs.rationalMul(quotient[i - 1], root)));
|
|
609
775
|
}
|
|
610
776
|
return quotient;
|
|
611
777
|
}
|
|
612
778
|
function solveQuadratic(a, b, c) {
|
|
613
|
-
const discriminant =
|
|
614
|
-
const twoA =
|
|
615
|
-
if (
|
|
616
|
-
return complexQuadraticRoots(
|
|
617
|
-
}
|
|
618
|
-
if (
|
|
619
|
-
const rootN =
|
|
620
|
-
const rootD =
|
|
779
|
+
const discriminant = chunkUM6BVY2S_cjs.rationalSub(chunkUM6BVY2S_cjs.rationalMul(b, b), chunkUM6BVY2S_cjs.rationalMul(rational4(), chunkUM6BVY2S_cjs.rationalMul(a, c)));
|
|
780
|
+
const twoA = chunkUM6BVY2S_cjs.rationalMul(rational2(), a);
|
|
781
|
+
if (chunkUM6BVY2S_cjs.rationalCompare(discriminant, chunkUM6BVY2S_cjs.RATIONAL_ZERO) < 0) {
|
|
782
|
+
return complexQuadraticRoots(chunkUM6BVY2S_cjs.rationalNeg(b), discriminant, twoA);
|
|
783
|
+
}
|
|
784
|
+
if (chunkUM6BVY2S_cjs.isRationalZero(discriminant)) return [chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalNeg(b), twoA))];
|
|
785
|
+
const rootN = chunkUM6BVY2S_cjs.exactIntegerSqrt(discriminant.n);
|
|
786
|
+
const rootD = chunkUM6BVY2S_cjs.exactIntegerSqrt(discriminant.d);
|
|
621
787
|
if (rootN !== null && rootD !== null) {
|
|
622
788
|
const root = { n: rootN, d: rootD };
|
|
623
|
-
const plus =
|
|
624
|
-
const minus =
|
|
625
|
-
return
|
|
626
|
-
}
|
|
627
|
-
const surd =
|
|
628
|
-
const ascending =
|
|
629
|
-
const lower = { kind: "div", left: { kind: "sub", left:
|
|
630
|
-
const upper = { kind: "div", left: { kind: "add", left:
|
|
789
|
+
const plus = chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalAdd(chunkUM6BVY2S_cjs.rationalNeg(b), root), twoA);
|
|
790
|
+
const minus = chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalSub(chunkUM6BVY2S_cjs.rationalNeg(b), root), twoA);
|
|
791
|
+
return chunkUM6BVY2S_cjs.rationalCompare(minus, plus) <= 0 ? [chunkUM6BVY2S_cjs.constNode(minus), chunkUM6BVY2S_cjs.constNode(plus)] : [chunkUM6BVY2S_cjs.constNode(plus), chunkUM6BVY2S_cjs.constNode(minus)];
|
|
792
|
+
}
|
|
793
|
+
const surd = chunkUM6BVY2S_cjs.surdNode(discriminant);
|
|
794
|
+
const ascending = chunkUM6BVY2S_cjs.rationalCompare(twoA, chunkUM6BVY2S_cjs.RATIONAL_ZERO) > 0;
|
|
795
|
+
const lower = { kind: "div", left: { kind: "sub", left: chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.rationalNeg(b)), right: surd }, right: chunkUM6BVY2S_cjs.constNode(twoA) };
|
|
796
|
+
const upper = { kind: "div", left: { kind: "add", left: chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.rationalNeg(b)), right: surd }, right: chunkUM6BVY2S_cjs.constNode(twoA) };
|
|
631
797
|
return ascending ? [lower, upper] : [upper, lower];
|
|
632
798
|
}
|
|
633
799
|
function complexQuadraticRoots(negatedB, discriminant, twoA) {
|
|
634
|
-
const
|
|
635
|
-
const rootN =
|
|
636
|
-
const rootD =
|
|
800
|
+
const magnitude2 = chunkUM6BVY2S_cjs.rationalNeg(discriminant);
|
|
801
|
+
const rootN = chunkUM6BVY2S_cjs.exactIntegerSqrt(magnitude2.n);
|
|
802
|
+
const rootD = chunkUM6BVY2S_cjs.exactIntegerSqrt(magnitude2.d);
|
|
637
803
|
if (rootN !== null && rootD !== null) {
|
|
638
|
-
const imaginary2 =
|
|
639
|
-
const real2 =
|
|
804
|
+
const imaginary2 = chunkUM6BVY2S_cjs.rationalDiv({ n: rootN, d: rootD }, twoA);
|
|
805
|
+
const real2 = chunkUM6BVY2S_cjs.rationalDiv(negatedB, twoA);
|
|
640
806
|
return [
|
|
641
|
-
|
|
642
|
-
|
|
807
|
+
chunkUM6BVY2S_cjs.complexNode(chunkUM6BVY2S_cjs.complex(real2, chunkUM6BVY2S_cjs.rationalNeg(imaginary2))),
|
|
808
|
+
chunkUM6BVY2S_cjs.complexNode(chunkUM6BVY2S_cjs.complex(real2, imaginary2))
|
|
643
809
|
];
|
|
644
810
|
}
|
|
645
|
-
const real =
|
|
646
|
-
const scaledRadicand =
|
|
647
|
-
const imaginary = { kind: "mul", left:
|
|
648
|
-
if (
|
|
811
|
+
const real = chunkUM6BVY2S_cjs.rationalDiv(negatedB, twoA);
|
|
812
|
+
const scaledRadicand = chunkUM6BVY2S_cjs.rationalDiv(magnitude2, chunkUM6BVY2S_cjs.rationalMul(twoA, twoA));
|
|
813
|
+
const imaginary = { kind: "mul", left: chunkUM6BVY2S_cjs.surdNode(scaledRadicand), right: chunkUM6BVY2S_cjs.complexNode(chunkUM6BVY2S_cjs.COMPLEX_I) };
|
|
814
|
+
if (chunkUM6BVY2S_cjs.isRationalZero(real)) {
|
|
649
815
|
return [{ kind: "neg", operand: imaginary }, imaginary];
|
|
650
816
|
}
|
|
651
817
|
return [
|
|
652
|
-
{ kind: "sub", left:
|
|
653
|
-
{ kind: "add", left:
|
|
818
|
+
{ kind: "sub", left: chunkUM6BVY2S_cjs.constNode(real), right: imaginary },
|
|
819
|
+
{ kind: "add", left: chunkUM6BVY2S_cjs.constNode(real), right: imaginary }
|
|
654
820
|
];
|
|
655
821
|
}
|
|
656
822
|
function rational2() {
|
|
@@ -659,47 +825,11 @@ function rational2() {
|
|
|
659
825
|
function rational4() {
|
|
660
826
|
return { n: 4n, d: 1n };
|
|
661
827
|
}
|
|
662
|
-
function
|
|
663
|
-
|
|
664
|
-
if (leading === 0) return [];
|
|
665
|
-
let bound = 0;
|
|
666
|
-
for (let i = 1; i < descending.length; i++) {
|
|
667
|
-
const ratio = Math.abs(chunk4CVLFLOB_cjs.rationalToNumber(descending[i]) / leading);
|
|
668
|
-
if (ratio > bound) bound = ratio;
|
|
669
|
-
}
|
|
670
|
-
bound += 1;
|
|
671
|
-
const roots = [];
|
|
672
|
-
const step = 2 * bound / NUMERIC_SCAN_STEPS;
|
|
673
|
-
let previousX = -bound;
|
|
674
|
-
let previousY = evaluateNumeric(descending, previousX);
|
|
675
|
-
for (let i = 1; i <= NUMERIC_SCAN_STEPS; i++) {
|
|
676
|
-
const x = -bound + i * step;
|
|
677
|
-
const y = evaluateNumeric(descending, x);
|
|
678
|
-
if (previousY === 0) roots.push(previousX);
|
|
679
|
-
else if (previousY < 0 !== y < 0) roots.push(bisect(descending, previousX, x));
|
|
680
|
-
previousX = x;
|
|
681
|
-
previousY = y;
|
|
682
|
-
}
|
|
683
|
-
return roots;
|
|
684
|
-
}
|
|
685
|
-
function bisect(descending, low, high) {
|
|
686
|
-
let left = low;
|
|
687
|
-
let right = high;
|
|
688
|
-
let leftValue = evaluateNumeric(descending, left);
|
|
689
|
-
for (let i = 0; i < NEWTON_MAX_ITERATIONS && right - left > NEWTON_TOLERANCE; i++) {
|
|
690
|
-
const middle = (left + right) / 2;
|
|
691
|
-
const middleValue = evaluateNumeric(descending, middle);
|
|
692
|
-
if (leftValue < 0 === middleValue < 0) {
|
|
693
|
-
left = middle;
|
|
694
|
-
leftValue = middleValue;
|
|
695
|
-
} else {
|
|
696
|
-
right = middle;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
return (left + right) / 2;
|
|
828
|
+
function realApproximation(value) {
|
|
829
|
+
return { re: value, im: 0 };
|
|
700
830
|
}
|
|
701
831
|
function solveForVariable(lhs, rhs, variable) {
|
|
702
|
-
const polynomial =
|
|
832
|
+
const polynomial = chunkUM6BVY2S_cjs.toPolynomial({ kind: "sub", left: lhs, right: rhs });
|
|
703
833
|
if (polynomial === null) {
|
|
704
834
|
return {
|
|
705
835
|
kind: "unsupported",
|
|
@@ -707,7 +837,7 @@ function solveForVariable(lhs, rhs, variable) {
|
|
|
707
837
|
};
|
|
708
838
|
}
|
|
709
839
|
const others = polynomial.vars.filter((name) => name !== variable);
|
|
710
|
-
const degree =
|
|
840
|
+
const degree = chunkUM6BVY2S_cjs.polyDegree(polynomial, variable);
|
|
711
841
|
if (others.length > 0) {
|
|
712
842
|
if (degree !== 1) {
|
|
713
843
|
return {
|
|
@@ -723,7 +853,7 @@ function solveForVariable(lhs, rhs, variable) {
|
|
|
723
853
|
if (degree > SOLVE_MAX_DEGREE) {
|
|
724
854
|
return { kind: "unsupported", reason: `degree ${degree} is above the supported maximum of ${SOLVE_MAX_DEGREE}` };
|
|
725
855
|
}
|
|
726
|
-
const descending = [...
|
|
856
|
+
const descending = [...chunkUM6BVY2S_cjs.polyCoefficients(polynomial, variable)].reverse();
|
|
727
857
|
return solveUnivariate(descending);
|
|
728
858
|
}
|
|
729
859
|
function solveLinearWithOtherUnknowns(polynomial, variable) {
|
|
@@ -748,8 +878,8 @@ function solveLinearWithOtherUnknowns(polynomial, variable) {
|
|
|
748
878
|
}
|
|
749
879
|
return [...names].sort();
|
|
750
880
|
};
|
|
751
|
-
const coefficient =
|
|
752
|
-
const constant =
|
|
881
|
+
const coefficient = chunkUM6BVY2S_cjs.fromPolynomial({ terms: coefficientTerms, vars: namesOf2(coefficientTerms) });
|
|
882
|
+
const constant = chunkUM6BVY2S_cjs.fromPolynomial({ terms: constantTerms, vars: namesOf2(constantTerms) });
|
|
753
883
|
return {
|
|
754
884
|
kind: "roots",
|
|
755
885
|
exact: [{ kind: "div", left: { kind: "neg", operand: constant }, right: coefficient }],
|
|
@@ -765,38 +895,76 @@ function closedFormRoots(descending) {
|
|
|
765
895
|
}
|
|
766
896
|
return null;
|
|
767
897
|
}
|
|
768
|
-
function
|
|
769
|
-
const
|
|
898
|
+
function extractRationalRoots(descending) {
|
|
899
|
+
const roots = [];
|
|
770
900
|
let remaining = [...descending];
|
|
771
|
-
let
|
|
772
|
-
while (
|
|
773
|
-
|
|
774
|
-
|
|
901
|
+
let powersOfX = 0;
|
|
902
|
+
while (remaining.length > 1 && chunkUM6BVY2S_cjs.isRationalZero(remaining[remaining.length - 1])) {
|
|
903
|
+
remaining = remaining.slice(0, -1);
|
|
904
|
+
powersOfX++;
|
|
905
|
+
}
|
|
906
|
+
if (powersOfX > 0) roots.push(chunkUM6BVY2S_cjs.RATIONAL_ZERO);
|
|
907
|
+
while (remaining.length > 1) {
|
|
908
|
+
const found = rationalRoots(remaining);
|
|
909
|
+
if (found.length === 0) break;
|
|
910
|
+
for (const root of found) {
|
|
911
|
+
let multiplicity = 0;
|
|
912
|
+
while (remaining.length > 1 && chunkUM6BVY2S_cjs.isRationalZero(evaluateRational(remaining, root))) {
|
|
775
913
|
remaining = divideByRoot2(remaining, root);
|
|
914
|
+
multiplicity++;
|
|
776
915
|
}
|
|
777
|
-
|
|
916
|
+
if (multiplicity > 0) roots.push(root);
|
|
778
917
|
}
|
|
779
|
-
roots = remaining.length > 1 ? [...rationalRoots(remaining)].sort(chunk4CVLFLOB_cjs.rationalCompare) : [];
|
|
780
918
|
}
|
|
919
|
+
return { roots: roots.sort(chunkUM6BVY2S_cjs.rationalCompare), remaining };
|
|
920
|
+
}
|
|
921
|
+
function solveUnivariate(descending) {
|
|
922
|
+
const { roots, remaining } = extractRationalRoots(descending);
|
|
923
|
+
const exact = roots.map(chunkUM6BVY2S_cjs.constNode);
|
|
924
|
+
const approximate = [];
|
|
781
925
|
const leftoverDegree = remaining.length - 1;
|
|
926
|
+
const solvedDegree = descending.length - remaining.length;
|
|
927
|
+
if (leftoverDegree <= 0) return finish(exact, approximate, solvedDegree, 0, "");
|
|
782
928
|
if (leftoverDegree === 1) {
|
|
783
|
-
exact.push(
|
|
784
|
-
return
|
|
929
|
+
exact.push(chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.rationalDiv(chunkUM6BVY2S_cjs.rationalNeg(remaining[1]), remaining[0])));
|
|
930
|
+
return finish(exact, approximate, solvedDegree + 1, 0, "");
|
|
785
931
|
}
|
|
786
932
|
if (leftoverDegree === 2) {
|
|
787
|
-
|
|
788
|
-
return
|
|
789
|
-
}
|
|
790
|
-
if (leftoverDegree <= 0) {
|
|
791
|
-
return exact.length > 0 ? { kind: "roots", exact, approximate: [] } : { kind: "no-real-solutions", reason: "there is no value that satisfies this equation" };
|
|
933
|
+
exact.push(...solveQuadratic(remaining[0], remaining[1], remaining[2]));
|
|
934
|
+
return finish(exact, approximate, solvedDegree + 2, 0, "");
|
|
792
935
|
}
|
|
793
936
|
const closedForm = closedFormRoots(remaining);
|
|
794
937
|
if (closedForm !== null) {
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
938
|
+
exact.push(...closedForm.exact);
|
|
939
|
+
approximate.push(...closedForm.approximate.map(realApproximation));
|
|
940
|
+
return finish(exact, approximate, solvedDegree + leftoverDegree, 0, "");
|
|
941
|
+
}
|
|
942
|
+
const numeric = approximateRoots(remaining);
|
|
943
|
+
if (numeric !== null) {
|
|
944
|
+
approximate.push(...numeric);
|
|
945
|
+
return finish(exact, approximate, solvedDegree + leftoverDegree, 0, "");
|
|
946
|
+
}
|
|
947
|
+
return finish(
|
|
948
|
+
exact,
|
|
949
|
+
approximate,
|
|
950
|
+
solvedDegree,
|
|
951
|
+
leftoverDegree,
|
|
952
|
+
`a degree-${leftoverDegree} factor of it has no exact solution here and the numerical method did not converge on that factor`
|
|
953
|
+
);
|
|
954
|
+
}
|
|
955
|
+
function finish(exact, approximate, solvedDegree, unsolvedDegree, reason) {
|
|
956
|
+
const found = exact.length + approximate.length;
|
|
957
|
+
const incoherent = solvedDegree >= 1 && (found < 1 || found > solvedDegree);
|
|
958
|
+
if (unsolvedDegree > 0 || incoherent) {
|
|
959
|
+
return {
|
|
960
|
+
kind: "incomplete",
|
|
961
|
+
exact,
|
|
962
|
+
approximate,
|
|
963
|
+
// A distinct root can stand for several equal ones, so the count found
|
|
964
|
+
// is a lower bound on what it covers. The degree left unsolved is not.
|
|
965
|
+
missing: incoherent ? Math.max(1, solvedDegree + unsolvedDegree - found) : unsolvedDegree,
|
|
966
|
+
reason: incoherent ? `${found} root${found === 1 ? "" : "s"} were produced for a degree-${solvedDegree + unsolvedDegree} equation, which does not add up` : reason
|
|
967
|
+
};
|
|
800
968
|
}
|
|
801
969
|
return { kind: "roots", exact, approximate };
|
|
802
970
|
}
|
|
@@ -846,15 +1014,15 @@ function valueToSymbolic(v) {
|
|
|
846
1014
|
if (v.type === 13 /* Error */ || v.type === 12 /* Pending */) return null;
|
|
847
1015
|
const numeric = v.toNumber();
|
|
848
1016
|
if (!Number.isFinite(numeric)) return null;
|
|
849
|
-
return
|
|
1017
|
+
return chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.rationalFromNumber(numeric));
|
|
850
1018
|
}
|
|
851
1019
|
function symbolicToValue(node) {
|
|
852
|
-
const simplified =
|
|
853
|
-
if (simplified.kind === "const") return
|
|
854
|
-
return
|
|
1020
|
+
const simplified = chunkUM6BVY2S_cjs.simplifySymbolic(node);
|
|
1021
|
+
if (simplified.kind === "const") return chunkJMXUNXQS_cjs.numberValue(chunkUM6BVY2S_cjs.rationalToNumber(simplified.value));
|
|
1022
|
+
return chunkJMXUNXQS_cjs.symbolicValue(simplified);
|
|
855
1023
|
}
|
|
856
1024
|
function unsupported(what) {
|
|
857
|
-
return
|
|
1025
|
+
return chunkJMXUNXQS_cjs.errorValue(
|
|
858
1026
|
"SYMBOLIC_UNSUPPORTED_FUNCTION",
|
|
859
1027
|
`"${what}" cannot be applied to an expression that still contains an unknown.`
|
|
860
1028
|
);
|
|
@@ -863,7 +1031,7 @@ function symbolicPow(l, r) {
|
|
|
863
1031
|
const base = valueToSymbolic(l);
|
|
864
1032
|
const exponent = valueToSymbolic(r);
|
|
865
1033
|
if (base === null || exponent === null) return unsupported("^");
|
|
866
|
-
return symbolicToValue(
|
|
1034
|
+
return symbolicToValue(chunkUM6BVY2S_cjs.powNode(base, exponent));
|
|
867
1035
|
}
|
|
868
1036
|
function symbolicNeg(v) {
|
|
869
1037
|
const operand = valueToSymbolic(v);
|
|
@@ -873,39 +1041,49 @@ function symbolicNeg(v) {
|
|
|
873
1041
|
function symbolicBuiltin(index, args) {
|
|
874
1042
|
const nodes = [];
|
|
875
1043
|
for (const arg of args) {
|
|
876
|
-
|
|
1044
|
+
const faulted = chunkJMXUNXQS_cjs.faultedOperand(arg);
|
|
1045
|
+
if (faulted) return faulted;
|
|
877
1046
|
const node = valueToSymbolic(arg);
|
|
878
1047
|
if (node === null) return unsupported(SYMBOLIC_BUILTIN_NAMES[index] ?? `builtin ${index}`);
|
|
879
1048
|
nodes.push(node);
|
|
880
1049
|
}
|
|
881
1050
|
if (index === POW_BUILTIN_INDEX && nodes.length === 2) {
|
|
882
|
-
return symbolicToValue(
|
|
1051
|
+
return symbolicToValue(chunkUM6BVY2S_cjs.powNode(nodes[0], nodes[1]));
|
|
883
1052
|
}
|
|
884
1053
|
const name = SYMBOLIC_BUILTIN_NAMES[index];
|
|
885
1054
|
if (name === void 0) return unsupported(`builtin ${index}`);
|
|
886
|
-
return symbolicToValue(
|
|
1055
|
+
return symbolicToValue(chunkUM6BVY2S_cjs.callNode(name, nodes));
|
|
887
1056
|
}
|
|
888
1057
|
function rootToValue(root) {
|
|
889
1058
|
const value = symbolicToValue(root);
|
|
890
|
-
if (value.type === 0 /* Number */ && !Number.isInteger(value.toNumber())) return
|
|
1059
|
+
if (value.type === 0 /* Number */ && !Number.isInteger(value.toNumber())) return chunkJMXUNXQS_cjs.symbolicValue(root);
|
|
891
1060
|
return value;
|
|
892
1061
|
}
|
|
1062
|
+
function approximateRootToValue(root) {
|
|
1063
|
+
if (root.im === 0) return chunkJMXUNXQS_cjs.numberValue(root.re);
|
|
1064
|
+
return chunkJMXUNXQS_cjs.symbolicValue(chunkUM6BVY2S_cjs.complexNode(chunkUM6BVY2S_cjs.complex(chunkUM6BVY2S_cjs.rationalFromNumber(root.re), chunkUM6BVY2S_cjs.rationalFromNumber(root.im))));
|
|
1065
|
+
}
|
|
893
1066
|
function solveOutcomeToValue(outcome) {
|
|
894
1067
|
switch (outcome.kind) {
|
|
895
1068
|
case "identity":
|
|
896
|
-
return
|
|
1069
|
+
return chunkJMXUNXQS_cjs.stringValue("true for every value");
|
|
897
1070
|
case "contradiction":
|
|
898
|
-
return
|
|
899
|
-
case "no-real-solutions":
|
|
900
|
-
return chunkOC6LTXYS_cjs.stringValue(`no real solutions (${outcome.reason})`);
|
|
1071
|
+
return chunkJMXUNXQS_cjs.stringValue("no solution");
|
|
901
1072
|
case "unsupported":
|
|
902
|
-
return
|
|
1073
|
+
return chunkJMXUNXQS_cjs.errorValue("SYMBOLIC_SOLVE_UNSUPPORTED", `Cannot solve this equation: ${outcome.reason}.`);
|
|
1074
|
+
case "incomplete": {
|
|
1075
|
+
const found = outcome.exact.length + outcome.approximate.length;
|
|
1076
|
+
return chunkJMXUNXQS_cjs.errorValue(
|
|
1077
|
+
"SYMBOLIC_SOLVE_INCOMPLETE",
|
|
1078
|
+
`Only ${found} of this equation's ${found + outcome.missing} roots could be found: ${outcome.reason}.`
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
903
1081
|
case "roots": {
|
|
904
1082
|
const values = outcome.exact.map(rootToValue);
|
|
905
|
-
for (const approximate of outcome.approximate) values.push(
|
|
906
|
-
if (values.length === 0) return
|
|
1083
|
+
for (const approximate of outcome.approximate) values.push(approximateRootToValue(approximate));
|
|
1084
|
+
if (values.length === 0) return chunkJMXUNXQS_cjs.stringValue("no solution");
|
|
907
1085
|
if (values.length === 1) return values[0];
|
|
908
|
-
return
|
|
1086
|
+
return chunkJMXUNXQS_cjs.matrixValue(1, values.length, values.map((v) => v.type === 9 /* Symbolic */ ? v.value : v.toNumber()));
|
|
909
1087
|
}
|
|
910
1088
|
}
|
|
911
1089
|
}
|
|
@@ -913,7 +1091,7 @@ function solveEquationValues(lhsValue, rhsValue, variable) {
|
|
|
913
1091
|
const lhs = valueToSymbolic(lhsValue);
|
|
914
1092
|
const rhs = valueToSymbolic(rhsValue);
|
|
915
1093
|
if (lhs === null || rhs === null) {
|
|
916
|
-
return
|
|
1094
|
+
return chunkJMXUNXQS_cjs.errorValue("SYMBOLIC_NONFINITE_OPERAND", "An equation side has no exact value to solve with.");
|
|
917
1095
|
}
|
|
918
1096
|
return solveOutcomeToValue(solveForVariable(lhs, rhs, variable));
|
|
919
1097
|
}
|
|
@@ -924,15 +1102,15 @@ function unifyUom(l, r) {
|
|
|
924
1102
|
if (l.unit === r.unit) {
|
|
925
1103
|
return { lv: l.toNumber(), rv: r.toNumber(), unit: l.unit, sameMeasure: true };
|
|
926
1104
|
}
|
|
927
|
-
const lMeasure =
|
|
928
|
-
const rMeasure =
|
|
929
|
-
const isCurrency =
|
|
1105
|
+
const lMeasure = chunkPFUESQTW_cjs.getMeasure(l.unit);
|
|
1106
|
+
const rMeasure = chunkPFUESQTW_cjs.getMeasure(r.unit);
|
|
1107
|
+
const isCurrency = chunkA2N2GFCG_cjs.sharedCurrencyExchange.isCurrency(l.unit) && chunkA2N2GFCG_cjs.sharedCurrencyExchange.isCurrency(r.unit);
|
|
930
1108
|
if (lMeasure && lMeasure === rMeasure) {
|
|
931
|
-
const rvConverted =
|
|
1109
|
+
const rvConverted = chunkPFUESQTW_cjs.convertUnit(r.toNumber(), r.unit, l.unit);
|
|
932
1110
|
return { lv: l.toNumber(), rv: rvConverted, unit: l.unit, sameMeasure: true };
|
|
933
1111
|
}
|
|
934
1112
|
if (isCurrency) {
|
|
935
|
-
const rvConverted =
|
|
1113
|
+
const rvConverted = chunkA2N2GFCG_cjs.sharedCurrencyExchange.convertSync(r.toNumber(), r.unit, l.unit);
|
|
936
1114
|
if (rvConverted !== null) {
|
|
937
1115
|
return { lv: l.toNumber(), rv: rvConverted, unit: l.unit, sameMeasure: true };
|
|
938
1116
|
}
|
|
@@ -947,6 +1125,65 @@ function unifyUom(l, r) {
|
|
|
947
1125
|
}
|
|
948
1126
|
return { lv: l.toNumber(), rv: r.toNumber(), unit: void 0, sameMeasure: true };
|
|
949
1127
|
}
|
|
1128
|
+
var UNIFIED_COMPARISON_TOLERANCE = 1e-12;
|
|
1129
|
+
function largestFiniteMagnitude(a, b, c) {
|
|
1130
|
+
let scale2 = 0;
|
|
1131
|
+
if (Number.isFinite(a) && Math.abs(a) > scale2) scale2 = Math.abs(a);
|
|
1132
|
+
if (Number.isFinite(b) && Math.abs(b) > scale2) scale2 = Math.abs(b);
|
|
1133
|
+
if (Number.isFinite(c) && Math.abs(c) > scale2) scale2 = Math.abs(c);
|
|
1134
|
+
return scale2;
|
|
1135
|
+
}
|
|
1136
|
+
function compareUom(l, r) {
|
|
1137
|
+
const { lv, rv, sameMeasure } = unifyUom(l, r);
|
|
1138
|
+
if (!sameMeasure) return { lv, rv, equal: false, sameMeasure: false };
|
|
1139
|
+
if (lv === rv) return { lv, rv, equal: true, sameMeasure: true };
|
|
1140
|
+
if (!Number.isFinite(lv) || !Number.isFinite(rv)) return { lv, rv, equal: false, sameMeasure: true };
|
|
1141
|
+
const scale2 = largestFiniteMagnitude(lv, rv, r.toNumber());
|
|
1142
|
+
return { lv, rv, equal: Math.abs(lv - rv) <= scale2 * UNIFIED_COMPARISON_TOLERANCE, sameMeasure: true };
|
|
1143
|
+
}
|
|
1144
|
+
function incomparableUnitsError(l, r) {
|
|
1145
|
+
const lUnit = l.type === 6 /* Uom */ ? l.unit : void 0;
|
|
1146
|
+
const rUnit = r.type === 6 /* Uom */ ? r.unit : void 0;
|
|
1147
|
+
return chunkJMXUNXQS_cjs.errorValue("INCOMPATIBLE_UNITS", `Cannot compare incompatible units: ${lUnit ?? "?"} and ${rUnit ?? "?"}`);
|
|
1148
|
+
}
|
|
1149
|
+
function toBigIntOperand(v) {
|
|
1150
|
+
if (v.type === 2 /* BigInt */) return v.value;
|
|
1151
|
+
const n = v.toNumber();
|
|
1152
|
+
if (!Number.isInteger(n)) {
|
|
1153
|
+
const shown = Number.isNaN(n) ? "NaN" : String(n);
|
|
1154
|
+
throw chunk5KMIY374_cjs.ErrorFactory.execution(
|
|
1155
|
+
"BIGINT_INEXACT_OPERAND",
|
|
1156
|
+
`A whole-number (n) value can only be combined with another whole number, and ${shown} is not one`,
|
|
1157
|
+
{ operand: shown }
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
return BigInt(n);
|
|
1161
|
+
}
|
|
1162
|
+
function bigIntDivisionByZero() {
|
|
1163
|
+
return chunk5KMIY374_cjs.ErrorFactory.execution(
|
|
1164
|
+
"BIGINT_DIVISION_BY_ZERO",
|
|
1165
|
+
"Division by zero: a whole-number (n) division is exact integer division, which has no answer at zero, unlike 1 / 0 which is Infinity"
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
function compareBigIntOperands(l, r) {
|
|
1169
|
+
const lb = exactBigInt(l);
|
|
1170
|
+
const rb = exactBigInt(r);
|
|
1171
|
+
if (lb === null || rb === null) return null;
|
|
1172
|
+
if (lb < rb) return -1;
|
|
1173
|
+
if (lb > rb) return 1;
|
|
1174
|
+
return 0;
|
|
1175
|
+
}
|
|
1176
|
+
function exactBigInt(v) {
|
|
1177
|
+
if (v.type === 2 /* BigInt */) return v.value;
|
|
1178
|
+
const n = v.toNumber();
|
|
1179
|
+
return Number.isInteger(n) ? BigInt(n) : null;
|
|
1180
|
+
}
|
|
1181
|
+
function power(base, exponent) {
|
|
1182
|
+
if (Number.isFinite(exponent)) return Math.pow(base, exponent);
|
|
1183
|
+
if (base === 1) return 1;
|
|
1184
|
+
if (base === -1 && !Number.isNaN(exponent)) return 1;
|
|
1185
|
+
return Math.pow(base, exponent);
|
|
1186
|
+
}
|
|
950
1187
|
function binaryOp(l, r, op, bigOp, symbolicOp) {
|
|
951
1188
|
if (l.type === 13 /* Error */) return l;
|
|
952
1189
|
if (r.type === 13 /* Error */) return r;
|
|
@@ -956,59 +1193,55 @@ function binaryOp(l, r, op, bigOp, symbolicOp) {
|
|
|
956
1193
|
const left = valueToSymbolic(l);
|
|
957
1194
|
const right = valueToSymbolic(r);
|
|
958
1195
|
if (left === null || right === null) {
|
|
959
|
-
return
|
|
1196
|
+
return chunkJMXUNXQS_cjs.errorValue(
|
|
960
1197
|
"SYMBOLIC_NONFINITE_OPERAND",
|
|
961
1198
|
"A symbolic expression cannot combine with a value that has no exact number (NaN or infinity)."
|
|
962
1199
|
);
|
|
963
1200
|
}
|
|
964
1201
|
const node = { kind: symbolicOp, left, right };
|
|
965
|
-
return
|
|
1202
|
+
return chunkJMXUNXQS_cjs.symbolicValue(chunkUM6BVY2S_cjs.simplifySymbolic(node));
|
|
966
1203
|
}
|
|
967
1204
|
if (l.type === 0 /* Number */ && r.type === 0 /* Number */) {
|
|
968
|
-
return
|
|
1205
|
+
return chunkJMXUNXQS_cjs.numberValue(op(l.value, r.value));
|
|
969
1206
|
}
|
|
970
1207
|
if (l.type === 2 /* BigInt */ || r.type === 2 /* BigInt */) {
|
|
971
|
-
const lb =
|
|
972
|
-
const rb =
|
|
973
|
-
if (bigOp) return
|
|
974
|
-
return
|
|
1208
|
+
const lb = toBigIntOperand(l);
|
|
1209
|
+
const rb = toBigIntOperand(r);
|
|
1210
|
+
if (bigOp) return chunkJMXUNXQS_cjs.bigIntValue(bigOp(lb, rb));
|
|
1211
|
+
return chunkJMXUNXQS_cjs.bigIntValue(lb + rb);
|
|
975
1212
|
}
|
|
976
1213
|
if (l.type === 6 /* Uom */ || r.type === 6 /* Uom */) {
|
|
977
1214
|
const { lv, rv, unit, sameMeasure } = unifyUom(l, r);
|
|
978
|
-
if (isNaN(lv) || isNaN(rv)) return chunkOC6LTXYS_cjs.numberValue(0);
|
|
979
1215
|
if (!sameMeasure) {
|
|
980
1216
|
const lUnit = l.type === 6 /* Uom */ ? l.unit : void 0;
|
|
981
1217
|
const rUnit = r.type === 6 /* Uom */ ? r.unit : void 0;
|
|
982
|
-
return
|
|
1218
|
+
return chunkJMXUNXQS_cjs.errorValue("INCOMPATIBLE_UNITS", `Cannot combine incompatible units: ${lUnit ?? "?"} and ${rUnit ?? "?"}`);
|
|
983
1219
|
}
|
|
984
|
-
return
|
|
1220
|
+
return chunkJMXUNXQS_cjs.uomValue(op(lv, rv), unit);
|
|
985
1221
|
}
|
|
986
1222
|
if (l.type === 7 /* Matrix */ && r.type === 7 /* Matrix */) {
|
|
987
1223
|
const lm = l.value;
|
|
988
1224
|
const rm = r.value;
|
|
989
|
-
if (!
|
|
990
|
-
return
|
|
1225
|
+
if (!chunkUM6BVY2S_cjs.sameShape(lm, rm)) {
|
|
1226
|
+
return chunkJMXUNXQS_cjs.errorValue("DIMENSION_MISMATCH", `Cannot combine matrices of different shapes: ${lm.rows}x${lm.cols} and ${rm.rows}x${rm.cols}`);
|
|
991
1227
|
}
|
|
992
1228
|
const result = new Array(lm.data.length);
|
|
993
1229
|
for (let i = 0; i < lm.data.length; i++) result[i] = op(lm.data[i], rm.data[i]);
|
|
994
|
-
return
|
|
1230
|
+
return chunkJMXUNXQS_cjs.matrixValue(lm.rows, lm.cols, result);
|
|
995
1231
|
}
|
|
996
1232
|
if (l.type === 7 /* Matrix */) {
|
|
997
1233
|
const lm = l.value;
|
|
998
1234
|
const scalar = r.toNumber();
|
|
999
1235
|
const result = lm.data.map((v) => op(v, scalar));
|
|
1000
|
-
return
|
|
1236
|
+
return chunkJMXUNXQS_cjs.matrixValue(lm.rows, lm.cols, result);
|
|
1001
1237
|
}
|
|
1002
1238
|
if (r.type === 7 /* Matrix */) {
|
|
1003
1239
|
const rm = r.value;
|
|
1004
1240
|
const scalar = l.toNumber();
|
|
1005
1241
|
const result = rm.data.map((v) => op(scalar, v));
|
|
1006
|
-
return
|
|
1242
|
+
return chunkJMXUNXQS_cjs.matrixValue(rm.rows, rm.cols, result);
|
|
1007
1243
|
}
|
|
1008
|
-
|
|
1009
|
-
const rNum = r.toNumber();
|
|
1010
|
-
if (isNaN(lNum) || isNaN(rNum)) return chunkOC6LTXYS_cjs.numberValue(0);
|
|
1011
|
-
return chunkOC6LTXYS_cjs.numberValue(op(lNum, rNum));
|
|
1244
|
+
return chunkJMXUNXQS_cjs.numberValue(op(l.toNumber(), r.toNumber()));
|
|
1012
1245
|
}
|
|
1013
1246
|
|
|
1014
1247
|
// src/vm/OpRegistry.ts
|
|
@@ -1047,7 +1280,7 @@ var OpRegistry = class {
|
|
|
1047
1280
|
*/
|
|
1048
1281
|
allocateOpcode() {
|
|
1049
1282
|
if (this.nextOpcode > MAX_OPCODE) {
|
|
1050
|
-
throw
|
|
1283
|
+
throw chunk5KMIY374_cjs.ErrorFactory.config(
|
|
1051
1284
|
"OPCODE_POOL_EXHAUSTED",
|
|
1052
1285
|
`OpRegistry: dynamic opcode pool exhausted (max ${MAX_OPCODE - DYNAMIC_OPCODE_START} allocations).`
|
|
1053
1286
|
);
|
|
@@ -1059,36 +1292,36 @@ var sharedOpRegistry = new OpRegistry();
|
|
|
1059
1292
|
|
|
1060
1293
|
// src/symbolic/PartialFractions.ts
|
|
1061
1294
|
var APART_MAX_DEGREE = 12;
|
|
1062
|
-
function
|
|
1295
|
+
function multiply2(a, b) {
|
|
1063
1296
|
if (a.length === 0 || b.length === 0) return [];
|
|
1064
|
-
const product2 = new Array(a.length + b.length - 1).fill(
|
|
1297
|
+
const product2 = new Array(a.length + b.length - 1).fill(chunkUM6BVY2S_cjs.RATIONAL_ZERO);
|
|
1065
1298
|
a.forEach((left, i) => {
|
|
1066
1299
|
b.forEach((right, j) => {
|
|
1067
|
-
product2[i + j] =
|
|
1300
|
+
product2[i + j] = chunkUM6BVY2S_cjs.rationalAdd(product2[i + j], chunkUM6BVY2S_cjs.rationalMul(left, right));
|
|
1068
1301
|
});
|
|
1069
1302
|
});
|
|
1070
1303
|
return product2;
|
|
1071
1304
|
}
|
|
1072
|
-
function
|
|
1073
|
-
let result = [
|
|
1074
|
-
for (let i = 0; i < exponent; i++) result =
|
|
1305
|
+
function power2(base, exponent) {
|
|
1306
|
+
let result = [chunkUM6BVY2S_cjs.RATIONAL_ONE];
|
|
1307
|
+
for (let i = 0; i < exponent; i++) result = multiply2(result, base);
|
|
1075
1308
|
return result;
|
|
1076
1309
|
}
|
|
1077
1310
|
function scale(coefficients, factor) {
|
|
1078
|
-
return coefficients.map((coefficient) =>
|
|
1311
|
+
return coefficients.map((coefficient) => chunkUM6BVY2S_cjs.rationalDiv(coefficient, factor));
|
|
1079
1312
|
}
|
|
1080
1313
|
function denominatorFactors(ascending, variable) {
|
|
1081
1314
|
const factors = [];
|
|
1082
1315
|
let lowest = 0;
|
|
1083
|
-
while (lowest < ascending.length &&
|
|
1084
|
-
if (lowest > 0) factors.push({ base: [
|
|
1316
|
+
while (lowest < ascending.length && chunkUM6BVY2S_cjs.isRationalZero(ascending[lowest])) lowest++;
|
|
1317
|
+
if (lowest > 0) factors.push({ base: [chunkUM6BVY2S_cjs.RATIONAL_ZERO, chunkUM6BVY2S_cjs.RATIONAL_ONE], power: lowest });
|
|
1085
1318
|
const remaining = ascending.slice(lowest);
|
|
1086
1319
|
if (remaining.length > 1) {
|
|
1087
1320
|
const factorization = factorUnivariate([...remaining].reverse(), variable);
|
|
1088
1321
|
for (const factor of factorization.factors) {
|
|
1089
|
-
const polynomial =
|
|
1322
|
+
const polynomial = chunkUM6BVY2S_cjs.toPolynomial(factor.base);
|
|
1090
1323
|
if (polynomial === null) return null;
|
|
1091
|
-
factors.push({ base: [...
|
|
1324
|
+
factors.push({ base: [...chunkUM6BVY2S_cjs.polyCoefficients(polynomial, variable)], power: factor.power });
|
|
1092
1325
|
}
|
|
1093
1326
|
}
|
|
1094
1327
|
return factors.length > 0 ? factors : null;
|
|
@@ -1106,19 +1339,19 @@ function enumerateUnknowns(factors) {
|
|
|
1106
1339
|
return unknowns;
|
|
1107
1340
|
}
|
|
1108
1341
|
function unknownColumn(unknown, factors, denominator) {
|
|
1109
|
-
const divisor =
|
|
1110
|
-
const { quotient, remainder } =
|
|
1111
|
-
if (!
|
|
1112
|
-
const shift = new Array(unknown.degree).fill(
|
|
1113
|
-
shift.push(
|
|
1114
|
-
return
|
|
1342
|
+
const divisor = power2(factors[unknown.factor].base, unknown.power);
|
|
1343
|
+
const { quotient, remainder } = chunkUM6BVY2S_cjs.polynomialDivide(denominator, divisor);
|
|
1344
|
+
if (!chunkUM6BVY2S_cjs.isZeroPolynomial(remainder)) return null;
|
|
1345
|
+
const shift = new Array(unknown.degree).fill(chunkUM6BVY2S_cjs.RATIONAL_ZERO);
|
|
1346
|
+
shift.push(chunkUM6BVY2S_cjs.RATIONAL_ONE);
|
|
1347
|
+
return multiply2(quotient, shift);
|
|
1115
1348
|
}
|
|
1116
1349
|
function solveLinearSystem(matrix, target) {
|
|
1117
1350
|
const size = target.length;
|
|
1118
1351
|
for (let column = 0; column < size; column++) {
|
|
1119
1352
|
let pivot = -1;
|
|
1120
1353
|
for (let row = column; row < size; row++) {
|
|
1121
|
-
if (!
|
|
1354
|
+
if (!chunkUM6BVY2S_cjs.isRationalZero(matrix[row][column])) {
|
|
1122
1355
|
pivot = row;
|
|
1123
1356
|
break;
|
|
1124
1357
|
}
|
|
@@ -1127,21 +1360,21 @@ function solveLinearSystem(matrix, target) {
|
|
|
1127
1360
|
[matrix[column], matrix[pivot]] = [matrix[pivot], matrix[column]];
|
|
1128
1361
|
[target[column], target[pivot]] = [target[pivot], target[column]];
|
|
1129
1362
|
for (let row = 0; row < size; row++) {
|
|
1130
|
-
if (row === column ||
|
|
1131
|
-
const factor =
|
|
1363
|
+
if (row === column || chunkUM6BVY2S_cjs.isRationalZero(matrix[row][column])) continue;
|
|
1364
|
+
const factor = chunkUM6BVY2S_cjs.rationalDiv(matrix[row][column], matrix[column][column]);
|
|
1132
1365
|
for (let k = column; k < size; k++) {
|
|
1133
|
-
matrix[row][k] =
|
|
1366
|
+
matrix[row][k] = chunkUM6BVY2S_cjs.rationalSub(matrix[row][k], chunkUM6BVY2S_cjs.rationalMul(factor, matrix[column][k]));
|
|
1134
1367
|
}
|
|
1135
|
-
target[row] =
|
|
1368
|
+
target[row] = chunkUM6BVY2S_cjs.rationalSub(target[row], chunkUM6BVY2S_cjs.rationalMul(factor, target[column]));
|
|
1136
1369
|
}
|
|
1137
1370
|
}
|
|
1138
|
-
return target.map((value, index) =>
|
|
1371
|
+
return target.map((value, index) => chunkUM6BVY2S_cjs.rationalDiv(value, matrix[index][index]));
|
|
1139
1372
|
}
|
|
1140
1373
|
function partialFractions(numerator, denominator, variable) {
|
|
1141
1374
|
if (denominator.length < 2 || denominator.length - 1 > APART_MAX_DEGREE) return null;
|
|
1142
|
-
const shared =
|
|
1143
|
-
const reducedNumerator = shared.length > 1 ?
|
|
1144
|
-
const reducedDenominator = shared.length > 1 ?
|
|
1375
|
+
const shared = chunkUM6BVY2S_cjs.coefficientGcd(numerator, denominator);
|
|
1376
|
+
const reducedNumerator = shared.length > 1 ? chunkUM6BVY2S_cjs.polynomialDivide(numerator, shared).quotient : [...numerator];
|
|
1377
|
+
const reducedDenominator = shared.length > 1 ? chunkUM6BVY2S_cjs.polynomialDivide(denominator, shared).quotient : [...denominator];
|
|
1145
1378
|
if (reducedDenominator.length === 1) {
|
|
1146
1379
|
return { polynomial: scale(reducedNumerator, reducedDenominator[0]), terms: [] };
|
|
1147
1380
|
}
|
|
@@ -1149,8 +1382,8 @@ function partialFractions(numerator, denominator, variable) {
|
|
|
1149
1382
|
const leading = reducedDenominator[reducedDenominator.length - 1];
|
|
1150
1383
|
const monicDenominator = scale(reducedDenominator, leading);
|
|
1151
1384
|
const scaledNumerator = scale(reducedNumerator, leading);
|
|
1152
|
-
const { quotient, remainder } =
|
|
1153
|
-
if (
|
|
1385
|
+
const { quotient, remainder } = chunkUM6BVY2S_cjs.polynomialDivide(scaledNumerator, monicDenominator);
|
|
1386
|
+
if (chunkUM6BVY2S_cjs.isZeroPolynomial(remainder)) return { polynomial: quotient, terms: [] };
|
|
1154
1387
|
const factors = denominatorFactors(monicDenominator, variable);
|
|
1155
1388
|
if (factors === null) return null;
|
|
1156
1389
|
const terms = solveForNumerators(factors, monicDenominator, remainder);
|
|
@@ -1168,10 +1401,10 @@ function solveForNumerators(factors, denominator, remainder) {
|
|
|
1168
1401
|
}
|
|
1169
1402
|
const matrix = [];
|
|
1170
1403
|
for (let row = 0; row < size; row++) {
|
|
1171
|
-
matrix.push(columns.map((column) => column[row] ??
|
|
1404
|
+
matrix.push(columns.map((column) => column[row] ?? chunkUM6BVY2S_cjs.RATIONAL_ZERO));
|
|
1172
1405
|
}
|
|
1173
1406
|
const target = [];
|
|
1174
|
-
for (let row = 0; row < size; row++) target.push(remainder[row] ??
|
|
1407
|
+
for (let row = 0; row < size; row++) target.push(remainder[row] ?? chunkUM6BVY2S_cjs.RATIONAL_ZERO);
|
|
1175
1408
|
const solution = solveLinearSystem(matrix, target);
|
|
1176
1409
|
if (solution === null) return null;
|
|
1177
1410
|
return groupSolution(unknowns, solution, factors);
|
|
@@ -1187,8 +1420,8 @@ function groupSolution(unknowns, solution, factors) {
|
|
|
1187
1420
|
const terms = [];
|
|
1188
1421
|
for (const [key, coefficients] of grouped) {
|
|
1189
1422
|
const [factorIndex, termPower] = key.split(":").map(Number);
|
|
1190
|
-
const filled = [...coefficients].map((value) => value ??
|
|
1191
|
-
if (filled.every(
|
|
1423
|
+
const filled = [...coefficients].map((value) => value ?? chunkUM6BVY2S_cjs.RATIONAL_ZERO);
|
|
1424
|
+
if (filled.every(chunkUM6BVY2S_cjs.isRationalZero)) continue;
|
|
1192
1425
|
terms.push({ numerator: filled, base: factors[factorIndex].base, power: termPower });
|
|
1193
1426
|
}
|
|
1194
1427
|
return terms;
|
|
@@ -1196,11 +1429,11 @@ function groupSolution(unknowns, solution, factors) {
|
|
|
1196
1429
|
function coefficientsToNode2(coefficients, variable) {
|
|
1197
1430
|
const terms = /* @__PURE__ */ new Map();
|
|
1198
1431
|
coefficients.forEach((coefficient, exponent) => {
|
|
1199
|
-
if (
|
|
1432
|
+
if (chunkUM6BVY2S_cjs.isRationalZero(coefficient)) return;
|
|
1200
1433
|
terms.set(exponent === 0 ? "" : exponent === 1 ? variable : `${variable}^${exponent}`, coefficient);
|
|
1201
1434
|
});
|
|
1202
|
-
if (terms.size === 0) return
|
|
1203
|
-
return
|
|
1435
|
+
if (terms.size === 0) return chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.RATIONAL_ZERO);
|
|
1436
|
+
return chunkUM6BVY2S_cjs.fromPolynomial({ terms, vars: coefficients.length > 1 ? [variable] : [] });
|
|
1204
1437
|
}
|
|
1205
1438
|
function apartSymbolic(node) {
|
|
1206
1439
|
const parts = asRationalFunction(node);
|
|
@@ -1210,9 +1443,9 @@ function apartSymbolic(node) {
|
|
|
1210
1443
|
let result = decomposition.polynomial.length > 0 ? coefficientsToNode2(decomposition.polynomial, parts.variable) : null;
|
|
1211
1444
|
for (const term of decomposition.terms) {
|
|
1212
1445
|
const base = coefficientsToNode2(term.base, parts.variable);
|
|
1213
|
-
const denominator = term.power === 1 ? base :
|
|
1446
|
+
const denominator = term.power === 1 ? base : chunkUM6BVY2S_cjs.powNode(base, chunkUM6BVY2S_cjs.constNode({ n: BigInt(term.power), d: 1n }));
|
|
1214
1447
|
const negative = isNegativeNumerator(term.numerator);
|
|
1215
|
-
const numerator = negative ? term.numerator.map((coefficient) =>
|
|
1448
|
+
const numerator = negative ? term.numerator.map((coefficient) => chunkUM6BVY2S_cjs.rationalNeg(coefficient)) : term.numerator;
|
|
1216
1449
|
const piece = {
|
|
1217
1450
|
kind: "div",
|
|
1218
1451
|
left: coefficientsToNode2(numerator, parts.variable),
|
|
@@ -1221,22 +1454,22 @@ function apartSymbolic(node) {
|
|
|
1221
1454
|
if (result === null) result = negative ? { kind: "neg", operand: piece } : piece;
|
|
1222
1455
|
else result = { kind: negative ? "sub" : "add", left: result, right: piece };
|
|
1223
1456
|
}
|
|
1224
|
-
return result === null ? node :
|
|
1457
|
+
return result === null ? node : chunkUM6BVY2S_cjs.simplifySymbolic(result);
|
|
1225
1458
|
}
|
|
1226
1459
|
function isNegativeNumerator(coefficients) {
|
|
1227
1460
|
return coefficients.some((coefficient) => coefficient.n < 0n) && coefficients.every((coefficient) => coefficient.n <= 0n);
|
|
1228
1461
|
}
|
|
1229
1462
|
function asRationalFunction(node) {
|
|
1230
1463
|
if (node.kind !== "div") return null;
|
|
1231
|
-
const numerator =
|
|
1232
|
-
const denominator =
|
|
1464
|
+
const numerator = chunkUM6BVY2S_cjs.toPolynomial(node.left);
|
|
1465
|
+
const denominator = chunkUM6BVY2S_cjs.toPolynomial(node.right);
|
|
1233
1466
|
if (numerator === null || denominator === null) return null;
|
|
1234
|
-
const variable =
|
|
1467
|
+
const variable = chunkUM6BVY2S_cjs.polyUnivariateVar(denominator);
|
|
1235
1468
|
if (variable === null) return null;
|
|
1236
1469
|
if (numerator.vars.some((name) => name !== variable)) return null;
|
|
1237
1470
|
return {
|
|
1238
|
-
numerator:
|
|
1239
|
-
denominator:
|
|
1471
|
+
numerator: chunkUM6BVY2S_cjs.polyCoefficients(numerator, variable),
|
|
1472
|
+
denominator: chunkUM6BVY2S_cjs.polyCoefficients(denominator, variable),
|
|
1240
1473
|
variable
|
|
1241
1474
|
};
|
|
1242
1475
|
}
|
|
@@ -1244,66 +1477,66 @@ function asRationalFunction(node) {
|
|
|
1244
1477
|
// src/symbolic/Derivative.ts
|
|
1245
1478
|
var DERIVATIVE_MAX_ORDER = 16;
|
|
1246
1479
|
function zero() {
|
|
1247
|
-
return
|
|
1480
|
+
return chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.RATIONAL_ZERO);
|
|
1248
1481
|
}
|
|
1249
1482
|
function one() {
|
|
1250
|
-
return
|
|
1483
|
+
return chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.RATIONAL_ONE);
|
|
1251
1484
|
}
|
|
1252
1485
|
function functionDerivative(name, argument) {
|
|
1253
1486
|
switch (name) {
|
|
1254
1487
|
case "sin":
|
|
1255
|
-
return
|
|
1488
|
+
return chunkUM6BVY2S_cjs.callNode("cos", [argument]);
|
|
1256
1489
|
case "cos":
|
|
1257
|
-
return { kind: "neg", operand:
|
|
1490
|
+
return { kind: "neg", operand: chunkUM6BVY2S_cjs.callNode("sin", [argument]) };
|
|
1258
1491
|
case "tan":
|
|
1259
|
-
return { kind: "div", left: one(), right:
|
|
1492
|
+
return { kind: "div", left: one(), right: chunkUM6BVY2S_cjs.powNode(chunkUM6BVY2S_cjs.callNode("cos", [argument]), chunkUM6BVY2S_cjs.constNode(2)) };
|
|
1260
1493
|
case "exp":
|
|
1261
|
-
return
|
|
1494
|
+
return chunkUM6BVY2S_cjs.callNode("exp", [argument]);
|
|
1262
1495
|
case "log":
|
|
1263
1496
|
return { kind: "div", left: one(), right: argument };
|
|
1264
1497
|
case "sqrt":
|
|
1265
1498
|
return {
|
|
1266
1499
|
kind: "div",
|
|
1267
1500
|
left: one(),
|
|
1268
|
-
right: { kind: "mul", left:
|
|
1501
|
+
right: { kind: "mul", left: chunkUM6BVY2S_cjs.constNode(2), right: chunkUM6BVY2S_cjs.callNode("sqrt", [argument]) }
|
|
1269
1502
|
};
|
|
1270
1503
|
case "asin":
|
|
1271
|
-
return { kind: "div", left: one(), right:
|
|
1504
|
+
return { kind: "div", left: one(), right: chunkUM6BVY2S_cjs.callNode("sqrt", [oneMinusSquare(argument)]) };
|
|
1272
1505
|
case "acos":
|
|
1273
|
-
return { kind: "neg", operand: { kind: "div", left: one(), right:
|
|
1506
|
+
return { kind: "neg", operand: { kind: "div", left: one(), right: chunkUM6BVY2S_cjs.callNode("sqrt", [oneMinusSquare(argument)]) } };
|
|
1274
1507
|
case "atan":
|
|
1275
1508
|
return { kind: "div", left: one(), right: onePlusSquare(argument) };
|
|
1276
1509
|
case "sinh":
|
|
1277
|
-
return
|
|
1510
|
+
return chunkUM6BVY2S_cjs.callNode("cosh", [argument]);
|
|
1278
1511
|
case "cosh":
|
|
1279
|
-
return
|
|
1512
|
+
return chunkUM6BVY2S_cjs.callNode("sinh", [argument]);
|
|
1280
1513
|
case "tanh":
|
|
1281
|
-
return { kind: "div", left: one(), right:
|
|
1514
|
+
return { kind: "div", left: one(), right: chunkUM6BVY2S_cjs.powNode(chunkUM6BVY2S_cjs.callNode("cosh", [argument]), chunkUM6BVY2S_cjs.constNode(2)) };
|
|
1282
1515
|
case "abs":
|
|
1283
|
-
return
|
|
1516
|
+
return chunkUM6BVY2S_cjs.callNode("sign", [argument]);
|
|
1284
1517
|
default:
|
|
1285
1518
|
return null;
|
|
1286
1519
|
}
|
|
1287
1520
|
}
|
|
1288
1521
|
function oneMinusSquare(argument) {
|
|
1289
|
-
return { kind: "sub", left: one(), right:
|
|
1522
|
+
return { kind: "sub", left: one(), right: chunkUM6BVY2S_cjs.powNode(argument, chunkUM6BVY2S_cjs.constNode(2)) };
|
|
1290
1523
|
}
|
|
1291
1524
|
function onePlusSquare(argument) {
|
|
1292
|
-
return { kind: "add", left: one(), right:
|
|
1525
|
+
return { kind: "add", left: one(), right: chunkUM6BVY2S_cjs.powNode(argument, chunkUM6BVY2S_cjs.constNode(2)) };
|
|
1293
1526
|
}
|
|
1294
|
-
function
|
|
1527
|
+
function differentiate2(node, variable, order = 1) {
|
|
1295
1528
|
if (order < 0 || !Number.isInteger(order)) {
|
|
1296
|
-
throw
|
|
1529
|
+
throw chunk5KMIY374_cjs.ErrorFactory.execution("SYMBOLIC_DERIVATIVE_ORDER_LIMIT", "A derivative order must be a whole number, at least zero.");
|
|
1297
1530
|
}
|
|
1298
1531
|
if (order > DERIVATIVE_MAX_ORDER) {
|
|
1299
|
-
throw
|
|
1532
|
+
throw chunk5KMIY374_cjs.ErrorFactory.execution(
|
|
1300
1533
|
"SYMBOLIC_DERIVATIVE_ORDER_LIMIT",
|
|
1301
1534
|
`A derivative order above ${DERIVATIVE_MAX_ORDER} is not supported.`,
|
|
1302
1535
|
{ limit: DERIVATIVE_MAX_ORDER }
|
|
1303
1536
|
);
|
|
1304
1537
|
}
|
|
1305
|
-
let result =
|
|
1306
|
-
for (let i = 0; i < order; i++) result =
|
|
1538
|
+
let result = chunkUM6BVY2S_cjs.simplifySymbolic(node);
|
|
1539
|
+
for (let i = 0; i < order; i++) result = chunkUM6BVY2S_cjs.simplifySymbolic(derive(result, variable));
|
|
1307
1540
|
return result;
|
|
1308
1541
|
}
|
|
1309
1542
|
function derive(node, variable) {
|
|
@@ -1333,7 +1566,7 @@ function derive(node, variable) {
|
|
|
1333
1566
|
left: { kind: "mul", left: derive(node.left, variable), right: node.right },
|
|
1334
1567
|
right: { kind: "mul", left: node.left, right: derive(node.right, variable) }
|
|
1335
1568
|
},
|
|
1336
|
-
right:
|
|
1569
|
+
right: chunkUM6BVY2S_cjs.powNode(node.right, chunkUM6BVY2S_cjs.constNode(2))
|
|
1337
1570
|
};
|
|
1338
1571
|
case "pow":
|
|
1339
1572
|
return derivePow(node, variable);
|
|
@@ -1347,79 +1580,79 @@ function derive(node, variable) {
|
|
|
1347
1580
|
}
|
|
1348
1581
|
function derivePow(node, variable) {
|
|
1349
1582
|
if (node.exponent.kind === "const") {
|
|
1350
|
-
const reduced =
|
|
1583
|
+
const reduced = chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.rationalSub(node.exponent.value, chunkUM6BVY2S_cjs.RATIONAL_ONE));
|
|
1351
1584
|
return {
|
|
1352
1585
|
kind: "mul",
|
|
1353
|
-
left: { kind: "mul", left: node.exponent, right:
|
|
1586
|
+
left: { kind: "mul", left: node.exponent, right: chunkUM6BVY2S_cjs.powNode(node.base, reduced) },
|
|
1354
1587
|
right: derive(node.base, variable)
|
|
1355
1588
|
};
|
|
1356
1589
|
}
|
|
1357
1590
|
if (node.base.kind === "const" && node.base.value.n > 0n) {
|
|
1358
1591
|
return {
|
|
1359
1592
|
kind: "mul",
|
|
1360
|
-
left: { kind: "mul", left: node, right:
|
|
1593
|
+
left: { kind: "mul", left: node, right: chunkUM6BVY2S_cjs.callNode("log", [node.base]) },
|
|
1361
1594
|
right: derive(node.exponent, variable)
|
|
1362
1595
|
};
|
|
1363
1596
|
}
|
|
1364
1597
|
return unevaluated(node, variable);
|
|
1365
1598
|
}
|
|
1366
1599
|
function unevaluated(node, variable) {
|
|
1367
|
-
return
|
|
1600
|
+
return chunkUM6BVY2S_cjs.callNode("der", [node, chunkUM6BVY2S_cjs.varNode(variable)]);
|
|
1368
1601
|
}
|
|
1369
1602
|
|
|
1370
1603
|
// src/symbolic/Integral.ts
|
|
1371
1604
|
function asLinear(node, variable) {
|
|
1372
|
-
const polynomial =
|
|
1605
|
+
const polynomial = chunkUM6BVY2S_cjs.toPolynomial(node);
|
|
1373
1606
|
if (polynomial === null) return null;
|
|
1374
1607
|
const others = polynomial.vars.filter((name) => name !== variable);
|
|
1375
1608
|
if (others.length > 0) return null;
|
|
1376
|
-
if (
|
|
1377
|
-
const ascending =
|
|
1609
|
+
if (chunkUM6BVY2S_cjs.polyDegree(polynomial, variable) > 1) return null;
|
|
1610
|
+
const ascending = chunkUM6BVY2S_cjs.polyCoefficients(polynomial, variable);
|
|
1378
1611
|
const intercept = ascending[0] ?? { n: 0n, d: 1n };
|
|
1379
1612
|
const slope = ascending[1] ?? { n: 0n, d: 1n };
|
|
1380
|
-
return
|
|
1613
|
+
return chunkUM6BVY2S_cjs.isRationalZero(slope) ? null : { slope, intercept };
|
|
1381
1614
|
}
|
|
1382
1615
|
function integratePolynomial(node, variable) {
|
|
1383
|
-
const polynomial =
|
|
1616
|
+
const polynomial = chunkUM6BVY2S_cjs.toPolynomial(node);
|
|
1384
1617
|
if (polynomial === null) return null;
|
|
1385
1618
|
const others = polynomial.vars.filter((name) => name !== variable);
|
|
1386
1619
|
if (others.length > 0) {
|
|
1387
1620
|
return { ok: false, reason: `it involves more than one unknown (${others.join(", ")})` };
|
|
1388
1621
|
}
|
|
1389
|
-
const ascending =
|
|
1390
|
-
let result =
|
|
1391
|
-
ascending.forEach((coeff,
|
|
1392
|
-
if (
|
|
1393
|
-
const nextPower =
|
|
1394
|
-
const scaled =
|
|
1622
|
+
const ascending = chunkUM6BVY2S_cjs.polyCoefficients(polynomial, variable);
|
|
1623
|
+
let result = chunkUM6BVY2S_cjs.constNode(0);
|
|
1624
|
+
ascending.forEach((coeff, power3) => {
|
|
1625
|
+
if (chunkUM6BVY2S_cjs.isRationalZero(coeff)) return;
|
|
1626
|
+
const nextPower = power3 + 1;
|
|
1627
|
+
const scaled = chunkUM6BVY2S_cjs.rationalDiv(coeff, { n: BigInt(nextPower), d: 1n });
|
|
1395
1628
|
const term = {
|
|
1396
1629
|
kind: "mul",
|
|
1397
|
-
left:
|
|
1398
|
-
right: nextPower === 1 ?
|
|
1630
|
+
left: chunkUM6BVY2S_cjs.constNode(scaled),
|
|
1631
|
+
right: nextPower === 1 ? chunkUM6BVY2S_cjs.varNode(variable) : chunkUM6BVY2S_cjs.powNode(chunkUM6BVY2S_cjs.varNode(variable), chunkUM6BVY2S_cjs.constNode(nextPower))
|
|
1399
1632
|
};
|
|
1400
1633
|
result = { kind: "add", left: result, right: term };
|
|
1401
1634
|
});
|
|
1402
|
-
return { ok: true, value:
|
|
1635
|
+
return { ok: true, value: chunkUM6BVY2S_cjs.simplifySymbolic(result) };
|
|
1403
1636
|
}
|
|
1404
1637
|
function integrateStandardForm(node, variable) {
|
|
1405
1638
|
if (node.kind !== "call" || node.args.length !== 1) return null;
|
|
1406
1639
|
const linear = asLinear(node.args[0], variable);
|
|
1407
1640
|
if (linear === null) return null;
|
|
1408
1641
|
const inner = node.args[0];
|
|
1409
|
-
const divideBySlope = (value) =>
|
|
1642
|
+
const divideBySlope = (value) => chunkUM6BVY2S_cjs.simplifySymbolic({ kind: "div", left: value, right: chunkUM6BVY2S_cjs.constNode(linear.slope) });
|
|
1410
1643
|
switch (node.name) {
|
|
1411
1644
|
case "exp":
|
|
1412
|
-
return { ok: true, value: divideBySlope(
|
|
1645
|
+
return { ok: true, value: divideBySlope(chunkUM6BVY2S_cjs.callNode("exp", [inner])) };
|
|
1413
1646
|
case "sin":
|
|
1414
|
-
return { ok: true, value: divideBySlope({ kind: "neg", operand:
|
|
1647
|
+
return { ok: true, value: divideBySlope({ kind: "neg", operand: chunkUM6BVY2S_cjs.callNode("cos", [inner]) }) };
|
|
1415
1648
|
case "cos":
|
|
1416
|
-
return { ok: true, value: divideBySlope(
|
|
1649
|
+
return { ok: true, value: divideBySlope(chunkUM6BVY2S_cjs.callNode("sin", [inner])) };
|
|
1417
1650
|
case "log":
|
|
1418
1651
|
return {
|
|
1419
1652
|
ok: true,
|
|
1420
1653
|
value: divideBySlope({
|
|
1421
1654
|
kind: "sub",
|
|
1422
|
-
left: { kind: "mul", left: inner, right:
|
|
1655
|
+
left: { kind: "mul", left: inner, right: chunkUM6BVY2S_cjs.callNode("log", [inner]) },
|
|
1423
1656
|
right: inner
|
|
1424
1657
|
})
|
|
1425
1658
|
};
|
|
@@ -1434,18 +1667,18 @@ function integrateReciprocalForms(node, variable) {
|
|
|
1434
1667
|
if (linear !== null) {
|
|
1435
1668
|
return {
|
|
1436
1669
|
ok: true,
|
|
1437
|
-
value:
|
|
1670
|
+
value: chunkUM6BVY2S_cjs.simplifySymbolic({
|
|
1438
1671
|
kind: "div",
|
|
1439
|
-
left:
|
|
1440
|
-
right:
|
|
1672
|
+
left: chunkUM6BVY2S_cjs.callNode("log", [node.right]),
|
|
1673
|
+
right: chunkUM6BVY2S_cjs.constNode(linear.slope)
|
|
1441
1674
|
})
|
|
1442
1675
|
};
|
|
1443
1676
|
}
|
|
1444
|
-
const denominator =
|
|
1677
|
+
const denominator = chunkUM6BVY2S_cjs.toPolynomial(node.right);
|
|
1445
1678
|
if (denominator !== null && denominator.vars.length === 1 && denominator.vars[0] === variable) {
|
|
1446
|
-
const ascending =
|
|
1447
|
-
const isOnePlusSquare = ascending.length === 3 && isRationalOneNode(ascending[0]) &&
|
|
1448
|
-
if (isOnePlusSquare) return { ok: true, value:
|
|
1679
|
+
const ascending = chunkUM6BVY2S_cjs.polyCoefficients(denominator, variable);
|
|
1680
|
+
const isOnePlusSquare = ascending.length === 3 && isRationalOneNode(ascending[0]) && chunkUM6BVY2S_cjs.isRationalZero(ascending[1]) && isRationalOneNode(ascending[2]);
|
|
1681
|
+
if (isOnePlusSquare) return { ok: true, value: chunkUM6BVY2S_cjs.callNode("atan", [chunkUM6BVY2S_cjs.varNode(variable)]) };
|
|
1449
1682
|
}
|
|
1450
1683
|
return null;
|
|
1451
1684
|
}
|
|
@@ -1457,7 +1690,7 @@ function integrateRationalFunction(node, variable) {
|
|
|
1457
1690
|
if (parts === null || parts.variable !== variable) return null;
|
|
1458
1691
|
const decomposition = partialFractions(parts.numerator, parts.denominator, variable);
|
|
1459
1692
|
if (decomposition === null) return null;
|
|
1460
|
-
let result = decomposition.polynomial.length > 0 ? polynomialAntiderivative(decomposition.polynomial, variable) :
|
|
1693
|
+
let result = decomposition.polynomial.length > 0 ? polynomialAntiderivative(decomposition.polynomial, variable) : chunkUM6BVY2S_cjs.constNode(0);
|
|
1461
1694
|
for (const term of decomposition.terms) {
|
|
1462
1695
|
const piece = integrateTerm(term, variable);
|
|
1463
1696
|
if (piece === null) {
|
|
@@ -1468,72 +1701,72 @@ function integrateRationalFunction(node, variable) {
|
|
|
1468
1701
|
}
|
|
1469
1702
|
result = { kind: "add", left: result, right: piece };
|
|
1470
1703
|
}
|
|
1471
|
-
return { ok: true, value:
|
|
1704
|
+
return { ok: true, value: chunkUM6BVY2S_cjs.simplifySymbolic(result) };
|
|
1472
1705
|
}
|
|
1473
1706
|
function integrateTerm(term, variable) {
|
|
1474
1707
|
const baseDegree = term.base.length - 1;
|
|
1475
1708
|
const base = coefficientsToNode2(term.base, variable);
|
|
1476
1709
|
if (baseDegree === 1) {
|
|
1477
|
-
const coefficient = term.numerator[0] ??
|
|
1710
|
+
const coefficient = term.numerator[0] ?? chunkUM6BVY2S_cjs.RATIONAL_ZERO;
|
|
1478
1711
|
if (term.power === 1) {
|
|
1479
|
-
return { kind: "mul", left:
|
|
1712
|
+
return { kind: "mul", left: chunkUM6BVY2S_cjs.constNode(coefficient), right: chunkUM6BVY2S_cjs.callNode("log", [base]) };
|
|
1480
1713
|
}
|
|
1481
1714
|
const reduced = term.power - 1;
|
|
1482
|
-
const scaled =
|
|
1715
|
+
const scaled = chunkUM6BVY2S_cjs.rationalDiv(coefficient, { n: BigInt(-reduced), d: 1n });
|
|
1483
1716
|
return {
|
|
1484
1717
|
kind: "div",
|
|
1485
|
-
left:
|
|
1486
|
-
right:
|
|
1718
|
+
left: chunkUM6BVY2S_cjs.constNode(scaled),
|
|
1719
|
+
right: chunkUM6BVY2S_cjs.powNode(base, chunkUM6BVY2S_cjs.constNode({ n: BigInt(reduced), d: 1n }))
|
|
1487
1720
|
};
|
|
1488
1721
|
}
|
|
1489
1722
|
if (baseDegree !== 2 || term.power !== 1) return null;
|
|
1490
1723
|
return integrateQuadraticTerm(term, variable, base);
|
|
1491
1724
|
}
|
|
1492
1725
|
function integrateQuadraticTerm(term, variable, base) {
|
|
1493
|
-
const constant = term.numerator[0] ??
|
|
1494
|
-
const linear = term.numerator[1] ??
|
|
1726
|
+
const constant = term.numerator[0] ?? chunkUM6BVY2S_cjs.RATIONAL_ZERO;
|
|
1727
|
+
const linear = term.numerator[1] ?? chunkUM6BVY2S_cjs.RATIONAL_ZERO;
|
|
1495
1728
|
const [q, p] = term.base;
|
|
1496
1729
|
const half = { n: 1n, d: 2n };
|
|
1497
|
-
const halfP =
|
|
1730
|
+
const halfP = chunkUM6BVY2S_cjs.rationalMul(p, half);
|
|
1498
1731
|
const logarithm = {
|
|
1499
1732
|
kind: "mul",
|
|
1500
|
-
left:
|
|
1501
|
-
right:
|
|
1733
|
+
left: chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.rationalMul(linear, half)),
|
|
1734
|
+
right: chunkUM6BVY2S_cjs.callNode("log", [base])
|
|
1502
1735
|
};
|
|
1503
|
-
const leftover =
|
|
1504
|
-
if (
|
|
1505
|
-
const width =
|
|
1736
|
+
const leftover = chunkUM6BVY2S_cjs.rationalSub(constant, chunkUM6BVY2S_cjs.rationalMul(linear, halfP));
|
|
1737
|
+
if (chunkUM6BVY2S_cjs.isRationalZero(leftover)) return logarithm;
|
|
1738
|
+
const width = chunkUM6BVY2S_cjs.surdNode(chunkUM6BVY2S_cjs.rationalSub(q, chunkUM6BVY2S_cjs.rationalMul(halfP, halfP)));
|
|
1506
1739
|
const shifted = {
|
|
1507
1740
|
kind: "add",
|
|
1508
|
-
left:
|
|
1509
|
-
right:
|
|
1741
|
+
left: chunkUM6BVY2S_cjs.varNode(variable),
|
|
1742
|
+
right: chunkUM6BVY2S_cjs.constNode(halfP)
|
|
1510
1743
|
};
|
|
1511
1744
|
const arctangent = {
|
|
1512
1745
|
kind: "mul",
|
|
1513
|
-
left: { kind: "div", left:
|
|
1514
|
-
right:
|
|
1746
|
+
left: { kind: "div", left: chunkUM6BVY2S_cjs.constNode(leftover), right: width },
|
|
1747
|
+
right: chunkUM6BVY2S_cjs.callNode("atan", [{ kind: "div", left: shifted, right: width }])
|
|
1515
1748
|
};
|
|
1516
|
-
return
|
|
1749
|
+
return chunkUM6BVY2S_cjs.isRationalZero(linear) ? arctangent : { kind: "add", left: logarithm, right: arctangent };
|
|
1517
1750
|
}
|
|
1518
1751
|
function polynomialAntiderivative(ascending, variable) {
|
|
1519
|
-
let result =
|
|
1752
|
+
let result = chunkUM6BVY2S_cjs.constNode(0);
|
|
1520
1753
|
ascending.forEach((coeff, exponent) => {
|
|
1521
|
-
if (
|
|
1754
|
+
if (chunkUM6BVY2S_cjs.isRationalZero(coeff)) return;
|
|
1522
1755
|
const nextPower = exponent + 1;
|
|
1523
|
-
const scaled =
|
|
1756
|
+
const scaled = chunkUM6BVY2S_cjs.rationalDiv(coeff, { n: BigInt(nextPower), d: 1n });
|
|
1524
1757
|
const term = {
|
|
1525
1758
|
kind: "mul",
|
|
1526
|
-
left:
|
|
1527
|
-
right: nextPower === 1 ?
|
|
1759
|
+
left: chunkUM6BVY2S_cjs.constNode(scaled),
|
|
1760
|
+
right: nextPower === 1 ? chunkUM6BVY2S_cjs.varNode(variable) : chunkUM6BVY2S_cjs.powNode(chunkUM6BVY2S_cjs.varNode(variable), chunkUM6BVY2S_cjs.constNode(nextPower))
|
|
1528
1761
|
};
|
|
1529
1762
|
result = { kind: "add", left: result, right: term };
|
|
1530
1763
|
});
|
|
1531
1764
|
return result;
|
|
1532
1765
|
}
|
|
1533
1766
|
function integrate(node, variable) {
|
|
1534
|
-
const simplified =
|
|
1535
|
-
if (!
|
|
1536
|
-
return { ok: true, value:
|
|
1767
|
+
const simplified = chunkUM6BVY2S_cjs.simplifySymbolic(node);
|
|
1768
|
+
if (!chunkUM6BVY2S_cjs.freeVariables(simplified).has(variable)) {
|
|
1769
|
+
return { ok: true, value: chunkUM6BVY2S_cjs.simplifySymbolic({ kind: "mul", left: simplified, right: chunkUM6BVY2S_cjs.varNode(variable) }) };
|
|
1537
1770
|
}
|
|
1538
1771
|
const polynomial = integratePolynomial(simplified, variable);
|
|
1539
1772
|
if (polynomial !== null) return polynomial;
|
|
@@ -1550,13 +1783,13 @@ function integrate(node, variable) {
|
|
|
1550
1783
|
if (!right.ok) return right;
|
|
1551
1784
|
return {
|
|
1552
1785
|
ok: true,
|
|
1553
|
-
value:
|
|
1786
|
+
value: chunkUM6BVY2S_cjs.simplifySymbolic({ kind: simplified.kind, left: left.value, right: right.value })
|
|
1554
1787
|
};
|
|
1555
1788
|
}
|
|
1556
1789
|
if (simplified.kind === "mul" && simplified.left.kind === "const") {
|
|
1557
1790
|
const inner = integrate(simplified.right, variable);
|
|
1558
1791
|
if (!inner.ok) return inner;
|
|
1559
|
-
return { ok: true, value:
|
|
1792
|
+
return { ok: true, value: chunkUM6BVY2S_cjs.simplifySymbolic({ kind: "mul", left: simplified.left, right: inner.value }) };
|
|
1560
1793
|
}
|
|
1561
1794
|
return {
|
|
1562
1795
|
ok: false,
|
|
@@ -1568,36 +1801,36 @@ function integrate(node, variable) {
|
|
|
1568
1801
|
var TAYLOR_MAX_DEGREE = 16;
|
|
1569
1802
|
function taylorSeries(node, variable, point, degree) {
|
|
1570
1803
|
if (degree < 0 || !Number.isInteger(degree) || degree > TAYLOR_MAX_DEGREE) {
|
|
1571
|
-
throw
|
|
1804
|
+
throw chunk5KMIY374_cjs.ErrorFactory.execution(
|
|
1572
1805
|
"SYMBOLIC_TAYLOR_DEGREE_LIMIT",
|
|
1573
1806
|
`A Taylor degree must be a whole number from 0 to ${TAYLOR_MAX_DEGREE}.`,
|
|
1574
1807
|
{ limit: TAYLOR_MAX_DEGREE }
|
|
1575
1808
|
);
|
|
1576
1809
|
}
|
|
1577
|
-
const pointNode =
|
|
1810
|
+
const pointNode = chunkUM6BVY2S_cjs.constNode(point);
|
|
1578
1811
|
let factorial = 1n;
|
|
1579
|
-
let result =
|
|
1812
|
+
let result = chunkUM6BVY2S_cjs.constNode(chunkUM6BVY2S_cjs.RATIONAL_ZERO);
|
|
1580
1813
|
for (let order = 0; order <= degree; order++) {
|
|
1581
1814
|
if (order > 0) factorial *= BigInt(order);
|
|
1582
|
-
const derivative =
|
|
1583
|
-
const atPoint =
|
|
1815
|
+
const derivative = differentiate2(node, variable, order);
|
|
1816
|
+
const atPoint = chunkUM6BVY2S_cjs.simplifySymbolic(chunkUM6BVY2S_cjs.substitute(derivative, variable, pointNode));
|
|
1584
1817
|
if (atPoint.kind !== "const") {
|
|
1585
|
-
throw
|
|
1818
|
+
throw chunk5KMIY374_cjs.ErrorFactory.execution(
|
|
1586
1819
|
"SYMBOLIC_TAYLOR_INEXACT",
|
|
1587
1820
|
`The derivative of order ${order} does not reduce to an exact number at the expansion point, so this series cannot be computed exactly.`,
|
|
1588
1821
|
{ order }
|
|
1589
1822
|
);
|
|
1590
1823
|
}
|
|
1591
|
-
const coefficient =
|
|
1592
|
-
if (
|
|
1593
|
-
const shifted =
|
|
1594
|
-
const
|
|
1595
|
-
result = { kind: "add", left: result, right: { kind: "mul", left:
|
|
1824
|
+
const coefficient = chunkUM6BVY2S_cjs.rationalDiv(atPoint.value, { n: factorial, d: 1n });
|
|
1825
|
+
if (chunkUM6BVY2S_cjs.isRationalZero(coefficient)) continue;
|
|
1826
|
+
const shifted = chunkUM6BVY2S_cjs.isRationalZero(point) ? chunkUM6BVY2S_cjs.varNode(variable) : { kind: "sub", left: chunkUM6BVY2S_cjs.varNode(variable), right: pointNode };
|
|
1827
|
+
const power3 = order === 0 ? chunkUM6BVY2S_cjs.constNode(1) : order === 1 ? shifted : chunkUM6BVY2S_cjs.powNode(shifted, chunkUM6BVY2S_cjs.constNode(order));
|
|
1828
|
+
result = { kind: "add", left: result, right: { kind: "mul", left: chunkUM6BVY2S_cjs.constNode(coefficient), right: power3 } };
|
|
1596
1829
|
}
|
|
1597
|
-
return
|
|
1830
|
+
return chunkUM6BVY2S_cjs.simplifySymbolic(result);
|
|
1598
1831
|
}
|
|
1599
1832
|
function jacobian(functions, variables) {
|
|
1600
|
-
return functions.map((fn) => variables.map((variable) =>
|
|
1833
|
+
return functions.map((fn) => variables.map((variable) => differentiate2(fn, variable)));
|
|
1601
1834
|
}
|
|
1602
1835
|
|
|
1603
1836
|
// src/engine/EngineContext.ts
|
|
@@ -1701,7 +1934,7 @@ function adjustForInflation(amount, fromYear, toYear) {
|
|
|
1701
1934
|
var ANGLE_KIND = 0;
|
|
1702
1935
|
function angleInRadians(value) {
|
|
1703
1936
|
if (value.type === 6 /* Uom */ && value.unit !== void 0) {
|
|
1704
|
-
const entry =
|
|
1937
|
+
const entry = chunkAMOJYLG2_cjs.UNIT_TABLE[value.unit.toLowerCase()];
|
|
1705
1938
|
if (entry !== void 0 && entry[0] === ANGLE_KIND) return value.toNumber() * entry[1];
|
|
1706
1939
|
}
|
|
1707
1940
|
return value.toNumber();
|
|
@@ -1709,7 +1942,56 @@ function angleInRadians(value) {
|
|
|
1709
1942
|
function pluraliseUnit(unit, count) {
|
|
1710
1943
|
if (count === 1) return unit;
|
|
1711
1944
|
const plural = `${unit}s`;
|
|
1712
|
-
return
|
|
1945
|
+
return chunkAMOJYLG2_cjs.UNIT_TABLE[plural.toLowerCase()] === void 0 ? unit : plural;
|
|
1946
|
+
}
|
|
1947
|
+
function extremum(args, wantLargest) {
|
|
1948
|
+
let best;
|
|
1949
|
+
let hasNaN = false;
|
|
1950
|
+
for (const a of args) {
|
|
1951
|
+
if (Number.isNaN(a.toNumber())) {
|
|
1952
|
+
hasNaN = true;
|
|
1953
|
+
continue;
|
|
1954
|
+
}
|
|
1955
|
+
if (best === void 0) {
|
|
1956
|
+
best = a;
|
|
1957
|
+
continue;
|
|
1958
|
+
}
|
|
1959
|
+
const { lv, rv, sameMeasure } = unifyUom(best, a);
|
|
1960
|
+
if (!sameMeasure) {
|
|
1961
|
+
const bestUnit = best.type === 6 /* Uom */ ? best.unit : void 0;
|
|
1962
|
+
const otherUnit = a.type === 6 /* Uom */ ? a.unit : void 0;
|
|
1963
|
+
return chunkJMXUNXQS_cjs.errorValue(
|
|
1964
|
+
"INCOMPATIBLE_UNITS",
|
|
1965
|
+
`Cannot compare incompatible units: ${bestUnit ?? "?"} and ${otherUnit ?? "?"}`
|
|
1966
|
+
);
|
|
1967
|
+
}
|
|
1968
|
+
if (wantLargest ? rv > lv : rv < lv) best = a;
|
|
1969
|
+
}
|
|
1970
|
+
if (hasNaN) return chunkJMXUNXQS_cjs.numberValue(NaN);
|
|
1971
|
+
if (best === void 0) return chunkJMXUNXQS_cjs.numberValue(wantLargest ? -Infinity : Infinity);
|
|
1972
|
+
return best.type === 6 /* Uom */ ? best : chunkJMXUNXQS_cjs.numberValue(best.toNumber());
|
|
1973
|
+
}
|
|
1974
|
+
function keepUnit(operand, magnitude2) {
|
|
1975
|
+
if (operand.type === 6 /* Uom */ && operand.unit !== void 0) return chunkJMXUNXQS_cjs.uomValue(magnitude2, operand.unit);
|
|
1976
|
+
return chunkJMXUNXQS_cjs.numberValue(magnitude2);
|
|
1977
|
+
}
|
|
1978
|
+
function nonFiniteEuclidOperand(a, b, name) {
|
|
1979
|
+
if (Number.isFinite(a) && Number.isFinite(b)) return null;
|
|
1980
|
+
const culprit = Number.isFinite(a) ? b : a;
|
|
1981
|
+
return chunkJMXUNXQS_cjs.errorValue(
|
|
1982
|
+
"INVALID_INTEGER_OPERAND",
|
|
1983
|
+
`${name} needs two whole numbers, and ${Number.isNaN(culprit) ? "one of them has no value" : "one of them is infinite"}`
|
|
1984
|
+
);
|
|
1985
|
+
}
|
|
1986
|
+
function euclidGcd(a, b) {
|
|
1987
|
+
let x = a;
|
|
1988
|
+
let y = b;
|
|
1989
|
+
while (y !== 0) {
|
|
1990
|
+
const t = y;
|
|
1991
|
+
y = x % y;
|
|
1992
|
+
x = t;
|
|
1993
|
+
}
|
|
1994
|
+
return x;
|
|
1713
1995
|
}
|
|
1714
1996
|
var builtinFunctions = {
|
|
1715
1997
|
// ── Populated below ──
|
|
@@ -1718,76 +2000,73 @@ var builtinFunctions = {
|
|
|
1718
2000
|
// first, so sqrt(-4) is 2i rather than an approximation.
|
|
1719
2001
|
0: (args) => {
|
|
1720
2002
|
const value = args[0].toNumber();
|
|
1721
|
-
if (value >= 0) return
|
|
1722
|
-
return symbolicToValue(
|
|
2003
|
+
if (value >= 0) return chunkJMXUNXQS_cjs.numberValue(Math.sqrt(value));
|
|
2004
|
+
return symbolicToValue(chunkUM6BVY2S_cjs.callNode("sqrt", [chunkUM6BVY2S_cjs.constNode(value)]));
|
|
1723
2005
|
},
|
|
1724
2006
|
// abs(a): for a Matrix, "|a|" (Calca's determinant-pipe notation) is a
|
|
1725
2007
|
// valid alias for det(a) (index 64), reusing the SAME implementation
|
|
1726
2008
|
// not a separate one. Plain-number abs is unaffected.
|
|
1727
|
-
1: (args) => args[0].type === 7 /* Matrix */ ?
|
|
2009
|
+
1: (args) => args[0].type === 7 /* Matrix */ ? chunkUM6BVY2S_cjs.determinant(args[0].value) : keepUnit(args[0], Math.abs(args[0].toNumber())),
|
|
1728
2010
|
// sin/cos/tan accept an angle with a unit; see angleInRadians().
|
|
1729
|
-
2: (args) =>
|
|
1730
|
-
3: (args) =>
|
|
1731
|
-
4: (args) =>
|
|
1732
|
-
5: (args) =>
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
// (
|
|
1738
|
-
//
|
|
1739
|
-
9: (args) =>
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
}
|
|
1757
|
-
return chunkOC6LTXYS_cjs.numberValue(hasNaN ? NaN : result);
|
|
1758
|
-
},
|
|
1759
|
-
11: (args) => chunkOC6LTXYS_cjs.numberValue(Math.asin(args[0].toNumber())),
|
|
1760
|
-
12: (args) => chunkOC6LTXYS_cjs.numberValue(Math.acos(args[0].toNumber())),
|
|
1761
|
-
13: (args) => chunkOC6LTXYS_cjs.numberValue(Math.atan(args[0].toNumber())),
|
|
1762
|
-
14: (args) => chunkOC6LTXYS_cjs.numberValue(Math.atan2(args[0].toNumber(), args[1].toNumber())),
|
|
1763
|
-
15: (args) => chunkOC6LTXYS_cjs.numberValue(Math.sinh(args[0].toNumber())),
|
|
1764
|
-
16: (args) => chunkOC6LTXYS_cjs.numberValue(Math.cosh(args[0].toNumber())),
|
|
1765
|
-
17: (args) => chunkOC6LTXYS_cjs.numberValue(Math.tanh(args[0].toNumber())),
|
|
1766
|
-
18: (args) => chunkOC6LTXYS_cjs.numberValue(Math.asinh(args[0].toNumber())),
|
|
1767
|
-
19: (args) => chunkOC6LTXYS_cjs.numberValue(Math.acosh(args[0].toNumber())),
|
|
1768
|
-
20: (args) => chunkOC6LTXYS_cjs.numberValue(Math.atanh(args[0].toNumber())),
|
|
1769
|
-
21: (args) => chunkOC6LTXYS_cjs.numberValue(Math.cbrt(args[0].toNumber())),
|
|
1770
|
-
22: (args) => chunkOC6LTXYS_cjs.numberValue(Math.clz32(args[0].toNumber())),
|
|
1771
|
-
23: (args) => chunkOC6LTXYS_cjs.numberValue(Math.expm1(args[0].toNumber())),
|
|
1772
|
-
24: (args) => chunkOC6LTXYS_cjs.numberValue(Math.exp(args[0].toNumber())),
|
|
1773
|
-
25: (args) => chunkOC6LTXYS_cjs.numberValue(Math.fround(args[0].toNumber())),
|
|
2011
|
+
2: (args) => chunkJMXUNXQS_cjs.numberValue(Math.sin(angleInRadians(args[0]))),
|
|
2012
|
+
3: (args) => chunkJMXUNXQS_cjs.numberValue(Math.cos(angleInRadians(args[0]))),
|
|
2013
|
+
4: (args) => chunkJMXUNXQS_cjs.numberValue(Math.tan(angleInRadians(args[0]))),
|
|
2014
|
+
5: (args) => chunkJMXUNXQS_cjs.numberValue(Math.log(args[0].toNumber())),
|
|
2015
|
+
// round/ceil/floor keep a unit for the same reason abs does; see keepUnit().
|
|
2016
|
+
6: (args) => keepUnit(args[0], Math.ceil(args[0].toNumber())),
|
|
2017
|
+
7: (args) => keepUnit(args[0], Math.floor(args[0].toNumber())),
|
|
2018
|
+
8: (args) => keepUnit(args[0], Math.round(args[0].toNumber())),
|
|
2019
|
+
// min/max: see extremum() for why the winner is carried around as a Value
|
|
2020
|
+
// rather than as a running number.
|
|
2021
|
+
9: (args) => extremum(args, false),
|
|
2022
|
+
10: (args) => extremum(args, true),
|
|
2023
|
+
11: (args) => chunkJMXUNXQS_cjs.numberValue(Math.asin(args[0].toNumber())),
|
|
2024
|
+
12: (args) => chunkJMXUNXQS_cjs.numberValue(Math.acos(args[0].toNumber())),
|
|
2025
|
+
13: (args) => chunkJMXUNXQS_cjs.numberValue(Math.atan(args[0].toNumber())),
|
|
2026
|
+
14: (args) => chunkJMXUNXQS_cjs.numberValue(Math.atan2(args[0].toNumber(), args[1].toNumber())),
|
|
2027
|
+
15: (args) => chunkJMXUNXQS_cjs.numberValue(Math.sinh(args[0].toNumber())),
|
|
2028
|
+
16: (args) => chunkJMXUNXQS_cjs.numberValue(Math.cosh(args[0].toNumber())),
|
|
2029
|
+
17: (args) => chunkJMXUNXQS_cjs.numberValue(Math.tanh(args[0].toNumber())),
|
|
2030
|
+
18: (args) => chunkJMXUNXQS_cjs.numberValue(Math.asinh(args[0].toNumber())),
|
|
2031
|
+
19: (args) => chunkJMXUNXQS_cjs.numberValue(Math.acosh(args[0].toNumber())),
|
|
2032
|
+
20: (args) => chunkJMXUNXQS_cjs.numberValue(Math.atanh(args[0].toNumber())),
|
|
2033
|
+
21: (args) => chunkJMXUNXQS_cjs.numberValue(Math.cbrt(args[0].toNumber())),
|
|
2034
|
+
22: (args) => chunkJMXUNXQS_cjs.numberValue(Math.clz32(args[0].toNumber())),
|
|
2035
|
+
23: (args) => chunkJMXUNXQS_cjs.numberValue(Math.expm1(args[0].toNumber())),
|
|
2036
|
+
24: (args) => chunkJMXUNXQS_cjs.numberValue(Math.exp(args[0].toNumber())),
|
|
2037
|
+
25: (args) => chunkJMXUNXQS_cjs.numberValue(Math.fround(args[0].toNumber())),
|
|
1774
2038
|
// hypot: left as .map()+spread (unlike min/max above), Math.hypot uses
|
|
1775
2039
|
// a numerically-stable scaling algorithm internally to avoid overflow
|
|
1776
2040
|
// for very large/small inputs; a naive manual reimplementation risks
|
|
1777
2041
|
// silently changing results at the extremes, so the tiny array
|
|
1778
2042
|
// allocation here is the safer trade.
|
|
1779
|
-
26: (args) =>
|
|
1780
|
-
27: (args) =>
|
|
1781
|
-
28: (args) =>
|
|
1782
|
-
29: (args) =>
|
|
1783
|
-
30: (args) =>
|
|
1784
|
-
|
|
1785
|
-
|
|
2043
|
+
26: (args) => chunkJMXUNXQS_cjs.numberValue(Math.hypot(...args.map((a) => a.toNumber()))),
|
|
2044
|
+
27: (args) => chunkJMXUNXQS_cjs.numberValue(Math.imul(args[0].toNumber(), args[1].toNumber())),
|
|
2045
|
+
28: (args) => chunkJMXUNXQS_cjs.numberValue(Math.log10(args[0].toNumber())),
|
|
2046
|
+
29: (args) => chunkJMXUNXQS_cjs.numberValue(Math.log1p(args[0].toNumber())),
|
|
2047
|
+
30: (args) => chunkJMXUNXQS_cjs.numberValue(Math.log2(args[0].toNumber())),
|
|
2048
|
+
// pow(): the spelled-out form of `^`, so a Matrix base means the same
|
|
2049
|
+
// repeated matrix multiplication `^` means. Without this branch
|
|
2050
|
+
// `pow([1,2;3,4], 2)` was Math.pow of a value whose toNumber() is 0, and
|
|
2051
|
+
// came back as the number 0. See vm/MatrixOps.ts's matrixPower().
|
|
2052
|
+
31: (args) => {
|
|
2053
|
+
if (args[0].type === 7 /* Matrix */) {
|
|
2054
|
+
if (args[1].type !== 0 /* Number */) {
|
|
2055
|
+
return chunkJMXUNXQS_cjs.errorValue("MATRIX_POWER_UNSUPPORTED", `pow: a matrix's exponent must be a whole number, as in "pow([1,2;3,4], 2)".`);
|
|
2056
|
+
}
|
|
2057
|
+
return chunkUM6BVY2S_cjs.matrixPower(args[0].value, args[1].value);
|
|
2058
|
+
}
|
|
2059
|
+
if (args[1].type === 7 /* Matrix */) {
|
|
2060
|
+
return chunkJMXUNXQS_cjs.errorValue("MATRIX_POWER_UNSUPPORTED", `pow: a matrix may only be the base, as in "pow([1,2;3,4], 2)".`);
|
|
2061
|
+
}
|
|
2062
|
+
return chunkJMXUNXQS_cjs.numberValue(power(args[0].toNumber(), args[1].toNumber()));
|
|
2063
|
+
},
|
|
2064
|
+
32: () => chunkJMXUNXQS_cjs.numberValue(Math.random()),
|
|
1786
2065
|
// takes no arguments, unlike its neighbours
|
|
1787
|
-
33: (args) =>
|
|
1788
|
-
34: (args) =>
|
|
1789
|
-
35: (args) =>
|
|
1790
|
-
36: (args) =>
|
|
2066
|
+
33: (args) => chunkJMXUNXQS_cjs.numberValue(Math.sign(args[0].toNumber())),
|
|
2067
|
+
34: (args) => chunkJMXUNXQS_cjs.numberValue(Math.trunc(args[0].toNumber())),
|
|
2068
|
+
35: (args) => chunkJMXUNXQS_cjs.numberValue(args[0].toNumber() * Math.PI / 180),
|
|
2069
|
+
36: (args) => chunkJMXUNXQS_cjs.numberValue(args[0].toNumber() * 180 / Math.PI),
|
|
1791
2070
|
// 37: diceRoll(from, to), random integer in range [from, to] inclusive.
|
|
1792
2071
|
// A reversed range (from > to) used to silently produce values outside
|
|
1793
2072
|
// [to, from] via a negative-length Math.random() spread (e.g.
|
|
@@ -1797,84 +2076,112 @@ var builtinFunctions = {
|
|
|
1797
2076
|
const from = args[0].toNumber();
|
|
1798
2077
|
const to = args[1].toNumber();
|
|
1799
2078
|
if (from > to) {
|
|
1800
|
-
return
|
|
2079
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `roll: invalid range, ${from} is greater than ${to}`);
|
|
1801
2080
|
}
|
|
1802
|
-
return
|
|
2081
|
+
return chunkJMXUNXQS_cjs.numberValue(Math.floor(Math.random() * (to - from + 1)) + from);
|
|
1803
2082
|
},
|
|
1804
2083
|
// gcd(a, b), Euclidean algorithm. Negative inputs are treated by
|
|
1805
2084
|
// magnitude (gcd is conventionally defined over non-negative integers).
|
|
1806
2085
|
38: (args) => {
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
a = t;
|
|
1813
|
-
}
|
|
1814
|
-
return chunkOC6LTXYS_cjs.numberValue(a);
|
|
2086
|
+
const a = Math.trunc(Math.abs(args[0].toNumber()));
|
|
2087
|
+
const b = Math.trunc(Math.abs(args[1].toNumber()));
|
|
2088
|
+
const nonFinite = nonFiniteEuclidOperand(a, b, "gcd");
|
|
2089
|
+
if (nonFinite) return nonFinite;
|
|
2090
|
+
return chunkJMXUNXQS_cjs.numberValue(euclidGcd(a, b));
|
|
1815
2091
|
},
|
|
1816
2092
|
// lcm(a, b) = |a*b| / gcd(a, b), via the same Euclidean gcd inline
|
|
1817
2093
|
// (a standalone gcd() call site, no shared helper needed for two uses).
|
|
1818
2094
|
39: (args) => {
|
|
1819
2095
|
const a = Math.trunc(Math.abs(args[0].toNumber()));
|
|
1820
2096
|
const b = Math.trunc(Math.abs(args[1].toNumber()));
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
y = x % y;
|
|
1826
|
-
x = t;
|
|
1827
|
-
}
|
|
1828
|
-
return chunkOC6LTXYS_cjs.numberValue(a / x * b);
|
|
2097
|
+
const nonFinite = nonFiniteEuclidOperand(a, b, "lcm");
|
|
2098
|
+
if (nonFinite) return nonFinite;
|
|
2099
|
+
if (a === 0 || b === 0) return chunkJMXUNXQS_cjs.numberValue(0);
|
|
2100
|
+
return chunkJMXUNXQS_cjs.numberValue(a / euclidGcd(a, b) * b);
|
|
1829
2101
|
},
|
|
1830
2102
|
// permutation(n, r) = n! / (n-r)!, computed as a running product
|
|
1831
2103
|
// rather than two full factorials, so it stays exact for n well
|
|
1832
2104
|
// beyond where n! itself would exceed Number.MAX_SAFE_INTEGER.
|
|
2105
|
+
//
|
|
2106
|
+
// The loop stops the moment the product stops being a representable
|
|
2107
|
+
// double, which is both the answer `fact` (index 62) already gives for
|
|
2108
|
+
// the same question and the thing that bounds the loop at all. `r` comes
|
|
2109
|
+
// straight off the stack: `permutation(1000000000000, 1000000000000)`
|
|
2110
|
+
// used to run a trillion iterations, of which the first ~170 computed
|
|
2111
|
+
// something and the rest multiplied Infinity by a number, and it had not
|
|
2112
|
+
// returned after thirty seconds. Every factor here is at least 1 and they
|
|
2113
|
+
// descend from `n`, so a product that is still finite after 170 steps
|
|
2114
|
+
// means the factors are small, which in turn means `r <= n` is small: the
|
|
2115
|
+
// early exit bounds the trip count without a separate estimate, and
|
|
2116
|
+
// without ever refusing a permutation that does have an answer.
|
|
1833
2117
|
40: (args) => {
|
|
1834
2118
|
const n = Math.trunc(args[0].toNumber());
|
|
1835
2119
|
const r = Math.trunc(args[1].toNumber());
|
|
1836
2120
|
if (n < 0 || r < 0 || r > n) {
|
|
1837
|
-
return
|
|
2121
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `permutation: invalid n=${n}, r=${r} (require 0 <= r <= n)`);
|
|
1838
2122
|
}
|
|
1839
2123
|
let result = 1;
|
|
1840
|
-
for (let i = 0; i < r; i++)
|
|
1841
|
-
|
|
2124
|
+
for (let i = 0; i < r; i++) {
|
|
2125
|
+
result *= n - i;
|
|
2126
|
+
if (!Number.isFinite(result)) {
|
|
2127
|
+
return chunkJMXUNXQS_cjs.errorValue(
|
|
2128
|
+
"PERMUTATION_OVERFLOW",
|
|
2129
|
+
`permutation: P(${n}, ${r}) exceeds the maximum representable double (it passed it after ${i + 1} of ${r} factors)`
|
|
2130
|
+
);
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
return chunkJMXUNXQS_cjs.numberValue(result);
|
|
1842
2134
|
},
|
|
1843
2135
|
// combination(n, r) = n! / (r! * (n-r)!), multiply-then-divide one
|
|
1844
2136
|
// step at a time (standard technique) keeps every intermediate result
|
|
1845
2137
|
// an integer, avoiding the overflow a naive factorial-ratio would hit.
|
|
2138
|
+
//
|
|
2139
|
+
// Same early exit, and needed for the same reason: `k = min(r, n-r)`
|
|
2140
|
+
// halves the trip count and bounds nothing, so `combination(1e12, 5e11)`
|
|
2141
|
+
// asked for five hundred billion iterations. The running value is C(n, i),
|
|
2142
|
+
// which grows monotonically to the middle, so once it is past what a
|
|
2143
|
+
// double can hold it never comes back, and the largest run this can now
|
|
2144
|
+
// take is the thousand-odd steps C(n, k) needs to cross that line.
|
|
1846
2145
|
41: (args) => {
|
|
1847
2146
|
const n = Math.trunc(args[0].toNumber());
|
|
1848
2147
|
const r = Math.trunc(args[1].toNumber());
|
|
1849
2148
|
if (n < 0 || r < 0 || r > n) {
|
|
1850
|
-
return
|
|
2149
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `combination: invalid n=${n}, r=${r} (require 0 <= r <= n)`);
|
|
1851
2150
|
}
|
|
1852
2151
|
const k = Math.min(r, n - r);
|
|
1853
2152
|
let result = 1;
|
|
1854
|
-
for (let i = 0; i < k; i++)
|
|
1855
|
-
|
|
2153
|
+
for (let i = 0; i < k; i++) {
|
|
2154
|
+
result = result * (n - i) / (i + 1);
|
|
2155
|
+
if (!Number.isFinite(result)) {
|
|
2156
|
+
return chunkJMXUNXQS_cjs.errorValue(
|
|
2157
|
+
"COMBINATION_OVERFLOW",
|
|
2158
|
+
`combination: C(${n}, ${r}) exceeds the maximum representable double (it passed it after ${i + 1} of ${k} steps)`
|
|
2159
|
+
);
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
return chunkJMXUNXQS_cjs.numberValue(Math.round(result));
|
|
1856
2163
|
},
|
|
1857
2164
|
// average(...), arithmetic mean of any number of arguments. Backs the
|
|
1858
2165
|
// MathPhrases package's "average of X, Y, Z" (packages/mathphrases/).
|
|
1859
2166
|
42: (args) => {
|
|
1860
|
-
if (args.length === 0) return
|
|
2167
|
+
if (args.length === 0) return chunkJMXUNXQS_cjs.numberValue(0);
|
|
1861
2168
|
const sum = args.reduce((acc, a) => acc + a.toNumber(), 0);
|
|
1862
|
-
return
|
|
2169
|
+
return chunkJMXUNXQS_cjs.numberValue(sum / args.length);
|
|
1863
2170
|
},
|
|
1864
2171
|
// median(...), middle value; average of the two middle values for an
|
|
1865
2172
|
// even argument count.
|
|
1866
2173
|
43: (args) => {
|
|
1867
|
-
if (args.length === 0) return
|
|
2174
|
+
if (args.length === 0) return chunkJMXUNXQS_cjs.numberValue(0);
|
|
1868
2175
|
const sorted = args.map((a) => a.toNumber()).sort((a, b) => a - b);
|
|
1869
2176
|
const mid = Math.floor(sorted.length / 2);
|
|
1870
|
-
return
|
|
2177
|
+
return chunkJMXUNXQS_cjs.numberValue(
|
|
1871
2178
|
sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid]
|
|
1872
2179
|
);
|
|
1873
2180
|
},
|
|
1874
2181
|
// total(...), sum of any number of arguments.
|
|
1875
|
-
44: (args) =>
|
|
2182
|
+
44: (args) => chunkJMXUNXQS_cjs.numberValue(args.reduce((acc, a) => acc + a.toNumber(), 0)),
|
|
1876
2183
|
// count(...), number of arguments passed.
|
|
1877
|
-
45: (args) =>
|
|
2184
|
+
45: (args) => chunkJMXUNXQS_cjs.numberValue(args.length),
|
|
1878
2185
|
// proportion(a, b, c) -> d such that a:b = c:d, i.e. d = c * (b/a)
|
|
1879
2186
|
// "A is to B as C is to what". Unit-aware via unifyUom: "5 km is to
|
|
1880
2187
|
// 500m as 5 cm is to what" unifies 5km/500m to a 10:1 ratio (500m ==
|
|
@@ -1885,10 +2192,10 @@ var builtinFunctions = {
|
|
|
1885
2192
|
const [a, b, c] = args;
|
|
1886
2193
|
const { lv: aNum, rv: bNum } = unifyUom(a, b);
|
|
1887
2194
|
if (aNum === 0) {
|
|
1888
|
-
return
|
|
2195
|
+
return chunkJMXUNXQS_cjs.errorValue("PROPORTION_DIVIDE_BY_ZERO", `Cannot compute proportion: "${a.value}" is zero`);
|
|
1889
2196
|
}
|
|
1890
2197
|
const result = c.toNumber() * (bNum / aNum);
|
|
1891
|
-
return c.type === 6 /* Uom */ ?
|
|
2198
|
+
return c.type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(result, c.unit) : chunkJMXUNXQS_cjs.numberValue(result);
|
|
1892
2199
|
},
|
|
1893
2200
|
// clamp(value, lo, hi), restrict value to [lo, hi]. Backs
|
|
1894
2201
|
// "clamp X between Y and Z" / "clamp X from Y to Z".
|
|
@@ -1897,9 +2204,9 @@ var builtinFunctions = {
|
|
|
1897
2204
|
const lo = args[1].toNumber();
|
|
1898
2205
|
const hi = args[2].toNumber();
|
|
1899
2206
|
if (lo > hi) {
|
|
1900
|
-
return
|
|
2207
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `clamp: invalid range, ${lo} is greater than ${hi}`);
|
|
1901
2208
|
}
|
|
1902
|
-
return
|
|
2209
|
+
return chunkJMXUNXQS_cjs.numberValue(Math.min(Math.max(value, lo), hi));
|
|
1903
2210
|
},
|
|
1904
2211
|
// hex(n), Python/JS-style call-syntax hex formatting, e.g. hex(255) ->
|
|
1905
2212
|
// "0xFF". Distinct from the Converters package's `255 as hex` (see
|
|
@@ -1909,16 +2216,16 @@ var builtinFunctions = {
|
|
|
1909
2216
|
// function call that returns an ordinary String value, matching
|
|
1910
2217
|
// Python's hex()/JS convention of a function returning display text,
|
|
1911
2218
|
// not a numeric type.
|
|
1912
|
-
48: (args) =>
|
|
2219
|
+
48: (args) => chunkJMXUNXQS_cjs.hexValue(args[0].toNumber()),
|
|
1913
2220
|
// bin(n). Same call-syntax shape as hex() above, e.g. bin(10) -> "0b1010".
|
|
1914
|
-
49: (args) =>
|
|
2221
|
+
49: (args) => chunkJMXUNXQS_cjs.hexValue(args[0].toNumber(), "bin"),
|
|
1915
2222
|
// int(x), coerce ANY value (Number, Percentage, Uom, String, Hex, ...)
|
|
1916
2223
|
// to a plain integer Number, truncating any fractional part toward
|
|
1917
2224
|
// zero (Math.trunc semantics: int(5.7) -> 5, int(-5.7) -> -5). Distinct
|
|
1918
2225
|
// from the Converters package's `x as number` (TO_NUMBER opcode),
|
|
1919
2226
|
// which only strips a unit/percentage wrapper and keeps any decimal
|
|
1920
2227
|
// part (e.g. "5.7 as number" -> 5.7), int() additionally truncates.
|
|
1921
|
-
50: (args) =>
|
|
2228
|
+
50: (args) => chunkJMXUNXQS_cjs.numberValue(Math.trunc(args[0].toNumber())),
|
|
1922
2229
|
// ── Finance (packages/finance/) ──────────────────────────────────────
|
|
1923
2230
|
// All finance builtins preserve the principal/amount argument's Uom
|
|
1924
2231
|
// unit (e.g. a currency like "$") onto the result, matching
|
|
@@ -1939,10 +2246,10 @@ var builtinFunctions = {
|
|
|
1939
2246
|
const rate = args[1].toNumber();
|
|
1940
2247
|
const years = args[2].toNumber();
|
|
1941
2248
|
if (1 + rate <= 0) {
|
|
1942
|
-
return
|
|
2249
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", `compoundInterest: rate ${rate} makes (1 + rate) non-positive`);
|
|
1943
2250
|
}
|
|
1944
2251
|
const fv = principal * Math.pow(1 + rate, years);
|
|
1945
|
-
return args[0].type === 6 /* Uom */ ?
|
|
2252
|
+
return args[0].type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(fv, args[0].unit) : chunkJMXUNXQS_cjs.numberValue(fv);
|
|
1946
2253
|
},
|
|
1947
2254
|
// compoundInterestEarned(principal, rate, years) -> FV - principal, the
|
|
1948
2255
|
// interest-only portion. Backs "interest on $P over Y years at R%" and
|
|
@@ -1952,10 +2259,10 @@ var builtinFunctions = {
|
|
|
1952
2259
|
const rate = args[1].toNumber();
|
|
1953
2260
|
const years = args[2].toNumber();
|
|
1954
2261
|
if (1 + rate <= 0) {
|
|
1955
|
-
return
|
|
2262
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", `interestEarned: rate ${rate} makes (1 + rate) non-positive`);
|
|
1956
2263
|
}
|
|
1957
2264
|
const interest = principal * (Math.pow(1 + rate, years) - 1);
|
|
1958
|
-
return args[0].type === 6 /* Uom */ ?
|
|
2265
|
+
return args[0].type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(interest, args[0].unit) : chunkJMXUNXQS_cjs.numberValue(interest);
|
|
1959
2266
|
},
|
|
1960
2267
|
// compoundInterestRate(principal, futureValue, years) -> the rate (as a
|
|
1961
2268
|
// decimal fraction) needed to grow principal to futureValue over years.
|
|
@@ -1967,12 +2274,12 @@ var builtinFunctions = {
|
|
|
1967
2274
|
const futureValue = args[1].toNumber();
|
|
1968
2275
|
const years = args[2].toNumber();
|
|
1969
2276
|
if (principal <= 0 || futureValue <= 0) {
|
|
1970
|
-
return
|
|
2277
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `compoundInterestRate: principal and futureValue must both be positive`);
|
|
1971
2278
|
}
|
|
1972
2279
|
if (years <= 0) {
|
|
1973
|
-
return
|
|
2280
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `compoundInterestRate: years must be greater than 0`);
|
|
1974
2281
|
}
|
|
1975
|
-
return
|
|
2282
|
+
return chunkJMXUNXQS_cjs.numberValue(Math.pow(futureValue / principal, 1 / years) - 1);
|
|
1976
2283
|
},
|
|
1977
2284
|
// compoundInterestYears(principal, futureValue, rate) -> the number of
|
|
1978
2285
|
// years needed to grow principal to futureValue at a fixed rate.
|
|
@@ -1982,12 +2289,12 @@ var builtinFunctions = {
|
|
|
1982
2289
|
const futureValue = args[1].toNumber();
|
|
1983
2290
|
const rate = args[2].toNumber();
|
|
1984
2291
|
if (principal <= 0 || futureValue <= 0) {
|
|
1985
|
-
return
|
|
2292
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `compoundInterestYears: principal and futureValue must both be positive`);
|
|
1986
2293
|
}
|
|
1987
2294
|
if (1 + rate <= 0 || rate === 0) {
|
|
1988
|
-
return
|
|
2295
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", `compoundInterestYears: rate ${rate} is not usable (must be > -1 and not 0)`);
|
|
1989
2296
|
}
|
|
1990
|
-
return
|
|
2297
|
+
return chunkJMXUNXQS_cjs.numberValue(Math.log(futureValue / principal) / Math.log(1 + rate));
|
|
1991
2298
|
},
|
|
1992
2299
|
// loanRepayment(principal, rate, years, periodsPerYear), standard
|
|
1993
2300
|
// amortizing-loan repayment (mortgage formula), redistributed evenly
|
|
@@ -2005,13 +2312,13 @@ var builtinFunctions = {
|
|
|
2005
2312
|
const rate = args[1].toNumber();
|
|
2006
2313
|
const years = args[2].toNumber();
|
|
2007
2314
|
const periodsPerYear = args[3].toNumber();
|
|
2008
|
-
if (principal <= 0) return
|
|
2009
|
-
if (years <= 0) return
|
|
2010
|
-
if (rate < 0) return
|
|
2011
|
-
if (periodsPerYear < 0) return
|
|
2315
|
+
if (principal <= 0) return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `loanRepayment: principal must be positive`);
|
|
2316
|
+
if (years <= 0) return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `loanRepayment: years must be positive`);
|
|
2317
|
+
if (rate < 0) return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", `loanRepayment: rate must not be negative`);
|
|
2318
|
+
if (periodsPerYear < 0) return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `loanRepayment: periodsPerYear must not be negative`);
|
|
2012
2319
|
const { totalRepayment } = amortizeLoan(principal, rate, years);
|
|
2013
2320
|
const result = periodsPerYear === 0 ? totalRepayment : totalRepayment / (years * periodsPerYear);
|
|
2014
|
-
return args[0].type === 6 /* Uom */ ?
|
|
2321
|
+
return args[0].type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(result, args[0].unit) : chunkJMXUNXQS_cjs.numberValue(result);
|
|
2015
2322
|
},
|
|
2016
2323
|
// loanInterest(principal, rate, years, periodsPerYear), the interest
|
|
2017
2324
|
// portion of index 55's repayment, same periodsPerYear convention.
|
|
@@ -2021,13 +2328,13 @@ var builtinFunctions = {
|
|
|
2021
2328
|
const rate = args[1].toNumber();
|
|
2022
2329
|
const years = args[2].toNumber();
|
|
2023
2330
|
const periodsPerYear = args[3].toNumber();
|
|
2024
|
-
if (principal <= 0) return
|
|
2025
|
-
if (years <= 0) return
|
|
2026
|
-
if (rate < 0) return
|
|
2027
|
-
if (periodsPerYear < 0) return
|
|
2331
|
+
if (principal <= 0) return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `loanInterest: principal must be positive`);
|
|
2332
|
+
if (years <= 0) return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `loanInterest: years must be positive`);
|
|
2333
|
+
if (rate < 0) return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", `loanInterest: rate must not be negative`);
|
|
2334
|
+
if (periodsPerYear < 0) return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `loanInterest: periodsPerYear must not be negative`);
|
|
2028
2335
|
const { totalInterest } = amortizeLoan(principal, rate, years);
|
|
2029
2336
|
const result = periodsPerYear === 0 ? totalInterest : totalInterest / (years * periodsPerYear);
|
|
2030
|
-
return args[0].type === 6 /* Uom */ ?
|
|
2337
|
+
return args[0].type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(result, args[0].unit) : chunkJMXUNXQS_cjs.numberValue(result);
|
|
2031
2338
|
},
|
|
2032
2339
|
// monthlyPayment(principal, rate, years), convenience 3-arg wrapper
|
|
2033
2340
|
// around index 55's monthly case, for direct function-call use without
|
|
@@ -2036,11 +2343,11 @@ var builtinFunctions = {
|
|
|
2036
2343
|
const principal = args[0].toNumber();
|
|
2037
2344
|
const rate = args[1].toNumber();
|
|
2038
2345
|
const years = args[2].toNumber();
|
|
2039
|
-
if (principal <= 0) return
|
|
2040
|
-
if (years <= 0) return
|
|
2041
|
-
if (rate < 0) return
|
|
2346
|
+
if (principal <= 0) return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `monthlyPayment: principal must be positive`);
|
|
2347
|
+
if (years <= 0) return chunkJMXUNXQS_cjs.errorValue("INVALID_RANGE", `monthlyPayment: years must be positive`);
|
|
2348
|
+
if (rate < 0) return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", `monthlyPayment: rate must not be negative`);
|
|
2042
2349
|
const { monthlyPayment } = amortizeLoan(principal, rate, years);
|
|
2043
|
-
return args[0].type === 6 /* Uom */ ?
|
|
2350
|
+
return args[0].type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(monthlyPayment, args[0].unit) : chunkJMXUNXQS_cjs.numberValue(monthlyPayment);
|
|
2044
2351
|
},
|
|
2045
2352
|
// taxAdd(amount, rate) -> amount * (1 + rate), the tax-inclusive total.
|
|
2046
2353
|
// Backs the taxAdd() function-call form, whose name promises exactly this.
|
|
@@ -2053,7 +2360,7 @@ var builtinFunctions = {
|
|
|
2053
2360
|
const amount = args[0].toNumber();
|
|
2054
2361
|
const rate = args[1].toNumber();
|
|
2055
2362
|
const result = amount * (1 + rate);
|
|
2056
|
-
return args[0].type === 6 /* Uom */ ?
|
|
2363
|
+
return args[0].type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(result, args[0].unit) : chunkJMXUNXQS_cjs.numberValue(result);
|
|
2057
2364
|
},
|
|
2058
2365
|
// taxRemove(amount, rate) -> amount / (1 + rate), extracts the
|
|
2059
2366
|
// pre-tax amount from a tax-INCLUSIVE total. Backs "tax off $X at R%" /
|
|
@@ -2062,9 +2369,9 @@ var builtinFunctions = {
|
|
|
2062
2369
|
const amount = args[0].toNumber();
|
|
2063
2370
|
const rate = args[1].toNumber();
|
|
2064
2371
|
if (1 + rate <= 0) {
|
|
2065
|
-
return
|
|
2372
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", `taxRemove: rate ${rate} makes (1 + rate) non-positive`);
|
|
2066
2373
|
}
|
|
2067
|
-
return args[0].type === 6 /* Uom */ ?
|
|
2374
|
+
return args[0].type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(amount / (1 + rate), args[0].unit) : chunkJMXUNXQS_cjs.numberValue(amount / (1 + rate));
|
|
2068
2375
|
},
|
|
2069
2376
|
// inflationAdjust(amount, fromYear, toYear) -- CPI-based inflation
|
|
2070
2377
|
// adjustment between two arbitrary years, using the bundled CPI-U
|
|
@@ -2084,13 +2391,13 @@ var builtinFunctions = {
|
|
|
2084
2391
|
const toYear = args[2].toNumber();
|
|
2085
2392
|
const ratio = inflationRatio(fromYear, toYear);
|
|
2086
2393
|
if (ratio === void 0) {
|
|
2087
|
-
return
|
|
2394
|
+
return chunkJMXUNXQS_cjs.errorValue(
|
|
2088
2395
|
"INFLATION_YEAR_OUT_OF_RANGE",
|
|
2089
2396
|
`inflationAdjust: fromYear ${fromYear} or toYear ${toYear} is outside the bundled CPI table's range (${CPI_MIN_YEAR}-${CPI_MAX_YEAR})`
|
|
2090
2397
|
);
|
|
2091
2398
|
}
|
|
2092
2399
|
const result = amount * ratio;
|
|
2093
|
-
return args[0].type === 6 /* Uom */ ?
|
|
2400
|
+
return args[0].type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(result, args[0].unit) : chunkJMXUNXQS_cjs.numberValue(result);
|
|
2094
2401
|
},
|
|
2095
2402
|
// root(n, x) -- the n-th root of x (Numi's `root n (x)` phrasing maps
|
|
2096
2403
|
// to this same call-style form; see FunctionCallParselet's name map).
|
|
@@ -2101,7 +2408,7 @@ var builtinFunctions = {
|
|
|
2101
2408
|
61: (args) => {
|
|
2102
2409
|
const n = args[0].toNumber();
|
|
2103
2410
|
const x = args[1].toNumber();
|
|
2104
|
-
return
|
|
2411
|
+
return chunkJMXUNXQS_cjs.numberValue(power(x, 1 / n));
|
|
2105
2412
|
},
|
|
2106
2413
|
// fact(n) / factorial(n) -- integer factorial. Deliberately rejects
|
|
2107
2414
|
// negative or non-integer input (factorial isn't defined for either
|
|
@@ -2112,14 +2419,14 @@ var builtinFunctions = {
|
|
|
2112
2419
|
62: (args) => {
|
|
2113
2420
|
const n = args[0].toNumber();
|
|
2114
2421
|
if (!Number.isInteger(n) || n < 0) {
|
|
2115
|
-
return
|
|
2422
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_FACTORIAL_INPUT", `fact: ${n} is not a non-negative integer`);
|
|
2116
2423
|
}
|
|
2117
2424
|
if (n > 170) {
|
|
2118
|
-
return
|
|
2425
|
+
return chunkJMXUNXQS_cjs.errorValue("FACTORIAL_OVERFLOW", `fact: ${n}! exceeds the maximum representable double (170! is the largest finite factorial)`);
|
|
2119
2426
|
}
|
|
2120
2427
|
let result = 1;
|
|
2121
2428
|
for (let i = 2; i <= n; i++) result *= i;
|
|
2122
|
-
return
|
|
2429
|
+
return chunkJMXUNXQS_cjs.numberValue(result);
|
|
2123
2430
|
},
|
|
2124
2431
|
// ── Matrix (packages/matrix/) ────────────────────────────────────────
|
|
2125
2432
|
// transpose(a)/det(a)/inv(a)/dot(a,b), reachable both via ordinary
|
|
@@ -2132,17 +2439,17 @@ var builtinFunctions = {
|
|
|
2132
2439
|
// own transpose (a 1x1 "matrix" transposed is itself), matches this
|
|
2133
2440
|
// engine's existing convention of treating a scalar as a trivial 1x1
|
|
2134
2441
|
// matrix (see Value.ts's toNumber()/isNaN() 1x1 special case).
|
|
2135
|
-
63: (args) => args[0].type === 7 /* Matrix */ ?
|
|
2442
|
+
63: (args) => args[0].type === 7 /* Matrix */ ? chunkUM6BVY2S_cjs.transpose(args[0].value) : args[0],
|
|
2136
2443
|
// det(a), determinant. A plain Number's "determinant" is itself (the
|
|
2137
2444
|
// determinant of a 1x1 matrix [x] is x).
|
|
2138
|
-
64: (args) => args[0].type === 7 /* Matrix */ ?
|
|
2445
|
+
64: (args) => args[0].type === 7 /* Matrix */ ? chunkUM6BVY2S_cjs.determinant(args[0].value) : chunkJMXUNXQS_cjs.numberValue(args[0].toNumber()),
|
|
2139
2446
|
// inv(a), matrix inverse for a Matrix; for a plain Number, `1/x`
|
|
2140
2447
|
// (byte-identical to `Math.pow(x, -1)`, which is what `x^-1` computed
|
|
2141
2448
|
// before this feature existed. See PrecedenceParser.ts's `^-1`
|
|
2142
2449
|
// special-case doc comment for why this must stay exact).
|
|
2143
2450
|
65: (args) => {
|
|
2144
|
-
if (args[0].type === 7 /* Matrix */) return
|
|
2145
|
-
return
|
|
2451
|
+
if (args[0].type === 7 /* Matrix */) return chunkUM6BVY2S_cjs.inverse(args[0].value);
|
|
2452
|
+
return chunkJMXUNXQS_cjs.numberValue(1 / args[0].toNumber());
|
|
2146
2453
|
},
|
|
2147
2454
|
// dot(a, b), matrix product / scalar-broadcast, the SAME dispatch as
|
|
2148
2455
|
// the `*` operator between two matrices (vm/VM.ts's MUL case). Plain
|
|
@@ -2152,10 +2459,10 @@ var builtinFunctions = {
|
|
|
2152
2459
|
66: (args) => {
|
|
2153
2460
|
const [a, b] = args;
|
|
2154
2461
|
if (a.type === 0 /* Number */ && b.type === 0 /* Number */) {
|
|
2155
|
-
return
|
|
2462
|
+
return chunkJMXUNXQS_cjs.numberValue(a.toNumber() * b.toNumber());
|
|
2156
2463
|
}
|
|
2157
2464
|
const toMatrix = (v) => v.type === 7 /* Matrix */ ? v.value : { rows: 1, cols: 1, data: [v.toNumber()], hasSymbolic: false };
|
|
2158
|
-
return
|
|
2465
|
+
return chunkUM6BVY2S_cjs.matrixMultiply(toMatrix(a), toMatrix(b));
|
|
2159
2466
|
},
|
|
2160
2467
|
// ── Symbolic algebra (packages/symbolic/) ──
|
|
2161
2468
|
// expand(expr), multiplying out every product and power. Reached only
|
|
@@ -2169,7 +2476,7 @@ var builtinFunctions = {
|
|
|
2169
2476
|
67: (args) => {
|
|
2170
2477
|
const [value] = args;
|
|
2171
2478
|
if (value.type !== 9 /* Symbolic */) return value;
|
|
2172
|
-
return symbolicToValue(
|
|
2479
|
+
return symbolicToValue(chunkUM6BVY2S_cjs.expandSymbolic(value.value));
|
|
2173
2480
|
},
|
|
2174
2481
|
// factor(expr), writing a polynomial as a product of irreducible factors
|
|
2175
2482
|
// over the RATIONALS. x^2-2 and x^2+1 come back unchanged, which is the
|
|
@@ -2186,7 +2493,7 @@ var builtinFunctions = {
|
|
|
2186
2493
|
69: (args) => {
|
|
2187
2494
|
const [lhsValue, rhsValue, variableValue] = args;
|
|
2188
2495
|
if (variableValue?.type !== 3 /* String */) {
|
|
2189
|
-
return
|
|
2496
|
+
return chunkJMXUNXQS_cjs.errorValue("SOLVE_REQUIRES_VARIABLE_NAME", "solve's second argument must be the name of the unknown.");
|
|
2190
2497
|
}
|
|
2191
2498
|
return solveEquationValues(lhsValue, rhsValue, variableValue.value);
|
|
2192
2499
|
},
|
|
@@ -2197,8 +2504,8 @@ var builtinFunctions = {
|
|
|
2197
2504
|
const variable = symbolicVariableName(variableValue, "der");
|
|
2198
2505
|
if (typeof variable !== "string") return variable;
|
|
2199
2506
|
const expression = valueToSymbolic(target);
|
|
2200
|
-
if (expression === null) return
|
|
2201
|
-
return symbolicToValue(
|
|
2507
|
+
if (expression === null) return chunkJMXUNXQS_cjs.errorValue("SYMBOLIC_NONFINITE_OPERAND", "der needs an expression with an exact value.");
|
|
2508
|
+
return symbolicToValue(differentiate2(expression, variable, orderValue?.toNumber() ?? 1));
|
|
2202
2509
|
},
|
|
2203
2510
|
// integral(expr, variable), the indefinite integral without a constant of
|
|
2204
2511
|
// integration. Reports what it cannot do rather than approximating; see
|
|
@@ -2208,9 +2515,9 @@ var builtinFunctions = {
|
|
|
2208
2515
|
const variable = symbolicVariableName(variableValue, "integral");
|
|
2209
2516
|
if (typeof variable !== "string") return variable;
|
|
2210
2517
|
const expression = valueToSymbolic(target);
|
|
2211
|
-
if (expression === null) return
|
|
2518
|
+
if (expression === null) return chunkJMXUNXQS_cjs.errorValue("SYMBOLIC_NONFINITE_OPERAND", "integral needs an expression with an exact value.");
|
|
2212
2519
|
const result = integrate(expression, variable);
|
|
2213
|
-
if (!result.ok) return
|
|
2520
|
+
if (!result.ok) return chunkJMXUNXQS_cjs.errorValue("SYMBOLIC_INTEGRAL_UNSUPPORTED", `Cannot integrate this: ${result.reason}.`);
|
|
2214
2521
|
return symbolicToValue(result.value);
|
|
2215
2522
|
},
|
|
2216
2523
|
// taylor(expr, variable = point, degree).
|
|
@@ -2221,7 +2528,7 @@ var builtinFunctions = {
|
|
|
2221
2528
|
const expression = valueToSymbolic(target);
|
|
2222
2529
|
const point = valueToSymbolic(pointValue);
|
|
2223
2530
|
if (expression === null || point === null || point.kind !== "const") {
|
|
2224
|
-
return
|
|
2531
|
+
return chunkJMXUNXQS_cjs.errorValue("SYMBOLIC_NONFINITE_OPERAND", "taylor needs an expression and an exact expansion point.");
|
|
2225
2532
|
}
|
|
2226
2533
|
return symbolicToValue(taylorSeries(expression, variable, point.value, degreeValue.toNumber()));
|
|
2227
2534
|
},
|
|
@@ -2231,23 +2538,23 @@ var builtinFunctions = {
|
|
|
2231
2538
|
const functions = [];
|
|
2232
2539
|
for (const arg of args) {
|
|
2233
2540
|
const node = valueToSymbolic(arg);
|
|
2234
|
-
if (node === null) return
|
|
2541
|
+
if (node === null) return chunkJMXUNXQS_cjs.errorValue("SYMBOLIC_NONFINITE_OPERAND", "jacobian needs expressions with exact values.");
|
|
2235
2542
|
functions.push(node);
|
|
2236
2543
|
}
|
|
2237
2544
|
const variables = /* @__PURE__ */ new Set();
|
|
2238
|
-
for (const fn of functions) for (const name of
|
|
2545
|
+
for (const fn of functions) for (const name of chunkUM6BVY2S_cjs.freeVariables(fn)) variables.add(name);
|
|
2239
2546
|
const sorted = [...variables].sort();
|
|
2240
|
-
if (sorted.length === 0) return
|
|
2547
|
+
if (sorted.length === 0) return chunkJMXUNXQS_cjs.errorValue("SYMBOLIC_JACOBIAN_NO_VARIABLES", "jacobian needs at least one unknown to differentiate against.");
|
|
2241
2548
|
const rows = jacobian(functions, sorted);
|
|
2242
2549
|
const rowMajor = [];
|
|
2243
2550
|
for (const row of rows) {
|
|
2244
|
-
for (const cell of row) rowMajor.push(
|
|
2551
|
+
for (const cell of row) rowMajor.push(chunkUM6BVY2S_cjs.symbolicToEntry(cell));
|
|
2245
2552
|
}
|
|
2246
|
-
return
|
|
2553
|
+
return chunkJMXUNXQS_cjs.matrixValue(rows.length, sorted.length, chunkUM6BVY2S_cjs.rowMajorToColumnMajor(rows.length, sorted.length, rowMajor));
|
|
2247
2554
|
},
|
|
2248
2555
|
// An imaginary literal, 3i. The parselet pushes the numeric part and this
|
|
2249
2556
|
// turns it into an exact imaginary value.
|
|
2250
|
-
74: (args) => symbolicToValue(
|
|
2557
|
+
74: (args) => symbolicToValue(chunkUM6BVY2S_cjs.complexNode(chunkUM6BVY2S_cjs.complex(chunkUM6BVY2S_cjs.RATIONAL_ZERO, chunkUM6BVY2S_cjs.rationalFromNumber(args[0].toNumber())))),
|
|
2251
2558
|
// conj(z), re(z) and im(z). Each folds immediately for a literal and stays
|
|
2252
2559
|
// symbolic for anything still carrying an unknown.
|
|
2253
2560
|
75: (args) => applyComplexAccessor("conj", args[0]),
|
|
@@ -2257,7 +2564,7 @@ var builtinFunctions = {
|
|
|
2257
2564
|
78: (args) => {
|
|
2258
2565
|
const value = args[0];
|
|
2259
2566
|
if (value.type !== 9 /* Symbolic */) return value;
|
|
2260
|
-
return symbolicToValue(
|
|
2567
|
+
return symbolicToValue(chunkUM6BVY2S_cjs.cancelSymbolic(value.value));
|
|
2261
2568
|
},
|
|
2262
2569
|
// apart(expr), the partial-fraction decomposition of a rational function.
|
|
2263
2570
|
79: (args) => {
|
|
@@ -2272,10 +2579,10 @@ var builtinFunctions = {
|
|
|
2272
2579
|
const amount = args[0].toNumber();
|
|
2273
2580
|
const rate = args[1].toNumber();
|
|
2274
2581
|
if (1 + rate <= 0) {
|
|
2275
|
-
return
|
|
2582
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", `taxIn: rate ${rate} makes (1 + rate) non-positive`);
|
|
2276
2583
|
}
|
|
2277
2584
|
const tax = amount - amount / (1 + rate);
|
|
2278
|
-
return args[0].type === 6 /* Uom */ ?
|
|
2585
|
+
return args[0].type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(tax, args[0].unit) : chunkJMXUNXQS_cjs.numberValue(tax);
|
|
2279
2586
|
},
|
|
2280
2587
|
// taxOn(amount, rate) -> amount * rate, the tax itself.
|
|
2281
2588
|
//
|
|
@@ -2288,21 +2595,21 @@ var builtinFunctions = {
|
|
|
2288
2595
|
const amount = args[0].toNumber();
|
|
2289
2596
|
const rate = args[1].toNumber();
|
|
2290
2597
|
const tax = amount * rate;
|
|
2291
|
-
return args[0].type === 6 /* Uom */ ?
|
|
2598
|
+
return args[0].type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(tax, args[0].unit) : chunkJMXUNXQS_cjs.numberValue(tax);
|
|
2292
2599
|
},
|
|
2293
2600
|
// ── Degree-taking trig (sind/cosd/tand and the inverses) ──────────────
|
|
2294
2601
|
// The "d" spellings take and return degrees rather than radians, which is
|
|
2295
2602
|
// the convention every scientific calculator uses. sin(90 degrees) is the
|
|
2296
2603
|
// other way to say the same thing; both exist because both get typed.
|
|
2297
|
-
87: (args) =>
|
|
2298
|
-
88: (args) =>
|
|
2299
|
-
89: (args) =>
|
|
2300
|
-
90: (args) =>
|
|
2301
|
-
91: (args) =>
|
|
2302
|
-
92: (args) =>
|
|
2604
|
+
87: (args) => chunkJMXUNXQS_cjs.numberValue(Math.sin(args[0].toNumber() * Math.PI / 180)),
|
|
2605
|
+
88: (args) => chunkJMXUNXQS_cjs.numberValue(Math.cos(args[0].toNumber() * Math.PI / 180)),
|
|
2606
|
+
89: (args) => chunkJMXUNXQS_cjs.numberValue(Math.tan(args[0].toNumber() * Math.PI / 180)),
|
|
2607
|
+
90: (args) => chunkJMXUNXQS_cjs.numberValue(Math.asin(args[0].toNumber()) * 180 / Math.PI),
|
|
2608
|
+
91: (args) => chunkJMXUNXQS_cjs.numberValue(Math.acos(args[0].toNumber()) * 180 / Math.PI),
|
|
2609
|
+
92: (args) => chunkJMXUNXQS_cjs.numberValue(Math.atan(args[0].toNumber()) * 180 / Math.PI),
|
|
2303
2610
|
// daysCount(n) -> n labelled as days. "days in Q3" is a count of days
|
|
2304
2611
|
// and should say so; a bare 92 loses what was being counted.
|
|
2305
|
-
93: (args) =>
|
|
2612
|
+
93: (args) => chunkJMXUNXQS_cjs.uomValue(args[0].toNumber(), "days"),
|
|
2306
2613
|
// asTwoUnits(value, majorUnit, minorUnit) -> "12 min 30 s".
|
|
2307
2614
|
//
|
|
2308
2615
|
// "12.5 minutes in minutes and seconds" asks for one quantity split
|
|
@@ -2313,25 +2620,28 @@ var builtinFunctions = {
|
|
|
2313
2620
|
// so nothing is lost. A pair that is not ordered major-then-minor, or
|
|
2314
2621
|
// that spans two different measures, reports rather than guessing.
|
|
2315
2622
|
94: (args) => {
|
|
2316
|
-
const major = args[1].value;
|
|
2317
|
-
const minor = args[2].value;
|
|
2318
|
-
|
|
2319
|
-
|
|
2623
|
+
const major = typeof args[1]?.value === "string" ? args[1].value : void 0;
|
|
2624
|
+
const minor = typeof args[2]?.value === "string" ? args[2].value : void 0;
|
|
2625
|
+
if (major === void 0 || minor === void 0) {
|
|
2626
|
+
return chunkJMXUNXQS_cjs.errorValue("UNKNOWN_UNIT", 'both units have to be named, as in "12.5 minutes in minutes and seconds"');
|
|
2627
|
+
}
|
|
2628
|
+
const majorEntry = chunkAMOJYLG2_cjs.UNIT_TABLE[major.toLowerCase()];
|
|
2629
|
+
const minorEntry = chunkAMOJYLG2_cjs.UNIT_TABLE[minor.toLowerCase()];
|
|
2320
2630
|
if (majorEntry === void 0 || minorEntry === void 0) {
|
|
2321
|
-
return
|
|
2631
|
+
return chunkJMXUNXQS_cjs.errorValue("UNKNOWN_UNIT", `${major} and ${minor}: one of these is not a unit`);
|
|
2322
2632
|
}
|
|
2323
2633
|
if (majorEntry[0] !== minorEntry[0]) {
|
|
2324
|
-
return
|
|
2634
|
+
return chunkJMXUNXQS_cjs.errorValue("INCOMPATIBLE_UNITS", `${major} and ${minor} measure different things`);
|
|
2325
2635
|
}
|
|
2326
2636
|
if (minorEntry[1] >= majorEntry[1]) {
|
|
2327
|
-
return
|
|
2637
|
+
return chunkJMXUNXQS_cjs.errorValue("INCOMPATIBLE_UNITS", `${major} and ${minor}: name the larger unit first`);
|
|
2328
2638
|
}
|
|
2329
2639
|
const source = args[0];
|
|
2330
|
-
const sourceEntry = source.type === 6 /* Uom */ && source.unit !== void 0 ?
|
|
2640
|
+
const sourceEntry = source.type === 6 /* Uom */ && source.unit !== void 0 ? chunkAMOJYLG2_cjs.UNIT_TABLE[source.unit.toLowerCase()] : void 0;
|
|
2331
2641
|
const inBase = source.toNumber() * (sourceEntry?.[1] ?? majorEntry[1]);
|
|
2332
2642
|
const majorCount = Math.floor(inBase / majorEntry[1]);
|
|
2333
2643
|
const minorCount = Math.round((inBase - majorCount * majorEntry[1]) / minorEntry[1] * 1e3) / 1e3;
|
|
2334
|
-
return
|
|
2644
|
+
return chunkJMXUNXQS_cjs.stringValue(`${majorCount} ${major} ${minorCount} ${minor}`);
|
|
2335
2645
|
},
|
|
2336
2646
|
// makeRate(value, denominatorUnit) -> value per that unit.
|
|
2337
2647
|
//
|
|
@@ -2347,9 +2657,9 @@ var builtinFunctions = {
|
|
|
2347
2657
|
const denominator = String(args[1].value);
|
|
2348
2658
|
const numerator = source.type === 6 /* Uom */ && source.unit !== void 0 ? source.unit : "";
|
|
2349
2659
|
if (numerator.includes("/")) {
|
|
2350
|
-
return
|
|
2660
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE_UNIT", `${numerator}/${denominator}: that is already a rate`);
|
|
2351
2661
|
}
|
|
2352
|
-
return
|
|
2662
|
+
return chunkJMXUNXQS_cjs.uomValue(source.toNumber(), `${numerator}/${denominator}`);
|
|
2353
2663
|
},
|
|
2354
2664
|
// atRate(quantity, rate) -> whichever of the two the question implies.
|
|
2355
2665
|
//
|
|
@@ -2364,28 +2674,28 @@ var builtinFunctions = {
|
|
|
2364
2674
|
const left = args[0];
|
|
2365
2675
|
const rate = args[1];
|
|
2366
2676
|
if (rate.type !== 6 /* Uom */ || rate.unit === void 0 || !rate.unit.includes("/")) {
|
|
2367
|
-
return
|
|
2677
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", 'at: the right-hand side has to be a rate, as in "$30/hour"');
|
|
2368
2678
|
}
|
|
2369
2679
|
const slash = rate.unit.indexOf("/");
|
|
2370
2680
|
const numerator = rate.unit.slice(0, slash);
|
|
2371
2681
|
const denominator = rate.unit.slice(slash + 1);
|
|
2372
2682
|
const leftUnit = left.type === 6 /* Uom */ ? left.unit : void 0;
|
|
2373
|
-
const denominatorEntry =
|
|
2374
|
-
const leftEntry = leftUnit === void 0 ? void 0 :
|
|
2683
|
+
const denominatorEntry = chunkAMOJYLG2_cjs.UNIT_TABLE[denominator.toLowerCase()];
|
|
2684
|
+
const leftEntry = leftUnit === void 0 ? void 0 : chunkAMOJYLG2_cjs.UNIT_TABLE[leftUnit.toLowerCase()];
|
|
2375
2685
|
if (leftEntry !== void 0 && denominatorEntry !== void 0 && leftEntry[0] === denominatorEntry[0]) {
|
|
2376
2686
|
const inDenominator = left.toNumber() * leftEntry[1] / denominatorEntry[1];
|
|
2377
2687
|
const total = inDenominator * rate.toNumber();
|
|
2378
|
-
return numerator === "" ?
|
|
2688
|
+
return numerator === "" ? chunkJMXUNXQS_cjs.numberValue(total) : chunkJMXUNXQS_cjs.uomValue(total, numerator);
|
|
2379
2689
|
}
|
|
2380
2690
|
if (leftUnit !== void 0 && leftUnit === numerator) {
|
|
2381
2691
|
const count = left.toNumber() / rate.toNumber();
|
|
2382
|
-
return
|
|
2692
|
+
return chunkJMXUNXQS_cjs.uomValue(count, pluraliseUnit(denominator, count));
|
|
2383
2693
|
}
|
|
2384
2694
|
if (leftUnit === void 0) {
|
|
2385
2695
|
const total = left.toNumber() * rate.toNumber();
|
|
2386
|
-
return numerator === "" ?
|
|
2696
|
+
return numerator === "" ? chunkJMXUNXQS_cjs.numberValue(total) : chunkJMXUNXQS_cjs.uomValue(total, numerator);
|
|
2387
2697
|
}
|
|
2388
|
-
return
|
|
2698
|
+
return chunkJMXUNXQS_cjs.errorValue("INCOMPATIBLE_UNITS", `at: ${leftUnit} matches neither side of ${rate.unit}`);
|
|
2389
2699
|
},
|
|
2390
2700
|
// ── Investments (packages/finance/) ────────────────────────────────────
|
|
2391
2701
|
// compoundFutureValueEvery(principal, rate, years, periodsPerYear)
|
|
@@ -2400,13 +2710,13 @@ var builtinFunctions = {
|
|
|
2400
2710
|
const years = args[2].toNumber();
|
|
2401
2711
|
const perYear = args[3].toNumber();
|
|
2402
2712
|
if (perYear <= 0) {
|
|
2403
|
-
return
|
|
2713
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", `compounding: ${perYear} periods per year is not a period`);
|
|
2404
2714
|
}
|
|
2405
2715
|
if (1 + rate / perYear <= 0) {
|
|
2406
|
-
return
|
|
2716
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", `compounding: rate ${rate} makes each period non-positive`);
|
|
2407
2717
|
}
|
|
2408
2718
|
const fv = principal * Math.pow(1 + rate / perYear, perYear * years);
|
|
2409
|
-
return args[0].type === 6 /* Uom */ ?
|
|
2719
|
+
return args[0].type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(fv, args[0].unit) : chunkJMXUNXQS_cjs.numberValue(fv);
|
|
2410
2720
|
},
|
|
2411
2721
|
// compoundInterestEarnedEvery(principal, rate, years, periodsPerYear)
|
|
2412
2722
|
// The interest-only portion of index 80, i.e. FV - P.
|
|
@@ -2416,10 +2726,10 @@ var builtinFunctions = {
|
|
|
2416
2726
|
const years = args[2].toNumber();
|
|
2417
2727
|
const perYear = args[3].toNumber();
|
|
2418
2728
|
if (perYear <= 0 || 1 + rate / perYear <= 0) {
|
|
2419
|
-
return
|
|
2729
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", `compounding: rate ${rate} over ${perYear} periods per year is not usable`);
|
|
2420
2730
|
}
|
|
2421
2731
|
const interest = principal * (Math.pow(1 + rate / perYear, perYear * years) - 1);
|
|
2422
|
-
return args[0].type === 6 /* Uom */ ?
|
|
2732
|
+
return args[0].type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(interest, args[0].unit) : chunkJMXUNXQS_cjs.numberValue(interest);
|
|
2423
2733
|
},
|
|
2424
2734
|
// presentValue(futureValue, rate, years) -> FV / (1 + r)^y, what a sum
|
|
2425
2735
|
// promised in the future is worth today. The inverse of index 51.
|
|
@@ -2428,10 +2738,10 @@ var builtinFunctions = {
|
|
|
2428
2738
|
const rate = args[1].toNumber();
|
|
2429
2739
|
const years = args[2].toNumber();
|
|
2430
2740
|
if (1 + rate <= 0) {
|
|
2431
|
-
return
|
|
2741
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", `presentValue: rate ${rate} makes (1 + rate) non-positive`);
|
|
2432
2742
|
}
|
|
2433
2743
|
const pv = future / Math.pow(1 + rate, years);
|
|
2434
|
-
return args[0].type === 6 /* Uom */ ?
|
|
2744
|
+
return args[0].type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(pv, args[0].unit) : chunkJMXUNXQS_cjs.numberValue(pv);
|
|
2435
2745
|
},
|
|
2436
2746
|
// returnOnInvestment(invested, returned) -> (returned - invested) /
|
|
2437
2747
|
// invested, the gain as a multiple of what was put in. $500 in and $1,500
|
|
@@ -2442,9 +2752,9 @@ var builtinFunctions = {
|
|
|
2442
2752
|
const invested = args[0].toNumber();
|
|
2443
2753
|
const returned = args[1].toNumber();
|
|
2444
2754
|
if (invested === 0) {
|
|
2445
|
-
return
|
|
2755
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", "roi: nothing was invested, so there is no return on it");
|
|
2446
2756
|
}
|
|
2447
|
-
return
|
|
2757
|
+
return chunkJMXUNXQS_cjs.numberValue((returned - invested) / invested);
|
|
2448
2758
|
},
|
|
2449
2759
|
// annualisedReturn(invested, returned, years) -> CAGR, the constant
|
|
2450
2760
|
// yearly rate that turns `invested` into `returned` over `years`:
|
|
@@ -2455,25 +2765,45 @@ var builtinFunctions = {
|
|
|
2455
2765
|
const returned = args[1].toNumber();
|
|
2456
2766
|
const years = args[2].toNumber();
|
|
2457
2767
|
if (invested <= 0) {
|
|
2458
|
-
return
|
|
2768
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", "annual return: the amount invested must be positive");
|
|
2459
2769
|
}
|
|
2460
2770
|
if (years <= 0) {
|
|
2461
|
-
return
|
|
2771
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", "annual return: the period must be longer than zero");
|
|
2462
2772
|
}
|
|
2463
2773
|
if (returned <= 0) {
|
|
2464
|
-
return
|
|
2774
|
+
return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", "annual return: nothing was returned, so there is no annual rate");
|
|
2465
2775
|
}
|
|
2466
|
-
return
|
|
2776
|
+
return chunkJMXUNXQS_cjs.percentageValue(Math.pow(returned / invested, 1 / years) - 1);
|
|
2777
|
+
},
|
|
2778
|
+
// roundToPlaces(value, places) -> value rounded to that many decimal
|
|
2779
|
+
// places, backing `<value> to <n> dp` (converters/parselets/
|
|
2780
|
+
// RoundingParselets.ts).
|
|
2781
|
+
//
|
|
2782
|
+
// It exists because the obvious bytecode for it, "multiply by 10^p, round,
|
|
2783
|
+
// divide by 10^p", is only safe for values small enough that the multiply
|
|
2784
|
+
// is exact. `1e21 to 2 dp` came back as 999999999999999900000: 1e21 has no
|
|
2785
|
+
// fractional part to round at all, and the round trip through 1e23 was
|
|
2786
|
+
// pure loss. Asking for fewer decimal places than a number has cannot
|
|
2787
|
+
// change it, so a value that is already whole is returned untouched.
|
|
2788
|
+
97: (args) => {
|
|
2789
|
+
const source = args[0];
|
|
2790
|
+
const value = source.toNumber();
|
|
2791
|
+
const places = args[1].toNumber();
|
|
2792
|
+
if (!Number.isFinite(value) || Number.isInteger(value)) return keepUnit(source, value);
|
|
2793
|
+
const scale2 = Math.pow(10, places);
|
|
2794
|
+
const scaled = value * scale2;
|
|
2795
|
+
if (!Number.isFinite(scaled) || Math.abs(scaled) > Number.MAX_SAFE_INTEGER) return keepUnit(source, value);
|
|
2796
|
+
return keepUnit(source, Math.round(scaled) / scale2);
|
|
2467
2797
|
}
|
|
2468
2798
|
};
|
|
2469
2799
|
function applyComplexAccessor(name, value) {
|
|
2470
2800
|
const node = valueToSymbolic(value);
|
|
2471
|
-
if (node === null) return
|
|
2472
|
-
return symbolicToValue(
|
|
2801
|
+
if (node === null) return chunkJMXUNXQS_cjs.errorValue("SYMBOLIC_NONFINITE_OPERAND", name + " needs a value with an exact number.");
|
|
2802
|
+
return symbolicToValue(chunkUM6BVY2S_cjs.callNode(name, [node]));
|
|
2473
2803
|
}
|
|
2474
2804
|
function symbolicVariableName(value, verb) {
|
|
2475
2805
|
if (value?.type !== 3 /* String */) {
|
|
2476
|
-
return
|
|
2806
|
+
return chunkJMXUNXQS_cjs.errorValue("SYMBOLIC_REQUIRES_VARIABLE_NAME", `${verb} needs the name of an unknown.`);
|
|
2477
2807
|
}
|
|
2478
2808
|
return value.value;
|
|
2479
2809
|
}
|
|
@@ -2490,7 +2820,7 @@ var MAX_PLUGIN_FUNCTION_INDEX = 255;
|
|
|
2490
2820
|
var nextPluginFunctionIndex = 0;
|
|
2491
2821
|
function allocatePluginFunctionIndex() {
|
|
2492
2822
|
if (nextPluginFunctionIndex > MAX_PLUGIN_FUNCTION_INDEX) {
|
|
2493
|
-
throw
|
|
2823
|
+
throw chunk5KMIY374_cjs.ErrorFactory.config(
|
|
2494
2824
|
"PLUGIN_FUNCTION_INDEX_POOL_EXHAUSTED",
|
|
2495
2825
|
`allocatePluginFunctionIndex: pool exhausted (max ${MAX_PLUGIN_FUNCTION_INDEX + 1} allocations).`
|
|
2496
2826
|
);
|
|
@@ -2621,12 +2951,17 @@ exports.SYMBOLIC_NATIVE_BUILTINS = SYMBOLIC_NATIVE_BUILTINS;
|
|
|
2621
2951
|
exports.adjustForInflation = adjustForInflation;
|
|
2622
2952
|
exports.allocatePluginFunctionIndex = allocatePluginFunctionIndex;
|
|
2623
2953
|
exports.asConverterRegistry = asConverterRegistry;
|
|
2954
|
+
exports.bigIntDivisionByZero = bigIntDivisionByZero;
|
|
2624
2955
|
exports.binaryOp = binaryOp;
|
|
2625
2956
|
exports.builtinFunctions = builtinFunctions;
|
|
2957
|
+
exports.compareBigIntOperands = compareBigIntOperands;
|
|
2958
|
+
exports.compareUom = compareUom;
|
|
2626
2959
|
exports.createEngineContext = createEngineContext;
|
|
2627
2960
|
exports.defaultEngineContext = defaultEngineContext;
|
|
2628
2961
|
exports.globalDagKey = globalDagKey;
|
|
2962
|
+
exports.incomparableUnitsError = incomparableUnitsError;
|
|
2629
2963
|
exports.pluginFunctionRegistry = pluginFunctionRegistry;
|
|
2964
|
+
exports.power = power;
|
|
2630
2965
|
exports.registerAsConverter = registerAsConverter;
|
|
2631
2966
|
exports.sharedGlobalVariableStore = sharedGlobalVariableStore;
|
|
2632
2967
|
exports.sharedOpRegistry = sharedOpRegistry;
|
|
@@ -2634,7 +2969,8 @@ exports.solveEquationValues = solveEquationValues;
|
|
|
2634
2969
|
exports.symbolicBuiltin = symbolicBuiltin;
|
|
2635
2970
|
exports.symbolicNeg = symbolicNeg;
|
|
2636
2971
|
exports.symbolicPow = symbolicPow;
|
|
2972
|
+
exports.toBigIntOperand = toBigIntOperand;
|
|
2637
2973
|
exports.unifyUom = unifyUom;
|
|
2638
2974
|
exports.unregisterAsConverter = unregisterAsConverter;
|
|
2639
|
-
//# sourceMappingURL=chunk-
|
|
2640
|
-
//# sourceMappingURL=chunk-
|
|
2975
|
+
//# sourceMappingURL=chunk-6WFMPTGB.cjs.map
|
|
2976
|
+
//# sourceMappingURL=chunk-6WFMPTGB.cjs.map
|