code wiki / _hdl_build / nx_math_render_page.nx
nx_math_render_page.nx source
↩ module page · 127 lines · 10417 B
1// nx_math_render_page.nx -- GENERATE the live "/wiki/math_render.html" page (IMS Thrust D, rung 1):
2// the VISIBLE proof of the sovereign "arXiv PDF->HTML / LaTeX" capability. A walkable Diataxis
3// REFERENCE page built through the reusable typed generator nx_ims_page (full walk furniture:
4// head/nav/breadcrumb/tree/prev-next/related/backlinks/infobox/toc/footer, nav read from
5// wiki_links.tsv by slug=math_render). The page's OWN content (body_html) embeds REAL presentation
6// MathML produced AT BUILD TIME by nx_tex (tx_render) -- the snippets are rendered, not hand-written:
7//
8// 1. the BM25 term-saturation factor f / (f + k) (the heart of the wiki's own ranker),
9// 2. the full BM25 single-term score IDF * f(k1+1) / (f + k1(1 - b + b|D|/avgdl)),
10// 3. the DLMF Gamma-function integral Gamma(z) = int_0^inf t^{z-1} e^{-t} dt,
11// 4. a quadratic & the quadratic formula (msqrt + mfrac showcase),
12// 5. a relations / greek line.
13//
14// Each formula is shown with its LaTeX source (escaped, in <code>) next to the rendered MathML, so a
15// reader sees input -> output. ADDITIVE: writes web_assets/math_render.html only (the publish step
16// pushes it live + fetch-verifies). REUSE (nothing reinvented): nx_ims_page ims_page (typed walkable
17// generator) + nx_tex tx_render (the sovereign renderer). license_tier: ORIGINAL
18import "nx_ims_page.nx"
19import "nx_tex.nx"
20
21const MR_BODY_CAP: i64 = 131072 // body_html scratch (>> the few KB this page needs)
22const MR_MML_CAP: i64 = 65536 // per-formula MathML scratch
23
24func mr_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
25func mr_num(v: i64) -> i64 {
26 let bb: *u8 = sys_mmap(28); var m: i64 = v
27 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
28 let t: *u8 = sys_mmap(28); var k: i64 = 0
29 if m == 0 { t[0] = 48 as u8; k = 1 }
30 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
31 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
32 sys_write(1, bb, k); return 0
33}
34func mr_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != 0 as u8 { dst[off + i] = s[i]; i = i + 1 } return off + i }
35func mr_catb(dst: *u8, off: i64, s: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { dst[off + i] = s[i]; i = i + 1 } return off + i }
36func mr_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
37
38// append a source LaTeX string into dst, HTML-escaping the few special bytes so the backslashes and
39// braces show literally in the <code> block (& < > stay safe). Returns new off.
40func mr_cat_escaped(dst: *u8, off: i64, s: *u8) -> i64 {
41 var o: i64 = off
42 var i: i64 = 0
43 while s[i] != (0 as u8) {
44 let c: i64 = s[i] as i64
45 if c == 38 { o = mr_cat(dst, o, "&" as *u8) } else {
46 if c == 60 { o = mr_cat(dst, o, "<" as *u8) } else {
47 if c == 62 { o = mr_cat(dst, o, ">" as *u8) } else {
48 dst[o] = c as u8; o = o + 1
49 }
50 }
51 }
52 i = i + 1
53 }
54 return o
55}
56
57// render ONE formula card: a <figure> with the escaped LaTeX source in <code> + the rendered MathML
58// (block display) + a caption. The MathML is produced by tx_render at build time. Returns new off.
59func mr_card(dst: *u8, off: i64, latex: *u8, caption: *u8) -> i64 {
60 let mml: *u8 = sys_mmap(MR_MML_CAP)
61 let nb: i64 = tx_render(latex, mml)
62 var o: i64 = off
63 o = mr_cat(dst, o, "<figure class=\"formula\">\n" as *u8)
64 o = mr_cat(dst, o, "<figcaption>" as *u8); o = mr_cat(dst, o, caption); o = mr_cat(dst, o, "</figcaption>\n" as *u8)
65 o = mr_cat(dst, o, "<p class=\"tex-src\">LaTeX: <code>" as *u8)
66 o = mr_cat_escaped(dst, o, latex)
67 o = mr_cat(dst, o, "</code></p>\n" as *u8)
68 if nb >= 0 {
69 o = mr_catb(dst, o, mml, nb) // the rendered MathML (already valid + balanced)
70 dst[o] = 0x0A as u8; o = o + 1
71 mr_w(" rendered '"); mr_w(latex); mr_w("' -> "); mr_num(nb); mr_w(" bytes MathML\n")
72 } else {
73 o = mr_cat(dst, o, "<p class=\"tex-err\"><em>(render error)</em></p>\n" as *u8)
74 mr_w(" FAILED '"); mr_w(latex); mr_w("' rc="); mr_num(nb); mr_w("\n")
75 }
76 o = mr_cat(dst, o, "</figure>\n" as *u8)
77 return o
78}
79
80func main() -> i64 {
81 let b: *u8 = sys_mmap(MR_BODY_CAP)
82 var o: i64 = 0
83
84 // ---- lede ----
85 o = mr_cat(b, o, "<p class=\"lede\"><strong>Sovereign LaTeX-math → MathML, rendered right here.</strong> Every formula below was turned from its LaTeX source into <a href=\"https://www.w3.org/Math/\">presentation MathML</a> by <code>nx_tex</code> — a pure, deterministic Nishi organ — <em>at the moment this page was built</em>. No JavaScript, no external math service: the markup your browser is laying out was emitted by sovereign code and verified well-formed by <code>nx_tex_gate</code>. This is the core of the arXiv-style “PDF→HTML” math capability.</p>\n" as *u8)
86 o = mr_cat(b, o, "<p class=\"why\">Why MathML and not an image? MathML is real, selectable, accessible, reflowable math that scales with the reader's font — the same reason modern arXiv HTML uses it instead of rasterized equations. The renderer covers a useful subset (fractions, roots, sub/superscripts, big operators with limits, Greek, and the common relations); unsupported input degrades to a visible <code><merror></code> rather than breaking the page.</p>\n" as *u8)
87
88 // ---- 1. BM25 saturation factor (the heart of the wiki's own ranker) ----
89 o = mr_cat(b, o, "<h3 id=\"bm25\">The ranker behind this wiki's search</h3>\n" as *u8)
90 o = mr_cat(b, o, "<p>The <a href=\"/wiki/search.html\">instant-answer search</a> ranks pages with BM25. Its defining feature is <em>term-frequency saturation</em> — the 10th occurrence of a word matters far less than the 1st. That saturation is exactly this shape:</p>\n" as *u8)
91 o = mr_card(b, o, "\\frac{f}{f + k}" as *u8, "Term-frequency saturation: as the raw count f grows, the score approaches 1 and flattens." as *u8)
92 o = mr_cat(b, o, "<p>The full single-term BM25 contribution, with document-length normalization, is:</p>\n" as *u8)
93 o = mr_card(b, o, "\\frac{f \\cdot (k_1 + 1)}{f + k_1 \\cdot (1 - b + b \\cdot \\frac{|D|}{avgdl})}" as *u8, "BM25 single-term weight: f = term frequency, |D| = document length, avgdl = average document length, k_1 and b are tuning constants." as *u8)
94
95 // ---- 2. DLMF Gamma integral ----
96 o = mr_cat(b, o, "<h3 id=\"gamma\">A special function from the DLMF</h3>\n" as *u8)
97 o = mr_cat(b, o, "<p>The Gamma function — the continuous extension of the factorial that the <a href=\"/wiki/nist_stem.html\">NIST DLMF</a> catalogs — is defined by Euler's integral:</p>\n" as *u8)
98 o = mr_card(b, o, "\\Gamma(z) = \\int_{0}^{\\infty} t^{z - 1} e^{-t} dt" as *u8, "Euler integral of the second kind (DLMF 5.2.1): the integral form of the Gamma function." as *u8)
99 o = mr_cat(b, o, "<p>Note the integral's limits render as <code>msubsup</code> (sub/super on the operator) — the integral convention — while a summation's limits render under/over (<code>munderover</code>):</p>\n" as *u8)
100 o = mr_card(b, o, "\\sum_{n=1}^{\\infty} \\frac{1}{n^2} = \\frac{\\pi^2}{6}" as *u8, "The Basel sum: limits under/over the summation sign, a fraction with a squared denominator, and the closed form." as *u8)
101
102 // ---- 3. quadratic showcase (msqrt + mfrac + sub/sup) ----
103 o = mr_cat(b, o, "<h3 id=\"quadratic\">Roots, fractions, and scripts together</h3>\n" as *u8)
104 o = mr_cat(b, o, "<p>The quadratic formula exercises a square root over a fraction with sub/superscripts — the pieces that make real math typesetting hard:</p>\n" as *u8)
105 o = mr_card(b, o, "x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}" as *u8, "The quadratic formula: msqrt nested inside the numerator of an mfrac." as *u8)
106
107 // ---- 4. relations + greek line ----
108 o = mr_cat(b, o, "<h3 id=\"symbols\">Greek and relations</h3>\n" as *u8)
109 o = mr_card(b, o, "\\alpha + \\beta \\le \\gamma \\neq \\delta \\approx \\epsilon \\cdot \\omega" as *u8, "Greek letters and comparison operators map to their proper Unicode glyphs." as *u8)
110
111 // ---- how it works ----
112 o = mr_cat(b, o, "<h3 id=\"how\">How it works</h3>\n" as *u8)
113 o = mr_cat(b, o, "<ol>\n" as *u8)
114 o = mr_cat(b, o, "<li><strong>Tokenize + recursive-descent parse.</strong> <code>nx_tex</code> scans the LaTeX byte by byte and builds the MathML tree directly — numbers to <code><mn></code>, identifiers to <code><mi></code>, operators to <code><mo></code>, <code>\\frac</code> to <code><mfrac></code>, <code>^</code>/<code>_</code> to <code><msup></code>/<code><msub></code>/<code><msubsup></code>, big operators to <code><munderover></code> or <code><msubsup></code>.</li>\n" as *u8)
115 o = mr_cat(b, o, "<li><strong>Well-formed by construction.</strong> Every open tag is closed; a single-element argument drops its redundant <code><mrow></code> to match what reference renderers emit.</li>\n" as *u8)
116 o = mr_cat(b, o, "<li><strong>Gated.</strong> <code>nx_tex_gate</code> asserts the exact MathML for hand-verified known-answer tests and runs a balanced-tag check on every output; a 3rd-party structural cross-check (LaTeXML / MathJax) is the next rigor step.</li>\n" as *u8)
117 o = mr_cat(b, o, "<li><strong>Graceful.</strong> An unsupported command becomes a visible <code><merror></code> — the page never breaks.</li>\n" as *u8)
118 o = mr_cat(b, o, "</ol>\n" as *u8)
119 o = mr_cat(b, o, "<p>Related: <a href=\"/wiki/search.html\">wiki search</a> (the BM25 ranker) · <a href=\"/wiki/nist_stem.html\">NIST STEM / DLMF</a> · <a href=\"/wiki/formats_uxf.html\">the format family</a>.</p>\n" as *u8)
120 b[o] = 0 as u8
121
122 mr_w("=== nx_math_render_page: rendering /wiki/math_render.html (reference, walkable, live MathML) ===\n");
123 let bytes: i64 = ims_page("math_render" as *u8, "reference" as *u8, "Math Rendering — Sovereign LaTeX to MathML" as *u8, b)
124 if bytes < 0 { mr_w("FATAL: ims_page failed rc="); mr_num(bytes); mr_w("\n"); sys_exit(2); return 2 }
125 mr_w("=== wrote web_assets/math_render.html bytes="); mr_num(bytes); mr_w(" ===\n")
126 sys_exit(0); return 0
127}