@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
@@ -106,14 +106,25 @@ function freeVarsHas(node, x) {
106
106
  * `differentiate` rather than matching `a*x+b` by shape means `(3-2x)^5` and `(-2x+3)^5` and
107
107
  * `3-2*x` all work without three separate matchers.
108
108
  */
109
+ /**
110
+ * The `a` in `u = ax + b`, as a NODE, or null when `u` is not linear in `x`.
111
+ *
112
+ * It used to demand a numeric `a`, which made `sin(2x)` integrable and `sin(ωt)` not. That is the
113
+ * wrong line to draw for physics: a coefficient that is a symbol is still a constant with respect
114
+ * to the integration variable, and `exp(-λt)`, `sin(ωt)` and `cos(kx)` are the shape of half the
115
+ * integrals in waves, decay and alternating current. The test is "does d/dx vanish under further
116
+ * differentiation", not "is it a literal number".
117
+ */
109
118
  function linearFactor(u, x) {
110
119
  const d = differentiate(u, x);
111
120
  if (!d) return null;
112
121
  const s = simplify(d);
113
- return s.type === "num" && s.value !== 0 ? s.value : null;
122
+ if (freeVarsHas(s, x)) return null;
123
+ if (s.type === "num" && s.value === 0) return null;
124
+ return s;
114
125
  }
115
- /** Divide by a constant, without emitting the noise of `expr / 1`. */
116
- const overConst = (node, a) => a === 1 ? node : div(node, num(a));
126
+ /** Divide by the linear coefficient, without emitting the noise of `expr / 1`. */
127
+ const overConst = (node, a) => a.type === "num" && a.value === 1 ? node : div(node, a);
117
128
  /**
118
129
  * Exact symbolic antiderivative with respect to `x`, or `null` when this engine cannot do it.
119
130
  *
@@ -121,12 +132,208 @@ const overConst = (node, a) => a === 1 ? node : div(node, num(a));
121
132
  * commonly dropped mark in the topic, so it belongs in the lesson's own working where a learner
122
133
  * has to write it, not silently bolted on by the engine.
123
134
  *
124
- * Covers the Cambridge P1/P3 toolkit: linearity, the power rule including the `1/x → ln|x|`
125
- * exception, and any of the above composed with a LINEAR inner function. Returns null for
126
- * integration by parts, by non-linear substitution, and partial fractions, so a caller can fall
127
- * back to the numerical `integrate` in `core/numeric` and show area rather than a wrong formula.
135
+ * Covers: linearity, the power rule including the `1/x → ln|x|` exception, any of those composed
136
+ * with a linear inner function whose coefficient may be a SYMBOL (`sin(ωt)`, `e^{-λt}`), and any
137
+ * polynomial that becomes one of the above after being multiplied out.
138
+ *
139
+ * Returns null for integration by parts (`x·eˣ`), non-linear substitution (`√(1−x²)`, `x/(1+x²)`)
140
+ * and trigonometric powers (`sin²x`). A caller that must produce a number regardless should fall
141
+ * back to `quadrature` in `analysis.ts` and say that it did, rather than show a wrong formula.
142
+ * `physics/integral-sweep` is the worked example of that pattern.
143
+ */
144
+ /**
145
+ * Squares and cubes of the trigonometric functions.
146
+ *
147
+ * These are not power-rule cases and they are not substitutions either. Each is a standard identity
148
+ * that turns the power into something already integrable:
149
+ *
150
+ * ∫sin²u du = u/2 − sin 2u / 4 the double-angle identity, cos 2u = 1 − 2sin²u
151
+ * ∫cos²u du = u/2 + sin 2u / 4
152
+ * ∫sin³u du = −cos u + cos³u / 3 writing sin³ as sin·(1 − cos²) and substituting
153
+ * ∫cos³u du = sin u − sin³u / 3
154
+ * ∫tan²u du = tan u − u from sec² = 1 + tan²
155
+ *
156
+ * WHY THESE FIVE AND NOT A GENERAL REDUCTION FORMULA. Squares are the ones that actually turn up:
157
+ * mean power in an alternating circuit is `∫sin²`, a spherical shell parameterised by angle is
158
+ * `∫sin³`, and between them they cover the syllabus. A general `sin^n` reduction is a much larger
159
+ * commitment for cases nobody sets, and returning null for `sin⁴` is honest.
160
+ *
161
+ * The inner function may be linear with a symbolic coefficient, so `sin²(ωt)` works, which is the
162
+ * form every alternating-current question is actually written in.
163
+ */
164
+ function integrateTrigPower(base, n, x) {
165
+ if (base.type !== "call" || base.args.length !== 1) return null;
166
+ const u = base.args[0];
167
+ if (!u) return null;
168
+ const a = linearFactor(u, x);
169
+ if (a === null) return null;
170
+ const sin = (arg) => call("sin", arg);
171
+ const cos = (arg) => call("cos", arg);
172
+ if (n === 2) {
173
+ if (base.fn === "sin") return overConst(sub(div(u, num(2)), div(sin(mul(num(2), u)), num(4))), a);
174
+ if (base.fn === "cos") return overConst(add(div(u, num(2)), div(sin(mul(num(2), u)), num(4))), a);
175
+ if (base.fn === "tan") return overConst(sub(call("tan", u), u), a);
176
+ return null;
177
+ }
178
+ if (n === 3) {
179
+ if (base.fn === "sin") return overConst(add(neg(cos(u)), div(pow(cos(u), num(3)), num(3))), a);
180
+ if (base.fn === "cos") return overConst(sub(sin(u), div(pow(sin(u), num(3)), num(3))), a);
181
+ return null;
182
+ }
183
+ return null;
184
+ }
185
+ /** How far `expand` will raise a sum before giving up. 8 covers anything at this level. */
186
+ const MAX_EXPAND_POWER = 8;
187
+ /**
188
+ * Multiply out products and integer powers of sums: `(R² − x²)²` becomes `R⁴ − 2R²x² + x⁴`.
189
+ *
190
+ * This exists because of a sharp edge in the integrator. It handles a sum term by term and a power
191
+ * of a LINEAR inner function, so `R⁴ − 2R²x² + x⁴` integrates and the identical `(R² − x²)²` does
192
+ * not. A student writing the moment of inertia of a sphere writes the second form, and being told
193
+ * it is not integrable while its expansion is would be indefensible.
194
+ *
195
+ * Not a general simplifier and not a normal form: it distributes and it raises, and it leaves
196
+ * everything else alone. `simplify` is still what tidies the result.
197
+ */
198
+ function expand(node) {
199
+ switch (node.type) {
200
+ case "neg": return neg(expand(node.arg));
201
+ case "call": return call(node.fn, ...node.args.map(expand));
202
+ case "binary": {
203
+ const left = expand(node.left);
204
+ const right = expand(node.right);
205
+ switch (node.op) {
206
+ case "+": return add(left, right);
207
+ case "-": return sub(left, right);
208
+ case "*": return distribute(left, right);
209
+ case "/": return isSum(left) ? expand(distributeOverSum(left, (t) => div(t, right))) : div(left, right);
210
+ case "^": {
211
+ const exponent = simplify(right);
212
+ if (!isSum(left) || exponent.type !== "num") return pow(left, right);
213
+ const n = exponent.value;
214
+ if (!Number.isInteger(n) || n < 2 || n > MAX_EXPAND_POWER) return pow(left, right);
215
+ let out = left;
216
+ for (let i = 1; i < n; i++) out = distribute(out, left);
217
+ return out;
218
+ }
219
+ default: return {
220
+ ...node,
221
+ left,
222
+ right
223
+ };
224
+ }
225
+ }
226
+ default: return node;
227
+ }
228
+ }
229
+ const isSum = (node) => node.type === "binary" && (node.op === "+" || node.op === "-");
230
+ /** Apply `f` to each term of a sum, preserving the signs. */
231
+ function distributeOverSum(sum, f) {
232
+ if (sum.type === "binary" && sum.op === "+") return add(distributeOverSum(sum.left, f), distributeOverSum(sum.right, f));
233
+ if (sum.type === "binary" && sum.op === "-") return sub(distributeOverSum(sum.left, f), distributeOverSum(sum.right, f));
234
+ return f(sum);
235
+ }
236
+ /** `(a + b)(c + d)` term by term, in whichever direction has a sum. */
237
+ function distribute(left, right) {
238
+ if (isSum(left)) return distributeOverSum(left, (term) => distribute(term, right));
239
+ if (isSum(right)) return distributeOverSum(right, (term) => distribute(left, term));
240
+ return mul(left, right);
241
+ }
242
+ /**
243
+ * A structural key for a node, so two occurrences of the same factor can be recognised.
244
+ *
245
+ * Deliberately crude and deliberately not a canonical form: `x*y` and `y*x` get different keys, so
246
+ * they are not merged. Merging them would need an ordering over expressions, which is a much larger
247
+ * commitment than this needs. Failing to merge costs nothing except a missed simplification.
248
+ */
249
+ function key(node) {
250
+ switch (node.type) {
251
+ case "num": return `#${node.value}`;
252
+ case "var": return `$${node.name}`;
253
+ case "neg": return `-(${key(node.arg)})`;
254
+ case "binary": return `(${key(node.left)}${node.op}${key(node.right)})`;
255
+ case "call": return `${node.fn}(${node.args.map(key).join(",")})`;
256
+ default: return "?";
257
+ }
258
+ }
259
+ /**
260
+ * Gather repeated factors into powers: `x·x` becomes `x²`, and `(x+1)/x` becomes `1 + x⁻¹`.
261
+ *
262
+ * Without this, `expand` is almost useless to the integrator. `∫x(x+1)dx` expands to `∫(x·x + x)dx`
263
+ * and the power rule reads `^`, not repeated multiplication, so it would still refuse. Division is
264
+ * folded in as a negative exponent, which is also what lets the `1/x → ln|x|` rule be reached
265
+ * through a quotient that was written as a fraction of sums.
266
+ */
267
+ function collect(node) {
268
+ const factors = [];
269
+ let numeric = 1;
270
+ let ok = true;
271
+ const gather = (n, sign) => {
272
+ if (!ok) return;
273
+ if (n.type === "binary" && n.op === "*") {
274
+ gather(n.left, sign);
275
+ gather(n.right, sign);
276
+ return;
277
+ }
278
+ if (n.type === "binary" && n.op === "/") {
279
+ gather(n.left, sign);
280
+ gather(n.right, sign === 1 ? -1 : 1);
281
+ return;
282
+ }
283
+ let base = n;
284
+ let exponent = 1;
285
+ if (n.type === "binary" && n.op === "^") {
286
+ const e = simplify(n.right);
287
+ if (e.type === "num" && Number.isFinite(e.value)) {
288
+ base = n.left;
289
+ exponent = e.value;
290
+ }
291
+ }
292
+ if (base.type === "num") {
293
+ if (exponent !== 1 && !Number.isInteger(exponent)) ok = false;
294
+ numeric *= Math.pow(base.value, sign * exponent);
295
+ return;
296
+ }
297
+ const k = key(base);
298
+ const found = factors.find((f) => key(f.base) === k);
299
+ if (found) found.exponent += sign * exponent;
300
+ else factors.push({
301
+ base,
302
+ exponent: sign * exponent
303
+ });
304
+ };
305
+ gather(node, 1);
306
+ if (!ok) return node;
307
+ const parts = [];
308
+ for (const { base, exponent } of factors) {
309
+ if (exponent === 0) continue;
310
+ parts.push(exponent === 1 ? base : pow(base, num(exponent)));
311
+ }
312
+ if (numeric !== 1 || parts.length === 0) parts.unshift(num(numeric));
313
+ return parts.reduce((a, b) => mul(a, b));
314
+ }
315
+ /** Run `collect` over every product in a sum, leaving the sum's shape alone. */
316
+ function collectAll(node) {
317
+ if (node.type === "binary" && (node.op === "+" || node.op === "-")) {
318
+ const left = collectAll(node.left);
319
+ const right = collectAll(node.right);
320
+ return node.op === "+" ? add(left, right) : sub(left, right);
321
+ }
322
+ if (node.type === "neg") return neg(collectAll(node.arg));
323
+ if (node.type === "binary" && (node.op === "*" || node.op === "/")) return collect(node);
324
+ return node;
325
+ }
326
+ /**
327
+ * Exact symbolic antiderivative, trying the expression as written and then multiplied out.
328
+ *
329
+ * The second attempt is what makes `∫x(x+1)dx` and `∫(R²−x²)²dx` work: expand distributes, collect
330
+ * turns the resulting repeated factors back into powers, and then the ordinary power rule applies
331
+ * term by term. A single retry, because both passes are idempotent on their own output.
128
332
  */
129
333
  function integrate(node, x) {
334
+ return integrateDirect(node, x) ?? integrateDirect(collectAll(expand(node)), x);
335
+ }
336
+ function integrateDirect(node, x) {
130
337
  if (isConstantIn(node, x)) return mul(node, variable(x));
131
338
  switch (node.type) {
132
339
  case "var": return div(pow(variable(x), num(2)), num(2));
@@ -167,6 +374,8 @@ function integrate(node, x) {
167
374
  const exponent = simplify(right);
168
375
  if (exponent.type !== "num") return null;
169
376
  const n = exponent.value;
377
+ const trig = integrateTrigPower(left, n, x);
378
+ if (trig) return trig;
170
379
  const a = linearFactor(left, x);
171
380
  if (a === null) return null;
172
381
  if (n === -1) return overConst(call("ln", call("abs", left)), a);
@@ -0,0 +1,93 @@
1
+ declare namespace complex_d_exports {
2
+ export { Complex, DEG2RAD, I, MAX_POW, MAX_ROOTS, ONE, RAD2DEG, TWO_PI, ZERO, abs, add, arg, argDeg, conj, cx, div, eq, fromPolar, iPow, isFiniteC, mul, neg, nthRoots, omega, powInt, rootsOfUnity, scale, sub, toPolar, toStr, toTex };
3
+ }
4
+ /**
5
+ * Complex-number kernel, the pure engine every complex/Argand/polar lab computes
6
+ * against (so a lab — or an agent — never hand-rolls a²+b² or atan2). A complex
7
+ * number is rectangular `{ re, im }`; the polar view (modulus r, argument θ) is
8
+ * derived, exactly the (x, y) ↔ (r, θ) bridge the vector labs already teach.
9
+ *
10
+ * Engineered for CORRECTNESS + SAFETY (no NaN spirals, no overflow, no runaway
11
+ * loops):
12
+ * • modulus uses Math.hypot (no re²+im² overflow);
13
+ * • division uses Smith's algorithm (scale by the larger term, avoids overflow
14
+ * / underflow), with a near-zero-denominator guard;
15
+ * • integer powers use exponentiation-by-squaring, |n| capped (MAX_POW), with a
16
+ * finiteness guard so r^n that overflows returns an explicit ∞, not garbage;
17
+ * • iⁿ is computed EXACTLY from n mod 4 (no float drift in the i, −1, −i, 1 cycle);
18
+ * • rootsOfUnity / nthRoots cap n (MAX_ROOTS) so an author can't request a
19
+ * billion-element array.
20
+ */
21
+ interface Complex {
22
+ re: number;
23
+ im: number;
24
+ }
25
+ declare const TWO_PI: number;
26
+ declare const RAD2DEG: number;
27
+ declare const DEG2RAD: number;
28
+ /** Hard caps so an authored value can never blow memory or hang a loop. */
29
+ declare const MAX_POW = 1024;
30
+ declare const MAX_ROOTS = 360;
31
+ declare const cx: (re: number, im?: number) => Complex;
32
+ declare const ZERO: Complex;
33
+ declare const ONE: Complex;
34
+ declare const I: Complex;
35
+ declare const isFiniteC: (z: Complex) => boolean;
36
+ declare const add: (a: Complex, b: Complex) => Complex;
37
+ declare const sub: (a: Complex, b: Complex) => Complex;
38
+ declare const neg: (a: Complex) => Complex;
39
+ declare const conj: (a: Complex) => Complex;
40
+ declare const scale: (a: Complex, k: number) => Complex;
41
+ /** (a+bi)(c+di) = (ac − bd) + (ad + bc)i. */
42
+ declare const mul: (a: Complex, b: Complex) => Complex;
43
+ /**
44
+ * Complex division via Smith's algorithm: divide through by the LARGER of the
45
+ * denominator's components so the intermediate ratio stays in [−1, 1] (no
46
+ * overflow when |b| is huge, no underflow when tiny). Returns an ∞/NaN complex
47
+ * for a (near-)zero denominator rather than throwing.
48
+ */
49
+ declare function div(a: Complex, b: Complex): Complex;
50
+ /** Modulus |z| = √(re² + im²), via hypot so large components don't overflow. */
51
+ declare const abs: (z: Complex) => number;
52
+ /** Argument arg(z) in RADIANS, in (−π, π]. arg(0) = 0 by convention. */
53
+ declare const arg: (z: Complex) => number;
54
+ /** Argument in DEGREES, in (−180, 180]. */
55
+ declare const argDeg: (z: Complex) => number;
56
+ /** Polar → rectangular: r·e^{iθ} = r(cosθ + i sinθ), θ in radians. */
57
+ declare const fromPolar: (r: number, theta: number) => Complex;
58
+ /** Rectangular → polar { r, theta(rad) }. */
59
+ declare const toPolar: (z: Complex) => {
60
+ r: number;
61
+ theta: number;
62
+ };
63
+ /**
64
+ * iⁿ for any integer n, EXACTLY (no De Moivre float drift): the 4-cycle
65
+ * 1, i, −1, −i. Negative n handled by the (n mod 4 + 4) mod 4 normalisation.
66
+ */
67
+ declare function iPow(n: number): Complex;
68
+ /**
69
+ * zⁿ for an INTEGER n via exponentiation-by-squaring (negative n inverts).
70
+ * |n| is capped at MAX_POW; an overflowing magnitude returns an explicit ∞
71
+ * complex (finite check) instead of looping into garbage.
72
+ */
73
+ declare function powInt(z: Complex, n: number): Complex;
74
+ /**
75
+ * The n nth-roots of UNITY: e^{2πik/n}, k = 0…n−1 (so ω = roots[1] is the
76
+ * primitive root). For n = 2 → {1, −1}; n = 3 → {1, ω, ω²}; n = 4 → {1, i, −1, −i}.
77
+ * n is clamped to [1, MAX_ROOTS]. The k = n/2 (real −1) and k = 0 (real 1) entries
78
+ * are snapped to exact values so labels read cleanly.
79
+ */
80
+ declare function rootsOfUnity(n: number): Complex[];
81
+ /** The n nth-roots of any z: |z|^{1/n} · e^{i(arg z + 2πk)/n}, k = 0…n−1. */
82
+ declare function nthRoots(z: Complex, n: number): Complex[];
83
+ /** The primitive nth root of unity ω (default the CUBE root, n = 3): e^{2πi/n}.
84
+ * For n = 3: ω = −½ + (√3/2)i, with ω³ = 1 and 1 + ω + ω² = 0. */
85
+ declare const omega: (n?: number) => Complex;
86
+ /** Equal within a tolerance (default 1e-9), on both components. */
87
+ declare const eq: (a: Complex, b: Complex, eps?: number) => boolean;
88
+ /** Plain string, e.g. "3 − 2i", "i", "−1", "0", "2i". */
89
+ declare function toStr(z: Complex, dp?: number): string;
90
+ /** LaTeX form for <Tex> (uses real minus signs, "i"). */
91
+ declare function toTex(z: Complex, dp?: number): string;
92
+ //#endregion
93
+ export { Complex, complex_d_exports };
@@ -0,0 +1,239 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.mjs";
2
+
3
+ //#region src/math/complex.ts
4
+ var complex_exports = /* @__PURE__ */ __exportAll({
5
+ DEG2RAD: () => DEG2RAD,
6
+ I: () => I,
7
+ MAX_POW: () => MAX_POW,
8
+ MAX_ROOTS: () => 360,
9
+ ONE: () => ONE,
10
+ RAD2DEG: () => RAD2DEG,
11
+ TWO_PI: () => TWO_PI,
12
+ ZERO: () => ZERO,
13
+ abs: () => abs,
14
+ add: () => add,
15
+ arg: () => arg,
16
+ argDeg: () => argDeg,
17
+ conj: () => conj,
18
+ cx: () => cx,
19
+ div: () => div,
20
+ eq: () => eq,
21
+ fromPolar: () => fromPolar,
22
+ iPow: () => iPow,
23
+ isFiniteC: () => isFiniteC,
24
+ mul: () => mul,
25
+ neg: () => neg,
26
+ nthRoots: () => nthRoots,
27
+ omega: () => omega,
28
+ powInt: () => powInt,
29
+ rootsOfUnity: () => rootsOfUnity,
30
+ scale: () => scale,
31
+ sub: () => sub,
32
+ toPolar: () => toPolar,
33
+ toStr: () => toStr,
34
+ toTex: () => toTex
35
+ });
36
+ const TWO_PI = Math.PI * 2;
37
+ const RAD2DEG = 180 / Math.PI;
38
+ const DEG2RAD = Math.PI / 180;
39
+ /** Hard caps so an authored value can never blow memory or hang a loop. */
40
+ const MAX_POW = 1024;
41
+ const MAX_ROOTS = 360;
42
+ const cx = (re, im = 0) => ({
43
+ re,
44
+ im
45
+ });
46
+ const ZERO = {
47
+ re: 0,
48
+ im: 0
49
+ };
50
+ const ONE = {
51
+ re: 1,
52
+ im: 0
53
+ };
54
+ const I = {
55
+ re: 0,
56
+ im: 1
57
+ };
58
+ const isFiniteC = (z) => Number.isFinite(z.re) && Number.isFinite(z.im);
59
+ const add = (a, b) => ({
60
+ re: a.re + b.re,
61
+ im: a.im + b.im
62
+ });
63
+ const sub = (a, b) => ({
64
+ re: a.re - b.re,
65
+ im: a.im - b.im
66
+ });
67
+ const neg = (a) => ({
68
+ re: -a.re,
69
+ im: -a.im
70
+ });
71
+ const conj = (a) => ({
72
+ re: a.re,
73
+ im: -a.im
74
+ });
75
+ const scale = (a, k) => ({
76
+ re: a.re * k,
77
+ im: a.im * k
78
+ });
79
+ /** (a+bi)(c+di) = (ac − bd) + (ad + bc)i. */
80
+ const mul = (a, b) => ({
81
+ re: a.re * b.re - a.im * b.im,
82
+ im: a.re * b.im + a.im * b.re
83
+ });
84
+ /**
85
+ * Complex division via Smith's algorithm: divide through by the LARGER of the
86
+ * denominator's components so the intermediate ratio stays in [−1, 1] (no
87
+ * overflow when |b| is huge, no underflow when tiny). Returns an ∞/NaN complex
88
+ * for a (near-)zero denominator rather than throwing.
89
+ */
90
+ function div(a, b) {
91
+ const { re: c, im: d } = b;
92
+ if (c === 0 && d === 0) return {
93
+ re: a.re / 0,
94
+ im: a.im / 0
95
+ };
96
+ if (Math.abs(c) >= Math.abs(d)) {
97
+ const r = d / c, den = c + d * r;
98
+ return {
99
+ re: (a.re + a.im * r) / den,
100
+ im: (a.im - a.re * r) / den
101
+ };
102
+ }
103
+ const r = c / d, den = c * r + d;
104
+ return {
105
+ re: (a.re * r + a.im) / den,
106
+ im: (a.im * r - a.re) / den
107
+ };
108
+ }
109
+ /** Modulus |z| = √(re² + im²), via hypot so large components don't overflow. */
110
+ const abs = (z) => Math.hypot(z.re, z.im);
111
+ /** Argument arg(z) in RADIANS, in (−π, π]. arg(0) = 0 by convention. */
112
+ const arg = (z) => z.re === 0 && z.im === 0 ? 0 : Math.atan2(z.im, z.re);
113
+ /** Argument in DEGREES, in (−180, 180]. */
114
+ const argDeg = (z) => arg(z) * RAD2DEG;
115
+ /** Polar → rectangular: r·e^{iθ} = r(cosθ + i sinθ), θ in radians. */
116
+ const fromPolar = (r, theta) => ({
117
+ re: r * Math.cos(theta),
118
+ im: r * Math.sin(theta)
119
+ });
120
+ /** Rectangular → polar { r, theta(rad) }. */
121
+ const toPolar = (z) => ({
122
+ r: abs(z),
123
+ theta: arg(z)
124
+ });
125
+ /**
126
+ * iⁿ for any integer n, EXACTLY (no De Moivre float drift): the 4-cycle
127
+ * 1, i, −1, −i. Negative n handled by the (n mod 4 + 4) mod 4 normalisation.
128
+ */
129
+ function iPow(n) {
130
+ if (!Number.isInteger(n)) return {
131
+ re: NaN,
132
+ im: NaN
133
+ };
134
+ switch ((n % 4 + 4) % 4) {
135
+ case 0: return {
136
+ re: 1,
137
+ im: 0
138
+ };
139
+ case 1: return {
140
+ re: 0,
141
+ im: 1
142
+ };
143
+ case 2: return {
144
+ re: -1,
145
+ im: 0
146
+ };
147
+ default: return {
148
+ re: 0,
149
+ im: -1
150
+ };
151
+ }
152
+ }
153
+ /**
154
+ * zⁿ for an INTEGER n via exponentiation-by-squaring (negative n inverts).
155
+ * |n| is capped at MAX_POW; an overflowing magnitude returns an explicit ∞
156
+ * complex (finite check) instead of looping into garbage.
157
+ */
158
+ function powInt(z, n) {
159
+ if (!Number.isInteger(n)) return {
160
+ re: NaN,
161
+ im: NaN
162
+ };
163
+ if (Math.abs(n) > 1024) return {
164
+ re: Infinity,
165
+ im: Infinity
166
+ };
167
+ if (n === 0) return { ...ONE };
168
+ let base = n < 0 ? div(ONE, z) : z;
169
+ let e = Math.abs(n);
170
+ let acc = { ...ONE };
171
+ while (e > 0) {
172
+ if (e & 1) acc = mul(acc, base);
173
+ e >>= 1;
174
+ if (e > 0) base = mul(base, base);
175
+ if (!isFiniteC(acc)) return {
176
+ re: Infinity,
177
+ im: Infinity
178
+ };
179
+ }
180
+ return acc;
181
+ }
182
+ /** Clamp an nth-root count to a safe, sane range [1, MAX_ROOTS]. */
183
+ const safeN = (n) => Number.isInteger(n) && n >= 1 ? Math.min(n, 360) : 1;
184
+ /**
185
+ * The n nth-roots of UNITY: e^{2πik/n}, k = 0…n−1 (so ω = roots[1] is the
186
+ * primitive root). For n = 2 → {1, −1}; n = 3 → {1, ω, ω²}; n = 4 → {1, i, −1, −i}.
187
+ * n is clamped to [1, MAX_ROOTS]. The k = n/2 (real −1) and k = 0 (real 1) entries
188
+ * are snapped to exact values so labels read cleanly.
189
+ */
190
+ function rootsOfUnity(n) {
191
+ const m = safeN(n);
192
+ return Array.from({ length: m }, (_, k) => {
193
+ if (k === 0) return {
194
+ re: 1,
195
+ im: 0
196
+ };
197
+ if (m % 2 === 0 && k === m / 2) return {
198
+ re: -1,
199
+ im: 0
200
+ };
201
+ return fromPolar(1, TWO_PI * k / m);
202
+ });
203
+ }
204
+ /** The n nth-roots of any z: |z|^{1/n} · e^{i(arg z + 2πk)/n}, k = 0…n−1. */
205
+ function nthRoots(z, n) {
206
+ const m = safeN(n);
207
+ const { r, theta } = toPolar(z);
208
+ const root = Math.pow(r, 1 / m);
209
+ return Array.from({ length: m }, (_, k) => fromPolar(root, (theta + TWO_PI * k) / m));
210
+ }
211
+ /** The primitive nth root of unity ω (default the CUBE root, n = 3): e^{2πi/n}.
212
+ * For n = 3: ω = −½ + (√3/2)i, with ω³ = 1 and 1 + ω + ω² = 0. */
213
+ const omega = (n = 3) => fromPolar(1, TWO_PI / safeN(n));
214
+ /** Equal within a tolerance (default 1e-9), on both components. */
215
+ const eq = (a, b, eps = 1e-9) => Math.abs(a.re - b.re) <= eps && Math.abs(a.im - b.im) <= eps;
216
+ const numStr = (n, dp) => {
217
+ if (!Number.isFinite(n)) return n > 0 ? "∞" : "−∞";
218
+ const r = Math.round(n * 10 ** dp) / 10 ** dp;
219
+ return Object.is(r, -0) ? "0" : String(r).replace(/^-/, "−");
220
+ };
221
+ /** Plain string, e.g. "3 − 2i", "i", "−1", "0", "2i". */
222
+ function toStr(z, dp = 2) {
223
+ if (!isFiniteC(z)) return "∞";
224
+ const re = Math.round(z.re * 10 ** dp) / 10 ** dp;
225
+ const im = Math.round(z.im * 10 ** dp) / 10 ** dp;
226
+ if (im === 0) return numStr(re, dp);
227
+ const imPart = im === 1 ? "i" : im === -1 ? "−i" : `${numStr(Math.abs(im), dp)}i`;
228
+ if (re === 0) return im < 0 && im !== -1 ? `−${imPart}` : im === -1 ? "−i" : imPart;
229
+ const sign = im < 0 ? "−" : "+";
230
+ const mag = Math.abs(im) === 1 ? "i" : `${numStr(Math.abs(im), dp)}i`;
231
+ return `${numStr(re, dp)} ${sign} ${mag}`;
232
+ }
233
+ /** LaTeX form for <Tex> (uses real minus signs, "i"). */
234
+ function toTex(z, dp = 2) {
235
+ return toStr(z, dp).replace(/−/g, "-");
236
+ }
237
+
238
+ //#endregion
239
+ export { ONE, ZERO, abs, add, complex_exports, cx, div, fromPolar, isFiniteC, mul, sub, toStr };
@@ -0,0 +1,23 @@
1
+ import { Node } from "./ast.mjs";
2
+
3
+ //#region src/math/expr.d.ts
4
+ interface CompiledExpr {
5
+ /** Evaluate against a scope of variable values (unknown vars → NaN). */
6
+ readonly fn: (scope: Record<string, number>) => number;
7
+ /** Free variables referenced (excludes constants & functions), e.g. `['x','a']`. */
8
+ readonly vars: string[];
9
+ /** The parsed syntax tree, for differentiation, LaTeX, or analysis. */
10
+ readonly ast: Node;
11
+ readonly error?: undefined;
12
+ }
13
+ interface ExprError {
14
+ readonly error: string;
15
+ readonly fn?: undefined;
16
+ readonly vars?: undefined;
17
+ readonly ast?: undefined;
18
+ }
19
+ type ExprResult = CompiledExpr | ExprError;
20
+ /** Compile a formula string. Returns `{ fn, vars, ast }` or `{ error }`, never throws. */
21
+ declare function compileExpr(src: string): ExprResult;
22
+ //#endregion
23
+ export { CompiledExpr, ExprError, ExprResult, compileExpr };
@@ -0,0 +1,36 @@
1
+ import { evaluate, freeVars } from "./ast.mjs";
2
+ import { parse } from "./parse.mjs";
3
+
4
+ //#region src/math/expr.ts
5
+ /**
6
+ * compileExpr, the stable entry point to the engine: a formula string in, a fast evaluator plus
7
+ * the free variables and the parsed AST out.
8
+ *
9
+ * It NEVER THROWS. `parse` throws on bad input, which is correct for a parser and wrong for the
10
+ * call site that matters here: an author or a student typing into a field, where a thrown error
11
+ * would take the lab down mid-keystroke. So the result is a union, `{ fn, vars, ast }` or
12
+ * `{ error }`, discriminated by an optional `error` on both arms so `if (c.error)` narrows without
13
+ * a type guard.
14
+ *
15
+ * This lived in `index.ts` until the answer checker needed it, which would have made the barrel
16
+ * import a file that imports the barrel. Implementation in a barrel is a circular import waiting
17
+ * for its second consumer.
18
+ */
19
+ /** Compile a formula string. Returns `{ fn, vars, ast }` or `{ error }`, never throws. */
20
+ function compileExpr(src) {
21
+ if (!src || !src.trim()) return { error: "Empty expression" };
22
+ let ast;
23
+ try {
24
+ ast = parse(src);
25
+ } catch (e) {
26
+ return { error: e instanceof Error ? e.message : "Parse error" };
27
+ }
28
+ return {
29
+ fn: (scope) => evaluate(ast, scope),
30
+ vars: [...freeVars(ast)],
31
+ ast
32
+ };
33
+ }
34
+
35
+ //#endregion
36
+ export { compileExpr };
@@ -1,27 +1,13 @@
1
1
  import { BinOp, Node, 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 { CompiledFn, compile } from "./compile.mjs";
5
6
  import { toLatex } from "./latex.mjs";
6
-
7
- //#region src/math/index.d.ts
8
- interface CompiledExpr {
9
- /** Evaluate against a scope of variable values (unknown vars → NaN). */
10
- readonly fn: (scope: Record<string, number>) => number;
11
- /** Free variables referenced (excludes constants & functions), e.g. `['x','a']`. */
12
- readonly vars: string[];
13
- /** The parsed syntax tree, for differentiation, LaTeX, or analysis. */
14
- readonly ast: Node;
15
- readonly error?: undefined;
16
- }
17
- interface ExprError {
18
- readonly error: string;
19
- readonly fn?: undefined;
20
- readonly vars?: undefined;
21
- readonly ast?: undefined;
22
- }
23
- type ExprResult = CompiledExpr | ExprError;
24
- /** Compile a formula string. Returns `{ fn, vars, ast }` or `{ error }`, never throws. */
25
- declare function compileExpr(src: string): ExprResult;
26
- //#endregion
27
- export { type BinOp, CompiledExpr, type CompiledFn, ExprError, ExprResult, type Node, compile, compileExpr, compileNode, definiteIntegral, differentiate, evaluate, freeVars, integrate, parse, simplify, toLatex };
7
+ import { CompiledExpr, ExprError, ExprResult, compileExpr } from "./expr.mjs";
8
+ import { Complex, complex_d_exports } from "./complex.mjs";
9
+ import { Poly, PolyRoots, allRoots, deflate, degree, deriv, evalC, evalPoly, factorTex, fromAst, polyRoots, polyTex, poly_d_exports, solveEquation, trim } from "./poly.mjs";
10
+ import { PolySolution, polyCoeffs, solutionTex, solvePoly } from "./solve.mjs";
11
+ import { Fn1, Line, areaBetween, intersections, normalAt, quadrature, roots, tangentAt } from "./analysis.mjs";
12
+ import { AnswerSpec, ExprCheckOpts, checkAnswer, checkExpression, checkNumber, normalizeMathInput, parseValue } from "./answer-check.mjs";
13
+ export { type AnswerSpec, type BinOp, type CompiledExpr, type CompiledFn, type Complex, type ExprCheckOpts, type ExprError, type ExprResult, type Fn1, type Line, type Node, type Poly, type PolyRoots, type PolySolution, allRoots, areaBetween, checkAnswer, checkExpression, checkNumber, compile, compileExpr, compileNode, complex_d_exports as complex, definiteIntegral, deflate, degree, deriv, differentiate, evalC, evalPoly, evaluate, factorTex, freeVars, fromAst, integrate, intersections, isolate, normalAt, normalizeMathInput, occurrences, parse, parseValue, poly_d_exports as poly, polyCoeffs, polyRoots, polyTex, quadrature, roots, simplify, solutionTex, solveEquation, solvePoly, tangentAt, toLatex, trim };