qsharp-lang 1.25.4-dev → 1.25.5-dev

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 (337) hide show
  1. package/docs/Microsoft.Quantum.Core/IsRangeEmpty.md +1 -1
  2. package/docs/Microsoft.Quantum.Core/Length.md +1 -1
  3. package/docs/Microsoft.Quantum.Core/RangeEnd.md +1 -1
  4. package/docs/Microsoft.Quantum.Core/RangeStart.md +1 -1
  5. package/docs/Microsoft.Quantum.Core/Repeated.md +1 -1
  6. package/docs/Microsoft.Quantum.Core/index.md +1 -1
  7. package/docs/Std.Arithmetic/AddLE.md +1 -1
  8. package/docs/Std.Arithmetic/ApplyIfEqualL.md +1 -1
  9. package/docs/Std.Arithmetic/ApplyIfEqualLE.md +1 -1
  10. package/docs/Std.Arithmetic/ApplyIfGreaterL.md +1 -1
  11. package/docs/Std.Arithmetic/ApplyIfGreaterLE.md +1 -1
  12. package/docs/Std.Arithmetic/ApplyIfGreaterOrEqualL.md +1 -1
  13. package/docs/Std.Arithmetic/ApplyIfGreaterOrEqualLE.md +1 -1
  14. package/docs/Std.Arithmetic/ApplyIfLessL.md +1 -1
  15. package/docs/Std.Arithmetic/ApplyIfLessLE.md +1 -1
  16. package/docs/Std.Arithmetic/ApplyIfLessOrEqualL.md +1 -1
  17. package/docs/Std.Arithmetic/ApplyIfLessOrEqualLE.md +1 -1
  18. package/docs/Std.Arithmetic/FourierTDIncByLE.md +1 -1
  19. package/docs/Std.Arithmetic/IncByI.md +1 -1
  20. package/docs/Std.Arithmetic/IncByIUsingIncByLE.md +1 -1
  21. package/docs/Std.Arithmetic/IncByL.md +1 -1
  22. package/docs/Std.Arithmetic/IncByLE.md +1 -1
  23. package/docs/Std.Arithmetic/IncByLEUsingAddLE.md +1 -1
  24. package/docs/Std.Arithmetic/IncByLUsingIncByLE.md +1 -1
  25. package/docs/Std.Arithmetic/LookAheadDKRSAddLE.md +1 -1
  26. package/docs/Std.Arithmetic/MAJ.md +1 -1
  27. package/docs/Std.Arithmetic/ReflectAboutInteger.md +1 -1
  28. package/docs/Std.Arithmetic/RippleCarryCGAddLE.md +1 -1
  29. package/docs/Std.Arithmetic/RippleCarryCGIncByLE.md +1 -1
  30. package/docs/Std.Arithmetic/RippleCarryTTKIncByLE.md +1 -1
  31. package/docs/Std.Arithmetic/index.md +1 -1
  32. package/docs/Std.Arrays/All.md +1 -1
  33. package/docs/Std.Arrays/Any.md +1 -1
  34. package/docs/Std.Arrays/Chunks.md +1 -1
  35. package/docs/Std.Arrays/CircularlyShifted.md +1 -1
  36. package/docs/Std.Arrays/ColumnAt.md +1 -1
  37. package/docs/Std.Arrays/Count.md +1 -1
  38. package/docs/Std.Arrays/Diagonal.md +1 -1
  39. package/docs/Std.Arrays/DrawMany.md +1 -1
  40. package/docs/Std.Arrays/Enumerated.md +1 -1
  41. package/docs/Std.Arrays/Excluding.md +1 -1
  42. package/docs/Std.Arrays/Filtered.md +1 -1
  43. package/docs/Std.Arrays/FlatMapped.md +1 -1
  44. package/docs/Std.Arrays/Flattened.md +1 -1
  45. package/docs/Std.Arrays/Fold.md +1 -1
  46. package/docs/Std.Arrays/ForEach.md +1 -1
  47. package/docs/Std.Arrays/Head.md +1 -1
  48. package/docs/Std.Arrays/HeadAndRest.md +1 -1
  49. package/docs/Std.Arrays/IndexOf.md +1 -1
  50. package/docs/Std.Arrays/IndexRange.md +1 -1
  51. package/docs/Std.Arrays/Interleaved.md +1 -1
  52. package/docs/Std.Arrays/IsEmpty.md +1 -1
  53. package/docs/Std.Arrays/IsRectangularArray.md +1 -1
  54. package/docs/Std.Arrays/IsSorted.md +1 -1
  55. package/docs/Std.Arrays/IsSquareArray.md +1 -1
  56. package/docs/Std.Arrays/Mapped.md +1 -1
  57. package/docs/Std.Arrays/MappedByIndex.md +1 -1
  58. package/docs/Std.Arrays/MappedOverRange.md +1 -1
  59. package/docs/Std.Arrays/Most.md +1 -1
  60. package/docs/Std.Arrays/MostAndTail.md +1 -1
  61. package/docs/Std.Arrays/Padded.md +1 -1
  62. package/docs/Std.Arrays/Partitioned.md +1 -1
  63. package/docs/Std.Arrays/Rest.md +1 -1
  64. package/docs/Std.Arrays/Reversed.md +1 -1
  65. package/docs/Std.Arrays/SequenceI.md +1 -1
  66. package/docs/Std.Arrays/SequenceL.md +1 -1
  67. package/docs/Std.Arrays/Sorted.md +1 -1
  68. package/docs/Std.Arrays/Subarray.md +1 -1
  69. package/docs/Std.Arrays/Swapped.md +1 -1
  70. package/docs/Std.Arrays/Tail.md +1 -1
  71. package/docs/Std.Arrays/Transposed.md +1 -1
  72. package/docs/Std.Arrays/Unzipped.md +1 -1
  73. package/docs/Std.Arrays/Where.md +1 -1
  74. package/docs/Std.Arrays/Windows.md +1 -1
  75. package/docs/Std.Arrays/Zipped.md +1 -1
  76. package/docs/Std.Arrays/index.md +1 -1
  77. package/docs/Std.Canon/ApplyCNOTChain.md +1 -1
  78. package/docs/Std.Canon/ApplyControlledOnBitString.md +1 -1
  79. package/docs/Std.Canon/ApplyControlledOnInt.md +1 -1
  80. package/docs/Std.Canon/ApplyOperationPowerA.md +1 -1
  81. package/docs/Std.Canon/ApplyOperationPowerCA.md +1 -1
  82. package/docs/Std.Canon/ApplyP.md +1 -1
  83. package/docs/Std.Canon/ApplyPauli.md +1 -1
  84. package/docs/Std.Canon/ApplyPauliFromBitString.md +1 -1
  85. package/docs/Std.Canon/ApplyPauliFromInt.md +1 -1
  86. package/docs/Std.Canon/ApplyQFT.md +1 -1
  87. package/docs/Std.Canon/ApplyQPE.md +1 -1
  88. package/docs/Std.Canon/ApplyToEach.md +1 -1
  89. package/docs/Std.Canon/ApplyToEachA.md +1 -1
  90. package/docs/Std.Canon/ApplyToEachC.md +1 -1
  91. package/docs/Std.Canon/ApplyToEachCA.md +1 -1
  92. package/docs/Std.Canon/ApplyXorInPlace.md +1 -1
  93. package/docs/Std.Canon/ApplyXorInPlaceL.md +1 -1
  94. package/docs/Std.Canon/CX.md +1 -1
  95. package/docs/Std.Canon/CY.md +1 -1
  96. package/docs/Std.Canon/CZ.md +1 -1
  97. package/docs/Std.Canon/Fst.md +1 -1
  98. package/docs/Std.Canon/MapPauliAxis.md +1 -1
  99. package/docs/Std.Canon/Relabel.md +1 -1
  100. package/docs/Std.Canon/Snd.md +1 -1
  101. package/docs/Std.Canon/SwapReverseRegister.md +1 -1
  102. package/docs/Std.Canon/index.md +1 -1
  103. package/docs/Std.Convert/BigIntAsBoolArray.md +1 -1
  104. package/docs/Std.Convert/BigIntAsInt.md +1 -1
  105. package/docs/Std.Convert/BoolArrayAsBigInt.md +1 -1
  106. package/docs/Std.Convert/BoolArrayAsInt.md +1 -1
  107. package/docs/Std.Convert/BoolArrayAsResultArray.md +1 -1
  108. package/docs/Std.Convert/BoolAsResult.md +1 -1
  109. package/docs/Std.Convert/ComplexAsComplexPolar.md +1 -1
  110. package/docs/Std.Convert/ComplexPolarAsComplex.md +1 -1
  111. package/docs/Std.Convert/DoubleAsStringWithPrecision.md +1 -1
  112. package/docs/Std.Convert/IntAsBigInt.md +1 -1
  113. package/docs/Std.Convert/IntAsBoolArray.md +1 -1
  114. package/docs/Std.Convert/IntAsDouble.md +1 -1
  115. package/docs/Std.Convert/ResultArrayAsBoolArray.md +1 -1
  116. package/docs/Std.Convert/ResultArrayAsInt.md +1 -1
  117. package/docs/Std.Convert/ResultAsBool.md +1 -1
  118. package/docs/Std.Convert/index.md +1 -1
  119. package/docs/Std.Core/Complex.md +1 -1
  120. package/docs/Std.Core/Length.md +1 -1
  121. package/docs/Std.Core/Repeated.md +1 -1
  122. package/docs/Std.Core/index.md +1 -1
  123. package/docs/Std.Diagnostics/ApplyIdleNoise.md +1 -1
  124. package/docs/Std.Diagnostics/BitFlipNoise.md +1 -1
  125. package/docs/Std.Diagnostics/CheckAllZero.md +1 -1
  126. package/docs/Std.Diagnostics/CheckOperationsAreEqual.md +1 -1
  127. package/docs/Std.Diagnostics/CheckZero.md +1 -1
  128. package/docs/Std.Diagnostics/ConfigurePauliNoise.md +1 -1
  129. package/docs/Std.Diagnostics/ConfigureQubitLoss.md +1 -1
  130. package/docs/Std.Diagnostics/DepolarizingNoise.md +1 -1
  131. package/docs/Std.Diagnostics/DumpMachine.md +1 -1
  132. package/docs/Std.Diagnostics/DumpOperation.md +1 -1
  133. package/docs/Std.Diagnostics/DumpRegister.md +1 -1
  134. package/docs/Std.Diagnostics/Fact.md +1 -1
  135. package/docs/Std.Diagnostics/NoNoise.md +1 -1
  136. package/docs/Std.Diagnostics/PhaseFlipNoise.md +1 -1
  137. package/docs/Std.Diagnostics/StartCountingFunction.md +1 -1
  138. package/docs/Std.Diagnostics/StartCountingOperation.md +1 -1
  139. package/docs/Std.Diagnostics/StartCountingQubits.md +1 -1
  140. package/docs/Std.Diagnostics/StopCountingFunction.md +1 -1
  141. package/docs/Std.Diagnostics/StopCountingOperation.md +1 -1
  142. package/docs/Std.Diagnostics/StopCountingQubits.md +1 -1
  143. package/docs/Std.Diagnostics/index.md +1 -1
  144. package/docs/Std.Intrinsic/AND.md +1 -1
  145. package/docs/Std.Intrinsic/ApplyUnitary.md +1 -1
  146. package/docs/Std.Intrinsic/CCNOT.md +1 -1
  147. package/docs/Std.Intrinsic/CNOT.md +1 -1
  148. package/docs/Std.Intrinsic/Exp.md +1 -1
  149. package/docs/Std.Intrinsic/H.md +1 -1
  150. package/docs/Std.Intrinsic/I.md +1 -1
  151. package/docs/Std.Intrinsic/M.md +1 -1
  152. package/docs/Std.Intrinsic/Measure.md +1 -1
  153. package/docs/Std.Intrinsic/Message.md +1 -1
  154. package/docs/Std.Intrinsic/R.md +1 -1
  155. package/docs/Std.Intrinsic/R1.md +1 -1
  156. package/docs/Std.Intrinsic/R1Frac.md +1 -1
  157. package/docs/Std.Intrinsic/RFrac.md +1 -1
  158. package/docs/Std.Intrinsic/Reset.md +1 -1
  159. package/docs/Std.Intrinsic/ResetAll.md +1 -1
  160. package/docs/Std.Intrinsic/Rx.md +1 -1
  161. package/docs/Std.Intrinsic/Rxx.md +1 -1
  162. package/docs/Std.Intrinsic/Ry.md +1 -1
  163. package/docs/Std.Intrinsic/Ryy.md +1 -1
  164. package/docs/Std.Intrinsic/Rz.md +1 -1
  165. package/docs/Std.Intrinsic/Rzz.md +1 -1
  166. package/docs/Std.Intrinsic/S.md +1 -1
  167. package/docs/Std.Intrinsic/SWAP.md +1 -1
  168. package/docs/Std.Intrinsic/SX.md +1 -1
  169. package/docs/Std.Intrinsic/T.md +1 -1
  170. package/docs/Std.Intrinsic/X.md +1 -1
  171. package/docs/Std.Intrinsic/Y.md +1 -1
  172. package/docs/Std.Intrinsic/Z.md +1 -1
  173. package/docs/Std.Intrinsic/index.md +1 -1
  174. package/docs/Std.Logical/Xor.md +1 -1
  175. package/docs/Std.Logical/index.md +1 -1
  176. package/docs/Std.Math/AbsComplex.md +1 -1
  177. package/docs/Std.Math/AbsComplexPolar.md +1 -1
  178. package/docs/Std.Math/AbsD.md +1 -1
  179. package/docs/Std.Math/AbsI.md +1 -1
  180. package/docs/Std.Math/AbsL.md +1 -1
  181. package/docs/Std.Math/AbsSquaredComplex.md +1 -1
  182. package/docs/Std.Math/AbsSquaredComplexPolar.md +1 -1
  183. package/docs/Std.Math/ApproximateFactorial.md +1 -1
  184. package/docs/Std.Math/ArcCos.md +1 -1
  185. package/docs/Std.Math/ArcCosh.md +1 -1
  186. package/docs/Std.Math/ArcSin.md +1 -1
  187. package/docs/Std.Math/ArcSinh.md +1 -1
  188. package/docs/Std.Math/ArcTan.md +1 -1
  189. package/docs/Std.Math/ArcTan2.md +1 -1
  190. package/docs/Std.Math/ArcTanh.md +1 -1
  191. package/docs/Std.Math/ArgComplex.md +1 -1
  192. package/docs/Std.Math/ArgComplexPolar.md +1 -1
  193. package/docs/Std.Math/Binom.md +1 -1
  194. package/docs/Std.Math/BitSizeI.md +1 -1
  195. package/docs/Std.Math/BitSizeL.md +1 -1
  196. package/docs/Std.Math/Ceiling.md +1 -1
  197. package/docs/Std.Math/Complex.md +1 -1
  198. package/docs/Std.Math/ComplexPolar.md +1 -1
  199. package/docs/Std.Math/ContinuedFractionConvergentI.md +1 -1
  200. package/docs/Std.Math/ContinuedFractionConvergentL.md +1 -1
  201. package/docs/Std.Math/Cos.md +1 -1
  202. package/docs/Std.Math/Cosh.md +1 -1
  203. package/docs/Std.Math/DivRemI.md +1 -1
  204. package/docs/Std.Math/DivRemL.md +1 -1
  205. package/docs/Std.Math/DividedByC.md +1 -1
  206. package/docs/Std.Math/DividedByCP.md +1 -1
  207. package/docs/Std.Math/E.md +1 -1
  208. package/docs/Std.Math/ExpModI.md +1 -1
  209. package/docs/Std.Math/ExpModL.md +1 -1
  210. package/docs/Std.Math/ExtendedGreatestCommonDivisorI.md +1 -1
  211. package/docs/Std.Math/ExtendedGreatestCommonDivisorL.md +1 -1
  212. package/docs/Std.Math/FactorialI.md +1 -1
  213. package/docs/Std.Math/FactorialL.md +1 -1
  214. package/docs/Std.Math/Floor.md +1 -1
  215. package/docs/Std.Math/GreatestCommonDivisorI.md +1 -1
  216. package/docs/Std.Math/GreatestCommonDivisorL.md +1 -1
  217. package/docs/Std.Math/HammingWeightI.md +1 -1
  218. package/docs/Std.Math/InverseModI.md +1 -1
  219. package/docs/Std.Math/InverseModL.md +1 -1
  220. package/docs/Std.Math/IsCoprimeI.md +1 -1
  221. package/docs/Std.Math/IsCoprimeL.md +1 -1
  222. package/docs/Std.Math/IsInfinite.md +1 -1
  223. package/docs/Std.Math/IsNaN.md +1 -1
  224. package/docs/Std.Math/LargestFixedPoint.md +1 -1
  225. package/docs/Std.Math/Lg.md +1 -1
  226. package/docs/Std.Math/Log.md +1 -1
  227. package/docs/Std.Math/Log10.md +1 -1
  228. package/docs/Std.Math/LogFactorialD.md +1 -1
  229. package/docs/Std.Math/LogGammaD.md +1 -1
  230. package/docs/Std.Math/LogOf2.md +1 -1
  231. package/docs/Std.Math/Max.md +1 -1
  232. package/docs/Std.Math/MaxD.md +1 -1
  233. package/docs/Std.Math/MaxI.md +1 -1
  234. package/docs/Std.Math/MaxL.md +1 -1
  235. package/docs/Std.Math/Min.md +1 -1
  236. package/docs/Std.Math/MinD.md +1 -1
  237. package/docs/Std.Math/MinI.md +1 -1
  238. package/docs/Std.Math/MinL.md +1 -1
  239. package/docs/Std.Math/MinusC.md +1 -1
  240. package/docs/Std.Math/MinusCP.md +1 -1
  241. package/docs/Std.Math/ModulusI.md +1 -1
  242. package/docs/Std.Math/ModulusL.md +1 -1
  243. package/docs/Std.Math/NegationC.md +1 -1
  244. package/docs/Std.Math/NegationCP.md +1 -1
  245. package/docs/Std.Math/PI.md +1 -1
  246. package/docs/Std.Math/PNorm.md +1 -1
  247. package/docs/Std.Math/PNormalized.md +1 -1
  248. package/docs/Std.Math/PlusC.md +1 -1
  249. package/docs/Std.Math/PlusCP.md +1 -1
  250. package/docs/Std.Math/PowC.md +1 -1
  251. package/docs/Std.Math/PowCP.md +1 -1
  252. package/docs/Std.Math/RealMod.md +1 -1
  253. package/docs/Std.Math/Round.md +1 -1
  254. package/docs/Std.Math/RoundHalfAwayFromZero.md +1 -1
  255. package/docs/Std.Math/SignD.md +1 -1
  256. package/docs/Std.Math/SignI.md +1 -1
  257. package/docs/Std.Math/SignL.md +1 -1
  258. package/docs/Std.Math/Sin.md +1 -1
  259. package/docs/Std.Math/Sinh.md +1 -1
  260. package/docs/Std.Math/SmallestFixedPoint.md +1 -1
  261. package/docs/Std.Math/Sqrt.md +1 -1
  262. package/docs/Std.Math/SquaredNorm.md +1 -1
  263. package/docs/Std.Math/Tan.md +1 -1
  264. package/docs/Std.Math/Tanh.md +1 -1
  265. package/docs/Std.Math/TimesC.md +1 -1
  266. package/docs/Std.Math/TimesCP.md +1 -1
  267. package/docs/Std.Math/TrailingZeroCountI.md +1 -1
  268. package/docs/Std.Math/TrailingZeroCountL.md +1 -1
  269. package/docs/Std.Math/Truncate.md +1 -1
  270. package/docs/Std.Math/index.md +1 -1
  271. package/docs/Std.Measurement/IsLossResult.md +1 -1
  272. package/docs/Std.Measurement/MResetEachZ.md +1 -1
  273. package/docs/Std.Measurement/MResetX.md +1 -1
  274. package/docs/Std.Measurement/MResetY.md +1 -1
  275. package/docs/Std.Measurement/MResetZ.md +1 -1
  276. package/docs/Std.Measurement/MResetZChecked.md +1 -1
  277. package/docs/Std.Measurement/MeasureAllZ.md +1 -1
  278. package/docs/Std.Measurement/MeasureEachZ.md +1 -1
  279. package/docs/Std.Measurement/MeasureInteger.md +1 -1
  280. package/docs/Std.Measurement/index.md +1 -1
  281. package/docs/Std.Random/DrawRandomBool.md +1 -1
  282. package/docs/Std.Random/DrawRandomDouble.md +1 -1
  283. package/docs/Std.Random/DrawRandomInt.md +1 -1
  284. package/docs/Std.Random/index.md +1 -1
  285. package/docs/Std.Range/IsRangeEmpty.md +1 -1
  286. package/docs/Std.Range/RangeEnd.md +1 -1
  287. package/docs/Std.Range/RangeReverse.md +1 -1
  288. package/docs/Std.Range/RangeStart.md +1 -1
  289. package/docs/Std.Range/RangeStep.md +1 -1
  290. package/docs/Std.Range/index.md +1 -1
  291. package/docs/Std.ResourceEstimation/AccountForEstimates.md +1 -1
  292. package/docs/Std.ResourceEstimation/AuxQubitCount.md +1 -1
  293. package/docs/Std.ResourceEstimation/BeginEstimateCaching.md +1 -1
  294. package/docs/Std.ResourceEstimation/BeginRepeatEstimates.md +1 -1
  295. package/docs/Std.ResourceEstimation/CczCount.md +1 -1
  296. package/docs/Std.ResourceEstimation/EnableMemoryComputeArchitecture.md +1 -1
  297. package/docs/Std.ResourceEstimation/EndEstimateCaching.md +1 -1
  298. package/docs/Std.ResourceEstimation/EndRepeatEstimates.md +1 -1
  299. package/docs/Std.ResourceEstimation/LeastFrequentlyUsed.md +1 -1
  300. package/docs/Std.ResourceEstimation/LeastRecentlyUsed.md +1 -1
  301. package/docs/Std.ResourceEstimation/MeasurementCount.md +1 -1
  302. package/docs/Std.ResourceEstimation/PSSPCLayout.md +1 -1
  303. package/docs/Std.ResourceEstimation/RepeatEstimates.md +1 -1
  304. package/docs/Std.ResourceEstimation/RotationCount.md +1 -1
  305. package/docs/Std.ResourceEstimation/RotationDepth.md +1 -1
  306. package/docs/Std.ResourceEstimation/SingleVariant.md +1 -1
  307. package/docs/Std.ResourceEstimation/TCount.md +1 -1
  308. package/docs/Std.ResourceEstimation/index.md +1 -1
  309. package/docs/Std.StatePreparation/ApproximatelyPreparePureStateCP.md +1 -1
  310. package/docs/Std.StatePreparation/PreparePureStateD.md +1 -1
  311. package/docs/Std.StatePreparation/PrepareUniformSuperposition.md +1 -1
  312. package/docs/Std.StatePreparation/index.md +1 -1
  313. package/docs/Std.TableLookup/Select.md +1 -1
  314. package/docs/Std.TableLookup/index.md +1 -1
  315. package/docs/index.md +1 -1
  316. package/lib/nodejs/qsc_wasm.cjs +1 -1
  317. package/lib/nodejs/qsc_wasm_bg.wasm +0 -0
  318. package/lib/web/qsc_wasm.js +1 -1
  319. package/lib/web/qsc_wasm_bg.wasm +0 -0
  320. package/package.json +2 -1
  321. package/ux/circuit-vis/angleExpression.ts +133 -0
  322. package/ux/circuit-vis/contextMenu.ts +8 -73
  323. package/ux/circuit-vis/events.ts +41 -1
  324. package/ux/circuit-vis/formatters/inputFormatter.ts +14 -6
  325. package/ux/circuit-vis/index.ts +12 -4
  326. package/ux/circuit-vis/panel.ts +65 -28
  327. package/ux/circuit-vis/sqore.ts +30 -16
  328. package/ux/circuit-vis/state-viz/stateViz.ts +763 -0
  329. package/ux/circuit-vis/state-viz/stateVizController.ts +285 -0
  330. package/ux/circuit-vis/state-viz/worker/index.ts +18 -0
  331. package/ux/circuit-vis/state-viz/worker/stateCompute.ts +260 -0
  332. package/ux/circuit-vis/state-viz/worker/stateVizPrep.ts +152 -0
  333. package/ux/circuit.tsx +15 -26
  334. package/ux/data.ts +5 -3
  335. package/ux/index.ts +2 -0
  336. package/ux/qdk-theme.css +15 -0
  337. package/ux/qsharp-circuit.css +311 -1
@@ -0,0 +1,763 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT license.
3
+
4
+ // State visualization renderer.
5
+ // Defines the renderable column/types and updates the `.state-panel` DOM
6
+ // (SVG/HTML) to display probabilities/phases, given either an amp map or
7
+ // pre-prepared columns.
8
+
9
+ export type RenderOptions = {
10
+ maxColumns?: number;
11
+ phaseColorMap?: (phaseRad: number) => string;
12
+ // Fill color for the aggregated "Others" column.
13
+ // Default comes from VIZ.defaultOthersColor.
14
+ othersColor?: string;
15
+ minColumnWidth?: number; // minimum width per column to avoid label collisions
16
+ minPanelWidthPx?: number; // prescribed minimum panel width in pixels
17
+ maxPanelWidthPx?: number; // prescribed maximum panel width in pixels
18
+ animationMs?: number; // global animation duration in ms (default 200ms)
19
+ };
20
+
21
+ // Visualization config constants
22
+ const VIZ = {
23
+ defaultAnimationMs: 200,
24
+ baseHeight: 80,
25
+ marginLeft: 36,
26
+ marginRight: 36,
27
+ marginBottom: 62,
28
+ minPanelWidthPx: 80,
29
+ defaultMinPanelWidth: 190,
30
+ defaultOthersColor: "#a6a6a6",
31
+ columnSpacing: 4,
32
+ minColumnWidthFloor: 16,
33
+ defaultMinColumnWidth: 36,
34
+ defaultMaxColumns: 16,
35
+ labelLongThresholdChars: 4,
36
+ barHeaderPadding: 36,
37
+ phaseHeaderPadding: 26,
38
+ stateHeaderPadding: 26,
39
+ percentLabelPadding: 29,
40
+ phaseLabelPadding: 39,
41
+ marginBottomMinPx: 48,
42
+ extraBottomPaddingPx: 24,
43
+ barAreaHeight: 234,
44
+ minProbEpsilon: 1e-12,
45
+ headerLabelXOffset: -8,
46
+ headerLabelYOffset: 9,
47
+ percentLabelOffset: 8,
48
+ phaseRadiusBase: 12,
49
+ phaseRadiusThreshold: 7.5,
50
+ phaseCirclePaddingX: 2,
51
+ phaseCirclePaddingY: 10,
52
+ phaseDotFrac: 0.25,
53
+ phaseDotRadiusMinPx: 1.5,
54
+ phaseTextBottomPad: 6,
55
+ verticalLabelCharHeight: 14,
56
+ phaseLabelLineHeight: 14,
57
+ verticalLabelExtraBase: 12,
58
+ stateLabelVerticalOffset: 4,
59
+ stateLabelHorizontalOffset: 16,
60
+ contentHeightExtra: 10,
61
+ edgePad: 36,
62
+ emptyStateFlexBasisPx: 360,
63
+ rowLabelFallbackPx: 24,
64
+ };
65
+
66
+ // --- Entry Points ---
67
+
68
+ export const createStatePanel = (): HTMLElement => {
69
+ try {
70
+ // Allows host environments (e.g., VS Code webview) to react to panel creation
71
+ // without needing a direct import hook.
72
+ (globalThis as any).dispatchEvent?.(
73
+ new CustomEvent("qsharp:stateviz:create"),
74
+ );
75
+ } catch {
76
+ // Ignore environments without CustomEvent / dispatchEvent
77
+ }
78
+ const panel = document.createElement("div");
79
+ panel.className = "state-panel";
80
+ panel.classList.add("collapsed");
81
+
82
+ const edge = document.createElement("div");
83
+ edge.className = "state-edge";
84
+ edge.setAttribute("role", "button");
85
+ edge.setAttribute("tabindex", "0");
86
+ edge.setAttribute("aria-label", "Toggle state panel");
87
+ edge.setAttribute("aria-expanded", "false");
88
+ const edgeText = document.createElement("span");
89
+ edgeText.className = "state-edge-text";
90
+ edgeText.textContent = "State Visualization";
91
+ edge.appendChild(edgeText);
92
+
93
+ const mkEdgeIcon = (cls: string): SVGSVGElement => {
94
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
95
+ svg.setAttribute("viewBox", "0 0 14 14");
96
+ svg.setAttribute("aria-hidden", "true");
97
+ svg.classList.add("edge-icon", cls);
98
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
99
+ path.setAttribute("d", "M 4.25 11 L 11 7 L 4.25 3 Z");
100
+ svg.appendChild(path);
101
+ return svg as SVGSVGElement;
102
+ };
103
+
104
+ const iconTop = mkEdgeIcon("edge-icon-top");
105
+ const iconBottom = mkEdgeIcon("edge-icon-bottom");
106
+ edge.appendChild(iconTop);
107
+ edge.appendChild(iconBottom);
108
+
109
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
110
+ svg.classList.add("state-svg");
111
+ svg.setAttribute("width", "100%");
112
+ svg.setAttribute("height", "100%");
113
+
114
+ panel.appendChild(edge);
115
+ panel.appendChild(svg);
116
+
117
+ const toggleCollapsed = () => {
118
+ const collapsed = panel.classList.toggle("collapsed");
119
+ edge.setAttribute("aria-expanded", (!collapsed).toString());
120
+ };
121
+ edge.addEventListener("click", toggleCollapsed);
122
+ edge.addEventListener("keydown", (ev) => {
123
+ if (ev.key === "Enter" || ev.key === " ") {
124
+ ev.preventDefault();
125
+ toggleCollapsed();
126
+ }
127
+ });
128
+ return panel;
129
+ };
130
+
131
+ const ensureLoadingOverlay = (panel: HTMLElement): HTMLElement => {
132
+ let overlay = panel.querySelector(
133
+ ".state-loading-overlay",
134
+ ) as HTMLElement | null;
135
+ if (overlay) return overlay;
136
+
137
+ overlay = document.createElement("div");
138
+ overlay.className = "state-loading-overlay";
139
+ overlay.setAttribute("aria-hidden", "true");
140
+
141
+ const spinner = document.createElement("div");
142
+ spinner.className = "state-loading-spinner";
143
+ overlay.appendChild(spinner);
144
+
145
+ panel.appendChild(overlay);
146
+ return overlay;
147
+ };
148
+
149
+ export const setStatePanelLoading = (panel: HTMLElement, loading: boolean) => {
150
+ if (!panel) return;
151
+ if (loading) {
152
+ ensureLoadingOverlay(panel);
153
+ panel.classList.add("loading");
154
+ } else {
155
+ panel.classList.remove("loading");
156
+ }
157
+ };
158
+
159
+ // Put the panel into a message state (e.g., empty circuit or unsupported).
160
+ export const renderMessageStatePanel = (
161
+ panel: HTMLElement,
162
+ message = "The circuit is empty.",
163
+ ): void => {
164
+ const svg = panel.querySelector("svg.state-svg") as SVGSVGElement | null;
165
+ if (svg) {
166
+ while (svg.firstChild) svg.removeChild(svg.firstChild);
167
+ svg.removeAttribute("height");
168
+ }
169
+ panel.classList.add("message");
170
+
171
+ let msg = panel.querySelector(".state-panel-message") as HTMLElement | null;
172
+ if (!msg) {
173
+ msg = document.createElement("div");
174
+ msg.className = "state-panel-message";
175
+ panel.appendChild(msg);
176
+ }
177
+ msg.textContent = message;
178
+ panel.style.flexBasis = `${VIZ.emptyStateFlexBasisPx}px`;
179
+ };
180
+
181
+ // Put the panel into a blank (non-message) state.
182
+ // This is used when the circuit is non-empty but state data isn't available yet.
183
+ export const renderBlankStatePanel = (panel: HTMLElement): void => {
184
+ const svg = panel.querySelector("svg.state-svg") as SVGSVGElement | null;
185
+ if (svg) {
186
+ while (svg.firstChild) svg.removeChild(svg.firstChild);
187
+ }
188
+ panel.classList.remove("message");
189
+ const msg = panel.querySelector(".state-panel-message");
190
+ if (msg) msg.remove();
191
+ // If we were previously in message state, restore sizing control back to CSS
192
+ // (or subsequent renders) instead of keeping the message-state flex-basis.
193
+ panel.style.flexBasis = "";
194
+ };
195
+
196
+ // Render from precomputed columns (e.g., prepared in a Web Worker).
197
+ export const updateStatePanelFromColumns = (
198
+ panel: HTMLElement,
199
+ columns: StateColumn[],
200
+ opts: RenderOptions = {},
201
+ ): void => {
202
+ // Content visibility restored via CSS when not in empty mode
203
+ // Remove empty mode to reveal content via CSS
204
+ panel.classList.remove("message");
205
+ const msg = panel.querySelector(".state-panel-message");
206
+ if (msg) msg.remove();
207
+ panel.style.flexBasis = "";
208
+
209
+ renderStatePanel(panel, columns, opts);
210
+ };
211
+
212
+ // --- State Amplitude Preparation ---
213
+
214
+ export type AmpComplex = { re: number; im: number };
215
+ export type AmpPolar = { prob?: number; phase?: number };
216
+ export type AmpLike = AmpComplex | AmpPolar;
217
+ export type AmpMap = Record<string, AmpLike>;
218
+
219
+ // --- Layout Computation ---
220
+
221
+ // The data for a single column in the state visualization
222
+ export type StateColumn = {
223
+ label: string;
224
+ prob: number;
225
+ phase: number;
226
+ isOthers?: boolean;
227
+ othersCount?: number;
228
+ };
229
+
230
+ // Layout metrics used to organize rendering logic
231
+ type LayoutMetrics = {
232
+ panelWidthPx: number;
233
+ contentWidthPx: number;
234
+
235
+ columnWidthPx: number;
236
+
237
+ maxProb: number;
238
+
239
+ phaseSectionTopY: number;
240
+ phaseCircleRadiusPx: number;
241
+
242
+ stateSectionTopY: number;
243
+ verticalLabels: boolean;
244
+ maxLabelLen: number;
245
+
246
+ animationMs: number;
247
+ othersColor: string;
248
+ phaseColor: (phi: number) => string;
249
+ };
250
+
251
+ // The animation speed for the state viz panel can be set via the passed in options
252
+ // argument, or via CSS custom property `--stateAnimMs` on the panel element.
253
+ // This function computes the effective animation duration in milliseconds from
254
+ // these sources, with the CSS value taking precedence over the options argument.
255
+ const getAnimationMs = (panel: HTMLElement, opts: RenderOptions): number => {
256
+ let animationMs = VIZ.defaultAnimationMs;
257
+ if (
258
+ typeof opts.animationMs === "number" &&
259
+ isFinite(opts.animationMs) &&
260
+ opts.animationMs >= 0
261
+ ) {
262
+ animationMs = Math.round(opts.animationMs);
263
+ }
264
+ if (panel.isConnected) {
265
+ const cssDur = getComputedStyle(panel)
266
+ .getPropertyValue("--stateAnimMs")
267
+ .trim();
268
+ const parsed = parseDurationMs(cssDur);
269
+ if (!isNaN(parsed) && parsed >= 0) animationMs = parsed;
270
+ }
271
+ return animationMs;
272
+ };
273
+
274
+ // Parse CSS duration strings (e.g., "200ms" or "0.2s") into milliseconds
275
+ const parseDurationMs = (val: string): number => {
276
+ const s = (val || "").trim();
277
+ if (!s) return NaN;
278
+ if (s.endsWith("ms")) {
279
+ const v = parseFloat(s.slice(0, -2));
280
+ return isFinite(v) ? v : NaN;
281
+ }
282
+ if (s.endsWith("s")) {
283
+ const v = parseFloat(s.slice(0, -1));
284
+ return isFinite(v) ? Math.round(v * 1000) : NaN;
285
+ }
286
+ const v = parseFloat(s);
287
+ return isFinite(v) ? v : NaN;
288
+ };
289
+
290
+ // Combines layout information from option, column data, and VIZ constants to compute finalized layout metrics.
291
+ const computeLayoutMetrics = (
292
+ panel: HTMLElement,
293
+ columnsData: StateColumn[],
294
+ opts: RenderOptions,
295
+ ): LayoutMetrics => {
296
+ const animationMs = getAnimationMs(panel, opts);
297
+
298
+ const columnCount = columnsData.length;
299
+ const minColumnWidthPx = Math.max(
300
+ VIZ.minColumnWidthFloor,
301
+ typeof opts.minColumnWidth === "number"
302
+ ? Math.floor(opts.minColumnWidth)
303
+ : VIZ.defaultMinColumnWidth,
304
+ );
305
+ const maxColumns = opts.maxColumns ?? VIZ.defaultMaxColumns;
306
+ const defaultMinPanelWidthPx = VIZ.defaultMinPanelWidth;
307
+ const defaultMaxPanelWidthPx =
308
+ VIZ.marginLeft +
309
+ VIZ.marginRight +
310
+ maxColumns * (minColumnWidthPx + VIZ.columnSpacing);
311
+
312
+ const minWidthPx = Math.max(
313
+ VIZ.minPanelWidthPx,
314
+ opts.minPanelWidthPx ?? defaultMinPanelWidthPx,
315
+ );
316
+ const maxWidthPx = Math.max(
317
+ minWidthPx,
318
+ opts.maxPanelWidthPx ?? defaultMaxPanelWidthPx,
319
+ );
320
+ const growthFactor = Math.max(
321
+ 0,
322
+ Math.min(1, (columnCount - 1) / (maxColumns - 1)),
323
+ );
324
+ const panelWidthPx = Math.round(
325
+ minWidthPx + growthFactor * (maxWidthPx - minWidthPx),
326
+ );
327
+ const contentWidthPx = panelWidthPx - VIZ.marginLeft - VIZ.marginRight;
328
+ const columnWidthPx = Math.max(
329
+ 4,
330
+ Math.floor(contentWidthPx / Math.max(1, columnCount)) - VIZ.columnSpacing,
331
+ );
332
+ const phaseCircleRadiusPx = Math.max(
333
+ VIZ.phaseRadiusBase,
334
+ Math.floor(columnWidthPx / 2) - 1,
335
+ );
336
+ const maxLabelLen = columnsData.reduce(
337
+ (m, b) => Math.max(m, (displayLabel(b) || "").length),
338
+ 0,
339
+ );
340
+ const verticalLabels = maxLabelLen > VIZ.labelLongThresholdChars;
341
+
342
+ const maxProb = Math.max(
343
+ VIZ.minProbEpsilon,
344
+ Math.max(...columnsData.map((b) => b.prob ?? 0)),
345
+ );
346
+
347
+ const phaseColor = opts.phaseColorMap ?? defaultPhaseColor;
348
+ const othersColor = opts.othersColor ?? VIZ.defaultOthersColor;
349
+
350
+ const phaseSectionTopY =
351
+ VIZ.barHeaderPadding + VIZ.barAreaHeight + VIZ.percentLabelPadding;
352
+ const stateSectionTopY =
353
+ phaseSectionTopY +
354
+ VIZ.phaseHeaderPadding +
355
+ 2 * phaseCircleRadiusPx +
356
+ VIZ.phaseLabelPadding;
357
+
358
+ return {
359
+ panelWidthPx,
360
+ contentWidthPx,
361
+ columnWidthPx,
362
+ maxProb,
363
+ phaseSectionTopY,
364
+ phaseCircleRadiusPx,
365
+ stateSectionTopY,
366
+ verticalLabels,
367
+ maxLabelLen,
368
+ animationMs,
369
+ phaseColor,
370
+ othersColor,
371
+ };
372
+ };
373
+
374
+ // --- Rendering functions ---
375
+
376
+ const renderStatePanel = (
377
+ panel: HTMLElement,
378
+ columnData: StateColumn[],
379
+ opts: RenderOptions = {},
380
+ ): void => {
381
+ const svg = panel.querySelector("svg.state-svg") as SVGSVGElement | null;
382
+ if (!svg) return;
383
+ const prev: Record<string, { prob: number; phase: number }> =
384
+ (panel as any)._stateVizPrev ?? {};
385
+
386
+ while (svg.firstChild) svg.removeChild(svg.firstChild);
387
+
388
+ const layout = computeLayoutMetrics(panel, columnData, opts);
389
+
390
+ const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
391
+ g.setAttribute("transform", `translate(${VIZ.marginLeft},${0})`);
392
+ svg.appendChild(g);
393
+
394
+ renderSectionHeaders(g, layout);
395
+
396
+ columnData.forEach((col, i) => renderColumn(g, col, i, prev, layout));
397
+
398
+ finalizeSvgAndFlex(svg, panel, g, layout);
399
+ savePreviousValues(panel, columnData);
400
+ };
401
+
402
+ // Render the section headers and separators
403
+ const renderSectionHeaders = (g: SVGGElement, layout: LayoutMetrics) => {
404
+ const mkLabel = (text: string, y: number) => {
405
+ const t = document.createElementNS("http://www.w3.org/2000/svg", "text");
406
+ t.setAttribute("x", `${VIZ.headerLabelXOffset}`);
407
+ t.setAttribute("y", `${y + VIZ.headerLabelYOffset}`);
408
+ t.setAttribute("class", "state-header");
409
+ t.textContent = text;
410
+ return t;
411
+ };
412
+ const mkSep = (y: number) => {
413
+ const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
414
+ line.setAttribute("x1", "0");
415
+ line.setAttribute("y1", `${y}`);
416
+ line.setAttribute("x2", `${layout.contentWidthPx}`);
417
+ line.setAttribute("y2", `${y}`);
418
+ line.setAttribute("class", "state-separator");
419
+ return line;
420
+ };
421
+ g.appendChild(mkLabel("Probability Density", 0));
422
+ g.appendChild(mkSep(layout.phaseSectionTopY));
423
+ g.appendChild(mkLabel("Phase", layout.phaseSectionTopY));
424
+ g.appendChild(mkSep(layout.stateSectionTopY));
425
+ g.appendChild(mkLabel("State", layout.stateSectionTopY));
426
+ };
427
+
428
+ // Render a full column (percentage bar + phase + label)
429
+ const renderColumn = (
430
+ g: SVGGElement,
431
+ column: StateColumn,
432
+ colIdx: number,
433
+ prev: Record<string, { prob: number; phase: number }>,
434
+ layout: LayoutMetrics,
435
+ ) => {
436
+ const colX = colIdx * (layout.columnWidthPx + VIZ.columnSpacing);
437
+
438
+ const prevProb = prev[column.label]?.prob ?? 0;
439
+ const bar = renderProbSection(g, column, prevProb, colX, layout);
440
+
441
+ const prevPhase = prev[column.label]?.phase ?? 0;
442
+ renderPhaseSection(g, column, prevPhase, bar, colX, layout);
443
+
444
+ renderStateLabelSection(g, column, colX, layout);
445
+ };
446
+
447
+ const renderProbSection = (
448
+ g: SVGGElement,
449
+ column: StateColumn,
450
+ prevProb: number,
451
+ colX: number,
452
+ layout: LayoutMetrics,
453
+ ): SVGRectElement => {
454
+ const { columnWidthPx, maxProb, animationMs, phaseColor, othersColor } =
455
+ layout;
456
+ const cx = colX + columnWidthPx / 2;
457
+
458
+ const scaleY = (p: number) =>
459
+ (Math.max(0, Math.min(p, maxProb)) / maxProb) * VIZ.barAreaHeight;
460
+
461
+ const bar = document.createElementNS(
462
+ "http://www.w3.org/2000/svg",
463
+ "rect",
464
+ ) as unknown as SVGRectElement;
465
+ bar.setAttribute("x", `${colX}`);
466
+ bar.setAttribute("width", `${columnWidthPx}`);
467
+ bar.setAttribute(
468
+ "fill",
469
+ column.isOthers ? othersColor : phaseColor(column.phase),
470
+ );
471
+ bar.setAttribute("class", "state-bar");
472
+ const tip = document.createElementNS("http://www.w3.org/2000/svg", "title");
473
+ const pctTipTarget = (column.prob ?? 0) * 100;
474
+ tip.textContent = column.isOthers
475
+ ? `${pctTipTarget.toFixed(1)}% • Others (${column.othersCount ?? 0} states)`
476
+ : `${pctTipTarget.toFixed(1)}% • φ=${formatPhasePiTip(column.phase)}`;
477
+ bar.appendChild(tip);
478
+ g.appendChild(bar);
479
+
480
+ const fromH = scaleY(prevProb);
481
+ const baseY = VIZ.barHeaderPadding + VIZ.barAreaHeight;
482
+ bar.setAttribute("y", `${baseY - fromH}`);
483
+ bar.setAttribute("height", `${fromH}`);
484
+ animate(prevProb, column.prob, animationMs, (pv) => {
485
+ const h = scaleY(pv);
486
+ bar.setAttribute("y", `${baseY - h}`);
487
+ bar.setAttribute("height", `${h}`);
488
+ });
489
+
490
+ const label = document.createElementNS("http://www.w3.org/2000/svg", "text");
491
+ label.setAttribute("x", `${cx}`);
492
+ const labelY =
493
+ VIZ.barHeaderPadding + VIZ.barAreaHeight + VIZ.percentLabelOffset;
494
+ label.setAttribute("y", `${labelY}`);
495
+ label.setAttribute("class", "state-bar-label");
496
+ animate(prevProb, column.prob, animationMs, (pv) => {
497
+ const pct = (pv ?? 0) * 100;
498
+ label.textContent = pct >= 1 ? `${pct.toFixed(0)}%` : `${pct.toFixed(1)}%`;
499
+ });
500
+ g.appendChild(label);
501
+
502
+ return bar;
503
+ };
504
+
505
+ const renderPhaseSection = (
506
+ g: SVGGElement,
507
+ column: StateColumn,
508
+ prevPhase: number,
509
+ bar: SVGRectElement,
510
+ colX: number,
511
+ layout: LayoutMetrics,
512
+ ): void => {
513
+ if (column.isOthers) return;
514
+
515
+ const {
516
+ columnWidthPx,
517
+ phaseSectionTopY,
518
+ phaseCircleRadiusPx,
519
+ stateSectionTopY,
520
+ animationMs,
521
+ phaseColor,
522
+ } = layout;
523
+ const cx = colX + columnWidthPx / 2;
524
+
525
+ let r = phaseCircleRadiusPx;
526
+ if (r >= VIZ.phaseRadiusThreshold) {
527
+ const maxR = Math.floor(
528
+ (columnWidthPx / 2 - VIZ.phaseCirclePaddingX) / (1 + VIZ.phaseDotFrac),
529
+ );
530
+ r = Math.min(r, Math.max(2, maxR));
531
+ } else {
532
+ const maxR = Math.floor(columnWidthPx / 2 - VIZ.phaseCirclePaddingX - 1.5);
533
+ r = Math.min(r, Math.max(2, maxR));
534
+ }
535
+
536
+ const phaseContentYBase = phaseSectionTopY + VIZ.phaseHeaderPadding;
537
+ const cy = phaseContentYBase + r + VIZ.phaseCirclePaddingY;
538
+ const sx = cx + r;
539
+ const sy = cy;
540
+ const ex = cx + r * Math.cos(column.phase);
541
+ const ey = cy - r * Math.sin(column.phase);
542
+ const largeArc = Math.abs(column.phase) > Math.PI ? 1 : 0;
543
+ const sweep = column.phase < 0 ? 1 : 0;
544
+
545
+ const wedge = document.createElementNS("http://www.w3.org/2000/svg", "path");
546
+ const dTarget = `M ${cx} ${cy} L ${sx} ${sy} A ${r} ${r} 0 ${largeArc} ${sweep} ${ex} ${ey} Z`;
547
+ wedge.setAttribute("d", dTarget);
548
+ wedge.setAttribute("class", "state-phase-wedge");
549
+ wedge.setAttribute("fill", phaseColor(column.phase));
550
+ g.appendChild(wedge);
551
+
552
+ const circle = document.createElementNS(
553
+ "http://www.w3.org/2000/svg",
554
+ "circle",
555
+ );
556
+ circle.setAttribute("cx", `${cx}`);
557
+ circle.setAttribute("cy", `${cy}`);
558
+ circle.setAttribute("r", `${r}`);
559
+ circle.setAttribute("class", "state-phase-circle");
560
+ const tipPhase = document.createElementNS(
561
+ "http://www.w3.org/2000/svg",
562
+ "title",
563
+ );
564
+ tipPhase.textContent = `φ=${formatPhasePiTip(column.phase)}`;
565
+ circle.appendChild(tipPhase);
566
+ g.appendChild(circle);
567
+
568
+ const phaseText = document.createElementNS(
569
+ "http://www.w3.org/2000/svg",
570
+ "text",
571
+ );
572
+ phaseText.setAttribute("x", `${cx}`);
573
+ const dotRadius = Math.max(VIZ.phaseDotRadiusMinPx, r * VIZ.phaseDotFrac);
574
+ const labelAreaTopY = cy + r + dotRadius;
575
+ const labelAreaBottomY = stateSectionTopY - VIZ.phaseTextBottomPad;
576
+ const availableH = Math.max(0, labelAreaBottomY - labelAreaTopY);
577
+ const textH = VIZ.phaseLabelLineHeight;
578
+ const yTextTop = Math.round(
579
+ labelAreaTopY + Math.max(0, (availableH - textH) / 2),
580
+ );
581
+ phaseText.setAttribute("y", `${yTextTop}`);
582
+ phaseText.setAttribute("class", "state-phase-text");
583
+ animate(prevPhase, column.phase, animationMs, (pv) => {
584
+ phaseText.textContent = formatPhasePi(pv);
585
+ });
586
+ g.appendChild(phaseText);
587
+
588
+ const prevDx = r * Math.cos(prevPhase);
589
+ const prevDy = r * Math.sin(prevPhase);
590
+ const dot = document.createElementNS("http://www.w3.org/2000/svg", "circle");
591
+ dot.setAttribute("cx", `${cx + prevDx}`);
592
+ dot.setAttribute("cy", `${cy - prevDy}`);
593
+ dot.setAttribute(
594
+ "r",
595
+ `${Math.max(VIZ.phaseDotRadiusMinPx, r * VIZ.phaseDotFrac)}`,
596
+ );
597
+ dot.setAttribute("fill", phaseColor(column.phase));
598
+ dot.setAttribute("class", "state-phase-dot");
599
+ g.appendChild(dot);
600
+
601
+ animate(prevPhase, column.phase, animationMs, (pv) => {
602
+ const dx = r * Math.cos(pv);
603
+ const dy = r * Math.sin(pv);
604
+ dot.setAttribute("cx", `${cx + dx}`);
605
+ dot.setAttribute("cy", `${cy - dy}`);
606
+ const fillColor = phaseColor(pv);
607
+ wedge.setAttribute("fill", fillColor);
608
+ dot.setAttribute("fill", fillColor);
609
+ bar.setAttribute("fill", fillColor);
610
+ const exA = cx + r * Math.cos(pv);
611
+ const eyA = cy - r * Math.sin(pv);
612
+ const largeArcA = Math.abs(pv) > Math.PI ? 1 : 0;
613
+ const sweepA = pv < 0 ? 1 : 0;
614
+ const dA = `M ${cx} ${cy} L ${sx} ${sy} A ${r} ${r} 0 ${largeArcA} ${sweepA} ${exA} ${eyA} Z`;
615
+ wedge.setAttribute("d", dA);
616
+ });
617
+ };
618
+
619
+ const renderStateLabelSection = (
620
+ g: SVGGElement,
621
+ column: StateColumn,
622
+ colX: number,
623
+ layout: LayoutMetrics,
624
+ ): void => {
625
+ const { columnWidthPx, stateSectionTopY, verticalLabels } = layout;
626
+ const cx = colX + columnWidthPx / 2;
627
+
628
+ const stateContentYBase = stateSectionTopY + VIZ.stateHeaderPadding;
629
+ const labelY = verticalLabels
630
+ ? stateContentYBase + VIZ.stateLabelVerticalOffset
631
+ : stateContentYBase + VIZ.stateLabelHorizontalOffset;
632
+
633
+ if (verticalLabels) {
634
+ const labelText = displayLabel(column);
635
+ const labelH =
636
+ VIZ.verticalLabelCharHeight * Math.max(1, (labelText || "").length);
637
+ const fo = document.createElementNS(
638
+ "http://www.w3.org/2000/svg",
639
+ "foreignObject",
640
+ );
641
+ fo.setAttribute("x", `${colX}`);
642
+ fo.setAttribute("y", `${labelY}`);
643
+ fo.setAttribute("width", `${columnWidthPx}`);
644
+ fo.setAttribute("height", `${labelH}`);
645
+ const div = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
646
+ div.setAttribute("class", "state-bitstring-fo");
647
+ div.textContent = labelText;
648
+ fo.appendChild(div);
649
+ g.appendChild(fo);
650
+ } else {
651
+ const t = document.createElementNS("http://www.w3.org/2000/svg", "text");
652
+ t.setAttribute("x", `${cx}`);
653
+ t.setAttribute("y", `${labelY}`);
654
+ t.setAttribute("class", "state-bitstring");
655
+ t.textContent = displayLabel(column);
656
+ g.appendChild(t);
657
+ }
658
+ };
659
+
660
+ const finalizeSvgAndFlex = (
661
+ svg: SVGSVGElement,
662
+ panel: HTMLElement,
663
+ g: SVGGElement,
664
+ layout: LayoutMetrics,
665
+ ) => {
666
+ try {
667
+ const bbox = g.getBBox();
668
+ const contentHeight = Math.ceil(bbox.height + VIZ.contentHeightExtra);
669
+ const svgHeight = Math.max(VIZ.baseHeight, contentHeight);
670
+ svg.setAttribute("height", svgHeight.toString());
671
+ svg.setAttribute("width", layout.panelWidthPx.toString());
672
+ const edgePad = VIZ.edgePad;
673
+ panel.style.flexBasis = `${Math.ceil(layout.panelWidthPx + edgePad)}px`;
674
+ } catch {
675
+ // If getBBox fails (e.g., JSDOM/SVG not fully rendered), fall back to a
676
+ // deterministic height based on our layout constants so snapshots still
677
+ // include the whole visualization.
678
+ const labelTextHeightPx = layout.verticalLabels
679
+ ? VIZ.verticalLabelCharHeight * Math.max(1, layout.maxLabelLen)
680
+ : VIZ.phaseLabelLineHeight;
681
+ const labelBottomY =
682
+ layout.stateSectionTopY +
683
+ VIZ.stateHeaderPadding +
684
+ (layout.verticalLabels
685
+ ? VIZ.stateLabelVerticalOffset
686
+ : VIZ.stateLabelHorizontalOffset) +
687
+ labelTextHeightPx;
688
+
689
+ const svgHeight = Math.max(
690
+ VIZ.baseHeight,
691
+ Math.ceil(
692
+ labelBottomY + VIZ.extraBottomPaddingPx + VIZ.marginBottomMinPx,
693
+ ),
694
+ );
695
+ svg.setAttribute("height", svgHeight.toString());
696
+ svg.setAttribute("width", layout.panelWidthPx.toString());
697
+ const edgePad = VIZ.edgePad;
698
+ panel.style.flexBasis = `${Math.ceil(layout.panelWidthPx + edgePad)}px`;
699
+ }
700
+ };
701
+
702
+ const savePreviousValues = (panel: HTMLElement, columnData: StateColumn[]) => {
703
+ const store: Record<string, { prob: number; phase: number }> = {};
704
+ for (const col of columnData)
705
+ store[col.label] = { prob: col.prob, phase: col.phase };
706
+ (panel as any)._stateVizPrev = store;
707
+ };
708
+
709
+ // Simple animation helper for numeric interpolation
710
+ const animate = (
711
+ from: number,
712
+ to: number,
713
+ durationMs: number,
714
+ onUpdate: (v: number) => void,
715
+ onDone?: () => void,
716
+ ) => {
717
+ if (!isFinite(durationMs) || durationMs <= 0) {
718
+ try {
719
+ onUpdate(to);
720
+ } catch {
721
+ // Ignore update errors
722
+ }
723
+ if (onDone) onDone();
724
+ return;
725
+ }
726
+ const start = performance.now();
727
+ const tick = (now: number) => {
728
+ const t = Math.min(1, (now - start) / durationMs);
729
+ const v = from + (to - from) * t;
730
+ try {
731
+ onUpdate(v);
732
+ } catch {
733
+ // Ignore update errors to keep the animation loop alive
734
+ }
735
+ if (t < 1) requestAnimationFrame(tick);
736
+ else if (onDone) onDone();
737
+ };
738
+ requestAnimationFrame(tick);
739
+ };
740
+
741
+ // The default phase color mapping: map phase (-π..π) to HSL hue (0..360)
742
+ const defaultPhaseColor = (phi: number) => {
743
+ const hue = ((phi + Math.PI) / (2 * Math.PI)) * 360;
744
+ return `hsl(${hue},70%,50%)`;
745
+ };
746
+
747
+ // Format phase in multiples of π, e.g., -0.5, +0.2
748
+ const formatPhasePi = (phi: number): string => {
749
+ const k = phi / Math.PI;
750
+ const sign = k >= 0 ? "+" : "";
751
+ return `${sign}${k.toFixed(1)}`;
752
+ };
753
+
754
+ // Format phase for tooltips, e.g., -0.50π, +0.25π
755
+ const formatPhasePiTip = (phi: number): string => {
756
+ const k = phi / Math.PI;
757
+ const sign = k >= 0 ? "+" : "";
758
+ return `${sign}${k.toFixed(2)}π`;
759
+ };
760
+
761
+ // Display label for a state column, handling "Others" case
762
+ const displayLabel = (b: StateColumn) =>
763
+ b.isOthers === true ? `Others (${b.othersCount ?? 0})` : b.label;