@classytic/stage 0.2.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 (458) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +5 -1
  3. package/dist/_virtual/_rolldown/runtime.mjs +18 -0
  4. package/dist/assets/index.mjs +0 -1
  5. package/dist/atomic/aufbau.d.mts +144 -0
  6. package/dist/atomic/aufbau.mjs +384 -0
  7. package/dist/atomic/elements.d.mts +67 -0
  8. package/dist/atomic/elements.mjs +785 -0
  9. package/dist/atomic/emission.d.mts +112 -0
  10. package/dist/atomic/emission.mjs +179 -0
  11. package/dist/atomic/index.d.mts +8 -0
  12. package/dist/atomic/index.mjs +9 -0
  13. package/dist/atomic/periodic.d.mts +82 -0
  14. package/dist/atomic/periodic.mjs +231 -0
  15. package/dist/atomic/properties.d.mts +100 -0
  16. package/dist/atomic/properties.mjs +574 -0
  17. package/dist/atomic/shells.d.mts +137 -0
  18. package/dist/atomic/shells.mjs +170 -0
  19. package/dist/atomic/trends.d.mts +148 -0
  20. package/dist/atomic/trends.mjs +225 -0
  21. package/dist/builder/Palette.mjs +50 -89
  22. package/dist/builder/SceneBuilder.mjs +15 -73
  23. package/dist/chem/chromatography.d.mts +66 -0
  24. package/dist/chem/chromatography.mjs +63 -0
  25. package/dist/chem/complex.d.mts +114 -0
  26. package/dist/chem/complex.mjs +234 -0
  27. package/dist/chem/cycle.d.mts +75 -0
  28. package/dist/chem/cycle.mjs +145 -0
  29. package/dist/chem/equation.d.mts +86 -0
  30. package/dist/chem/equation.mjs +168 -0
  31. package/dist/chem/formula.d.mts +90 -0
  32. package/dist/chem/formula.mjs +201 -0
  33. package/dist/chem/functional-groups.d.mts +31 -0
  34. package/dist/chem/functional-groups.mjs +187 -0
  35. package/dist/chem/hazard.d.mts +94 -0
  36. package/dist/chem/hazard.mjs +329 -0
  37. package/dist/chem/index.d.mts +34 -33
  38. package/dist/chem/index.mjs +34 -28
  39. package/dist/chem/ionic.d.mts +98 -0
  40. package/dist/chem/ionic.mjs +156 -0
  41. package/dist/chem/layout.d.mts +46 -0
  42. package/dist/chem/layout.mjs +342 -0
  43. package/dist/chem/lewis.d.mts +79 -0
  44. package/dist/chem/lewis.mjs +163 -0
  45. package/dist/chem/molecular-orbital.d.mts +114 -0
  46. package/dist/chem/molecular-orbital.mjs +201 -0
  47. package/dist/chem/molecule.d.mts +154 -0
  48. package/dist/chem/molecule.mjs +282 -0
  49. package/dist/chem/nmr.d.mts +153 -0
  50. package/dist/chem/nmr.mjs +165 -0
  51. package/dist/chem/polymer.d.mts +65 -0
  52. package/dist/chem/polymer.mjs +179 -0
  53. package/dist/chem/redox.d.mts +138 -0
  54. package/dist/chem/redox.mjs +328 -0
  55. package/dist/chem/relations.d.mts +183 -0
  56. package/dist/chem/relations.mjs +299 -0
  57. package/dist/chem/skeleton.d.mts +51 -0
  58. package/dist/chem/skeleton.mjs +186 -0
  59. package/dist/chem/solution.d.mts +116 -0
  60. package/dist/chem/solution.mjs +186 -0
  61. package/dist/chem/species.d.mts +47 -0
  62. package/dist/chem/species.mjs +128 -0
  63. package/dist/chem/stereo.d.mts +108 -0
  64. package/dist/chem/stereo.mjs +286 -0
  65. package/dist/chem/stoichiometry.d.mts +95 -0
  66. package/dist/chem/stoichiometry.mjs +145 -0
  67. package/dist/chem/synthesis.d.mts +113 -0
  68. package/dist/chem/synthesis.mjs +281 -0
  69. package/dist/chem/vsepr.d.mts +80 -0
  70. package/dist/chem/vsepr.mjs +247 -0
  71. package/dist/circuit/ac.d.mts +163 -0
  72. package/dist/circuit/ac.mjs +452 -0
  73. package/dist/circuit/dc.d.mts +92 -0
  74. package/dist/circuit/dc.mjs +333 -0
  75. package/dist/circuit/index.d.mts +5 -92
  76. package/dist/circuit/index.mjs +5 -332
  77. package/dist/circuit/network.d.mts +99 -0
  78. package/dist/circuit/network.mjs +440 -0
  79. package/dist/circuit/topology.d.mts +102 -0
  80. package/dist/circuit/topology.mjs +143 -0
  81. package/dist/colour/absorption.d.mts +79 -0
  82. package/dist/colour/absorption.mjs +137 -0
  83. package/dist/colour/index.d.mts +6 -0
  84. package/dist/colour/index.mjs +7 -0
  85. package/dist/colour/name.d.mts +14 -0
  86. package/dist/colour/name.mjs +76 -0
  87. package/dist/colour/observer.d.mts +31 -0
  88. package/dist/colour/observer.mjs +46 -0
  89. package/dist/colour/spectrum.d.mts +61 -0
  90. package/dist/colour/spectrum.mjs +108 -0
  91. package/dist/colour/srgb.d.mts +49 -0
  92. package/dist/colour/srgb.mjs +108 -0
  93. package/dist/core/constants.d.mts +138 -0
  94. package/dist/core/constants.mjs +139 -0
  95. package/dist/core/index.d.mts +4 -1
  96. package/dist/core/index.mjs +4 -1
  97. package/dist/core/math.d.mts +26 -0
  98. package/dist/core/math.mjs +37 -0
  99. package/dist/core/vec3.d.mts +94 -0
  100. package/dist/core/vec3.mjs +123 -0
  101. package/dist/core/worked.d.mts +35 -0
  102. package/dist/core/worked.mjs +44 -0
  103. package/dist/electro/cell.d.mts +102 -0
  104. package/dist/electro/cell.mjs +170 -0
  105. package/dist/electro/conductivity.d.mts +157 -0
  106. package/dist/electro/conductivity.mjs +156 -0
  107. package/dist/electro/couples.d.mts +114 -0
  108. package/dist/electro/couples.mjs +334 -0
  109. package/dist/electro/electrolysis.d.mts +96 -0
  110. package/dist/electro/electrolysis.mjs +274 -0
  111. package/dist/electro/faraday.d.mts +150 -0
  112. package/dist/electro/faraday.mjs +118 -0
  113. package/dist/electro/index.d.mts +6 -0
  114. package/dist/electro/index.mjs +7 -0
  115. package/dist/finance/accounting/adjustments.d.mts +17 -0
  116. package/dist/finance/accounting/adjustments.mjs +202 -0
  117. package/dist/finance/accounting/analysis.d.mts +8 -0
  118. package/dist/finance/accounting/analysis.mjs +205 -0
  119. package/dist/finance/accounting/clubs.d.mts +21 -0
  120. package/dist/finance/accounting/clubs.mjs +217 -0
  121. package/dist/finance/accounting/company-statements.d.mts +7 -0
  122. package/dist/finance/accounting/company-statements.mjs +150 -0
  123. package/dist/finance/accounting/harness.d.mts +7 -0
  124. package/dist/finance/accounting/harness.mjs +45 -0
  125. package/dist/finance/accounting/index.d.mts +18 -0
  126. package/dist/finance/accounting/index.mjs +18 -0
  127. package/dist/finance/accounting/journalize.d.mts +16 -0
  128. package/dist/finance/accounting/journalize.mjs +128 -0
  129. package/dist/finance/accounting/manufacturing.d.mts +8 -0
  130. package/dist/finance/accounting/manufacturing.mjs +236 -0
  131. package/dist/finance/accounting/partnership.d.mts +7 -0
  132. package/dist/finance/accounting/partnership.mjs +152 -0
  133. package/dist/finance/accounting/period-case.d.mts +6 -0
  134. package/dist/finance/accounting/period-case.mjs +71 -0
  135. package/dist/finance/accounting/post.d.mts +9 -0
  136. package/dist/finance/accounting/post.mjs +84 -0
  137. package/dist/finance/accounting/precision.d.mts +9 -0
  138. package/dist/finance/accounting/precision.mjs +15 -0
  139. package/dist/finance/accounting/rules.d.mts +21 -0
  140. package/dist/finance/accounting/rules.mjs +37 -0
  141. package/dist/finance/accounting/solve.d.mts +28 -0
  142. package/dist/finance/accounting/solve.mjs +92 -0
  143. package/dist/finance/accounting/statements.d.mts +7 -0
  144. package/dist/finance/accounting/statements.mjs +142 -0
  145. package/dist/finance/accounting/types.d.mts +649 -0
  146. package/dist/finance/accounting/validate.d.mts +7 -0
  147. package/dist/finance/accounting/validate.mjs +67 -0
  148. package/dist/finance/accounting/verification.d.mts +24 -0
  149. package/dist/finance/accounting/verification.mjs +386 -0
  150. package/dist/finance/bizsim.d.mts +75 -0
  151. package/dist/finance/bizsim.mjs +296 -0
  152. package/dist/finance/index.d.mts +95 -0
  153. package/dist/finance/index.mjs +145 -0
  154. package/dist/finance/investment-math.d.mts +7 -0
  155. package/dist/finance/investment-math.mjs +18 -0
  156. package/dist/finance/management-accounting/budgeting.d.mts +7 -0
  157. package/dist/finance/management-accounting/budgeting.mjs +189 -0
  158. package/dist/finance/management-accounting/cash-budget.d.mts +7 -0
  159. package/dist/finance/management-accounting/cash-budget.mjs +154 -0
  160. package/dist/finance/management-accounting/costing.d.mts +8 -0
  161. package/dist/finance/management-accounting/costing.mjs +175 -0
  162. package/dist/finance/management-accounting/decisions.d.mts +8 -0
  163. package/dist/finance/management-accounting/decisions.mjs +164 -0
  164. package/dist/finance/management-accounting/index.d.mts +13 -0
  165. package/dist/finance/management-accounting/index.mjs +13 -0
  166. package/dist/finance/management-accounting/integrated-budget.d.mts +8 -0
  167. package/dist/finance/management-accounting/integrated-budget.mjs +67 -0
  168. package/dist/finance/management-accounting/inventory-costing.d.mts +7 -0
  169. package/dist/finance/management-accounting/inventory-costing.mjs +173 -0
  170. package/dist/finance/management-accounting/investment-appraisal.d.mts +7 -0
  171. package/dist/finance/management-accounting/investment-appraisal.mjs +148 -0
  172. package/dist/finance/management-accounting/management-case.d.mts +8 -0
  173. package/dist/finance/management-accounting/management-case.mjs +91 -0
  174. package/dist/finance/management-accounting/master-budget.d.mts +7 -0
  175. package/dist/finance/management-accounting/master-budget.mjs +137 -0
  176. package/dist/finance/management-accounting/production-costing.d.mts +8 -0
  177. package/dist/finance/management-accounting/production-costing.mjs +214 -0
  178. package/dist/finance/management-accounting/types.d.mts +644 -0
  179. package/dist/finance/management-accounting/variances.d.mts +7 -0
  180. package/dist/finance/management-accounting/variances.mjs +150 -0
  181. package/dist/index.d.mts +9 -8
  182. package/dist/index.mjs +5 -5
  183. package/dist/interaction/MovableDot.mjs +19 -0
  184. package/dist/interaction/useDraggable.mjs +24 -4
  185. package/dist/math/analysis.d.mts +61 -0
  186. package/dist/math/analysis.mjs +187 -0
  187. package/dist/math/answer-check.d.mts +50 -0
  188. package/dist/math/answer-check.mjs +106 -0
  189. package/dist/math/calculus.d.mts +17 -1
  190. package/dist/math/calculus.mjs +365 -2
  191. package/dist/math/complex.d.mts +93 -0
  192. package/dist/math/complex.mjs +239 -0
  193. package/dist/math/expr.d.mts +23 -0
  194. package/dist/math/expr.mjs +36 -0
  195. package/dist/math/index.d.mts +9 -23
  196. package/dist/math/index.mjs +9 -38
  197. package/dist/math/latex.mjs +10 -1
  198. package/dist/math/parse.mjs +1 -1
  199. package/dist/math/poly.d.mts +55 -0
  200. package/dist/math/poly.mjs +273 -0
  201. package/dist/math/rearrange.d.mts +14 -0
  202. package/dist/math/rearrange.mjs +125 -0
  203. package/dist/math/solve.d.mts +21 -0
  204. package/dist/math/solve.mjs +75 -0
  205. package/dist/networking/addressing.d.mts +26 -0
  206. package/dist/networking/addressing.mjs +33 -0
  207. package/dist/networking/cloud/access.d.mts +36 -0
  208. package/dist/networking/cloud/access.mjs +95 -0
  209. package/dist/networking/cloud/containers.d.mts +43 -0
  210. package/dist/networking/cloud/containers.mjs +54 -0
  211. package/dist/networking/cloud/edge.d.mts +17 -0
  212. package/dist/networking/cloud/edge.mjs +31 -0
  213. package/dist/networking/cloud/failure-domains.d.mts +19 -0
  214. package/dist/networking/cloud/failure-domains.mjs +22 -0
  215. package/dist/networking/cloud/geo-routing.d.mts +22 -0
  216. package/dist/networking/cloud/geo-routing.mjs +64 -0
  217. package/dist/networking/cloud/index.d.mts +18 -0
  218. package/dist/networking/cloud/index.mjs +19 -0
  219. package/dist/networking/cloud/inference-reliability.d.mts +30 -0
  220. package/dist/networking/cloud/inference-reliability.mjs +76 -0
  221. package/dist/networking/cloud/inference.d.mts +118 -0
  222. package/dist/networking/cloud/inference.mjs +179 -0
  223. package/dist/networking/cloud/infrastructure.d.mts +45 -0
  224. package/dist/networking/cloud/infrastructure.mjs +96 -0
  225. package/dist/networking/cloud/observability.d.mts +24 -0
  226. package/dist/networking/cloud/observability.mjs +34 -0
  227. package/dist/networking/cloud/orchestration.d.mts +32 -0
  228. package/dist/networking/cloud/orchestration.mjs +38 -0
  229. package/dist/networking/cloud/recovery.d.mts +21 -0
  230. package/dist/networking/cloud/recovery.mjs +27 -0
  231. package/dist/networking/cloud/releases.d.mts +42 -0
  232. package/dist/networking/cloud/releases.mjs +135 -0
  233. package/dist/networking/cloud/scaling.d.mts +25 -0
  234. package/dist/networking/cloud/scaling.mjs +65 -0
  235. package/dist/networking/cloud/secrets.d.mts +39 -0
  236. package/dist/networking/cloud/secrets.mjs +68 -0
  237. package/dist/networking/cloud/server-deployment.d.mts +29 -0
  238. package/dist/networking/cloud/server-deployment.mjs +72 -0
  239. package/dist/networking/cloud/storage.d.mts +16 -0
  240. package/dist/networking/cloud/storage.mjs +58 -0
  241. package/dist/networking/cloud/vpc.d.mts +18 -0
  242. package/dist/networking/cloud/vpc.mjs +100 -0
  243. package/dist/networking/delivery.d.mts +34 -0
  244. package/dist/networking/delivery.mjs +52 -0
  245. package/dist/networking/index.d.mts +47 -0
  246. package/dist/networking/index.mjs +47 -0
  247. package/dist/networking/ipv6.d.mts +28 -0
  248. package/dist/networking/ipv6.mjs +17 -0
  249. package/dist/networking/journeys.d.mts +83 -0
  250. package/dist/networking/journeys.mjs +161 -0
  251. package/dist/networking/models/airtime.d.mts +87 -0
  252. package/dist/networking/models/airtime.mjs +130 -0
  253. package/dist/networking/models/cellular.d.mts +157 -0
  254. package/dist/networking/models/cellular.mjs +252 -0
  255. package/dist/networking/models/encapsulation.d.mts +98 -0
  256. package/dist/networking/models/encapsulation.mjs +132 -0
  257. package/dist/networking/models/handover.d.mts +116 -0
  258. package/dist/networking/models/handover.mjs +209 -0
  259. package/dist/networking/models/handshake.d.mts +90 -0
  260. package/dist/networking/models/handshake.mjs +122 -0
  261. package/dist/networking/models/index.d.mts +14 -0
  262. package/dist/networking/models/index.mjs +15 -0
  263. package/dist/networking/models/media.d.mts +82 -0
  264. package/dist/networking/models/media.mjs +188 -0
  265. package/dist/networking/models/satellite.d.mts +86 -0
  266. package/dist/networking/models/satellite.mjs +121 -0
  267. package/dist/networking/models/spectrum.d.mts +83 -0
  268. package/dist/networking/models/spectrum.mjs +235 -0
  269. package/dist/networking/models/switch.d.mts +80 -0
  270. package/dist/networking/models/switch.mjs +155 -0
  271. package/dist/networking/models/vlan.d.mts +62 -0
  272. package/dist/networking/models/vlan.mjs +100 -0
  273. package/dist/networking/models/vpn.d.mts +66 -0
  274. package/dist/networking/models/vpn.mjs +125 -0
  275. package/dist/networking/models/wifi-privacy.d.mts +82 -0
  276. package/dist/networking/models/wifi-privacy.mjs +130 -0
  277. package/dist/networking/models/wifi.d.mts +240 -0
  278. package/dist/networking/models/wifi.mjs +562 -0
  279. package/dist/networking/nat-traversal.d.mts +24 -0
  280. package/dist/networking/nat-traversal.mjs +38 -0
  281. package/dist/networking/protocols.d.mts +17 -0
  282. package/dist/networking/protocols.mjs +57 -0
  283. package/dist/networking/queue.d.mts +12 -0
  284. package/dist/networking/queue.mjs +18 -0
  285. package/dist/networking/route-learning.d.mts +23 -0
  286. package/dist/networking/route-learning.mjs +43 -0
  287. package/dist/networking/routing.d.mts +11 -0
  288. package/dist/networking/routing.mjs +25 -0
  289. package/dist/networking/signals.d.mts +26 -0
  290. package/dist/networking/signals.mjs +35 -0
  291. package/dist/networking/subnet.d.mts +49 -0
  292. package/dist/networking/subnet.mjs +89 -0
  293. package/dist/networking/tcp-reliability.d.mts +24 -0
  294. package/dist/networking/tcp-reliability.mjs +38 -0
  295. package/dist/networking/topology/contract.d.mts +123 -0
  296. package/dist/networking/topology/index.d.mts +4 -0
  297. package/dist/networking/topology/index.mjs +4 -0
  298. package/dist/networking/topology/presets.d.mts +7 -0
  299. package/dist/networking/topology/presets.mjs +302 -0
  300. package/dist/networking/topology/simulation.d.mts +8 -0
  301. package/dist/networking/topology/simulation.mjs +179 -0
  302. package/dist/networking/wireless.d.mts +11 -0
  303. package/dist/networking/wireless.mjs +17 -0
  304. package/dist/optics/imaging.d.mts +218 -0
  305. package/dist/optics/imaging.mjs +276 -0
  306. package/dist/optics/index.d.mts +7 -0
  307. package/dist/optics/index.mjs +8 -0
  308. package/dist/optics/laws.d.mts +70 -0
  309. package/dist/optics/laws.mjs +195 -0
  310. package/dist/optics/prism.d.mts +148 -0
  311. package/dist/optics/prism.mjs +197 -0
  312. package/dist/optics/refraction.d.mts +201 -0
  313. package/dist/optics/refraction.mjs +270 -0
  314. package/dist/optics/wave-optics.d.mts +171 -0
  315. package/dist/optics/wave-optics.mjs +259 -0
  316. package/dist/physics/ac/index.d.mts +183 -0
  317. package/dist/physics/ac/index.mjs +203 -0
  318. package/dist/physics/dynamics/forces.d.mts +98 -0
  319. package/dist/physics/dynamics/forces.mjs +153 -0
  320. package/dist/physics/dynamics/friction.d.mts +76 -0
  321. package/dist/physics/dynamics/friction.mjs +119 -0
  322. package/dist/physics/dynamics/system.d.mts +68 -0
  323. package/dist/physics/dynamics/system.mjs +125 -0
  324. package/dist/physics/electrostatics/index.d.mts +169 -0
  325. package/dist/physics/electrostatics/index.mjs +249 -0
  326. package/dist/physics/energy/centre-of-mass.d.mts +115 -0
  327. package/dist/physics/energy/centre-of-mass.mjs +180 -0
  328. package/dist/physics/energy/conservation.d.mts +81 -0
  329. package/dist/physics/energy/conservation.mjs +129 -0
  330. package/dist/physics/energy/power.d.mts +90 -0
  331. package/dist/physics/energy/power.mjs +167 -0
  332. package/dist/physics/energy/spring.d.mts +73 -0
  333. package/dist/physics/energy/spring.mjs +129 -0
  334. package/dist/physics/energy/store.d.mts +63 -0
  335. package/dist/physics/energy/store.mjs +108 -0
  336. package/dist/physics/energy/theorem.d.mts +65 -0
  337. package/dist/physics/energy/theorem.mjs +113 -0
  338. package/dist/physics/energy/work.d.mts +114 -0
  339. package/dist/physics/energy/work.mjs +219 -0
  340. package/dist/physics/gravitation/body.d.mts +85 -0
  341. package/dist/physics/gravitation/body.mjs +168 -0
  342. package/dist/physics/gravitation/kepler.d.mts +127 -0
  343. package/dist/physics/gravitation/kepler.mjs +216 -0
  344. package/dist/physics/gravitation/law.d.mts +117 -0
  345. package/dist/physics/gravitation/law.mjs +175 -0
  346. package/dist/physics/gravitation/orbit.d.mts +119 -0
  347. package/dist/physics/gravitation/orbit.mjs +202 -0
  348. package/dist/physics/gravitation/potential.d.mts +114 -0
  349. package/dist/physics/gravitation/potential.mjs +202 -0
  350. package/dist/physics/gravitation/variation.d.mts +97 -0
  351. package/dist/physics/gravitation/variation.mjs +175 -0
  352. package/dist/physics/index.d.mts +35 -0
  353. package/dist/physics/index.mjs +36 -0
  354. package/dist/physics/integral-sweep.d.mts +63 -0
  355. package/dist/physics/integral-sweep.mjs +126 -0
  356. package/dist/physics/kinematics/equations.d.mts +47 -0
  357. package/dist/physics/kinematics/equations.mjs +126 -0
  358. package/dist/physics/kinematics/free-fall.d.mts +53 -0
  359. package/dist/physics/kinematics/free-fall.mjs +71 -0
  360. package/dist/physics/kinematics/given.d.mts +16 -0
  361. package/dist/physics/kinematics/given.mjs +55 -0
  362. package/dist/physics/kinematics/roots.d.mts +41 -0
  363. package/dist/physics/kinematics/roots.mjs +72 -0
  364. package/dist/physics/kinematics/solve.d.mts +52 -0
  365. package/dist/physics/kinematics/solve.mjs +172 -0
  366. package/dist/physics/magnetism/biot-savart.d.mts +161 -0
  367. package/dist/physics/magnetism/biot-savart.mjs +353 -0
  368. package/dist/physics/magnetism/flux.d.mts +94 -0
  369. package/dist/physics/magnetism/flux.mjs +313 -0
  370. package/dist/physics/magnetism/geomagnetism.d.mts +151 -0
  371. package/dist/physics/magnetism/geomagnetism.mjs +184 -0
  372. package/dist/physics/magnetism/index.d.mts +12 -0
  373. package/dist/physics/magnetism/index.mjs +74 -0
  374. package/dist/physics/magnetism/lorentz.d.mts +28 -0
  375. package/dist/physics/magnetism/lorentz.mjs +88 -0
  376. package/dist/physics/magnetism/magnetic-force.d.mts +102 -0
  377. package/dist/physics/magnetism/magnetic-force.mjs +169 -0
  378. package/dist/physics/momentum/collide.d.mts +77 -0
  379. package/dist/physics/momentum/collide.mjs +115 -0
  380. package/dist/physics/momentum/impulse.d.mts +89 -0
  381. package/dist/physics/momentum/impulse.mjs +159 -0
  382. package/dist/physics/momentum/planar.d.mts +60 -0
  383. package/dist/physics/momentum/planar.mjs +110 -0
  384. package/dist/physics/projectile.d.mts +107 -0
  385. package/dist/physics/projectile.mjs +185 -0
  386. package/dist/physics/rotation/angular.d.mts +85 -0
  387. package/dist/physics/rotation/angular.mjs +130 -0
  388. package/dist/physics/rotation/circular.d.mts +79 -0
  389. package/dist/physics/rotation/circular.mjs +131 -0
  390. package/dist/physics/rotation/inertia.d.mts +164 -0
  391. package/dist/physics/rotation/inertia.mjs +332 -0
  392. package/dist/physics/rotation/torque.d.mts +65 -0
  393. package/dist/physics/rotation/torque.mjs +134 -0
  394. package/dist/physics/vectors.d.mts +64 -0
  395. package/dist/physics/vectors.mjs +114 -0
  396. package/dist/primitives/Dot.d.mts +2 -15
  397. package/dist/primitives/Dot.mjs +6 -4
  398. package/dist/primitives/Grid.d.mts +33 -17
  399. package/dist/primitives/Grid.mjs +89 -17
  400. package/dist/primitives/Label.d.mts +1 -14
  401. package/dist/primitives/Label.mjs +3 -2
  402. package/dist/primitives/Lines.d.mts +4 -32
  403. package/dist/primitives/Lines.mjs +10 -8
  404. package/dist/primitives/Shapes.d.mts +5 -43
  405. package/dist/primitives/Shapes.mjs +12 -10
  406. package/dist/primitives/index.d.mts +2 -2
  407. package/dist/primitives/index.mjs +2 -2
  408. package/dist/primitives/props.mjs +31 -0
  409. package/dist/quantity/index.d.mts +119 -0
  410. package/dist/quantity/index.mjs +417 -0
  411. package/dist/relation/derive.d.mts +74 -0
  412. package/dist/relation/derive.mjs +73 -0
  413. package/dist/relation/index.d.mts +56 -0
  414. package/dist/relation/index.mjs +234 -0
  415. package/dist/scene/Scene.d.mts +6 -1
  416. package/dist/scene/Scene.mjs +15 -40
  417. package/dist/scene/evaluators.mjs +1 -1
  418. package/dist/sim/thermal.mjs +45 -20
  419. package/dist/thermo/calorimetry.d.mts +207 -0
  420. package/dist/thermo/calorimetry.mjs +345 -0
  421. package/dist/thermo/cycles.d.mts +142 -0
  422. package/dist/thermo/cycles.mjs +256 -0
  423. package/dist/thermo/entropy.d.mts +87 -0
  424. package/dist/thermo/entropy.mjs +140 -0
  425. package/dist/thermo/expansion.d.mts +130 -0
  426. package/dist/thermo/expansion.mjs +178 -0
  427. package/dist/thermo/gas.d.mts +197 -0
  428. package/dist/thermo/gas.mjs +279 -0
  429. package/dist/thermo/heat-transfer.d.mts +164 -0
  430. package/dist/thermo/heat-transfer.mjs +217 -0
  431. package/dist/thermo/index.d.mts +9 -82
  432. package/dist/thermo/index.mjs +9 -132
  433. package/dist/thermo/processes.d.mts +95 -0
  434. package/dist/thermo/processes.mjs +154 -0
  435. package/dist/thermo/temperature.d.mts +174 -0
  436. package/dist/thermo/temperature.mjs +236 -0
  437. package/dist/view/Stage.mjs +4 -11
  438. package/dist/waves/damping.d.mts +224 -0
  439. package/dist/waves/damping.mjs +317 -0
  440. package/dist/waves/doppler.d.mts +72 -0
  441. package/dist/waves/doppler.mjs +125 -0
  442. package/dist/waves/index.d.mts +10 -0
  443. package/dist/waves/index.mjs +10 -0
  444. package/dist/waves/pendulum.d.mts +130 -0
  445. package/dist/waves/pendulum.mjs +211 -0
  446. package/dist/waves/pitch.d.mts +125 -0
  447. package/dist/waves/pitch.mjs +158 -0
  448. package/dist/waves/shm.d.mts +170 -0
  449. package/dist/waves/shm.mjs +279 -0
  450. package/dist/waves/springs.d.mts +103 -0
  451. package/dist/waves/springs.mjs +176 -0
  452. package/dist/waves/superposition.d.mts +124 -0
  453. package/dist/waves/superposition.mjs +196 -0
  454. package/dist/waves/wave.d.mts +154 -0
  455. package/dist/waves/wave.mjs +178 -0
  456. package/package.json +103 -23
  457. package/styles.css +125 -8
  458. package/dist/assets/kit/index.mjs +0 -4
@@ -0,0 +1,163 @@
1
+ import { Edge } from "./topology.mjs";
2
+ import { Complex } from "../math/complex.mjs";
3
+
4
+ //#region src/circuit/ac.d.ts
5
+ type ElementKind = 'R' | 'L' | 'C';
6
+ /** One component. Ohms for R, henries for L, farads for C. */
7
+ interface Element extends Edge {
8
+ kind: ElementKind;
9
+ value: number;
10
+ }
11
+ interface AcNetwork {
12
+ elements: Element[];
13
+ terminals: [string, string];
14
+ }
15
+ /** A resistance so small it is a wire, used to keep a division from blowing up. */
16
+ declare const TINY = 1e-12;
17
+ /**
18
+ * The impedance of one component at angular frequency ω.
19
+ *
20
+ * R Z = R real, and the same at every frequency
21
+ * L Z = jωL purely positive-imaginary: current LAGS the voltage
22
+ * C Z = 1/(jωC) = −j/(ωC) purely negative-imaginary: current LEADS the voltage
23
+ *
24
+ * The signs are the whole content of the topic, and they are why a capacitor and an inductor can
25
+ * cancel each other out exactly.
26
+ */
27
+ declare function impedanceOf(element: Element, omegaRadPerS: number): Complex;
28
+ /** Reactance: the imaginary part. Positive is inductive, negative is capacitive. */
29
+ declare const reactance: (z: Complex) => number;
30
+ /** Resistance: the real part, which is the only part that dissipates energy. */
31
+ declare const resistance: (z: Complex) => number;
32
+ /** Magnitude |Z|, in ohms. */
33
+ declare const magnitude: (z: Complex) => number;
34
+ /** Phase of the impedance in degrees. Positive means the current lags the voltage. */
35
+ declare const phaseDeg: (z: Complex) => number;
36
+ /** Series impedances add. Always, for every component kind, at every frequency. */
37
+ declare function seriesImpedance(zs: readonly Complex[]): Complex;
38
+ /**
39
+ * Parallel impedances combine by adding ADMITTANCES, Y = 1/Z.
40
+ *
41
+ * An infinite impedance (a capacitor at DC) contributes zero admittance rather than breaking the
42
+ * sum, which is both numerically necessary and physically exactly right: an open branch in parallel
43
+ * changes nothing.
44
+ */
45
+ declare function parallelImpedance(zs: readonly Complex[]): Complex;
46
+ /**
47
+ * The equivalent impedance between the terminals at one frequency.
48
+ *
49
+ * Uses the same structural rules as the DC reducer, from `topology.ts`, because the shape of a
50
+ * network has nothing to do with what it is made of. Only the arithmetic differs, and here the
51
+ * arithmetic is complex.
52
+ *
53
+ * A reduced edge is carried as an R whose "value" is meaningless; what matters is the impedance map
54
+ * kept alongside. Doing it that way means a merged branch is a first-class edge for the next rule
55
+ * rather than a special case.
56
+ */
57
+ declare function equivalentImpedance(network: AcNetwork, omegaRadPerS: number): Complex | null;
58
+ /**
59
+ * The equivalent impedance of ANY network, by nodal analysis in the frequency domain.
60
+ *
61
+ * Where `equivalentImpedance` reduces by series and parallel and gives up honestly when those run
62
+ * out, this always answers. It injects one amp into the first terminal, grounds the second, solves
63
+ * the complex nodal equations and reads the voltage that appears: Z = V/I with I = 1.
64
+ *
65
+ * This is what makes the engine complete rather than merely correct. An unbalanced AC bridge has no
66
+ * series or parallel move anywhere in it, which is a fact about the shape and not a gap in the
67
+ * rules, and before this it could only be reported as unsolvable. A tool that reports defeat on a
68
+ * circuit an undergraduate is expected to analyse is a teaching aid, not an engine.
69
+ *
70
+ * The two coexist on purpose: the reducer narrates and this one answers, and the tests require them
71
+ * to agree wherever the reducer can finish.
72
+ */
73
+ declare function impedanceByNodalAnalysis(network: AcNetwork, omegaRadPerS: number): Complex | null;
74
+ /**
75
+ * Does an AC bridge balance?
76
+ *
77
+ * The condition is Z_P/Z_Q = Z_R/Z_S as COMPLEX numbers, which means the magnitudes must be in
78
+ * proportion AND the phases must match. That is two conditions, not one, and it is exactly why a
79
+ * real AC bridge has two adjustable components where a Wheatstone bridge has one. A student who
80
+ * has only met the DC bridge finds this genuinely surprising, and it falls straight out of using
81
+ * complex numbers rather than being an extra rule to remember.
82
+ */
83
+ declare function bridgeBalances(p: Complex, q: Complex, r: Complex, s: Complex): boolean;
84
+ /**
85
+ * The angular frequency at which an inductor and a capacitor cancel exactly.
86
+ *
87
+ * ωL = 1/(ωC) so ω₀ = 1/√(LC)
88
+ *
89
+ * At ω₀ a series LC pair has zero net reactance, so a series RLC looks purely resistive and the
90
+ * current is at a maximum. That is the whole of tuning: a radio picks one station by making its
91
+ * circuit resonate there and nowhere else.
92
+ */
93
+ declare function resonantOmega(henries: number, farads: number): number;
94
+ /** Resonance in hertz, which is what a dial is marked in. */
95
+ declare const resonantHz: (henries: number, farads: number) => number;
96
+ /**
97
+ * The quality factor of a series RLC: how sharply it selects its resonant frequency.
98
+ *
99
+ * Q = (1/R)·√(L/C)
100
+ *
101
+ * A high Q is a narrow peak, which is a radio that separates adjacent stations. Resistance is what
102
+ * spoils it, because resistance is the only part that takes energy out of the oscillation.
103
+ */
104
+ declare function qualityFactor(ohms: number, henries: number, farads: number): number;
105
+ /** The width of the resonance peak between its half-power points, in rad/s. */
106
+ declare const bandwidthRadPerS: (ohms: number, henries: number, farads: number) => number;
107
+ interface AcResponse {
108
+ omegaRadPerS: number;
109
+ impedance: Complex;
110
+ /** |Z| in ohms. */
111
+ magnitudeOhm: number;
112
+ /** Phase of Z in degrees: positive means the current lags. */
113
+ phaseDeg: number;
114
+ /** Peak current for a given peak driving voltage, in amps. */
115
+ currentAmp: number;
116
+ /** Phase of the CURRENT relative to the driving voltage, in degrees. The negative of Z's phase. */
117
+ currentPhaseDeg: number;
118
+ }
119
+ /** How a network responds to a sinusoid of a given peak voltage at one frequency. */
120
+ declare function responseAt(network: AcNetwork, omegaRadPerS: number, drivePeakV?: number): AcResponse | null;
121
+ /**
122
+ * A frequency sweep, spaced logarithmically.
123
+ *
124
+ * Log spacing is not a presentation choice. A response that matters over four decades has almost
125
+ * all of its structure in the first decade, and a linear sweep spends 90% of its points on the last
126
+ * one, where nothing happens. Every instrument that measures this sweeps logarithmically.
127
+ */
128
+ declare function sweep(network: AcNetwork, omegaFrom: number, omegaTo: number, points?: number, drivePeakV?: number): AcResponse[];
129
+ /**
130
+ * The power factor, cos φ.
131
+ *
132
+ * Only the resistance dissipates energy. A purely reactive component takes energy in for a quarter
133
+ * cycle and gives every joule back in the next, so it carries current and consumes nothing. A
134
+ * factory with a poor power factor pays for current it never turns into anything, which is why
135
+ * power factor correction is a real industrial expense rather than a textbook curiosity.
136
+ */
137
+ declare const powerFactor: (z: Complex) => number;
138
+ /** Average power actually dissipated, from RMS current: only the real part counts. */
139
+ declare const realPowerW: (z: Complex, rmsCurrentAmp: number) => number;
140
+ /** Apparent power, which is what the supply has to be sized for: |Z| I². */
141
+ declare const apparentPowerVA: (z: Complex, rmsCurrentAmp: number) => number;
142
+ /** RMS is the peak divided by root two, for a sinusoid and for nothing else. */
143
+ declare const rmsFromPeak: (peak: number) => number;
144
+ /** A series RLC between A and B, the circuit every resonance question is about. */
145
+ declare function seriesRlc(ohms: number, henries: number, farads: number): AcNetwork;
146
+ /** A first-order RC low-pass: output taken across the capacitor. */
147
+ declare function rcLowPass(ohms: number, farads: number): AcNetwork;
148
+ /** The −3 dB corner of a first-order RC, where |Z_C| = R and the output has fallen to 1/√2. */
149
+ declare const rcCornerOmega: (ohms: number, farads: number) => number;
150
+ /**
151
+ * The transfer function of a two-element divider: what fraction of the input appears across the
152
+ * second element, as a complex number carrying both size and phase shift.
153
+ *
154
+ * This is the potential divider again, with complex numbers, and recognising that is most of what
155
+ * makes filters approachable.
156
+ */
157
+ declare function dividerGain(zSeries: Complex, zShunt: Complex): Complex;
158
+ /** Gain expressed in decibels, which is how every frequency response is actually plotted. */
159
+ declare const decibels: (gain: number) => number;
160
+ /** Multiply two complex numbers, re-exported so a caller need not import the maths kernel too. */
161
+ declare const timesC: (a: Complex, b: Complex) => Complex;
162
+ //#endregion
163
+ export { AcNetwork, AcResponse, Element, ElementKind, TINY, apparentPowerVA, bandwidthRadPerS, bridgeBalances, decibels, dividerGain, equivalentImpedance, impedanceByNodalAnalysis, impedanceOf, magnitude, parallelImpedance, phaseDeg, powerFactor, qualityFactor, rcCornerOmega, rcLowPass, reactance, realPowerW, resistance, resonantHz, resonantOmega, responseAt, rmsFromPeak, seriesImpedance, seriesRlc, sweep, timesC };
@@ -0,0 +1,452 @@
1
+ import { complex_exports } from "../math/complex.mjs";
2
+ import { findBridgeShape, findDangling, findParallelGroup, findSelfLoop, findSeriesPair, isReduced, mergedId, validateTopology } from "./topology.mjs";
3
+
4
+ //#region src/circuit/ac.ts
5
+ /**
6
+ * @classytic/stage/circuit/ac-impedance — AC steady state: impedance, phasors, resonance and the frequency response of a network.
7
+ *
8
+ * This is the engine the DC ones were a special case of, and saying that plainly is the point of
9
+ * the file. `network-reduction` showed that resistors and capacitors reduce by the same rules with
10
+ * the arithmetic swapped. The swap was never real. It was an artefact of insisting on real numbers:
11
+ *
12
+ * Z_R = R Z_L = jωL Z_C = 1/(jωC)
13
+ *
14
+ * and with those, series ALWAYS adds impedance and parallel always adds admittance, for every
15
+ * component at every frequency. The reciprocal that looked like a special rule for capacitors is
16
+ * just what 1/(jωC) does when you add it up.
17
+ *
18
+ * ── What this buys that DC could not ────────────────────────────────────────────────────────────
19
+ * Everything that depends on frequency, which is most of what a circuit is actually used for:
20
+ * filters, resonance, tuning, coupling, the reason a loudspeaker crossover works, the reason an
21
+ * oscilloscope probe is compensated. It is the core of an undergraduate circuits course and it is
22
+ * on A2 physics as the LCR circuit.
23
+ *
24
+ * ── How it is checked ───────────────────────────────────────────────────────────────────────────
25
+ * Phasor algebra is easy to get subtly wrong in the sign of the reactance, and a test that compares
26
+ * the algebra with itself would never notice. So the tests integrate the governing ODE of a driven
27
+ * series RLC forward in time and measure the steady-state amplitude and phase off the waveform,
28
+ * then compare that with what this file predicts. Time domain against frequency domain is the
29
+ * strongest independent check available for this, and it catches a sign error immediately: a
30
+ * current that should lag would be measured leading.
31
+ */
32
+ /**
33
+ * The complex kernel is NAMESPACED on purpose, and must stay that way here.
34
+ *
35
+ * `@classytic/stage/math` re-exports it as `export * as complex` because `complex` and `poly` both
36
+ * export an `add` and a `mul` that mean entirely different things. Importing them flat compiles and
37
+ * then silently resolves to whichever the bundler saw last. `C.add` costs two characters and
38
+ * removes the possibility.
39
+ */
40
+ const { abs, add, argDeg, cx, div, mul, sub } = complex_exports;
41
+ const finitePositive = (value, what) => {
42
+ if (!Number.isFinite(value) || value <= 0) throw new RangeError(`${what} must be positive`);
43
+ return value;
44
+ };
45
+ const finiteNonNegative = (value, what) => {
46
+ if (!Number.isFinite(value) || value < 0) throw new RangeError(`${what} must be zero or more`);
47
+ return value;
48
+ };
49
+ /** A resistance so small it is a wire, used to keep a division from blowing up. */
50
+ const TINY = 1e-12;
51
+ /**
52
+ * The impedance of one component at angular frequency ω.
53
+ *
54
+ * R Z = R real, and the same at every frequency
55
+ * L Z = jωL purely positive-imaginary: current LAGS the voltage
56
+ * C Z = 1/(jωC) = −j/(ωC) purely negative-imaginary: current LEADS the voltage
57
+ *
58
+ * The signs are the whole content of the topic, and they are why a capacitor and an inductor can
59
+ * cancel each other out exactly.
60
+ */
61
+ function impedanceOf(element, omegaRadPerS) {
62
+ const omega = finiteNonNegative(omegaRadPerS, "angular frequency");
63
+ switch (element.kind) {
64
+ case "R": return cx(finiteNonNegative(element.value, `resistor ${element.id}`), 0);
65
+ case "L": return cx(0, omega * finiteNonNegative(element.value, `inductor ${element.id}`));
66
+ case "C": {
67
+ const c = finitePositive(element.value, `capacitor ${element.id}`);
68
+ if (omega === 0) return cx(Infinity, 0);
69
+ return cx(0, -1 / (omega * c));
70
+ }
71
+ }
72
+ }
73
+ /** Reactance: the imaginary part. Positive is inductive, negative is capacitive. */
74
+ const reactance = (z) => z.im;
75
+ /** Resistance: the real part, which is the only part that dissipates energy. */
76
+ const resistance = (z) => z.re;
77
+ /** Magnitude |Z|, in ohms. */
78
+ const magnitude = (z) => abs(z);
79
+ /** Phase of the impedance in degrees. Positive means the current lags the voltage. */
80
+ const phaseDeg = (z) => argDeg(z);
81
+ /** Series impedances add. Always, for every component kind, at every frequency. */
82
+ function seriesImpedance(zs) {
83
+ return zs.reduce((sum, z) => add(sum, z), cx(0, 0));
84
+ }
85
+ /**
86
+ * Parallel impedances combine by adding ADMITTANCES, Y = 1/Z.
87
+ *
88
+ * An infinite impedance (a capacitor at DC) contributes zero admittance rather than breaking the
89
+ * sum, which is both numerically necessary and physically exactly right: an open branch in parallel
90
+ * changes nothing.
91
+ */
92
+ function parallelImpedance(zs) {
93
+ let y = cx(0, 0);
94
+ for (const z of zs) {
95
+ if (!Number.isFinite(z.re) || !Number.isFinite(z.im)) continue;
96
+ if (abs(z) < 1e-12) return cx(0, 0);
97
+ y = add(y, div(cx(1, 0), z));
98
+ }
99
+ if (abs(y) < 1e-12) return cx(Infinity, 0);
100
+ return div(cx(1, 0), y);
101
+ }
102
+ const asTopology = (network) => ({
103
+ edges: network.elements,
104
+ terminals: network.terminals
105
+ });
106
+ /**
107
+ * The equivalent impedance between the terminals at one frequency.
108
+ *
109
+ * Uses the same structural rules as the DC reducer, from `topology.ts`, because the shape of a
110
+ * network has nothing to do with what it is made of. Only the arithmetic differs, and here the
111
+ * arithmetic is complex.
112
+ *
113
+ * A reduced edge is carried as an R whose "value" is meaningless; what matters is the impedance map
114
+ * kept alongside. Doing it that way means a merged branch is a first-class edge for the next rule
115
+ * rather than a special case.
116
+ */
117
+ function equivalentImpedance(network, omegaRadPerS) {
118
+ validateTopology(asTopology(network));
119
+ const omega = finiteNonNegative(omegaRadPerS, "angular frequency");
120
+ let edges = network.elements.map((e) => ({
121
+ id: e.id,
122
+ a: e.a,
123
+ b: e.b
124
+ }));
125
+ const z = /* @__PURE__ */ new Map();
126
+ for (const element of network.elements) z.set(element.id, impedanceOf(element, omega));
127
+ const terminals = network.terminals;
128
+ const zOf = (edge) => z.get(edge.id) ?? cx(0, 0);
129
+ let guard = edges.length * 4 + 8;
130
+ while (guard-- > 0) {
131
+ const t = {
132
+ edges,
133
+ terminals
134
+ };
135
+ if (isReduced(t)) break;
136
+ const dangling = findDangling(t);
137
+ if (dangling) {
138
+ edges = edges.filter((e) => e.id !== dangling.edge.id);
139
+ continue;
140
+ }
141
+ const loop = findSelfLoop(t);
142
+ if (loop) {
143
+ edges = edges.filter((e) => e.id !== loop.id);
144
+ continue;
145
+ }
146
+ const group = findParallelGroup(t);
147
+ if (group) {
148
+ const id = mergedId(t, group);
149
+ const combined = parallelImpedance(group.map(zOf));
150
+ const ids = new Set(group.map((e) => e.id));
151
+ edges = [...edges.filter((e) => !ids.has(e.id)), {
152
+ id,
153
+ a: group[0].a,
154
+ b: group[0].b
155
+ }];
156
+ z.set(id, combined);
157
+ continue;
158
+ }
159
+ const pair = findSeriesPair(t);
160
+ if (pair) {
161
+ const id = mergedId(t, pair.edges);
162
+ const combined = seriesImpedance(pair.edges.map(zOf));
163
+ const ids = new Set(pair.edges.map((e) => e.id));
164
+ edges = [...edges.filter((e) => !ids.has(e.id)), {
165
+ id,
166
+ a: pair.ends[0],
167
+ b: pair.ends[1]
168
+ }];
169
+ z.set(id, combined);
170
+ continue;
171
+ }
172
+ const shape = findBridgeShape(t);
173
+ if (shape && bridgeBalances(zOf(shape.p), zOf(shape.q), zOf(shape.r), zOf(shape.s))) {
174
+ edges = edges.filter((e) => e.id !== shape.bridge.id);
175
+ continue;
176
+ }
177
+ return null;
178
+ }
179
+ const only = edges[0];
180
+ return only ? zOf(only) : null;
181
+ }
182
+ /**
183
+ * Complex Gaussian elimination with partial pivoting.
184
+ *
185
+ * `solveLinear` in `@classytic/stage/circuit` does this for real matrices and cannot be reused:
186
+ * every entry here is a complex admittance, and pivoting has to compare MAGNITUDES rather than
187
+ * signed values. Small enough to own, and the alternative is to represent each complex unknown as
188
+ * two real ones and solve a system of twice the size, which doubles the work and makes every
189
+ * intermediate unreadable.
190
+ */
191
+ function solveComplexLinear(matrix, rhs) {
192
+ const n = rhs.length;
193
+ const a = matrix.map((row, i) => [...row, rhs[i]]);
194
+ for (let col = 0; col < n; col++) {
195
+ let best = col;
196
+ for (let row = col + 1; row < n; row++) if (abs(a[row][col]) > abs(a[best][col])) best = row;
197
+ if (abs(a[best][col]) < 1e-18) return null;
198
+ if (best !== col) {
199
+ const swap = a[best];
200
+ a[best] = a[col];
201
+ a[col] = swap;
202
+ }
203
+ const pivot = a[col][col];
204
+ for (let row = col + 1; row < n; row++) {
205
+ const factor = div(a[row][col], pivot);
206
+ if (abs(factor) === 0) continue;
207
+ for (let k = col; k <= n; k++) a[row][k] = sub(a[row][k], mul(factor, a[col][k]));
208
+ }
209
+ }
210
+ const out = new Array(n).fill(cx(0, 0));
211
+ for (let row = n - 1; row >= 0; row--) {
212
+ let sum = a[row][n];
213
+ for (let col = row + 1; col < n; col++) sum = sub(sum, mul(a[row][col], out[col]));
214
+ out[row] = div(sum, a[row][row]);
215
+ }
216
+ return out;
217
+ }
218
+ /** Admittance of one element, with the two degenerate cases handled explicitly. */
219
+ function admittanceOf(element, omega) {
220
+ const z = impedanceOf(element, omega);
221
+ if (!Number.isFinite(z.re) || !Number.isFinite(z.im)) return cx(0, 0);
222
+ if (abs(z) < 1e-12) return cx(1 / TINY, 0);
223
+ return div(cx(1, 0), z);
224
+ }
225
+ /**
226
+ * The equivalent impedance of ANY network, by nodal analysis in the frequency domain.
227
+ *
228
+ * Where `equivalentImpedance` reduces by series and parallel and gives up honestly when those run
229
+ * out, this always answers. It injects one amp into the first terminal, grounds the second, solves
230
+ * the complex nodal equations and reads the voltage that appears: Z = V/I with I = 1.
231
+ *
232
+ * This is what makes the engine complete rather than merely correct. An unbalanced AC bridge has no
233
+ * series or parallel move anywhere in it, which is a fact about the shape and not a gap in the
234
+ * rules, and before this it could only be reported as unsolvable. A tool that reports defeat on a
235
+ * circuit an undergraduate is expected to analyse is a teaching aid, not an engine.
236
+ *
237
+ * The two coexist on purpose: the reducer narrates and this one answers, and the tests require them
238
+ * to agree wherever the reducer can finish.
239
+ */
240
+ function impedanceByNodalAnalysis(network, omegaRadPerS) {
241
+ validateTopology(asTopology(network));
242
+ const omega = finiteNonNegative(omegaRadPerS, "angular frequency");
243
+ const [source, ground] = network.terminals;
244
+ const index = /* @__PURE__ */ new Map();
245
+ for (const element of network.elements) for (const node of [element.a, element.b]) if (node !== ground && !index.has(node)) index.set(node, index.size);
246
+ const driven = index.get(source);
247
+ if (driven === void 0) return null;
248
+ const n = index.size;
249
+ const build = (gmin) => {
250
+ const y = Array.from({ length: n }, () => Array.from({ length: n }, () => cx(0, 0)));
251
+ for (let k = 0; k < n; k++) y[k][k] = cx(gmin, 0);
252
+ for (const element of network.elements) {
253
+ const ya = admittanceOf(element, omega);
254
+ const i = element.a === ground ? -1 : index.get(element.a);
255
+ const j = element.b === ground ? -1 : index.get(element.b);
256
+ if (i === j) continue;
257
+ if (i >= 0) y[i][i] = add(y[i][i], ya);
258
+ if (j >= 0) y[j][j] = add(y[j][j], ya);
259
+ if (i >= 0 && j >= 0) {
260
+ y[i][j] = sub(y[i][j], ya);
261
+ y[j][i] = sub(y[j][i], ya);
262
+ }
263
+ }
264
+ return y;
265
+ };
266
+ const current = Array.from({ length: n }, (_, k) => k === driven ? cx(1, 0) : cx(0, 0));
267
+ /**
268
+ * A dangling branch leaves its far node connected to nothing else, which makes the matrix
269
+ * singular even though the network has a perfectly good answer. A tiny conductance to ground on
270
+ * every node fixes exactly that, and is what every circuit simulator does for the same reason.
271
+ * It is tried SECOND so an ordinary network is solved with no perturbation at all.
272
+ */
273
+ const solved = solveComplexLinear(build(0), current) ?? solveComplexLinear(build(1e-12), current);
274
+ if (!solved) return null;
275
+ const v = solved[driven];
276
+ return v && Number.isFinite(v.re) && Number.isFinite(v.im) ? v : null;
277
+ }
278
+ /**
279
+ * Does an AC bridge balance?
280
+ *
281
+ * The condition is Z_P/Z_Q = Z_R/Z_S as COMPLEX numbers, which means the magnitudes must be in
282
+ * proportion AND the phases must match. That is two conditions, not one, and it is exactly why a
283
+ * real AC bridge has two adjustable components where a Wheatstone bridge has one. A student who
284
+ * has only met the DC bridge finds this genuinely surprising, and it falls straight out of using
285
+ * complex numbers rather than being an extra rule to remember.
286
+ */
287
+ function bridgeBalances(p, q, r, s) {
288
+ if (abs(q) < 1e-12 || abs(s) < 1e-12) return false;
289
+ const left = div(p, q);
290
+ const right = div(r, s);
291
+ const scale = Math.max(1, abs(left), abs(right));
292
+ return abs({
293
+ re: left.re - right.re,
294
+ im: left.im - right.im
295
+ }) < 1e-9 * scale;
296
+ }
297
+ /**
298
+ * The angular frequency at which an inductor and a capacitor cancel exactly.
299
+ *
300
+ * ωL = 1/(ωC) so ω₀ = 1/√(LC)
301
+ *
302
+ * At ω₀ a series LC pair has zero net reactance, so a series RLC looks purely resistive and the
303
+ * current is at a maximum. That is the whole of tuning: a radio picks one station by making its
304
+ * circuit resonate there and nowhere else.
305
+ */
306
+ function resonantOmega(henries, farads) {
307
+ return 1 / Math.sqrt(finitePositive(henries, "inductance") * finitePositive(farads, "capacitance"));
308
+ }
309
+ /** Resonance in hertz, which is what a dial is marked in. */
310
+ const resonantHz = (henries, farads) => resonantOmega(henries, farads) / (2 * Math.PI);
311
+ /**
312
+ * The quality factor of a series RLC: how sharply it selects its resonant frequency.
313
+ *
314
+ * Q = (1/R)·√(L/C)
315
+ *
316
+ * A high Q is a narrow peak, which is a radio that separates adjacent stations. Resistance is what
317
+ * spoils it, because resistance is the only part that takes energy out of the oscillation.
318
+ */
319
+ function qualityFactor(ohms, henries, farads) {
320
+ const r = finitePositive(ohms, "resistance");
321
+ return Math.sqrt(finitePositive(henries, "inductance") / finitePositive(farads, "capacitance")) / r;
322
+ }
323
+ /** The width of the resonance peak between its half-power points, in rad/s. */
324
+ const bandwidthRadPerS = (ohms, henries, farads) => resonantOmega(henries, farads) / qualityFactor(ohms, henries, farads);
325
+ /** How a network responds to a sinusoid of a given peak voltage at one frequency. */
326
+ function responseAt(network, omegaRadPerS, drivePeakV = 1) {
327
+ /**
328
+ * Uses the GENERAL solver, not the reducer.
329
+ *
330
+ * A frequency response is not a teaching narrative, it is an answer, and an unbalanced bridge has
331
+ * one even though series and parallel cannot find it. Reaching for the reducer here would make
332
+ * whole families of perfectly ordinary circuits unplottable.
333
+ */
334
+ const impedance = impedanceByNodalAnalysis(network, omegaRadPerS);
335
+ if (!impedance) return null;
336
+ const magnitudeOhm = abs(impedance);
337
+ const drive = finiteNonNegative(drivePeakV, "driving voltage");
338
+ return {
339
+ omegaRadPerS,
340
+ impedance,
341
+ magnitudeOhm,
342
+ phaseDeg: argDeg(impedance),
343
+ currentAmp: magnitudeOhm > 1e-12 && Number.isFinite(magnitudeOhm) ? drive / magnitudeOhm : 0,
344
+ currentPhaseDeg: -argDeg(impedance)
345
+ };
346
+ }
347
+ /**
348
+ * A frequency sweep, spaced logarithmically.
349
+ *
350
+ * Log spacing is not a presentation choice. A response that matters over four decades has almost
351
+ * all of its structure in the first decade, and a linear sweep spends 90% of its points on the last
352
+ * one, where nothing happens. Every instrument that measures this sweeps logarithmically.
353
+ */
354
+ function sweep(network, omegaFrom, omegaTo, points = 120, drivePeakV = 1) {
355
+ const from = finitePositive(omegaFrom, "start frequency");
356
+ const to = finitePositive(omegaTo, "end frequency");
357
+ if (to <= from) throw new RangeError("the sweep must end above where it started");
358
+ const n = Math.max(2, Math.floor(points));
359
+ const out = [];
360
+ for (let i = 0; i < n; i++) {
361
+ const response = responseAt(network, from * (to / from) ** (i / (n - 1)), drivePeakV);
362
+ if (response) out.push(response);
363
+ }
364
+ return out;
365
+ }
366
+ /**
367
+ * The power factor, cos φ.
368
+ *
369
+ * Only the resistance dissipates energy. A purely reactive component takes energy in for a quarter
370
+ * cycle and gives every joule back in the next, so it carries current and consumes nothing. A
371
+ * factory with a poor power factor pays for current it never turns into anything, which is why
372
+ * power factor correction is a real industrial expense rather than a textbook curiosity.
373
+ */
374
+ const powerFactor = (z) => {
375
+ const m = abs(z);
376
+ return m < 1e-12 ? 1 : z.re / m;
377
+ };
378
+ /** Average power actually dissipated, from RMS current: only the real part counts. */
379
+ const realPowerW = (z, rmsCurrentAmp) => finiteNonNegative(rmsCurrentAmp, "current") ** 2 * z.re;
380
+ /** Apparent power, which is what the supply has to be sized for: |Z| I². */
381
+ const apparentPowerVA = (z, rmsCurrentAmp) => finiteNonNegative(rmsCurrentAmp, "current") ** 2 * abs(z);
382
+ /** RMS is the peak divided by root two, for a sinusoid and for nothing else. */
383
+ const rmsFromPeak = (peak) => finiteNonNegative(peak, "peak") / Math.SQRT2;
384
+ /** A series RLC between A and B, the circuit every resonance question is about. */
385
+ function seriesRlc(ohms, henries, farads) {
386
+ return {
387
+ terminals: ["A", "B"],
388
+ elements: [
389
+ {
390
+ id: "R",
391
+ kind: "R",
392
+ value: ohms,
393
+ a: "A",
394
+ b: "M"
395
+ },
396
+ {
397
+ id: "L",
398
+ kind: "L",
399
+ value: henries,
400
+ a: "M",
401
+ b: "N"
402
+ },
403
+ {
404
+ id: "C",
405
+ kind: "C",
406
+ value: farads,
407
+ a: "N",
408
+ b: "B"
409
+ }
410
+ ]
411
+ };
412
+ }
413
+ /** A first-order RC low-pass: output taken across the capacitor. */
414
+ function rcLowPass(ohms, farads) {
415
+ return {
416
+ terminals: ["A", "B"],
417
+ elements: [{
418
+ id: "R",
419
+ kind: "R",
420
+ value: ohms,
421
+ a: "A",
422
+ b: "M"
423
+ }, {
424
+ id: "C",
425
+ kind: "C",
426
+ value: farads,
427
+ a: "M",
428
+ b: "B"
429
+ }]
430
+ };
431
+ }
432
+ /** The −3 dB corner of a first-order RC, where |Z_C| = R and the output has fallen to 1/√2. */
433
+ const rcCornerOmega = (ohms, farads) => 1 / (finitePositive(ohms, "resistance") * finitePositive(farads, "capacitance"));
434
+ /**
435
+ * The transfer function of a two-element divider: what fraction of the input appears across the
436
+ * second element, as a complex number carrying both size and phase shift.
437
+ *
438
+ * This is the potential divider again, with complex numbers, and recognising that is most of what
439
+ * makes filters approachable.
440
+ */
441
+ function dividerGain(zSeries, zShunt) {
442
+ const total = add(zSeries, zShunt);
443
+ if (abs(total) < 1e-12) return cx(0, 0);
444
+ return div(zShunt, total);
445
+ }
446
+ /** Gain expressed in decibels, which is how every frequency response is actually plotted. */
447
+ const decibels = (gain) => gain <= 0 ? -Infinity : 20 * Math.log10(gain);
448
+ /** Multiply two complex numbers, re-exported so a caller need not import the maths kernel too. */
449
+ const timesC = mul;
450
+
451
+ //#endregion
452
+ export { TINY, apparentPowerVA, bandwidthRadPerS, bridgeBalances, decibels, dividerGain, equivalentImpedance, impedanceByNodalAnalysis, impedanceOf, magnitude, parallelImpedance, phaseDeg, powerFactor, qualityFactor, rcCornerOmega, rcLowPass, reactance, realPowerW, resistance, resonantHz, resonantOmega, responseAt, rmsFromPeak, seriesImpedance, seriesRlc, sweep, timesC };