@vessel-dsp/compiler 0.0.0-stage → 0.3.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 (226) hide show
  1. package/README.md +118 -2
  2. package/dist/bake.d.ts +38 -0
  3. package/dist/bake.d.ts.map +1 -0
  4. package/dist/bake.js +101 -0
  5. package/dist/bake.js.map +1 -0
  6. package/dist/bbd-clock.d.ts +171 -0
  7. package/dist/bbd-clock.d.ts.map +1 -0
  8. package/dist/bbd-clock.js +1750 -0
  9. package/dist/bbd-clock.js.map +1 -0
  10. package/dist/block-row.d.ts +51 -0
  11. package/dist/block-row.d.ts.map +1 -0
  12. package/dist/block-row.js +17 -0
  13. package/dist/block-row.js.map +1 -0
  14. package/dist/bypass.d.ts +3 -0
  15. package/dist/bypass.d.ts.map +1 -0
  16. package/dist/bypass.js +228 -0
  17. package/dist/bypass.js.map +1 -0
  18. package/dist/compile.d.ts +24 -0
  19. package/dist/compile.d.ts.map +1 -0
  20. package/dist/compile.js +348 -0
  21. package/dist/compile.js.map +1 -0
  22. package/dist/converter-scale.d.ts +14 -0
  23. package/dist/converter-scale.d.ts.map +1 -0
  24. package/dist/converter-scale.js +133 -0
  25. package/dist/converter-scale.js.map +1 -0
  26. package/dist/couple.d.ts +28 -0
  27. package/dist/couple.d.ts.map +1 -0
  28. package/dist/couple.js +567 -0
  29. package/dist/couple.js.map +1 -0
  30. package/dist/dangling-active-terminal.d.ts +47 -0
  31. package/dist/dangling-active-terminal.d.ts.map +1 -0
  32. package/dist/dangling-active-terminal.js +542 -0
  33. package/dist/dangling-active-terminal.js.map +1 -0
  34. package/dist/declared-program.d.ts +23 -0
  35. package/dist/declared-program.d.ts.map +1 -0
  36. package/dist/declared-program.js +387 -0
  37. package/dist/declared-program.js.map +1 -0
  38. package/dist/denomination.d.ts +48 -0
  39. package/dist/denomination.d.ts.map +1 -0
  40. package/dist/denomination.js +27 -0
  41. package/dist/denomination.js.map +1 -0
  42. package/dist/device-laws.d.ts +237 -0
  43. package/dist/device-laws.d.ts.map +1 -0
  44. package/dist/device-laws.js +3513 -0
  45. package/dist/device-laws.js.map +1 -0
  46. package/dist/diagnostics.d.ts +13 -0
  47. package/dist/diagnostics.d.ts.map +1 -0
  48. package/dist/diagnostics.js +19 -0
  49. package/dist/diagnostics.js.map +1 -0
  50. package/dist/emit.d.ts +8 -0
  51. package/dist/emit.d.ts.map +1 -0
  52. package/dist/emit.js +43 -0
  53. package/dist/emit.js.map +1 -0
  54. package/dist/errors.d.ts +22 -0
  55. package/dist/errors.d.ts.map +1 -0
  56. package/dist/errors.js +39 -0
  57. package/dist/errors.js.map +1 -0
  58. package/dist/firmware-class.d.ts +69 -0
  59. package/dist/firmware-class.d.ts.map +1 -0
  60. package/dist/firmware-class.js +20 -0
  61. package/dist/firmware-class.js.map +1 -0
  62. package/dist/fixtures/circuits.d.ts +1742 -0
  63. package/dist/fixtures/circuits.d.ts.map +1 -0
  64. package/dist/fixtures/circuits.js +13896 -0
  65. package/dist/fixtures/circuits.js.map +1 -0
  66. package/dist/fixtures/expected.d.ts +261 -0
  67. package/dist/fixtures/expected.d.ts.map +1 -0
  68. package/dist/fixtures/expected.js +315 -0
  69. package/dist/fixtures/expected.js.map +1 -0
  70. package/dist/fixtures/index.d.ts +4 -0
  71. package/dist/fixtures/index.d.ts.map +1 -0
  72. package/dist/fixtures/index.js +8 -0
  73. package/dist/fixtures/index.js.map +1 -0
  74. package/dist/fixtures/registry.d.ts +52 -0
  75. package/dist/fixtures/registry.d.ts.map +1 -0
  76. package/dist/fixtures/registry.js +341 -0
  77. package/dist/fixtures/registry.js.map +1 -0
  78. package/dist/generic-tube-fit.d.ts +12 -0
  79. package/dist/generic-tube-fit.d.ts.map +1 -0
  80. package/dist/generic-tube-fit.js +45 -0
  81. package/dist/generic-tube-fit.js.map +1 -0
  82. package/dist/grounded-clock-supply.d.ts +13 -0
  83. package/dist/grounded-clock-supply.d.ts.map +1 -0
  84. package/dist/grounded-clock-supply.js +45 -0
  85. package/dist/grounded-clock-supply.js.map +1 -0
  86. package/dist/identify.d.ts +50 -0
  87. package/dist/identify.d.ts.map +1 -0
  88. package/dist/identify.js +319 -0
  89. package/dist/identify.js.map +1 -0
  90. package/dist/index.d.ts +10 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +19 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/inert-controls.d.ts +15 -0
  95. package/dist/inert-controls.d.ts.map +1 -0
  96. package/dist/inert-controls.js +266 -0
  97. package/dist/inert-controls.js.map +1 -0
  98. package/dist/latch-seed.d.ts +53 -0
  99. package/dist/latch-seed.d.ts.map +1 -0
  100. package/dist/latch-seed.js +257 -0
  101. package/dist/latch-seed.js.map +1 -0
  102. package/dist/link.d.ts +7 -0
  103. package/dist/link.d.ts.map +1 -0
  104. package/dist/link.js +270 -0
  105. package/dist/link.js.map +1 -0
  106. package/dist/lower.d.ts +79 -0
  107. package/dist/lower.d.ts.map +1 -0
  108. package/dist/lower.js +1855 -0
  109. package/dist/lower.js.map +1 -0
  110. package/dist/netlist.d.ts +79 -0
  111. package/dist/netlist.d.ts.map +1 -0
  112. package/dist/netlist.js +4746 -0
  113. package/dist/netlist.js.map +1 -0
  114. package/dist/non-executable-clock-drivers.d.ts +8 -0
  115. package/dist/non-executable-clock-drivers.d.ts.map +1 -0
  116. package/dist/non-executable-clock-drivers.js +33 -0
  117. package/dist/non-executable-clock-drivers.js.map +1 -0
  118. package/dist/open-category.d.ts +98 -0
  119. package/dist/open-category.d.ts.map +1 -0
  120. package/dist/open-category.js +111 -0
  121. package/dist/open-category.js.map +1 -0
  122. package/dist/over-driven-node.d.ts +33 -0
  123. package/dist/over-driven-node.d.ts.map +1 -0
  124. package/dist/over-driven-node.js +188 -0
  125. package/dist/over-driven-node.js.map +1 -0
  126. package/dist/part-catalog.d.ts +15 -0
  127. package/dist/part-catalog.d.ts.map +1 -0
  128. package/dist/part-catalog.js +6712 -0
  129. package/dist/part-catalog.js.map +1 -0
  130. package/dist/part-number.d.ts +32 -0
  131. package/dist/part-number.d.ts.map +1 -0
  132. package/dist/part-number.js +80 -0
  133. package/dist/part-number.js.map +1 -0
  134. package/dist/partition.d.ts +7 -0
  135. package/dist/partition.d.ts.map +1 -0
  136. package/dist/partition.js +242 -0
  137. package/dist/partition.js.map +1 -0
  138. package/dist/port-full-scale.d.ts +70 -0
  139. package/dist/port-full-scale.d.ts.map +1 -0
  140. package/dist/port-full-scale.js +235 -0
  141. package/dist/port-full-scale.js.map +1 -0
  142. package/dist/pot-orientation.d.ts +114 -0
  143. package/dist/pot-orientation.d.ts.map +1 -0
  144. package/dist/pot-orientation.js +551 -0
  145. package/dist/pot-orientation.js.map +1 -0
  146. package/dist/power-domain-control.d.ts +40 -0
  147. package/dist/power-domain-control.d.ts.map +1 -0
  148. package/dist/power-domain-control.js +142 -0
  149. package/dist/power-domain-control.js.map +1 -0
  150. package/dist/proxy-declaration.d.ts +121 -0
  151. package/dist/proxy-declaration.d.ts.map +1 -0
  152. package/dist/proxy-declaration.js +50 -0
  153. package/dist/proxy-declaration.js.map +1 -0
  154. package/dist/registry.d.ts +323 -0
  155. package/dist/registry.d.ts.map +1 -0
  156. package/dist/registry.js +192 -0
  157. package/dist/registry.js.map +1 -0
  158. package/dist/sparse-schedule.d.ts +65 -0
  159. package/dist/sparse-schedule.d.ts.map +1 -0
  160. package/dist/sparse-schedule.js +421 -0
  161. package/dist/sparse-schedule.js.map +1 -0
  162. package/dist/speaker-load.d.ts +38 -0
  163. package/dist/speaker-load.d.ts.map +1 -0
  164. package/dist/speaker-load.js +97 -0
  165. package/dist/speaker-load.js.map +1 -0
  166. package/dist/stage-coverage.d.ts +21 -0
  167. package/dist/stage-coverage.d.ts.map +1 -0
  168. package/dist/stage-coverage.js +124 -0
  169. package/dist/stage-coverage.js.map +1 -0
  170. package/dist/stamp-partition.d.ts +314 -0
  171. package/dist/stamp-partition.d.ts.map +1 -0
  172. package/dist/stamp-partition.js +472 -0
  173. package/dist/stamp-partition.js.map +1 -0
  174. package/dist/supply-reference.d.ts +19 -0
  175. package/dist/supply-reference.d.ts.map +1 -0
  176. package/dist/supply-reference.js +66 -0
  177. package/dist/supply-reference.js.map +1 -0
  178. package/dist/supply-short.d.ts +32 -0
  179. package/dist/supply-short.d.ts.map +1 -0
  180. package/dist/supply-short.js +118 -0
  181. package/dist/supply-short.js.map +1 -0
  182. package/dist/supply-stamps.d.ts +51 -0
  183. package/dist/supply-stamps.d.ts.map +1 -0
  184. package/dist/supply-stamps.js +363 -0
  185. package/dist/supply-stamps.js.map +1 -0
  186. package/dist/terminal-role.d.ts +109 -0
  187. package/dist/terminal-role.d.ts.map +1 -0
  188. package/dist/terminal-role.js +46 -0
  189. package/dist/terminal-role.js.map +1 -0
  190. package/dist/terminal-roles.d.ts +59 -0
  191. package/dist/terminal-roles.d.ts.map +1 -0
  192. package/dist/terminal-roles.js +92 -0
  193. package/dist/terminal-roles.js.map +1 -0
  194. package/dist/transformer.d.ts +181 -0
  195. package/dist/transformer.d.ts.map +1 -0
  196. package/dist/transformer.js +476 -0
  197. package/dist/transformer.js.map +1 -0
  198. package/dist/types.d.ts +3157 -0
  199. package/dist/types.d.ts.map +1 -0
  200. package/dist/types.js +11 -0
  201. package/dist/types.js.map +1 -0
  202. package/dist/unbounded-operating-point.d.ts +35 -0
  203. package/dist/unbounded-operating-point.d.ts.map +1 -0
  204. package/dist/unbounded-operating-point.js +181 -0
  205. package/dist/unbounded-operating-point.js.map +1 -0
  206. package/dist/unexecuted-region.d.ts +3 -0
  207. package/dist/unexecuted-region.d.ts.map +1 -0
  208. package/dist/unexecuted-region.js +122 -0
  209. package/dist/unexecuted-region.js.map +1 -0
  210. package/dist/unimplemented-control-role.d.ts +3 -0
  211. package/dist/unimplemented-control-role.d.ts.map +1 -0
  212. package/dist/unimplemented-control-role.js +61 -0
  213. package/dist/unimplemented-control-role.js.map +1 -0
  214. package/dist/unreachable-output.d.ts +3 -0
  215. package/dist/unreachable-output.d.ts.map +1 -0
  216. package/dist/unreachable-output.js +97 -0
  217. package/dist/unreachable-output.js.map +1 -0
  218. package/dist/unreadable-terminal-role.d.ts +67 -0
  219. package/dist/unreadable-terminal-role.d.ts.map +1 -0
  220. package/dist/unreadable-terminal-role.js +409 -0
  221. package/dist/unreadable-terminal-role.js.map +1 -0
  222. package/dist/unverified-pinout.d.ts +27 -0
  223. package/dist/unverified-pinout.d.ts.map +1 -0
  224. package/dist/unverified-pinout.js +121 -0
  225. package/dist/unverified-pinout.js.map +1 -0
  226. package/package.json +75 -5
@@ -0,0 +1,421 @@
1
+ import { stampAuxRows, stampNodeValue, stampShape, } from "./stamp-partition.js";
2
+ /**
3
+ * Every matrix entry a stamp can write, over-approximated as the full square over the stamp's
4
+ * own terminals.
5
+ *
6
+ * Read off the shape table in `stamp-partition.ts` rather than restated here. `terminalNodes`
7
+ * lets a kind narrow the set -- only `vccs` does, to its output pair -- and `terminalsDropGround`
8
+ * lets it drop ground, which `vccs` also does and nothing else may, because `schedulePattern`
9
+ * removes row 0 globally but keeps column 0.
10
+ *
11
+ * Order is not significant: the caller expands these into every (row, column) pair and collects
12
+ * them in a `Set`.
13
+ */
14
+ export function stampTerminals(stamp, nodeCount) {
15
+ const shape = stampShape(stamp);
16
+ const fields = shape.terminalNodes ?? shape.nodes;
17
+ const rows = [
18
+ ...stampAuxRows(stamp, nodeCount),
19
+ ...fields.map((field) => stampNodeValue(stamp, field)),
20
+ ];
21
+ return shape.terminalsDropGround ? rows.filter((row) => row !== 0) : rows;
22
+ }
23
+ /**
24
+ * Entries that are provably nonzero at every control position and every Newton iterate,
25
+ * and are therefore the only ones allowed to be pivots.
26
+ *
27
+ * **Two conditions, and both are load-bearing. An entry belongs here only when the stamp
28
+ * writes it (a) in the direction being claimed and (b) on every iterate.** Marking an entry
29
+ * the stamp leaves zero does not produce a wrong answer -- the runtime's pivot guard catches
30
+ * the collapse and re-solves densely -- but it produces a *silently dense* block, which is
31
+ * worse than a slow one because nothing reports it. Measured 2026-09-18 on the shipping
32
+ * console: `boss-ch-1` gave its schedule up inside `prepare()` and ran 100x100 dense for the
33
+ * whole session (12.8x real time), `boss-ce-5` tripped the guard on half its iterations and
34
+ * paid for the schedule *and* the dense solve (6.6x), and `boss-ce-2`, `boss-ce-2b`,
35
+ * `boss-dm-2` and `boss-dd-3b` abandoned within their first 64 audio iterations. Every one of
36
+ * those traced back to an entry marked here that the owning stamp cannot guarantee. See
37
+ * `thoughts/shared/2026-09-18-sparse-schedule-runtime-audit.md`.
38
+ *
39
+ * So `pair()` is for symmetric writes only. A stamp that writes `matrix[row][column]` and not
40
+ * its transpose -- every controlled-source coupling in this file's device set does exactly
41
+ * that -- marks the one entry with `eligible.add`, or marks nothing when the value can vanish.
42
+ *
43
+ * **What this does NOT establish is that an eligible pivot is numerically usable.** Every node
44
+ * diagonal is listed below because the runtime adds `gmin` to it, which is true and nearly
45
+ * useless: a pivot of 1e-12 against entries of order 1e2 is a growth factor of 1e14, and dense
46
+ * partial pivoting would never choose it. That is a separate, open defect (`boss-aw-2` fails to
47
+ * converge on the sparse path and converges in four iterations densely), and it cannot be fixed
48
+ * from the pattern alone -- it needs the pivot search to see magnitudes. Recorded in §6 of the
49
+ * audit above.
50
+ */
51
+ export function provablyNonzeroEntries(block, size) {
52
+ const eligible = new Set();
53
+ for (let node = 0; node < block.nodeCount; node += 1) {
54
+ eligible.add(node * size + node);
55
+ }
56
+ /** For entries a stamp writes in BOTH directions on every iterate, and only those. */
57
+ const pair = (row, column) => {
58
+ eligible.add(row * size + column);
59
+ eligible.add(column * size + row);
60
+ };
61
+ const auxRow = (sourceIndex, offset = 0) => block.nodeCount + sourceIndex + offset;
62
+ for (const stamp of block.stamps) {
63
+ switch (stamp.kind) {
64
+ // **The three by-inspection cases, and they were the largest omission.** A resistor's
65
+ // conductance is `g > 0` at every control position and every iterate; a capacitor's
66
+ // trapezoidal companion is `2C/dt`; an inductor's is `dt/2L` (scaled by `1/(1+Rk)`
67
+ // when a winding resistance is declared, which is still strictly positive). None can
68
+ // vanish, so all four entries of each pair are provable by inspection rather than by
69
+ // analysis.
70
+ //
71
+ // Their absence is why ~74% of every packet's pivot candidates read as "unproven" --
72
+ // 407 of 544 on `mxr-carbon-copy` and **185 of 268 on healthy `marshall-jtm45`** --
73
+ // which left Markowitz choosing from a quarter of its real options everywhere, and
74
+ // forced 10 unproven pivots on carbon-copy that then failed 144,188 times.
75
+ case "conductance":
76
+ case "capacitor":
77
+ case "inductor": {
78
+ const { a, b } = stamp;
79
+ if (a === b) {
80
+ break;
81
+ }
82
+ pair(a, a);
83
+ pair(b, b);
84
+ pair(a, b);
85
+ break;
86
+ }
87
+ case "dc-source":
88
+ case "ac-source": {
89
+ if (stamp.positive === stamp.negative) {
90
+ break;
91
+ }
92
+ const row = auxRow(stamp.sourceIndex);
93
+ pair(row, stamp.positive);
94
+ pair(row, stamp.negative);
95
+ break;
96
+ }
97
+ case "logic-divider": {
98
+ if (stamp.qNode === stamp.gndNode) {
99
+ break;
100
+ }
101
+ const row = auxRow(stamp.sourceIndex);
102
+ pair(row, stamp.qNode);
103
+ pair(row, stamp.gndNode);
104
+ break;
105
+ }
106
+ case "analog-switch": {
107
+ // **The channel only.** `g = gOff + (gOn - gOff) * sigmoid` is bounded below by
108
+ // `gOff = 1/offOhms > 0` at every control voltage, and `stampConductance` writes
109
+ // all four of its cells, so the channel pair is provable.
110
+ //
111
+ // The gate couplings are not, on both counts. `coupling = dg/dvCtrl * (vA - vB)`
112
+ // is written into `matrix[a][control]` and `matrix[b][control]` and **never their
113
+ // transposes**, and it is exactly zero twice over: the sigmoid derivative
114
+ // underflows once the gate is more than ~8 V past threshold (which is where a
115
+ // CMOS switch spends all of its time), and `vA - vB` is zero across a closed
116
+ // switch feeding a settled node. `boss-dd-3b` pivoted on `(node23, node6)` and
117
+ // abandoned its schedule 27 iterations into the operating point.
118
+ if (stamp.a !== stamp.b) {
119
+ pair(stamp.a, stamp.b);
120
+ }
121
+ break;
122
+ }
123
+ case "compandor": {
124
+ // **Nothing is provable here.** `(sumNode, cellIn)` carries `-gCell`, where
125
+ // `gCell` is the *envelope* state: zero until the rectifier's capacitor has
126
+ // charged, which on a fresh `prepare()` is every iterate of the operating point
127
+ // and the first few hundred samples after it. It is also written one way only.
128
+ // `mxr-carbon-copy` and `electro-harmonix-deluxe-memory-man` carry two of these
129
+ // each on their dominant block.
130
+ break;
131
+ }
132
+ case "clock-driver": {
133
+ // **The phase rows and their own diagonals; NOT the supply couplings.**
134
+ //
135
+ // Each phase row is an ideal source row for one output pin: `matrix[row][cpN] +=
136
+ // 1`, `matrix[cpN][row] += 1`, `matrix[row][row] -= 1`. All three are
137
+ // unconditional, the first two are symmetric, and an aux row belongs to exactly
138
+ // one stamp, so nothing else can cancel the -1 on its diagonal. That diagonal is
139
+ // the best pivot in the block and was previously not listed at all.
140
+ //
141
+ // The supply couplings are the opposite of provable. `couple(theta < 0.5 ? vdd :
142
+ // gnd, row1, 1.0)` writes ONE of the two pins per iterate, into `matrix[row][pin]`
143
+ // and never the transpose. Both were listed, so at any instant at least half of
144
+ // what was marked was zero, and the alternation guaranteed that a pivot chosen on
145
+ // one phase collapsed on the next. This is what `boss-ch-1` (aux10, node2),
146
+ // `boss-ce-5` (aux4, node1), `boss-ce-2` (node2, aux5 -- a transpose that no
147
+ // stamp ever writes) and `boss-dm-2` (node1, aux7) each pivoted on.
148
+ //
149
+ // The *pattern* still needs both pins, and still has them: `stampTerminals` reads
150
+ // the shape table, which is a different question from what may be a pivot. The
151
+ // bug the old comment here describes -- a pattern missing a cell the stamp writes
152
+ // -- is real and is not this set's job to prevent.
153
+ const row1 = auxRow(stamp.sourceIndex);
154
+ pair(row1, stamp.cp1);
155
+ eligible.add(row1 * size + row1);
156
+ const row2 = auxRow(stamp.sourceIndex, 1);
157
+ pair(row2, stamp.cp2);
158
+ eligible.add(row2 * size + row2);
159
+ const row3 = auxRow(stamp.sourceIndex, 2);
160
+ pair(row3, stamp.vgg);
161
+ eligible.add(row3 * size + row3);
162
+ break;
163
+ }
164
+ case "comparator": {
165
+ // **The pull-down only.** `gCell = gOn * sigma + gOff` is bounded below by
166
+ // `gOff = 1/floatOhms > 0` and goes through `stampConductance`, so it is
167
+ // symmetric and cannot vanish.
168
+ //
169
+ // The input couplings carry `gControl = gOn * dsigma * (vOut - vVee)`, written
170
+ // into the output and vee rows only, never the transpose, and zero whenever the
171
+ // comparator is saturated -- which for a comparator is its entire working life,
172
+ // the linear band being a few millivolts wide. `moogerfooger-mf-102` carries four.
173
+ if (stamp.output !== stamp.vee) {
174
+ pair(stamp.output, stamp.vee);
175
+ }
176
+ break;
177
+ }
178
+ case "transformer": {
179
+ const nodes = [
180
+ stamp.primaryPlus,
181
+ stamp.primaryMinus,
182
+ stamp.secondaryPlus,
183
+ stamp.secondaryMinus,
184
+ ];
185
+ if (new Set(nodes).size !== 4) {
186
+ break;
187
+ }
188
+ const row = block.nodeCount + stamp.sourceIndex;
189
+ pair(row, stamp.primaryPlus);
190
+ pair(row, stamp.primaryMinus);
191
+ break;
192
+ }
193
+ case "input-source":
194
+ case "macro-audio-source":
195
+ pair(auxRow(stamp.sourceIndex), stamp.node);
196
+ break;
197
+ case "ideal-opamp":
198
+ eligible.add(stamp.output * size + auxRow(stamp.sourceIndex));
199
+ break;
200
+ case "vccs": {
201
+ const gm = stamp.transconductance;
202
+ if (gm !== 0) {
203
+ if (stamp.outP !== 0) {
204
+ if (stamp.inP !== 0)
205
+ eligible.add(stamp.outP * size + stamp.inP);
206
+ if (stamp.inN !== 0)
207
+ eligible.add(stamp.outP * size + stamp.inN);
208
+ }
209
+ if (stamp.outN !== 0) {
210
+ if (stamp.inP !== 0)
211
+ eligible.add(stamp.outN * size + stamp.inP);
212
+ if (stamp.inN !== 0)
213
+ eligible.add(stamp.outN * size + stamp.inN);
214
+ }
215
+ }
216
+ break;
217
+ }
218
+ case "ota": {
219
+ if (stamp.bias !== stamp.vee) {
220
+ pair(stamp.bias, stamp.vee);
221
+ }
222
+ break;
223
+ }
224
+ default:
225
+ break;
226
+ }
227
+ }
228
+ return eligible;
229
+ }
230
+ /**
231
+ * The block's structural pattern: every entry any stamp can write, plus the gmin diagonals,
232
+ * with ground-pin overwrite applied.
233
+ */
234
+ export function schedulePattern(block, size) {
235
+ const pattern = new Set();
236
+ for (const stamp of block.stamps) {
237
+ const terminals = stampTerminals(stamp, block.nodeCount);
238
+ for (const row of terminals) {
239
+ for (const column of terminals) {
240
+ pattern.add(row * size + column);
241
+ }
242
+ }
243
+ }
244
+ for (let node = 1; node < block.nodeCount; node += 1) {
245
+ pattern.add(node * size + node);
246
+ }
247
+ for (let column = 0; column < size; column += 1) {
248
+ pattern.delete(column);
249
+ }
250
+ pattern.add(0);
251
+ return pattern;
252
+ }
253
+ /**
254
+ * Work out the elimination order and emit its opcode stream.
255
+ *
256
+ * Returns null when the pattern cannot be eliminated at all (a structurally singular block).
257
+ */
258
+ export function computeSparseSchedule(block) {
259
+ const size = block.nodeCount + block.auxCount;
260
+ if (size === 0) {
261
+ return null;
262
+ }
263
+ const pattern = schedulePattern(block, size);
264
+ const eligible = provablyNonzeroEntries(block, size);
265
+ const rows = Array.from({ length: size }, () => new Set());
266
+ const columns = Array.from({ length: size }, () => new Set());
267
+ for (const key of pattern) {
268
+ const row = Math.floor(key / size);
269
+ rows[row]?.add(key % size);
270
+ columns[key % size]?.add(row);
271
+ }
272
+ const doneRow = new Set();
273
+ const doneColumn = new Set();
274
+ const pivots = [];
275
+ let unprovenPivots = 0;
276
+ for (let step = 0; step < size; step += 1) {
277
+ let bestRow = -1;
278
+ let bestColumn = -1;
279
+ let bestKey = Infinity;
280
+ let bestProven = false;
281
+ for (let row = 0; row < size; row += 1) {
282
+ if (doneRow.has(row)) {
283
+ continue;
284
+ }
285
+ let rowCount = 0;
286
+ for (const column of rows[row]) {
287
+ if (!doneColumn.has(column)) {
288
+ rowCount += 1;
289
+ }
290
+ }
291
+ if (rowCount === 0) {
292
+ continue;
293
+ }
294
+ for (const column of rows[row]) {
295
+ if (doneColumn.has(column)) {
296
+ continue;
297
+ }
298
+ let columnCount = 0;
299
+ for (const other of columns[column]) {
300
+ if (!doneRow.has(other)) {
301
+ columnCount += 1;
302
+ }
303
+ }
304
+ const key = (rowCount - 1) * (columnCount - 1) * 2 + (row === column ? 0 : 1);
305
+ const proven = eligible.has(row * size + column);
306
+ if (proven && !bestProven) {
307
+ bestProven = true;
308
+ bestKey = key;
309
+ bestRow = row;
310
+ bestColumn = column;
311
+ continue;
312
+ }
313
+ if (!proven && bestProven) {
314
+ continue;
315
+ }
316
+ if (key < bestKey) {
317
+ bestKey = key;
318
+ bestRow = row;
319
+ bestColumn = column;
320
+ }
321
+ }
322
+ }
323
+ if (bestRow < 0) {
324
+ break;
325
+ }
326
+ if (!bestProven) {
327
+ unprovenPivots += 1;
328
+ }
329
+ const pivotRow = [...rows[bestRow]].filter((column) => !doneColumn.has(column) && column !== bestColumn);
330
+ const pivotColumn = [...columns[bestColumn]].filter((row) => !doneRow.has(row) && row !== bestRow);
331
+ for (const row of pivotColumn) {
332
+ for (const column of pivotRow) {
333
+ if (!rows[row].has(column)) {
334
+ rows[row]?.add(column);
335
+ columns[column]?.add(row);
336
+ }
337
+ }
338
+ }
339
+ pivots.push({ row: bestRow, column: bestColumn });
340
+ doneRow.add(bestRow);
341
+ doneColumn.add(bestColumn);
342
+ }
343
+ if (pivots.length !== size) {
344
+ return null;
345
+ }
346
+ const slotOf = new Map();
347
+ const gatherRow = [];
348
+ const gatherColumn = [];
349
+ for (let row = 0; row < size; row += 1) {
350
+ for (const column of rows[row]) {
351
+ slotOf.set(row * size + column, gatherRow.length);
352
+ gatherRow.push(row);
353
+ gatherColumn.push(column);
354
+ }
355
+ }
356
+ const slot = (row, column) => {
357
+ const found = slotOf.get(row * size + column);
358
+ if (found === undefined) {
359
+ throw new Error(`sparse schedule has no slot for entry (${row}, ${column})`);
360
+ }
361
+ return found;
362
+ };
363
+ const liveRows = Array.from({ length: size }, () => new Set());
364
+ const liveColumns = Array.from({ length: size }, () => new Set());
365
+ for (const key of pattern) {
366
+ const row = Math.floor(key / size);
367
+ liveRows[row]?.add(key % size);
368
+ liveColumns[key % size]?.add(row);
369
+ }
370
+ const eliminatedRow = new Set();
371
+ const eliminatedColumn = new Set();
372
+ const ops = [];
373
+ let factorCount = 0;
374
+ let sparseOps = 0;
375
+ for (const pivot of pivots) {
376
+ ops.push(6, slot(pivot.row, pivot.column), 0, 0);
377
+ const pivotRow = [...liveRows[pivot.row]].filter((column) => !eliminatedColumn.has(column) && column !== pivot.column);
378
+ const pivotColumn = [...liveColumns[pivot.column]].filter((row) => !eliminatedRow.has(row) && row !== pivot.row);
379
+ for (const row of pivotColumn) {
380
+ const factor = factorCount;
381
+ factorCount += 1;
382
+ ops.push(0, factor, slot(row, pivot.column), slot(pivot.row, pivot.column));
383
+ for (const column of pivotRow) {
384
+ if (!liveRows[row].has(column)) {
385
+ liveRows[row]?.add(column);
386
+ liveColumns[column]?.add(row);
387
+ }
388
+ ops.push(1, slot(row, column), factor, slot(pivot.row, column));
389
+ sparseOps += 1;
390
+ }
391
+ ops.push(2, row, factor, pivot.row);
392
+ sparseOps += 1;
393
+ }
394
+ eliminatedRow.add(pivot.row);
395
+ eliminatedColumn.add(pivot.column);
396
+ }
397
+ for (let step = pivots.length - 1; step >= 0; step -= 1) {
398
+ const pivot = pivots[step];
399
+ ops.push(3, pivot.row, 0, 0);
400
+ for (let later = step + 1; later < pivots.length; later += 1) {
401
+ const column = pivots[later].column;
402
+ if (liveRows[pivot.row].has(column)) {
403
+ ops.push(4, slot(pivot.row, column), column, 0);
404
+ sparseOps += 1;
405
+ }
406
+ }
407
+ ops.push(5, pivot.column, slot(pivot.row, pivot.column), 0);
408
+ }
409
+ return {
410
+ ops,
411
+ slots: gatherRow.length,
412
+ factorCount,
413
+ gatherRow,
414
+ gatherColumn,
415
+ size,
416
+ sparseOps,
417
+ denseOps: (size * size * size - size) / 3,
418
+ unprovenPivots,
419
+ };
420
+ }
421
+ //# sourceMappingURL=sparse-schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sparse-schedule.js","sourceRoot":"","sources":["../src/sparse-schedule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ export type SpeakerOnePort = {
2
+ readonly reOhms: number;
3
+ readonly leHenries: number;
4
+ readonly motionalOhms: number;
5
+ readonly motionalHenries: number;
6
+ readonly motionalFarads: number;
7
+ /** What the whole network was scaled by, for the warning to quote. */
8
+ readonly nominalOhms: number;
9
+ };
10
+ /**
11
+ * The generic driver's one-port, impedance-scaled to a declared nominal impedance.
12
+ *
13
+ * A 16 ohm driver is not a different curve from an 8 ohm one, it is the same curve twice as high:
14
+ * scaling `Re`, `Rmot` and `Lmot` by `k` and dividing `Cmot` by `k` multiplies the impedance by `k`
15
+ * at every frequency and leaves the resonance and its Q exactly where they were. That is exact for
16
+ * the electrical one-port, which is what makes one seed profile usable for the corpus's 8 and 16
17
+ * ohm jacks without inventing a second driver.
18
+ */
19
+ export declare function speakerOnePort(nominalOhms: number): SpeakerOnePort;
20
+ /**
21
+ * `Z` of the one-port at a frequency, complex.
22
+ *
23
+ * Series `Re + jwLe`, then the three motional elements in parallel. Kept here beside the element
24
+ * values so a check cannot drift from the thing it checks.
25
+ *
26
+ * **Complex, not a magnitude, because a divider needs the phase.** Reflecting this through a
27
+ * transformer and dividing against a power stage's output impedance with magnitudes alone is wrong
28
+ * wherever the load is reactive: measured on `report-speaker-load.ts`'s fixture, a scalar divider
29
+ * agrees at resonance and at the impedance minimum -- both nearly real -- and is 14.7% off at 5 kHz,
30
+ * where the voice-coil inductance dominates.
31
+ */
32
+ export declare function speakerImpedance(port: SpeakerOnePort, frequencyHz: number): {
33
+ readonly re: number;
34
+ readonly im: number;
35
+ };
36
+ /** `|Z|` of the one-port, from {@link speakerImpedance}. */
37
+ export declare function speakerImpedanceMagnitude(port: SpeakerOnePort, frequencyHz: number): number;
38
+ //# sourceMappingURL=speaker-load.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speaker-load.d.ts","sourceRoot":"","sources":["../src/speaker-load.ts"],"names":[],"mappings":"AA+CA,MAAM,MAAM,cAAc,GAAG;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,CAclE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,MAAM,GACjB;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAU9C;AAED,4DAA4D;AAC5D,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,MAAM,GACjB,MAAM,CAGR"}
@@ -0,0 +1,97 @@
1
+ // Stage B: a speaker as a linear one-port, instead of a resistor.
2
+ //
3
+ // Stage A terminated an output transformer's secondary with the jack's declared nominal impedance,
4
+ // which made the plate load line real. A real driver is not a resistor: its impedance rises to a
5
+ // peak at cone resonance and climbs again with voice-coil inductance, and the power tubes see that
6
+ // curve rather than a flat 8 or 16 ohms.
7
+ //
8
+ // The standard linear equivalent, and the one `speakerThieleSmallSpiceReferenceDeck()` already
9
+ // emits so its curve is the acceptance test:
10
+ //
11
+ // Re --- Le --- ( Rmot || Lmot || Cmot ) --- return
12
+ //
13
+ // Rmot = Bl^2 / Rms Cmot = Mms / Bl^2 Lmot = Cms * Bl^2 Rms = 2*pi*fs*Mms / Qms
14
+ //
15
+ // Five plain elements over two extra nodes. No new operator, no Newton cost -- every one of them is
16
+ // linear, and the v2 runtime already stamps resistors, inductors and capacitors.
17
+ //
18
+ // **This is a generic driver, never a named one, and that is a deliberate decision rather than a
19
+ // shortcut.** No corpus packet identifies its driver in a form that resolves: the five that §5
20
+ // credits with driver identity all declare prose (`SpeakerModel: "Celestion T4437"`, `SpeakerSet:
21
+ // "two 8 ohm 12 inch speakers in parallel"`). Matching the first to a `celestion-blue-alnico-8`
22
+ // profile is a name inference this pipeline forbids, and the other two name no driver at all. So
23
+ // the choice is a generic profile or no Stage B, and every application of it carries a
24
+ // `generic-speaker-profile` warning naming the jack, so a render can never be quoted as *this
25
+ // amp's* speaker.
26
+ //
27
+ // The numbers below are the `celestion-vintage-30-8` seed from
28
+ // `src/web/assets/cab-mic-profiles.vdsp`, which v1 names as its own default profile. Transcribed
29
+ // rather than imported, because the v2 compiler may not read `src/web` -- the same reason
30
+ // `GENERIC_TRIODE` holds a 12AX7 fit as data here. Its own record states
31
+ // `sourceConfidence: official-basic-aggregate-physical-seed` and says the full T-S row is a
32
+ // "non-factory consensus seed for runtime-load development, not a promotion-grade exact driver
33
+ // revision claim". That bound travels with anything this produces: it is the *shape* of a real
34
+ // driver's impedance, not a measurement of one.
35
+ /** The one generic driver, as its source states it. 8 ohm nominal. */
36
+ const GENERIC_DRIVER = {
37
+ nominalOhms: 8,
38
+ reOhms: 7.3,
39
+ leHenries: 0.00045,
40
+ fsHz: 75,
41
+ qms: 4.88,
42
+ mmsKg: 0.0331,
43
+ cmsMetersPerNewton: 0.00013604724221864757,
44
+ blTeslaMeters: 13.1,
45
+ };
46
+ /**
47
+ * The generic driver's one-port, impedance-scaled to a declared nominal impedance.
48
+ *
49
+ * A 16 ohm driver is not a different curve from an 8 ohm one, it is the same curve twice as high:
50
+ * scaling `Re`, `Rmot` and `Lmot` by `k` and dividing `Cmot` by `k` multiplies the impedance by `k`
51
+ * at every frequency and leaves the resonance and its Q exactly where they were. That is exact for
52
+ * the electrical one-port, which is what makes one seed profile usable for the corpus's 8 and 16
53
+ * ohm jacks without inventing a second driver.
54
+ */
55
+ export function speakerOnePort(nominalOhms) {
56
+ const k = nominalOhms / GENERIC_DRIVER.nominalOhms;
57
+ const rms = (2 * Math.PI * GENERIC_DRIVER.fsHz * GENERIC_DRIVER.mmsKg) /
58
+ GENERIC_DRIVER.qms;
59
+ const motor = GENERIC_DRIVER.blTeslaMeters * GENERIC_DRIVER.blTeslaMeters;
60
+ return {
61
+ reOhms: GENERIC_DRIVER.reOhms * k,
62
+ leHenries: GENERIC_DRIVER.leHenries * k,
63
+ motionalOhms: (motor / rms) * k,
64
+ motionalHenries: GENERIC_DRIVER.cmsMetersPerNewton * motor * k,
65
+ motionalFarads: GENERIC_DRIVER.mmsKg / motor / k,
66
+ nominalOhms,
67
+ };
68
+ }
69
+ /**
70
+ * `Z` of the one-port at a frequency, complex.
71
+ *
72
+ * Series `Re + jwLe`, then the three motional elements in parallel. Kept here beside the element
73
+ * values so a check cannot drift from the thing it checks.
74
+ *
75
+ * **Complex, not a magnitude, because a divider needs the phase.** Reflecting this through a
76
+ * transformer and dividing against a power stage's output impedance with magnitudes alone is wrong
77
+ * wherever the load is reactive: measured on `report-speaker-load.ts`'s fixture, a scalar divider
78
+ * agrees at resonance and at the impedance minimum -- both nearly real -- and is 14.7% off at 5 kHz,
79
+ * where the voice-coil inductance dominates.
80
+ */
81
+ export function speakerImpedance(port, frequencyHz) {
82
+ const w = 2 * Math.PI * frequencyHz;
83
+ const gr = 1 / port.motionalOhms;
84
+ const bl = w === 0 ? Number.POSITIVE_INFINITY : -1 / (w * port.motionalHenries);
85
+ const bc = w * port.motionalFarads;
86
+ const b = bl === Number.POSITIVE_INFINITY ? Number.POSITIVE_INFINITY : bl + bc;
87
+ const denom = gr * gr + b * b;
88
+ const zr = denom === 0 || !Number.isFinite(b) ? 0 : gr / denom;
89
+ const zi = denom === 0 || !Number.isFinite(b) ? 0 : -b / denom;
90
+ return { re: port.reOhms + zr, im: w * port.leHenries + zi };
91
+ }
92
+ /** `|Z|` of the one-port, from {@link speakerImpedance}. */
93
+ export function speakerImpedanceMagnitude(port, frequencyHz) {
94
+ const z = speakerImpedance(port, frequencyHz);
95
+ return Math.hypot(z.re, z.im);
96
+ }
97
+ //# sourceMappingURL=speaker-load.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speaker-load.js","sourceRoot":"","sources":["../src/speaker-load.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { type Block, type Ports, type Program } from "./types";
2
+ /**
3
+ * Read from the lowered stamps, the same discipline as `supply-reference.ts` and
4
+ * `port-full-scale.ts`.
5
+ *
6
+ * The distinctions available from a program, and nothing finer:
7
+ *
8
+ * - `speaker-electrical` — the output port sits on a winding of a transformer declaring a `ratio`,
9
+ * so it *is* the speaker terminal. **Position, not load quality**: whether a speaker is
10
+ * modelled across it is a different question, answered by Stage A of the output-stage plan and
11
+ * its §4.6 table. An earlier draft here split this by "is something resistive across the node",
12
+ * and `fender-bassman` showed why that fails -- a 27 kOhm network element sits on its secondary
13
+ * and no test at this stage can tell that from an 8 Ohm driver without guessing from magnitude.
14
+ * - `preamp` — no output transformer at all, but the program declares a high-voltage supply
15
+ * winding (`voltsHv`), which only an amp has. `mesa-boogie-mark-v` lands here: its packet hands
16
+ * the transformer and speaker to a companion fixture, so its render is a preamp level.
17
+ * - `instrument` — everything else, which is every pedal: a pedal does not claim to be further
18
+ * along the chain than the instrument feeding it.
19
+ */
20
+ export declare function stageCoverage(blocks: readonly Block[], ports: Ports): Program["stageCoverage"];
21
+ //# sourceMappingURL=stage-coverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stage-coverage.d.ts","sourceRoot":"","sources":["../src/stage-coverage.ts"],"names":[],"mappings":"AAeA,OAAO,EAAU,KAAK,KAAK,EAAe,KAAK,KAAK,EAAE,KAAK,OAAO,EAAE,MAAM,SAAS,CAAC;AAEpF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAC5B,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,KAAK,EAAE,KAAK,GACV,OAAO,CAAC,eAAe,CAAC,CAyF1B"}