solve-engine 1.0.2 → 1.1.1

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.
Files changed (237) hide show
  1. package/dist/{BytecodeBuilder-B0xskcv5.d.cts → BytecodeBuilder-Bp9xeTmX.d.cts} +4 -0
  2. package/dist/{BytecodeBuilder-B0xskcv5.d.ts → BytecodeBuilder-Bp9xeTmX.d.ts} +4 -0
  3. package/dist/{Configuration-B-G5gTRn.d.cts → Configuration-C9W8tJv_.d.cts} +53 -1
  4. package/dist/{Configuration-B-G5gTRn.d.ts → Configuration-C9W8tJv_.d.ts} +53 -1
  5. package/dist/{EngineError-LU7W7AgI.d.cts → EngineError-B61GS1jp.d.cts} +14 -0
  6. package/dist/{EngineError-LU7W7AgI.d.ts → EngineError-B61GS1jp.d.ts} +14 -0
  7. package/dist/FormattingSettings-CJHyxcYu.d.cts +27 -0
  8. package/dist/FormattingSettings-CJHyxcYu.d.ts +27 -0
  9. package/dist/{Lexer-DpjdaQ98.d.cts → Lexer-BOs7euZe.d.cts} +28 -1
  10. package/dist/{Lexer-CNmWxabg.d.ts → Lexer-CSI_lwbW.d.ts} +28 -1
  11. package/dist/PackageCompatibility-B-7rK1TD.d.cts +76 -0
  12. package/dist/PackageCompatibility-Dh59eF-X.d.ts +76 -0
  13. package/dist/{PackageRegistry-zuzqt51V.d.cts → PackageRegistry-BHWJP83F.d.cts} +449 -11
  14. package/dist/{PackageRegistry-ClIFXxAe.d.ts → PackageRegistry-_8rDlvxI.d.ts} +449 -11
  15. package/dist/{Parselet-BaySkMV3.d.ts → Parselet-BBT8riYh.d.ts} +12 -3
  16. package/dist/{Parselet-DuI1Pjiq.d.cts → Parselet-BHcgK9S7.d.cts} +12 -3
  17. package/dist/{ScopeManager-B6GzdhVG.d.cts → ScopeManager-8vf02dwj.d.cts} +56 -5
  18. package/dist/{ScopeManager-udv4Twwq.d.ts → ScopeManager-CxA24W5n.d.ts} +56 -5
  19. package/dist/{Token-BzG5G4ja.d.cts → Token-B1hdkedD.d.cts} +9 -0
  20. package/dist/{Token-BzG5G4ja.d.ts → Token-B1hdkedD.d.ts} +9 -0
  21. package/dist/{TokenNormalizer-t_GotBxr.d.ts → TokenNormalizer-C6VzZgHa.d.ts} +1 -1
  22. package/dist/{TokenNormalizer-DGVa24Q-.d.cts → TokenNormalizer-DRc1Js1V.d.cts} +1 -1
  23. package/dist/{VMCheckpoints-DwLjivM7.d.cts → VMCheckpoints-ELYqITdF.d.cts} +3 -3
  24. package/dist/{VMCheckpoints-BiaIlOOY.d.ts → VMCheckpoints-MK--EBH2.d.ts} +3 -3
  25. package/dist/{Value-CXJqDH9J.d.cts → Value-BUi1RA3S.d.cts} +124 -5
  26. package/dist/{Value-CXJqDH9J.d.ts → Value-BUi1RA3S.d.ts} +124 -5
  27. package/dist/WorkerError-_-RkoQ5P.d.ts +75 -0
  28. package/dist/WorkerError-gzmaopj2.d.cts +75 -0
  29. package/dist/{chunk-GQCOSXMG.js → chunk-267JPOTF.js} +43 -5
  30. package/dist/chunk-267JPOTF.js.map +1 -0
  31. package/dist/{chunk-JMXUNXQS.cjs → chunk-2TZKENDH.cjs} +51 -8
  32. package/dist/chunk-2TZKENDH.cjs.map +1 -0
  33. package/dist/chunk-3OWCDIPN.js +215 -0
  34. package/dist/chunk-3OWCDIPN.js.map +1 -0
  35. package/dist/{chunk-VB37OC6I.js → chunk-4D6NIHE2.js} +40 -3
  36. package/dist/chunk-4D6NIHE2.js.map +1 -0
  37. package/dist/{chunk-YXCTLWOH.js → chunk-4HQKTMWG.js} +1530 -57
  38. package/dist/chunk-4HQKTMWG.js.map +1 -0
  39. package/dist/{chunk-TY3TLZAW.cjs → chunk-536WPM2V.cjs} +18 -2
  40. package/dist/chunk-536WPM2V.cjs.map +1 -0
  41. package/dist/chunk-5HRB36DK.js +405 -0
  42. package/dist/chunk-5HRB36DK.js.map +1 -0
  43. package/dist/chunk-5ON7PUAZ.js +12 -0
  44. package/dist/chunk-5ON7PUAZ.js.map +1 -0
  45. package/dist/{chunk-KV7UW6T6.js → chunk-7KYSUDQO.js} +12 -5
  46. package/dist/chunk-7KYSUDQO.js.map +1 -0
  47. package/dist/{chunk-6WFMPTGB.cjs → chunk-7ZX6B7SY.cjs} +774 -528
  48. package/dist/chunk-7ZX6B7SY.cjs.map +1 -0
  49. package/dist/chunk-ALYRJ72W.cjs +434 -0
  50. package/dist/chunk-ALYRJ72W.cjs.map +1 -0
  51. package/dist/{chunk-5KMIY374.cjs → chunk-B4HBEFTB.cjs} +17 -2
  52. package/dist/chunk-B4HBEFTB.cjs.map +1 -0
  53. package/dist/chunk-B7NLZMQ3.cjs +74 -0
  54. package/dist/chunk-B7NLZMQ3.cjs.map +1 -0
  55. package/dist/{chunk-UQ3UIZJC.js → chunk-BLI4NIQY.js} +6 -2
  56. package/dist/chunk-BLI4NIQY.js.map +1 -0
  57. package/dist/{chunk-IP7ASJEW.js → chunk-BYJBUL7U.js} +5 -5
  58. package/dist/{chunk-IP7ASJEW.js.map → chunk-BYJBUL7U.js.map} +1 -1
  59. package/dist/{chunk-G535KJEG.js → chunk-CCBZZQAE.js} +2 -2
  60. package/dist/{chunk-G535KJEG.js.map → chunk-CCBZZQAE.js.map} +1 -1
  61. package/dist/chunk-CKQMXMHR.cjs +219 -0
  62. package/dist/chunk-CKQMXMHR.cjs.map +1 -0
  63. package/dist/{chunk-T556MJDZ.cjs → chunk-CUR2WLI4.cjs} +11 -11
  64. package/dist/{chunk-T556MJDZ.cjs.map → chunk-CUR2WLI4.cjs.map} +1 -1
  65. package/dist/{chunk-AA3KTWTX.js → chunk-DLEBSLF4.js} +4 -4
  66. package/dist/{chunk-AA3KTWTX.js.map → chunk-DLEBSLF4.js.map} +1 -1
  67. package/dist/{chunk-524F3ATQ.cjs → chunk-E23GZEWL.cjs} +15 -9
  68. package/dist/chunk-E23GZEWL.cjs.map +1 -0
  69. package/dist/{chunk-PFUESQTW.cjs → chunk-EJ3ILXX6.cjs} +48 -2
  70. package/dist/chunk-EJ3ILXX6.cjs.map +1 -0
  71. package/dist/{chunk-526PMQOA.js → chunk-ENKKJYD3.js} +10 -4
  72. package/dist/chunk-ENKKJYD3.js.map +1 -0
  73. package/dist/{chunk-5X2PTP6F.cjs → chunk-ENRIK36Q.cjs} +2 -12
  74. package/dist/chunk-ENRIK36Q.cjs.map +1 -0
  75. package/dist/{chunk-3D7V24DG.js → chunk-ERCOHGXD.js} +17 -2
  76. package/dist/chunk-ERCOHGXD.js.map +1 -0
  77. package/dist/{chunk-IF532O7C.js → chunk-FD5ZZHEU.js} +3 -12
  78. package/dist/chunk-FD5ZZHEU.js.map +1 -0
  79. package/dist/{chunk-7FSDNNNC.js → chunk-GLA4JXBO.js} +11 -5
  80. package/dist/chunk-GLA4JXBO.js.map +1 -0
  81. package/dist/{chunk-UM6BVY2S.cjs → chunk-HIQ5HSZL.cjs} +175 -43
  82. package/dist/chunk-HIQ5HSZL.cjs.map +1 -0
  83. package/dist/{chunk-HVQFNJKE.cjs → chunk-HVRVSI2Z.cjs} +104 -86
  84. package/dist/chunk-HVRVSI2Z.cjs.map +1 -0
  85. package/dist/{chunk-3LAEG75D.js → chunk-I4GAWIPW.js} +24 -6
  86. package/dist/chunk-I4GAWIPW.js.map +1 -0
  87. package/dist/{chunk-PA4VC73I.cjs → chunk-J45BCEZ4.cjs} +33 -27
  88. package/dist/chunk-J45BCEZ4.cjs.map +1 -0
  89. package/dist/{chunk-FQGX2PA2.js → chunk-JG6ZJ2WU.js} +128 -4
  90. package/dist/chunk-JG6ZJ2WU.js.map +1 -0
  91. package/dist/chunk-L2TE7PMO.cjs +14 -0
  92. package/dist/chunk-L2TE7PMO.cjs.map +1 -0
  93. package/dist/chunk-LHZ6VOA7.js +1764 -0
  94. package/dist/chunk-LHZ6VOA7.js.map +1 -0
  95. package/dist/{chunk-SESSWASV.cjs → chunk-MN3LHRGV.cjs} +1868 -393
  96. package/dist/chunk-MN3LHRGV.cjs.map +1 -0
  97. package/dist/{chunk-R3PY4G7J.js → chunk-MVTOCRV2.js} +48 -3
  98. package/dist/chunk-MVTOCRV2.js.map +1 -0
  99. package/dist/{chunk-FE23VSSA.cjs → chunk-N5NNW4VG.cjs} +6 -6
  100. package/dist/{chunk-FE23VSSA.cjs.map → chunk-N5NNW4VG.cjs.map} +1 -1
  101. package/dist/{chunk-Y7FT4IQT.js → chunk-NKW7LKYU.js} +266 -28
  102. package/dist/chunk-NKW7LKYU.js.map +1 -0
  103. package/dist/{chunk-O3ANBHSA.js → chunk-NNQ2TYDF.js} +123 -5
  104. package/dist/chunk-NNQ2TYDF.js.map +1 -0
  105. package/dist/{chunk-NG2JHZHE.js → chunk-NNZAEUDW.js} +1853 -2640
  106. package/dist/chunk-NNZAEUDW.js.map +1 -0
  107. package/dist/{chunk-5LI5EPGJ.cjs → chunk-QFTDTX6K.cjs} +40 -3
  108. package/dist/chunk-QFTDTX6K.cjs.map +1 -0
  109. package/dist/{chunk-HDP7VK3C.cjs → chunk-SRGQ72IR.cjs} +649 -349
  110. package/dist/chunk-SRGQ72IR.cjs.map +1 -0
  111. package/dist/{chunk-4B2CNWQU.cjs → chunk-SSV46KFA.cjs} +14 -7
  112. package/dist/chunk-SSV46KFA.cjs.map +1 -0
  113. package/dist/{chunk-HBVFFBRR.cjs → chunk-T6ZYQJ63.cjs} +1962 -2748
  114. package/dist/chunk-T6ZYQJ63.cjs.map +1 -0
  115. package/dist/{chunk-AJA6LUI7.js → chunk-UO6BUV6K.js} +18 -2
  116. package/dist/chunk-UO6BUV6K.js.map +1 -0
  117. package/dist/chunk-WWQEY7BV.js +67 -0
  118. package/dist/chunk-WWQEY7BV.js.map +1 -0
  119. package/dist/{chunk-5WVP4YHP.js → chunk-WXEHD6TT.js} +333 -33
  120. package/dist/chunk-WXEHD6TT.js.map +1 -0
  121. package/dist/{chunk-47LRVGOT.cjs → chunk-XA4CKRML.cjs} +2 -2
  122. package/dist/{chunk-47LRVGOT.cjs.map → chunk-XA4CKRML.cjs.map} +1 -1
  123. package/dist/{chunk-6KFYJ6TD.cjs → chunk-XIYYHA65.cjs} +6 -2
  124. package/dist/chunk-XIYYHA65.cjs.map +1 -0
  125. package/dist/chunk-YRIKITGF.cjs +1768 -0
  126. package/dist/chunk-YRIKITGF.cjs.map +1 -0
  127. package/dist/{chunk-TMA4RCEN.js → chunk-Z7XGGLI2.js} +3 -3
  128. package/dist/{chunk-TMA4RCEN.js.map → chunk-Z7XGGLI2.js.map} +1 -1
  129. package/dist/{chunk-R7YVBHCV.cjs → chunk-ZMW6NU2K.cjs} +197 -73
  130. package/dist/chunk-ZMW6NU2K.cjs.map +1 -0
  131. package/dist/{chunk-A2N2GFCG.cjs → chunk-ZVTWQLK4.cjs} +10 -10
  132. package/dist/{chunk-A2N2GFCG.cjs.map → chunk-ZVTWQLK4.cjs.map} +1 -1
  133. package/dist/constants.cjs +5 -5
  134. package/dist/constants.d.cts +1 -1
  135. package/dist/constants.d.ts +1 -1
  136. package/dist/constants.js +2 -2
  137. package/dist/engine.cjs +52 -35
  138. package/dist/engine.d.cts +13 -13
  139. package/dist/engine.d.ts +13 -13
  140. package/dist/engine.js +26 -21
  141. package/dist/errors.cjs +44 -19
  142. package/dist/errors.d.cts +3 -2
  143. package/dist/errors.d.ts +3 -2
  144. package/dist/errors.js +2 -1
  145. package/dist/format.cjs +19 -169
  146. package/dist/format.cjs.map +1 -1
  147. package/dist/format.d.cts +18 -26
  148. package/dist/format.d.ts +18 -26
  149. package/dist/format.js +7 -171
  150. package/dist/format.js.map +1 -1
  151. package/dist/index.cjs +250 -31
  152. package/dist/index.cjs.map +1 -1
  153. package/dist/index.d.cts +110 -74
  154. package/dist/index.d.ts +110 -74
  155. package/dist/index.js +228 -23
  156. package/dist/index.js.map +1 -1
  157. package/dist/language.cjs +9 -9
  158. package/dist/language.d.cts +12 -12
  159. package/dist/language.d.ts +12 -12
  160. package/dist/language.js +3 -3
  161. package/dist/lexer.cjs +16 -16
  162. package/dist/lexer.d.cts +3 -3
  163. package/dist/lexer.d.ts +3 -3
  164. package/dist/lexer.js +5 -5
  165. package/dist/normalizer.cjs +10 -10
  166. package/dist/normalizer.d.cts +3 -3
  167. package/dist/normalizer.d.ts +3 -3
  168. package/dist/normalizer.js +4 -4
  169. package/dist/packages.cjs +45 -36
  170. package/dist/packages.d.cts +135 -31
  171. package/dist/packages.d.ts +135 -31
  172. package/dist/packages.js +14 -13
  173. package/dist/parser.cjs +16 -16
  174. package/dist/parser.d.cts +6 -5
  175. package/dist/parser.d.ts +6 -5
  176. package/dist/parser.js +6 -6
  177. package/dist/{pipeline-BEb3hujr.d.cts → pipeline-CtfJtPQc.d.cts} +3 -3
  178. package/dist/{pipeline-B6k5lCB7.d.ts → pipeline-DCd5M6Gk.d.ts} +3 -3
  179. package/dist/resolvers.d.cts +3 -3
  180. package/dist/resolvers.d.ts +3 -3
  181. package/dist/testing.cjs +478 -0
  182. package/dist/testing.cjs.map +1 -0
  183. package/dist/testing.d.cts +271 -0
  184. package/dist/testing.d.ts +271 -0
  185. package/dist/testing.js +470 -0
  186. package/dist/testing.js.map +1 -0
  187. package/dist/uom.cjs +16 -16
  188. package/dist/uom.d.cts +3 -3
  189. package/dist/uom.d.ts +3 -3
  190. package/dist/uom.js +6 -6
  191. package/dist/utilities.cjs +6 -5
  192. package/dist/utilities.js +2 -1
  193. package/dist/vm.cjs +34 -34
  194. package/dist/vm.d.cts +8 -8
  195. package/dist/vm.d.ts +8 -8
  196. package/dist/vm.js +9 -9
  197. package/dist/worker.cjs +493 -0
  198. package/dist/worker.cjs.map +1 -0
  199. package/dist/worker.d.cts +509 -0
  200. package/dist/worker.d.ts +509 -0
  201. package/dist/worker.js +484 -0
  202. package/dist/worker.js.map +1 -0
  203. package/package.json +21 -1
  204. package/dist/chunk-3D7V24DG.js.map +0 -1
  205. package/dist/chunk-3LAEG75D.js.map +0 -1
  206. package/dist/chunk-4B2CNWQU.cjs.map +0 -1
  207. package/dist/chunk-524F3ATQ.cjs.map +0 -1
  208. package/dist/chunk-526PMQOA.js.map +0 -1
  209. package/dist/chunk-5KMIY374.cjs.map +0 -1
  210. package/dist/chunk-5LI5EPGJ.cjs.map +0 -1
  211. package/dist/chunk-5WVP4YHP.js.map +0 -1
  212. package/dist/chunk-5X2PTP6F.cjs.map +0 -1
  213. package/dist/chunk-6KFYJ6TD.cjs.map +0 -1
  214. package/dist/chunk-6WFMPTGB.cjs.map +0 -1
  215. package/dist/chunk-7FSDNNNC.js.map +0 -1
  216. package/dist/chunk-AJA6LUI7.js.map +0 -1
  217. package/dist/chunk-FQGX2PA2.js.map +0 -1
  218. package/dist/chunk-GQCOSXMG.js.map +0 -1
  219. package/dist/chunk-HBVFFBRR.cjs.map +0 -1
  220. package/dist/chunk-HDP7VK3C.cjs.map +0 -1
  221. package/dist/chunk-HVQFNJKE.cjs.map +0 -1
  222. package/dist/chunk-IF532O7C.js.map +0 -1
  223. package/dist/chunk-JMXUNXQS.cjs.map +0 -1
  224. package/dist/chunk-KV7UW6T6.js.map +0 -1
  225. package/dist/chunk-NG2JHZHE.js.map +0 -1
  226. package/dist/chunk-O3ANBHSA.js.map +0 -1
  227. package/dist/chunk-PA4VC73I.cjs.map +0 -1
  228. package/dist/chunk-PFUESQTW.cjs.map +0 -1
  229. package/dist/chunk-R3PY4G7J.js.map +0 -1
  230. package/dist/chunk-R7YVBHCV.cjs.map +0 -1
  231. package/dist/chunk-SESSWASV.cjs.map +0 -1
  232. package/dist/chunk-TY3TLZAW.cjs.map +0 -1
  233. package/dist/chunk-UM6BVY2S.cjs.map +0 -1
  234. package/dist/chunk-UQ3UIZJC.js.map +0 -1
  235. package/dist/chunk-VB37OC6I.js.map +0 -1
  236. package/dist/chunk-Y7FT4IQT.js.map +0 -1
  237. package/dist/chunk-YXCTLWOH.js.map +0 -1
@@ -1,10 +1,10 @@
1
1
  import { VariableResolver } from './chunk-GCM5JHMX.js';
2
- import { sharedCurrencyExchange } from './chunk-TMA4RCEN.js';
3
- import { powNode, callNode, simplifySymbolic, sameShape, cancelSymbolic, complexNode, complex, RATIONAL_ZERO, rationalFromNumber, freeVariables, symbolicToEntry, rowMajorToColumnMajor, expandSymbolic, matrixMultiply, inverse, determinant, transpose, matrixPower, constNode, rationalToNumber, toPolynomial, polyDegree, polyCoefficients, rationalNeg, substitute, rationalDiv, isRationalZero, varNode, isRationalOne, RATIONAL_ONE, polyUnivariateVar, rationalMul, fromPolynomial, coefficientGcd, polynomialDivide, isZeroPolynomial, rationalCompare, rationalSub, exactIntegerSqrt, rationalAdd, surdNode, compareMonomials, COMPLEX_I, squareFreePart, exactRationalSqrt, symbolicKey, monomialFromKey, monomialToKey, signedSurdNode, exactIntegerCbrt } from './chunk-O3ANBHSA.js';
4
- import { faultedOperand, errorValue, symbolicValue, numberValue, bigIntValue, uomValue, matrixValue, percentageValue, stringValue, hexValue } from './chunk-GQCOSXMG.js';
5
- import { getMeasure, convertUnit } from './chunk-R3PY4G7J.js';
2
+ import { sharedCurrencyExchange } from './chunk-Z7XGGLI2.js';
3
+ import { decimalFromInteger, toPolynomial, polyDegree, polyCoefficients, fromPolynomial, constNode, rationalDiv, rationalNeg, powNode, callNode, decimalCompare, isRationalZero, rationalMul, rationalSub, rationalAdd, rationalToNumber, rationalCompare, simplifySymbolic, sameShape, decimalFromNumberIfExact, decimalMultiply, decimalToNumber, decimalAdd, decimalNegate, cancelSymbolic, complexNode, complex, RATIONAL_ZERO, rationalFromNumber, freeVariables, symbolicToEntry, rowMajorToColumnMajor, expandSymbolic, matrixMultiply, inverse, determinant, transpose, matrixPower, exactIntegerSqrt, surdNode, rational, decimalIsZero, decimalDivide, decimalSubtract, decimalFromLiteral, decimalRound, substitute, varNode, isRationalOne, RATIONAL_ONE, polyUnivariateVar, COMPLEX_I, squareFreePart, coefficientGcd, polynomialDivide, isZeroPolynomial, exactRationalSqrt, symbolicKey, compareMonomials, signedSurdNode, monomialFromKey, monomialToKey, exactIntegerCbrt } from './chunk-NNQ2TYDF.js';
4
+ import { faultedOperand, errorValue, numberValueRational, numberValueUncertain, symbolicValue, numberValue, bigIntValue, uomValue, matrixValue, uomValueExact, percentageValue, stringValue, hexValue } from './chunk-267JPOTF.js';
5
+ import { getMeasure, convertUnit } from './chunk-MVTOCRV2.js';
6
6
  import { UNIT_TABLE } from './chunk-V4XG5QF6.js';
7
- import { ErrorFactory } from './chunk-3D7V24DG.js';
7
+ import { ErrorFactory } from './chunk-ERCOHGXD.js';
8
8
 
9
9
  // src/symbolic/MultivariateFactor.ts
10
10
  function exactRoot(value, degree) {
@@ -1134,15 +1134,59 @@ function largestFiniteMagnitude(a, b, c) {
1134
1134
  function compareUom(l, r) {
1135
1135
  const { lv, rv, sameMeasure } = unifyUom(l, r);
1136
1136
  if (!sameMeasure) return { lv, rv, equal: false, sameMeasure: false };
1137
+ 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 && sharedCurrencyExchange.isCurrency(l.unit)) {
1138
+ return { lv, rv, equal: decimalCompare(l.exact, r.exact) === 0, sameMeasure: true };
1139
+ }
1137
1140
  if (lv === rv) return { lv, rv, equal: true, sameMeasure: true };
1138
1141
  if (!Number.isFinite(lv) || !Number.isFinite(rv)) return { lv, rv, equal: false, sameMeasure: true };
1139
1142
  const scale2 = largestFiniteMagnitude(lv, rv, r.toNumber());
1140
1143
  return { lv, rv, equal: Math.abs(lv - rv) <= scale2 * UNIFIED_COMPARISON_TOLERANCE, sameMeasure: true };
1141
1144
  }
1145
+ var MEASURE_NOUNS = {
1146
+ time: "duration",
1147
+ luminousIntensity: "luminous intensity"
1148
+ };
1149
+ var UNCOUNTABLE_MEASURES = /* @__PURE__ */ new Set(["money", "data"]);
1150
+ var COMBINE_VERBS = {
1151
+ add: "added",
1152
+ sub: "subtracted",
1153
+ mul: "multiplied",
1154
+ div: "divided"
1155
+ };
1156
+ function describeMeasure(unit) {
1157
+ if (sharedCurrencyExchange.isCurrency(unit)) return "money";
1158
+ const measure = getMeasure(unit);
1159
+ if (measure === void 0) return void 0;
1160
+ return MEASURE_NOUNS[measure] ?? measure;
1161
+ }
1162
+ function withMeasureArticle(noun) {
1163
+ if (UNCOUNTABLE_MEASURES.has(noun)) return noun;
1164
+ return /^[aeiou]/.test(noun) ? `an ${noun}` : `a ${noun}`;
1165
+ }
1166
+ function describeMeasureMismatch(lUnit, rUnit, verb) {
1167
+ const left = lUnit === void 0 ? void 0 : describeMeasure(lUnit);
1168
+ const right = rUnit === void 0 ? void 0 : describeMeasure(rUnit);
1169
+ if (left !== void 0 && right !== void 0 && left !== right) {
1170
+ return `${left} and ${right} cannot be ${verb}`;
1171
+ }
1172
+ return void 0;
1173
+ }
1174
+ function combineVerb(op) {
1175
+ return op !== void 0 ? COMBINE_VERBS[op] ?? "combined" : "combined";
1176
+ }
1177
+ function describeConversionMismatch(fromUnit, toUnit) {
1178
+ const from = describeMeasure(fromUnit);
1179
+ const to = describeMeasure(toUnit);
1180
+ if (from !== void 0 && to !== void 0 && from !== to) {
1181
+ return `${withMeasureArticle(from)} cannot be converted to ${withMeasureArticle(to)}`;
1182
+ }
1183
+ return void 0;
1184
+ }
1142
1185
  function incomparableUnitsError(l, r) {
1143
1186
  const lUnit = l.type === 6 /* Uom */ ? l.unit : void 0;
1144
1187
  const rUnit = r.type === 6 /* Uom */ ? r.unit : void 0;
1145
- return errorValue("INCOMPATIBLE_UNITS", `Cannot compare incompatible units: ${lUnit ?? "?"} and ${rUnit ?? "?"}`);
1188
+ const named = describeMeasureMismatch(lUnit, rUnit, "compared");
1189
+ return errorValue("INCOMPATIBLE_UNITS", named ?? `Cannot compare incompatible units: ${lUnit ?? "?"} and ${rUnit ?? "?"}`);
1146
1190
  }
1147
1191
  function toBigIntOperand(v) {
1148
1192
  if (v.type === 2 /* BigInt */) return v.value;
@@ -1182,6 +1226,121 @@ function power(base, exponent) {
1182
1226
  if (base === -1 && !Number.isNaN(exponent)) return 1;
1183
1227
  return Math.pow(base, exponent);
1184
1228
  }
1229
+ function operandExactDecimal(v) {
1230
+ if (v.exact !== void 0) return v.exact;
1231
+ return decimalFromNumberIfExact(v.toNumber());
1232
+ }
1233
+ function exactMoneyOp(l, r, op) {
1234
+ const lMoney = l.type === 6 /* Uom */ && l.unit !== void 0 && l.exact !== void 0 && sharedCurrencyExchange.isCurrency(l.unit);
1235
+ const rMoney = r.type === 6 /* Uom */ && r.unit !== void 0 && r.exact !== void 0 && sharedCurrencyExchange.isCurrency(r.unit);
1236
+ if (!lMoney && !rMoney) return null;
1237
+ let ld;
1238
+ let rd;
1239
+ let unit;
1240
+ if (lMoney && rMoney) {
1241
+ if (l.unit !== r.unit || op === "div") return null;
1242
+ ld = l.exact;
1243
+ rd = r.exact;
1244
+ unit = l.unit;
1245
+ } else if (lMoney && r.type !== 6 /* Uom */) {
1246
+ ld = l.exact;
1247
+ unit = l.unit;
1248
+ rd = operandExactDecimal(r);
1249
+ } else if (rMoney && l.type !== 6 /* Uom */) {
1250
+ rd = r.exact;
1251
+ unit = r.unit;
1252
+ ld = operandExactDecimal(l);
1253
+ } else {
1254
+ return null;
1255
+ }
1256
+ if (ld === null || rd === null) return null;
1257
+ let result;
1258
+ switch (op) {
1259
+ case "add":
1260
+ result = decimalAdd(ld, rd);
1261
+ break;
1262
+ case "sub":
1263
+ result = decimalSubtract(ld, rd);
1264
+ break;
1265
+ case "mul":
1266
+ result = decimalMultiply(ld, rd);
1267
+ break;
1268
+ case "div":
1269
+ if (decimalIsZero(rd)) return null;
1270
+ result = decimalDivide(ld, rd);
1271
+ break;
1272
+ }
1273
+ return uomValueExact(decimalToNumber(result), unit, result);
1274
+ }
1275
+ function operandRational(v) {
1276
+ if (v.rational !== void 0) return v.rational;
1277
+ if ((v.type === 0 /* Number */ || v.type === 1 /* Hex */) && typeof v.value === "number" && Number.isInteger(v.value)) {
1278
+ return rational(BigInt(v.value));
1279
+ }
1280
+ return null;
1281
+ }
1282
+ function exactRationalOp(l, r, op) {
1283
+ const lr = operandRational(l);
1284
+ if (lr === null) return null;
1285
+ const rr = operandRational(r);
1286
+ if (rr === null) return null;
1287
+ if (op === "div" && isRationalZero(rr)) return null;
1288
+ let result;
1289
+ try {
1290
+ switch (op) {
1291
+ case "add":
1292
+ result = rationalAdd(lr, rr);
1293
+ break;
1294
+ case "sub":
1295
+ result = rationalSub(lr, rr);
1296
+ break;
1297
+ case "mul":
1298
+ result = rationalMul(lr, rr);
1299
+ break;
1300
+ case "div":
1301
+ result = rationalDiv(lr, rr);
1302
+ break;
1303
+ }
1304
+ } catch {
1305
+ return null;
1306
+ }
1307
+ return numberValueRational(rationalToNumber(result), result);
1308
+ }
1309
+ function uncertainOp(l, r, op) {
1310
+ if (l.type !== 0 /* Number */ || r.type !== 0 /* Number */) return null;
1311
+ const a = l.value;
1312
+ const b = r.value;
1313
+ const sa = l.uncertainty ?? 0;
1314
+ const sb = r.uncertainty ?? 0;
1315
+ let center;
1316
+ let sigma;
1317
+ switch (op) {
1318
+ case "add":
1319
+ center = a + b;
1320
+ sigma = Math.hypot(sa, sb);
1321
+ break;
1322
+ case "sub":
1323
+ center = a - b;
1324
+ sigma = Math.hypot(sa, sb);
1325
+ break;
1326
+ case "mul":
1327
+ center = a * b;
1328
+ sigma = Math.hypot(b * sa, a * sb);
1329
+ break;
1330
+ case "div":
1331
+ center = a / b;
1332
+ sigma = Math.hypot(sa / b, a * sb / (b * b));
1333
+ break;
1334
+ }
1335
+ return numberValueUncertain(center, sigma);
1336
+ }
1337
+ function compareRationalOperands(l, r) {
1338
+ const lr = operandRational(l);
1339
+ if (lr === null) return null;
1340
+ const rr = operandRational(r);
1341
+ if (rr === null) return null;
1342
+ return rationalCompare(lr, rr);
1343
+ }
1185
1344
  function binaryOp(l, r, op, bigOp, symbolicOp) {
1186
1345
  if (l.type === 13 /* Error */) return l;
1187
1346
  if (r.type === 13 /* Error */) return r;
@@ -1209,11 +1368,16 @@ function binaryOp(l, r, op, bigOp, symbolicOp) {
1209
1368
  return bigIntValue(lb + rb);
1210
1369
  }
1211
1370
  if (l.type === 6 /* Uom */ || r.type === 6 /* Uom */) {
1371
+ if (symbolicOp) {
1372
+ const exactMoney = exactMoneyOp(l, r, symbolicOp);
1373
+ if (exactMoney) return exactMoney;
1374
+ }
1212
1375
  const { lv, rv, unit, sameMeasure } = unifyUom(l, r);
1213
1376
  if (!sameMeasure) {
1214
1377
  const lUnit = l.type === 6 /* Uom */ ? l.unit : void 0;
1215
1378
  const rUnit = r.type === 6 /* Uom */ ? r.unit : void 0;
1216
- return errorValue("INCOMPATIBLE_UNITS", `Cannot combine incompatible units: ${lUnit ?? "?"} and ${rUnit ?? "?"}`);
1379
+ const named = describeMeasureMismatch(lUnit, rUnit, combineVerb(symbolicOp));
1380
+ return errorValue("INCOMPATIBLE_UNITS", named ?? `Cannot combine incompatible units: ${lUnit ?? "?"} and ${rUnit ?? "?"}`);
1217
1381
  }
1218
1382
  return uomValue(op(lv, rv), unit);
1219
1383
  }
@@ -1288,6 +1452,57 @@ var OpRegistry = class {
1288
1452
  };
1289
1453
  var sharedOpRegistry = new OpRegistry();
1290
1454
 
1455
+ // src/vm/MoneyExact.ts
1456
+ var ONE_DECIMAL = decimalFromInteger(1);
1457
+ function moneyExactMagnitude(operand, unit) {
1458
+ if (!sharedCurrencyExchange.isCurrency(unit)) return null;
1459
+ return operand.exact ?? decimalFromNumberIfExact(operand.toNumber());
1460
+ }
1461
+ function decimalFromShortDecimal(n) {
1462
+ if (!Number.isFinite(n)) return null;
1463
+ if (Number.isInteger(n)) return decimalFromInteger(BigInt(n));
1464
+ const s = String(n);
1465
+ if (!/^-?\d+\.\d+$/.test(s)) return null;
1466
+ return decimalFromLiteral(s);
1467
+ }
1468
+ function scaleMoneyExact(amount, factor, unit) {
1469
+ const base = moneyExactMagnitude(amount, unit);
1470
+ const factorDecimal = decimalFromShortDecimal(factor);
1471
+ if (base !== null && factorDecimal !== null) {
1472
+ const result = decimalMultiply(base, factorDecimal);
1473
+ return uomValueExact(decimalToNumber(result), unit, result);
1474
+ }
1475
+ return uomValue(amount.toNumber() * factor, unit);
1476
+ }
1477
+ function scaleMoneyByPercent(money, unit, percent, sign) {
1478
+ const base = moneyExactMagnitude(money, unit);
1479
+ const percentDecimal = decimalFromShortDecimal(percent);
1480
+ if (base !== null && percentDecimal !== null) {
1481
+ const factor = decimalAdd(ONE_DECIMAL, sign === 1 ? percentDecimal : decimalNegate(percentDecimal));
1482
+ const result = decimalMultiply(base, factor);
1483
+ return uomValueExact(decimalToNumber(result), unit, result);
1484
+ }
1485
+ return uomValue(money.toNumber() * (1 + sign * percent), unit);
1486
+ }
1487
+ function onePlusRateDecimal(rate) {
1488
+ const rateDecimal = decimalFromShortDecimal(rate);
1489
+ return rateDecimal === null ? null : decimalAdd(ONE_DECIMAL, rateDecimal);
1490
+ }
1491
+ function removeTaxExact(money, unit, rate) {
1492
+ const base = moneyExactMagnitude(money, unit);
1493
+ const divisor = onePlusRateDecimal(rate);
1494
+ if (base === null || divisor === null || decimalIsZero(divisor)) return null;
1495
+ const quotient = decimalDivide(base, divisor);
1496
+ return uomValueExact(decimalToNumber(quotient), unit, quotient);
1497
+ }
1498
+ function taxInExact(money, unit, rate) {
1499
+ const base = moneyExactMagnitude(money, unit);
1500
+ const divisor = onePlusRateDecimal(rate);
1501
+ if (base === null || divisor === null || decimalIsZero(divisor)) return null;
1502
+ const tax = decimalSubtract(base, decimalDivide(base, divisor));
1503
+ return uomValueExact(decimalToNumber(tax), unit, tax);
1504
+ }
1505
+
1291
1506
  // src/symbolic/PartialFractions.ts
1292
1507
  var APART_MAX_DEGREE = 12;
1293
1508
  function multiply2(a, b) {
@@ -1958,9 +2173,10 @@ function extremum(args, wantLargest) {
1958
2173
  if (!sameMeasure) {
1959
2174
  const bestUnit = best.type === 6 /* Uom */ ? best.unit : void 0;
1960
2175
  const otherUnit = a.type === 6 /* Uom */ ? a.unit : void 0;
2176
+ const named = describeMeasureMismatch(bestUnit, otherUnit, "compared");
1961
2177
  return errorValue(
1962
2178
  "INCOMPATIBLE_UNITS",
1963
- `Cannot compare incompatible units: ${bestUnit ?? "?"} and ${otherUnit ?? "?"}`
2179
+ named ?? `Cannot compare incompatible units: ${bestUnit ?? "?"} and ${otherUnit ?? "?"}`
1964
2180
  );
1965
2181
  }
1966
2182
  if (wantLargest ? rv > lv : rv < lv) best = a;
@@ -1973,6 +2189,25 @@ function keepUnit(operand, magnitude2) {
1973
2189
  if (operand.type === 6 /* Uom */ && operand.unit !== void 0) return uomValue(magnitude2, operand.unit);
1974
2190
  return numberValue(magnitude2);
1975
2191
  }
2192
+ function roundToPlaces(source, places) {
2193
+ const p = Number.isFinite(places) ? Math.min(100, Math.max(0, Math.trunc(places))) : 0;
2194
+ if (source.exact !== void 0) {
2195
+ const rounded = decimalRound(source.exact, p);
2196
+ return withPlaces(source, decimalToNumber(rounded), p, rounded);
2197
+ }
2198
+ const value = source.toNumber();
2199
+ if (!Number.isFinite(value)) return withPlaces(source, value, p);
2200
+ const scale2 = Math.pow(10, p);
2201
+ const scaled = value * scale2;
2202
+ if (!Number.isFinite(scaled) || Math.abs(scaled) > Number.MAX_SAFE_INTEGER) return withPlaces(source, value, p);
2203
+ return withPlaces(source, Math.round(scaled) / scale2, p);
2204
+ }
2205
+ function withPlaces(source, magnitude2, places, exact) {
2206
+ const result = source.type === 6 /* Uom */ && source.unit !== void 0 ? uomValue(magnitude2, source.unit) : numberValue(magnitude2);
2207
+ result.decimalPlaces = places;
2208
+ if (exact !== void 0) result.exact = exact;
2209
+ return result;
2210
+ }
1976
2211
  function nonFiniteEuclidOperand(a, b, name) {
1977
2212
  if (Number.isFinite(a) && Number.isFinite(b)) return null;
1978
2213
  const culprit = Number.isFinite(a) ? b : a;
@@ -2013,7 +2248,13 @@ var builtinFunctions = {
2013
2248
  // round/ceil/floor keep a unit for the same reason abs does; see keepUnit().
2014
2249
  6: (args) => keepUnit(args[0], Math.ceil(args[0].toNumber())),
2015
2250
  7: (args) => keepUnit(args[0], Math.floor(args[0].toNumber())),
2016
- 8: (args) => keepUnit(args[0], Math.round(args[0].toNumber())),
2251
+ 8: (args) => args.length >= 2 ? (
2252
+ // round(x, n): round to n decimal places and display at that precision.
2253
+ roundToPlaces(args[0], args[1].toNumber())
2254
+ ) : (
2255
+ // round(x): nearest whole number, the way it always was.
2256
+ keepUnit(args[0], Math.round(args[0].toNumber()))
2257
+ ),
2017
2258
  // min/max: see extremum() for why the winner is carried around as a Value
2018
2259
  // rather than as a running number.
2019
2260
  9: (args) => extremum(args, false),
@@ -2357,8 +2598,8 @@ var builtinFunctions = {
2357
2598
  58: (args) => {
2358
2599
  const amount = args[0].toNumber();
2359
2600
  const rate = args[1].toNumber();
2360
- const result = amount * (1 + rate);
2361
- return args[0].type === 6 /* Uom */ ? uomValue(result, args[0].unit) : numberValue(result);
2601
+ if (args[0].type === 6 /* Uom */) return scaleMoneyByPercent(args[0], args[0].unit, rate, 1);
2602
+ return numberValue(amount * (1 + rate));
2362
2603
  },
2363
2604
  // taxRemove(amount, rate) -> amount / (1 + rate), extracts the
2364
2605
  // pre-tax amount from a tax-INCLUSIVE total. Backs "tax off $X at R%" /
@@ -2369,7 +2610,10 @@ var builtinFunctions = {
2369
2610
  if (1 + rate <= 0) {
2370
2611
  return errorValue("INVALID_RATE", `taxRemove: rate ${rate} makes (1 + rate) non-positive`);
2371
2612
  }
2372
- return args[0].type === 6 /* Uom */ ? uomValue(amount / (1 + rate), args[0].unit) : numberValue(amount / (1 + rate));
2613
+ if (args[0].type === 6 /* Uom */) {
2614
+ return removeTaxExact(args[0], args[0].unit, rate) ?? uomValue(amount / (1 + rate), args[0].unit);
2615
+ }
2616
+ return numberValue(amount / (1 + rate));
2373
2617
  },
2374
2618
  // inflationAdjust(amount, fromYear, toYear) -- CPI-based inflation
2375
2619
  // adjustment between two arbitrary years, using the bundled CPI-U
@@ -2580,7 +2824,10 @@ var builtinFunctions = {
2580
2824
  return errorValue("INVALID_RATE", `taxIn: rate ${rate} makes (1 + rate) non-positive`);
2581
2825
  }
2582
2826
  const tax = amount - amount / (1 + rate);
2583
- return args[0].type === 6 /* Uom */ ? uomValue(tax, args[0].unit) : numberValue(tax);
2827
+ if (args[0].type === 6 /* Uom */) {
2828
+ return taxInExact(args[0], args[0].unit, rate) ?? uomValue(tax, args[0].unit);
2829
+ }
2830
+ return numberValue(tax);
2584
2831
  },
2585
2832
  // taxOn(amount, rate) -> amount * rate, the tax itself.
2586
2833
  //
@@ -2592,8 +2839,8 @@ var builtinFunctions = {
2592
2839
  86: (args) => {
2593
2840
  const amount = args[0].toNumber();
2594
2841
  const rate = args[1].toNumber();
2595
- const tax = amount * rate;
2596
- return args[0].type === 6 /* Uom */ ? uomValue(tax, args[0].unit) : numberValue(tax);
2842
+ if (args[0].type === 6 /* Uom */) return scaleMoneyExact(args[0], rate, args[0].unit);
2843
+ return numberValue(amount * rate);
2597
2844
  },
2598
2845
  // ── Degree-taking trig (sind/cosd/tand and the inverses) ──────────────
2599
2846
  // The "d" spellings take and return degrees rather than radians, which is
@@ -2783,16 +3030,7 @@ var builtinFunctions = {
2783
3030
  // fractional part to round at all, and the round trip through 1e23 was
2784
3031
  // pure loss. Asking for fewer decimal places than a number has cannot
2785
3032
  // change it, so a value that is already whole is returned untouched.
2786
- 97: (args) => {
2787
- const source = args[0];
2788
- const value = source.toNumber();
2789
- const places = args[1].toNumber();
2790
- if (!Number.isFinite(value) || Number.isInteger(value)) return keepUnit(source, value);
2791
- const scale2 = Math.pow(10, places);
2792
- const scaled = value * scale2;
2793
- if (!Number.isFinite(scaled) || Math.abs(scaled) > Number.MAX_SAFE_INTEGER) return keepUnit(source, value);
2794
- return keepUnit(source, Math.round(scaled) / scale2);
2795
- }
3033
+ 97: (args) => roundToPlaces(args[0], args[1].toNumber())
2796
3034
  };
2797
3035
  function applyComplexAccessor(name, value) {
2798
3036
  const node = valueToSymbolic(value);
@@ -2942,6 +3180,6 @@ function globalDagKey(name) {
2942
3180
  return `global:${name}`;
2943
3181
  }
2944
3182
 
2945
- export { CPI_MAX_YEAR, CPI_MIN_YEAR, OpRegistry, SYMBOLIC_NATIVE_BUILTINS, adjustForInflation, allocatePluginFunctionIndex, asConverterRegistry, bigIntDivisionByZero, binaryOp, builtinFunctions, compareBigIntOperands, compareUom, createEngineContext, defaultEngineContext, globalDagKey, incomparableUnitsError, pluginFunctionRegistry, power, registerAsConverter, sharedGlobalVariableStore, sharedOpRegistry, solveEquationValues, symbolicBuiltin, symbolicNeg, symbolicPow, toBigIntOperand, unifyUom, unregisterAsConverter };
2946
- //# sourceMappingURL=chunk-Y7FT4IQT.js.map
2947
- //# sourceMappingURL=chunk-Y7FT4IQT.js.map
3183
+ export { CPI_MAX_YEAR, CPI_MIN_YEAR, OpRegistry, SYMBOLIC_NATIVE_BUILTINS, adjustForInflation, allocatePluginFunctionIndex, asConverterRegistry, bigIntDivisionByZero, binaryOp, builtinFunctions, compareBigIntOperands, compareRationalOperands, compareUom, createEngineContext, defaultEngineContext, describeConversionMismatch, exactRationalOp, globalDagKey, incomparableUnitsError, moneyExactMagnitude, pluginFunctionRegistry, power, registerAsConverter, scaleMoneyByPercent, scaleMoneyExact, sharedGlobalVariableStore, sharedOpRegistry, solveEquationValues, solveForVariable, symbolicBuiltin, symbolicNeg, symbolicPow, toBigIntOperand, uncertainOp, unifyUom, unregisterAsConverter };
3184
+ //# sourceMappingURL=chunk-NKW7LKYU.js.map
3185
+ //# sourceMappingURL=chunk-NKW7LKYU.js.map