@classytic/stage 0.3.0 → 0.4.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.
Files changed (431) hide show
  1. package/dist/_virtual/_rolldown/runtime.mjs +18 -0
  2. package/dist/atomic/aufbau.d.mts +144 -0
  3. package/dist/atomic/aufbau.mjs +384 -0
  4. package/dist/atomic/elements.d.mts +67 -0
  5. package/dist/atomic/elements.mjs +785 -0
  6. package/dist/atomic/emission.d.mts +112 -0
  7. package/dist/atomic/emission.mjs +179 -0
  8. package/dist/atomic/index.d.mts +8 -0
  9. package/dist/atomic/index.mjs +9 -0
  10. package/dist/atomic/periodic.d.mts +82 -0
  11. package/dist/atomic/periodic.mjs +231 -0
  12. package/dist/atomic/properties.d.mts +100 -0
  13. package/dist/atomic/properties.mjs +574 -0
  14. package/dist/atomic/shells.d.mts +137 -0
  15. package/dist/atomic/shells.mjs +170 -0
  16. package/dist/atomic/trends.d.mts +148 -0
  17. package/dist/atomic/trends.mjs +225 -0
  18. package/dist/chem/chromatography.d.mts +66 -0
  19. package/dist/chem/chromatography.mjs +63 -0
  20. package/dist/chem/complex.d.mts +114 -0
  21. package/dist/chem/complex.mjs +234 -0
  22. package/dist/chem/cycle.d.mts +75 -0
  23. package/dist/chem/cycle.mjs +145 -0
  24. package/dist/chem/equation.d.mts +86 -0
  25. package/dist/chem/equation.mjs +168 -0
  26. package/dist/chem/formula.d.mts +90 -0
  27. package/dist/chem/formula.mjs +201 -0
  28. package/dist/chem/functional-groups.d.mts +31 -0
  29. package/dist/chem/functional-groups.mjs +187 -0
  30. package/dist/chem/hazard.d.mts +94 -0
  31. package/dist/chem/hazard.mjs +329 -0
  32. package/dist/chem/index.d.mts +34 -33
  33. package/dist/chem/index.mjs +34 -28
  34. package/dist/chem/ionic.d.mts +98 -0
  35. package/dist/chem/ionic.mjs +156 -0
  36. package/dist/chem/layout.d.mts +46 -0
  37. package/dist/chem/layout.mjs +342 -0
  38. package/dist/chem/lewis.d.mts +79 -0
  39. package/dist/chem/lewis.mjs +163 -0
  40. package/dist/chem/molecular-orbital.d.mts +114 -0
  41. package/dist/chem/molecular-orbital.mjs +201 -0
  42. package/dist/chem/molecule.d.mts +154 -0
  43. package/dist/chem/molecule.mjs +282 -0
  44. package/dist/chem/nmr.d.mts +153 -0
  45. package/dist/chem/nmr.mjs +165 -0
  46. package/dist/chem/polymer.d.mts +65 -0
  47. package/dist/chem/polymer.mjs +179 -0
  48. package/dist/chem/redox.d.mts +138 -0
  49. package/dist/chem/redox.mjs +328 -0
  50. package/dist/chem/relations.d.mts +183 -0
  51. package/dist/chem/relations.mjs +299 -0
  52. package/dist/chem/skeleton.d.mts +51 -0
  53. package/dist/chem/skeleton.mjs +186 -0
  54. package/dist/chem/solution.d.mts +116 -0
  55. package/dist/chem/solution.mjs +186 -0
  56. package/dist/chem/species.d.mts +47 -0
  57. package/dist/chem/species.mjs +128 -0
  58. package/dist/chem/stereo.d.mts +108 -0
  59. package/dist/chem/stereo.mjs +286 -0
  60. package/dist/chem/stoichiometry.d.mts +95 -0
  61. package/dist/chem/stoichiometry.mjs +145 -0
  62. package/dist/chem/synthesis.d.mts +113 -0
  63. package/dist/chem/synthesis.mjs +281 -0
  64. package/dist/chem/vsepr.d.mts +80 -0
  65. package/dist/chem/vsepr.mjs +247 -0
  66. package/dist/circuit/ac.d.mts +163 -0
  67. package/dist/circuit/ac.mjs +452 -0
  68. package/dist/circuit/dc.d.mts +92 -0
  69. package/dist/circuit/dc.mjs +333 -0
  70. package/dist/circuit/index.d.mts +5 -92
  71. package/dist/circuit/index.mjs +5 -332
  72. package/dist/circuit/network.d.mts +99 -0
  73. package/dist/circuit/network.mjs +440 -0
  74. package/dist/circuit/topology.d.mts +102 -0
  75. package/dist/circuit/topology.mjs +143 -0
  76. package/dist/colour/absorption.d.mts +79 -0
  77. package/dist/colour/absorption.mjs +137 -0
  78. package/dist/colour/index.d.mts +6 -0
  79. package/dist/colour/index.mjs +7 -0
  80. package/dist/colour/name.d.mts +14 -0
  81. package/dist/colour/name.mjs +76 -0
  82. package/dist/colour/observer.d.mts +31 -0
  83. package/dist/colour/observer.mjs +46 -0
  84. package/dist/colour/spectrum.d.mts +61 -0
  85. package/dist/colour/spectrum.mjs +108 -0
  86. package/dist/colour/srgb.d.mts +49 -0
  87. package/dist/colour/srgb.mjs +108 -0
  88. package/dist/core/constants.d.mts +138 -0
  89. package/dist/core/constants.mjs +139 -0
  90. package/dist/core/index.d.mts +3 -1
  91. package/dist/core/index.mjs +3 -1
  92. package/dist/core/vec3.d.mts +94 -0
  93. package/dist/core/vec3.mjs +123 -0
  94. package/dist/core/worked.d.mts +35 -0
  95. package/dist/core/worked.mjs +44 -0
  96. package/dist/electro/cell.d.mts +102 -0
  97. package/dist/electro/cell.mjs +170 -0
  98. package/dist/electro/conductivity.d.mts +157 -0
  99. package/dist/electro/conductivity.mjs +156 -0
  100. package/dist/electro/couples.d.mts +114 -0
  101. package/dist/electro/couples.mjs +334 -0
  102. package/dist/electro/electrolysis.d.mts +96 -0
  103. package/dist/electro/electrolysis.mjs +274 -0
  104. package/dist/electro/faraday.d.mts +150 -0
  105. package/dist/electro/faraday.mjs +118 -0
  106. package/dist/electro/index.d.mts +6 -0
  107. package/dist/electro/index.mjs +7 -0
  108. package/dist/finance/accounting/adjustments.d.mts +17 -0
  109. package/dist/finance/accounting/adjustments.mjs +202 -0
  110. package/dist/finance/accounting/analysis.d.mts +8 -0
  111. package/dist/finance/accounting/analysis.mjs +205 -0
  112. package/dist/finance/accounting/clubs.d.mts +21 -0
  113. package/dist/finance/accounting/clubs.mjs +217 -0
  114. package/dist/finance/accounting/company-statements.d.mts +7 -0
  115. package/dist/finance/accounting/company-statements.mjs +150 -0
  116. package/dist/finance/accounting/harness.d.mts +7 -0
  117. package/dist/finance/accounting/harness.mjs +45 -0
  118. package/dist/finance/accounting/index.d.mts +18 -0
  119. package/dist/finance/accounting/index.mjs +18 -0
  120. package/dist/finance/accounting/journalize.d.mts +16 -0
  121. package/dist/finance/accounting/journalize.mjs +128 -0
  122. package/dist/finance/accounting/manufacturing.d.mts +8 -0
  123. package/dist/finance/accounting/manufacturing.mjs +236 -0
  124. package/dist/finance/accounting/partnership.d.mts +7 -0
  125. package/dist/finance/accounting/partnership.mjs +152 -0
  126. package/dist/finance/accounting/period-case.d.mts +6 -0
  127. package/dist/finance/accounting/period-case.mjs +71 -0
  128. package/dist/finance/accounting/post.d.mts +9 -0
  129. package/dist/finance/accounting/post.mjs +84 -0
  130. package/dist/finance/accounting/precision.d.mts +9 -0
  131. package/dist/finance/accounting/precision.mjs +15 -0
  132. package/dist/finance/accounting/rules.d.mts +21 -0
  133. package/dist/finance/accounting/rules.mjs +37 -0
  134. package/dist/finance/accounting/solve.d.mts +28 -0
  135. package/dist/finance/accounting/solve.mjs +92 -0
  136. package/dist/finance/accounting/statements.d.mts +7 -0
  137. package/dist/finance/accounting/statements.mjs +142 -0
  138. package/dist/finance/accounting/types.d.mts +649 -0
  139. package/dist/finance/accounting/validate.d.mts +7 -0
  140. package/dist/finance/accounting/validate.mjs +67 -0
  141. package/dist/finance/accounting/verification.d.mts +24 -0
  142. package/dist/finance/accounting/verification.mjs +386 -0
  143. package/dist/finance/bizsim.d.mts +21 -39
  144. package/dist/finance/bizsim.mjs +276 -97
  145. package/dist/finance/index.d.mts +20 -43
  146. package/dist/finance/index.mjs +19 -77
  147. package/dist/finance/investment-math.d.mts +7 -0
  148. package/dist/finance/investment-math.mjs +18 -0
  149. package/dist/finance/management-accounting/budgeting.d.mts +7 -0
  150. package/dist/finance/management-accounting/budgeting.mjs +189 -0
  151. package/dist/finance/management-accounting/cash-budget.d.mts +7 -0
  152. package/dist/finance/management-accounting/cash-budget.mjs +154 -0
  153. package/dist/finance/management-accounting/costing.d.mts +8 -0
  154. package/dist/finance/management-accounting/costing.mjs +175 -0
  155. package/dist/finance/management-accounting/decisions.d.mts +8 -0
  156. package/dist/finance/management-accounting/decisions.mjs +164 -0
  157. package/dist/finance/management-accounting/index.d.mts +13 -0
  158. package/dist/finance/management-accounting/index.mjs +13 -0
  159. package/dist/finance/management-accounting/integrated-budget.d.mts +8 -0
  160. package/dist/finance/management-accounting/integrated-budget.mjs +67 -0
  161. package/dist/finance/management-accounting/inventory-costing.d.mts +7 -0
  162. package/dist/finance/management-accounting/inventory-costing.mjs +173 -0
  163. package/dist/finance/management-accounting/investment-appraisal.d.mts +7 -0
  164. package/dist/finance/management-accounting/investment-appraisal.mjs +148 -0
  165. package/dist/finance/management-accounting/management-case.d.mts +8 -0
  166. package/dist/finance/management-accounting/management-case.mjs +91 -0
  167. package/dist/finance/management-accounting/master-budget.d.mts +7 -0
  168. package/dist/finance/management-accounting/master-budget.mjs +137 -0
  169. package/dist/finance/management-accounting/production-costing.d.mts +8 -0
  170. package/dist/finance/management-accounting/production-costing.mjs +214 -0
  171. package/dist/finance/management-accounting/types.d.mts +644 -0
  172. package/dist/finance/management-accounting/variances.d.mts +7 -0
  173. package/dist/finance/management-accounting/variances.mjs +150 -0
  174. package/dist/index.d.mts +6 -6
  175. package/dist/index.mjs +1 -1
  176. package/dist/math/analysis.d.mts +61 -0
  177. package/dist/math/analysis.mjs +187 -0
  178. package/dist/math/answer-check.d.mts +50 -0
  179. package/dist/math/answer-check.mjs +106 -0
  180. package/dist/math/calculus.d.mts +4 -9
  181. package/dist/math/calculus.mjs +216 -7
  182. package/dist/math/complex.d.mts +93 -0
  183. package/dist/math/complex.mjs +239 -0
  184. package/dist/math/expr.d.mts +23 -0
  185. package/dist/math/expr.mjs +36 -0
  186. package/dist/math/index.d.mts +8 -22
  187. package/dist/math/index.mjs +8 -37
  188. package/dist/math/latex.mjs +2 -1
  189. package/dist/math/parse.mjs +1 -1
  190. package/dist/math/poly.d.mts +55 -0
  191. package/dist/math/poly.mjs +273 -0
  192. package/dist/math/rearrange.d.mts +14 -0
  193. package/dist/math/rearrange.mjs +125 -0
  194. package/dist/math/solve.d.mts +21 -0
  195. package/dist/math/solve.mjs +75 -0
  196. package/dist/networking/addressing.d.mts +26 -0
  197. package/dist/networking/addressing.mjs +33 -0
  198. package/dist/networking/cloud/access.d.mts +36 -0
  199. package/dist/networking/cloud/access.mjs +95 -0
  200. package/dist/networking/cloud/containers.d.mts +43 -0
  201. package/dist/networking/cloud/containers.mjs +54 -0
  202. package/dist/networking/cloud/edge.d.mts +17 -0
  203. package/dist/networking/cloud/edge.mjs +31 -0
  204. package/dist/networking/cloud/failure-domains.d.mts +19 -0
  205. package/dist/networking/cloud/failure-domains.mjs +22 -0
  206. package/dist/networking/cloud/geo-routing.d.mts +22 -0
  207. package/dist/networking/cloud/geo-routing.mjs +64 -0
  208. package/dist/networking/cloud/index.d.mts +18 -0
  209. package/dist/networking/cloud/index.mjs +19 -0
  210. package/dist/networking/cloud/inference-reliability.d.mts +30 -0
  211. package/dist/networking/cloud/inference-reliability.mjs +76 -0
  212. package/dist/networking/cloud/inference.d.mts +118 -0
  213. package/dist/networking/cloud/inference.mjs +179 -0
  214. package/dist/networking/cloud/infrastructure.d.mts +45 -0
  215. package/dist/networking/cloud/infrastructure.mjs +96 -0
  216. package/dist/networking/cloud/observability.d.mts +24 -0
  217. package/dist/networking/cloud/observability.mjs +34 -0
  218. package/dist/networking/cloud/orchestration.d.mts +32 -0
  219. package/dist/networking/cloud/orchestration.mjs +38 -0
  220. package/dist/networking/cloud/recovery.d.mts +21 -0
  221. package/dist/networking/cloud/recovery.mjs +27 -0
  222. package/dist/networking/cloud/releases.d.mts +42 -0
  223. package/dist/networking/cloud/releases.mjs +135 -0
  224. package/dist/networking/cloud/scaling.d.mts +25 -0
  225. package/dist/networking/cloud/scaling.mjs +65 -0
  226. package/dist/networking/cloud/secrets.d.mts +39 -0
  227. package/dist/networking/cloud/secrets.mjs +68 -0
  228. package/dist/networking/cloud/server-deployment.d.mts +29 -0
  229. package/dist/networking/cloud/server-deployment.mjs +72 -0
  230. package/dist/networking/cloud/storage.d.mts +16 -0
  231. package/dist/networking/cloud/storage.mjs +58 -0
  232. package/dist/networking/cloud/vpc.d.mts +18 -0
  233. package/dist/networking/cloud/vpc.mjs +100 -0
  234. package/dist/networking/delivery.d.mts +34 -0
  235. package/dist/networking/delivery.mjs +52 -0
  236. package/dist/networking/index.d.mts +47 -0
  237. package/dist/networking/index.mjs +47 -0
  238. package/dist/networking/ipv6.d.mts +28 -0
  239. package/dist/networking/ipv6.mjs +17 -0
  240. package/dist/networking/journeys.d.mts +83 -0
  241. package/dist/networking/journeys.mjs +161 -0
  242. package/dist/networking/models/airtime.d.mts +87 -0
  243. package/dist/networking/models/airtime.mjs +130 -0
  244. package/dist/networking/models/cellular.d.mts +157 -0
  245. package/dist/networking/models/cellular.mjs +252 -0
  246. package/dist/networking/models/encapsulation.d.mts +98 -0
  247. package/dist/networking/models/encapsulation.mjs +132 -0
  248. package/dist/networking/models/handover.d.mts +116 -0
  249. package/dist/networking/models/handover.mjs +209 -0
  250. package/dist/networking/models/handshake.d.mts +90 -0
  251. package/dist/networking/models/handshake.mjs +122 -0
  252. package/dist/networking/models/index.d.mts +14 -0
  253. package/dist/networking/models/index.mjs +15 -0
  254. package/dist/networking/models/media.d.mts +82 -0
  255. package/dist/networking/models/media.mjs +188 -0
  256. package/dist/networking/models/satellite.d.mts +86 -0
  257. package/dist/networking/models/satellite.mjs +121 -0
  258. package/dist/networking/models/spectrum.d.mts +83 -0
  259. package/dist/networking/models/spectrum.mjs +235 -0
  260. package/dist/networking/models/switch.d.mts +80 -0
  261. package/dist/networking/models/switch.mjs +155 -0
  262. package/dist/networking/models/vlan.d.mts +62 -0
  263. package/dist/networking/models/vlan.mjs +100 -0
  264. package/dist/networking/models/vpn.d.mts +66 -0
  265. package/dist/networking/models/vpn.mjs +125 -0
  266. package/dist/networking/models/wifi-privacy.d.mts +82 -0
  267. package/dist/networking/models/wifi-privacy.mjs +130 -0
  268. package/dist/networking/models/wifi.d.mts +240 -0
  269. package/dist/networking/models/wifi.mjs +562 -0
  270. package/dist/networking/nat-traversal.d.mts +24 -0
  271. package/dist/networking/nat-traversal.mjs +38 -0
  272. package/dist/networking/protocols.d.mts +17 -0
  273. package/dist/networking/protocols.mjs +57 -0
  274. package/dist/networking/queue.d.mts +12 -0
  275. package/dist/networking/queue.mjs +18 -0
  276. package/dist/networking/route-learning.d.mts +23 -0
  277. package/dist/networking/route-learning.mjs +43 -0
  278. package/dist/networking/routing.d.mts +11 -0
  279. package/dist/networking/routing.mjs +25 -0
  280. package/dist/networking/signals.d.mts +26 -0
  281. package/dist/networking/signals.mjs +35 -0
  282. package/dist/networking/subnet.d.mts +49 -0
  283. package/dist/networking/subnet.mjs +89 -0
  284. package/dist/networking/tcp-reliability.d.mts +24 -0
  285. package/dist/networking/tcp-reliability.mjs +38 -0
  286. package/dist/networking/topology/contract.d.mts +123 -0
  287. package/dist/networking/topology/index.d.mts +4 -0
  288. package/dist/networking/topology/index.mjs +4 -0
  289. package/dist/networking/topology/presets.d.mts +7 -0
  290. package/dist/networking/topology/presets.mjs +302 -0
  291. package/dist/networking/topology/simulation.d.mts +8 -0
  292. package/dist/networking/topology/simulation.mjs +179 -0
  293. package/dist/networking/wireless.d.mts +11 -0
  294. package/dist/networking/wireless.mjs +17 -0
  295. package/dist/optics/imaging.d.mts +218 -0
  296. package/dist/optics/imaging.mjs +276 -0
  297. package/dist/optics/index.d.mts +7 -0
  298. package/dist/optics/index.mjs +8 -0
  299. package/dist/optics/laws.d.mts +70 -0
  300. package/dist/optics/laws.mjs +195 -0
  301. package/dist/optics/prism.d.mts +148 -0
  302. package/dist/optics/prism.mjs +197 -0
  303. package/dist/optics/refraction.d.mts +201 -0
  304. package/dist/optics/refraction.mjs +270 -0
  305. package/dist/optics/wave-optics.d.mts +171 -0
  306. package/dist/optics/wave-optics.mjs +259 -0
  307. package/dist/physics/ac/index.d.mts +183 -0
  308. package/dist/physics/ac/index.mjs +203 -0
  309. package/dist/physics/dynamics/forces.d.mts +98 -0
  310. package/dist/physics/dynamics/forces.mjs +153 -0
  311. package/dist/physics/dynamics/friction.d.mts +76 -0
  312. package/dist/physics/dynamics/friction.mjs +119 -0
  313. package/dist/physics/dynamics/system.d.mts +68 -0
  314. package/dist/physics/dynamics/system.mjs +125 -0
  315. package/dist/physics/electrostatics/index.d.mts +169 -0
  316. package/dist/physics/electrostatics/index.mjs +249 -0
  317. package/dist/physics/energy/centre-of-mass.d.mts +115 -0
  318. package/dist/physics/energy/centre-of-mass.mjs +180 -0
  319. package/dist/physics/energy/conservation.d.mts +81 -0
  320. package/dist/physics/energy/conservation.mjs +129 -0
  321. package/dist/physics/energy/power.d.mts +90 -0
  322. package/dist/physics/energy/power.mjs +167 -0
  323. package/dist/physics/energy/spring.d.mts +73 -0
  324. package/dist/physics/energy/spring.mjs +129 -0
  325. package/dist/physics/energy/store.d.mts +63 -0
  326. package/dist/physics/energy/store.mjs +108 -0
  327. package/dist/physics/energy/theorem.d.mts +65 -0
  328. package/dist/physics/energy/theorem.mjs +113 -0
  329. package/dist/physics/energy/work.d.mts +114 -0
  330. package/dist/physics/energy/work.mjs +219 -0
  331. package/dist/physics/gravitation/body.d.mts +85 -0
  332. package/dist/physics/gravitation/body.mjs +168 -0
  333. package/dist/physics/gravitation/kepler.d.mts +127 -0
  334. package/dist/physics/gravitation/kepler.mjs +216 -0
  335. package/dist/physics/gravitation/law.d.mts +117 -0
  336. package/dist/physics/gravitation/law.mjs +175 -0
  337. package/dist/physics/gravitation/orbit.d.mts +119 -0
  338. package/dist/physics/gravitation/orbit.mjs +202 -0
  339. package/dist/physics/gravitation/potential.d.mts +114 -0
  340. package/dist/physics/gravitation/potential.mjs +202 -0
  341. package/dist/physics/gravitation/variation.d.mts +97 -0
  342. package/dist/physics/gravitation/variation.mjs +175 -0
  343. package/dist/physics/index.d.mts +35 -0
  344. package/dist/physics/index.mjs +36 -0
  345. package/dist/physics/integral-sweep.d.mts +63 -0
  346. package/dist/physics/integral-sweep.mjs +126 -0
  347. package/dist/physics/kinematics/equations.d.mts +47 -0
  348. package/dist/physics/kinematics/equations.mjs +126 -0
  349. package/dist/physics/kinematics/free-fall.d.mts +53 -0
  350. package/dist/physics/kinematics/free-fall.mjs +71 -0
  351. package/dist/physics/kinematics/given.d.mts +16 -0
  352. package/dist/physics/kinematics/given.mjs +55 -0
  353. package/dist/physics/kinematics/roots.d.mts +41 -0
  354. package/dist/physics/kinematics/roots.mjs +72 -0
  355. package/dist/physics/kinematics/solve.d.mts +52 -0
  356. package/dist/physics/kinematics/solve.mjs +172 -0
  357. package/dist/physics/magnetism/biot-savart.d.mts +161 -0
  358. package/dist/physics/magnetism/biot-savart.mjs +353 -0
  359. package/dist/physics/magnetism/flux.d.mts +94 -0
  360. package/dist/physics/magnetism/flux.mjs +313 -0
  361. package/dist/physics/magnetism/geomagnetism.d.mts +151 -0
  362. package/dist/physics/magnetism/geomagnetism.mjs +184 -0
  363. package/dist/physics/magnetism/index.d.mts +12 -0
  364. package/dist/physics/magnetism/index.mjs +74 -0
  365. package/dist/physics/magnetism/lorentz.d.mts +28 -0
  366. package/dist/physics/magnetism/lorentz.mjs +88 -0
  367. package/dist/physics/magnetism/magnetic-force.d.mts +102 -0
  368. package/dist/physics/magnetism/magnetic-force.mjs +169 -0
  369. package/dist/physics/momentum/collide.d.mts +77 -0
  370. package/dist/physics/momentum/collide.mjs +115 -0
  371. package/dist/physics/momentum/impulse.d.mts +89 -0
  372. package/dist/physics/momentum/impulse.mjs +159 -0
  373. package/dist/physics/momentum/planar.d.mts +60 -0
  374. package/dist/physics/momentum/planar.mjs +110 -0
  375. package/dist/physics/projectile.d.mts +107 -0
  376. package/dist/physics/projectile.mjs +185 -0
  377. package/dist/physics/rotation/angular.d.mts +85 -0
  378. package/dist/physics/rotation/angular.mjs +130 -0
  379. package/dist/physics/rotation/circular.d.mts +79 -0
  380. package/dist/physics/rotation/circular.mjs +131 -0
  381. package/dist/physics/rotation/inertia.d.mts +164 -0
  382. package/dist/physics/rotation/inertia.mjs +332 -0
  383. package/dist/physics/rotation/torque.d.mts +65 -0
  384. package/dist/physics/rotation/torque.mjs +134 -0
  385. package/dist/physics/vectors.d.mts +64 -0
  386. package/dist/physics/vectors.mjs +114 -0
  387. package/dist/quantity/index.d.mts +119 -0
  388. package/dist/quantity/index.mjs +417 -0
  389. package/dist/relation/derive.d.mts +74 -0
  390. package/dist/relation/derive.mjs +73 -0
  391. package/dist/relation/index.d.mts +56 -0
  392. package/dist/relation/index.mjs +234 -0
  393. package/dist/scene/evaluators.mjs +1 -1
  394. package/dist/sim/thermal.mjs +45 -20
  395. package/dist/thermo/calorimetry.d.mts +207 -0
  396. package/dist/thermo/calorimetry.mjs +345 -0
  397. package/dist/thermo/cycles.d.mts +142 -0
  398. package/dist/thermo/cycles.mjs +256 -0
  399. package/dist/thermo/entropy.d.mts +87 -0
  400. package/dist/thermo/entropy.mjs +140 -0
  401. package/dist/thermo/expansion.d.mts +130 -0
  402. package/dist/thermo/expansion.mjs +178 -0
  403. package/dist/thermo/gas.d.mts +197 -0
  404. package/dist/thermo/gas.mjs +279 -0
  405. package/dist/thermo/heat-transfer.d.mts +164 -0
  406. package/dist/thermo/heat-transfer.mjs +217 -0
  407. package/dist/thermo/index.d.mts +9 -82
  408. package/dist/thermo/index.mjs +9 -132
  409. package/dist/thermo/processes.d.mts +95 -0
  410. package/dist/thermo/processes.mjs +154 -0
  411. package/dist/thermo/temperature.d.mts +174 -0
  412. package/dist/thermo/temperature.mjs +236 -0
  413. package/dist/waves/damping.d.mts +224 -0
  414. package/dist/waves/damping.mjs +317 -0
  415. package/dist/waves/doppler.d.mts +72 -0
  416. package/dist/waves/doppler.mjs +125 -0
  417. package/dist/waves/index.d.mts +10 -0
  418. package/dist/waves/index.mjs +10 -0
  419. package/dist/waves/pendulum.d.mts +130 -0
  420. package/dist/waves/pendulum.mjs +211 -0
  421. package/dist/waves/pitch.d.mts +125 -0
  422. package/dist/waves/pitch.mjs +158 -0
  423. package/dist/waves/shm.d.mts +170 -0
  424. package/dist/waves/shm.mjs +279 -0
  425. package/dist/waves/springs.d.mts +103 -0
  426. package/dist/waves/springs.mjs +176 -0
  427. package/dist/waves/superposition.d.mts +124 -0
  428. package/dist/waves/superposition.mjs +196 -0
  429. package/dist/waves/wave.d.mts +154 -0
  430. package/dist/waves/wave.mjs +178 -0
  431. package/package.json +74 -2
@@ -1,43 +1,14 @@
1
1
  import { compileNode, evaluate, freeVars } from "./ast.mjs";
2
2
  import { parse } from "./parse.mjs";
3
+ import { isolate, occurrences } from "./rearrange.mjs";
3
4
  import { definiteIntegral, differentiate, integrate, simplify } from "./calculus.mjs";
4
5
  import { compile } from "./compile.mjs";
5
6
  import { toLatex } from "./latex.mjs";
7
+ import { compileExpr } from "./expr.mjs";
8
+ import { complex_exports } from "./complex.mjs";
9
+ import { allRoots, deflate, degree, deriv, evalC, evalPoly, factorTex, fromAst, polyRoots, polyTex, poly_exports, solveEquation, trim } from "./poly.mjs";
10
+ import { polyCoeffs, solutionTex, solvePoly } from "./solve.mjs";
11
+ import { areaBetween, intersections, normalAt, quadrature, roots, tangentAt } from "./analysis.mjs";
12
+ import { checkAnswer, checkExpression, checkNumber, normalizeMathInput, parseValue } from "./answer-check.mjs";
6
13
 
7
- //#region src/math/index.ts
8
- /**
9
- * expr, a tiny, safe, dependency-free symbolic math engine.
10
- *
11
- * Pipeline: `tokenize → parse (AST) → evaluate`. On top of the AST it offers
12
- * exact `differentiate`, `simplify`, and `toLatex`, so the same typed formula
13
- * can be plotted, differentiated for an exact tangent, and rendered beautifully.
14
- * No `eval`/`new Function`.
15
- *
16
- * `compileExpr(src)` is the stable, simple entry point (returns a fast `fn` plus
17
- * the free `vars` and the parsed `ast`); the lower-level pieces are exported for
18
- * widgets that need the tree (derivative explorers, LaTeX labels, step-by-step).
19
- *
20
- * Supports: numbers (incl. `1.5e3`), variable `x` + named params, constants
21
- * (`pi`/`e`/`tau`), operators `+ - * / % ^` (^ right-assoc) and unary minus,
22
- * implicit multiplication (`2x`, `3sin(x)`), and functions `sin cos tan cot sec
23
- * csc asin acos atan sinh cosh tanh sqrt cbrt abs exp ln log log2 log10 floor
24
- * ceil round sign` (+ 2-arg `pow atan2 min max mod hypot`).
25
- */
26
- /** Compile a formula string. Returns `{ fn, vars, ast }` or `{ error }`, never throws. */
27
- function compileExpr(src) {
28
- if (!src || !src.trim()) return { error: "Empty expression" };
29
- let ast;
30
- try {
31
- ast = parse(src);
32
- } catch (e) {
33
- return { error: e instanceof Error ? e.message : "Parse error" };
34
- }
35
- return {
36
- fn: (scope) => evaluate(ast, scope),
37
- vars: [...freeVars(ast)],
38
- ast
39
- };
40
- }
41
-
42
- //#endregion
43
- export { compile, compileExpr, compileNode, definiteIntegral, differentiate, evaluate, freeVars, integrate, parse, simplify, toLatex };
14
+ export { allRoots, areaBetween, checkAnswer, checkExpression, checkNumber, compile, compileExpr, compileNode, complex_exports as complex, definiteIntegral, deflate, degree, deriv, differentiate, evalC, evalPoly, evaluate, factorTex, freeVars, fromAst, integrate, intersections, isolate, normalAt, normalizeMathInput, occurrences, parse, parseValue, poly_exports as poly, polyCoeffs, polyRoots, polyTex, quadrature, roots, simplify, solutionTex, solveEquation, solvePoly, tangentAt, toLatex, trim };
@@ -81,8 +81,9 @@ function texP(node) {
81
81
  prec: 2
82
82
  };
83
83
  const sep = node.right.type === "num" ? " \\cdot " : "";
84
+ const right = node.right.type === "neg" ? `\\left(${texP(node.right).s}\\right)` : wrap(node.right, 2);
84
85
  return {
85
- s: `${wrap(node.left, 2)}${sep}${wrap(node.right, 2)}`,
86
+ s: `${wrap(node.left, 2)}${sep}${right}`,
86
87
  prec: 2
87
88
  };
88
89
  }
@@ -1,6 +1,6 @@
1
1
  import { arityOf } from "./defs.mjs";
2
- import { tokenize } from "./tokenize.mjs";
3
2
  import { bin, call, neg, num, variable } from "./ast.mjs";
3
+ import { tokenize } from "./tokenize.mjs";
4
4
 
5
5
  //#region src/math/parse.ts
6
6
  /**
@@ -0,0 +1,55 @@
1
+ import { Node } from "./ast.mjs";
2
+ import { Complex } from "./complex.mjs";
3
+
4
+ //#region src/math/poly.d.ts
5
+ declare namespace poly_d_exports {
6
+ export { Poly, PolyRoots, add, allRoots, deflate, degree, deriv, evalC, evalPoly, factorTex, fromAst, mul, polyRoots, polyTex, solveEquation, trim };
7
+ }
8
+ type Poly = number[];
9
+ declare const trim: (p: Poly) => Poly;
10
+ declare const degree: (p: Poly) => number;
11
+ /** Horner evaluation (real). */
12
+ declare function evalPoly(p: Poly, x: number): number;
13
+ /** Horner evaluation (complex). */
14
+ declare function evalC(p: Poly, z: Complex): Complex;
15
+ /** Derivative polynomial. */
16
+ declare const deriv: (p: Poly) => Poly;
17
+ declare function add(a: Poly, b: Poly): Poly;
18
+ declare function mul(a: Poly, b: Poly): Poly;
19
+ /** Synthetic division of p by (x − r); returns the quotient (assumes r is a root,
20
+ * i.e. drops the remainder). The "divide out a found factor" step. */
21
+ declare function deflate(p: Poly, r: number): Poly;
22
+ /** LaTeX of a polynomial in descending order, e.g. [−6,11,−6,1] → "x^{3} - 6x^{2} + 11x - 6". */
23
+ declare function polyTex(p0: Poly, x?: string): string;
24
+ /** Coefficients of `node` as a polynomial in `x` (other vars from `params`), or
25
+ * null if it isn't a polynomial in x (sin(x), 1/x, fractional power, …). */
26
+ declare function fromAst(node: Node, x?: string, params?: Record<string, number>): Poly | null;
27
+ /**
28
+ * All complex roots of `p` via Durand–Kerner simultaneous iteration (then snapped).
29
+ * For a degree-n polynomial returns n roots; real roots come back with im = 0.
30
+ */
31
+ declare function allRoots(p0: Poly): Complex[];
32
+ interface PolyRoots {
33
+ poly: Poly;
34
+ degree: number;
35
+ roots: Complex[];
36
+ realRoots: number[];
37
+ }
38
+ /**
39
+ * Solve p = 0 for ALL roots (any degree up to MAX_DEG). null if degenerate.
40
+ *
41
+ * Named `polyRoots` because `solve` alone said nothing about which roots of what: labs exported
42
+ * three of them (closed-form polynomial, these numeric ones, and the circuit solver).
43
+ */
44
+ declare function polyRoots(p0: Poly): PolyRoots | null;
45
+ /** Solve an expression-AST equation `expr = 0` for x, any degree. null if not a
46
+ * polynomial in x. (Linear/quadratic also flow through here, exactly.) */
47
+ declare function solveEquation(node: Node, x?: string, params?: Record<string, number>): PolyRoots | null;
48
+ /**
49
+ * Factored form of the polynomial over the reals: leading coefficient × linear
50
+ * factors (real roots, with multiplicity) × irreducible quadratics (complex
51
+ * conjugate pairs). e.g. x³−6x²+11x−6 → "(x − 1)(x − 2)(x − 3)".
52
+ */
53
+ declare function factorTex(p0: Poly, x?: string): string;
54
+ //#endregion
55
+ export { Poly, PolyRoots, allRoots, deflate, degree, deriv, evalC, evalPoly, factorTex, fromAst, polyRoots, polyTex, poly_d_exports, solveEquation, trim };
@@ -0,0 +1,273 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.mjs";
2
+ import { evaluate } from "./ast.mjs";
3
+ import { ONE, ZERO, abs, add as add$1, cx, div, fromPolar, isFiniteC, mul as mul$1, sub } from "./complex.mjs";
4
+
5
+ //#region src/math/poly.ts
6
+ /**
7
+ * Polynomial core, the canonical single-variable polynomial engine. The clean,
8
+ * focused alternative to bolting on a heavy general CAS (Algebrite / nerdamer):
9
+ * for the polynomial algebra school actually needs — expand, evaluate,
10
+ * differentiate, FACTOR, and SOLVE any degree — a normalised coefficient form
11
+ * makes everything fall out.
12
+ *
13
+ * • a Poly is just `number[]` ascending: [a0, a1, …, an] = a0 + a1 x + … + an xⁿ.
14
+ * • roots of ANY degree via DURAND–KERNER (Weierstrass) simultaneous iteration,
15
+ * reusing the complex kernel — all n complex roots at once, then snapped to
16
+ * exact rationals where they're clearly nice (so 2, ½, −3 print exact, not
17
+ * 1.9999999).
18
+ * • factored form is read straight off the cleaned roots (real → (x−r);
19
+ * complex pair → an irreducible real quadratic).
20
+ *
21
+ * Numerically safe: Durand–Kerner is capped at MAX_ITER and falls back gracefully;
22
+ * coefficient arrays are trimmed; no overflow paths (the complex kernel guards div).
23
+ */
24
+ var poly_exports = /* @__PURE__ */ __exportAll({
25
+ add: () => add,
26
+ allRoots: () => allRoots,
27
+ deflate: () => deflate,
28
+ degree: () => degree,
29
+ deriv: () => deriv,
30
+ evalC: () => evalC,
31
+ evalPoly: () => evalPoly,
32
+ factorTex: () => factorTex,
33
+ fromAst: () => fromAst,
34
+ mul: () => mul,
35
+ polyRoots: () => polyRoots,
36
+ polyTex: () => polyTex,
37
+ solveEquation: () => solveEquation,
38
+ trim: () => trim
39
+ });
40
+ const EPS = 1e-9;
41
+ const MAX_ITER = 300;
42
+ const MAX_DEG = 8;
43
+ const trim = (p) => {
44
+ let n = p.length;
45
+ while (n > 1 && Math.abs(p[n - 1]) < 1e-12) n--;
46
+ return p.slice(0, n);
47
+ };
48
+ const degree = (p) => trim(p).length - 1;
49
+ /** Horner evaluation (real). */
50
+ function evalPoly(p, x) {
51
+ let s = 0;
52
+ for (let i = p.length - 1; i >= 0; i--) s = s * x + (p[i] ?? 0);
53
+ return s;
54
+ }
55
+ /** Horner evaluation (complex). */
56
+ function evalC(p, z) {
57
+ let s = ZERO;
58
+ for (let i = p.length - 1; i >= 0; i--) s = add$1(mul$1(s, z), cx(p[i] ?? 0));
59
+ return s;
60
+ }
61
+ /** Derivative polynomial. */
62
+ const deriv = (p) => trim(p.slice(1).map((c, i) => c * (i + 1)));
63
+ function add(a, b) {
64
+ const n = Math.max(a.length, b.length), o = [];
65
+ for (let i = 0; i < n; i++) o.push((a[i] ?? 0) + (b[i] ?? 0));
66
+ return trim(o);
67
+ }
68
+ function mul(a, b) {
69
+ const o = new Array(a.length + b.length - 1).fill(0);
70
+ for (let i = 0; i < a.length; i++) for (let j = 0; j < b.length; j++) o[i + j] += a[i] * b[j];
71
+ return trim(o);
72
+ }
73
+ /** Synthetic division of p by (x − r); returns the quotient (assumes r is a root,
74
+ * i.e. drops the remainder). The "divide out a found factor" step. */
75
+ function deflate(p, r) {
76
+ const n = p.length - 1;
77
+ if (n < 1) return [0];
78
+ const q = new Array(n).fill(0);
79
+ q[n - 1] = p[n];
80
+ for (let k = n - 2; k >= 0; k--) q[k] = p[k + 1] + r * q[k + 1];
81
+ return trim(q);
82
+ }
83
+ const tnum = (n) => {
84
+ const r = Math.round(n * 1e6) / 1e6;
85
+ return (Object.is(r, -0) ? 0 : r).toString();
86
+ };
87
+ /** LaTeX of a polynomial in descending order, e.g. [−6,11,−6,1] → "x^{3} - 6x^{2} + 11x - 6". */
88
+ function polyTex(p0, x = "x") {
89
+ const p = trim(p0);
90
+ let out = "";
91
+ for (let d = p.length - 1; d >= 0; d--) {
92
+ const c = p[d];
93
+ if (c === 0) continue;
94
+ const mag = Math.abs(c);
95
+ const t = `${d === 0 ? tnum(mag) : mag === 1 ? "" : tnum(mag)}${d === 0 ? "" : d === 1 ? x : `${x}^{${d}}`}`;
96
+ out += out === "" ? c < 0 ? `-${t}` : t : c < 0 ? ` - ${t}` : ` + ${t}`;
97
+ }
98
+ return out || "0";
99
+ }
100
+ function hasVar(node, x) {
101
+ switch (node.type) {
102
+ case "var": return node.name === x;
103
+ case "neg": return hasVar(node.arg, x);
104
+ case "binary": return hasVar(node.left, x) || hasVar(node.right, x);
105
+ case "call": return node.args.some((a) => hasVar(a, x));
106
+ default: return false;
107
+ }
108
+ }
109
+ /** Coefficients of `node` as a polynomial in `x` (other vars from `params`), or
110
+ * null if it isn't a polynomial in x (sin(x), 1/x, fractional power, …). */
111
+ function fromAst(node, x = "x", params = {}) {
112
+ if (!hasVar(node, x)) {
113
+ const v = evaluate(node, params);
114
+ return Number.isFinite(v) ? [v] : null;
115
+ }
116
+ switch (node.type) {
117
+ case "var": return [0, 1];
118
+ case "neg": {
119
+ const c = fromAst(node.arg, x, params);
120
+ return c && c.map((k) => -k);
121
+ }
122
+ case "binary": {
123
+ const { op, left, right } = node;
124
+ const L = fromAst(left, x, params);
125
+ if (!L) return null;
126
+ if (op === "+") {
127
+ const R = fromAst(right, x, params);
128
+ return R && add(L, R);
129
+ }
130
+ if (op === "-") {
131
+ const R = fromAst(right, x, params);
132
+ return R && add(L, R.map((k) => -k));
133
+ }
134
+ if (op === "*") {
135
+ const R = fromAst(right, x, params);
136
+ return R && mul(L, R);
137
+ }
138
+ if (op === "/") {
139
+ if (hasVar(right, x)) return null;
140
+ const d = evaluate(right, params);
141
+ return Number.isFinite(d) && d !== 0 ? L.map((k) => k / d) : null;
142
+ }
143
+ if (op === "^") {
144
+ if (hasVar(right, x)) return null;
145
+ const n = evaluate(right, params);
146
+ if (!Number.isInteger(n) || n < 0 || n > MAX_DEG) return null;
147
+ let acc = [1];
148
+ for (let i = 0; i < n; i++) acc = mul(acc, L);
149
+ return acc;
150
+ }
151
+ return null;
152
+ }
153
+ default: return null;
154
+ }
155
+ }
156
+ /** Snap a near-rational real to its exact value (denominators 1..12), else itself. */
157
+ function snapReal(r) {
158
+ for (const d of [
159
+ 1,
160
+ 2,
161
+ 3,
162
+ 4,
163
+ 5,
164
+ 6,
165
+ 8,
166
+ 10,
167
+ 12
168
+ ]) {
169
+ const n = Math.round(r * d);
170
+ if (Math.abs(r * d - n) < 1e-7) {
171
+ const v = n / d;
172
+ return Object.is(v, -0) ? 0 : v;
173
+ }
174
+ }
175
+ return Math.round(r * 1e9) / 1e9;
176
+ }
177
+ const snap = (z) => Math.abs(z.im) < 1e-7 ? {
178
+ re: snapReal(z.re),
179
+ im: 0
180
+ } : {
181
+ re: snapReal(z.re),
182
+ im: snapReal(z.im)
183
+ };
184
+ /**
185
+ * All complex roots of `p` via Durand–Kerner simultaneous iteration (then snapped).
186
+ * For a degree-n polynomial returns n roots; real roots come back with im = 0.
187
+ */
188
+ function allRoots(p0) {
189
+ const p = trim(p0);
190
+ const n = p.length - 1;
191
+ if (n <= 0) return [];
192
+ const lead = p[n];
193
+ const m = p.map((c) => c / lead);
194
+ let z = Array.from({ length: n }, (_, k) => fromPolar(1 + .1 * k / n, 2 * Math.PI * k / n + .6));
195
+ for (let it = 0; it < MAX_ITER; it++) {
196
+ let maxDelta = 0;
197
+ z = z.map((zi, i) => {
198
+ let denom = ONE;
199
+ for (let j = 0; j < n; j++) if (j !== i) denom = mul$1(denom, sub(zi, z[j]));
200
+ const corr = div(evalC(m, zi), denom);
201
+ if (!isFiniteC(corr)) return zi;
202
+ maxDelta = Math.max(maxDelta, abs(corr));
203
+ return sub(zi, corr);
204
+ });
205
+ if (maxDelta < EPS) break;
206
+ }
207
+ const roots = z.map(snap);
208
+ roots.sort((a, b) => a.im === 0 && b.im === 0 ? a.re - b.re : a.im === 0 ? -1 : b.im === 0 ? 1 : a.re - b.re || a.im - b.im);
209
+ return roots;
210
+ }
211
+ /**
212
+ * Solve p = 0 for ALL roots (any degree up to MAX_DEG). null if degenerate.
213
+ *
214
+ * Named `polyRoots` because `solve` alone said nothing about which roots of what: labs exported
215
+ * three of them (closed-form polynomial, these numeric ones, and the circuit solver).
216
+ */
217
+ function polyRoots(p0) {
218
+ const p = trim(p0);
219
+ const d = p.length - 1;
220
+ if (d < 1) return null;
221
+ const roots = allRoots(p);
222
+ return {
223
+ poly: p,
224
+ degree: d,
225
+ roots,
226
+ realRoots: roots.filter((r) => r.im === 0).map((r) => r.re)
227
+ };
228
+ }
229
+ /** Solve an expression-AST equation `expr = 0` for x, any degree. null if not a
230
+ * polynomial in x. (Linear/quadratic also flow through here, exactly.) */
231
+ function solveEquation(node, x = "x", params = {}) {
232
+ const p = fromAst(node, x, params);
233
+ return p ? polyRoots(p) : null;
234
+ }
235
+ const fnum = (n) => {
236
+ const r = Math.round(n * 1e6) / 1e6;
237
+ return (Object.is(r, -0) ? 0 : r).toString().replace(/^-/, "−");
238
+ };
239
+ /** "(x − r)" with the sign tucked in, and "(x − 0)" → "x". */
240
+ const linTex = (r, x) => r === 0 ? x : `(${x} ${r < 0 ? "+" : "−"} ${fnum(Math.abs(r))})`;
241
+ /**
242
+ * Factored form of the polynomial over the reals: leading coefficient × linear
243
+ * factors (real roots, with multiplicity) × irreducible quadratics (complex
244
+ * conjugate pairs). e.g. x³−6x²+11x−6 → "(x − 1)(x − 2)(x − 3)".
245
+ */
246
+ function factorTex(p0, x = "x") {
247
+ const p = trim(p0);
248
+ const lead = p[p.length - 1] ?? 1;
249
+ const sol = polyRoots(p);
250
+ if (!sol) return fnum(p[0] ?? 0);
251
+ const used = new Array(sol.roots.length).fill(false);
252
+ const parts = [];
253
+ for (let i = 0; i < sol.roots.length; i++) {
254
+ if (used[i]) continue;
255
+ const z = sol.roots[i];
256
+ if (z.im === 0) {
257
+ used[i] = true;
258
+ parts.push(linTex(z.re, x));
259
+ continue;
260
+ }
261
+ used[i] = true;
262
+ const j = sol.roots.findIndex((w, k) => !used[k] && Math.abs(w.re - z.re) < 1e-6 && Math.abs(w.im + z.im) < 1e-6);
263
+ if (j >= 0) used[j] = true;
264
+ const b2 = z.re * z.re + z.im * z.im, two = 2 * z.re;
265
+ const mid = Math.abs(two) < 1e-9 ? "" : ` ${two < 0 ? "+" : "−"} ${fnum(Math.abs(two))}${x}`;
266
+ parts.push(`(${x}^2${mid} ${b2 < 0 ? "−" : "+"} ${fnum(Math.abs(b2))})`);
267
+ }
268
+ const lc = Math.abs(lead - 1) < 1e-9 ? "" : `${fnum(lead)}\\,`;
269
+ return parts.length ? `${lc}${parts.join("")}` : fnum(lead);
270
+ }
271
+
272
+ //#endregion
273
+ export { allRoots, deflate, degree, deriv, evalC, evalPoly, factorTex, fromAst, polyRoots, polyTex, poly_exports, solveEquation, trim };
@@ -0,0 +1,14 @@
1
+ import { Node } from "./ast.mjs";
2
+
3
+ //#region src/math/rearrange.d.ts
4
+ /** How many times a variable appears in an expression. */
5
+ declare function occurrences(node: Node, name: string): number;
6
+ /**
7
+ * Rearrange `left = right` into `target = <expression>`, and return that expression.
8
+ *
9
+ * Throws when the target appears in an exponent, inside a function with no inverse here, or more
10
+ * than once. Each of those is a real limit of isolation rather than a gap to paper over.
11
+ */
12
+ declare function isolate(left: Node, right: Node, target: string): Node;
13
+ //#endregion
14
+ export { isolate, occurrences };
@@ -0,0 +1,125 @@
1
+ //#region src/math/rearrange.ts
2
+ /** How many times a variable appears in an expression. */
3
+ function occurrences(node, name) {
4
+ switch (node.type) {
5
+ case "var": return node.name === name ? 1 : 0;
6
+ case "neg": return occurrences(node.arg, name);
7
+ case "binary": return occurrences(node.left, name) + occurrences(node.right, name);
8
+ case "call": return node.args.reduce((n, a) => n + occurrences(a, name), 0);
9
+ default: return 0;
10
+ }
11
+ }
12
+ const n = (value) => ({
13
+ type: "num",
14
+ value
15
+ });
16
+ const b = (op, left, right) => ({
17
+ type: "binary",
18
+ op,
19
+ left,
20
+ right
21
+ });
22
+ const fn = (name, ...args) => ({
23
+ type: "call",
24
+ fn: name,
25
+ args
26
+ });
27
+ /**
28
+ * Rearrange `left = right` into `target = <expression>`, and return that expression.
29
+ *
30
+ * Throws when the target appears in an exponent, inside a function with no inverse here, or more
31
+ * than once. Each of those is a real limit of isolation rather than a gap to paper over.
32
+ */
33
+ function isolate(left, right, target) {
34
+ let lhs = left;
35
+ let rhs = right;
36
+ for (let guard = 0; guard < 64; guard++) {
37
+ if (occurrences(lhs, target) === 0) [lhs, rhs] = [rhs, lhs];
38
+ if (lhs.type === "var" && lhs.name === target) return rhs;
39
+ if (lhs.type === "neg") {
40
+ lhs = lhs.arg;
41
+ rhs = {
42
+ type: "neg",
43
+ arg: rhs
44
+ };
45
+ continue;
46
+ }
47
+ if (lhs.type === "binary") {
48
+ const inLeft = occurrences(lhs.left, target) > 0;
49
+ const keep = inLeft ? lhs.left : lhs.right;
50
+ const move = inLeft ? lhs.right : lhs.left;
51
+ switch (lhs.op) {
52
+ case "+":
53
+ rhs = b("-", rhs, move);
54
+ break;
55
+ case "-":
56
+ rhs = inLeft ? b("+", rhs, move) : b("-", move, rhs);
57
+ break;
58
+ case "*":
59
+ rhs = b("/", rhs, move);
60
+ break;
61
+ case "/":
62
+ rhs = inLeft ? b("*", rhs, move) : b("/", move, rhs);
63
+ break;
64
+ case "^":
65
+ if (!inLeft) throw new Error(`Cannot solve for "${target}": it appears in an exponent. Declare a second relation.`);
66
+ rhs = b("^", rhs, b("/", n(1), move));
67
+ break;
68
+ default: throw new Error(`Cannot solve for "${target}" through the "${lhs.op}" operator.`);
69
+ }
70
+ lhs = keep;
71
+ continue;
72
+ }
73
+ if (lhs.type === "call") {
74
+ const arg = lhs.args[0];
75
+ if (!arg) throw new Error(`Cannot solve for "${target}" through ${lhs.fn}()`);
76
+ switch (lhs.fn) {
77
+ case "log10":
78
+ case "log":
79
+ rhs = b("^", n(10), rhs);
80
+ break;
81
+ case "ln":
82
+ rhs = fn("exp", rhs);
83
+ break;
84
+ case "exp":
85
+ rhs = fn("ln", rhs);
86
+ break;
87
+ case "log2":
88
+ rhs = b("^", n(2), rhs);
89
+ break;
90
+ case "sqrt":
91
+ rhs = b("^", rhs, n(2));
92
+ break;
93
+ case "cbrt":
94
+ rhs = b("^", rhs, n(3));
95
+ break;
96
+ case "sin":
97
+ rhs = fn("asin", rhs);
98
+ break;
99
+ case "cos":
100
+ rhs = fn("acos", rhs);
101
+ break;
102
+ case "tan":
103
+ rhs = fn("atan", rhs);
104
+ break;
105
+ case "asin":
106
+ rhs = fn("sin", rhs);
107
+ break;
108
+ case "acos":
109
+ rhs = fn("cos", rhs);
110
+ break;
111
+ case "atan":
112
+ rhs = fn("tan", rhs);
113
+ break;
114
+ default: throw new Error(`Cannot invert ${lhs.fn}() to solve for "${target}".`);
115
+ }
116
+ lhs = arg;
117
+ continue;
118
+ }
119
+ throw new Error(`Cannot solve for "${target}" in this equation.`);
120
+ }
121
+ throw new Error(`Gave up isolating "${target}" (the equation nests too deeply).`);
122
+ }
123
+
124
+ //#endregion
125
+ export { isolate, occurrences };
@@ -0,0 +1,21 @@
1
+ import { Node } from "./ast.mjs";
2
+ import { Complex } from "./complex.mjs";
3
+ import { fromAst } from "./poly.mjs";
4
+
5
+ //#region src/math/solve.d.ts
6
+ /** Coefficients [a0, a1, …] of `node` as a polynomial in `x` (the canonical poly
7
+ * engine does the extraction). null if it isn't polynomial in x. */
8
+ declare const polyCoeffs: typeof fromAst;
9
+ interface PolySolution {
10
+ coeffs: number[];
11
+ degree: number;
12
+ roots: Complex[];
13
+ realRoots: number[];
14
+ discriminant?: number;
15
+ }
16
+ /** Solve `node` = 0 for x exactly (degree 1 or 2). null if not a usable polynomial. */
17
+ declare function solvePoly(node: Node, x?: string, params?: Record<string, number>): PolySolution | null;
18
+ /** "x = 2 or x = −2" (complex when needed), or "no real solutions" framing. */
19
+ declare function solutionTex(sol: PolySolution, x?: string): string;
20
+ //#endregion
21
+ export { PolySolution, polyCoeffs, solutionTex, solvePoly };
@@ -0,0 +1,75 @@
1
+ import { toStr } from "./complex.mjs";
2
+ import { fromAst, trim } from "./poly.mjs";
3
+
4
+ //#region src/math/solve.ts
5
+ const cleanNum = (n) => {
6
+ const r = Math.round(n * 1e9) / 1e9;
7
+ return Object.is(r, -0) ? 0 : r;
8
+ };
9
+ /** Coefficients [a0, a1, …] of `node` as a polynomial in `x` (the canonical poly
10
+ * engine does the extraction). null if it isn't polynomial in x. */
11
+ const polyCoeffs = fromAst;
12
+ /** Solve `node` = 0 for x exactly (degree 1 or 2). null if not a usable polynomial. */
13
+ function solvePoly(node, x = "x", params = {}) {
14
+ const raw = polyCoeffs(node, x, params);
15
+ if (!raw) return null;
16
+ const coeffs = trim(raw);
17
+ const degree = coeffs.length - 1;
18
+ if (degree === 1) {
19
+ const a0 = coeffs[0], a1 = coeffs[1];
20
+ const r = cleanNum(-a0 / a1);
21
+ return {
22
+ coeffs,
23
+ degree,
24
+ roots: [{
25
+ re: r,
26
+ im: 0
27
+ }],
28
+ realRoots: [r]
29
+ };
30
+ }
31
+ if (degree === 2) {
32
+ const c0 = coeffs[0], c1 = coeffs[1], c2 = coeffs[2];
33
+ const disc = c1 * c1 - 4 * c2 * c0;
34
+ const twoA = 2 * c2;
35
+ if (disc >= 0) {
36
+ const s = Math.sqrt(disc);
37
+ const real = [cleanNum((-c1 - s) / twoA), cleanNum((-c1 + s) / twoA)].sort((u, v) => u - v);
38
+ return {
39
+ coeffs,
40
+ degree,
41
+ discriminant: disc,
42
+ roots: real.map((r) => ({
43
+ re: r,
44
+ im: 0
45
+ })),
46
+ realRoots: real
47
+ };
48
+ }
49
+ const s = Math.sqrt(-disc), re = cleanNum(-c1 / twoA), im = cleanNum(s / twoA);
50
+ return {
51
+ coeffs,
52
+ degree,
53
+ discriminant: disc,
54
+ roots: [{
55
+ re,
56
+ im: -im
57
+ }, {
58
+ re,
59
+ im
60
+ }],
61
+ realRoots: []
62
+ };
63
+ }
64
+ return null;
65
+ }
66
+ /** "x = 2 or x = −2" (complex when needed), or "no real solutions" framing. */
67
+ function solutionTex(sol, x = "x") {
68
+ if (sol.roots.length === 1) return `${x} = ${toStr(sol.roots[0])}`;
69
+ const [r1, r2] = sol.roots;
70
+ if (r1 && r2 && r1.re === r2.re && r1.im === r2.im) return `${x} = ${toStr(r1)} \\text{ (repeated)}`;
71
+ return `${x} = ${toStr(r1)} \\text{ or } ${x} = ${toStr(r2)}`;
72
+ }
73
+
74
+ //#endregion
75
+ export { polyCoeffs, solutionTex, solvePoly };
@@ -0,0 +1,26 @@
1
+ //#region src/networking/addressing.d.ts
2
+ type DhcpClientState = "new" | "renewing" | "expired";
3
+ interface DhcpLeaseOptions {
4
+ clientState: DhcpClientState;
5
+ serverAvailable: boolean;
6
+ requestedAddress?: string;
7
+ offeredAddress?: string;
8
+ leaseSeconds?: number;
9
+ }
10
+ interface DhcpLeaseResult {
11
+ messages: readonly ("DISCOVER" | "OFFER" | "REQUEST" | "ACK" | "NAK")[];
12
+ address: string | null;
13
+ usable: boolean;
14
+ leaseSeconds: number;
15
+ nextAction: "use-lease" | "retry-discovery" | "stop-and-discover";
16
+ }
17
+ /** Resolve one DHCP exchange. Rendering and timers belong to the consuming lab. */
18
+ declare function simulateDhcpLease({
19
+ clientState,
20
+ serverAvailable,
21
+ requestedAddress,
22
+ offeredAddress,
23
+ leaseSeconds
24
+ }: DhcpLeaseOptions): DhcpLeaseResult;
25
+ //#endregion
26
+ export { DhcpClientState, DhcpLeaseOptions, DhcpLeaseResult, simulateDhcpLease };