Cockpit MathML converter: sums, products, dots; verified in browser

Extend the LaTeX→MathML converter for the deep-instrumentation notation:
big operators ∏ ∑ with msubsup limits (\sum_{i=1}^{m}), ∘ ∗ ∼ log, and the
dots family (\cdots ⋯, \ldots …, \vdots, \ddots). Handle _{}^{} pairs as
msubsup and ignore \textstyle/\Bigg.

Trim the shuffle-argument template so the core relation fits without wrapping.

Verified in a real browser (6-voter run, full 2×3 shuffle matrix so every
sub-argument fires): Pedersen commitment, all five Bayer-Groth sub-arguments
(shuffle, product, Hadamard, zero, SVP, multi-exp), and partial decryption all
render as clean typeset math with live values — no console errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
saymrwulf 2026-07-07 16:31:43 +02:00
parent c24650885e
commit 31e9a25bb8
2 changed files with 18 additions and 6 deletions

View file

@ -81,7 +81,11 @@ function short(s){ if(s.length<=15) return s; return s.slice(0,8)+"…"+s.slice(
// ============================================================
const GREEK={sigma:"σ",gamma:"γ",rho:"ρ",pi:"π",phi:"φ",tau:"τ",lambda:"λ",mu:"μ",delta:"δ"};
const OPS={cdot:"⋅",in:"∈",gets:"←",Vert:"∥",times:"×",oplus:"⊕",bmod:"mod",
circ:"∘",ast:"∗",sim:"∼",log:"log",prod:"∏",sum:"∑",
cdots:"⋯",ldots:"…",dots:"…",vdots:"⋮",ddots:"⋱",
qquad:" ",quad:" "};
// big operators get msubsup limits from a following _{}^{}
const BIGOP={prod:"∏",sum:"∑"};
const BB={Z:"ℤ",X:"𝕏",N:"ℕ",G:"𝔾",F:"𝔽",Q:"ℚ"};
const CAL={H:"ℋ",R:"ℛ",C:"𝒞",E:"ℰ"};
const MML="http://www.w3.org/1998/Math/MathML";
@ -117,9 +121,17 @@ function render(src,values){
const tk=toks[i];
if(tk.t==="^"||tk.t==="_"){
const base=nodes.pop()||mi("");
const nxt=toks[++i];
const sub=nxt.t==="grp"?groupOf(render(nxt.v,values)):renderOne(nxt,values);
nodes.push(el(tk.t==="^"?"msup":"msub",base,sub||mi("")));
const readScript=()=>{ const nxt=toks[++i]; return nxt&&nxt.t==="grp"?groupOf(render(nxt.v,values)):(nxt?renderOne(nxt,values):null)||mi(""); };
let sup=null,sub=null;
if(tk.t==="^") sup=readScript(); else sub=readScript();
// pair a complementary script if the next token supplies it (x_{..}^{..})
const nx=toks[i+1];
if(nx&&(nx.t==="^"||nx.t==="_")&&((nx.t==="^")!==(sup!=null))){
i++; if(nx.t==="^") sup=readScript(); else sub=readScript();
}
if(sub&&sup) nodes.push(el("msubsup",base,sub,sup));
else if(sub) nodes.push(el("msub",base,sub));
else nodes.push(el("msup",base,sup));
continue;
}
const consume=()=>toks[++i];
@ -157,7 +169,7 @@ function renderOne(tk,values,consume){
if(v==="sqrt"){ const a=consume&&consume(); return el("msqrt",groupOf(render(a?a.v:"",values))); }
if(v==="xleftarrow"){ const a=consume&&consume();
return el("mover",mo("←"),el("mtext",a?a.v.replace(/\\\$/,"$"):"")); }
if(v==="big"||v==="Big"||v==="bigg"||v==="left"||v==="right"||v==="displaystyle") return null;
if(v==="big"||v==="Big"||v==="bigg"||v==="Bigg"||v==="left"||v==="right"||v==="displaystyle"||v==="textstyle") return null;
// spacing control symbols: \, \: \; \ (backslash-space) -> spaces; \! -> nothing
if(v==="!") return null;
if(v==="," ){ const s=el("mspace"); s.setAttribute("width","0.17em"); return s; }

View file

@ -32,8 +32,8 @@ func GenShuffleArgument(
emitArgument("shuffle",
"Shuffle argument: prove C' is a permutation + re-encryption of C, without revealing π",
`\text{ShuffleArgument}:\ \prod_i C_i^{x^i} \;\sim\; \prod_i C'^{\,x^{\pi(i)}}_i \ \text{via commitments } \mathbf{c}_A, \mathbf{c}_B \text{ and challenges } x,y,z`,
"ShuffleArgument: bind C and C' through commitments c_A, c_B and challenges x, y, z",
`\text{ShuffleArgument}:\ \prod_i C_i^{\,x^{i}} \;\sim\; \prod_i C'^{\,x^{\pi(i)}}_i`,
"ShuffleArgument: Π_i C_i^{x^i} ~ Π_i C'_i^{x^π(i)} (bound via c_A, c_B; challenges x,y,z)",
dims(m, n))
// 1. Convert permutation to m×n matrix A