solve-engine 1.1.1 → 2.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/README.md +12 -17
- package/dist/{BytecodeBuilder-Bp9xeTmX.d.cts → BytecodeBuilder-DGGeByAP.d.cts} +18 -0
- package/dist/{BytecodeBuilder-Bp9xeTmX.d.ts → BytecodeBuilder-DGGeByAP.d.ts} +18 -0
- package/dist/{Configuration-C9W8tJv_.d.cts → Configuration-B6W0-T67.d.cts} +17 -4
- package/dist/{Configuration-C9W8tJv_.d.ts → Configuration-B6W0-T67.d.ts} +17 -4
- package/dist/{EngineError-B61GS1jp.d.cts → EngineError-Ce1lPkjZ.d.cts} +8 -0
- package/dist/{EngineError-B61GS1jp.d.ts → EngineError-Ce1lPkjZ.d.ts} +8 -0
- package/dist/{Lexer-BOs7euZe.d.cts → Lexer-B4C1qHXu.d.cts} +1 -1
- package/dist/{Lexer-CSI_lwbW.d.ts → Lexer-DKMlj7Sy.d.ts} +1 -1
- package/dist/{PackageCompatibility-B-7rK1TD.d.cts → PackageCompatibility-Bn5jnBtA.d.cts} +2 -2
- package/dist/{PackageCompatibility-Dh59eF-X.d.ts → PackageCompatibility-CIvq2MP5.d.ts} +2 -2
- package/dist/{PackageRegistry-_8rDlvxI.d.ts → PackageRegistry-DzeiWcv4.d.ts} +143 -175
- package/dist/{PackageRegistry-BHWJP83F.d.cts → PackageRegistry-dpdurBVO.d.cts} +143 -175
- package/dist/{Parselet-BBT8riYh.d.ts → Parselet-B-zoPrTa.d.ts} +9 -6
- package/dist/{Parselet-BHcgK9S7.d.cts → Parselet-C4Wu055_.d.cts} +9 -6
- package/dist/{ScopeManager-CxA24W5n.d.ts → ScopeManager-C2LDOrDx.d.ts} +14 -16
- package/dist/{ScopeManager-8vf02dwj.d.cts → ScopeManager-D7uMXbhS.d.cts} +14 -16
- package/dist/{Token-B1hdkedD.d.cts → Token-CbP_OutD.d.cts} +9 -0
- package/dist/{Token-B1hdkedD.d.ts → Token-CbP_OutD.d.ts} +9 -0
- package/dist/{TokenNormalizer-C6VzZgHa.d.ts → TokenNormalizer-DCWdZjGz.d.ts} +1 -1
- package/dist/{TokenNormalizer-DRc1Js1V.d.cts → TokenNormalizer-DnlL7_8c.d.cts} +1 -1
- package/dist/{VMCheckpoints-MK--EBH2.d.ts → VMCheckpoints-CGyFhivM.d.ts} +3 -3
- package/dist/{VMCheckpoints-ELYqITdF.d.cts → VMCheckpoints-I9jg3jWR.d.cts} +3 -3
- package/dist/{Value-BUi1RA3S.d.cts → Value-CCi_Eecs.d.cts} +72 -5
- package/dist/{Value-BUi1RA3S.d.ts → Value-CCi_Eecs.d.ts} +72 -5
- package/dist/{WorkerError-gzmaopj2.d.cts → WorkerError-B4p6PNfx.d.cts} +1 -1
- package/dist/{WorkerError-_-RkoQ5P.d.ts → WorkerError-Dhj9BQ_A.d.ts} +1 -1
- package/dist/chunk-2JMFUQZH.js +2 -0
- package/dist/chunk-2JMFUQZH.js.map +1 -0
- package/dist/chunk-2RWAXT6O.js +0 -1
- package/dist/chunk-4BZIYU7S.cjs +3 -0
- package/dist/chunk-4BZIYU7S.cjs.map +1 -0
- package/dist/chunk-4J7XZSZJ.cjs +5 -0
- package/dist/chunk-4J7XZSZJ.cjs.map +1 -0
- package/dist/chunk-4QVBSG6B.cjs +2 -0
- package/dist/chunk-4QVBSG6B.cjs.map +1 -0
- package/dist/chunk-5IJD5L3O.cjs +2 -0
- package/dist/chunk-5IJD5L3O.cjs.map +1 -0
- package/dist/chunk-62LMTO4F.js +2 -0
- package/dist/chunk-62LMTO4F.js.map +1 -0
- package/dist/chunk-6CY44ZPG.js +2 -0
- package/dist/chunk-6CY44ZPG.js.map +1 -0
- package/dist/chunk-6G3PMEPA.js +2 -0
- package/dist/chunk-6G3PMEPA.js.map +1 -0
- package/dist/chunk-6INX773F.cjs +2 -0
- package/dist/chunk-6INX773F.cjs.map +1 -0
- package/dist/chunk-6KFVG6UY.cjs +2 -0
- package/dist/chunk-6KFVG6UY.cjs.map +1 -0
- package/dist/chunk-76F3LCIL.js +4 -0
- package/dist/chunk-76F3LCIL.js.map +1 -0
- package/dist/chunk-7GK3XEZF.js +2 -0
- package/dist/chunk-7GK3XEZF.js.map +1 -0
- package/dist/chunk-APN442VD.cjs +2 -0
- package/dist/chunk-APN442VD.cjs.map +1 -0
- package/dist/chunk-AXMQG5TS.cjs +2 -0
- package/dist/chunk-AXMQG5TS.cjs.map +1 -0
- package/dist/chunk-CIQOK7Q4.cjs +2 -0
- package/dist/chunk-CIQOK7Q4.cjs.map +1 -0
- package/dist/chunk-E6Z4NQAS.js +2 -0
- package/dist/chunk-E6Z4NQAS.js.map +1 -0
- package/dist/chunk-EFJCC6FJ.cjs +2 -0
- package/dist/chunk-EFJCC6FJ.cjs.map +1 -0
- package/dist/chunk-ESUN2THE.cjs +2 -0
- package/dist/chunk-ESUN2THE.cjs.map +1 -0
- package/dist/chunk-EVAOPEO4.js +2 -0
- package/dist/chunk-EVAOPEO4.js.map +1 -0
- package/dist/chunk-EYRBENHC.js +3 -0
- package/dist/chunk-EYRBENHC.js.map +1 -0
- package/dist/chunk-FDE5HWDI.cjs +2 -0
- package/dist/chunk-FDE5HWDI.cjs.map +1 -0
- package/dist/chunk-FWW3M36J.cjs +2 -0
- package/dist/chunk-FWW3M36J.cjs.map +1 -0
- package/dist/chunk-GOIQYUWV.js +2 -0
- package/dist/chunk-GOIQYUWV.js.map +1 -0
- package/dist/chunk-HFKDWQUL.js +2 -0
- package/dist/chunk-HFKDWQUL.js.map +1 -0
- package/dist/chunk-HLBYHXQD.cjs +3 -0
- package/dist/chunk-HLBYHXQD.cjs.map +1 -0
- package/dist/chunk-IANAMBJQ.cjs +2 -0
- package/dist/chunk-IANAMBJQ.cjs.map +1 -0
- package/dist/chunk-IJMNVBIS.js +2 -0
- package/dist/chunk-IJMNVBIS.js.map +1 -0
- package/dist/chunk-J4LZD4ZY.js +3 -0
- package/dist/chunk-J4LZD4ZY.js.map +1 -0
- package/dist/chunk-JAK3RAFA.cjs +2 -0
- package/dist/chunk-JAK3RAFA.cjs.map +1 -0
- package/dist/chunk-JFAJN3C2.cjs +2 -0
- package/dist/chunk-JFAJN3C2.cjs.map +1 -0
- package/dist/chunk-JPFCXLJV.js +2 -0
- package/dist/chunk-JPFCXLJV.js.map +1 -0
- package/dist/chunk-JSPKKNPQ.js +3 -0
- package/dist/chunk-JSPKKNPQ.js.map +1 -0
- package/dist/chunk-L3FPQSGN.js +2 -0
- package/dist/chunk-L3FPQSGN.js.map +1 -0
- package/dist/chunk-LR4E4A4W.cjs +2 -0
- package/dist/chunk-LR4E4A4W.cjs.map +1 -0
- package/dist/chunk-MIQBJGGR.js +2 -0
- package/dist/chunk-MIQBJGGR.js.map +1 -0
- package/dist/chunk-MPB7KUN5.js +3 -0
- package/dist/chunk-MPB7KUN5.js.map +1 -0
- package/dist/chunk-MSYX32PF.cjs +2 -0
- package/dist/chunk-MSYX32PF.cjs.map +1 -0
- package/dist/chunk-MVZUTETT.js +2 -0
- package/dist/chunk-MVZUTETT.js.map +1 -0
- package/dist/chunk-N7N7MPMK.cjs +2 -0
- package/dist/chunk-N7N7MPMK.cjs.map +1 -0
- package/dist/chunk-NGBBNL4K.cjs +1 -3
- package/dist/chunk-P6WPEUAJ.cjs +2 -0
- package/dist/chunk-P6WPEUAJ.cjs.map +1 -0
- package/dist/chunk-PS272DZJ.cjs +2 -0
- package/dist/chunk-PS272DZJ.cjs.map +1 -0
- package/dist/chunk-QXQE7X4S.js +2 -0
- package/dist/chunk-QXQE7X4S.js.map +1 -0
- package/dist/chunk-R2ENWQ76.js +2 -0
- package/dist/chunk-R2ENWQ76.js.map +1 -0
- package/dist/chunk-R2SZFJTT.cjs +2 -0
- package/dist/chunk-R2SZFJTT.cjs.map +1 -0
- package/dist/chunk-RAF57WYO.js +2 -0
- package/dist/chunk-RAF57WYO.js.map +1 -0
- package/dist/chunk-RSF25YSJ.js +2 -0
- package/dist/chunk-RSF25YSJ.js.map +1 -0
- package/dist/chunk-SOMGSIO4.cjs +3 -0
- package/dist/chunk-SOMGSIO4.cjs.map +1 -0
- package/dist/chunk-SUXRZWH2.cjs +3 -0
- package/dist/chunk-SUXRZWH2.cjs.map +1 -0
- package/dist/chunk-SYYE3QAX.cjs +2 -0
- package/dist/chunk-SYYE3QAX.cjs.map +1 -0
- package/dist/chunk-SZGK6RIP.cjs +2 -0
- package/dist/chunk-SZGK6RIP.cjs.map +1 -0
- package/dist/chunk-TCZSPH4A.js +2 -0
- package/dist/chunk-TCZSPH4A.js.map +1 -0
- package/dist/chunk-TLG7VZRX.cjs +2 -0
- package/dist/chunk-TLG7VZRX.cjs.map +1 -0
- package/dist/chunk-TRBXW6HW.js +2 -0
- package/dist/{chunk-AQNHHJMJ.cjs.map → chunk-TRBXW6HW.js.map} +1 -1
- package/dist/chunk-TTFO4YDP.cjs +2 -0
- package/dist/chunk-TTFO4YDP.cjs.map +1 -0
- package/dist/chunk-TWC7K3ZX.js +2 -0
- package/dist/chunk-TWC7K3ZX.js.map +1 -0
- package/dist/chunk-UDQ57ZRX.cjs +2 -0
- package/dist/chunk-UDQ57ZRX.cjs.map +1 -0
- package/dist/chunk-UI6IFGBT.js +2 -0
- package/dist/chunk-UI6IFGBT.js.map +1 -0
- package/dist/chunk-UURM7P3P.cjs +4 -0
- package/dist/chunk-UURM7P3P.cjs.map +1 -0
- package/dist/chunk-W2JAR233.js +2 -0
- package/dist/chunk-W2JAR233.js.map +1 -0
- package/dist/chunk-WGZ3FNHI.js +2 -0
- package/dist/chunk-WGZ3FNHI.js.map +1 -0
- package/dist/chunk-WN5CMP4T.cjs +3 -0
- package/dist/chunk-WN5CMP4T.cjs.map +1 -0
- package/dist/chunk-XEIDV5JP.js +2 -0
- package/dist/chunk-XEIDV5JP.js.map +1 -0
- package/dist/chunk-XNIWQHXY.js +2 -0
- package/dist/chunk-XNIWQHXY.js.map +1 -0
- package/dist/chunk-XR7HEC7B.js +5 -0
- package/dist/chunk-XR7HEC7B.js.map +1 -0
- package/dist/chunk-Y7O4D3BJ.cjs +2 -0
- package/dist/chunk-Y7O4D3BJ.cjs.map +1 -0
- package/dist/chunk-YAYBVVG2.js +3 -0
- package/dist/chunk-YAYBVVG2.js.map +1 -0
- package/dist/chunk-YJ2OPULK.js +2 -0
- package/dist/chunk-YJ2OPULK.js.map +1 -0
- package/dist/chunk-YVKHEAFT.js +2 -0
- package/dist/chunk-YVKHEAFT.js.map +1 -0
- package/dist/chunk-ZCNBT44X.cjs +2 -0
- package/dist/chunk-ZCNBT44X.cjs.map +1 -0
- package/dist/chunk-ZLRJ7TDP.cjs +2 -0
- package/dist/chunk-ZLRJ7TDP.cjs.map +1 -0
- package/dist/constants.cjs +1 -21
- package/dist/constants.d.cts +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -4
- package/dist/engine.cjs +1 -94
- package/dist/engine.d.cts +29 -14
- package/dist/engine.d.ts +29 -14
- package/dist/engine.js +1 -37
- package/dist/errors.cjs +1 -105
- package/dist/errors.d.cts +3 -3
- package/dist/errors.d.ts +3 -3
- package/dist/errors.js +1 -4
- package/dist/format.cjs +1 -26
- package/dist/format.d.cts +2 -2
- package/dist/format.d.ts +2 -2
- package/dist/format.js +1 -9
- package/dist/index.cjs +1 -314
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -23
- package/dist/index.d.ts +55 -23
- package/dist/index.js +1 -278
- package/dist/index.js.map +1 -1
- package/dist/language.cjs +1 -369
- package/dist/language.cjs.map +1 -1
- package/dist/language.d.cts +12 -13
- package/dist/language.d.ts +12 -13
- package/dist/language.js +1 -348
- package/dist/language.js.map +1 -1
- package/dist/lexer.cjs +1 -63
- package/dist/lexer.d.cts +3 -3
- package/dist/lexer.d.ts +3 -3
- package/dist/lexer.js +1 -10
- package/dist/normalizer.cjs +1 -39
- package/dist/normalizer.d.cts +3 -3
- package/dist/normalizer.d.ts +3 -3
- package/dist/normalizer.js +1 -10
- package/dist/packages.cjs +1 -128
- package/dist/packages.d.cts +39 -14
- package/dist/packages.d.ts +39 -14
- package/dist/packages.js +1 -23
- package/dist/parser.cjs +1 -54
- package/dist/parser.d.cts +9 -9
- package/dist/parser.d.ts +9 -9
- package/dist/parser.js +1 -9
- package/dist/{pipeline-CtfJtPQc.d.cts → pipeline-72QmQlGx.d.ts} +3 -3
- package/dist/{pipeline-DCd5M6Gk.d.ts → pipeline-DCQicwWX.d.cts} +3 -3
- package/dist/resolvers.cjs +1 -12
- package/dist/resolvers.d.cts +3 -3
- package/dist/resolvers.d.ts +3 -3
- package/dist/resolvers.js +1 -3
- package/dist/services.cjs +1 -20
- package/dist/services.js +1 -3
- package/dist/testing.cjs +3 -477
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +12 -13
- package/dist/testing.d.ts +12 -13
- package/dist/testing.js +3 -469
- package/dist/testing.js.map +1 -1
- package/dist/uom.cjs +1 -55
- package/dist/uom.d.cts +3 -3
- package/dist/uom.d.ts +3 -3
- package/dist/uom.js +1 -10
- package/dist/utilities.cjs +1 -36
- package/dist/utilities.js +1 -7
- package/dist/vm.cjs +1 -295
- package/dist/vm.cjs.map +1 -1
- package/dist/vm.d.cts +22 -10
- package/dist/vm.d.ts +22 -10
- package/dist/vm.js +1 -193
- package/dist/vm.js.map +1 -1
- package/dist/worker.cjs +2 -492
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.cts +19 -20
- package/dist/worker.d.ts +19 -20
- package/dist/worker.js +2 -483
- package/dist/worker.js.map +1 -1
- package/package.json +1 -13
- package/dist/chunk-267JPOTF.js +0 -406
- package/dist/chunk-267JPOTF.js.map +0 -1
- package/dist/chunk-2TZKENDH.cjs +0 -448
- package/dist/chunk-2TZKENDH.cjs.map +0 -1
- package/dist/chunk-3BOK2LDK.js +0 -17
- package/dist/chunk-3BOK2LDK.js.map +0 -1
- package/dist/chunk-3OWCDIPN.js +0 -215
- package/dist/chunk-3OWCDIPN.js.map +0 -1
- package/dist/chunk-3VGDNEE3.js +0 -84
- package/dist/chunk-3VGDNEE3.js.map +0 -1
- package/dist/chunk-4D6NIHE2.js +0 -451
- package/dist/chunk-4D6NIHE2.js.map +0 -1
- package/dist/chunk-4HQKTMWG.js +0 -7985
- package/dist/chunk-4HQKTMWG.js.map +0 -1
- package/dist/chunk-536WPM2V.cjs +0 -283
- package/dist/chunk-536WPM2V.cjs.map +0 -1
- package/dist/chunk-5HRB36DK.js +0 -405
- package/dist/chunk-5HRB36DK.js.map +0 -1
- package/dist/chunk-5ON7PUAZ.js +0 -12
- package/dist/chunk-5ON7PUAZ.js.map +0 -1
- package/dist/chunk-7KYSUDQO.js +0 -109
- package/dist/chunk-7KYSUDQO.js.map +0 -1
- package/dist/chunk-7ZX6B7SY.cjs +0 -3222
- package/dist/chunk-7ZX6B7SY.cjs.map +0 -1
- package/dist/chunk-ADBA3XBE.cjs +0 -20
- package/dist/chunk-ADBA3XBE.cjs.map +0 -1
- package/dist/chunk-ALYRJ72W.cjs +0 -434
- package/dist/chunk-ALYRJ72W.cjs.map +0 -1
- package/dist/chunk-AMOJYLG2.cjs +0 -1692
- package/dist/chunk-AMOJYLG2.cjs.map +0 -1
- package/dist/chunk-AQNHHJMJ.cjs +0 -261
- package/dist/chunk-B4HBEFTB.cjs +0 -375
- package/dist/chunk-B4HBEFTB.cjs.map +0 -1
- package/dist/chunk-B7LXJ6LC.cjs +0 -36
- package/dist/chunk-B7LXJ6LC.cjs.map +0 -1
- package/dist/chunk-B7NLZMQ3.cjs +0 -74
- package/dist/chunk-B7NLZMQ3.cjs.map +0 -1
- package/dist/chunk-BLI4NIQY.js +0 -98
- package/dist/chunk-BLI4NIQY.js.map +0 -1
- package/dist/chunk-BYJBUL7U.js +0 -499
- package/dist/chunk-BYJBUL7U.js.map +0 -1
- package/dist/chunk-CCBZZQAE.js +0 -312
- package/dist/chunk-CCBZZQAE.js.map +0 -1
- package/dist/chunk-CKQMXMHR.cjs +0 -219
- package/dist/chunk-CKQMXMHR.cjs.map +0 -1
- package/dist/chunk-CUR2WLI4.cjs +0 -507
- package/dist/chunk-CUR2WLI4.cjs.map +0 -1
- package/dist/chunk-DLEBSLF4.js +0 -336
- package/dist/chunk-DLEBSLF4.js.map +0 -1
- package/dist/chunk-E23GZEWL.cjs +0 -209
- package/dist/chunk-E23GZEWL.cjs.map +0 -1
- package/dist/chunk-EJ3ILXX6.cjs +0 -223
- package/dist/chunk-EJ3ILXX6.cjs.map +0 -1
- package/dist/chunk-ENKKJYD3.js +0 -333
- package/dist/chunk-ENKKJYD3.js.map +0 -1
- package/dist/chunk-ENRIK36Q.cjs +0 -94
- package/dist/chunk-ENRIK36Q.cjs.map +0 -1
- package/dist/chunk-ERCOHGXD.js +0 -356
- package/dist/chunk-ERCOHGXD.js.map +0 -1
- package/dist/chunk-FD5ZZHEU.js +0 -92
- package/dist/chunk-FD5ZZHEU.js.map +0 -1
- package/dist/chunk-FEAIOR7N.cjs +0 -91
- package/dist/chunk-FEAIOR7N.cjs.map +0 -1
- package/dist/chunk-GCM5JHMX.js +0 -88
- package/dist/chunk-GCM5JHMX.js.map +0 -1
- package/dist/chunk-GLA4JXBO.js +0 -204
- package/dist/chunk-GLA4JXBO.js.map +0 -1
- package/dist/chunk-HIQ5HSZL.cjs +0 -1923
- package/dist/chunk-HIQ5HSZL.cjs.map +0 -1
- package/dist/chunk-HVRVSI2Z.cjs +0 -829
- package/dist/chunk-HVRVSI2Z.cjs.map +0 -1
- package/dist/chunk-I4GAWIPW.js +0 -825
- package/dist/chunk-I4GAWIPW.js.map +0 -1
- package/dist/chunk-J45BCEZ4.cjs +0 -339
- package/dist/chunk-J45BCEZ4.cjs.map +0 -1
- package/dist/chunk-JG6ZJ2WU.js +0 -1513
- package/dist/chunk-JG6ZJ2WU.js.map +0 -1
- package/dist/chunk-L2TE7PMO.cjs +0 -14
- package/dist/chunk-L2TE7PMO.cjs.map +0 -1
- package/dist/chunk-LHZ6VOA7.js +0 -1764
- package/dist/chunk-LHZ6VOA7.js.map +0 -1
- package/dist/chunk-MN3LHRGV.cjs +0 -8012
- package/dist/chunk-MN3LHRGV.cjs.map +0 -1
- package/dist/chunk-MVTOCRV2.js +0 -213
- package/dist/chunk-MVTOCRV2.js.map +0 -1
- package/dist/chunk-N5NNW4VG.cjs +0 -341
- package/dist/chunk-N5NNW4VG.cjs.map +0 -1
- package/dist/chunk-N7FNVFXW.cjs +0 -32
- package/dist/chunk-N7FNVFXW.cjs.map +0 -1
- package/dist/chunk-NKW7LKYU.js +0 -3185
- package/dist/chunk-NKW7LKYU.js.map +0 -1
- package/dist/chunk-NLNDMWZC.js +0 -31
- package/dist/chunk-NLNDMWZC.js.map +0 -1
- package/dist/chunk-NNQ2TYDF.js +0 -1848
- package/dist/chunk-NNQ2TYDF.js.map +0 -1
- package/dist/chunk-NNZAEUDW.js +0 -6792
- package/dist/chunk-NNZAEUDW.js.map +0 -1
- package/dist/chunk-OUHT5Z36.cjs +0 -393
- package/dist/chunk-OUHT5Z36.cjs.map +0 -1
- package/dist/chunk-QFTDTX6K.cjs +0 -457
- package/dist/chunk-QFTDTX6K.cjs.map +0 -1
- package/dist/chunk-SBUFNJVE.js +0 -258
- package/dist/chunk-SBUFNJVE.js.map +0 -1
- package/dist/chunk-SRGQ72IR.cjs +0 -2800
- package/dist/chunk-SRGQ72IR.cjs.map +0 -1
- package/dist/chunk-SSV46KFA.cjs +0 -112
- package/dist/chunk-SSV46KFA.cjs.map +0 -1
- package/dist/chunk-T6ZYQJ63.cjs +0 -6807
- package/dist/chunk-T6ZYQJ63.cjs.map +0 -1
- package/dist/chunk-UKQHXPGW.js +0 -30
- package/dist/chunk-UKQHXPGW.js.map +0 -1
- package/dist/chunk-UO6BUV6K.js +0 -278
- package/dist/chunk-UO6BUV6K.js.map +0 -1
- package/dist/chunk-V4XG5QF6.js +0 -1685
- package/dist/chunk-V4XG5QF6.js.map +0 -1
- package/dist/chunk-VEKIWQ3F.cjs +0 -39
- package/dist/chunk-VEKIWQ3F.cjs.map +0 -1
- package/dist/chunk-WWQEY7BV.js +0 -67
- package/dist/chunk-WWQEY7BV.js.map +0 -1
- package/dist/chunk-WXEHD6TT.js +0 -2795
- package/dist/chunk-WXEHD6TT.js.map +0 -1
- package/dist/chunk-X6K3HUOY.cjs +0 -86
- package/dist/chunk-X6K3HUOY.cjs.map +0 -1
- package/dist/chunk-XA4CKRML.cjs +0 -316
- package/dist/chunk-XA4CKRML.cjs.map +0 -1
- package/dist/chunk-XBTEO4OB.js +0 -391
- package/dist/chunk-XBTEO4OB.js.map +0 -1
- package/dist/chunk-XIYYHA65.cjs +0 -101
- package/dist/chunk-XIYYHA65.cjs.map +0 -1
- package/dist/chunk-YLJ4XMA6.js +0 -33
- package/dist/chunk-YLJ4XMA6.js.map +0 -1
- package/dist/chunk-YRIKITGF.cjs +0 -1768
- package/dist/chunk-YRIKITGF.cjs.map +0 -1
- package/dist/chunk-Z2XP767T.cjs +0 -35
- package/dist/chunk-Z2XP767T.cjs.map +0 -1
- package/dist/chunk-Z4X2RWOF.js +0 -37
- package/dist/chunk-Z4X2RWOF.js.map +0 -1
- package/dist/chunk-Z7XGGLI2.js +0 -455
- package/dist/chunk-Z7XGGLI2.js.map +0 -1
- package/dist/chunk-ZMW6NU2K.cjs +0 -1516
- package/dist/chunk-ZMW6NU2K.cjs.map +0 -1
- package/dist/chunk-ZVTWQLK4.cjs +0 -459
- package/dist/chunk-ZVTWQLK4.cjs.map +0 -1
- package/dist/variables.cjs +0 -17
- package/dist/variables.cjs.map +0 -1
- package/dist/variables.d.cts +0 -87
- package/dist/variables.d.ts +0 -87
- package/dist/variables.js +0 -4
- package/dist/variables.js.map +0 -1
package/dist/chunk-7ZX6B7SY.cjs
DELETED
|
@@ -1,3222 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunkFEAIOR7N_cjs = require('./chunk-FEAIOR7N.cjs');
|
|
4
|
-
var chunkZVTWQLK4_cjs = require('./chunk-ZVTWQLK4.cjs');
|
|
5
|
-
var chunkHIQ5HSZL_cjs = require('./chunk-HIQ5HSZL.cjs');
|
|
6
|
-
var chunk2TZKENDH_cjs = require('./chunk-2TZKENDH.cjs');
|
|
7
|
-
var chunkEJ3ILXX6_cjs = require('./chunk-EJ3ILXX6.cjs');
|
|
8
|
-
var chunkAMOJYLG2_cjs = require('./chunk-AMOJYLG2.cjs');
|
|
9
|
-
var chunkB4HBEFTB_cjs = require('./chunk-B4HBEFTB.cjs');
|
|
10
|
-
|
|
11
|
-
// src/symbolic/MultivariateFactor.ts
|
|
12
|
-
function exactRoot(value, degree) {
|
|
13
|
-
const rootOf = degree === 2 ? chunkHIQ5HSZL_cjs.exactIntegerSqrt : chunkHIQ5HSZL_cjs.exactIntegerCbrt;
|
|
14
|
-
const numerator = rootOf(value.n);
|
|
15
|
-
const denominator = rootOf(value.d);
|
|
16
|
-
return numerator === null || denominator === null ? null : { n: numerator, d: denominator };
|
|
17
|
-
}
|
|
18
|
-
function monomialRoot(key, degree) {
|
|
19
|
-
const monomial = chunkHIQ5HSZL_cjs.monomialFromKey(key);
|
|
20
|
-
const root = /* @__PURE__ */ new Map();
|
|
21
|
-
for (const [name, exponent] of monomial) {
|
|
22
|
-
if (exponent % degree !== 0) return null;
|
|
23
|
-
root.set(name, exponent / degree);
|
|
24
|
-
}
|
|
25
|
-
return chunkHIQ5HSZL_cjs.monomialToKey(root);
|
|
26
|
-
}
|
|
27
|
-
function monomialMul(a, b) {
|
|
28
|
-
const product2 = chunkHIQ5HSZL_cjs.monomialFromKey(a);
|
|
29
|
-
for (const [name, exponent] of chunkHIQ5HSZL_cjs.monomialFromKey(b)) {
|
|
30
|
-
product2.set(name, (product2.get(name) ?? 0) + exponent);
|
|
31
|
-
}
|
|
32
|
-
return chunkHIQ5HSZL_cjs.monomialToKey(product2);
|
|
33
|
-
}
|
|
34
|
-
function monomialDiv(a, b) {
|
|
35
|
-
const quotient = chunkHIQ5HSZL_cjs.monomialFromKey(a);
|
|
36
|
-
for (const [name, exponent] of chunkHIQ5HSZL_cjs.monomialFromKey(b)) {
|
|
37
|
-
const remaining = (quotient.get(name) ?? 0) - exponent;
|
|
38
|
-
if (remaining <= 0) quotient.delete(name);
|
|
39
|
-
else quotient.set(name, remaining);
|
|
40
|
-
}
|
|
41
|
-
return chunkHIQ5HSZL_cjs.monomialToKey(quotient);
|
|
42
|
-
}
|
|
43
|
-
function monomialGcd(a, b) {
|
|
44
|
-
const left = chunkHIQ5HSZL_cjs.monomialFromKey(a);
|
|
45
|
-
const shared = /* @__PURE__ */ new Map();
|
|
46
|
-
for (const [name, exponent] of chunkHIQ5HSZL_cjs.monomialFromKey(b)) {
|
|
47
|
-
const other = left.get(name);
|
|
48
|
-
if (other !== void 0) shared.set(name, Math.min(other, exponent));
|
|
49
|
-
}
|
|
50
|
-
return chunkHIQ5HSZL_cjs.monomialToKey(shared);
|
|
51
|
-
}
|
|
52
|
-
function namesOf(keys) {
|
|
53
|
-
const names = /* @__PURE__ */ new Set();
|
|
54
|
-
for (const key of keys) for (const name of chunkHIQ5HSZL_cjs.monomialFromKey(key).keys()) names.add(name);
|
|
55
|
-
return [...names].sort();
|
|
56
|
-
}
|
|
57
|
-
function termsToNode(terms) {
|
|
58
|
-
const map = /* @__PURE__ */ new Map();
|
|
59
|
-
for (const term of terms) map.set(term.key, term.coefficient);
|
|
60
|
-
return chunkHIQ5HSZL_cjs.fromPolynomial({ terms: map, vars: namesOf(terms.map((term) => term.key)) });
|
|
61
|
-
}
|
|
62
|
-
function product(factors) {
|
|
63
|
-
let result = factors[0];
|
|
64
|
-
for (let i = 1; i < factors.length; i++) result = { kind: "mul", left: result, right: factors[i] };
|
|
65
|
-
return result;
|
|
66
|
-
}
|
|
67
|
-
function orderedTerms(p) {
|
|
68
|
-
const terms = [...p.terms].map(([key, coefficient]) => ({ key, coefficient }));
|
|
69
|
-
return terms.sort((a, b) => chunkHIQ5HSZL_cjs.compareMonomials(a.key, b.key, p.vars));
|
|
70
|
-
}
|
|
71
|
-
function factorMultivariate(p) {
|
|
72
|
-
if (p.vars.length < 2) return null;
|
|
73
|
-
const terms = orderedTerms(p);
|
|
74
|
-
if (terms.length === 2) return factorBinomial(terms[0], terms[1]);
|
|
75
|
-
if (terms.length === 3) return factorPerfectSquare(terms);
|
|
76
|
-
if (terms.length === 4) return factorByGrouping(terms);
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
function factorBinomial(first, second) {
|
|
80
|
-
const firstPositive = first.coefficient.n > 0n;
|
|
81
|
-
const secondPositive = second.coefficient.n > 0n;
|
|
82
|
-
if (!firstPositive) return null;
|
|
83
|
-
const squares = asPowerPair(first, second, 2);
|
|
84
|
-
if (squares !== null && !secondPositive) {
|
|
85
|
-
return product([
|
|
86
|
-
termsToNode([squares.a, negated(squares.b)]),
|
|
87
|
-
termsToNode([squares.a, squares.b])
|
|
88
|
-
]);
|
|
89
|
-
}
|
|
90
|
-
const cubes = asPowerPair(first, second, 3);
|
|
91
|
-
if (cubes === null) return null;
|
|
92
|
-
const linear = secondPositive ? termsToNode([cubes.a, cubes.b]) : termsToNode([cubes.a, negated(cubes.b)]);
|
|
93
|
-
const middle = secondPositive ? negated(multiplyTerms(cubes.a, cubes.b)) : multiplyTerms(cubes.a, cubes.b);
|
|
94
|
-
return product([linear, termsToNode([squareOf(cubes.a), middle, squareOf(cubes.b)])]);
|
|
95
|
-
}
|
|
96
|
-
function asPowerPair(first, second, degree) {
|
|
97
|
-
const magnitude2 = second.coefficient.n < 0n ? chunkHIQ5HSZL_cjs.rationalNeg(second.coefficient) : second.coefficient;
|
|
98
|
-
const firstRoot = exactRoot(first.coefficient, degree);
|
|
99
|
-
const secondRoot = exactRoot(magnitude2, degree);
|
|
100
|
-
if (firstRoot === null || secondRoot === null) return null;
|
|
101
|
-
const firstKey = monomialRoot(first.key, degree);
|
|
102
|
-
const secondKey = monomialRoot(second.key, degree);
|
|
103
|
-
if (firstKey === null || secondKey === null) return null;
|
|
104
|
-
return { a: { key: firstKey, coefficient: firstRoot }, b: { key: secondKey, coefficient: secondRoot } };
|
|
105
|
-
}
|
|
106
|
-
function negated(term) {
|
|
107
|
-
return { key: term.key, coefficient: chunkHIQ5HSZL_cjs.rationalNeg(term.coefficient) };
|
|
108
|
-
}
|
|
109
|
-
function multiplyTerms(a, b) {
|
|
110
|
-
return { key: monomialMul(a.key, b.key), coefficient: chunkHIQ5HSZL_cjs.rationalMul(a.coefficient, b.coefficient) };
|
|
111
|
-
}
|
|
112
|
-
function squareOf(term) {
|
|
113
|
-
return multiplyTerms(term, term);
|
|
114
|
-
}
|
|
115
|
-
function factorPerfectSquare(terms) {
|
|
116
|
-
const [first, middle, last] = terms;
|
|
117
|
-
if (first.coefficient.n < 0n || last.coefficient.n < 0n) return null;
|
|
118
|
-
const roots = asPowerPair(first, last, 2);
|
|
119
|
-
if (roots === null) return null;
|
|
120
|
-
const cross = multiplyTerms(roots.a, roots.b);
|
|
121
|
-
if (cross.key !== middle.key) return null;
|
|
122
|
-
const twice = chunkHIQ5HSZL_cjs.rationalMul(cross.coefficient, { n: 2n, d: 1n });
|
|
123
|
-
const negative = middle.coefficient.n < 0n;
|
|
124
|
-
const magnitude2 = negative ? chunkHIQ5HSZL_cjs.rationalNeg(middle.coefficient) : middle.coefficient;
|
|
125
|
-
if (!chunkHIQ5HSZL_cjs.isRationalOne(chunkHIQ5HSZL_cjs.rationalDiv(magnitude2, twice))) return null;
|
|
126
|
-
const base = termsToNode([roots.a, negative ? negated(roots.b) : roots.b]);
|
|
127
|
-
return { kind: "pow", base, exponent: chunkHIQ5HSZL_cjs.constNode(2) };
|
|
128
|
-
}
|
|
129
|
-
function factorByGrouping(terms) {
|
|
130
|
-
const pairings = [
|
|
131
|
-
[[0, 1], [2, 3]],
|
|
132
|
-
[[0, 2], [1, 3]],
|
|
133
|
-
[[0, 3], [1, 2]]
|
|
134
|
-
];
|
|
135
|
-
for (const pairing of pairings) {
|
|
136
|
-
const first = splitPair(terms[pairing[0][0]], terms[pairing[0][1]]);
|
|
137
|
-
const second = splitPair(terms[pairing[1][0]], terms[pairing[1][1]]);
|
|
138
|
-
if (first === null || second === null) continue;
|
|
139
|
-
if (!cofactorsAgree(first.cofactor, second.cofactor)) continue;
|
|
140
|
-
return product([
|
|
141
|
-
termsToNode([first.common, second.common]),
|
|
142
|
-
termsToNode(first.cofactor)
|
|
143
|
-
]);
|
|
144
|
-
}
|
|
145
|
-
return null;
|
|
146
|
-
}
|
|
147
|
-
function splitPair(first, second) {
|
|
148
|
-
const shared = monomialGcd(first.key, second.key);
|
|
149
|
-
const common = { key: shared, coefficient: first.coefficient };
|
|
150
|
-
const cofactor = [
|
|
151
|
-
{ key: monomialDiv(first.key, shared), coefficient: { n: 1n, d: 1n } },
|
|
152
|
-
{ key: monomialDiv(second.key, shared), coefficient: chunkHIQ5HSZL_cjs.rationalDiv(second.coefficient, first.coefficient) }
|
|
153
|
-
];
|
|
154
|
-
return cofactor[0].key === cofactor[1].key ? null : { common, cofactor };
|
|
155
|
-
}
|
|
156
|
-
function cofactorsAgree(a, b) {
|
|
157
|
-
if (a.length !== b.length) return false;
|
|
158
|
-
return a.every((term, index) => term.key === b[index].key && term.coefficient.n === b[index].coefficient.n && term.coefficient.d === b[index].coefficient.d);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// src/symbolic/Factor.ts
|
|
162
|
-
var FACTOR_MAX_DEGREE = 12;
|
|
163
|
-
var FACTOR_MAX_ROOT_CANDIDATES = 4096;
|
|
164
|
-
function gcd(a, b) {
|
|
165
|
-
let x = a < 0n ? -a : a;
|
|
166
|
-
let y = b < 0n ? -b : b;
|
|
167
|
-
while (y !== 0n) {
|
|
168
|
-
const remainder = x % y;
|
|
169
|
-
x = y;
|
|
170
|
-
y = remainder;
|
|
171
|
-
}
|
|
172
|
-
return x;
|
|
173
|
-
}
|
|
174
|
-
function lcm(a, b) {
|
|
175
|
-
if (a === 0n || b === 0n) return 0n;
|
|
176
|
-
return a / gcd(a, b) * b;
|
|
177
|
-
}
|
|
178
|
-
function divisors(value) {
|
|
179
|
-
const magnitude2 = value < 0n ? -value : value;
|
|
180
|
-
if (magnitude2 === 0n) return null;
|
|
181
|
-
const found = [];
|
|
182
|
-
for (let candidate = 1n; candidate * candidate <= magnitude2; candidate++) {
|
|
183
|
-
if (magnitude2 % candidate !== 0n) continue;
|
|
184
|
-
found.push(candidate);
|
|
185
|
-
const paired = magnitude2 / candidate;
|
|
186
|
-
if (paired !== candidate) found.push(paired);
|
|
187
|
-
if (found.length > FACTOR_MAX_ROOT_CANDIDATES) return null;
|
|
188
|
-
}
|
|
189
|
-
return found;
|
|
190
|
-
}
|
|
191
|
-
function evaluateAt(descending, x) {
|
|
192
|
-
let total = chunkHIQ5HSZL_cjs.RATIONAL_ZERO;
|
|
193
|
-
for (const coeff of descending) total = chunkHIQ5HSZL_cjs.rationalAdd(chunkHIQ5HSZL_cjs.rationalMul(total, x), coeff);
|
|
194
|
-
return total;
|
|
195
|
-
}
|
|
196
|
-
function divideByRoot(descending, root) {
|
|
197
|
-
const quotient = [descending[0]];
|
|
198
|
-
for (let i = 1; i < descending.length - 1; i++) {
|
|
199
|
-
quotient.push(chunkHIQ5HSZL_cjs.rationalAdd(descending[i], chunkHIQ5HSZL_cjs.rationalMul(quotient[i - 1], root)));
|
|
200
|
-
}
|
|
201
|
-
return quotient;
|
|
202
|
-
}
|
|
203
|
-
function rationalRoots(descending) {
|
|
204
|
-
if (descending.length < 2) return [];
|
|
205
|
-
let multiplier = 1n;
|
|
206
|
-
for (const coeff of descending) multiplier = lcm(multiplier, coeff.d);
|
|
207
|
-
const integers = descending.map((coeff) => coeff.n * multiplier / coeff.d);
|
|
208
|
-
const leading = integers[0];
|
|
209
|
-
const trailing = integers[integers.length - 1];
|
|
210
|
-
if (trailing === 0n) return [];
|
|
211
|
-
const numeratorDivisors = divisors(trailing);
|
|
212
|
-
const denominatorDivisors = divisors(leading);
|
|
213
|
-
if (numeratorDivisors === null || denominatorDivisors === null) {
|
|
214
|
-
throw chunkB4HBEFTB_cjs.ErrorFactory.execution(
|
|
215
|
-
"SYMBOLIC_FACTOR_LIMIT_EXCEEDED",
|
|
216
|
-
"This polynomial's coefficients have too many divisors to search for rational roots.",
|
|
217
|
-
{ limit: FACTOR_MAX_ROOT_CANDIDATES }
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
if (numeratorDivisors.length * denominatorDivisors.length > FACTOR_MAX_ROOT_CANDIDATES) {
|
|
221
|
-
throw chunkB4HBEFTB_cjs.ErrorFactory.execution(
|
|
222
|
-
"SYMBOLIC_FACTOR_LIMIT_EXCEEDED",
|
|
223
|
-
"This polynomial has too many candidate rational roots to test.",
|
|
224
|
-
{ limit: FACTOR_MAX_ROOT_CANDIDATES }
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
const roots = [];
|
|
228
|
-
const seen = /* @__PURE__ */ new Set();
|
|
229
|
-
for (const p of numeratorDivisors) {
|
|
230
|
-
for (const q of denominatorDivisors) {
|
|
231
|
-
for (const sign of [1n, -1n]) {
|
|
232
|
-
const candidate = { n: sign * p / gcd(p, q), d: q / gcd(p, q) };
|
|
233
|
-
const key = `${candidate.n}/${candidate.d}`;
|
|
234
|
-
if (seen.has(key)) continue;
|
|
235
|
-
seen.add(key);
|
|
236
|
-
if (chunkHIQ5HSZL_cjs.isRationalZero(evaluateAt(descending, candidate))) roots.push(candidate);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
return roots;
|
|
241
|
-
}
|
|
242
|
-
function linearFactorNode(variable, root) {
|
|
243
|
-
if (chunkHIQ5HSZL_cjs.isRationalZero(root)) return chunkHIQ5HSZL_cjs.varNode(variable);
|
|
244
|
-
return root.n > 0n ? { kind: "sub", left: chunkHIQ5HSZL_cjs.varNode(variable), right: chunkHIQ5HSZL_cjs.constNode(root) } : { kind: "add", left: chunkHIQ5HSZL_cjs.varNode(variable), right: chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.rationalNeg(root)) };
|
|
245
|
-
}
|
|
246
|
-
function coefficientsToNode(descending, variable) {
|
|
247
|
-
const degree = descending.length - 1;
|
|
248
|
-
const terms = /* @__PURE__ */ new Map();
|
|
249
|
-
descending.forEach((coeff, index) => {
|
|
250
|
-
if (chunkHIQ5HSZL_cjs.isRationalZero(coeff)) return;
|
|
251
|
-
const power3 = degree - index;
|
|
252
|
-
terms.set(power3 === 0 ? "" : power3 === 1 ? variable : `${variable}^${power3}`, coeff);
|
|
253
|
-
});
|
|
254
|
-
return chunkHIQ5HSZL_cjs.fromPolynomial({ terms, vars: terms.size > 0 ? [variable] : [] });
|
|
255
|
-
}
|
|
256
|
-
function factorUnivariate(descending, variable) {
|
|
257
|
-
const factors = [];
|
|
258
|
-
let remaining = [...descending];
|
|
259
|
-
let roots = rationalRoots(remaining);
|
|
260
|
-
while (roots.length > 0 && remaining.length > 2) {
|
|
261
|
-
for (const root of roots) {
|
|
262
|
-
let multiplicity = 0;
|
|
263
|
-
while (remaining.length > 1 && chunkHIQ5HSZL_cjs.isRationalZero(evaluateAt(remaining, root))) {
|
|
264
|
-
remaining = divideByRoot(remaining, root);
|
|
265
|
-
multiplicity++;
|
|
266
|
-
}
|
|
267
|
-
if (multiplicity > 0) factors.push({ base: linearFactorNode(variable, root), power: multiplicity });
|
|
268
|
-
}
|
|
269
|
-
roots = remaining.length > 2 ? rationalRoots(remaining) : [];
|
|
270
|
-
}
|
|
271
|
-
const leftoverDegree = remaining.length - 1;
|
|
272
|
-
if (leftoverDegree >= 1) {
|
|
273
|
-
factors.push({ base: coefficientsToNode(remaining, variable), power: 1 });
|
|
274
|
-
return { content: chunkHIQ5HSZL_cjs.RATIONAL_ONE, factors };
|
|
275
|
-
}
|
|
276
|
-
return { content: remaining.length === 1 ? remaining[0] : chunkHIQ5HSZL_cjs.RATIONAL_ONE, factors };
|
|
277
|
-
}
|
|
278
|
-
function factorizationToNode(factorization) {
|
|
279
|
-
const pieces = [];
|
|
280
|
-
if (!chunkHIQ5HSZL_cjs.isRationalOne(factorization.content)) pieces.push(chunkHIQ5HSZL_cjs.constNode(factorization.content));
|
|
281
|
-
for (const factor of factorization.factors) {
|
|
282
|
-
pieces.push(factor.power === 1 ? factor.base : chunkHIQ5HSZL_cjs.powNode(factor.base, chunkHIQ5HSZL_cjs.constNode({ n: BigInt(factor.power), d: 1n })));
|
|
283
|
-
}
|
|
284
|
-
if (pieces.length === 0) return chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.RATIONAL_ONE);
|
|
285
|
-
let result = pieces[0];
|
|
286
|
-
for (let i = 1; i < pieces.length; i++) result = { kind: "mul", left: result, right: pieces[i] };
|
|
287
|
-
return result;
|
|
288
|
-
}
|
|
289
|
-
function contentOf(p) {
|
|
290
|
-
let numeratorGcd = 0n;
|
|
291
|
-
let denominatorLcm = 1n;
|
|
292
|
-
for (const coeff of p.terms.values()) {
|
|
293
|
-
numeratorGcd = gcd(numeratorGcd, coeff.n);
|
|
294
|
-
denominatorLcm = lcm(denominatorLcm, coeff.d);
|
|
295
|
-
}
|
|
296
|
-
if (numeratorGcd === 0n) return chunkHIQ5HSZL_cjs.RATIONAL_ONE;
|
|
297
|
-
return { n: numeratorGcd, d: denominatorLcm };
|
|
298
|
-
}
|
|
299
|
-
function extractCommonMonomial(p) {
|
|
300
|
-
const common = /* @__PURE__ */ new Map();
|
|
301
|
-
for (const name of p.vars) {
|
|
302
|
-
let lowest = Infinity;
|
|
303
|
-
for (const key of p.terms.keys()) {
|
|
304
|
-
const exponent = exponentOf(key, name);
|
|
305
|
-
if (exponent < lowest) lowest = exponent;
|
|
306
|
-
}
|
|
307
|
-
if (lowest > 0 && lowest !== Infinity) common.set(name, lowest);
|
|
308
|
-
}
|
|
309
|
-
if (common.size === 0) return { monomial: common, reduced: p };
|
|
310
|
-
const terms = /* @__PURE__ */ new Map();
|
|
311
|
-
for (const [key, coeff] of p.terms) {
|
|
312
|
-
const exponents = parseKey(key);
|
|
313
|
-
for (const [name, shared] of common) exponents.set(name, (exponents.get(name) ?? 0) - shared);
|
|
314
|
-
terms.set(buildKey(exponents), coeff);
|
|
315
|
-
}
|
|
316
|
-
const names = /* @__PURE__ */ new Set();
|
|
317
|
-
for (const key of terms.keys()) for (const name of parseKey(key).keys()) names.add(name);
|
|
318
|
-
return { monomial: common, reduced: { terms, vars: [...names].sort() } };
|
|
319
|
-
}
|
|
320
|
-
function exponentOf(key, name) {
|
|
321
|
-
return parseKey(key).get(name) ?? 0;
|
|
322
|
-
}
|
|
323
|
-
function parseKey(key) {
|
|
324
|
-
const exponents = /* @__PURE__ */ new Map();
|
|
325
|
-
if (key === "") return exponents;
|
|
326
|
-
for (const factor of key.split("*")) {
|
|
327
|
-
const caret = factor.indexOf("^");
|
|
328
|
-
if (caret === -1) exponents.set(factor, 1);
|
|
329
|
-
else exponents.set(factor.slice(0, caret), Number(factor.slice(caret + 1)));
|
|
330
|
-
}
|
|
331
|
-
return exponents;
|
|
332
|
-
}
|
|
333
|
-
function buildKey(exponents) {
|
|
334
|
-
const names = [...exponents.keys()].filter((name) => (exponents.get(name) ?? 0) > 0).sort();
|
|
335
|
-
return names.map((name) => exponents.get(name) === 1 ? name : `${name}^${exponents.get(name)}`).join("*");
|
|
336
|
-
}
|
|
337
|
-
function monomialNode(monomial) {
|
|
338
|
-
const names = [...monomial.keys()].sort();
|
|
339
|
-
let result = null;
|
|
340
|
-
for (const name of names) {
|
|
341
|
-
const exponent = monomial.get(name);
|
|
342
|
-
const factor = exponent === 1 ? chunkHIQ5HSZL_cjs.varNode(name) : chunkHIQ5HSZL_cjs.powNode(chunkHIQ5HSZL_cjs.varNode(name), chunkHIQ5HSZL_cjs.constNode({ n: BigInt(exponent), d: 1n }));
|
|
343
|
-
result = result === null ? factor : { kind: "mul", left: result, right: factor };
|
|
344
|
-
}
|
|
345
|
-
return result;
|
|
346
|
-
}
|
|
347
|
-
function factorSymbolic(node) {
|
|
348
|
-
const polynomial = chunkHIQ5HSZL_cjs.toPolynomial(node);
|
|
349
|
-
if (polynomial === null || polynomial.terms.size === 0) return node;
|
|
350
|
-
if (chunkHIQ5HSZL_cjs.polyDegree(polynomial) > FACTOR_MAX_DEGREE) return node;
|
|
351
|
-
if (polynomial.vars.length === 0) return node;
|
|
352
|
-
const content = contentOf(polynomial);
|
|
353
|
-
const primitive = chunkHIQ5HSZL_cjs.isRationalOne(content) ? polynomial : scaleTerms(polynomial, chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.RATIONAL_ONE, content));
|
|
354
|
-
const { monomial, reduced } = extractCommonMonomial(primitive);
|
|
355
|
-
const monomialFactor = monomialNode(monomial);
|
|
356
|
-
const variable = chunkHIQ5HSZL_cjs.polyUnivariateVar(reduced);
|
|
357
|
-
if (variable === null) {
|
|
358
|
-
const patterned = factorMultivariate(reduced);
|
|
359
|
-
if (patterned !== null) return assemble(content, monomialFactor, patterned);
|
|
360
|
-
const pieces2 = buildPieces(content, monomialFactor, reduced);
|
|
361
|
-
return pieces2 ?? node;
|
|
362
|
-
}
|
|
363
|
-
const descending = [...chunkHIQ5HSZL_cjs.polyCoefficients(reduced, variable)].reverse();
|
|
364
|
-
const factorization = factorUnivariate(descending, variable);
|
|
365
|
-
const combinedContent = chunkHIQ5HSZL_cjs.rationalMul(content, factorization.content);
|
|
366
|
-
const isUnchanged = factorization.factors.length <= 1 && (factorization.factors[0]?.power ?? 1) === 1 && monomialFactor === null && chunkHIQ5HSZL_cjs.isRationalOne(combinedContent);
|
|
367
|
-
if (isUnchanged) return node;
|
|
368
|
-
const pieces = [];
|
|
369
|
-
if (!chunkHIQ5HSZL_cjs.isRationalOne(combinedContent)) pieces.push(chunkHIQ5HSZL_cjs.constNode(combinedContent));
|
|
370
|
-
if (monomialFactor !== null) pieces.push(monomialFactor);
|
|
371
|
-
pieces.push(factorizationToNode({ content: chunkHIQ5HSZL_cjs.RATIONAL_ONE, factors: factorization.factors }));
|
|
372
|
-
let result = pieces[0];
|
|
373
|
-
for (let i = 1; i < pieces.length; i++) result = { kind: "mul", left: result, right: pieces[i] };
|
|
374
|
-
return result;
|
|
375
|
-
}
|
|
376
|
-
function scaleTerms(p, k) {
|
|
377
|
-
const terms = /* @__PURE__ */ new Map();
|
|
378
|
-
for (const [key, coeff] of p.terms) terms.set(key, chunkHIQ5HSZL_cjs.rationalMul(coeff, k));
|
|
379
|
-
return { terms, vars: p.vars };
|
|
380
|
-
}
|
|
381
|
-
function assemble(content, monomialFactor, factored) {
|
|
382
|
-
const pieces = [];
|
|
383
|
-
if (!chunkHIQ5HSZL_cjs.isRationalOne(content)) pieces.push(chunkHIQ5HSZL_cjs.constNode(content));
|
|
384
|
-
if (monomialFactor !== null) pieces.push(monomialFactor);
|
|
385
|
-
pieces.push(factored);
|
|
386
|
-
let result = pieces[0];
|
|
387
|
-
for (let i = 1; i < pieces.length; i++) result = { kind: "mul", left: result, right: pieces[i] };
|
|
388
|
-
return result;
|
|
389
|
-
}
|
|
390
|
-
function buildPieces(content, monomialFactor, reduced) {
|
|
391
|
-
if (monomialFactor === null && chunkHIQ5HSZL_cjs.isRationalOne(content)) return null;
|
|
392
|
-
const pieces = [];
|
|
393
|
-
if (!chunkHIQ5HSZL_cjs.isRationalOne(content)) pieces.push(chunkHIQ5HSZL_cjs.constNode(content));
|
|
394
|
-
if (monomialFactor !== null) pieces.push(monomialFactor);
|
|
395
|
-
pieces.push(chunkHIQ5HSZL_cjs.fromPolynomial(reduced));
|
|
396
|
-
let result = pieces[0];
|
|
397
|
-
for (let i = 1; i < pieces.length; i++) result = { kind: "mul", left: result, right: pieces[i] };
|
|
398
|
-
return result;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// src/symbolic/CubicQuartic.ts
|
|
402
|
-
var TWO = { n: 2n, d: 1n };
|
|
403
|
-
var THREE = { n: 3n, d: 1n };
|
|
404
|
-
var FOUR = { n: 4n, d: 1n };
|
|
405
|
-
function depressCubic(a, b, c, d) {
|
|
406
|
-
const shift = chunkHIQ5HSZL_cjs.rationalNeg(chunkHIQ5HSZL_cjs.rationalDiv(b, chunkHIQ5HSZL_cjs.rationalMul(THREE, a)));
|
|
407
|
-
const p = chunkHIQ5HSZL_cjs.rationalDiv(
|
|
408
|
-
chunkHIQ5HSZL_cjs.rationalSub(chunkHIQ5HSZL_cjs.rationalMul(THREE, chunkHIQ5HSZL_cjs.rationalMul(a, c)), chunkHIQ5HSZL_cjs.rationalMul(b, b)),
|
|
409
|
-
chunkHIQ5HSZL_cjs.rationalMul(THREE, chunkHIQ5HSZL_cjs.rationalMul(a, a))
|
|
410
|
-
);
|
|
411
|
-
const twoBCubed = chunkHIQ5HSZL_cjs.rationalMul(TWO, chunkHIQ5HSZL_cjs.rationalMul(b, chunkHIQ5HSZL_cjs.rationalMul(b, b)));
|
|
412
|
-
const nineABC = chunkHIQ5HSZL_cjs.rationalMul({ n: 9n, d: 1n }, chunkHIQ5HSZL_cjs.rationalMul(a, chunkHIQ5HSZL_cjs.rationalMul(b, c)));
|
|
413
|
-
const twentySevenAAD = chunkHIQ5HSZL_cjs.rationalMul({ n: 27n, d: 1n }, chunkHIQ5HSZL_cjs.rationalMul(chunkHIQ5HSZL_cjs.rationalMul(a, a), d));
|
|
414
|
-
const q = chunkHIQ5HSZL_cjs.rationalDiv(
|
|
415
|
-
chunkHIQ5HSZL_cjs.rationalAdd(chunkHIQ5HSZL_cjs.rationalSub(twoBCubed, nineABC), twentySevenAAD),
|
|
416
|
-
chunkHIQ5HSZL_cjs.rationalMul({ n: 27n, d: 1n }, chunkHIQ5HSZL_cjs.rationalMul(a, chunkHIQ5HSZL_cjs.rationalMul(a, a)))
|
|
417
|
-
);
|
|
418
|
-
return { p, q, shift };
|
|
419
|
-
}
|
|
420
|
-
function solveCubic(a, b, c, d) {
|
|
421
|
-
const { p, q, shift } = depressCubic(a, b, c, d);
|
|
422
|
-
const discriminant = chunkHIQ5HSZL_cjs.rationalNeg(
|
|
423
|
-
chunkHIQ5HSZL_cjs.rationalAdd(
|
|
424
|
-
chunkHIQ5HSZL_cjs.rationalMul(FOUR, chunkHIQ5HSZL_cjs.rationalMul(p, chunkHIQ5HSZL_cjs.rationalMul(p, p))),
|
|
425
|
-
chunkHIQ5HSZL_cjs.rationalMul({ n: 27n, d: 1n }, chunkHIQ5HSZL_cjs.rationalMul(q, q))
|
|
426
|
-
)
|
|
427
|
-
);
|
|
428
|
-
if (chunkHIQ5HSZL_cjs.rationalCompare(discriminant, chunkHIQ5HSZL_cjs.RATIONAL_ZERO) > 0) {
|
|
429
|
-
return { exact: [], approximate: trigonometricRoots(p, q, shift) };
|
|
430
|
-
}
|
|
431
|
-
if (chunkHIQ5HSZL_cjs.isRationalZero(discriminant)) return { exact: repeatedCubicRoots(p, q, shift), approximate: [] };
|
|
432
|
-
return { exact: cardanoRoots(p, q, shift), approximate: [] };
|
|
433
|
-
}
|
|
434
|
-
function repeatedCubicRoots(p, q, shift) {
|
|
435
|
-
if (chunkHIQ5HSZL_cjs.isRationalZero(p)) return [chunkHIQ5HSZL_cjs.constNode(shift)];
|
|
436
|
-
const simple = chunkHIQ5HSZL_cjs.rationalAdd(chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalMul(THREE, q), p), shift);
|
|
437
|
-
const repeated = chunkHIQ5HSZL_cjs.rationalAdd(chunkHIQ5HSZL_cjs.rationalNeg(chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalMul(THREE, q), chunkHIQ5HSZL_cjs.rationalMul(TWO, p))), shift);
|
|
438
|
-
const ordered = [simple, repeated].sort(chunkHIQ5HSZL_cjs.rationalCompare);
|
|
439
|
-
return ordered.map(chunkHIQ5HSZL_cjs.constNode);
|
|
440
|
-
}
|
|
441
|
-
function cardanoRoots(p, q, shift) {
|
|
442
|
-
const half = chunkHIQ5HSZL_cjs.rationalNeg(chunkHIQ5HSZL_cjs.rationalDiv(q, TWO));
|
|
443
|
-
const radicand = chunkHIQ5HSZL_cjs.rationalAdd(
|
|
444
|
-
chunkHIQ5HSZL_cjs.rationalMul(chunkHIQ5HSZL_cjs.rationalDiv(q, TWO), chunkHIQ5HSZL_cjs.rationalDiv(q, TWO)),
|
|
445
|
-
chunkHIQ5HSZL_cjs.rationalMul(chunkHIQ5HSZL_cjs.rationalDiv(p, THREE), chunkHIQ5HSZL_cjs.rationalMul(chunkHIQ5HSZL_cjs.rationalDiv(p, THREE), chunkHIQ5HSZL_cjs.rationalDiv(p, THREE)))
|
|
446
|
-
);
|
|
447
|
-
const inner = chunkHIQ5HSZL_cjs.surdNode(radicand);
|
|
448
|
-
const u = { kind: "call", name: "cbrt", args: [{ kind: "add", left: chunkHIQ5HSZL_cjs.constNode(half), right: inner }] };
|
|
449
|
-
const v = { kind: "call", name: "cbrt", args: [{ kind: "sub", left: chunkHIQ5HSZL_cjs.constNode(half), right: inner }] };
|
|
450
|
-
const sum = { kind: "add", left: u, right: v };
|
|
451
|
-
const difference = { kind: "sub", left: u, right: v };
|
|
452
|
-
const real = { kind: "add", left: chunkHIQ5HSZL_cjs.constNode(shift), right: { kind: "div", left: { kind: "neg", operand: sum }, right: chunkHIQ5HSZL_cjs.constNode(TWO) } };
|
|
453
|
-
const imaginary = {
|
|
454
|
-
kind: "mul",
|
|
455
|
-
left: { kind: "div", left: { kind: "mul", left: difference, right: chunkHIQ5HSZL_cjs.surdNode(THREE) }, right: chunkHIQ5HSZL_cjs.constNode(TWO) },
|
|
456
|
-
right: chunkHIQ5HSZL_cjs.complexNode(chunkHIQ5HSZL_cjs.COMPLEX_I)
|
|
457
|
-
};
|
|
458
|
-
return [
|
|
459
|
-
{ kind: "add", left: chunkHIQ5HSZL_cjs.constNode(shift), right: sum },
|
|
460
|
-
{ kind: "sub", left: real, right: imaginary },
|
|
461
|
-
{ kind: "add", left: real, right: imaginary }
|
|
462
|
-
];
|
|
463
|
-
}
|
|
464
|
-
function trigonometricRoots(p, q, shift) {
|
|
465
|
-
const pNumber = chunkHIQ5HSZL_cjs.rationalToNumber(p);
|
|
466
|
-
const qNumber = chunkHIQ5HSZL_cjs.rationalToNumber(q);
|
|
467
|
-
const shiftNumber = chunkHIQ5HSZL_cjs.rationalToNumber(shift);
|
|
468
|
-
const magnitude2 = 2 * Math.sqrt(-pNumber / 3);
|
|
469
|
-
const ratio = 3 * qNumber / (2 * pNumber) * Math.sqrt(-3 / pNumber);
|
|
470
|
-
const angle = Math.acos(Math.min(1, Math.max(-1, ratio))) / 3;
|
|
471
|
-
return [0, 1, 2].map((k) => magnitude2 * Math.cos(angle - 2 * Math.PI * k / 3) + shiftNumber).sort((left, right) => left - right);
|
|
472
|
-
}
|
|
473
|
-
function depressQuartic(b, c, d, e) {
|
|
474
|
-
const shift = chunkHIQ5HSZL_cjs.rationalNeg(chunkHIQ5HSZL_cjs.rationalDiv(b, FOUR));
|
|
475
|
-
const bb = chunkHIQ5HSZL_cjs.rationalMul(b, b);
|
|
476
|
-
const p = chunkHIQ5HSZL_cjs.rationalSub(c, chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalMul(THREE, bb), { n: 8n, d: 1n }));
|
|
477
|
-
const q = chunkHIQ5HSZL_cjs.rationalAdd(
|
|
478
|
-
chunkHIQ5HSZL_cjs.rationalSub(d, chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalMul(b, c), TWO)),
|
|
479
|
-
chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalMul(bb, b), { n: 8n, d: 1n })
|
|
480
|
-
);
|
|
481
|
-
const r = chunkHIQ5HSZL_cjs.rationalSub(
|
|
482
|
-
chunkHIQ5HSZL_cjs.rationalAdd(
|
|
483
|
-
chunkHIQ5HSZL_cjs.rationalSub(e, chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalMul(b, d), FOUR)),
|
|
484
|
-
chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalMul(bb, c), { n: 16n, d: 1n })
|
|
485
|
-
),
|
|
486
|
-
chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalMul(THREE, chunkHIQ5HSZL_cjs.rationalMul(bb, bb)), { n: 256n, d: 1n })
|
|
487
|
-
);
|
|
488
|
-
return { p, q, r, shift };
|
|
489
|
-
}
|
|
490
|
-
function solveQuartic(a, b, c, d, e, solveQuadratic2) {
|
|
491
|
-
const monic = (value) => chunkHIQ5HSZL_cjs.rationalDiv(value, a);
|
|
492
|
-
const { p, q, r, shift } = depressQuartic(monic(b), monic(c), monic(d), monic(e));
|
|
493
|
-
const roots = chunkHIQ5HSZL_cjs.isRationalZero(q) ? biquadraticRoots(p, r) : splitQuarticRoots(p, q, r, solveQuadratic2);
|
|
494
|
-
if (roots === null) return null;
|
|
495
|
-
const shifted = chunkHIQ5HSZL_cjs.isRationalZero(shift) ? roots : roots.map((root) => ({ kind: "add", left: chunkHIQ5HSZL_cjs.constNode(shift), right: root }));
|
|
496
|
-
return { exact: distinct(shifted), approximate: [] };
|
|
497
|
-
}
|
|
498
|
-
function distinct(roots) {
|
|
499
|
-
const seen = /* @__PURE__ */ new Set();
|
|
500
|
-
const unique = [];
|
|
501
|
-
for (const root of roots) {
|
|
502
|
-
const key = chunkHIQ5HSZL_cjs.symbolicKey(chunkHIQ5HSZL_cjs.simplifySymbolic(root));
|
|
503
|
-
if (seen.has(key)) continue;
|
|
504
|
-
seen.add(key);
|
|
505
|
-
unique.push(root);
|
|
506
|
-
}
|
|
507
|
-
return unique;
|
|
508
|
-
}
|
|
509
|
-
function biquadraticRoots(p, r) {
|
|
510
|
-
const discriminant = chunkHIQ5HSZL_cjs.rationalSub(chunkHIQ5HSZL_cjs.rationalMul(p, p), chunkHIQ5HSZL_cjs.rationalMul(FOUR, r));
|
|
511
|
-
if (chunkHIQ5HSZL_cjs.rationalCompare(discriminant, chunkHIQ5HSZL_cjs.RATIONAL_ZERO) < 0) return complexBiquadraticRoots(p, r);
|
|
512
|
-
const root = chunkHIQ5HSZL_cjs.exactRationalSqrt(discriminant);
|
|
513
|
-
if (root !== null) return rationalSquareRoots(chunkHIQ5HSZL_cjs.rationalNeg(p), root, chunkHIQ5HSZL_cjs.isRationalZero(discriminant));
|
|
514
|
-
return nestedSquareRoots(p, r, discriminant);
|
|
515
|
-
}
|
|
516
|
-
function rationalSquareRoots(negatedP, root, repeated) {
|
|
517
|
-
const values = repeated ? [chunkHIQ5HSZL_cjs.rationalDiv(negatedP, TWO)] : [chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalAdd(negatedP, root), TWO), chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalSub(negatedP, root), TWO)];
|
|
518
|
-
const roots = [];
|
|
519
|
-
for (const value of values) {
|
|
520
|
-
if (chunkHIQ5HSZL_cjs.isRationalZero(value)) {
|
|
521
|
-
roots.push(chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.RATIONAL_ZERO));
|
|
522
|
-
continue;
|
|
523
|
-
}
|
|
524
|
-
const square = chunkHIQ5HSZL_cjs.signedSurdNode(value);
|
|
525
|
-
roots.push({ kind: "neg", operand: square }, square);
|
|
526
|
-
}
|
|
527
|
-
return roots;
|
|
528
|
-
}
|
|
529
|
-
function nestedSquareRoots(p, r, discriminant) {
|
|
530
|
-
const negatedP = chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.rationalNeg(p));
|
|
531
|
-
const surd = chunkHIQ5HSZL_cjs.surdNode(discriminant);
|
|
532
|
-
const negativeP = chunkHIQ5HSZL_cjs.rationalCompare(p, chunkHIQ5HSZL_cjs.RATIONAL_ZERO) <= 0;
|
|
533
|
-
const solutions = [
|
|
534
|
-
{ node: halved({ kind: "add", left: negatedP, right: surd }), positive: negativeP || chunkHIQ5HSZL_cjs.rationalCompare(r, chunkHIQ5HSZL_cjs.RATIONAL_ZERO) <= 0 },
|
|
535
|
-
{ node: halved({ kind: "sub", left: negatedP, right: surd }), positive: negativeP && chunkHIQ5HSZL_cjs.rationalCompare(r, chunkHIQ5HSZL_cjs.RATIONAL_ZERO) >= 0 }
|
|
536
|
-
];
|
|
537
|
-
const roots = [];
|
|
538
|
-
for (const { node, positive } of solutions) {
|
|
539
|
-
const radicand = positive ? node : { kind: "neg", operand: node };
|
|
540
|
-
const magnitude2 = { kind: "call", name: "sqrt", args: [radicand] };
|
|
541
|
-
const square = positive ? magnitude2 : { kind: "mul", left: magnitude2, right: chunkHIQ5HSZL_cjs.complexNode(chunkHIQ5HSZL_cjs.COMPLEX_I) };
|
|
542
|
-
roots.push({ kind: "neg", operand: square }, square);
|
|
543
|
-
}
|
|
544
|
-
return roots;
|
|
545
|
-
}
|
|
546
|
-
function halved(node) {
|
|
547
|
-
return { kind: "div", left: node, right: chunkHIQ5HSZL_cjs.constNode(TWO) };
|
|
548
|
-
}
|
|
549
|
-
function complexBiquadraticRoots(p, r) {
|
|
550
|
-
const centre = chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalNeg(p), TWO);
|
|
551
|
-
const modulus = chunkHIQ5HSZL_cjs.exactRationalSqrt(r);
|
|
552
|
-
const re = modulus === null ? nestedSurd(chunkHIQ5HSZL_cjs.surdNode(r), centre) : chunkHIQ5HSZL_cjs.surdNode(chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalAdd(modulus, centre), TWO));
|
|
553
|
-
const imaginaryMagnitude = modulus === null ? nestedSurd(chunkHIQ5HSZL_cjs.surdNode(r), chunkHIQ5HSZL_cjs.rationalNeg(centre)) : chunkHIQ5HSZL_cjs.surdNode(chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalSub(modulus, centre), TWO));
|
|
554
|
-
const im = { kind: "mul", left: imaginaryMagnitude, right: chunkHIQ5HSZL_cjs.complexNode(chunkHIQ5HSZL_cjs.COMPLEX_I) };
|
|
555
|
-
const first = { kind: "add", left: re, right: im };
|
|
556
|
-
const second = { kind: "sub", left: re, right: im };
|
|
557
|
-
return [
|
|
558
|
-
{ kind: "neg", operand: first },
|
|
559
|
-
{ kind: "neg", operand: second },
|
|
560
|
-
second,
|
|
561
|
-
first
|
|
562
|
-
];
|
|
563
|
-
}
|
|
564
|
-
function nestedSurd(surd, offset) {
|
|
565
|
-
const shifted = offset.n >= 0n ? { kind: "add", left: surd, right: chunkHIQ5HSZL_cjs.constNode(offset) } : { kind: "sub", left: surd, right: chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.rationalNeg(offset)) };
|
|
566
|
-
return { kind: "call", name: "sqrt", args: [halved(shifted)] };
|
|
567
|
-
}
|
|
568
|
-
function splitQuarticRoots(p, q, r, solveQuadratic2) {
|
|
569
|
-
const resolvent = [
|
|
570
|
-
{ n: 1n, d: 1n },
|
|
571
|
-
chunkHIQ5HSZL_cjs.rationalMul(TWO, p),
|
|
572
|
-
chunkHIQ5HSZL_cjs.rationalSub(chunkHIQ5HSZL_cjs.rationalMul(p, p), chunkHIQ5HSZL_cjs.rationalMul(FOUR, r)),
|
|
573
|
-
chunkHIQ5HSZL_cjs.rationalNeg(chunkHIQ5HSZL_cjs.rationalMul(q, q))
|
|
574
|
-
];
|
|
575
|
-
for (const z of rationalRoots(resolvent)) {
|
|
576
|
-
if (chunkHIQ5HSZL_cjs.rationalCompare(z, chunkHIQ5HSZL_cjs.RATIONAL_ZERO) <= 0) continue;
|
|
577
|
-
const alpha = chunkHIQ5HSZL_cjs.exactRationalSqrt(z);
|
|
578
|
-
if (alpha === null) continue;
|
|
579
|
-
const sum = chunkHIQ5HSZL_cjs.rationalAdd(p, z);
|
|
580
|
-
const difference = chunkHIQ5HSZL_cjs.rationalDiv(q, alpha);
|
|
581
|
-
const beta = chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalSub(sum, difference), TWO);
|
|
582
|
-
const gamma = chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalAdd(sum, difference), TWO);
|
|
583
|
-
const one2 = { n: 1n, d: 1n };
|
|
584
|
-
return [
|
|
585
|
-
...solveQuadratic2(one2, alpha, beta),
|
|
586
|
-
...solveQuadratic2(one2, chunkHIQ5HSZL_cjs.rationalNeg(alpha), gamma)
|
|
587
|
-
];
|
|
588
|
-
}
|
|
589
|
-
return null;
|
|
590
|
-
}
|
|
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 = [...chunkHIQ5HSZL_cjs.squareFreePart(ascending)].reverse();
|
|
644
|
-
const doubles = squareFree.map(chunkHIQ5HSZL_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
|
-
|
|
764
|
-
// src/symbolic/Solve.ts
|
|
765
|
-
var SOLVE_MAX_DEGREE = 8;
|
|
766
|
-
function evaluateRational(descending, x) {
|
|
767
|
-
let total = chunkHIQ5HSZL_cjs.RATIONAL_ZERO;
|
|
768
|
-
for (const coeff of descending) total = chunkHIQ5HSZL_cjs.rationalAdd(chunkHIQ5HSZL_cjs.rationalMul(total, x), coeff);
|
|
769
|
-
return total;
|
|
770
|
-
}
|
|
771
|
-
function divideByRoot2(descending, root) {
|
|
772
|
-
const quotient = [descending[0]];
|
|
773
|
-
for (let i = 1; i < descending.length - 1; i++) {
|
|
774
|
-
quotient.push(chunkHIQ5HSZL_cjs.rationalAdd(descending[i], chunkHIQ5HSZL_cjs.rationalMul(quotient[i - 1], root)));
|
|
775
|
-
}
|
|
776
|
-
return quotient;
|
|
777
|
-
}
|
|
778
|
-
function solveQuadratic(a, b, c) {
|
|
779
|
-
const discriminant = chunkHIQ5HSZL_cjs.rationalSub(chunkHIQ5HSZL_cjs.rationalMul(b, b), chunkHIQ5HSZL_cjs.rationalMul(rational4(), chunkHIQ5HSZL_cjs.rationalMul(a, c)));
|
|
780
|
-
const twoA = chunkHIQ5HSZL_cjs.rationalMul(rational2(), a);
|
|
781
|
-
if (chunkHIQ5HSZL_cjs.rationalCompare(discriminant, chunkHIQ5HSZL_cjs.RATIONAL_ZERO) < 0) {
|
|
782
|
-
return complexQuadraticRoots(chunkHIQ5HSZL_cjs.rationalNeg(b), discriminant, twoA);
|
|
783
|
-
}
|
|
784
|
-
if (chunkHIQ5HSZL_cjs.isRationalZero(discriminant)) return [chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalNeg(b), twoA))];
|
|
785
|
-
const rootN = chunkHIQ5HSZL_cjs.exactIntegerSqrt(discriminant.n);
|
|
786
|
-
const rootD = chunkHIQ5HSZL_cjs.exactIntegerSqrt(discriminant.d);
|
|
787
|
-
if (rootN !== null && rootD !== null) {
|
|
788
|
-
const root = { n: rootN, d: rootD };
|
|
789
|
-
const plus = chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalAdd(chunkHIQ5HSZL_cjs.rationalNeg(b), root), twoA);
|
|
790
|
-
const minus = chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalSub(chunkHIQ5HSZL_cjs.rationalNeg(b), root), twoA);
|
|
791
|
-
return chunkHIQ5HSZL_cjs.rationalCompare(minus, plus) <= 0 ? [chunkHIQ5HSZL_cjs.constNode(minus), chunkHIQ5HSZL_cjs.constNode(plus)] : [chunkHIQ5HSZL_cjs.constNode(plus), chunkHIQ5HSZL_cjs.constNode(minus)];
|
|
792
|
-
}
|
|
793
|
-
const surd = chunkHIQ5HSZL_cjs.surdNode(discriminant);
|
|
794
|
-
const ascending = chunkHIQ5HSZL_cjs.rationalCompare(twoA, chunkHIQ5HSZL_cjs.RATIONAL_ZERO) > 0;
|
|
795
|
-
const lower = { kind: "div", left: { kind: "sub", left: chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.rationalNeg(b)), right: surd }, right: chunkHIQ5HSZL_cjs.constNode(twoA) };
|
|
796
|
-
const upper = { kind: "div", left: { kind: "add", left: chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.rationalNeg(b)), right: surd }, right: chunkHIQ5HSZL_cjs.constNode(twoA) };
|
|
797
|
-
return ascending ? [lower, upper] : [upper, lower];
|
|
798
|
-
}
|
|
799
|
-
function complexQuadraticRoots(negatedB, discriminant, twoA) {
|
|
800
|
-
const magnitude2 = chunkHIQ5HSZL_cjs.rationalNeg(discriminant);
|
|
801
|
-
const rootN = chunkHIQ5HSZL_cjs.exactIntegerSqrt(magnitude2.n);
|
|
802
|
-
const rootD = chunkHIQ5HSZL_cjs.exactIntegerSqrt(magnitude2.d);
|
|
803
|
-
if (rootN !== null && rootD !== null) {
|
|
804
|
-
const imaginary2 = chunkHIQ5HSZL_cjs.rationalDiv({ n: rootN, d: rootD }, twoA);
|
|
805
|
-
const real2 = chunkHIQ5HSZL_cjs.rationalDiv(negatedB, twoA);
|
|
806
|
-
return [
|
|
807
|
-
chunkHIQ5HSZL_cjs.complexNode(chunkHIQ5HSZL_cjs.complex(real2, chunkHIQ5HSZL_cjs.rationalNeg(imaginary2))),
|
|
808
|
-
chunkHIQ5HSZL_cjs.complexNode(chunkHIQ5HSZL_cjs.complex(real2, imaginary2))
|
|
809
|
-
];
|
|
810
|
-
}
|
|
811
|
-
const real = chunkHIQ5HSZL_cjs.rationalDiv(negatedB, twoA);
|
|
812
|
-
const scaledRadicand = chunkHIQ5HSZL_cjs.rationalDiv(magnitude2, chunkHIQ5HSZL_cjs.rationalMul(twoA, twoA));
|
|
813
|
-
const imaginary = { kind: "mul", left: chunkHIQ5HSZL_cjs.surdNode(scaledRadicand), right: chunkHIQ5HSZL_cjs.complexNode(chunkHIQ5HSZL_cjs.COMPLEX_I) };
|
|
814
|
-
if (chunkHIQ5HSZL_cjs.isRationalZero(real)) {
|
|
815
|
-
return [{ kind: "neg", operand: imaginary }, imaginary];
|
|
816
|
-
}
|
|
817
|
-
return [
|
|
818
|
-
{ kind: "sub", left: chunkHIQ5HSZL_cjs.constNode(real), right: imaginary },
|
|
819
|
-
{ kind: "add", left: chunkHIQ5HSZL_cjs.constNode(real), right: imaginary }
|
|
820
|
-
];
|
|
821
|
-
}
|
|
822
|
-
function rational2() {
|
|
823
|
-
return { n: 2n, d: 1n };
|
|
824
|
-
}
|
|
825
|
-
function rational4() {
|
|
826
|
-
return { n: 4n, d: 1n };
|
|
827
|
-
}
|
|
828
|
-
function realApproximation(value) {
|
|
829
|
-
return { re: value, im: 0 };
|
|
830
|
-
}
|
|
831
|
-
function solveForVariable(lhs, rhs, variable) {
|
|
832
|
-
const polynomial = chunkHIQ5HSZL_cjs.toPolynomial({ kind: "sub", left: lhs, right: rhs });
|
|
833
|
-
if (polynomial === null) {
|
|
834
|
-
return {
|
|
835
|
-
kind: "unsupported",
|
|
836
|
-
reason: "this is not a polynomial equation (it divides by an unknown, or calls a function of one)"
|
|
837
|
-
};
|
|
838
|
-
}
|
|
839
|
-
const others = polynomial.vars.filter((name) => name !== variable);
|
|
840
|
-
const degree = chunkHIQ5HSZL_cjs.polyDegree(polynomial, variable);
|
|
841
|
-
if (others.length > 0) {
|
|
842
|
-
if (degree !== 1) {
|
|
843
|
-
return {
|
|
844
|
-
kind: "unsupported",
|
|
845
|
-
reason: `solving for "${variable}" needs the equation to be linear in it when other unknowns (${others.join(", ")}) are present`
|
|
846
|
-
};
|
|
847
|
-
}
|
|
848
|
-
return solveLinearWithOtherUnknowns(polynomial, variable);
|
|
849
|
-
}
|
|
850
|
-
if (degree === 0) {
|
|
851
|
-
return polynomial.terms.size === 0 ? { kind: "identity" } : { kind: "contradiction" };
|
|
852
|
-
}
|
|
853
|
-
if (degree > SOLVE_MAX_DEGREE) {
|
|
854
|
-
return { kind: "unsupported", reason: `degree ${degree} is above the supported maximum of ${SOLVE_MAX_DEGREE}` };
|
|
855
|
-
}
|
|
856
|
-
const descending = [...chunkHIQ5HSZL_cjs.polyCoefficients(polynomial, variable)].reverse();
|
|
857
|
-
return solveUnivariate(descending);
|
|
858
|
-
}
|
|
859
|
-
function solveLinearWithOtherUnknowns(polynomial, variable) {
|
|
860
|
-
const coefficientTerms = /* @__PURE__ */ new Map();
|
|
861
|
-
const constantTerms = /* @__PURE__ */ new Map();
|
|
862
|
-
for (const [key, coeff] of polynomial.terms) {
|
|
863
|
-
const factors = key.split("*").filter((part) => part.length > 0);
|
|
864
|
-
const index = factors.indexOf(variable);
|
|
865
|
-
if (index === -1) {
|
|
866
|
-
constantTerms.set(key, coeff);
|
|
867
|
-
} else {
|
|
868
|
-
factors.splice(index, 1);
|
|
869
|
-
coefficientTerms.set(factors.join("*"), coeff);
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
const namesOf2 = (terms) => {
|
|
873
|
-
const names = /* @__PURE__ */ new Set();
|
|
874
|
-
for (const key of terms.keys()) {
|
|
875
|
-
for (const part of key.split("*")) {
|
|
876
|
-
if (part.length > 0) names.add(part.split("^")[0]);
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
return [...names].sort();
|
|
880
|
-
};
|
|
881
|
-
const coefficient = chunkHIQ5HSZL_cjs.fromPolynomial({ terms: coefficientTerms, vars: namesOf2(coefficientTerms) });
|
|
882
|
-
const constant = chunkHIQ5HSZL_cjs.fromPolynomial({ terms: constantTerms, vars: namesOf2(constantTerms) });
|
|
883
|
-
return {
|
|
884
|
-
kind: "roots",
|
|
885
|
-
exact: [{ kind: "div", left: { kind: "neg", operand: constant }, right: coefficient }],
|
|
886
|
-
approximate: []
|
|
887
|
-
};
|
|
888
|
-
}
|
|
889
|
-
function closedFormRoots(descending) {
|
|
890
|
-
if (descending.length === 4) {
|
|
891
|
-
return solveCubic(descending[0], descending[1], descending[2], descending[3]);
|
|
892
|
-
}
|
|
893
|
-
if (descending.length === 5) {
|
|
894
|
-
return solveQuartic(descending[0], descending[1], descending[2], descending[3], descending[4], solveQuadratic);
|
|
895
|
-
}
|
|
896
|
-
return null;
|
|
897
|
-
}
|
|
898
|
-
function extractRationalRoots(descending) {
|
|
899
|
-
const roots = [];
|
|
900
|
-
let remaining = [...descending];
|
|
901
|
-
let powersOfX = 0;
|
|
902
|
-
while (remaining.length > 1 && chunkHIQ5HSZL_cjs.isRationalZero(remaining[remaining.length - 1])) {
|
|
903
|
-
remaining = remaining.slice(0, -1);
|
|
904
|
-
powersOfX++;
|
|
905
|
-
}
|
|
906
|
-
if (powersOfX > 0) roots.push(chunkHIQ5HSZL_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 && chunkHIQ5HSZL_cjs.isRationalZero(evaluateRational(remaining, root))) {
|
|
913
|
-
remaining = divideByRoot2(remaining, root);
|
|
914
|
-
multiplicity++;
|
|
915
|
-
}
|
|
916
|
-
if (multiplicity > 0) roots.push(root);
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
return { roots: roots.sort(chunkHIQ5HSZL_cjs.rationalCompare), remaining };
|
|
920
|
-
}
|
|
921
|
-
function solveUnivariate(descending) {
|
|
922
|
-
const { roots, remaining } = extractRationalRoots(descending);
|
|
923
|
-
const exact = roots.map(chunkHIQ5HSZL_cjs.constNode);
|
|
924
|
-
const approximate = [];
|
|
925
|
-
const leftoverDegree = remaining.length - 1;
|
|
926
|
-
const solvedDegree = descending.length - remaining.length;
|
|
927
|
-
if (leftoverDegree <= 0) return finish(exact, approximate, solvedDegree, 0, "");
|
|
928
|
-
if (leftoverDegree === 1) {
|
|
929
|
-
exact.push(chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.rationalDiv(chunkHIQ5HSZL_cjs.rationalNeg(remaining[1]), remaining[0])));
|
|
930
|
-
return finish(exact, approximate, solvedDegree + 1, 0, "");
|
|
931
|
-
}
|
|
932
|
-
if (leftoverDegree === 2) {
|
|
933
|
-
exact.push(...solveQuadratic(remaining[0], remaining[1], remaining[2]));
|
|
934
|
-
return finish(exact, approximate, solvedDegree + 2, 0, "");
|
|
935
|
-
}
|
|
936
|
-
const closedForm = closedFormRoots(remaining);
|
|
937
|
-
if (closedForm !== null) {
|
|
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
|
-
};
|
|
968
|
-
}
|
|
969
|
-
return { kind: "roots", exact, approximate };
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
// src/vm/SymbolicOps.ts
|
|
973
|
-
var SYMBOLIC_BUILTIN_NAMES = {
|
|
974
|
-
0: "sqrt",
|
|
975
|
-
1: "abs",
|
|
976
|
-
2: "sin",
|
|
977
|
-
3: "cos",
|
|
978
|
-
4: "tan",
|
|
979
|
-
5: "log",
|
|
980
|
-
6: "ceil",
|
|
981
|
-
7: "floor",
|
|
982
|
-
8: "round",
|
|
983
|
-
11: "asin",
|
|
984
|
-
12: "acos",
|
|
985
|
-
13: "atan",
|
|
986
|
-
14: "atan2",
|
|
987
|
-
15: "sinh",
|
|
988
|
-
16: "cosh",
|
|
989
|
-
17: "tanh",
|
|
990
|
-
18: "asinh",
|
|
991
|
-
19: "acosh",
|
|
992
|
-
20: "atanh",
|
|
993
|
-
21: "cbrt",
|
|
994
|
-
23: "expm1",
|
|
995
|
-
24: "exp",
|
|
996
|
-
26: "hypot",
|
|
997
|
-
28: "log10",
|
|
998
|
-
29: "log1p",
|
|
999
|
-
30: "log2",
|
|
1000
|
-
33: "sign",
|
|
1001
|
-
34: "trunc",
|
|
1002
|
-
// Spelled exactly as `builtinNameToIndex` accepts them, all lower case. A
|
|
1003
|
-
// `call` node's name is what gets displayed, so a name the parser would not
|
|
1004
|
-
// accept back would render an expression the user cannot retype.
|
|
1005
|
-
35: "degtorad",
|
|
1006
|
-
36: "radtodeg",
|
|
1007
|
-
61: "root",
|
|
1008
|
-
62: "fact"
|
|
1009
|
-
};
|
|
1010
|
-
var POW_BUILTIN_INDEX = 31;
|
|
1011
|
-
var SYMBOLIC_NATIVE_BUILTINS = /* @__PURE__ */ new Set([67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79]);
|
|
1012
|
-
function valueToSymbolic(v) {
|
|
1013
|
-
if (v.type === 9 /* Symbolic */) return v.value;
|
|
1014
|
-
if (v.type === 13 /* Error */ || v.type === 12 /* Pending */) return null;
|
|
1015
|
-
const numeric = v.toNumber();
|
|
1016
|
-
if (!Number.isFinite(numeric)) return null;
|
|
1017
|
-
return chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.rationalFromNumber(numeric));
|
|
1018
|
-
}
|
|
1019
|
-
function symbolicToValue(node) {
|
|
1020
|
-
const simplified = chunkHIQ5HSZL_cjs.simplifySymbolic(node);
|
|
1021
|
-
if (simplified.kind === "const") return chunk2TZKENDH_cjs.numberValue(chunkHIQ5HSZL_cjs.rationalToNumber(simplified.value));
|
|
1022
|
-
return chunk2TZKENDH_cjs.symbolicValue(simplified);
|
|
1023
|
-
}
|
|
1024
|
-
function unsupported(what) {
|
|
1025
|
-
return chunk2TZKENDH_cjs.errorValue(
|
|
1026
|
-
"SYMBOLIC_UNSUPPORTED_FUNCTION",
|
|
1027
|
-
`"${what}" cannot be applied to an expression that still contains an unknown.`
|
|
1028
|
-
);
|
|
1029
|
-
}
|
|
1030
|
-
function symbolicPow(l, r) {
|
|
1031
|
-
const base = valueToSymbolic(l);
|
|
1032
|
-
const exponent = valueToSymbolic(r);
|
|
1033
|
-
if (base === null || exponent === null) return unsupported("^");
|
|
1034
|
-
return symbolicToValue(chunkHIQ5HSZL_cjs.powNode(base, exponent));
|
|
1035
|
-
}
|
|
1036
|
-
function symbolicNeg(v) {
|
|
1037
|
-
const operand = valueToSymbolic(v);
|
|
1038
|
-
if (operand === null) return unsupported("-");
|
|
1039
|
-
return symbolicToValue({ kind: "neg", operand });
|
|
1040
|
-
}
|
|
1041
|
-
function symbolicBuiltin(index, args) {
|
|
1042
|
-
const nodes = [];
|
|
1043
|
-
for (const arg of args) {
|
|
1044
|
-
const faulted = chunk2TZKENDH_cjs.faultedOperand(arg);
|
|
1045
|
-
if (faulted) return faulted;
|
|
1046
|
-
const node = valueToSymbolic(arg);
|
|
1047
|
-
if (node === null) return unsupported(SYMBOLIC_BUILTIN_NAMES[index] ?? `builtin ${index}`);
|
|
1048
|
-
nodes.push(node);
|
|
1049
|
-
}
|
|
1050
|
-
if (index === POW_BUILTIN_INDEX && nodes.length === 2) {
|
|
1051
|
-
return symbolicToValue(chunkHIQ5HSZL_cjs.powNode(nodes[0], nodes[1]));
|
|
1052
|
-
}
|
|
1053
|
-
const name = SYMBOLIC_BUILTIN_NAMES[index];
|
|
1054
|
-
if (name === void 0) return unsupported(`builtin ${index}`);
|
|
1055
|
-
return symbolicToValue(chunkHIQ5HSZL_cjs.callNode(name, nodes));
|
|
1056
|
-
}
|
|
1057
|
-
function rootToValue(root) {
|
|
1058
|
-
const value = symbolicToValue(root);
|
|
1059
|
-
if (value.type === 0 /* Number */ && !Number.isInteger(value.toNumber())) return chunk2TZKENDH_cjs.symbolicValue(root);
|
|
1060
|
-
return value;
|
|
1061
|
-
}
|
|
1062
|
-
function approximateRootToValue(root) {
|
|
1063
|
-
if (root.im === 0) return chunk2TZKENDH_cjs.numberValue(root.re);
|
|
1064
|
-
return chunk2TZKENDH_cjs.symbolicValue(chunkHIQ5HSZL_cjs.complexNode(chunkHIQ5HSZL_cjs.complex(chunkHIQ5HSZL_cjs.rationalFromNumber(root.re), chunkHIQ5HSZL_cjs.rationalFromNumber(root.im))));
|
|
1065
|
-
}
|
|
1066
|
-
function solveOutcomeToValue(outcome) {
|
|
1067
|
-
switch (outcome.kind) {
|
|
1068
|
-
case "identity":
|
|
1069
|
-
return chunk2TZKENDH_cjs.stringValue("true for every value");
|
|
1070
|
-
case "contradiction":
|
|
1071
|
-
return chunk2TZKENDH_cjs.stringValue("no solution");
|
|
1072
|
-
case "unsupported":
|
|
1073
|
-
return chunk2TZKENDH_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 chunk2TZKENDH_cjs.errorValue(
|
|
1077
|
-
"SYMBOLIC_SOLVE_INCOMPLETE",
|
|
1078
|
-
`Only ${found} of this equation's ${found + outcome.missing} roots could be found: ${outcome.reason}.`
|
|
1079
|
-
);
|
|
1080
|
-
}
|
|
1081
|
-
case "roots": {
|
|
1082
|
-
const values = outcome.exact.map(rootToValue);
|
|
1083
|
-
for (const approximate of outcome.approximate) values.push(approximateRootToValue(approximate));
|
|
1084
|
-
if (values.length === 0) return chunk2TZKENDH_cjs.stringValue("no solution");
|
|
1085
|
-
if (values.length === 1) return values[0];
|
|
1086
|
-
return chunk2TZKENDH_cjs.matrixValue(1, values.length, values.map((v) => v.type === 9 /* Symbolic */ ? v.value : v.toNumber()));
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
function solveEquationValues(lhsValue, rhsValue, variable) {
|
|
1091
|
-
const lhs = valueToSymbolic(lhsValue);
|
|
1092
|
-
const rhs = valueToSymbolic(rhsValue);
|
|
1093
|
-
if (lhs === null || rhs === null) {
|
|
1094
|
-
return chunk2TZKENDH_cjs.errorValue("SYMBOLIC_NONFINITE_OPERAND", "An equation side has no exact value to solve with.");
|
|
1095
|
-
}
|
|
1096
|
-
return solveOutcomeToValue(solveForVariable(lhs, rhs, variable));
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
// src/vm/VMConversion.ts
|
|
1100
|
-
function unifyUom(l, r) {
|
|
1101
|
-
if (l.type === 6 /* Uom */ && r.type === 6 /* Uom */) {
|
|
1102
|
-
if (l.unit === r.unit) {
|
|
1103
|
-
return { lv: l.toNumber(), rv: r.toNumber(), unit: l.unit, sameMeasure: true };
|
|
1104
|
-
}
|
|
1105
|
-
const lMeasure = chunkEJ3ILXX6_cjs.getMeasure(l.unit);
|
|
1106
|
-
const rMeasure = chunkEJ3ILXX6_cjs.getMeasure(r.unit);
|
|
1107
|
-
const isCurrency = chunkZVTWQLK4_cjs.sharedCurrencyExchange.isCurrency(l.unit) && chunkZVTWQLK4_cjs.sharedCurrencyExchange.isCurrency(r.unit);
|
|
1108
|
-
if (lMeasure && lMeasure === rMeasure) {
|
|
1109
|
-
const rvConverted = chunkEJ3ILXX6_cjs.convertUnit(r.toNumber(), r.unit, l.unit);
|
|
1110
|
-
return { lv: l.toNumber(), rv: rvConverted, unit: l.unit, sameMeasure: true };
|
|
1111
|
-
}
|
|
1112
|
-
if (isCurrency) {
|
|
1113
|
-
const rvConverted = chunkZVTWQLK4_cjs.sharedCurrencyExchange.convertSync(r.toNumber(), r.unit, l.unit);
|
|
1114
|
-
if (rvConverted !== null) {
|
|
1115
|
-
return { lv: l.toNumber(), rv: rvConverted, unit: l.unit, sameMeasure: true };
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
return { lv: l.toNumber(), rv: r.toNumber(), unit: void 0, sameMeasure: false };
|
|
1119
|
-
}
|
|
1120
|
-
if (l.type === 6 /* Uom */) {
|
|
1121
|
-
return { lv: l.toNumber(), rv: r.toNumber(), unit: l.unit, sameMeasure: true };
|
|
1122
|
-
}
|
|
1123
|
-
if (r.type === 6 /* Uom */) {
|
|
1124
|
-
return { lv: l.toNumber(), rv: r.toNumber(), unit: r.unit, sameMeasure: true };
|
|
1125
|
-
}
|
|
1126
|
-
return { lv: l.toNumber(), rv: r.toNumber(), unit: void 0, sameMeasure: true };
|
|
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 (l.type === 6 /* Uom */ && r.type === 6 /* Uom */ && l.unit !== void 0 && l.unit === r.unit && l.exact !== void 0 && r.exact !== void 0 && chunkZVTWQLK4_cjs.sharedCurrencyExchange.isCurrency(l.unit)) {
|
|
1140
|
-
return { lv, rv, equal: chunkHIQ5HSZL_cjs.decimalCompare(l.exact, r.exact) === 0, sameMeasure: true };
|
|
1141
|
-
}
|
|
1142
|
-
if (lv === rv) return { lv, rv, equal: true, sameMeasure: true };
|
|
1143
|
-
if (!Number.isFinite(lv) || !Number.isFinite(rv)) return { lv, rv, equal: false, sameMeasure: true };
|
|
1144
|
-
const scale2 = largestFiniteMagnitude(lv, rv, r.toNumber());
|
|
1145
|
-
return { lv, rv, equal: Math.abs(lv - rv) <= scale2 * UNIFIED_COMPARISON_TOLERANCE, sameMeasure: true };
|
|
1146
|
-
}
|
|
1147
|
-
var MEASURE_NOUNS = {
|
|
1148
|
-
time: "duration",
|
|
1149
|
-
luminousIntensity: "luminous intensity"
|
|
1150
|
-
};
|
|
1151
|
-
var UNCOUNTABLE_MEASURES = /* @__PURE__ */ new Set(["money", "data"]);
|
|
1152
|
-
var COMBINE_VERBS = {
|
|
1153
|
-
add: "added",
|
|
1154
|
-
sub: "subtracted",
|
|
1155
|
-
mul: "multiplied",
|
|
1156
|
-
div: "divided"
|
|
1157
|
-
};
|
|
1158
|
-
function describeMeasure(unit) {
|
|
1159
|
-
if (chunkZVTWQLK4_cjs.sharedCurrencyExchange.isCurrency(unit)) return "money";
|
|
1160
|
-
const measure = chunkEJ3ILXX6_cjs.getMeasure(unit);
|
|
1161
|
-
if (measure === void 0) return void 0;
|
|
1162
|
-
return MEASURE_NOUNS[measure] ?? measure;
|
|
1163
|
-
}
|
|
1164
|
-
function withMeasureArticle(noun) {
|
|
1165
|
-
if (UNCOUNTABLE_MEASURES.has(noun)) return noun;
|
|
1166
|
-
return /^[aeiou]/.test(noun) ? `an ${noun}` : `a ${noun}`;
|
|
1167
|
-
}
|
|
1168
|
-
function describeMeasureMismatch(lUnit, rUnit, verb) {
|
|
1169
|
-
const left = lUnit === void 0 ? void 0 : describeMeasure(lUnit);
|
|
1170
|
-
const right = rUnit === void 0 ? void 0 : describeMeasure(rUnit);
|
|
1171
|
-
if (left !== void 0 && right !== void 0 && left !== right) {
|
|
1172
|
-
return `${left} and ${right} cannot be ${verb}`;
|
|
1173
|
-
}
|
|
1174
|
-
return void 0;
|
|
1175
|
-
}
|
|
1176
|
-
function combineVerb(op) {
|
|
1177
|
-
return op !== void 0 ? COMBINE_VERBS[op] ?? "combined" : "combined";
|
|
1178
|
-
}
|
|
1179
|
-
function describeConversionMismatch(fromUnit, toUnit) {
|
|
1180
|
-
const from = describeMeasure(fromUnit);
|
|
1181
|
-
const to = describeMeasure(toUnit);
|
|
1182
|
-
if (from !== void 0 && to !== void 0 && from !== to) {
|
|
1183
|
-
return `${withMeasureArticle(from)} cannot be converted to ${withMeasureArticle(to)}`;
|
|
1184
|
-
}
|
|
1185
|
-
return void 0;
|
|
1186
|
-
}
|
|
1187
|
-
function incomparableUnitsError(l, r) {
|
|
1188
|
-
const lUnit = l.type === 6 /* Uom */ ? l.unit : void 0;
|
|
1189
|
-
const rUnit = r.type === 6 /* Uom */ ? r.unit : void 0;
|
|
1190
|
-
const named = describeMeasureMismatch(lUnit, rUnit, "compared");
|
|
1191
|
-
return chunk2TZKENDH_cjs.errorValue("INCOMPATIBLE_UNITS", named ?? `Cannot compare incompatible units: ${lUnit ?? "?"} and ${rUnit ?? "?"}`);
|
|
1192
|
-
}
|
|
1193
|
-
function toBigIntOperand(v) {
|
|
1194
|
-
if (v.type === 2 /* BigInt */) return v.value;
|
|
1195
|
-
const n = v.toNumber();
|
|
1196
|
-
if (!Number.isInteger(n)) {
|
|
1197
|
-
const shown = Number.isNaN(n) ? "NaN" : String(n);
|
|
1198
|
-
throw chunkB4HBEFTB_cjs.ErrorFactory.execution(
|
|
1199
|
-
"BIGINT_INEXACT_OPERAND",
|
|
1200
|
-
`A whole-number (n) value can only be combined with another whole number, and ${shown} is not one`,
|
|
1201
|
-
{ operand: shown }
|
|
1202
|
-
);
|
|
1203
|
-
}
|
|
1204
|
-
return BigInt(n);
|
|
1205
|
-
}
|
|
1206
|
-
function bigIntDivisionByZero() {
|
|
1207
|
-
return chunkB4HBEFTB_cjs.ErrorFactory.execution(
|
|
1208
|
-
"BIGINT_DIVISION_BY_ZERO",
|
|
1209
|
-
"Division by zero: a whole-number (n) division is exact integer division, which has no answer at zero, unlike 1 / 0 which is Infinity"
|
|
1210
|
-
);
|
|
1211
|
-
}
|
|
1212
|
-
function compareBigIntOperands(l, r) {
|
|
1213
|
-
const lb = exactBigInt(l);
|
|
1214
|
-
const rb = exactBigInt(r);
|
|
1215
|
-
if (lb === null || rb === null) return null;
|
|
1216
|
-
if (lb < rb) return -1;
|
|
1217
|
-
if (lb > rb) return 1;
|
|
1218
|
-
return 0;
|
|
1219
|
-
}
|
|
1220
|
-
function exactBigInt(v) {
|
|
1221
|
-
if (v.type === 2 /* BigInt */) return v.value;
|
|
1222
|
-
const n = v.toNumber();
|
|
1223
|
-
return Number.isInteger(n) ? BigInt(n) : null;
|
|
1224
|
-
}
|
|
1225
|
-
function power(base, exponent) {
|
|
1226
|
-
if (Number.isFinite(exponent)) return Math.pow(base, exponent);
|
|
1227
|
-
if (base === 1) return 1;
|
|
1228
|
-
if (base === -1 && !Number.isNaN(exponent)) return 1;
|
|
1229
|
-
return Math.pow(base, exponent);
|
|
1230
|
-
}
|
|
1231
|
-
function operandExactDecimal(v) {
|
|
1232
|
-
if (v.exact !== void 0) return v.exact;
|
|
1233
|
-
return chunkHIQ5HSZL_cjs.decimalFromNumberIfExact(v.toNumber());
|
|
1234
|
-
}
|
|
1235
|
-
function exactMoneyOp(l, r, op) {
|
|
1236
|
-
const lMoney = l.type === 6 /* Uom */ && l.unit !== void 0 && l.exact !== void 0 && chunkZVTWQLK4_cjs.sharedCurrencyExchange.isCurrency(l.unit);
|
|
1237
|
-
const rMoney = r.type === 6 /* Uom */ && r.unit !== void 0 && r.exact !== void 0 && chunkZVTWQLK4_cjs.sharedCurrencyExchange.isCurrency(r.unit);
|
|
1238
|
-
if (!lMoney && !rMoney) return null;
|
|
1239
|
-
let ld;
|
|
1240
|
-
let rd;
|
|
1241
|
-
let unit;
|
|
1242
|
-
if (lMoney && rMoney) {
|
|
1243
|
-
if (l.unit !== r.unit || op === "div") return null;
|
|
1244
|
-
ld = l.exact;
|
|
1245
|
-
rd = r.exact;
|
|
1246
|
-
unit = l.unit;
|
|
1247
|
-
} else if (lMoney && r.type !== 6 /* Uom */) {
|
|
1248
|
-
ld = l.exact;
|
|
1249
|
-
unit = l.unit;
|
|
1250
|
-
rd = operandExactDecimal(r);
|
|
1251
|
-
} else if (rMoney && l.type !== 6 /* Uom */) {
|
|
1252
|
-
rd = r.exact;
|
|
1253
|
-
unit = r.unit;
|
|
1254
|
-
ld = operandExactDecimal(l);
|
|
1255
|
-
} else {
|
|
1256
|
-
return null;
|
|
1257
|
-
}
|
|
1258
|
-
if (ld === null || rd === null) return null;
|
|
1259
|
-
let result;
|
|
1260
|
-
switch (op) {
|
|
1261
|
-
case "add":
|
|
1262
|
-
result = chunkHIQ5HSZL_cjs.decimalAdd(ld, rd);
|
|
1263
|
-
break;
|
|
1264
|
-
case "sub":
|
|
1265
|
-
result = chunkHIQ5HSZL_cjs.decimalSubtract(ld, rd);
|
|
1266
|
-
break;
|
|
1267
|
-
case "mul":
|
|
1268
|
-
result = chunkHIQ5HSZL_cjs.decimalMultiply(ld, rd);
|
|
1269
|
-
break;
|
|
1270
|
-
case "div":
|
|
1271
|
-
if (chunkHIQ5HSZL_cjs.decimalIsZero(rd)) return null;
|
|
1272
|
-
result = chunkHIQ5HSZL_cjs.decimalDivide(ld, rd);
|
|
1273
|
-
break;
|
|
1274
|
-
}
|
|
1275
|
-
return chunk2TZKENDH_cjs.uomValueExact(chunkHIQ5HSZL_cjs.decimalToNumber(result), unit, result);
|
|
1276
|
-
}
|
|
1277
|
-
function operandRational(v) {
|
|
1278
|
-
if (v.rational !== void 0) return v.rational;
|
|
1279
|
-
if ((v.type === 0 /* Number */ || v.type === 1 /* Hex */) && typeof v.value === "number" && Number.isInteger(v.value)) {
|
|
1280
|
-
return chunkHIQ5HSZL_cjs.rational(BigInt(v.value));
|
|
1281
|
-
}
|
|
1282
|
-
return null;
|
|
1283
|
-
}
|
|
1284
|
-
function exactRationalOp(l, r, op) {
|
|
1285
|
-
const lr = operandRational(l);
|
|
1286
|
-
if (lr === null) return null;
|
|
1287
|
-
const rr = operandRational(r);
|
|
1288
|
-
if (rr === null) return null;
|
|
1289
|
-
if (op === "div" && chunkHIQ5HSZL_cjs.isRationalZero(rr)) return null;
|
|
1290
|
-
let result;
|
|
1291
|
-
try {
|
|
1292
|
-
switch (op) {
|
|
1293
|
-
case "add":
|
|
1294
|
-
result = chunkHIQ5HSZL_cjs.rationalAdd(lr, rr);
|
|
1295
|
-
break;
|
|
1296
|
-
case "sub":
|
|
1297
|
-
result = chunkHIQ5HSZL_cjs.rationalSub(lr, rr);
|
|
1298
|
-
break;
|
|
1299
|
-
case "mul":
|
|
1300
|
-
result = chunkHIQ5HSZL_cjs.rationalMul(lr, rr);
|
|
1301
|
-
break;
|
|
1302
|
-
case "div":
|
|
1303
|
-
result = chunkHIQ5HSZL_cjs.rationalDiv(lr, rr);
|
|
1304
|
-
break;
|
|
1305
|
-
}
|
|
1306
|
-
} catch {
|
|
1307
|
-
return null;
|
|
1308
|
-
}
|
|
1309
|
-
return chunk2TZKENDH_cjs.numberValueRational(chunkHIQ5HSZL_cjs.rationalToNumber(result), result);
|
|
1310
|
-
}
|
|
1311
|
-
function uncertainOp(l, r, op) {
|
|
1312
|
-
if (l.type !== 0 /* Number */ || r.type !== 0 /* Number */) return null;
|
|
1313
|
-
const a = l.value;
|
|
1314
|
-
const b = r.value;
|
|
1315
|
-
const sa = l.uncertainty ?? 0;
|
|
1316
|
-
const sb = r.uncertainty ?? 0;
|
|
1317
|
-
let center;
|
|
1318
|
-
let sigma;
|
|
1319
|
-
switch (op) {
|
|
1320
|
-
case "add":
|
|
1321
|
-
center = a + b;
|
|
1322
|
-
sigma = Math.hypot(sa, sb);
|
|
1323
|
-
break;
|
|
1324
|
-
case "sub":
|
|
1325
|
-
center = a - b;
|
|
1326
|
-
sigma = Math.hypot(sa, sb);
|
|
1327
|
-
break;
|
|
1328
|
-
case "mul":
|
|
1329
|
-
center = a * b;
|
|
1330
|
-
sigma = Math.hypot(b * sa, a * sb);
|
|
1331
|
-
break;
|
|
1332
|
-
case "div":
|
|
1333
|
-
center = a / b;
|
|
1334
|
-
sigma = Math.hypot(sa / b, a * sb / (b * b));
|
|
1335
|
-
break;
|
|
1336
|
-
}
|
|
1337
|
-
return chunk2TZKENDH_cjs.numberValueUncertain(center, sigma);
|
|
1338
|
-
}
|
|
1339
|
-
function compareRationalOperands(l, r) {
|
|
1340
|
-
const lr = operandRational(l);
|
|
1341
|
-
if (lr === null) return null;
|
|
1342
|
-
const rr = operandRational(r);
|
|
1343
|
-
if (rr === null) return null;
|
|
1344
|
-
return chunkHIQ5HSZL_cjs.rationalCompare(lr, rr);
|
|
1345
|
-
}
|
|
1346
|
-
function binaryOp(l, r, op, bigOp, symbolicOp) {
|
|
1347
|
-
if (l.type === 13 /* Error */) return l;
|
|
1348
|
-
if (r.type === 13 /* Error */) return r;
|
|
1349
|
-
if (l.type === 12 /* Pending */) return l;
|
|
1350
|
-
if (r.type === 12 /* Pending */) return r;
|
|
1351
|
-
if (symbolicOp && (l.type === 9 /* Symbolic */ || r.type === 9 /* Symbolic */)) {
|
|
1352
|
-
const left = valueToSymbolic(l);
|
|
1353
|
-
const right = valueToSymbolic(r);
|
|
1354
|
-
if (left === null || right === null) {
|
|
1355
|
-
return chunk2TZKENDH_cjs.errorValue(
|
|
1356
|
-
"SYMBOLIC_NONFINITE_OPERAND",
|
|
1357
|
-
"A symbolic expression cannot combine with a value that has no exact number (NaN or infinity)."
|
|
1358
|
-
);
|
|
1359
|
-
}
|
|
1360
|
-
const node = { kind: symbolicOp, left, right };
|
|
1361
|
-
return chunk2TZKENDH_cjs.symbolicValue(chunkHIQ5HSZL_cjs.simplifySymbolic(node));
|
|
1362
|
-
}
|
|
1363
|
-
if (l.type === 0 /* Number */ && r.type === 0 /* Number */) {
|
|
1364
|
-
return chunk2TZKENDH_cjs.numberValue(op(l.value, r.value));
|
|
1365
|
-
}
|
|
1366
|
-
if (l.type === 2 /* BigInt */ || r.type === 2 /* BigInt */) {
|
|
1367
|
-
const lb = toBigIntOperand(l);
|
|
1368
|
-
const rb = toBigIntOperand(r);
|
|
1369
|
-
if (bigOp) return chunk2TZKENDH_cjs.bigIntValue(bigOp(lb, rb));
|
|
1370
|
-
return chunk2TZKENDH_cjs.bigIntValue(lb + rb);
|
|
1371
|
-
}
|
|
1372
|
-
if (l.type === 6 /* Uom */ || r.type === 6 /* Uom */) {
|
|
1373
|
-
if (symbolicOp) {
|
|
1374
|
-
const exactMoney = exactMoneyOp(l, r, symbolicOp);
|
|
1375
|
-
if (exactMoney) return exactMoney;
|
|
1376
|
-
}
|
|
1377
|
-
const { lv, rv, unit, sameMeasure } = unifyUom(l, r);
|
|
1378
|
-
if (!sameMeasure) {
|
|
1379
|
-
const lUnit = l.type === 6 /* Uom */ ? l.unit : void 0;
|
|
1380
|
-
const rUnit = r.type === 6 /* Uom */ ? r.unit : void 0;
|
|
1381
|
-
const named = describeMeasureMismatch(lUnit, rUnit, combineVerb(symbolicOp));
|
|
1382
|
-
return chunk2TZKENDH_cjs.errorValue("INCOMPATIBLE_UNITS", named ?? `Cannot combine incompatible units: ${lUnit ?? "?"} and ${rUnit ?? "?"}`);
|
|
1383
|
-
}
|
|
1384
|
-
return chunk2TZKENDH_cjs.uomValue(op(lv, rv), unit);
|
|
1385
|
-
}
|
|
1386
|
-
if (l.type === 7 /* Matrix */ && r.type === 7 /* Matrix */) {
|
|
1387
|
-
const lm = l.value;
|
|
1388
|
-
const rm = r.value;
|
|
1389
|
-
if (!chunkHIQ5HSZL_cjs.sameShape(lm, rm)) {
|
|
1390
|
-
return chunk2TZKENDH_cjs.errorValue("DIMENSION_MISMATCH", `Cannot combine matrices of different shapes: ${lm.rows}x${lm.cols} and ${rm.rows}x${rm.cols}`);
|
|
1391
|
-
}
|
|
1392
|
-
const result = new Array(lm.data.length);
|
|
1393
|
-
for (let i = 0; i < lm.data.length; i++) result[i] = op(lm.data[i], rm.data[i]);
|
|
1394
|
-
return chunk2TZKENDH_cjs.matrixValue(lm.rows, lm.cols, result);
|
|
1395
|
-
}
|
|
1396
|
-
if (l.type === 7 /* Matrix */) {
|
|
1397
|
-
const lm = l.value;
|
|
1398
|
-
const scalar = r.toNumber();
|
|
1399
|
-
const result = lm.data.map((v) => op(v, scalar));
|
|
1400
|
-
return chunk2TZKENDH_cjs.matrixValue(lm.rows, lm.cols, result);
|
|
1401
|
-
}
|
|
1402
|
-
if (r.type === 7 /* Matrix */) {
|
|
1403
|
-
const rm = r.value;
|
|
1404
|
-
const scalar = l.toNumber();
|
|
1405
|
-
const result = rm.data.map((v) => op(scalar, v));
|
|
1406
|
-
return chunk2TZKENDH_cjs.matrixValue(rm.rows, rm.cols, result);
|
|
1407
|
-
}
|
|
1408
|
-
return chunk2TZKENDH_cjs.numberValue(op(l.toNumber(), r.toNumber()));
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
// src/vm/OpRegistry.ts
|
|
1412
|
-
var MAX_OPCODE = 254;
|
|
1413
|
-
var DYNAMIC_OPCODE_START = 200;
|
|
1414
|
-
var OpRegistry = class {
|
|
1415
|
-
constructor() {
|
|
1416
|
-
this.handlers = /* @__PURE__ */ new Map();
|
|
1417
|
-
this.nextOpcode = DYNAMIC_OPCODE_START + 1;
|
|
1418
|
-
}
|
|
1419
|
-
register(registration) {
|
|
1420
|
-
this.handlers.set(registration.opcode, registration.handler);
|
|
1421
|
-
}
|
|
1422
|
-
/**
|
|
1423
|
-
* Remove a previously registered opcode handler.
|
|
1424
|
-
* Used by package unregistration to reverse shared-registry contributions.
|
|
1425
|
-
*/
|
|
1426
|
-
unregister(opcode) {
|
|
1427
|
-
this.handlers.delete(opcode);
|
|
1428
|
-
}
|
|
1429
|
-
get(opcode) {
|
|
1430
|
-
return this.handlers.get(opcode);
|
|
1431
|
-
}
|
|
1432
|
-
has(opcode) {
|
|
1433
|
-
return this.handlers.has(opcode);
|
|
1434
|
-
}
|
|
1435
|
-
/**
|
|
1436
|
-
* Allocate a unique opcode for a plugin's custom bytecode handler.
|
|
1437
|
-
*
|
|
1438
|
-
* Returns the next available opcode (starting at 201). Each call
|
|
1439
|
-
* returns a distinct value. Plugins should call this once during
|
|
1440
|
-
* registration and store the result.
|
|
1441
|
-
*
|
|
1442
|
-
* @throws If the dynamic opcode pool is exhausted.
|
|
1443
|
-
* @returns A unique opcode number for the calling plugin.
|
|
1444
|
-
*/
|
|
1445
|
-
allocateOpcode() {
|
|
1446
|
-
if (this.nextOpcode > MAX_OPCODE) {
|
|
1447
|
-
throw chunkB4HBEFTB_cjs.ErrorFactory.config(
|
|
1448
|
-
"OPCODE_POOL_EXHAUSTED",
|
|
1449
|
-
`OpRegistry: dynamic opcode pool exhausted (max ${MAX_OPCODE - DYNAMIC_OPCODE_START} allocations).`
|
|
1450
|
-
);
|
|
1451
|
-
}
|
|
1452
|
-
return this.nextOpcode++;
|
|
1453
|
-
}
|
|
1454
|
-
};
|
|
1455
|
-
var sharedOpRegistry = new OpRegistry();
|
|
1456
|
-
|
|
1457
|
-
// src/vm/MoneyExact.ts
|
|
1458
|
-
var ONE_DECIMAL = chunkHIQ5HSZL_cjs.decimalFromInteger(1);
|
|
1459
|
-
function moneyExactMagnitude(operand, unit) {
|
|
1460
|
-
if (!chunkZVTWQLK4_cjs.sharedCurrencyExchange.isCurrency(unit)) return null;
|
|
1461
|
-
return operand.exact ?? chunkHIQ5HSZL_cjs.decimalFromNumberIfExact(operand.toNumber());
|
|
1462
|
-
}
|
|
1463
|
-
function decimalFromShortDecimal(n) {
|
|
1464
|
-
if (!Number.isFinite(n)) return null;
|
|
1465
|
-
if (Number.isInteger(n)) return chunkHIQ5HSZL_cjs.decimalFromInteger(BigInt(n));
|
|
1466
|
-
const s = String(n);
|
|
1467
|
-
if (!/^-?\d+\.\d+$/.test(s)) return null;
|
|
1468
|
-
return chunkHIQ5HSZL_cjs.decimalFromLiteral(s);
|
|
1469
|
-
}
|
|
1470
|
-
function scaleMoneyExact(amount, factor, unit) {
|
|
1471
|
-
const base = moneyExactMagnitude(amount, unit);
|
|
1472
|
-
const factorDecimal = decimalFromShortDecimal(factor);
|
|
1473
|
-
if (base !== null && factorDecimal !== null) {
|
|
1474
|
-
const result = chunkHIQ5HSZL_cjs.decimalMultiply(base, factorDecimal);
|
|
1475
|
-
return chunk2TZKENDH_cjs.uomValueExact(chunkHIQ5HSZL_cjs.decimalToNumber(result), unit, result);
|
|
1476
|
-
}
|
|
1477
|
-
return chunk2TZKENDH_cjs.uomValue(amount.toNumber() * factor, unit);
|
|
1478
|
-
}
|
|
1479
|
-
function scaleMoneyByPercent(money, unit, percent, sign) {
|
|
1480
|
-
const base = moneyExactMagnitude(money, unit);
|
|
1481
|
-
const percentDecimal = decimalFromShortDecimal(percent);
|
|
1482
|
-
if (base !== null && percentDecimal !== null) {
|
|
1483
|
-
const factor = chunkHIQ5HSZL_cjs.decimalAdd(ONE_DECIMAL, sign === 1 ? percentDecimal : chunkHIQ5HSZL_cjs.decimalNegate(percentDecimal));
|
|
1484
|
-
const result = chunkHIQ5HSZL_cjs.decimalMultiply(base, factor);
|
|
1485
|
-
return chunk2TZKENDH_cjs.uomValueExact(chunkHIQ5HSZL_cjs.decimalToNumber(result), unit, result);
|
|
1486
|
-
}
|
|
1487
|
-
return chunk2TZKENDH_cjs.uomValue(money.toNumber() * (1 + sign * percent), unit);
|
|
1488
|
-
}
|
|
1489
|
-
function onePlusRateDecimal(rate) {
|
|
1490
|
-
const rateDecimal = decimalFromShortDecimal(rate);
|
|
1491
|
-
return rateDecimal === null ? null : chunkHIQ5HSZL_cjs.decimalAdd(ONE_DECIMAL, rateDecimal);
|
|
1492
|
-
}
|
|
1493
|
-
function removeTaxExact(money, unit, rate) {
|
|
1494
|
-
const base = moneyExactMagnitude(money, unit);
|
|
1495
|
-
const divisor = onePlusRateDecimal(rate);
|
|
1496
|
-
if (base === null || divisor === null || chunkHIQ5HSZL_cjs.decimalIsZero(divisor)) return null;
|
|
1497
|
-
const quotient = chunkHIQ5HSZL_cjs.decimalDivide(base, divisor);
|
|
1498
|
-
return chunk2TZKENDH_cjs.uomValueExact(chunkHIQ5HSZL_cjs.decimalToNumber(quotient), unit, quotient);
|
|
1499
|
-
}
|
|
1500
|
-
function taxInExact(money, unit, rate) {
|
|
1501
|
-
const base = moneyExactMagnitude(money, unit);
|
|
1502
|
-
const divisor = onePlusRateDecimal(rate);
|
|
1503
|
-
if (base === null || divisor === null || chunkHIQ5HSZL_cjs.decimalIsZero(divisor)) return null;
|
|
1504
|
-
const tax = chunkHIQ5HSZL_cjs.decimalSubtract(base, chunkHIQ5HSZL_cjs.decimalDivide(base, divisor));
|
|
1505
|
-
return chunk2TZKENDH_cjs.uomValueExact(chunkHIQ5HSZL_cjs.decimalToNumber(tax), unit, tax);
|
|
1506
|
-
}
|
|
1507
|
-
|
|
1508
|
-
// src/symbolic/PartialFractions.ts
|
|
1509
|
-
var APART_MAX_DEGREE = 12;
|
|
1510
|
-
function multiply2(a, b) {
|
|
1511
|
-
if (a.length === 0 || b.length === 0) return [];
|
|
1512
|
-
const product2 = new Array(a.length + b.length - 1).fill(chunkHIQ5HSZL_cjs.RATIONAL_ZERO);
|
|
1513
|
-
a.forEach((left, i) => {
|
|
1514
|
-
b.forEach((right, j) => {
|
|
1515
|
-
product2[i + j] = chunkHIQ5HSZL_cjs.rationalAdd(product2[i + j], chunkHIQ5HSZL_cjs.rationalMul(left, right));
|
|
1516
|
-
});
|
|
1517
|
-
});
|
|
1518
|
-
return product2;
|
|
1519
|
-
}
|
|
1520
|
-
function power2(base, exponent) {
|
|
1521
|
-
let result = [chunkHIQ5HSZL_cjs.RATIONAL_ONE];
|
|
1522
|
-
for (let i = 0; i < exponent; i++) result = multiply2(result, base);
|
|
1523
|
-
return result;
|
|
1524
|
-
}
|
|
1525
|
-
function scale(coefficients, factor) {
|
|
1526
|
-
return coefficients.map((coefficient) => chunkHIQ5HSZL_cjs.rationalDiv(coefficient, factor));
|
|
1527
|
-
}
|
|
1528
|
-
function denominatorFactors(ascending, variable) {
|
|
1529
|
-
const factors = [];
|
|
1530
|
-
let lowest = 0;
|
|
1531
|
-
while (lowest < ascending.length && chunkHIQ5HSZL_cjs.isRationalZero(ascending[lowest])) lowest++;
|
|
1532
|
-
if (lowest > 0) factors.push({ base: [chunkHIQ5HSZL_cjs.RATIONAL_ZERO, chunkHIQ5HSZL_cjs.RATIONAL_ONE], power: lowest });
|
|
1533
|
-
const remaining = ascending.slice(lowest);
|
|
1534
|
-
if (remaining.length > 1) {
|
|
1535
|
-
const factorization = factorUnivariate([...remaining].reverse(), variable);
|
|
1536
|
-
for (const factor of factorization.factors) {
|
|
1537
|
-
const polynomial = chunkHIQ5HSZL_cjs.toPolynomial(factor.base);
|
|
1538
|
-
if (polynomial === null) return null;
|
|
1539
|
-
factors.push({ base: [...chunkHIQ5HSZL_cjs.polyCoefficients(polynomial, variable)], power: factor.power });
|
|
1540
|
-
}
|
|
1541
|
-
}
|
|
1542
|
-
return factors.length > 0 ? factors : null;
|
|
1543
|
-
}
|
|
1544
|
-
function enumerateUnknowns(factors) {
|
|
1545
|
-
const unknowns = [];
|
|
1546
|
-
factors.forEach((factor, index) => {
|
|
1547
|
-
const factorDegree = factor.base.length - 1;
|
|
1548
|
-
for (let p = 1; p <= factor.power; p++) {
|
|
1549
|
-
for (let degree = 0; degree < factorDegree; degree++) {
|
|
1550
|
-
unknowns.push({ factor: index, power: p, degree });
|
|
1551
|
-
}
|
|
1552
|
-
}
|
|
1553
|
-
});
|
|
1554
|
-
return unknowns;
|
|
1555
|
-
}
|
|
1556
|
-
function unknownColumn(unknown, factors, denominator) {
|
|
1557
|
-
const divisor = power2(factors[unknown.factor].base, unknown.power);
|
|
1558
|
-
const { quotient, remainder } = chunkHIQ5HSZL_cjs.polynomialDivide(denominator, divisor);
|
|
1559
|
-
if (!chunkHIQ5HSZL_cjs.isZeroPolynomial(remainder)) return null;
|
|
1560
|
-
const shift = new Array(unknown.degree).fill(chunkHIQ5HSZL_cjs.RATIONAL_ZERO);
|
|
1561
|
-
shift.push(chunkHIQ5HSZL_cjs.RATIONAL_ONE);
|
|
1562
|
-
return multiply2(quotient, shift);
|
|
1563
|
-
}
|
|
1564
|
-
function solveLinearSystem(matrix, target) {
|
|
1565
|
-
const size = target.length;
|
|
1566
|
-
for (let column = 0; column < size; column++) {
|
|
1567
|
-
let pivot = -1;
|
|
1568
|
-
for (let row = column; row < size; row++) {
|
|
1569
|
-
if (!chunkHIQ5HSZL_cjs.isRationalZero(matrix[row][column])) {
|
|
1570
|
-
pivot = row;
|
|
1571
|
-
break;
|
|
1572
|
-
}
|
|
1573
|
-
}
|
|
1574
|
-
if (pivot === -1) return null;
|
|
1575
|
-
[matrix[column], matrix[pivot]] = [matrix[pivot], matrix[column]];
|
|
1576
|
-
[target[column], target[pivot]] = [target[pivot], target[column]];
|
|
1577
|
-
for (let row = 0; row < size; row++) {
|
|
1578
|
-
if (row === column || chunkHIQ5HSZL_cjs.isRationalZero(matrix[row][column])) continue;
|
|
1579
|
-
const factor = chunkHIQ5HSZL_cjs.rationalDiv(matrix[row][column], matrix[column][column]);
|
|
1580
|
-
for (let k = column; k < size; k++) {
|
|
1581
|
-
matrix[row][k] = chunkHIQ5HSZL_cjs.rationalSub(matrix[row][k], chunkHIQ5HSZL_cjs.rationalMul(factor, matrix[column][k]));
|
|
1582
|
-
}
|
|
1583
|
-
target[row] = chunkHIQ5HSZL_cjs.rationalSub(target[row], chunkHIQ5HSZL_cjs.rationalMul(factor, target[column]));
|
|
1584
|
-
}
|
|
1585
|
-
}
|
|
1586
|
-
return target.map((value, index) => chunkHIQ5HSZL_cjs.rationalDiv(value, matrix[index][index]));
|
|
1587
|
-
}
|
|
1588
|
-
function partialFractions(numerator, denominator, variable) {
|
|
1589
|
-
if (denominator.length < 2 || denominator.length - 1 > APART_MAX_DEGREE) return null;
|
|
1590
|
-
const shared = chunkHIQ5HSZL_cjs.coefficientGcd(numerator, denominator);
|
|
1591
|
-
const reducedNumerator = shared.length > 1 ? chunkHIQ5HSZL_cjs.polynomialDivide(numerator, shared).quotient : [...numerator];
|
|
1592
|
-
const reducedDenominator = shared.length > 1 ? chunkHIQ5HSZL_cjs.polynomialDivide(denominator, shared).quotient : [...denominator];
|
|
1593
|
-
if (reducedDenominator.length === 1) {
|
|
1594
|
-
return { polynomial: scale(reducedNumerator, reducedDenominator[0]), terms: [] };
|
|
1595
|
-
}
|
|
1596
|
-
if (reducedDenominator.length === 0) return null;
|
|
1597
|
-
const leading = reducedDenominator[reducedDenominator.length - 1];
|
|
1598
|
-
const monicDenominator = scale(reducedDenominator, leading);
|
|
1599
|
-
const scaledNumerator = scale(reducedNumerator, leading);
|
|
1600
|
-
const { quotient, remainder } = chunkHIQ5HSZL_cjs.polynomialDivide(scaledNumerator, monicDenominator);
|
|
1601
|
-
if (chunkHIQ5HSZL_cjs.isZeroPolynomial(remainder)) return { polynomial: quotient, terms: [] };
|
|
1602
|
-
const factors = denominatorFactors(monicDenominator, variable);
|
|
1603
|
-
if (factors === null) return null;
|
|
1604
|
-
const terms = solveForNumerators(factors, monicDenominator, remainder);
|
|
1605
|
-
return terms === null ? null : { polynomial: quotient, terms };
|
|
1606
|
-
}
|
|
1607
|
-
function solveForNumerators(factors, denominator, remainder) {
|
|
1608
|
-
const unknowns = enumerateUnknowns(factors);
|
|
1609
|
-
const size = denominator.length - 1;
|
|
1610
|
-
if (unknowns.length !== size) return null;
|
|
1611
|
-
const columns = [];
|
|
1612
|
-
for (const unknown of unknowns) {
|
|
1613
|
-
const column = unknownColumn(unknown, factors, denominator);
|
|
1614
|
-
if (column === null) return null;
|
|
1615
|
-
columns.push(column);
|
|
1616
|
-
}
|
|
1617
|
-
const matrix = [];
|
|
1618
|
-
for (let row = 0; row < size; row++) {
|
|
1619
|
-
matrix.push(columns.map((column) => column[row] ?? chunkHIQ5HSZL_cjs.RATIONAL_ZERO));
|
|
1620
|
-
}
|
|
1621
|
-
const target = [];
|
|
1622
|
-
for (let row = 0; row < size; row++) target.push(remainder[row] ?? chunkHIQ5HSZL_cjs.RATIONAL_ZERO);
|
|
1623
|
-
const solution = solveLinearSystem(matrix, target);
|
|
1624
|
-
if (solution === null) return null;
|
|
1625
|
-
return groupSolution(unknowns, solution, factors);
|
|
1626
|
-
}
|
|
1627
|
-
function groupSolution(unknowns, solution, factors) {
|
|
1628
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
1629
|
-
unknowns.forEach((unknown, index) => {
|
|
1630
|
-
const key = `${unknown.factor}:${unknown.power}`;
|
|
1631
|
-
const existing = grouped.get(key) ?? [];
|
|
1632
|
-
existing[unknown.degree] = solution[index];
|
|
1633
|
-
grouped.set(key, existing);
|
|
1634
|
-
});
|
|
1635
|
-
const terms = [];
|
|
1636
|
-
for (const [key, coefficients] of grouped) {
|
|
1637
|
-
const [factorIndex, termPower] = key.split(":").map(Number);
|
|
1638
|
-
const filled = [...coefficients].map((value) => value ?? chunkHIQ5HSZL_cjs.RATIONAL_ZERO);
|
|
1639
|
-
if (filled.every(chunkHIQ5HSZL_cjs.isRationalZero)) continue;
|
|
1640
|
-
terms.push({ numerator: filled, base: factors[factorIndex].base, power: termPower });
|
|
1641
|
-
}
|
|
1642
|
-
return terms;
|
|
1643
|
-
}
|
|
1644
|
-
function coefficientsToNode2(coefficients, variable) {
|
|
1645
|
-
const terms = /* @__PURE__ */ new Map();
|
|
1646
|
-
coefficients.forEach((coefficient, exponent) => {
|
|
1647
|
-
if (chunkHIQ5HSZL_cjs.isRationalZero(coefficient)) return;
|
|
1648
|
-
terms.set(exponent === 0 ? "" : exponent === 1 ? variable : `${variable}^${exponent}`, coefficient);
|
|
1649
|
-
});
|
|
1650
|
-
if (terms.size === 0) return chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.RATIONAL_ZERO);
|
|
1651
|
-
return chunkHIQ5HSZL_cjs.fromPolynomial({ terms, vars: coefficients.length > 1 ? [variable] : [] });
|
|
1652
|
-
}
|
|
1653
|
-
function apartSymbolic(node) {
|
|
1654
|
-
const parts = asRationalFunction(node);
|
|
1655
|
-
if (parts === null) return node;
|
|
1656
|
-
const decomposition = partialFractions(parts.numerator, parts.denominator, parts.variable);
|
|
1657
|
-
if (decomposition === null || decomposition.terms.length === 0) return node;
|
|
1658
|
-
let result = decomposition.polynomial.length > 0 ? coefficientsToNode2(decomposition.polynomial, parts.variable) : null;
|
|
1659
|
-
for (const term of decomposition.terms) {
|
|
1660
|
-
const base = coefficientsToNode2(term.base, parts.variable);
|
|
1661
|
-
const denominator = term.power === 1 ? base : chunkHIQ5HSZL_cjs.powNode(base, chunkHIQ5HSZL_cjs.constNode({ n: BigInt(term.power), d: 1n }));
|
|
1662
|
-
const negative = isNegativeNumerator(term.numerator);
|
|
1663
|
-
const numerator = negative ? term.numerator.map((coefficient) => chunkHIQ5HSZL_cjs.rationalNeg(coefficient)) : term.numerator;
|
|
1664
|
-
const piece = {
|
|
1665
|
-
kind: "div",
|
|
1666
|
-
left: coefficientsToNode2(numerator, parts.variable),
|
|
1667
|
-
right: denominator
|
|
1668
|
-
};
|
|
1669
|
-
if (result === null) result = negative ? { kind: "neg", operand: piece } : piece;
|
|
1670
|
-
else result = { kind: negative ? "sub" : "add", left: result, right: piece };
|
|
1671
|
-
}
|
|
1672
|
-
return result === null ? node : chunkHIQ5HSZL_cjs.simplifySymbolic(result);
|
|
1673
|
-
}
|
|
1674
|
-
function isNegativeNumerator(coefficients) {
|
|
1675
|
-
return coefficients.some((coefficient) => coefficient.n < 0n) && coefficients.every((coefficient) => coefficient.n <= 0n);
|
|
1676
|
-
}
|
|
1677
|
-
function asRationalFunction(node) {
|
|
1678
|
-
if (node.kind !== "div") return null;
|
|
1679
|
-
const numerator = chunkHIQ5HSZL_cjs.toPolynomial(node.left);
|
|
1680
|
-
const denominator = chunkHIQ5HSZL_cjs.toPolynomial(node.right);
|
|
1681
|
-
if (numerator === null || denominator === null) return null;
|
|
1682
|
-
const variable = chunkHIQ5HSZL_cjs.polyUnivariateVar(denominator);
|
|
1683
|
-
if (variable === null) return null;
|
|
1684
|
-
if (numerator.vars.some((name) => name !== variable)) return null;
|
|
1685
|
-
return {
|
|
1686
|
-
numerator: chunkHIQ5HSZL_cjs.polyCoefficients(numerator, variable),
|
|
1687
|
-
denominator: chunkHIQ5HSZL_cjs.polyCoefficients(denominator, variable),
|
|
1688
|
-
variable
|
|
1689
|
-
};
|
|
1690
|
-
}
|
|
1691
|
-
|
|
1692
|
-
// src/symbolic/Derivative.ts
|
|
1693
|
-
var DERIVATIVE_MAX_ORDER = 16;
|
|
1694
|
-
function zero() {
|
|
1695
|
-
return chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.RATIONAL_ZERO);
|
|
1696
|
-
}
|
|
1697
|
-
function one() {
|
|
1698
|
-
return chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.RATIONAL_ONE);
|
|
1699
|
-
}
|
|
1700
|
-
function functionDerivative(name, argument) {
|
|
1701
|
-
switch (name) {
|
|
1702
|
-
case "sin":
|
|
1703
|
-
return chunkHIQ5HSZL_cjs.callNode("cos", [argument]);
|
|
1704
|
-
case "cos":
|
|
1705
|
-
return { kind: "neg", operand: chunkHIQ5HSZL_cjs.callNode("sin", [argument]) };
|
|
1706
|
-
case "tan":
|
|
1707
|
-
return { kind: "div", left: one(), right: chunkHIQ5HSZL_cjs.powNode(chunkHIQ5HSZL_cjs.callNode("cos", [argument]), chunkHIQ5HSZL_cjs.constNode(2)) };
|
|
1708
|
-
case "exp":
|
|
1709
|
-
return chunkHIQ5HSZL_cjs.callNode("exp", [argument]);
|
|
1710
|
-
case "log":
|
|
1711
|
-
return { kind: "div", left: one(), right: argument };
|
|
1712
|
-
case "sqrt":
|
|
1713
|
-
return {
|
|
1714
|
-
kind: "div",
|
|
1715
|
-
left: one(),
|
|
1716
|
-
right: { kind: "mul", left: chunkHIQ5HSZL_cjs.constNode(2), right: chunkHIQ5HSZL_cjs.callNode("sqrt", [argument]) }
|
|
1717
|
-
};
|
|
1718
|
-
case "asin":
|
|
1719
|
-
return { kind: "div", left: one(), right: chunkHIQ5HSZL_cjs.callNode("sqrt", [oneMinusSquare(argument)]) };
|
|
1720
|
-
case "acos":
|
|
1721
|
-
return { kind: "neg", operand: { kind: "div", left: one(), right: chunkHIQ5HSZL_cjs.callNode("sqrt", [oneMinusSquare(argument)]) } };
|
|
1722
|
-
case "atan":
|
|
1723
|
-
return { kind: "div", left: one(), right: onePlusSquare(argument) };
|
|
1724
|
-
case "sinh":
|
|
1725
|
-
return chunkHIQ5HSZL_cjs.callNode("cosh", [argument]);
|
|
1726
|
-
case "cosh":
|
|
1727
|
-
return chunkHIQ5HSZL_cjs.callNode("sinh", [argument]);
|
|
1728
|
-
case "tanh":
|
|
1729
|
-
return { kind: "div", left: one(), right: chunkHIQ5HSZL_cjs.powNode(chunkHIQ5HSZL_cjs.callNode("cosh", [argument]), chunkHIQ5HSZL_cjs.constNode(2)) };
|
|
1730
|
-
case "abs":
|
|
1731
|
-
return chunkHIQ5HSZL_cjs.callNode("sign", [argument]);
|
|
1732
|
-
default:
|
|
1733
|
-
return null;
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
function oneMinusSquare(argument) {
|
|
1737
|
-
return { kind: "sub", left: one(), right: chunkHIQ5HSZL_cjs.powNode(argument, chunkHIQ5HSZL_cjs.constNode(2)) };
|
|
1738
|
-
}
|
|
1739
|
-
function onePlusSquare(argument) {
|
|
1740
|
-
return { kind: "add", left: one(), right: chunkHIQ5HSZL_cjs.powNode(argument, chunkHIQ5HSZL_cjs.constNode(2)) };
|
|
1741
|
-
}
|
|
1742
|
-
function differentiate2(node, variable, order = 1) {
|
|
1743
|
-
if (order < 0 || !Number.isInteger(order)) {
|
|
1744
|
-
throw chunkB4HBEFTB_cjs.ErrorFactory.execution("SYMBOLIC_DERIVATIVE_ORDER_LIMIT", "A derivative order must be a whole number, at least zero.");
|
|
1745
|
-
}
|
|
1746
|
-
if (order > DERIVATIVE_MAX_ORDER) {
|
|
1747
|
-
throw chunkB4HBEFTB_cjs.ErrorFactory.execution(
|
|
1748
|
-
"SYMBOLIC_DERIVATIVE_ORDER_LIMIT",
|
|
1749
|
-
`A derivative order above ${DERIVATIVE_MAX_ORDER} is not supported.`,
|
|
1750
|
-
{ limit: DERIVATIVE_MAX_ORDER }
|
|
1751
|
-
);
|
|
1752
|
-
}
|
|
1753
|
-
let result = chunkHIQ5HSZL_cjs.simplifySymbolic(node);
|
|
1754
|
-
for (let i = 0; i < order; i++) result = chunkHIQ5HSZL_cjs.simplifySymbolic(derive(result, variable));
|
|
1755
|
-
return result;
|
|
1756
|
-
}
|
|
1757
|
-
function derive(node, variable) {
|
|
1758
|
-
switch (node.kind) {
|
|
1759
|
-
case "const":
|
|
1760
|
-
case "complex":
|
|
1761
|
-
return zero();
|
|
1762
|
-
case "var":
|
|
1763
|
-
return node.name === variable ? one() : zero();
|
|
1764
|
-
case "add":
|
|
1765
|
-
return { kind: "add", left: derive(node.left, variable), right: derive(node.right, variable) };
|
|
1766
|
-
case "sub":
|
|
1767
|
-
return { kind: "sub", left: derive(node.left, variable), right: derive(node.right, variable) };
|
|
1768
|
-
case "neg":
|
|
1769
|
-
return { kind: "neg", operand: derive(node.operand, variable) };
|
|
1770
|
-
case "mul":
|
|
1771
|
-
return {
|
|
1772
|
-
kind: "add",
|
|
1773
|
-
left: { kind: "mul", left: derive(node.left, variable), right: node.right },
|
|
1774
|
-
right: { kind: "mul", left: node.left, right: derive(node.right, variable) }
|
|
1775
|
-
};
|
|
1776
|
-
case "div":
|
|
1777
|
-
return {
|
|
1778
|
-
kind: "div",
|
|
1779
|
-
left: {
|
|
1780
|
-
kind: "sub",
|
|
1781
|
-
left: { kind: "mul", left: derive(node.left, variable), right: node.right },
|
|
1782
|
-
right: { kind: "mul", left: node.left, right: derive(node.right, variable) }
|
|
1783
|
-
},
|
|
1784
|
-
right: chunkHIQ5HSZL_cjs.powNode(node.right, chunkHIQ5HSZL_cjs.constNode(2))
|
|
1785
|
-
};
|
|
1786
|
-
case "pow":
|
|
1787
|
-
return derivePow(node, variable);
|
|
1788
|
-
case "call": {
|
|
1789
|
-
if (node.args.length !== 1) return unevaluated(node, variable);
|
|
1790
|
-
const outer = functionDerivative(node.name, node.args[0]);
|
|
1791
|
-
if (outer === null) return unevaluated(node, variable);
|
|
1792
|
-
return { kind: "mul", left: outer, right: derive(node.args[0], variable) };
|
|
1793
|
-
}
|
|
1794
|
-
}
|
|
1795
|
-
}
|
|
1796
|
-
function derivePow(node, variable) {
|
|
1797
|
-
if (node.exponent.kind === "const") {
|
|
1798
|
-
const reduced = chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.rationalSub(node.exponent.value, chunkHIQ5HSZL_cjs.RATIONAL_ONE));
|
|
1799
|
-
return {
|
|
1800
|
-
kind: "mul",
|
|
1801
|
-
left: { kind: "mul", left: node.exponent, right: chunkHIQ5HSZL_cjs.powNode(node.base, reduced) },
|
|
1802
|
-
right: derive(node.base, variable)
|
|
1803
|
-
};
|
|
1804
|
-
}
|
|
1805
|
-
if (node.base.kind === "const" && node.base.value.n > 0n) {
|
|
1806
|
-
return {
|
|
1807
|
-
kind: "mul",
|
|
1808
|
-
left: { kind: "mul", left: node, right: chunkHIQ5HSZL_cjs.callNode("log", [node.base]) },
|
|
1809
|
-
right: derive(node.exponent, variable)
|
|
1810
|
-
};
|
|
1811
|
-
}
|
|
1812
|
-
return unevaluated(node, variable);
|
|
1813
|
-
}
|
|
1814
|
-
function unevaluated(node, variable) {
|
|
1815
|
-
return chunkHIQ5HSZL_cjs.callNode("der", [node, chunkHIQ5HSZL_cjs.varNode(variable)]);
|
|
1816
|
-
}
|
|
1817
|
-
|
|
1818
|
-
// src/symbolic/Integral.ts
|
|
1819
|
-
function asLinear(node, variable) {
|
|
1820
|
-
const polynomial = chunkHIQ5HSZL_cjs.toPolynomial(node);
|
|
1821
|
-
if (polynomial === null) return null;
|
|
1822
|
-
const others = polynomial.vars.filter((name) => name !== variable);
|
|
1823
|
-
if (others.length > 0) return null;
|
|
1824
|
-
if (chunkHIQ5HSZL_cjs.polyDegree(polynomial, variable) > 1) return null;
|
|
1825
|
-
const ascending = chunkHIQ5HSZL_cjs.polyCoefficients(polynomial, variable);
|
|
1826
|
-
const intercept = ascending[0] ?? { n: 0n, d: 1n };
|
|
1827
|
-
const slope = ascending[1] ?? { n: 0n, d: 1n };
|
|
1828
|
-
return chunkHIQ5HSZL_cjs.isRationalZero(slope) ? null : { slope, intercept };
|
|
1829
|
-
}
|
|
1830
|
-
function integratePolynomial(node, variable) {
|
|
1831
|
-
const polynomial = chunkHIQ5HSZL_cjs.toPolynomial(node);
|
|
1832
|
-
if (polynomial === null) return null;
|
|
1833
|
-
const others = polynomial.vars.filter((name) => name !== variable);
|
|
1834
|
-
if (others.length > 0) {
|
|
1835
|
-
return { ok: false, reason: `it involves more than one unknown (${others.join(", ")})` };
|
|
1836
|
-
}
|
|
1837
|
-
const ascending = chunkHIQ5HSZL_cjs.polyCoefficients(polynomial, variable);
|
|
1838
|
-
let result = chunkHIQ5HSZL_cjs.constNode(0);
|
|
1839
|
-
ascending.forEach((coeff, power3) => {
|
|
1840
|
-
if (chunkHIQ5HSZL_cjs.isRationalZero(coeff)) return;
|
|
1841
|
-
const nextPower = power3 + 1;
|
|
1842
|
-
const scaled = chunkHIQ5HSZL_cjs.rationalDiv(coeff, { n: BigInt(nextPower), d: 1n });
|
|
1843
|
-
const term = {
|
|
1844
|
-
kind: "mul",
|
|
1845
|
-
left: chunkHIQ5HSZL_cjs.constNode(scaled),
|
|
1846
|
-
right: nextPower === 1 ? chunkHIQ5HSZL_cjs.varNode(variable) : chunkHIQ5HSZL_cjs.powNode(chunkHIQ5HSZL_cjs.varNode(variable), chunkHIQ5HSZL_cjs.constNode(nextPower))
|
|
1847
|
-
};
|
|
1848
|
-
result = { kind: "add", left: result, right: term };
|
|
1849
|
-
});
|
|
1850
|
-
return { ok: true, value: chunkHIQ5HSZL_cjs.simplifySymbolic(result) };
|
|
1851
|
-
}
|
|
1852
|
-
function integrateStandardForm(node, variable) {
|
|
1853
|
-
if (node.kind !== "call" || node.args.length !== 1) return null;
|
|
1854
|
-
const linear = asLinear(node.args[0], variable);
|
|
1855
|
-
if (linear === null) return null;
|
|
1856
|
-
const inner = node.args[0];
|
|
1857
|
-
const divideBySlope = (value) => chunkHIQ5HSZL_cjs.simplifySymbolic({ kind: "div", left: value, right: chunkHIQ5HSZL_cjs.constNode(linear.slope) });
|
|
1858
|
-
switch (node.name) {
|
|
1859
|
-
case "exp":
|
|
1860
|
-
return { ok: true, value: divideBySlope(chunkHIQ5HSZL_cjs.callNode("exp", [inner])) };
|
|
1861
|
-
case "sin":
|
|
1862
|
-
return { ok: true, value: divideBySlope({ kind: "neg", operand: chunkHIQ5HSZL_cjs.callNode("cos", [inner]) }) };
|
|
1863
|
-
case "cos":
|
|
1864
|
-
return { ok: true, value: divideBySlope(chunkHIQ5HSZL_cjs.callNode("sin", [inner])) };
|
|
1865
|
-
case "log":
|
|
1866
|
-
return {
|
|
1867
|
-
ok: true,
|
|
1868
|
-
value: divideBySlope({
|
|
1869
|
-
kind: "sub",
|
|
1870
|
-
left: { kind: "mul", left: inner, right: chunkHIQ5HSZL_cjs.callNode("log", [inner]) },
|
|
1871
|
-
right: inner
|
|
1872
|
-
})
|
|
1873
|
-
};
|
|
1874
|
-
default:
|
|
1875
|
-
return null;
|
|
1876
|
-
}
|
|
1877
|
-
}
|
|
1878
|
-
function integrateReciprocalForms(node, variable) {
|
|
1879
|
-
if (node.kind !== "div") return null;
|
|
1880
|
-
if (node.left.kind !== "const" || !isRationalOneNode(node.left.value)) return null;
|
|
1881
|
-
const linear = asLinear(node.right, variable);
|
|
1882
|
-
if (linear !== null) {
|
|
1883
|
-
return {
|
|
1884
|
-
ok: true,
|
|
1885
|
-
value: chunkHIQ5HSZL_cjs.simplifySymbolic({
|
|
1886
|
-
kind: "div",
|
|
1887
|
-
left: chunkHIQ5HSZL_cjs.callNode("log", [node.right]),
|
|
1888
|
-
right: chunkHIQ5HSZL_cjs.constNode(linear.slope)
|
|
1889
|
-
})
|
|
1890
|
-
};
|
|
1891
|
-
}
|
|
1892
|
-
const denominator = chunkHIQ5HSZL_cjs.toPolynomial(node.right);
|
|
1893
|
-
if (denominator !== null && denominator.vars.length === 1 && denominator.vars[0] === variable) {
|
|
1894
|
-
const ascending = chunkHIQ5HSZL_cjs.polyCoefficients(denominator, variable);
|
|
1895
|
-
const isOnePlusSquare = ascending.length === 3 && isRationalOneNode(ascending[0]) && chunkHIQ5HSZL_cjs.isRationalZero(ascending[1]) && isRationalOneNode(ascending[2]);
|
|
1896
|
-
if (isOnePlusSquare) return { ok: true, value: chunkHIQ5HSZL_cjs.callNode("atan", [chunkHIQ5HSZL_cjs.varNode(variable)]) };
|
|
1897
|
-
}
|
|
1898
|
-
return null;
|
|
1899
|
-
}
|
|
1900
|
-
function isRationalOneNode(value) {
|
|
1901
|
-
return value.n === 1n && value.d === 1n;
|
|
1902
|
-
}
|
|
1903
|
-
function integrateRationalFunction(node, variable) {
|
|
1904
|
-
const parts = asRationalFunction(node);
|
|
1905
|
-
if (parts === null || parts.variable !== variable) return null;
|
|
1906
|
-
const decomposition = partialFractions(parts.numerator, parts.denominator, variable);
|
|
1907
|
-
if (decomposition === null) return null;
|
|
1908
|
-
let result = decomposition.polynomial.length > 0 ? polynomialAntiderivative(decomposition.polynomial, variable) : chunkHIQ5HSZL_cjs.constNode(0);
|
|
1909
|
-
for (const term of decomposition.terms) {
|
|
1910
|
-
const piece = integrateTerm(term, variable);
|
|
1911
|
-
if (piece === null) {
|
|
1912
|
-
return {
|
|
1913
|
-
ok: false,
|
|
1914
|
-
reason: "its denominator has a repeated irreducible quadratic factor, which needs a reduction formula this does not have"
|
|
1915
|
-
};
|
|
1916
|
-
}
|
|
1917
|
-
result = { kind: "add", left: result, right: piece };
|
|
1918
|
-
}
|
|
1919
|
-
return { ok: true, value: chunkHIQ5HSZL_cjs.simplifySymbolic(result) };
|
|
1920
|
-
}
|
|
1921
|
-
function integrateTerm(term, variable) {
|
|
1922
|
-
const baseDegree = term.base.length - 1;
|
|
1923
|
-
const base = coefficientsToNode2(term.base, variable);
|
|
1924
|
-
if (baseDegree === 1) {
|
|
1925
|
-
const coefficient = term.numerator[0] ?? chunkHIQ5HSZL_cjs.RATIONAL_ZERO;
|
|
1926
|
-
if (term.power === 1) {
|
|
1927
|
-
return { kind: "mul", left: chunkHIQ5HSZL_cjs.constNode(coefficient), right: chunkHIQ5HSZL_cjs.callNode("log", [base]) };
|
|
1928
|
-
}
|
|
1929
|
-
const reduced = term.power - 1;
|
|
1930
|
-
const scaled = chunkHIQ5HSZL_cjs.rationalDiv(coefficient, { n: BigInt(-reduced), d: 1n });
|
|
1931
|
-
return {
|
|
1932
|
-
kind: "div",
|
|
1933
|
-
left: chunkHIQ5HSZL_cjs.constNode(scaled),
|
|
1934
|
-
right: chunkHIQ5HSZL_cjs.powNode(base, chunkHIQ5HSZL_cjs.constNode({ n: BigInt(reduced), d: 1n }))
|
|
1935
|
-
};
|
|
1936
|
-
}
|
|
1937
|
-
if (baseDegree !== 2 || term.power !== 1) return null;
|
|
1938
|
-
return integrateQuadraticTerm(term, variable, base);
|
|
1939
|
-
}
|
|
1940
|
-
function integrateQuadraticTerm(term, variable, base) {
|
|
1941
|
-
const constant = term.numerator[0] ?? chunkHIQ5HSZL_cjs.RATIONAL_ZERO;
|
|
1942
|
-
const linear = term.numerator[1] ?? chunkHIQ5HSZL_cjs.RATIONAL_ZERO;
|
|
1943
|
-
const [q, p] = term.base;
|
|
1944
|
-
const half = { n: 1n, d: 2n };
|
|
1945
|
-
const halfP = chunkHIQ5HSZL_cjs.rationalMul(p, half);
|
|
1946
|
-
const logarithm = {
|
|
1947
|
-
kind: "mul",
|
|
1948
|
-
left: chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.rationalMul(linear, half)),
|
|
1949
|
-
right: chunkHIQ5HSZL_cjs.callNode("log", [base])
|
|
1950
|
-
};
|
|
1951
|
-
const leftover = chunkHIQ5HSZL_cjs.rationalSub(constant, chunkHIQ5HSZL_cjs.rationalMul(linear, halfP));
|
|
1952
|
-
if (chunkHIQ5HSZL_cjs.isRationalZero(leftover)) return logarithm;
|
|
1953
|
-
const width = chunkHIQ5HSZL_cjs.surdNode(chunkHIQ5HSZL_cjs.rationalSub(q, chunkHIQ5HSZL_cjs.rationalMul(halfP, halfP)));
|
|
1954
|
-
const shifted = {
|
|
1955
|
-
kind: "add",
|
|
1956
|
-
left: chunkHIQ5HSZL_cjs.varNode(variable),
|
|
1957
|
-
right: chunkHIQ5HSZL_cjs.constNode(halfP)
|
|
1958
|
-
};
|
|
1959
|
-
const arctangent = {
|
|
1960
|
-
kind: "mul",
|
|
1961
|
-
left: { kind: "div", left: chunkHIQ5HSZL_cjs.constNode(leftover), right: width },
|
|
1962
|
-
right: chunkHIQ5HSZL_cjs.callNode("atan", [{ kind: "div", left: shifted, right: width }])
|
|
1963
|
-
};
|
|
1964
|
-
return chunkHIQ5HSZL_cjs.isRationalZero(linear) ? arctangent : { kind: "add", left: logarithm, right: arctangent };
|
|
1965
|
-
}
|
|
1966
|
-
function polynomialAntiderivative(ascending, variable) {
|
|
1967
|
-
let result = chunkHIQ5HSZL_cjs.constNode(0);
|
|
1968
|
-
ascending.forEach((coeff, exponent) => {
|
|
1969
|
-
if (chunkHIQ5HSZL_cjs.isRationalZero(coeff)) return;
|
|
1970
|
-
const nextPower = exponent + 1;
|
|
1971
|
-
const scaled = chunkHIQ5HSZL_cjs.rationalDiv(coeff, { n: BigInt(nextPower), d: 1n });
|
|
1972
|
-
const term = {
|
|
1973
|
-
kind: "mul",
|
|
1974
|
-
left: chunkHIQ5HSZL_cjs.constNode(scaled),
|
|
1975
|
-
right: nextPower === 1 ? chunkHIQ5HSZL_cjs.varNode(variable) : chunkHIQ5HSZL_cjs.powNode(chunkHIQ5HSZL_cjs.varNode(variable), chunkHIQ5HSZL_cjs.constNode(nextPower))
|
|
1976
|
-
};
|
|
1977
|
-
result = { kind: "add", left: result, right: term };
|
|
1978
|
-
});
|
|
1979
|
-
return result;
|
|
1980
|
-
}
|
|
1981
|
-
function integrate(node, variable) {
|
|
1982
|
-
const simplified = chunkHIQ5HSZL_cjs.simplifySymbolic(node);
|
|
1983
|
-
if (!chunkHIQ5HSZL_cjs.freeVariables(simplified).has(variable)) {
|
|
1984
|
-
return { ok: true, value: chunkHIQ5HSZL_cjs.simplifySymbolic({ kind: "mul", left: simplified, right: chunkHIQ5HSZL_cjs.varNode(variable) }) };
|
|
1985
|
-
}
|
|
1986
|
-
const polynomial = integratePolynomial(simplified, variable);
|
|
1987
|
-
if (polynomial !== null) return polynomial;
|
|
1988
|
-
const standard = integrateStandardForm(simplified, variable);
|
|
1989
|
-
if (standard !== null) return standard;
|
|
1990
|
-
const reciprocal = integrateReciprocalForms(simplified, variable);
|
|
1991
|
-
if (reciprocal !== null) return reciprocal;
|
|
1992
|
-
const rationalFunction = integrateRationalFunction(simplified, variable);
|
|
1993
|
-
if (rationalFunction !== null) return rationalFunction;
|
|
1994
|
-
if (simplified.kind === "add" || simplified.kind === "sub") {
|
|
1995
|
-
const left = integrate(simplified.left, variable);
|
|
1996
|
-
if (!left.ok) return left;
|
|
1997
|
-
const right = integrate(simplified.right, variable);
|
|
1998
|
-
if (!right.ok) return right;
|
|
1999
|
-
return {
|
|
2000
|
-
ok: true,
|
|
2001
|
-
value: chunkHIQ5HSZL_cjs.simplifySymbolic({ kind: simplified.kind, left: left.value, right: right.value })
|
|
2002
|
-
};
|
|
2003
|
-
}
|
|
2004
|
-
if (simplified.kind === "mul" && simplified.left.kind === "const") {
|
|
2005
|
-
const inner = integrate(simplified.right, variable);
|
|
2006
|
-
if (!inner.ok) return inner;
|
|
2007
|
-
return { ok: true, value: chunkHIQ5HSZL_cjs.simplifySymbolic({ kind: "mul", left: simplified.left, right: inner.value }) };
|
|
2008
|
-
}
|
|
2009
|
-
return {
|
|
2010
|
-
ok: false,
|
|
2011
|
-
reason: "no elementary antiderivative is known for this expression"
|
|
2012
|
-
};
|
|
2013
|
-
}
|
|
2014
|
-
|
|
2015
|
-
// src/symbolic/Taylor.ts
|
|
2016
|
-
var TAYLOR_MAX_DEGREE = 16;
|
|
2017
|
-
function taylorSeries(node, variable, point, degree) {
|
|
2018
|
-
if (degree < 0 || !Number.isInteger(degree) || degree > TAYLOR_MAX_DEGREE) {
|
|
2019
|
-
throw chunkB4HBEFTB_cjs.ErrorFactory.execution(
|
|
2020
|
-
"SYMBOLIC_TAYLOR_DEGREE_LIMIT",
|
|
2021
|
-
`A Taylor degree must be a whole number from 0 to ${TAYLOR_MAX_DEGREE}.`,
|
|
2022
|
-
{ limit: TAYLOR_MAX_DEGREE }
|
|
2023
|
-
);
|
|
2024
|
-
}
|
|
2025
|
-
const pointNode = chunkHIQ5HSZL_cjs.constNode(point);
|
|
2026
|
-
let factorial = 1n;
|
|
2027
|
-
let result = chunkHIQ5HSZL_cjs.constNode(chunkHIQ5HSZL_cjs.RATIONAL_ZERO);
|
|
2028
|
-
for (let order = 0; order <= degree; order++) {
|
|
2029
|
-
if (order > 0) factorial *= BigInt(order);
|
|
2030
|
-
const derivative = differentiate2(node, variable, order);
|
|
2031
|
-
const atPoint = chunkHIQ5HSZL_cjs.simplifySymbolic(chunkHIQ5HSZL_cjs.substitute(derivative, variable, pointNode));
|
|
2032
|
-
if (atPoint.kind !== "const") {
|
|
2033
|
-
throw chunkB4HBEFTB_cjs.ErrorFactory.execution(
|
|
2034
|
-
"SYMBOLIC_TAYLOR_INEXACT",
|
|
2035
|
-
`The derivative of order ${order} does not reduce to an exact number at the expansion point, so this series cannot be computed exactly.`,
|
|
2036
|
-
{ order }
|
|
2037
|
-
);
|
|
2038
|
-
}
|
|
2039
|
-
const coefficient = chunkHIQ5HSZL_cjs.rationalDiv(atPoint.value, { n: factorial, d: 1n });
|
|
2040
|
-
if (chunkHIQ5HSZL_cjs.isRationalZero(coefficient)) continue;
|
|
2041
|
-
const shifted = chunkHIQ5HSZL_cjs.isRationalZero(point) ? chunkHIQ5HSZL_cjs.varNode(variable) : { kind: "sub", left: chunkHIQ5HSZL_cjs.varNode(variable), right: pointNode };
|
|
2042
|
-
const power3 = order === 0 ? chunkHIQ5HSZL_cjs.constNode(1) : order === 1 ? shifted : chunkHIQ5HSZL_cjs.powNode(shifted, chunkHIQ5HSZL_cjs.constNode(order));
|
|
2043
|
-
result = { kind: "add", left: result, right: { kind: "mul", left: chunkHIQ5HSZL_cjs.constNode(coefficient), right: power3 } };
|
|
2044
|
-
}
|
|
2045
|
-
return chunkHIQ5HSZL_cjs.simplifySymbolic(result);
|
|
2046
|
-
}
|
|
2047
|
-
function jacobian(functions, variables) {
|
|
2048
|
-
return functions.map((fn) => variables.map((variable) => differentiate2(fn, variable)));
|
|
2049
|
-
}
|
|
2050
|
-
|
|
2051
|
-
// src/engine/EngineContext.ts
|
|
2052
|
-
function createEngineContext() {
|
|
2053
|
-
return {
|
|
2054
|
-
pluginFunctions: {},
|
|
2055
|
-
opRegistry: new OpRegistry(),
|
|
2056
|
-
variableResolver: new chunkFEAIOR7N_cjs.VariableResolver(),
|
|
2057
|
-
pluginFunctionOwners: {}
|
|
2058
|
-
};
|
|
2059
|
-
}
|
|
2060
|
-
var defaultEngineContext = createEngineContext();
|
|
2061
|
-
|
|
2062
|
-
// src/packages/finance/data/CpiTable.ts
|
|
2063
|
-
var CPI_TABLE = {
|
|
2064
|
-
1970: 38.8,
|
|
2065
|
-
1971: 40.5,
|
|
2066
|
-
1972: 41.8,
|
|
2067
|
-
1973: 44.4,
|
|
2068
|
-
1974: 49.3,
|
|
2069
|
-
1975: 53.8,
|
|
2070
|
-
1976: 56.9,
|
|
2071
|
-
1977: 60.6,
|
|
2072
|
-
1978: 65.2,
|
|
2073
|
-
1979: 72.6,
|
|
2074
|
-
1980: 82.4,
|
|
2075
|
-
1981: 90.9,
|
|
2076
|
-
1982: 96.5,
|
|
2077
|
-
1983: 99.6,
|
|
2078
|
-
1984: 103.9,
|
|
2079
|
-
1985: 107.6,
|
|
2080
|
-
1986: 109.6,
|
|
2081
|
-
1987: 113.6,
|
|
2082
|
-
1988: 118.3,
|
|
2083
|
-
1989: 124,
|
|
2084
|
-
1990: 130.7,
|
|
2085
|
-
1991: 136.2,
|
|
2086
|
-
1992: 140.3,
|
|
2087
|
-
1993: 144.5,
|
|
2088
|
-
1994: 148.2,
|
|
2089
|
-
1995: 152.4,
|
|
2090
|
-
1996: 156.9,
|
|
2091
|
-
1997: 160.5,
|
|
2092
|
-
1998: 163,
|
|
2093
|
-
1999: 166.6,
|
|
2094
|
-
2e3: 172.2,
|
|
2095
|
-
2001: 177.1,
|
|
2096
|
-
2002: 179.9,
|
|
2097
|
-
2003: 184,
|
|
2098
|
-
2004: 188.9,
|
|
2099
|
-
2005: 195.3,
|
|
2100
|
-
2006: 201.6,
|
|
2101
|
-
2007: 207.3,
|
|
2102
|
-
2008: 215.3,
|
|
2103
|
-
2009: 214.5,
|
|
2104
|
-
2010: 218.1,
|
|
2105
|
-
2011: 224.9,
|
|
2106
|
-
2012: 229.6,
|
|
2107
|
-
2013: 233,
|
|
2108
|
-
2014: 236.7,
|
|
2109
|
-
2015: 237,
|
|
2110
|
-
2016: 240,
|
|
2111
|
-
2017: 245.1,
|
|
2112
|
-
2018: 251.1,
|
|
2113
|
-
2019: 255.7,
|
|
2114
|
-
2020: 258.8,
|
|
2115
|
-
2021: 271,
|
|
2116
|
-
2022: 292.7,
|
|
2117
|
-
2023: 304.7,
|
|
2118
|
-
2024: 313.7,
|
|
2119
|
-
// 2025-2026 were projected from model knowledge and are now derived from
|
|
2120
|
-
// the IMF monthly CPI series (statisticsoftheworld.com,
|
|
2121
|
-
// IMF.CPI.YOY.M?geo=USA), chained forward from the published 2024 figure
|
|
2122
|
-
// using annual mean year-over-year rates. 2026 covers January to June only,
|
|
2123
|
-
// so it remains a partial year and will move.
|
|
2124
|
-
//
|
|
2125
|
-
// The projections were 320.6 and 327.4, low by 0.49% and 1.63%. Everything
|
|
2126
|
-
// from 2021 to 2024 reproduced the same series to within 0.02%, which is
|
|
2127
|
-
// what makes those two the only entries worth changing.
|
|
2128
|
-
2025: 322.2,
|
|
2129
|
-
2026: 332.7
|
|
2130
|
-
};
|
|
2131
|
-
var CPI_MIN_YEAR = 1970;
|
|
2132
|
-
var CPI_MAX_YEAR = 2026;
|
|
2133
|
-
function getCpi(year) {
|
|
2134
|
-
return CPI_TABLE[Math.trunc(year)];
|
|
2135
|
-
}
|
|
2136
|
-
function inflationRatio(fromYear, toYear) {
|
|
2137
|
-
const fromCpi = getCpi(fromYear);
|
|
2138
|
-
const toCpi = getCpi(toYear);
|
|
2139
|
-
if (fromCpi === void 0 || toCpi === void 0 || fromCpi === 0) return void 0;
|
|
2140
|
-
return toCpi / fromCpi;
|
|
2141
|
-
}
|
|
2142
|
-
function adjustForInflation(amount, fromYear, toYear) {
|
|
2143
|
-
const ratio = inflationRatio(fromYear, toYear);
|
|
2144
|
-
if (ratio === void 0) return void 0;
|
|
2145
|
-
return amount * ratio;
|
|
2146
|
-
}
|
|
2147
|
-
|
|
2148
|
-
// src/vm/VMBuiltins.ts
|
|
2149
|
-
var ANGLE_KIND = 0;
|
|
2150
|
-
function angleInRadians(value) {
|
|
2151
|
-
if (value.type === 6 /* Uom */ && value.unit !== void 0) {
|
|
2152
|
-
const entry = chunkAMOJYLG2_cjs.UNIT_TABLE[value.unit.toLowerCase()];
|
|
2153
|
-
if (entry !== void 0 && entry[0] === ANGLE_KIND) return value.toNumber() * entry[1];
|
|
2154
|
-
}
|
|
2155
|
-
return value.toNumber();
|
|
2156
|
-
}
|
|
2157
|
-
function pluraliseUnit(unit, count) {
|
|
2158
|
-
if (count === 1) return unit;
|
|
2159
|
-
const plural = `${unit}s`;
|
|
2160
|
-
return chunkAMOJYLG2_cjs.UNIT_TABLE[plural.toLowerCase()] === void 0 ? unit : plural;
|
|
2161
|
-
}
|
|
2162
|
-
function extremum(args, wantLargest) {
|
|
2163
|
-
let best;
|
|
2164
|
-
let hasNaN = false;
|
|
2165
|
-
for (const a of args) {
|
|
2166
|
-
if (Number.isNaN(a.toNumber())) {
|
|
2167
|
-
hasNaN = true;
|
|
2168
|
-
continue;
|
|
2169
|
-
}
|
|
2170
|
-
if (best === void 0) {
|
|
2171
|
-
best = a;
|
|
2172
|
-
continue;
|
|
2173
|
-
}
|
|
2174
|
-
const { lv, rv, sameMeasure } = unifyUom(best, a);
|
|
2175
|
-
if (!sameMeasure) {
|
|
2176
|
-
const bestUnit = best.type === 6 /* Uom */ ? best.unit : void 0;
|
|
2177
|
-
const otherUnit = a.type === 6 /* Uom */ ? a.unit : void 0;
|
|
2178
|
-
const named = describeMeasureMismatch(bestUnit, otherUnit, "compared");
|
|
2179
|
-
return chunk2TZKENDH_cjs.errorValue(
|
|
2180
|
-
"INCOMPATIBLE_UNITS",
|
|
2181
|
-
named ?? `Cannot compare incompatible units: ${bestUnit ?? "?"} and ${otherUnit ?? "?"}`
|
|
2182
|
-
);
|
|
2183
|
-
}
|
|
2184
|
-
if (wantLargest ? rv > lv : rv < lv) best = a;
|
|
2185
|
-
}
|
|
2186
|
-
if (hasNaN) return chunk2TZKENDH_cjs.numberValue(NaN);
|
|
2187
|
-
if (best === void 0) return chunk2TZKENDH_cjs.numberValue(wantLargest ? -Infinity : Infinity);
|
|
2188
|
-
return best.type === 6 /* Uom */ ? best : chunk2TZKENDH_cjs.numberValue(best.toNumber());
|
|
2189
|
-
}
|
|
2190
|
-
function keepUnit(operand, magnitude2) {
|
|
2191
|
-
if (operand.type === 6 /* Uom */ && operand.unit !== void 0) return chunk2TZKENDH_cjs.uomValue(magnitude2, operand.unit);
|
|
2192
|
-
return chunk2TZKENDH_cjs.numberValue(magnitude2);
|
|
2193
|
-
}
|
|
2194
|
-
function roundToPlaces(source, places) {
|
|
2195
|
-
const p = Number.isFinite(places) ? Math.min(100, Math.max(0, Math.trunc(places))) : 0;
|
|
2196
|
-
if (source.exact !== void 0) {
|
|
2197
|
-
const rounded = chunkHIQ5HSZL_cjs.decimalRound(source.exact, p);
|
|
2198
|
-
return withPlaces(source, chunkHIQ5HSZL_cjs.decimalToNumber(rounded), p, rounded);
|
|
2199
|
-
}
|
|
2200
|
-
const value = source.toNumber();
|
|
2201
|
-
if (!Number.isFinite(value)) return withPlaces(source, value, p);
|
|
2202
|
-
const scale2 = Math.pow(10, p);
|
|
2203
|
-
const scaled = value * scale2;
|
|
2204
|
-
if (!Number.isFinite(scaled) || Math.abs(scaled) > Number.MAX_SAFE_INTEGER) return withPlaces(source, value, p);
|
|
2205
|
-
return withPlaces(source, Math.round(scaled) / scale2, p);
|
|
2206
|
-
}
|
|
2207
|
-
function withPlaces(source, magnitude2, places, exact) {
|
|
2208
|
-
const result = source.type === 6 /* Uom */ && source.unit !== void 0 ? chunk2TZKENDH_cjs.uomValue(magnitude2, source.unit) : chunk2TZKENDH_cjs.numberValue(magnitude2);
|
|
2209
|
-
result.decimalPlaces = places;
|
|
2210
|
-
if (exact !== void 0) result.exact = exact;
|
|
2211
|
-
return result;
|
|
2212
|
-
}
|
|
2213
|
-
function nonFiniteEuclidOperand(a, b, name) {
|
|
2214
|
-
if (Number.isFinite(a) && Number.isFinite(b)) return null;
|
|
2215
|
-
const culprit = Number.isFinite(a) ? b : a;
|
|
2216
|
-
return chunk2TZKENDH_cjs.errorValue(
|
|
2217
|
-
"INVALID_INTEGER_OPERAND",
|
|
2218
|
-
`${name} needs two whole numbers, and ${Number.isNaN(culprit) ? "one of them has no value" : "one of them is infinite"}`
|
|
2219
|
-
);
|
|
2220
|
-
}
|
|
2221
|
-
function euclidGcd(a, b) {
|
|
2222
|
-
let x = a;
|
|
2223
|
-
let y = b;
|
|
2224
|
-
while (y !== 0) {
|
|
2225
|
-
const t = y;
|
|
2226
|
-
y = x % y;
|
|
2227
|
-
x = t;
|
|
2228
|
-
}
|
|
2229
|
-
return x;
|
|
2230
|
-
}
|
|
2231
|
-
var builtinFunctions = {
|
|
2232
|
-
// ── Populated below ──
|
|
2233
|
-
// sqrt: a negative argument has a complex answer now that there is a complex
|
|
2234
|
-
// number to give, so this no longer quietly returns NaN. The exact path runs
|
|
2235
|
-
// first, so sqrt(-4) is 2i rather than an approximation.
|
|
2236
|
-
0: (args) => {
|
|
2237
|
-
const value = args[0].toNumber();
|
|
2238
|
-
if (value >= 0) return chunk2TZKENDH_cjs.numberValue(Math.sqrt(value));
|
|
2239
|
-
return symbolicToValue(chunkHIQ5HSZL_cjs.callNode("sqrt", [chunkHIQ5HSZL_cjs.constNode(value)]));
|
|
2240
|
-
},
|
|
2241
|
-
// abs(a): for a Matrix, "|a|" (Calca's determinant-pipe notation) is a
|
|
2242
|
-
// valid alias for det(a) (index 64), reusing the SAME implementation
|
|
2243
|
-
// not a separate one. Plain-number abs is unaffected.
|
|
2244
|
-
1: (args) => args[0].type === 7 /* Matrix */ ? chunkHIQ5HSZL_cjs.determinant(args[0].value) : keepUnit(args[0], Math.abs(args[0].toNumber())),
|
|
2245
|
-
// sin/cos/tan accept an angle with a unit; see angleInRadians().
|
|
2246
|
-
2: (args) => chunk2TZKENDH_cjs.numberValue(Math.sin(angleInRadians(args[0]))),
|
|
2247
|
-
3: (args) => chunk2TZKENDH_cjs.numberValue(Math.cos(angleInRadians(args[0]))),
|
|
2248
|
-
4: (args) => chunk2TZKENDH_cjs.numberValue(Math.tan(angleInRadians(args[0]))),
|
|
2249
|
-
5: (args) => chunk2TZKENDH_cjs.numberValue(Math.log(args[0].toNumber())),
|
|
2250
|
-
// round/ceil/floor keep a unit for the same reason abs does; see keepUnit().
|
|
2251
|
-
6: (args) => keepUnit(args[0], Math.ceil(args[0].toNumber())),
|
|
2252
|
-
7: (args) => keepUnit(args[0], Math.floor(args[0].toNumber())),
|
|
2253
|
-
8: (args) => args.length >= 2 ? (
|
|
2254
|
-
// round(x, n): round to n decimal places and display at that precision.
|
|
2255
|
-
roundToPlaces(args[0], args[1].toNumber())
|
|
2256
|
-
) : (
|
|
2257
|
-
// round(x): nearest whole number, the way it always was.
|
|
2258
|
-
keepUnit(args[0], Math.round(args[0].toNumber()))
|
|
2259
|
-
),
|
|
2260
|
-
// min/max: see extremum() for why the winner is carried around as a Value
|
|
2261
|
-
// rather than as a running number.
|
|
2262
|
-
9: (args) => extremum(args, false),
|
|
2263
|
-
10: (args) => extremum(args, true),
|
|
2264
|
-
11: (args) => chunk2TZKENDH_cjs.numberValue(Math.asin(args[0].toNumber())),
|
|
2265
|
-
12: (args) => chunk2TZKENDH_cjs.numberValue(Math.acos(args[0].toNumber())),
|
|
2266
|
-
13: (args) => chunk2TZKENDH_cjs.numberValue(Math.atan(args[0].toNumber())),
|
|
2267
|
-
14: (args) => chunk2TZKENDH_cjs.numberValue(Math.atan2(args[0].toNumber(), args[1].toNumber())),
|
|
2268
|
-
15: (args) => chunk2TZKENDH_cjs.numberValue(Math.sinh(args[0].toNumber())),
|
|
2269
|
-
16: (args) => chunk2TZKENDH_cjs.numberValue(Math.cosh(args[0].toNumber())),
|
|
2270
|
-
17: (args) => chunk2TZKENDH_cjs.numberValue(Math.tanh(args[0].toNumber())),
|
|
2271
|
-
18: (args) => chunk2TZKENDH_cjs.numberValue(Math.asinh(args[0].toNumber())),
|
|
2272
|
-
19: (args) => chunk2TZKENDH_cjs.numberValue(Math.acosh(args[0].toNumber())),
|
|
2273
|
-
20: (args) => chunk2TZKENDH_cjs.numberValue(Math.atanh(args[0].toNumber())),
|
|
2274
|
-
21: (args) => chunk2TZKENDH_cjs.numberValue(Math.cbrt(args[0].toNumber())),
|
|
2275
|
-
22: (args) => chunk2TZKENDH_cjs.numberValue(Math.clz32(args[0].toNumber())),
|
|
2276
|
-
23: (args) => chunk2TZKENDH_cjs.numberValue(Math.expm1(args[0].toNumber())),
|
|
2277
|
-
24: (args) => chunk2TZKENDH_cjs.numberValue(Math.exp(args[0].toNumber())),
|
|
2278
|
-
25: (args) => chunk2TZKENDH_cjs.numberValue(Math.fround(args[0].toNumber())),
|
|
2279
|
-
// hypot: left as .map()+spread (unlike min/max above), Math.hypot uses
|
|
2280
|
-
// a numerically-stable scaling algorithm internally to avoid overflow
|
|
2281
|
-
// for very large/small inputs; a naive manual reimplementation risks
|
|
2282
|
-
// silently changing results at the extremes, so the tiny array
|
|
2283
|
-
// allocation here is the safer trade.
|
|
2284
|
-
26: (args) => chunk2TZKENDH_cjs.numberValue(Math.hypot(...args.map((a) => a.toNumber()))),
|
|
2285
|
-
27: (args) => chunk2TZKENDH_cjs.numberValue(Math.imul(args[0].toNumber(), args[1].toNumber())),
|
|
2286
|
-
28: (args) => chunk2TZKENDH_cjs.numberValue(Math.log10(args[0].toNumber())),
|
|
2287
|
-
29: (args) => chunk2TZKENDH_cjs.numberValue(Math.log1p(args[0].toNumber())),
|
|
2288
|
-
30: (args) => chunk2TZKENDH_cjs.numberValue(Math.log2(args[0].toNumber())),
|
|
2289
|
-
// pow(): the spelled-out form of `^`, so a Matrix base means the same
|
|
2290
|
-
// repeated matrix multiplication `^` means. Without this branch
|
|
2291
|
-
// `pow([1,2;3,4], 2)` was Math.pow of a value whose toNumber() is 0, and
|
|
2292
|
-
// came back as the number 0. See vm/MatrixOps.ts's matrixPower().
|
|
2293
|
-
31: (args) => {
|
|
2294
|
-
if (args[0].type === 7 /* Matrix */) {
|
|
2295
|
-
if (args[1].type !== 0 /* Number */) {
|
|
2296
|
-
return chunk2TZKENDH_cjs.errorValue("MATRIX_POWER_UNSUPPORTED", `pow: a matrix's exponent must be a whole number, as in "pow([1,2;3,4], 2)".`);
|
|
2297
|
-
}
|
|
2298
|
-
return chunkHIQ5HSZL_cjs.matrixPower(args[0].value, args[1].value);
|
|
2299
|
-
}
|
|
2300
|
-
if (args[1].type === 7 /* Matrix */) {
|
|
2301
|
-
return chunk2TZKENDH_cjs.errorValue("MATRIX_POWER_UNSUPPORTED", `pow: a matrix may only be the base, as in "pow([1,2;3,4], 2)".`);
|
|
2302
|
-
}
|
|
2303
|
-
return chunk2TZKENDH_cjs.numberValue(power(args[0].toNumber(), args[1].toNumber()));
|
|
2304
|
-
},
|
|
2305
|
-
32: () => chunk2TZKENDH_cjs.numberValue(Math.random()),
|
|
2306
|
-
// takes no arguments, unlike its neighbours
|
|
2307
|
-
33: (args) => chunk2TZKENDH_cjs.numberValue(Math.sign(args[0].toNumber())),
|
|
2308
|
-
34: (args) => chunk2TZKENDH_cjs.numberValue(Math.trunc(args[0].toNumber())),
|
|
2309
|
-
35: (args) => chunk2TZKENDH_cjs.numberValue(args[0].toNumber() * Math.PI / 180),
|
|
2310
|
-
36: (args) => chunk2TZKENDH_cjs.numberValue(args[0].toNumber() * 180 / Math.PI),
|
|
2311
|
-
// 37: diceRoll(from, to), random integer in range [from, to] inclusive.
|
|
2312
|
-
// A reversed range (from > to) used to silently produce values outside
|
|
2313
|
-
// [to, from] via a negative-length Math.random() spread (e.g.
|
|
2314
|
-
// "roll(6, 1)" returning values like 2-5, never 1 or 6) instead of
|
|
2315
|
-
// erroring on the invalid input.
|
|
2316
|
-
37: (args) => {
|
|
2317
|
-
const from = args[0].toNumber();
|
|
2318
|
-
const to = args[1].toNumber();
|
|
2319
|
-
if (from > to) {
|
|
2320
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `roll: invalid range, ${from} is greater than ${to}`);
|
|
2321
|
-
}
|
|
2322
|
-
return chunk2TZKENDH_cjs.numberValue(Math.floor(Math.random() * (to - from + 1)) + from);
|
|
2323
|
-
},
|
|
2324
|
-
// gcd(a, b), Euclidean algorithm. Negative inputs are treated by
|
|
2325
|
-
// magnitude (gcd is conventionally defined over non-negative integers).
|
|
2326
|
-
38: (args) => {
|
|
2327
|
-
const a = Math.trunc(Math.abs(args[0].toNumber()));
|
|
2328
|
-
const b = Math.trunc(Math.abs(args[1].toNumber()));
|
|
2329
|
-
const nonFinite = nonFiniteEuclidOperand(a, b, "gcd");
|
|
2330
|
-
if (nonFinite) return nonFinite;
|
|
2331
|
-
return chunk2TZKENDH_cjs.numberValue(euclidGcd(a, b));
|
|
2332
|
-
},
|
|
2333
|
-
// lcm(a, b) = |a*b| / gcd(a, b), via the same Euclidean gcd inline
|
|
2334
|
-
// (a standalone gcd() call site, no shared helper needed for two uses).
|
|
2335
|
-
39: (args) => {
|
|
2336
|
-
const a = Math.trunc(Math.abs(args[0].toNumber()));
|
|
2337
|
-
const b = Math.trunc(Math.abs(args[1].toNumber()));
|
|
2338
|
-
const nonFinite = nonFiniteEuclidOperand(a, b, "lcm");
|
|
2339
|
-
if (nonFinite) return nonFinite;
|
|
2340
|
-
if (a === 0 || b === 0) return chunk2TZKENDH_cjs.numberValue(0);
|
|
2341
|
-
return chunk2TZKENDH_cjs.numberValue(a / euclidGcd(a, b) * b);
|
|
2342
|
-
},
|
|
2343
|
-
// permutation(n, r) = n! / (n-r)!, computed as a running product
|
|
2344
|
-
// rather than two full factorials, so it stays exact for n well
|
|
2345
|
-
// beyond where n! itself would exceed Number.MAX_SAFE_INTEGER.
|
|
2346
|
-
//
|
|
2347
|
-
// The loop stops the moment the product stops being a representable
|
|
2348
|
-
// double, which is both the answer `fact` (index 62) already gives for
|
|
2349
|
-
// the same question and the thing that bounds the loop at all. `r` comes
|
|
2350
|
-
// straight off the stack: `permutation(1000000000000, 1000000000000)`
|
|
2351
|
-
// used to run a trillion iterations, of which the first ~170 computed
|
|
2352
|
-
// something and the rest multiplied Infinity by a number, and it had not
|
|
2353
|
-
// returned after thirty seconds. Every factor here is at least 1 and they
|
|
2354
|
-
// descend from `n`, so a product that is still finite after 170 steps
|
|
2355
|
-
// means the factors are small, which in turn means `r <= n` is small: the
|
|
2356
|
-
// early exit bounds the trip count without a separate estimate, and
|
|
2357
|
-
// without ever refusing a permutation that does have an answer.
|
|
2358
|
-
40: (args) => {
|
|
2359
|
-
const n = Math.trunc(args[0].toNumber());
|
|
2360
|
-
const r = Math.trunc(args[1].toNumber());
|
|
2361
|
-
if (n < 0 || r < 0 || r > n) {
|
|
2362
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `permutation: invalid n=${n}, r=${r} (require 0 <= r <= n)`);
|
|
2363
|
-
}
|
|
2364
|
-
let result = 1;
|
|
2365
|
-
for (let i = 0; i < r; i++) {
|
|
2366
|
-
result *= n - i;
|
|
2367
|
-
if (!Number.isFinite(result)) {
|
|
2368
|
-
return chunk2TZKENDH_cjs.errorValue(
|
|
2369
|
-
"PERMUTATION_OVERFLOW",
|
|
2370
|
-
`permutation: P(${n}, ${r}) exceeds the maximum representable double (it passed it after ${i + 1} of ${r} factors)`
|
|
2371
|
-
);
|
|
2372
|
-
}
|
|
2373
|
-
}
|
|
2374
|
-
return chunk2TZKENDH_cjs.numberValue(result);
|
|
2375
|
-
},
|
|
2376
|
-
// combination(n, r) = n! / (r! * (n-r)!), multiply-then-divide one
|
|
2377
|
-
// step at a time (standard technique) keeps every intermediate result
|
|
2378
|
-
// an integer, avoiding the overflow a naive factorial-ratio would hit.
|
|
2379
|
-
//
|
|
2380
|
-
// Same early exit, and needed for the same reason: `k = min(r, n-r)`
|
|
2381
|
-
// halves the trip count and bounds nothing, so `combination(1e12, 5e11)`
|
|
2382
|
-
// asked for five hundred billion iterations. The running value is C(n, i),
|
|
2383
|
-
// which grows monotonically to the middle, so once it is past what a
|
|
2384
|
-
// double can hold it never comes back, and the largest run this can now
|
|
2385
|
-
// take is the thousand-odd steps C(n, k) needs to cross that line.
|
|
2386
|
-
41: (args) => {
|
|
2387
|
-
const n = Math.trunc(args[0].toNumber());
|
|
2388
|
-
const r = Math.trunc(args[1].toNumber());
|
|
2389
|
-
if (n < 0 || r < 0 || r > n) {
|
|
2390
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `combination: invalid n=${n}, r=${r} (require 0 <= r <= n)`);
|
|
2391
|
-
}
|
|
2392
|
-
const k = Math.min(r, n - r);
|
|
2393
|
-
let result = 1;
|
|
2394
|
-
for (let i = 0; i < k; i++) {
|
|
2395
|
-
result = result * (n - i) / (i + 1);
|
|
2396
|
-
if (!Number.isFinite(result)) {
|
|
2397
|
-
return chunk2TZKENDH_cjs.errorValue(
|
|
2398
|
-
"COMBINATION_OVERFLOW",
|
|
2399
|
-
`combination: C(${n}, ${r}) exceeds the maximum representable double (it passed it after ${i + 1} of ${k} steps)`
|
|
2400
|
-
);
|
|
2401
|
-
}
|
|
2402
|
-
}
|
|
2403
|
-
return chunk2TZKENDH_cjs.numberValue(Math.round(result));
|
|
2404
|
-
},
|
|
2405
|
-
// average(...), arithmetic mean of any number of arguments. Backs the
|
|
2406
|
-
// MathPhrases package's "average of X, Y, Z" (packages/mathphrases/).
|
|
2407
|
-
42: (args) => {
|
|
2408
|
-
if (args.length === 0) return chunk2TZKENDH_cjs.numberValue(0);
|
|
2409
|
-
const sum = args.reduce((acc, a) => acc + a.toNumber(), 0);
|
|
2410
|
-
return chunk2TZKENDH_cjs.numberValue(sum / args.length);
|
|
2411
|
-
},
|
|
2412
|
-
// median(...), middle value; average of the two middle values for an
|
|
2413
|
-
// even argument count.
|
|
2414
|
-
43: (args) => {
|
|
2415
|
-
if (args.length === 0) return chunk2TZKENDH_cjs.numberValue(0);
|
|
2416
|
-
const sorted = args.map((a) => a.toNumber()).sort((a, b) => a - b);
|
|
2417
|
-
const mid = Math.floor(sorted.length / 2);
|
|
2418
|
-
return chunk2TZKENDH_cjs.numberValue(
|
|
2419
|
-
sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid]
|
|
2420
|
-
);
|
|
2421
|
-
},
|
|
2422
|
-
// total(...), sum of any number of arguments.
|
|
2423
|
-
44: (args) => chunk2TZKENDH_cjs.numberValue(args.reduce((acc, a) => acc + a.toNumber(), 0)),
|
|
2424
|
-
// count(...), number of arguments passed.
|
|
2425
|
-
45: (args) => chunk2TZKENDH_cjs.numberValue(args.length),
|
|
2426
|
-
// proportion(a, b, c) -> d such that a:b = c:d, i.e. d = c * (b/a)
|
|
2427
|
-
// "A is to B as C is to what". Unit-aware via unifyUom: "5 km is to
|
|
2428
|
-
// 500m as 5 cm is to what" unifies 5km/500m to a 10:1 ratio (500m ==
|
|
2429
|
-
// 0.5km), so 5cm at the same ratio -> 0.5cm. Falls back to plain
|
|
2430
|
-
// toNumber() ratios when the units aren't the same measure (unifyUom's
|
|
2431
|
-
// own fallback) rather than guessing at an unsupported conversion.
|
|
2432
|
-
46: (args) => {
|
|
2433
|
-
const [a, b, c] = args;
|
|
2434
|
-
const { lv: aNum, rv: bNum } = unifyUom(a, b);
|
|
2435
|
-
if (aNum === 0) {
|
|
2436
|
-
return chunk2TZKENDH_cjs.errorValue("PROPORTION_DIVIDE_BY_ZERO", `Cannot compute proportion: "${a.value}" is zero`);
|
|
2437
|
-
}
|
|
2438
|
-
const result = c.toNumber() * (bNum / aNum);
|
|
2439
|
-
return c.type === 6 /* Uom */ ? chunk2TZKENDH_cjs.uomValue(result, c.unit) : chunk2TZKENDH_cjs.numberValue(result);
|
|
2440
|
-
},
|
|
2441
|
-
// clamp(value, lo, hi), restrict value to [lo, hi]. Backs
|
|
2442
|
-
// "clamp X between Y and Z" / "clamp X from Y to Z".
|
|
2443
|
-
47: (args) => {
|
|
2444
|
-
const value = args[0].toNumber();
|
|
2445
|
-
const lo = args[1].toNumber();
|
|
2446
|
-
const hi = args[2].toNumber();
|
|
2447
|
-
if (lo > hi) {
|
|
2448
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `clamp: invalid range, ${lo} is greater than ${hi}`);
|
|
2449
|
-
}
|
|
2450
|
-
return chunk2TZKENDH_cjs.numberValue(Math.min(Math.max(value, lo), hi));
|
|
2451
|
-
},
|
|
2452
|
-
// hex(n), Python/JS-style call-syntax hex formatting, e.g. hex(255) ->
|
|
2453
|
-
// "0xFF". Distinct from the Converters package's `255 as hex` (see
|
|
2454
|
-
// packages/converters/parselets/AsConverterParselet.ts): "as hex"
|
|
2455
|
-
// produces a ValueType.Hex (a typed NUMBER that still participates in
|
|
2456
|
-
// arithmetic, formatted specially on display), while hex() is a plain
|
|
2457
|
-
// function call that returns an ordinary String value, matching
|
|
2458
|
-
// Python's hex()/JS convention of a function returning display text,
|
|
2459
|
-
// not a numeric type.
|
|
2460
|
-
48: (args) => chunk2TZKENDH_cjs.hexValue(args[0].toNumber()),
|
|
2461
|
-
// bin(n). Same call-syntax shape as hex() above, e.g. bin(10) -> "0b1010".
|
|
2462
|
-
49: (args) => chunk2TZKENDH_cjs.hexValue(args[0].toNumber(), "bin"),
|
|
2463
|
-
// int(x), coerce ANY value (Number, Percentage, Uom, String, Hex, ...)
|
|
2464
|
-
// to a plain integer Number, truncating any fractional part toward
|
|
2465
|
-
// zero (Math.trunc semantics: int(5.7) -> 5, int(-5.7) -> -5). Distinct
|
|
2466
|
-
// from the Converters package's `x as number` (TO_NUMBER opcode),
|
|
2467
|
-
// which only strips a unit/percentage wrapper and keeps any decimal
|
|
2468
|
-
// part (e.g. "5.7 as number" -> 5.7), int() additionally truncates.
|
|
2469
|
-
50: (args) => chunk2TZKENDH_cjs.numberValue(Math.trunc(args[0].toNumber())),
|
|
2470
|
-
// ── Finance (packages/finance/) ──────────────────────────────────────
|
|
2471
|
-
// All finance builtins preserve the principal/amount argument's Uom
|
|
2472
|
-
// unit (e.g. a currency like "$") onto the result, matching
|
|
2473
|
-
// ProportionParselet's convention (index 46, above), a plain-number
|
|
2474
|
-
// input produces a plain-number result.
|
|
2475
|
-
//
|
|
2476
|
-
// `rate` arguments are always a decimal fraction (e.g. 0.07 for 7%)
|
|
2477
|
-
// this is how "%" already normalizes everywhere else in this codebase
|
|
2478
|
-
// (see packages/percentage/parselets/PercentParselet.ts: "7%" divides
|
|
2479
|
-
// by 100 at parse time, producing a plain Number 0.07, not a distinct
|
|
2480
|
-
// percentage type). Writing "at 7" instead of "at 7%" in a phrase form
|
|
2481
|
-
// passes 7 as-is (not 0.07), the "%" is not implicit.
|
|
2482
|
-
// compoundFutureValue(principal, rate, years) -> FV = P*(1+r)^years.
|
|
2483
|
-
// Backs "compound interest on $P over Y years at R%" and the
|
|
2484
|
-
// compoundInterest(principal, rate, years) function-call form.
|
|
2485
|
-
51: (args) => {
|
|
2486
|
-
const principal = args[0].toNumber();
|
|
2487
|
-
const rate = args[1].toNumber();
|
|
2488
|
-
const years = args[2].toNumber();
|
|
2489
|
-
if (1 + rate <= 0) {
|
|
2490
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", `compoundInterest: rate ${rate} makes (1 + rate) non-positive`);
|
|
2491
|
-
}
|
|
2492
|
-
const fv = principal * Math.pow(1 + rate, years);
|
|
2493
|
-
return args[0].type === 6 /* Uom */ ? chunk2TZKENDH_cjs.uomValue(fv, args[0].unit) : chunk2TZKENDH_cjs.numberValue(fv);
|
|
2494
|
-
},
|
|
2495
|
-
// compoundInterestEarned(principal, rate, years) -> FV - principal, the
|
|
2496
|
-
// interest-only portion. Backs "interest on $P over Y years at R%" and
|
|
2497
|
-
// the interestEarned(principal, rate, years) function-call form.
|
|
2498
|
-
52: (args) => {
|
|
2499
|
-
const principal = args[0].toNumber();
|
|
2500
|
-
const rate = args[1].toNumber();
|
|
2501
|
-
const years = args[2].toNumber();
|
|
2502
|
-
if (1 + rate <= 0) {
|
|
2503
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", `interestEarned: rate ${rate} makes (1 + rate) non-positive`);
|
|
2504
|
-
}
|
|
2505
|
-
const interest = principal * (Math.pow(1 + rate, years) - 1);
|
|
2506
|
-
return args[0].type === 6 /* Uom */ ? chunk2TZKENDH_cjs.uomValue(interest, args[0].unit) : chunk2TZKENDH_cjs.numberValue(interest);
|
|
2507
|
-
},
|
|
2508
|
-
// compoundInterestRate(principal, futureValue, years) -> the rate (as a
|
|
2509
|
-
// decimal fraction) needed to grow principal to futureValue over years.
|
|
2510
|
-
// Function-call only, no clean phrase form for a reverse calculation
|
|
2511
|
-
// like this without inventing awkward new keywords, so it's scoped to
|
|
2512
|
-
// compoundInterestRate(...) rather than a natural-language phrase.
|
|
2513
|
-
53: (args) => {
|
|
2514
|
-
const principal = args[0].toNumber();
|
|
2515
|
-
const futureValue = args[1].toNumber();
|
|
2516
|
-
const years = args[2].toNumber();
|
|
2517
|
-
if (principal <= 0 || futureValue <= 0) {
|
|
2518
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `compoundInterestRate: principal and futureValue must both be positive`);
|
|
2519
|
-
}
|
|
2520
|
-
if (years <= 0) {
|
|
2521
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `compoundInterestRate: years must be greater than 0`);
|
|
2522
|
-
}
|
|
2523
|
-
return chunk2TZKENDH_cjs.numberValue(Math.pow(futureValue / principal, 1 / years) - 1);
|
|
2524
|
-
},
|
|
2525
|
-
// compoundInterestYears(principal, futureValue, rate) -> the number of
|
|
2526
|
-
// years needed to grow principal to futureValue at a fixed rate.
|
|
2527
|
-
// Function-call only, same reasoning as index 53 above.
|
|
2528
|
-
54: (args) => {
|
|
2529
|
-
const principal = args[0].toNumber();
|
|
2530
|
-
const futureValue = args[1].toNumber();
|
|
2531
|
-
const rate = args[2].toNumber();
|
|
2532
|
-
if (principal <= 0 || futureValue <= 0) {
|
|
2533
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `compoundInterestYears: principal and futureValue must both be positive`);
|
|
2534
|
-
}
|
|
2535
|
-
if (1 + rate <= 0 || rate === 0) {
|
|
2536
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", `compoundInterestYears: rate ${rate} is not usable (must be > -1 and not 0)`);
|
|
2537
|
-
}
|
|
2538
|
-
return chunk2TZKENDH_cjs.numberValue(Math.log(futureValue / principal) / Math.log(1 + rate));
|
|
2539
|
-
},
|
|
2540
|
-
// loanRepayment(principal, rate, years, periodsPerYear), standard
|
|
2541
|
-
// amortizing-loan repayment (mortgage formula), redistributed evenly
|
|
2542
|
-
// across `periodsPerYear` periods/year: 365=daily, 12=monthly, 1=annual,
|
|
2543
|
-
// 0=total over the life of the loan. The loan is ALWAYS amortized
|
|
2544
|
-
// monthly internally (the standard mortgage convention) regardless of
|
|
2545
|
-
// periodsPerYear, "daily"/"annual"/"total" are the same total
|
|
2546
|
-
// repayment redistributed, not separately-amortized loans. Verified
|
|
2547
|
-
// against real worked numbers (principal=$10,000, rate=6%, years=6):
|
|
2548
|
-
// monthly $165.73, annual $1,988.75 (== total/years exactly), daily
|
|
2549
|
-
// $5.45 (== total/(years*365)), total $11,932.48.
|
|
2550
|
-
// Backs "daily/monthly/annual/total repayment on $P over Y years at R%".
|
|
2551
|
-
55: (args) => {
|
|
2552
|
-
const principal = args[0].toNumber();
|
|
2553
|
-
const rate = args[1].toNumber();
|
|
2554
|
-
const years = args[2].toNumber();
|
|
2555
|
-
const periodsPerYear = args[3].toNumber();
|
|
2556
|
-
if (principal <= 0) return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `loanRepayment: principal must be positive`);
|
|
2557
|
-
if (years <= 0) return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `loanRepayment: years must be positive`);
|
|
2558
|
-
if (rate < 0) return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", `loanRepayment: rate must not be negative`);
|
|
2559
|
-
if (periodsPerYear < 0) return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `loanRepayment: periodsPerYear must not be negative`);
|
|
2560
|
-
const { totalRepayment } = amortizeLoan(principal, rate, years);
|
|
2561
|
-
const result = periodsPerYear === 0 ? totalRepayment : totalRepayment / (years * periodsPerYear);
|
|
2562
|
-
return args[0].type === 6 /* Uom */ ? chunk2TZKENDH_cjs.uomValue(result, args[0].unit) : chunk2TZKENDH_cjs.numberValue(result);
|
|
2563
|
-
},
|
|
2564
|
-
// loanInterest(principal, rate, years, periodsPerYear), the interest
|
|
2565
|
-
// portion of index 55's repayment, same periodsPerYear convention.
|
|
2566
|
-
// Backs "daily/monthly/annual/total interest on $P over Y years at R%".
|
|
2567
|
-
56: (args) => {
|
|
2568
|
-
const principal = args[0].toNumber();
|
|
2569
|
-
const rate = args[1].toNumber();
|
|
2570
|
-
const years = args[2].toNumber();
|
|
2571
|
-
const periodsPerYear = args[3].toNumber();
|
|
2572
|
-
if (principal <= 0) return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `loanInterest: principal must be positive`);
|
|
2573
|
-
if (years <= 0) return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `loanInterest: years must be positive`);
|
|
2574
|
-
if (rate < 0) return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", `loanInterest: rate must not be negative`);
|
|
2575
|
-
if (periodsPerYear < 0) return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `loanInterest: periodsPerYear must not be negative`);
|
|
2576
|
-
const { totalInterest } = amortizeLoan(principal, rate, years);
|
|
2577
|
-
const result = periodsPerYear === 0 ? totalInterest : totalInterest / (years * periodsPerYear);
|
|
2578
|
-
return args[0].type === 6 /* Uom */ ? chunk2TZKENDH_cjs.uomValue(result, args[0].unit) : chunk2TZKENDH_cjs.numberValue(result);
|
|
2579
|
-
},
|
|
2580
|
-
// monthlyPayment(principal, rate, years), convenience 3-arg wrapper
|
|
2581
|
-
// around index 55's monthly case, for direct function-call use without
|
|
2582
|
-
// the periodsPerYear parameter (the task's minimum-ask function form).
|
|
2583
|
-
57: (args) => {
|
|
2584
|
-
const principal = args[0].toNumber();
|
|
2585
|
-
const rate = args[1].toNumber();
|
|
2586
|
-
const years = args[2].toNumber();
|
|
2587
|
-
if (principal <= 0) return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `monthlyPayment: principal must be positive`);
|
|
2588
|
-
if (years <= 0) return chunk2TZKENDH_cjs.errorValue("INVALID_RANGE", `monthlyPayment: years must be positive`);
|
|
2589
|
-
if (rate < 0) return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", `monthlyPayment: rate must not be negative`);
|
|
2590
|
-
const { monthlyPayment } = amortizeLoan(principal, rate, years);
|
|
2591
|
-
return args[0].type === 6 /* Uom */ ? chunk2TZKENDH_cjs.uomValue(monthlyPayment, args[0].unit) : chunk2TZKENDH_cjs.numberValue(monthlyPayment);
|
|
2592
|
-
},
|
|
2593
|
-
// taxAdd(amount, rate) -> amount * (1 + rate), the tax-inclusive total.
|
|
2594
|
-
// Backs the taxAdd() function-call form, whose name promises exactly this.
|
|
2595
|
-
// The "tax on $X at R%" PHRASE does NOT use it, see index 86.
|
|
2596
|
-
//
|
|
2597
|
-
// No default rate is baked in anywhere, the caller always supplies one
|
|
2598
|
-
// explicitly, since tax rates vary by region and change over time; this
|
|
2599
|
-
// package makes no assumption about which rate applies.
|
|
2600
|
-
58: (args) => {
|
|
2601
|
-
const amount = args[0].toNumber();
|
|
2602
|
-
const rate = args[1].toNumber();
|
|
2603
|
-
if (args[0].type === 6 /* Uom */) return scaleMoneyByPercent(args[0], args[0].unit, rate, 1);
|
|
2604
|
-
return chunk2TZKENDH_cjs.numberValue(amount * (1 + rate));
|
|
2605
|
-
},
|
|
2606
|
-
// taxRemove(amount, rate) -> amount / (1 + rate), extracts the
|
|
2607
|
-
// pre-tax amount from a tax-INCLUSIVE total. Backs "tax off $X at R%" /
|
|
2608
|
-
// "VAT off $X at R%".
|
|
2609
|
-
59: (args) => {
|
|
2610
|
-
const amount = args[0].toNumber();
|
|
2611
|
-
const rate = args[1].toNumber();
|
|
2612
|
-
if (1 + rate <= 0) {
|
|
2613
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", `taxRemove: rate ${rate} makes (1 + rate) non-positive`);
|
|
2614
|
-
}
|
|
2615
|
-
if (args[0].type === 6 /* Uom */) {
|
|
2616
|
-
return removeTaxExact(args[0], args[0].unit, rate) ?? chunk2TZKENDH_cjs.uomValue(amount / (1 + rate), args[0].unit);
|
|
2617
|
-
}
|
|
2618
|
-
return chunk2TZKENDH_cjs.numberValue(amount / (1 + rate));
|
|
2619
|
-
},
|
|
2620
|
-
// inflationAdjust(amount, fromYear, toYear) -- CPI-based inflation
|
|
2621
|
-
// adjustment between two arbitrary years, using the bundled CPI-U
|
|
2622
|
-
// table (packages/finance/data/CpiTable.ts -- see its doc comment for
|
|
2623
|
-
// vintage/accuracy notes). Backs the function-call form
|
|
2624
|
-
// inflationAdjust(...) (FunctionCallParselet's builtinNameToIndex map)
|
|
2625
|
-
// and the "what is $X in fromYear worth in toYear" phrase form
|
|
2626
|
-
// (InflationQueryParselet.ts). The two present-year-relative phrase
|
|
2627
|
-
// forms ("what is $X from year" / "what was $X worth in year" / "$X
|
|
2628
|
-
// in year dollars") and the flat-rate future-value projection ("value
|
|
2629
|
-
// of $X in year assuming N% inflation") are collision-safe
|
|
2630
|
-
// pluginFunctions instead, not indices here -- see
|
|
2631
|
-
// packages/finance/parselets/InflationPluginFunctions.ts.
|
|
2632
|
-
60: (args) => {
|
|
2633
|
-
const amount = args[0].toNumber();
|
|
2634
|
-
const fromYear = args[1].toNumber();
|
|
2635
|
-
const toYear = args[2].toNumber();
|
|
2636
|
-
const ratio = inflationRatio(fromYear, toYear);
|
|
2637
|
-
if (ratio === void 0) {
|
|
2638
|
-
return chunk2TZKENDH_cjs.errorValue(
|
|
2639
|
-
"INFLATION_YEAR_OUT_OF_RANGE",
|
|
2640
|
-
`inflationAdjust: fromYear ${fromYear} or toYear ${toYear} is outside the bundled CPI table's range (${CPI_MIN_YEAR}-${CPI_MAX_YEAR})`
|
|
2641
|
-
);
|
|
2642
|
-
}
|
|
2643
|
-
const result = amount * ratio;
|
|
2644
|
-
return args[0].type === 6 /* Uom */ ? chunk2TZKENDH_cjs.uomValue(result, args[0].unit) : chunk2TZKENDH_cjs.numberValue(result);
|
|
2645
|
-
},
|
|
2646
|
-
// root(n, x) -- the n-th root of x (Numi's `root n (x)` phrasing maps
|
|
2647
|
-
// to this same call-style form; see FunctionCallParselet's name map).
|
|
2648
|
-
// No native Math.root exists (unlike Math.cbrt for n=3 specifically),
|
|
2649
|
-
// so this is Math.pow(x, 1/n) directly -- exact for n=2/n=3 modulo the
|
|
2650
|
-
// usual floating-point pow() rounding, same precision class as every
|
|
2651
|
-
// other builtin here.
|
|
2652
|
-
61: (args) => {
|
|
2653
|
-
const n = args[0].toNumber();
|
|
2654
|
-
const x = args[1].toNumber();
|
|
2655
|
-
return chunk2TZKENDH_cjs.numberValue(power(x, 1 / n));
|
|
2656
|
-
},
|
|
2657
|
-
// fact(n) / factorial(n) -- integer factorial. Deliberately rejects
|
|
2658
|
-
// negative or non-integer input (factorial isn't defined for either
|
|
2659
|
-
// without a gamma-function generalization this engine doesn't need) and
|
|
2660
|
-
// caps at 170 -- Number.MAX_VALUE overflows to Infinity at 171!, so
|
|
2661
|
-
// returning a silently-wrong (or silently-infinite) result past that
|
|
2662
|
-
// point would be worse than a clear error.
|
|
2663
|
-
62: (args) => {
|
|
2664
|
-
const n = args[0].toNumber();
|
|
2665
|
-
if (!Number.isInteger(n) || n < 0) {
|
|
2666
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_FACTORIAL_INPUT", `fact: ${n} is not a non-negative integer`);
|
|
2667
|
-
}
|
|
2668
|
-
if (n > 170) {
|
|
2669
|
-
return chunk2TZKENDH_cjs.errorValue("FACTORIAL_OVERFLOW", `fact: ${n}! exceeds the maximum representable double (170! is the largest finite factorial)`);
|
|
2670
|
-
}
|
|
2671
|
-
let result = 1;
|
|
2672
|
-
for (let i = 2; i <= n; i++) result *= i;
|
|
2673
|
-
return chunk2TZKENDH_cjs.numberValue(result);
|
|
2674
|
-
},
|
|
2675
|
-
// ── Matrix (packages/matrix/) ────────────────────────────────────────
|
|
2676
|
-
// transpose(a)/det(a)/inv(a)/dot(a,b), reachable both via ordinary
|
|
2677
|
-
// function-call syntax (this map) and via operator syntax (`^T`, `^-1`
|
|
2678
|
-
//. See PrecedenceParser.ts's CARET special-casing, which emits these
|
|
2679
|
-
// SAME indices) and `|a|` (abs()'s Matrix branch, index 1 above).
|
|
2680
|
-
// Real linear-algebra work lives in vm/MatrixOps.ts, shared by both
|
|
2681
|
-
// entry points rather than duplicated.
|
|
2682
|
-
// transpose(a), for a Matrix, swaps rows/cols. A plain Number is its
|
|
2683
|
-
// own transpose (a 1x1 "matrix" transposed is itself), matches this
|
|
2684
|
-
// engine's existing convention of treating a scalar as a trivial 1x1
|
|
2685
|
-
// matrix (see Value.ts's toNumber()/isNaN() 1x1 special case).
|
|
2686
|
-
63: (args) => args[0].type === 7 /* Matrix */ ? chunkHIQ5HSZL_cjs.transpose(args[0].value) : args[0],
|
|
2687
|
-
// det(a), determinant. A plain Number's "determinant" is itself (the
|
|
2688
|
-
// determinant of a 1x1 matrix [x] is x).
|
|
2689
|
-
64: (args) => args[0].type === 7 /* Matrix */ ? chunkHIQ5HSZL_cjs.determinant(args[0].value) : chunk2TZKENDH_cjs.numberValue(args[0].toNumber()),
|
|
2690
|
-
// inv(a), matrix inverse for a Matrix; for a plain Number, `1/x`
|
|
2691
|
-
// (byte-identical to `Math.pow(x, -1)`, which is what `x^-1` computed
|
|
2692
|
-
// before this feature existed. See PrecedenceParser.ts's `^-1`
|
|
2693
|
-
// special-case doc comment for why this must stay exact).
|
|
2694
|
-
65: (args) => {
|
|
2695
|
-
if (args[0].type === 7 /* Matrix */) return chunkHIQ5HSZL_cjs.inverse(args[0].value);
|
|
2696
|
-
return chunk2TZKENDH_cjs.numberValue(1 / args[0].toNumber());
|
|
2697
|
-
},
|
|
2698
|
-
// dot(a, b), matrix product / scalar-broadcast, the SAME dispatch as
|
|
2699
|
-
// the `*` operator between two matrices (vm/VM.ts's MUL case). Plain
|
|
2700
|
-
// Number operands multiply directly; a Number mixed with a Matrix
|
|
2701
|
-
// promotes the Number to a 1x1 Matrix first, so it broadcasts exactly
|
|
2702
|
-
// like matrixMultiply()'s own 1x1-scalar case.
|
|
2703
|
-
66: (args) => {
|
|
2704
|
-
const [a, b] = args;
|
|
2705
|
-
if (a.type === 0 /* Number */ && b.type === 0 /* Number */) {
|
|
2706
|
-
return chunk2TZKENDH_cjs.numberValue(a.toNumber() * b.toNumber());
|
|
2707
|
-
}
|
|
2708
|
-
const toMatrix = (v) => v.type === 7 /* Matrix */ ? v.value : { rows: 1, cols: 1, data: [v.toNumber()], hasSymbolic: false };
|
|
2709
|
-
return chunkHIQ5HSZL_cjs.matrixMultiply(toMatrix(a), toMatrix(b));
|
|
2710
|
-
},
|
|
2711
|
-
// ── Symbolic algebra (packages/symbolic/) ──
|
|
2712
|
-
// expand(expr), multiplying out every product and power. Reached only
|
|
2713
|
-
// through its own parselet, never the builtinNameToIndex name map, so that
|
|
2714
|
-
// `expand` keeps working as an ordinary variable name; see
|
|
2715
|
-
// packages/symbolic/normalizer/SymbolicCallNormalizerRule.ts.
|
|
2716
|
-
//
|
|
2717
|
-
// A non-symbolic argument has nothing to expand and is returned unchanged,
|
|
2718
|
-
// which is why this does not go through the CALL_BUILTIN symbolic dispatch:
|
|
2719
|
-
// `expand(2+3)` is simply 5.
|
|
2720
|
-
67: (args) => {
|
|
2721
|
-
const [value] = args;
|
|
2722
|
-
if (value.type !== 9 /* Symbolic */) return value;
|
|
2723
|
-
return symbolicToValue(chunkHIQ5HSZL_cjs.expandSymbolic(value.value));
|
|
2724
|
-
},
|
|
2725
|
-
// factor(expr), writing a polynomial as a product of irreducible factors
|
|
2726
|
-
// over the RATIONALS. x^2-2 and x^2+1 come back unchanged, which is the
|
|
2727
|
-
// correct answer over that field rather than a failure; see symbolic/Factor.ts.
|
|
2728
|
-
68: (args) => {
|
|
2729
|
-
const [value] = args;
|
|
2730
|
-
if (value.type !== 9 /* Symbolic */) return value;
|
|
2731
|
-
return symbolicToValue(factorSymbolic(value.value));
|
|
2732
|
-
},
|
|
2733
|
-
// solve(equation, variable), emitted by its own parselet as three stack
|
|
2734
|
-
// values: the two sides of the equation, then the variable NAME as a
|
|
2735
|
-
// String. Reading the name as a string rather than compiling it as a
|
|
2736
|
-
// variable read is what lets `solve(x^2-4=0, x)` work without `x` existing.
|
|
2737
|
-
69: (args) => {
|
|
2738
|
-
const [lhsValue, rhsValue, variableValue] = args;
|
|
2739
|
-
if (variableValue?.type !== 3 /* String */) {
|
|
2740
|
-
return chunk2TZKENDH_cjs.errorValue("SOLVE_REQUIRES_VARIABLE_NAME", "solve's second argument must be the name of the unknown.");
|
|
2741
|
-
}
|
|
2742
|
-
return solveEquationValues(lhsValue, rhsValue, variableValue.value);
|
|
2743
|
-
},
|
|
2744
|
-
// der(expr, variable, order), the symbolic derivative. Genuinely symbolic
|
|
2745
|
-
// rather than a finite difference, so it is exact.
|
|
2746
|
-
70: (args) => {
|
|
2747
|
-
const [target, variableValue, orderValue] = args;
|
|
2748
|
-
const variable = symbolicVariableName(variableValue, "der");
|
|
2749
|
-
if (typeof variable !== "string") return variable;
|
|
2750
|
-
const expression = valueToSymbolic(target);
|
|
2751
|
-
if (expression === null) return chunk2TZKENDH_cjs.errorValue("SYMBOLIC_NONFINITE_OPERAND", "der needs an expression with an exact value.");
|
|
2752
|
-
return symbolicToValue(differentiate2(expression, variable, orderValue?.toNumber() ?? 1));
|
|
2753
|
-
},
|
|
2754
|
-
// integral(expr, variable), the indefinite integral without a constant of
|
|
2755
|
-
// integration. Reports what it cannot do rather than approximating; see
|
|
2756
|
-
// symbolic/Integral.ts.
|
|
2757
|
-
71: (args) => {
|
|
2758
|
-
const [target, variableValue] = args;
|
|
2759
|
-
const variable = symbolicVariableName(variableValue, "integral");
|
|
2760
|
-
if (typeof variable !== "string") return variable;
|
|
2761
|
-
const expression = valueToSymbolic(target);
|
|
2762
|
-
if (expression === null) return chunk2TZKENDH_cjs.errorValue("SYMBOLIC_NONFINITE_OPERAND", "integral needs an expression with an exact value.");
|
|
2763
|
-
const result = integrate(expression, variable);
|
|
2764
|
-
if (!result.ok) return chunk2TZKENDH_cjs.errorValue("SYMBOLIC_INTEGRAL_UNSUPPORTED", `Cannot integrate this: ${result.reason}.`);
|
|
2765
|
-
return symbolicToValue(result.value);
|
|
2766
|
-
},
|
|
2767
|
-
// taylor(expr, variable = point, degree).
|
|
2768
|
-
72: (args) => {
|
|
2769
|
-
const [target, variableValue, pointValue, degreeValue] = args;
|
|
2770
|
-
const variable = symbolicVariableName(variableValue, "taylor");
|
|
2771
|
-
if (typeof variable !== "string") return variable;
|
|
2772
|
-
const expression = valueToSymbolic(target);
|
|
2773
|
-
const point = valueToSymbolic(pointValue);
|
|
2774
|
-
if (expression === null || point === null || point.kind !== "const") {
|
|
2775
|
-
return chunk2TZKENDH_cjs.errorValue("SYMBOLIC_NONFINITE_OPERAND", "taylor needs an expression and an exact expansion point.");
|
|
2776
|
-
}
|
|
2777
|
-
return symbolicToValue(taylorSeries(expression, variable, point.value, degreeValue.toNumber()));
|
|
2778
|
-
},
|
|
2779
|
-
// jacobian(f1, f2, ...), variadic. The variables are not named: they come
|
|
2780
|
-
// from the union of the functions' own unknowns, sorted, matching Calca.
|
|
2781
|
-
73: (args) => {
|
|
2782
|
-
const functions = [];
|
|
2783
|
-
for (const arg of args) {
|
|
2784
|
-
const node = valueToSymbolic(arg);
|
|
2785
|
-
if (node === null) return chunk2TZKENDH_cjs.errorValue("SYMBOLIC_NONFINITE_OPERAND", "jacobian needs expressions with exact values.");
|
|
2786
|
-
functions.push(node);
|
|
2787
|
-
}
|
|
2788
|
-
const variables = /* @__PURE__ */ new Set();
|
|
2789
|
-
for (const fn of functions) for (const name of chunkHIQ5HSZL_cjs.freeVariables(fn)) variables.add(name);
|
|
2790
|
-
const sorted = [...variables].sort();
|
|
2791
|
-
if (sorted.length === 0) return chunk2TZKENDH_cjs.errorValue("SYMBOLIC_JACOBIAN_NO_VARIABLES", "jacobian needs at least one unknown to differentiate against.");
|
|
2792
|
-
const rows = jacobian(functions, sorted);
|
|
2793
|
-
const rowMajor = [];
|
|
2794
|
-
for (const row of rows) {
|
|
2795
|
-
for (const cell of row) rowMajor.push(chunkHIQ5HSZL_cjs.symbolicToEntry(cell));
|
|
2796
|
-
}
|
|
2797
|
-
return chunk2TZKENDH_cjs.matrixValue(rows.length, sorted.length, chunkHIQ5HSZL_cjs.rowMajorToColumnMajor(rows.length, sorted.length, rowMajor));
|
|
2798
|
-
},
|
|
2799
|
-
// An imaginary literal, 3i. The parselet pushes the numeric part and this
|
|
2800
|
-
// turns it into an exact imaginary value.
|
|
2801
|
-
74: (args) => symbolicToValue(chunkHIQ5HSZL_cjs.complexNode(chunkHIQ5HSZL_cjs.complex(chunkHIQ5HSZL_cjs.RATIONAL_ZERO, chunkHIQ5HSZL_cjs.rationalFromNumber(args[0].toNumber())))),
|
|
2802
|
-
// conj(z), re(z) and im(z). Each folds immediately for a literal and stays
|
|
2803
|
-
// symbolic for anything still carrying an unknown.
|
|
2804
|
-
75: (args) => applyComplexAccessor("conj", args[0]),
|
|
2805
|
-
76: (args) => applyComplexAccessor("re", args[0]),
|
|
2806
|
-
77: (args) => applyComplexAccessor("im", args[0]),
|
|
2807
|
-
// cancel(expr), reducing a quotient of polynomials to lowest terms.
|
|
2808
|
-
78: (args) => {
|
|
2809
|
-
const value = args[0];
|
|
2810
|
-
if (value.type !== 9 /* Symbolic */) return value;
|
|
2811
|
-
return symbolicToValue(chunkHIQ5HSZL_cjs.cancelSymbolic(value.value));
|
|
2812
|
-
},
|
|
2813
|
-
// apart(expr), the partial-fraction decomposition of a rational function.
|
|
2814
|
-
79: (args) => {
|
|
2815
|
-
const value = args[0];
|
|
2816
|
-
if (value.type !== 9 /* Symbolic */) return value;
|
|
2817
|
-
return symbolicToValue(apartSymbolic(value.value));
|
|
2818
|
-
},
|
|
2819
|
-
// taxIn(amount, rate) -> amount - amount/(1 + rate), the tax already
|
|
2820
|
-
// contained in a tax-INCLUSIVE total. Backs "tax in/of/from $X at R%".
|
|
2821
|
-
// The complement of taxRemove (index 59): the two sum to the gross amount.
|
|
2822
|
-
85: (args) => {
|
|
2823
|
-
const amount = args[0].toNumber();
|
|
2824
|
-
const rate = args[1].toNumber();
|
|
2825
|
-
if (1 + rate <= 0) {
|
|
2826
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", `taxIn: rate ${rate} makes (1 + rate) non-positive`);
|
|
2827
|
-
}
|
|
2828
|
-
const tax = amount - amount / (1 + rate);
|
|
2829
|
-
if (args[0].type === 6 /* Uom */) {
|
|
2830
|
-
return taxInExact(args[0], args[0].unit, rate) ?? chunk2TZKENDH_cjs.uomValue(tax, args[0].unit);
|
|
2831
|
-
}
|
|
2832
|
-
return chunk2TZKENDH_cjs.numberValue(tax);
|
|
2833
|
-
},
|
|
2834
|
-
// taxOn(amount, rate) -> amount * rate, the tax itself.
|
|
2835
|
-
//
|
|
2836
|
-
// The "tax on $X at R%" phrase used to compile to taxAdd (index 58) and
|
|
2837
|
-
// answer $345.00 for "tax on $300 at 15%". Soulver answers $45.00, and
|
|
2838
|
-
// "the tax on $300" is the tax, not the bill. The total is "$300 + 15%",
|
|
2839
|
-
// which reads as a relative increase (see PercentParselet.ts), or
|
|
2840
|
-
// taxAdd(300, 0.15) for the function form.
|
|
2841
|
-
86: (args) => {
|
|
2842
|
-
const amount = args[0].toNumber();
|
|
2843
|
-
const rate = args[1].toNumber();
|
|
2844
|
-
if (args[0].type === 6 /* Uom */) return scaleMoneyExact(args[0], rate, args[0].unit);
|
|
2845
|
-
return chunk2TZKENDH_cjs.numberValue(amount * rate);
|
|
2846
|
-
},
|
|
2847
|
-
// ── Degree-taking trig (sind/cosd/tand and the inverses) ──────────────
|
|
2848
|
-
// The "d" spellings take and return degrees rather than radians, which is
|
|
2849
|
-
// the convention every scientific calculator uses. sin(90 degrees) is the
|
|
2850
|
-
// other way to say the same thing; both exist because both get typed.
|
|
2851
|
-
87: (args) => chunk2TZKENDH_cjs.numberValue(Math.sin(args[0].toNumber() * Math.PI / 180)),
|
|
2852
|
-
88: (args) => chunk2TZKENDH_cjs.numberValue(Math.cos(args[0].toNumber() * Math.PI / 180)),
|
|
2853
|
-
89: (args) => chunk2TZKENDH_cjs.numberValue(Math.tan(args[0].toNumber() * Math.PI / 180)),
|
|
2854
|
-
90: (args) => chunk2TZKENDH_cjs.numberValue(Math.asin(args[0].toNumber()) * 180 / Math.PI),
|
|
2855
|
-
91: (args) => chunk2TZKENDH_cjs.numberValue(Math.acos(args[0].toNumber()) * 180 / Math.PI),
|
|
2856
|
-
92: (args) => chunk2TZKENDH_cjs.numberValue(Math.atan(args[0].toNumber()) * 180 / Math.PI),
|
|
2857
|
-
// daysCount(n) -> n labelled as days. "days in Q3" is a count of days
|
|
2858
|
-
// and should say so; a bare 92 loses what was being counted.
|
|
2859
|
-
93: (args) => chunk2TZKENDH_cjs.uomValue(args[0].toNumber(), "days"),
|
|
2860
|
-
// asTwoUnits(value, majorUnit, minorUnit) -> "12 min 30 s".
|
|
2861
|
-
//
|
|
2862
|
-
// "12.5 minutes in minutes and seconds" asks for one quantity split
|
|
2863
|
-
// across two units, which every other conversion path cannot express:
|
|
2864
|
-
// they each produce a single number in a single unit.
|
|
2865
|
-
//
|
|
2866
|
-
// The whole part goes to the major unit and the remainder to the minor,
|
|
2867
|
-
// so nothing is lost. A pair that is not ordered major-then-minor, or
|
|
2868
|
-
// that spans two different measures, reports rather than guessing.
|
|
2869
|
-
94: (args) => {
|
|
2870
|
-
const major = typeof args[1]?.value === "string" ? args[1].value : void 0;
|
|
2871
|
-
const minor = typeof args[2]?.value === "string" ? args[2].value : void 0;
|
|
2872
|
-
if (major === void 0 || minor === void 0) {
|
|
2873
|
-
return chunk2TZKENDH_cjs.errorValue("UNKNOWN_UNIT", 'both units have to be named, as in "12.5 minutes in minutes and seconds"');
|
|
2874
|
-
}
|
|
2875
|
-
const majorEntry = chunkAMOJYLG2_cjs.UNIT_TABLE[major.toLowerCase()];
|
|
2876
|
-
const minorEntry = chunkAMOJYLG2_cjs.UNIT_TABLE[minor.toLowerCase()];
|
|
2877
|
-
if (majorEntry === void 0 || minorEntry === void 0) {
|
|
2878
|
-
return chunk2TZKENDH_cjs.errorValue("UNKNOWN_UNIT", `${major} and ${minor}: one of these is not a unit`);
|
|
2879
|
-
}
|
|
2880
|
-
if (majorEntry[0] !== minorEntry[0]) {
|
|
2881
|
-
return chunk2TZKENDH_cjs.errorValue("INCOMPATIBLE_UNITS", `${major} and ${minor} measure different things`);
|
|
2882
|
-
}
|
|
2883
|
-
if (minorEntry[1] >= majorEntry[1]) {
|
|
2884
|
-
return chunk2TZKENDH_cjs.errorValue("INCOMPATIBLE_UNITS", `${major} and ${minor}: name the larger unit first`);
|
|
2885
|
-
}
|
|
2886
|
-
const source = args[0];
|
|
2887
|
-
const sourceEntry = source.type === 6 /* Uom */ && source.unit !== void 0 ? chunkAMOJYLG2_cjs.UNIT_TABLE[source.unit.toLowerCase()] : void 0;
|
|
2888
|
-
const inBase = source.toNumber() * (sourceEntry?.[1] ?? majorEntry[1]);
|
|
2889
|
-
const majorCount = Math.floor(inBase / majorEntry[1]);
|
|
2890
|
-
const minorCount = Math.round((inBase - majorCount * majorEntry[1]) / minorEntry[1] * 1e3) / 1e3;
|
|
2891
|
-
return chunk2TZKENDH_cjs.stringValue(`${majorCount} ${major} ${minorCount} ${minor}`);
|
|
2892
|
-
},
|
|
2893
|
-
// makeRate(value, denominatorUnit) -> value per that unit.
|
|
2894
|
-
//
|
|
2895
|
-
// `3 hours / day` is a rate, `3 hours / 3 days` is a division. The
|
|
2896
|
-
// difference is whether a number was written in the denominator, which
|
|
2897
|
-
// is decided at parse time, so this only ever receives the rate case.
|
|
2898
|
-
//
|
|
2899
|
-
// Building the rate directly rather than dividing by an implied 1 is the
|
|
2900
|
-
// whole point: a division makes same-measure units cancel, which turned
|
|
2901
|
-
// `3 hours / day` into 0.125 when that shortcut was tried.
|
|
2902
|
-
95: (args) => {
|
|
2903
|
-
const source = args[0];
|
|
2904
|
-
const denominator = String(args[1].value);
|
|
2905
|
-
const numerator = source.type === 6 /* Uom */ && source.unit !== void 0 ? source.unit : "";
|
|
2906
|
-
if (numerator.includes("/")) {
|
|
2907
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE_UNIT", `${numerator}/${denominator}: that is already a rate`);
|
|
2908
|
-
}
|
|
2909
|
-
return chunk2TZKENDH_cjs.uomValue(source.toNumber(), `${numerator}/${denominator}`);
|
|
2910
|
-
},
|
|
2911
|
-
// atRate(quantity, rate) -> whichever of the two the question implies.
|
|
2912
|
-
//
|
|
2913
|
-
// 30 hours at $30/hour $900 a duration at a price per duration
|
|
2914
|
-
// $500 at $20/hour 25 hours money at a price per duration
|
|
2915
|
-
//
|
|
2916
|
-
// Both are written with the same word and mean opposite operations. Which
|
|
2917
|
-
// one applies is decided by which half of the rate the left side matches:
|
|
2918
|
-
// match the denominator and you are buying that many, match the numerator
|
|
2919
|
-
// and you are asking how many it buys.
|
|
2920
|
-
96: (args) => {
|
|
2921
|
-
const left = args[0];
|
|
2922
|
-
const rate = args[1];
|
|
2923
|
-
if (rate.type !== 6 /* Uom */ || rate.unit === void 0 || !rate.unit.includes("/")) {
|
|
2924
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", 'at: the right-hand side has to be a rate, as in "$30/hour"');
|
|
2925
|
-
}
|
|
2926
|
-
const slash = rate.unit.indexOf("/");
|
|
2927
|
-
const numerator = rate.unit.slice(0, slash);
|
|
2928
|
-
const denominator = rate.unit.slice(slash + 1);
|
|
2929
|
-
const leftUnit = left.type === 6 /* Uom */ ? left.unit : void 0;
|
|
2930
|
-
const denominatorEntry = chunkAMOJYLG2_cjs.UNIT_TABLE[denominator.toLowerCase()];
|
|
2931
|
-
const leftEntry = leftUnit === void 0 ? void 0 : chunkAMOJYLG2_cjs.UNIT_TABLE[leftUnit.toLowerCase()];
|
|
2932
|
-
if (leftEntry !== void 0 && denominatorEntry !== void 0 && leftEntry[0] === denominatorEntry[0]) {
|
|
2933
|
-
const inDenominator = left.toNumber() * leftEntry[1] / denominatorEntry[1];
|
|
2934
|
-
const total = inDenominator * rate.toNumber();
|
|
2935
|
-
return numerator === "" ? chunk2TZKENDH_cjs.numberValue(total) : chunk2TZKENDH_cjs.uomValue(total, numerator);
|
|
2936
|
-
}
|
|
2937
|
-
if (leftUnit !== void 0 && leftUnit === numerator) {
|
|
2938
|
-
const count = left.toNumber() / rate.toNumber();
|
|
2939
|
-
return chunk2TZKENDH_cjs.uomValue(count, pluraliseUnit(denominator, count));
|
|
2940
|
-
}
|
|
2941
|
-
if (leftUnit === void 0) {
|
|
2942
|
-
const total = left.toNumber() * rate.toNumber();
|
|
2943
|
-
return numerator === "" ? chunk2TZKENDH_cjs.numberValue(total) : chunk2TZKENDH_cjs.uomValue(total, numerator);
|
|
2944
|
-
}
|
|
2945
|
-
return chunk2TZKENDH_cjs.errorValue("INCOMPATIBLE_UNITS", `at: ${leftUnit} matches neither side of ${rate.unit}`);
|
|
2946
|
-
},
|
|
2947
|
-
// ── Investments (packages/finance/) ────────────────────────────────────
|
|
2948
|
-
// compoundFutureValueEvery(principal, rate, years, periodsPerYear)
|
|
2949
|
-
// FV = P(1 + r/n)^(n·y). Index 51 is the same formula with n fixed at 1;
|
|
2950
|
-
// this one backs "compounding monthly"/"quarterly"/"daily"/"weekly".
|
|
2951
|
-
// Kept separate rather than widening 51, because 51 is also the public
|
|
2952
|
-
// compoundInterest(principal, rate, years) call and its arity is part of
|
|
2953
|
-
// that contract.
|
|
2954
|
-
80: (args) => {
|
|
2955
|
-
const principal = args[0].toNumber();
|
|
2956
|
-
const rate = args[1].toNumber();
|
|
2957
|
-
const years = args[2].toNumber();
|
|
2958
|
-
const perYear = args[3].toNumber();
|
|
2959
|
-
if (perYear <= 0) {
|
|
2960
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", `compounding: ${perYear} periods per year is not a period`);
|
|
2961
|
-
}
|
|
2962
|
-
if (1 + rate / perYear <= 0) {
|
|
2963
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", `compounding: rate ${rate} makes each period non-positive`);
|
|
2964
|
-
}
|
|
2965
|
-
const fv = principal * Math.pow(1 + rate / perYear, perYear * years);
|
|
2966
|
-
return args[0].type === 6 /* Uom */ ? chunk2TZKENDH_cjs.uomValue(fv, args[0].unit) : chunk2TZKENDH_cjs.numberValue(fv);
|
|
2967
|
-
},
|
|
2968
|
-
// compoundInterestEarnedEvery(principal, rate, years, periodsPerYear)
|
|
2969
|
-
// The interest-only portion of index 80, i.e. FV - P.
|
|
2970
|
-
81: (args) => {
|
|
2971
|
-
const principal = args[0].toNumber();
|
|
2972
|
-
const rate = args[1].toNumber();
|
|
2973
|
-
const years = args[2].toNumber();
|
|
2974
|
-
const perYear = args[3].toNumber();
|
|
2975
|
-
if (perYear <= 0 || 1 + rate / perYear <= 0) {
|
|
2976
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", `compounding: rate ${rate} over ${perYear} periods per year is not usable`);
|
|
2977
|
-
}
|
|
2978
|
-
const interest = principal * (Math.pow(1 + rate / perYear, perYear * years) - 1);
|
|
2979
|
-
return args[0].type === 6 /* Uom */ ? chunk2TZKENDH_cjs.uomValue(interest, args[0].unit) : chunk2TZKENDH_cjs.numberValue(interest);
|
|
2980
|
-
},
|
|
2981
|
-
// presentValue(futureValue, rate, years) -> FV / (1 + r)^y, what a sum
|
|
2982
|
-
// promised in the future is worth today. The inverse of index 51.
|
|
2983
|
-
82: (args) => {
|
|
2984
|
-
const future = args[0].toNumber();
|
|
2985
|
-
const rate = args[1].toNumber();
|
|
2986
|
-
const years = args[2].toNumber();
|
|
2987
|
-
if (1 + rate <= 0) {
|
|
2988
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", `presentValue: rate ${rate} makes (1 + rate) non-positive`);
|
|
2989
|
-
}
|
|
2990
|
-
const pv = future / Math.pow(1 + rate, years);
|
|
2991
|
-
return args[0].type === 6 /* Uom */ ? chunk2TZKENDH_cjs.uomValue(pv, args[0].unit) : chunk2TZKENDH_cjs.numberValue(pv);
|
|
2992
|
-
},
|
|
2993
|
-
// returnOnInvestment(invested, returned) -> (returned - invested) /
|
|
2994
|
-
// invested, the gain as a multiple of what was put in. $500 in and $1,500
|
|
2995
|
-
// out is 2x, not 3x: ROI conventionally measures the profit against the
|
|
2996
|
-
// cost, so doubling your money is 1x return and tripling it is 2x. The
|
|
2997
|
-
// money multiple (3x here) is a different figure; `$1,500 / $500` gives it.
|
|
2998
|
-
83: (args) => {
|
|
2999
|
-
const invested = args[0].toNumber();
|
|
3000
|
-
const returned = args[1].toNumber();
|
|
3001
|
-
if (invested === 0) {
|
|
3002
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", "roi: nothing was invested, so there is no return on it");
|
|
3003
|
-
}
|
|
3004
|
-
return chunk2TZKENDH_cjs.numberValue((returned - invested) / invested);
|
|
3005
|
-
},
|
|
3006
|
-
// annualisedReturn(invested, returned, years) -> CAGR, the constant
|
|
3007
|
-
// yearly rate that turns `invested` into `returned` over `years`:
|
|
3008
|
-
// (returned/invested)^(1/years) - 1. Returned as a Percentage so it
|
|
3009
|
-
// renders "13.99%" rather than 0.1399.
|
|
3010
|
-
84: (args) => {
|
|
3011
|
-
const invested = args[0].toNumber();
|
|
3012
|
-
const returned = args[1].toNumber();
|
|
3013
|
-
const years = args[2].toNumber();
|
|
3014
|
-
if (invested <= 0) {
|
|
3015
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", "annual return: the amount invested must be positive");
|
|
3016
|
-
}
|
|
3017
|
-
if (years <= 0) {
|
|
3018
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", "annual return: the period must be longer than zero");
|
|
3019
|
-
}
|
|
3020
|
-
if (returned <= 0) {
|
|
3021
|
-
return chunk2TZKENDH_cjs.errorValue("INVALID_RATE", "annual return: nothing was returned, so there is no annual rate");
|
|
3022
|
-
}
|
|
3023
|
-
return chunk2TZKENDH_cjs.percentageValue(Math.pow(returned / invested, 1 / years) - 1);
|
|
3024
|
-
},
|
|
3025
|
-
// roundToPlaces(value, places) -> value rounded to that many decimal
|
|
3026
|
-
// places, backing `<value> to <n> dp` (converters/parselets/
|
|
3027
|
-
// RoundingParselets.ts).
|
|
3028
|
-
//
|
|
3029
|
-
// It exists because the obvious bytecode for it, "multiply by 10^p, round,
|
|
3030
|
-
// divide by 10^p", is only safe for values small enough that the multiply
|
|
3031
|
-
// is exact. `1e21 to 2 dp` came back as 999999999999999900000: 1e21 has no
|
|
3032
|
-
// fractional part to round at all, and the round trip through 1e23 was
|
|
3033
|
-
// pure loss. Asking for fewer decimal places than a number has cannot
|
|
3034
|
-
// change it, so a value that is already whole is returned untouched.
|
|
3035
|
-
97: (args) => roundToPlaces(args[0], args[1].toNumber())
|
|
3036
|
-
};
|
|
3037
|
-
function applyComplexAccessor(name, value) {
|
|
3038
|
-
const node = valueToSymbolic(value);
|
|
3039
|
-
if (node === null) return chunk2TZKENDH_cjs.errorValue("SYMBOLIC_NONFINITE_OPERAND", name + " needs a value with an exact number.");
|
|
3040
|
-
return symbolicToValue(chunkHIQ5HSZL_cjs.callNode(name, [node]));
|
|
3041
|
-
}
|
|
3042
|
-
function symbolicVariableName(value, verb) {
|
|
3043
|
-
if (value?.type !== 3 /* String */) {
|
|
3044
|
-
return chunk2TZKENDH_cjs.errorValue("SYMBOLIC_REQUIRES_VARIABLE_NAME", `${verb} needs the name of an unknown.`);
|
|
3045
|
-
}
|
|
3046
|
-
return value.value;
|
|
3047
|
-
}
|
|
3048
|
-
function amortizeLoan(principal, annualRate, years) {
|
|
3049
|
-
const n = years * 12;
|
|
3050
|
-
const rMonthly = annualRate / 12;
|
|
3051
|
-
const monthlyPayment = rMonthly === 0 ? principal / n : principal * rMonthly / (1 - Math.pow(1 + rMonthly, -n));
|
|
3052
|
-
const totalRepayment = monthlyPayment * n;
|
|
3053
|
-
const totalInterest = totalRepayment - principal;
|
|
3054
|
-
return { monthlyPayment, totalRepayment, totalInterest };
|
|
3055
|
-
}
|
|
3056
|
-
var pluginFunctionRegistry = defaultEngineContext.pluginFunctions;
|
|
3057
|
-
var MAX_PLUGIN_FUNCTION_INDEX = 255;
|
|
3058
|
-
var nextPluginFunctionIndex = 0;
|
|
3059
|
-
function allocatePluginFunctionIndex() {
|
|
3060
|
-
if (nextPluginFunctionIndex > MAX_PLUGIN_FUNCTION_INDEX) {
|
|
3061
|
-
throw chunkB4HBEFTB_cjs.ErrorFactory.config(
|
|
3062
|
-
"PLUGIN_FUNCTION_INDEX_POOL_EXHAUSTED",
|
|
3063
|
-
`allocatePluginFunctionIndex: pool exhausted (max ${MAX_PLUGIN_FUNCTION_INDEX + 1} allocations).`
|
|
3064
|
-
);
|
|
3065
|
-
}
|
|
3066
|
-
return nextPluginFunctionIndex++;
|
|
3067
|
-
}
|
|
3068
|
-
var asConverterRegistry = /* @__PURE__ */ new Map();
|
|
3069
|
-
function registerAsConverter(name, handler) {
|
|
3070
|
-
const key = name.toLowerCase();
|
|
3071
|
-
const existing = asConverterRegistry.get(key);
|
|
3072
|
-
if (existing && existing !== handler) {
|
|
3073
|
-
console.warn(`[asConverterRegistry] Converter name "${key}" is already registered \u2014 overwriting.`);
|
|
3074
|
-
}
|
|
3075
|
-
asConverterRegistry.set(key, handler);
|
|
3076
|
-
}
|
|
3077
|
-
function unregisterAsConverter(name) {
|
|
3078
|
-
asConverterRegistry.delete(name.toLowerCase());
|
|
3079
|
-
}
|
|
3080
|
-
|
|
3081
|
-
// src/vm/GlobalVariableStore.ts
|
|
3082
|
-
var _GlobalVariableStore = class _GlobalVariableStore {
|
|
3083
|
-
constructor() {
|
|
3084
|
-
this.values = /* @__PURE__ */ new Map();
|
|
3085
|
-
this.listeners = /* @__PURE__ */ new Set();
|
|
3086
|
-
this.notifyDepth = 0;
|
|
3087
|
-
}
|
|
3088
|
-
get(name) {
|
|
3089
|
-
return this.values.get(name);
|
|
3090
|
-
}
|
|
3091
|
-
has(name) {
|
|
3092
|
-
return this.values.has(name);
|
|
3093
|
-
}
|
|
3094
|
-
/**
|
|
3095
|
-
* Last-write-wins: any document may call this for any name at any time.
|
|
3096
|
-
* Notifies listeners synchronously, within the same call, before
|
|
3097
|
-
* returning, so that ThreeTierEvaluator's dirty-marking (a listener)
|
|
3098
|
-
* and GlobalVariableAsyncResolver's first-write promise (also a
|
|
3099
|
-
* listener) both observe the new value immediately, no microtask delay.
|
|
3100
|
-
*
|
|
3101
|
-
* A write that does not CHANGE the stored value notifies nobody. This
|
|
3102
|
-
* is not just an optimisation, it is what stops a re-evaluation cycle
|
|
3103
|
-
* from sustaining itself. Every listener re-runs work in response to a
|
|
3104
|
-
* write (ThreeTierEvaluator marks dependent lines dirty; the playground
|
|
3105
|
-
* worker refreshes other documents), and those re-runs re-execute the
|
|
3106
|
-
* very STORE_GLOBAL_VAR opcode that produced this write. Re-evaluating
|
|
3107
|
-
* an unchanged `global :x = 5` line therefore used to re-notify, which
|
|
3108
|
-
* re-triggered the listeners, which re-evaluated... bounded only by
|
|
3109
|
-
* MAX_NOTIFY_DEPTH below, and only in DEPTH, so with more than one
|
|
3110
|
-
* writer the work per keystroke grew exponentially. Nothing observable
|
|
3111
|
-
* changed, so there is nothing for a listener to react to.
|
|
3112
|
-
*/
|
|
3113
|
-
set(name, value) {
|
|
3114
|
-
const previous = this.values.get(name);
|
|
3115
|
-
this.values.set(name, value);
|
|
3116
|
-
if (previous !== void 0 && sameValue(previous, value)) return;
|
|
3117
|
-
this.notify(name, value);
|
|
3118
|
-
}
|
|
3119
|
-
notify(name, value) {
|
|
3120
|
-
if (this.notifyDepth >= _GlobalVariableStore.MAX_NOTIFY_DEPTH) return;
|
|
3121
|
-
this.notifyDepth++;
|
|
3122
|
-
try {
|
|
3123
|
-
for (const listener of this.listeners) listener(name, value);
|
|
3124
|
-
} finally {
|
|
3125
|
-
this.notifyDepth--;
|
|
3126
|
-
}
|
|
3127
|
-
}
|
|
3128
|
-
/**
|
|
3129
|
-
* Subscribe to every global-variable write (all names, callers filter
|
|
3130
|
-
* for the name(s) they care about). Returns an unsubscribe function;
|
|
3131
|
-
* callers MUST invoke it when disposing (e.g. ThreeTierEvaluator's
|
|
3132
|
-
* terminateWorker()) to avoid leaking listeners for closed documents.
|
|
3133
|
-
*/
|
|
3134
|
-
subscribe(listener) {
|
|
3135
|
-
this.listeners.add(listener);
|
|
3136
|
-
return () => {
|
|
3137
|
-
this.listeners.delete(listener);
|
|
3138
|
-
};
|
|
3139
|
-
}
|
|
3140
|
-
/**
|
|
3141
|
-
* Full reset, test-only. Never called from production code paths;
|
|
3142
|
-
* globals must outlive any single engine's own clear()/dispose cycle.
|
|
3143
|
-
* Tests MUST call this in beforeEach/afterEach since this is a
|
|
3144
|
-
* module-level singleton whose state and listeners otherwise leak
|
|
3145
|
-
* across test cases and files.
|
|
3146
|
-
*/
|
|
3147
|
-
clear() {
|
|
3148
|
-
this.values.clear();
|
|
3149
|
-
this.listeners.clear();
|
|
3150
|
-
this.notifyDepth = 0;
|
|
3151
|
-
}
|
|
3152
|
-
};
|
|
3153
|
-
/**
|
|
3154
|
-
* Guards against runaway cross-document write cycles: doc A's write
|
|
3155
|
-
* notifies doc B, whose dirty line, once evaluated, writes a global
|
|
3156
|
-
* that notifies doc C, ... eventually back to A. Same philosophy as the
|
|
3157
|
-
* VM's own instruction-limit safety net: stop propagating past the
|
|
3158
|
-
* limit rather than let a genuine cycle recurse unboundedly. The store
|
|
3159
|
-
* itself is left in a well-defined state either way. This only bounds
|
|
3160
|
-
* *notification* depth, never the value actually stored.
|
|
3161
|
-
*/
|
|
3162
|
-
_GlobalVariableStore.MAX_NOTIFY_DEPTH = 64;
|
|
3163
|
-
var GlobalVariableStore = _GlobalVariableStore;
|
|
3164
|
-
function sameValue(a, b) {
|
|
3165
|
-
if (a.type !== b.type) return false;
|
|
3166
|
-
if (a.unit !== b.unit) return false;
|
|
3167
|
-
if ((a.timedOut ?? false) !== (b.timedOut ?? false)) return false;
|
|
3168
|
-
const av = a.value;
|
|
3169
|
-
const bv = b.value;
|
|
3170
|
-
if (Array.isArray(av) || Array.isArray(bv)) {
|
|
3171
|
-
if (!Array.isArray(av) || !Array.isArray(bv)) return false;
|
|
3172
|
-
if (av.length !== bv.length) return false;
|
|
3173
|
-
for (let i = 0; i < av.length; i++) {
|
|
3174
|
-
if (!Object.is(av[i], bv[i])) return false;
|
|
3175
|
-
}
|
|
3176
|
-
return true;
|
|
3177
|
-
}
|
|
3178
|
-
return Object.is(av, bv);
|
|
3179
|
-
}
|
|
3180
|
-
var sharedGlobalVariableStore = new GlobalVariableStore();
|
|
3181
|
-
function globalDagKey(name) {
|
|
3182
|
-
return `global:${name}`;
|
|
3183
|
-
}
|
|
3184
|
-
|
|
3185
|
-
exports.CPI_MAX_YEAR = CPI_MAX_YEAR;
|
|
3186
|
-
exports.CPI_MIN_YEAR = CPI_MIN_YEAR;
|
|
3187
|
-
exports.OpRegistry = OpRegistry;
|
|
3188
|
-
exports.SYMBOLIC_NATIVE_BUILTINS = SYMBOLIC_NATIVE_BUILTINS;
|
|
3189
|
-
exports.adjustForInflation = adjustForInflation;
|
|
3190
|
-
exports.allocatePluginFunctionIndex = allocatePluginFunctionIndex;
|
|
3191
|
-
exports.asConverterRegistry = asConverterRegistry;
|
|
3192
|
-
exports.bigIntDivisionByZero = bigIntDivisionByZero;
|
|
3193
|
-
exports.binaryOp = binaryOp;
|
|
3194
|
-
exports.builtinFunctions = builtinFunctions;
|
|
3195
|
-
exports.compareBigIntOperands = compareBigIntOperands;
|
|
3196
|
-
exports.compareRationalOperands = compareRationalOperands;
|
|
3197
|
-
exports.compareUom = compareUom;
|
|
3198
|
-
exports.createEngineContext = createEngineContext;
|
|
3199
|
-
exports.defaultEngineContext = defaultEngineContext;
|
|
3200
|
-
exports.describeConversionMismatch = describeConversionMismatch;
|
|
3201
|
-
exports.exactRationalOp = exactRationalOp;
|
|
3202
|
-
exports.globalDagKey = globalDagKey;
|
|
3203
|
-
exports.incomparableUnitsError = incomparableUnitsError;
|
|
3204
|
-
exports.moneyExactMagnitude = moneyExactMagnitude;
|
|
3205
|
-
exports.pluginFunctionRegistry = pluginFunctionRegistry;
|
|
3206
|
-
exports.power = power;
|
|
3207
|
-
exports.registerAsConverter = registerAsConverter;
|
|
3208
|
-
exports.scaleMoneyByPercent = scaleMoneyByPercent;
|
|
3209
|
-
exports.scaleMoneyExact = scaleMoneyExact;
|
|
3210
|
-
exports.sharedGlobalVariableStore = sharedGlobalVariableStore;
|
|
3211
|
-
exports.sharedOpRegistry = sharedOpRegistry;
|
|
3212
|
-
exports.solveEquationValues = solveEquationValues;
|
|
3213
|
-
exports.solveForVariable = solveForVariable;
|
|
3214
|
-
exports.symbolicBuiltin = symbolicBuiltin;
|
|
3215
|
-
exports.symbolicNeg = symbolicNeg;
|
|
3216
|
-
exports.symbolicPow = symbolicPow;
|
|
3217
|
-
exports.toBigIntOperand = toBigIntOperand;
|
|
3218
|
-
exports.uncertainOp = uncertainOp;
|
|
3219
|
-
exports.unifyUom = unifyUom;
|
|
3220
|
-
exports.unregisterAsConverter = unregisterAsConverter;
|
|
3221
|
-
//# sourceMappingURL=chunk-7ZX6B7SY.cjs.map
|
|
3222
|
-
//# sourceMappingURL=chunk-7ZX6B7SY.cjs.map
|